22 #include "myisamdef.h"
23 #include "my_default.h"
26 #include "mysys_err.h"
27 #ifndef __GNU_LIBRARY__
28 #define __GNU_LIBRARY__
30 #include <my_getopt.h>
33 #if SIZEOF_LONG_LONG > 4
39 #define IS_OFFSET ((uint) 32768)
40 #define HEAD_LENGTH 32
41 #define ALLOWED_JOIN_DIFF 256
43 #define DATA_TMP_EXT ".TMD"
44 #define OLD_EXT ".OLD"
45 #define FRM_EXT ".frm"
46 #define WRITE_COUNT MY_HOW_OFTEN_TO_WRITE
50 uchar *buffer,*pos,*end;
60 uint field_length,max_zero_fill;
62 uint max_end_space,max_pre_space,length_bits,min_space;
64 enum en_fieldtype field_type;
67 my_off_t end_space[8];
68 my_off_t pre_space[8];
69 my_off_t tot_end_space,tot_pre_space,zero_fields,empty_fields,bytes_packed;
100 my_off_t bytes_packed;
101 uint tree_pack_length;
102 uint min_chr,max_chr,char_bits,offset_bits,max_offset,height;
109 MI_INFO **file,**current,**end;
112 uint min_pack_length;
113 uint max_pack_length;
115 uint max_blob_length;
118 my_bool src_file_has_indexes_disabled;
122 extern int main(
int argc,
char * *argv);
123 static void get_options(
int *argc,
char ***argv);
125 static my_bool open_isam_files(
PACK_MRG_INFO *mrg,
char **names,uint count);
127 static int create_dest_frm(
char *source_table,
char *dest_table);
129 static void free_counts_and_tree_and_queue(
HUFF_TREE *huff_trees,
133 static int compare_tree(
void* cmp_arg __attribute__((unused)),
134 const uchar *s,
const uchar *t);
136 static void check_counts(
HUFF_COUNTS *huff_counts,uint trees,
138 static int test_space_compress(
HUFF_COUNTS *huff_counts,my_off_t records,
139 uint max_space_length,my_off_t *space_counts,
140 my_off_t tot_space_count,
141 enum en_fieldtype field_type);
144 static int compare_huff_elements(
void *not_used, uchar *a,uchar *b);
145 static int save_counts_in_queue(uchar *key,element_count count,
147 static my_off_t calc_packed_length(
HUFF_COUNTS *huff_counts,uint flag);
148 static uint join_same_trees(
HUFF_COUNTS *huff_counts,uint trees);
149 static int make_huff_decode_table(
HUFF_TREE *huff_tree,uint trees);
150 static void make_traverse_code_tree(
HUFF_TREE *huff_tree,
153 static int write_header(
PACK_MRG_INFO *isam_file, uint header_length,uint trees,
154 my_off_t tot_elements,my_off_t filelength);
155 static void write_field_info(
HUFF_COUNTS *counts, uint fields,uint trees);
156 static my_off_t write_huff_tree(
HUFF_TREE *huff_tree,uint trees);
157 static uint *make_offset_code_tree(
HUFF_TREE *huff_tree,
160 static uint max_bit(uint value);
162 static char *make_new_name(
char *new_name,
char *old_name);
163 static char *make_old_name(
char *new_name,
char *old_name);
164 static void init_file_buffer(File
file,pbool read_buffer);
165 static int flush_buffer(ulong neaded_length);
166 static void end_file_buffer(
void);
167 static void write_bits(ulonglong value, uint bits);
168 static void flush_bits(
void);
171 static int save_state_mrg(File
file,
PACK_MRG_INFO *isam_file,my_off_t new_length,
176 #if !defined(DBUG_OFF)
178 static int fakecmp(my_off_t **count1, my_off_t **count2);
182 static int error_on_write=0,test_only=0,verbose=0,silent=0,
183 write_loop=0,force_pack=0, isamchk_neaded=0;
184 static int tmpfile_createflag=O_RDWR | O_TRUNC | O_EXCL;
185 static my_bool backup, opt_wait;
192 static uint tree_buff_length= 65536 - MALLOC_OVERHEAD;
193 static char tmp_dir[FN_REFLEN]={0},*join_table;
194 static my_off_t intervall_length;
195 static ha_checksum glob_crc;
199 static char zero_string[]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
200 static const char *load_default_groups[]= {
"myisampack",0 };
204 int main(
int argc,
char **argv)
211 if (load_defaults(
"my",load_default_groups,&argc,&argv))
215 get_options(&argc,&argv);
217 error=ok=isamchk_neaded=0;
224 if (open_isam_files(&merge,argv,(uint) argc) ||
225 compress(&merge, join_table) || create_dest_frm(argv[0], join_table))
231 if (!(isam_file=open_isam_file(*argv++,O_RDWR)))
235 merge.file= &isam_file;
239 if (compress(&merge,0))
245 if (ok && isamchk_neaded && !silent)
246 puts(
"Remember to run myisamchk -rq on compressed tables");
247 (void) fflush(stdout);
248 (void) fflush(stderr);
249 free_defaults(default_argv);
250 my_end(verbose ? MY_CHECK_ERROR | MY_GIVE_INFO : MY_CHECK_ERROR);
257 enum options_mp {OPT_CHARSETS_DIR_MP=256};
259 static struct my_option my_long_options[] =
261 {
"backup",
'b',
"Make a backup of the table as table_name.OLD.",
262 &backup, &backup, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
263 {
"character-sets-dir", OPT_CHARSETS_DIR_MP,
264 "Directory where character sets are.", &charsets_dir,
265 &charsets_dir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
266 {
"debug",
'#',
"Output debug log. Often this is 'd:t:o,filename'.",
267 0, 0, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0},
269 "Force packing of table even if it gets bigger or if tempfile exists.",
270 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
272 "Join all given tables into 'new_table_name'. All tables MUST have identical layouts.",
273 &join_table, &join_table, 0, GET_STR, REQUIRED_ARG, 0, 0, 0,
275 {
"help",
'?',
"Display this help and exit.",
276 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
277 {
"silent",
's',
"Be more silent.",
278 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
279 {
"tmpdir",
'T',
"Use temporary directory to store temporary table.",
280 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
281 {
"test",
't',
"Don't pack table, only test packing it.",
282 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
283 {
"verbose",
'v',
"Write info about progress and packing result. Use many -v for more verbosity!",
284 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
285 {
"version",
'V',
"Output version information and exit.",
286 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
287 {
"wait",
'w',
"Wait and retry if table is in use.", &opt_wait,
288 &opt_wait, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
289 { 0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
293 static void print_version(
void)
295 printf(
"%s Ver 1.23 for %s on %s\n",
296 my_progname, SYSTEM_TYPE, MACHINE_TYPE);
300 static void usage(
void)
303 puts(
"Copyright 2002-2008 MySQL AB, 2008 Sun Microsystems, Inc.");
304 puts(
"This software comes with ABSOLUTELY NO WARRANTY. This is free software,");
305 puts(
"and you are welcome to modify and redistribute it under the GPL license\n");
307 puts(
"Pack a MyISAM-table to take much less space.");
308 puts(
"Keys are not updated, you must run myisamchk -rq on the datafile");
309 puts(
"afterwards to update the keys.");
310 puts(
"You should give the .MYI file as the filename argument.");
312 printf(
"\nUsage: %s [OPTIONS] filename...\n", my_progname);
313 my_print_help(my_long_options);
314 print_defaults(
"my", load_default_groups);
315 my_print_variables(my_long_options);
320 get_one_option(
int optid,
const struct my_option *opt __attribute__((unused)),
328 tmpfile_createflag= O_RDWR | O_TRUNC;
331 write_loop= verbose= 0;
341 length= (uint) (strmov(tmp_dir, argument) - tmp_dir);
342 if (length != dirname_length(tmp_dir))
344 tmp_dir[length]=FN_LIBCHAR;
353 DBUG_PUSH(argument ? argument :
"d:t:o");
369 static void get_options(
int *argc,
char ***argv)
373 my_progname= argv[0][0];
374 if (isatty(fileno(stdout)))
377 if ((ho_error=handle_options(argc, argv, my_long_options, get_one_option)))
398 DBUG_ENTER(
"open_isam_file");
400 if (!(isam_file=mi_open(name,mode,
401 (opt_wait ? HA_OPEN_WAIT_IF_LOCKED :
402 HA_OPEN_ABORT_IF_LOCKED))))
404 (void) fprintf(stderr,
"%s gave error %d on open\n", name, my_errno);
408 if (share->options & HA_OPTION_COMPRESS_RECORD && !join_table)
412 (void) fprintf(stderr,
"%s is already compressed\n", name);
413 (void) mi_close(isam_file);
417 puts(
"Recompressing already compressed table");
418 share->options&= ~HA_OPTION_READ_ONLY_DATA;
420 if (! force_pack && share->state.state.records != 0 &&
421 (share->state.state.records <= 1 ||
422 share->state.state.data_file_length < 1024))
424 (void) fprintf(stderr,
"%s is too small to compress\n", name);
425 (void) mi_close(isam_file);
428 (void) mi_lock_database(isam_file,F_WRLCK);
429 DBUG_RETURN(isam_file);
433 static my_bool open_isam_files(
PACK_MRG_INFO *mrg,
char **names, uint count)
438 mrg->file=(
MI_INFO**) my_malloc(
sizeof(
MI_INFO*)*count,MYF(MY_FAE));
440 mrg->src_file_has_indexes_disabled= 0;
441 for (i=0; i < count ; i++)
443 if (!(mrg->file[i]=open_isam_file(names[i],O_RDONLY)))
446 mrg->src_file_has_indexes_disabled|=
447 ! mi_is_all_keys_active(mrg->file[i]->s->state.key_map,
448 mrg->file[i]->s->base.keys);
451 for (j=0 ; j < count-1 ; j++)
454 if (mrg->file[j]->s->base.reclength != mrg->file[j+1]->s->base.reclength ||
455 mrg->file[j]->s->base.fields != mrg->file[j+1]->s->base.fields)
457 m1=mrg->file[j]->s->rec;
458 end=m1+mrg->file[j]->s->base.fields;
459 m2=mrg->file[j+1]->s->rec;
460 for ( ; m1 != end ; m1++,m2++)
462 if (m1->type != m2->type || m1->length != m2->length)
470 (void) fprintf(stderr,
"%s: Tables '%s' and '%s' are not identical\n",
471 my_progname, names[j], names[j+1]);
474 mi_close(mrg->file[i]);
483 File new_file,join_isam_file;
486 char org_name[FN_REFLEN],new_name[FN_REFLEN],temp_name[FN_REFLEN];
487 uint
i,header_length,fields,trees,used_trees;
488 my_off_t old_length,new_length,tot_elements;
491 DBUG_ENTER(
"compress");
493 isam_file=mrg->file[0];
495 new_file=join_isam_file= -1;
503 (void) fn_format(org_name,isam_file->filename,
"",MI_NAME_DEXT,2);
505 (
void) fn_format(org_name,isam_file->filename,
"",MI_NAME_DEXT,2+4+16);
506 if (!test_only && result_table)
511 strmov(org_name,result_table);
512 (void) fn_format(new_name,result_table,
"",MI_NAME_IEXT,2);
513 if ((join_isam_file=my_create(new_name,0,tmpfile_createflag,MYF(MY_WME)))
516 length=(uint) share->base.keystart;
517 if (!(buff= (uchar*) my_malloc(length,MYF(MY_WME))))
519 if (my_pread(share->kfile,buff,length,0L,MYF(MY_WME | MY_NABP)) ||
520 my_write(join_isam_file,buff,length,
521 MYF(MY_WME | MY_NABP | MY_WAIT_IF_FULL)))
527 (void) fn_format(new_name,result_table,
"",MI_NAME_DEXT,2);
529 else if (!tmp_dir[0])
530 (void) make_new_name(new_name,org_name);
532 (
void) fn_format(new_name,org_name,tmp_dir,DATA_TMP_EXT,1+2+4);
534 (new_file=my_create(new_name,0,tmpfile_createflag,MYF(MY_WME))) < 0)
540 for (i=0 ; i < mrg->count ; i++)
541 mrg->records+=mrg->file[i]->s->state.state.records;
543 DBUG_PRINT(
"info", (
"Compressing %s: (%lu records)",
544 result_table ? new_name : org_name,
545 (ulong) mrg->records));
546 if (write_loop || verbose)
548 printf(
"Compressing %s: (%lu records)\n",
549 result_table ? new_name : org_name, (ulong) mrg->records);
551 trees=fields=share->base.fields;
552 huff_counts=init_huff_count(isam_file,mrg->records);
557 DBUG_PRINT(
"info", (
"- Calculating statistics"));
558 if (write_loop || verbose)
559 printf(
"- Calculating statistics\n");
560 if (get_statistic(mrg,huff_counts))
564 for (i=0; i < mrg->count ; i++)
565 old_length+= (mrg->file[i]->s->state.state.data_file_length -
566 mrg->file[i]->s->state.state.empty);
572 if (init_queue(&queue,256,0,0,compare_huff_elements,0))
579 check_counts(huff_counts,fields,mrg->records);
584 huff_trees=make_huff_trees(huff_counts,trees);
592 if ((
int) (used_trees=join_same_trees(huff_counts,trees)) < 0)
598 if (make_huff_decode_table(huff_trees,fields))
602 init_file_buffer(new_file,0);
607 file_buffer.pos_in_file=HEAD_LENGTH;
609 my_seek(new_file,file_buffer.pos_in_file,MY_SEEK_SET,MYF(0));
614 write_field_info(huff_counts,fields,used_trees);
619 if (!(tot_elements=write_huff_tree(huff_trees,trees)))
627 header_length=(uint) file_buffer.pos_in_file+
628 (uint) (file_buffer.pos-file_buffer.buffer);
633 DBUG_PRINT(
"info", (
"- Compressing file"));
634 if (write_loop || verbose)
635 printf(
"- Compressing file\n");
636 error=compress_isam_file(mrg,huff_counts);
637 new_length=file_buffer.pos_in_file;
638 if (!error && !test_only)
640 uchar buff[MEMMAP_EXTRA_MARGIN];
641 memset(buff, 0,
sizeof(buff));
642 error=my_write(file_buffer.file,buff,
sizeof(buff),
643 MYF(MY_WME | MY_NABP | MY_WAIT_IF_FULL)) != 0;
650 error=write_header(mrg,header_length,used_trees,tot_elements,
657 DBUG_PRINT(
"info", (
"Min record length: %6d Max length: %6d "
658 "Mean total length: %6ld\n",
659 mrg->min_pack_length, mrg->max_pack_length,
660 (ulong) (mrg->records ? (new_length/mrg->records) : 0)));
661 if (verbose && mrg->records)
662 printf(
"Min record length: %6d Max length: %6d "
663 "Mean total length: %6ld\n", mrg->min_pack_length,
664 mrg->max_pack_length, (ulong) (new_length/mrg->records));
669 error|=my_close(new_file,MYF(MY_WME));
672 error|=my_close(isam_file->dfile,MYF(MY_WME));
673 isam_file->dfile= -1;
678 free_counts_and_tree_and_queue(huff_trees,trees,huff_counts,fields);
679 if (! test_only && ! error)
683 error=save_state_mrg(join_isam_file,mrg,new_length,glob_crc);
689 if (my_rename(org_name,make_old_name(temp_name,isam_file->filename),
695 error=my_copy(new_name,org_name,MYF(MY_WME));
697 error=my_rename(new_name,org_name,MYF(MY_WME));
700 (void) my_copystat(temp_name,org_name,MYF(MY_COPYTIME));
702 (void) my_delete(new_name,MYF(MY_WME));
710 error=my_copy(new_name,org_name,
711 MYF(MY_WME | MY_HOLD_ORIGINAL_MODES | MY_COPYTIME));
713 (void) my_delete(new_name,MYF(MY_WME));
716 error=my_redel(org_name,new_name,MYF(MY_WME | MY_COPYTIME));
719 error=save_state(isam_file,mrg,new_length,glob_crc);
722 error|=mrg_close(mrg);
723 if (join_isam_file >= 0)
724 error|=my_close(join_isam_file,MYF(MY_WME));
727 (void) fprintf(stderr,
"Aborting: %s is not compressed\n", org_name);
728 (void) my_delete(new_name,MYF(MY_WME));
731 if (write_loop || verbose)
735 (((longlong) (old_length - new_length)) * 100.0 /
736 (longlong) old_length));
738 puts(
"Empty file saved in compressed format");
743 free_counts_and_tree_and_queue(huff_trees,trees,huff_counts,fields);
745 (void) my_close(new_file,MYF(0));
746 if (join_isam_file >= 0)
747 (void) my_close(join_isam_file,MYF(0));
749 (void) fprintf(stderr,
"Aborted: %s is not compressed\n", org_name);
768 static int create_dest_frm(
char *source_table,
char *dest_table)
770 char source_name[FN_REFLEN], dest_name[FN_REFLEN];
772 DBUG_ENTER(
"create_dest_frm");
774 (void) fn_format(source_name, source_table,
775 "", FRM_EXT, MY_UNPACK_FILENAME | MY_RESOLVE_SYMLINKS);
776 (void) fn_format(dest_name, dest_table,
777 "", FRM_EXT, MY_UNPACK_FILENAME | MY_RESOLVE_SYMLINKS);
785 (void) my_copy(source_name, dest_name, MYF(MY_DONT_OVERWRITE_FILE));
797 if ((count = (
HUFF_COUNTS*) my_malloc(info->s->base.fields*
799 MYF(MY_ZEROFILL | MY_WME))))
801 for (i=0 ; i < info->s->base.fields ; i++)
803 enum en_fieldtype
type;
804 count[
i].field_length=info->s->rec[
i].length;
805 type= count[
i].field_type= (
enum en_fieldtype) info->s->rec[i].type;
806 if (type == FIELD_INTERVALL ||
807 type == FIELD_CONSTANT ||
810 if (count[i].field_length <= 8 &&
811 (type == FIELD_NORMAL ||
812 type == FIELD_SKIP_ZERO))
813 count[i].max_zero_fill= count[i].field_length;
820 init_tree(&count[i].int_tree,0,0,-1,(qsort_cmp2) compare_tree,0, NULL,
822 if (records && type != FIELD_BLOB && type != FIELD_VARCHAR)
823 count[
i].tree_pos=count[
i].tree_buff =
824 my_malloc(count[i].field_length > 1 ? tree_buff_length : 2,
834 static void free_counts_and_tree_and_queue(
HUFF_TREE *huff_trees, uint trees,
842 for (i=0 ; i < trees ; i++)
844 if (huff_trees[i].element_buffer)
845 my_free(huff_trees[i].element_buffer);
846 if (huff_trees[i].
code)
847 my_free(huff_trees[i].code);
853 for (i=0 ; i < fields ; i++)
855 if (huff_counts[i].tree_buff)
857 my_free(huff_counts[i].tree_buff);
858 delete_tree(&huff_counts[i].int_tree);
861 my_free(huff_counts);
863 delete_queue(&queue);
873 ulong reclength,max_blob_length;
874 uchar *
record,*pos,*next_pos,*end_pos,*start_pos;
875 ha_rows record_count;
876 my_bool static_row_size;
879 DBUG_ENTER(
"get_statistic");
881 reclength=mrg->file[0]->s->base.reclength;
882 record=(uchar*) my_alloca(reclength);
883 end_count=huff_counts+mrg->file[0]->s->base.fields;
884 record_count=0; glob_crc=0;
889 for (count=huff_counts ; count < end_count ; count++)
891 if (count->field_type == FIELD_BLOB ||
892 count->field_type == FIELD_VARCHAR)
900 while ((error=mrg_rrnd(mrg,record)) != HA_ERR_END_OF_FILE)
902 ulong tot_blob_length=0;
907 glob_crc+=mi_static_checksum(mrg->file[0],record);
909 glob_crc+=mi_checksum(mrg->file[0],record);
912 for (pos=record,count=huff_counts ;
917 next_pos=end_pos=(start_pos=pos)+count->field_length;
952 if (count->tree_buff)
955 if (!(element=tree_insert(&count->int_tree,pos, 0,
956 count->int_tree.custom_arg)) ||
957 (element->count == 1 &&
958 (count->tree_buff + tree_buff_length <
959 count->tree_pos + count->field_length)) ||
960 (count->int_tree.elements_in_tree > IS_OFFSET / 2) ||
961 (count->field_length == 1 &&
962 count->int_tree.elements_in_tree > 1))
964 delete_tree(&count->int_tree);
965 my_free(count->tree_buff);
974 if (element->count == 1)
977 memcpy(count->tree_pos,pos,(
size_t) count->field_length);
979 tree_set_pointer(element,count->tree_pos);
981 count->tree_pos+=count->field_length;
987 if (count->field_type == FIELD_NORMAL ||
988 count->field_type == FIELD_SKIP_ENDSPACE)
991 for ( ; end_pos > pos ; end_pos--)
992 if (end_pos[-1] !=
' ')
997 count->empty_fields++;
998 count->max_zero_fill=0;
1005 length= (uint) (next_pos-end_pos);
1006 count->tot_end_space+=length;
1008 count->end_space[length]++;
1009 if (count->max_end_space < length)
1010 count->max_end_space = length;
1013 if (count->field_type == FIELD_NORMAL ||
1014 count->field_type == FIELD_SKIP_PRESPACE)
1017 for (pos=start_pos; pos < end_pos ; pos++)
1023 count->empty_fields++;
1024 count->max_zero_fill=0;
1031 length= (uint) (pos-start_pos);
1032 count->tot_pre_space+=length;
1034 count->pre_space[length]++;
1035 if (count->max_pre_space < length)
1036 count->max_pre_space = length;
1040 if (count->field_type == FIELD_BLOB)
1042 uint field_length=count->field_length -portable_sizeof_char_ptr;
1043 ulong blob_length= _mi_calc_blob_length(field_length, start_pos);
1044 memcpy(&pos, start_pos+field_length,
sizeof(
char*));
1045 end_pos=pos+blob_length;
1046 tot_blob_length+=blob_length;
1047 set_if_bigger(count->max_length,blob_length);
1049 else if (count->field_type == FIELD_VARCHAR)
1051 uint pack_length= HA_VARCHAR_PACKLENGTH(count->field_length-1);
1052 length= (pack_length == 1 ? (uint) *(uchar*) start_pos :
1053 uint2korr(start_pos));
1054 pos= start_pos+pack_length;
1055 end_pos= pos+length;
1056 set_if_bigger(count->max_length,length);
1060 if (count->field_length <= 8 &&
1061 (count->field_type == FIELD_NORMAL ||
1062 count->field_type == FIELD_SKIP_ZERO))
1066 if (!memcmp((uchar*) start_pos,zero_string,count->field_length))
1068 count->zero_fields++;
1077 for (i =0 ; i < count->max_zero_fill && ! end_pos[-1 - (int) i] ;
1079 if (i < count->max_zero_fill)
1080 count->max_zero_fill=
i;
1084 if (count->field_type == FIELD_ZERO ||
1085 count->field_type == FIELD_CHECK)
1092 for ( ; pos < end_pos ; pos++)
1093 count->counts[(uchar) *pos]++;
1098 if (tot_blob_length > max_blob_length)
1099 max_blob_length=tot_blob_length;
1101 if (write_loop && record_count % WRITE_COUNT == 0)
1103 printf(
"%lu\r", (ulong) record_count);
1104 (void) fflush(stdout);
1107 else if (error != HA_ERR_RECORD_DELETED)
1109 (void) fprintf(stderr,
"Got error %d while reading rows", error);
1118 (void) fflush(stdout);
1125 DBUG_EXECUTE_IF(
"fakebigcodes", fakebigcodes(huff_counts, end_count););
1127 DBUG_PRINT(
"info", (
"Found the following number of incidents "
1128 "of the byte codes:"));
1130 printf(
"Found the following number of incidents "
1131 "of the byte codes:\n");
1132 for (count= huff_counts ; count < end_count; count++)
1135 my_off_t total_count;
1138 DBUG_PRINT(
"info", (
"column: %3u", (uint) (count - huff_counts + 1)));
1140 printf(
"column: %3u\n", (uint) (count - huff_counts + 1));
1141 if (count->tree_buff)
1143 DBUG_PRINT(
"info", (
"number of distinct values: %u",
1144 (uint) ((count->tree_pos - count->tree_buff) /
1145 count->field_length)));
1147 printf(
"number of distinct values: %u\n",
1148 (uint) ((count->tree_pos - count->tree_buff) /
1149 count->field_length));
1152 for (idx= 0; idx < 256; idx++)
1154 if (count->counts[idx])
1156 total_count+= count->counts[idx];
1157 DBUG_PRINT(
"info", (
"counts[0x%02x]: %12s", idx,
1158 llstr((longlong) count->counts[idx], llbuf)));
1160 printf(
"counts[0x%02x]: %12s\n", idx,
1161 llstr((longlong) count->counts[idx], llbuf));
1164 DBUG_PRINT(
"info", (
"total: %12s", llstr((longlong) total_count,
1166 if ((verbose >= 2) && total_count)
1168 printf(
"total: %12s\n",
1169 llstr((longlong) total_count, llbuf));
1173 mrg->records=record_count;
1174 mrg->max_blob_length=max_blob_length;
1175 my_afree((uchar*) record);
1176 DBUG_RETURN(error != HA_ERR_END_OF_FILE);
1179 static int compare_huff_elements(
void *not_used __attribute__((unused)),
1182 return *((my_off_t*) a) < *((my_off_t*) b) ? -1 :
1183 (*((my_off_t*) a) == *((my_off_t*) b) ? 0 : 1);
1189 static void check_counts(
HUFF_COUNTS *huff_counts, uint trees,
1192 uint space_fields,fill_zero_fields,field_count[(int) FIELD_enum_val_count];
1193 my_off_t old_length,new_length,length;
1194 DBUG_ENTER(
"check_counts");
1196 memset(field_count, 0,
sizeof(field_count));
1197 space_fields=fill_zero_fields=0;
1199 for (; trees-- ; huff_counts++)
1201 if (huff_counts->field_type == FIELD_BLOB)
1203 huff_counts->length_bits=max_bit(huff_counts->max_length);
1206 else if (huff_counts->field_type == FIELD_VARCHAR)
1208 huff_counts->length_bits=max_bit(huff_counts->max_length);
1211 else if (huff_counts->field_type == FIELD_CHECK)
1213 huff_counts->bytes_packed=0;
1214 huff_counts->counts[0]=0;
1218 huff_counts->field_type=FIELD_NORMAL;
1219 huff_counts->pack_type=0;
1222 if (huff_counts->zero_fields || ! records)
1224 my_off_t old_space_count;
1229 if (huff_counts->zero_fields == records)
1231 huff_counts->field_type= FIELD_ZERO;
1232 huff_counts->bytes_packed=0;
1233 huff_counts->counts[0]=0;
1237 old_space_count=huff_counts->counts[
' '];
1239 huff_counts->counts[
' ']+= (huff_counts->tot_end_space +
1240 huff_counts->tot_pre_space +
1241 huff_counts->empty_fields *
1242 huff_counts->field_length);
1244 old_length=calc_packed_length(huff_counts,0)+records/8;
1246 length=huff_counts->zero_fields*huff_counts->field_length;
1248 huff_counts->counts[0]+=length;
1250 new_length=calc_packed_length(huff_counts,0);
1252 if (old_length < new_length && huff_counts->field_length > 1)
1254 huff_counts->field_type=FIELD_SKIP_ZERO;
1255 huff_counts->counts[0]-=length;
1256 huff_counts->bytes_packed=old_length- records/8;
1260 huff_counts->counts[
' ']=old_space_count;
1263 huff_counts->bytes_packed=calc_packed_length(huff_counts,0);
1269 if (huff_counts->empty_fields)
1271 if (huff_counts->field_length > 2 &&
1272 huff_counts->empty_fields + (records - huff_counts->empty_fields)*
1273 (1+max_bit(MY_MAX(huff_counts->max_pre_space,
1274 huff_counts->max_end_space))) <
1275 records * max_bit(huff_counts->field_length))
1277 huff_counts->pack_type |= PACK_TYPE_SPACE_FIELDS;
1281 length=huff_counts->empty_fields*huff_counts->field_length;
1282 if (huff_counts->tot_end_space || ! huff_counts->tot_pre_space)
1284 huff_counts->tot_end_space+=length;
1285 huff_counts->max_end_space=huff_counts->field_length;
1286 if (huff_counts->field_length < 8)
1287 huff_counts->end_space[huff_counts->field_length]+=
1288 huff_counts->empty_fields;
1290 if (huff_counts->tot_pre_space)
1292 huff_counts->tot_pre_space+=length;
1293 huff_counts->max_pre_space=huff_counts->field_length;
1294 if (huff_counts->field_length < 8)
1295 huff_counts->pre_space[huff_counts->field_length]+=
1296 huff_counts->empty_fields;
1305 if (huff_counts->tot_end_space)
1307 huff_counts->counts[
' ']+=huff_counts->tot_pre_space;
1308 if (test_space_compress(huff_counts,records,huff_counts->max_end_space,
1309 huff_counts->end_space,
1310 huff_counts->tot_end_space,FIELD_SKIP_ENDSPACE))
1312 huff_counts->counts[
' ']-=huff_counts->tot_pre_space;
1319 if (huff_counts->tot_pre_space)
1321 if (test_space_compress(huff_counts,records,huff_counts->max_pre_space,
1322 huff_counts->pre_space,
1323 huff_counts->tot_pre_space,FIELD_SKIP_PRESPACE))
1331 if (huff_counts->max_zero_fill &&
1332 (huff_counts->field_type == FIELD_NORMAL ||
1333 huff_counts->field_type == FIELD_SKIP_ZERO))
1335 huff_counts->counts[0]-=huff_counts->max_zero_fill*
1336 (huff_counts->field_type == FIELD_SKIP_ZERO ?
1337 records - huff_counts->zero_fields : records);
1338 huff_counts->pack_type|=PACK_TYPE_ZERO_FILL;
1339 huff_counts->bytes_packed=calc_packed_length(huff_counts,0);
1344 if (huff_counts->tree_buff)
1348 DBUG_EXECUTE_IF(
"forceintervall",
1349 huff_counts->bytes_packed= ~ (my_off_t) 0;);
1350 tree.element_buffer=0;
1351 if (!make_huff_tree(&tree,huff_counts) &&
1352 tree.bytes_packed+tree.tree_pack_length < huff_counts->bytes_packed)
1354 if (tree.elements == 1)
1355 huff_counts->field_type=FIELD_CONSTANT;
1357 huff_counts->field_type=FIELD_INTERVALL;
1358 huff_counts->pack_type=0;
1362 my_free(huff_counts->tree_buff);
1363 delete_tree(&huff_counts->int_tree);
1364 huff_counts->tree_buff=0;
1366 if (tree.element_buffer)
1367 my_free(tree.element_buffer);
1369 if (huff_counts->pack_type & PACK_TYPE_SPACE_FIELDS)
1371 if (huff_counts->pack_type & PACK_TYPE_ZERO_FILL)
1373 field_count[huff_counts->field_type]++;
1375 DBUG_PRINT(
"info", (
"normal: %3d empty-space: %3d "
1376 "empty-zero: %3d empty-fill: %3d",
1377 field_count[FIELD_NORMAL],space_fields,
1378 field_count[FIELD_SKIP_ZERO],fill_zero_fields));
1379 DBUG_PRINT(
"info", (
"pre-space: %3d end-space: %3d "
1380 "intervall-fields: %3d zero: %3d",
1381 field_count[FIELD_SKIP_PRESPACE],
1382 field_count[FIELD_SKIP_ENDSPACE],
1383 field_count[FIELD_INTERVALL],
1384 field_count[FIELD_ZERO]));
1386 printf(
"\nnormal: %3d empty-space: %3d "
1387 "empty-zero: %3d empty-fill: %3d\n"
1388 "pre-space: %3d end-space: %3d "
1389 "intervall-fields: %3d zero: %3d\n",
1390 field_count[FIELD_NORMAL],space_fields,
1391 field_count[FIELD_SKIP_ZERO],fill_zero_fields,
1392 field_count[FIELD_SKIP_PRESPACE],
1393 field_count[FIELD_SKIP_ENDSPACE],
1394 field_count[FIELD_INTERVALL],
1395 field_count[FIELD_ZERO]);
1402 test_space_compress(
HUFF_COUNTS *huff_counts, my_off_t records,
1403 uint max_space_length, my_off_t *space_counts,
1404 my_off_t tot_space_count,
enum en_fieldtype field_type)
1408 my_off_t space_count,min_space_count,min_pack,new_length,
skip;
1410 length_bits=max_bit(max_space_length);
1413 space_count=huff_counts->counts[(uint)
' '];
1414 min_space_count= (huff_counts->counts[(uint)
' ']+= tot_space_count);
1415 min_pack=calc_packed_length(huff_counts,0);
1417 huff_counts->counts[(uint)
' ']=space_count;
1420 new_length=huff_counts->bytes_packed+length_bits*records/8;
1421 if (new_length+1 < min_pack)
1424 min_pack=new_length;
1425 min_space_count=space_count;
1428 for (skip=0L, i=0 ; i < 8 ; i++)
1430 if (space_counts[i])
1433 huff_counts->counts[(uint)
' ']+=space_counts[i];
1434 skip+=huff_counts->pre_space[
i];
1435 new_length=calc_packed_length(huff_counts,0)+
1436 (records+(records-
skip)*(1+length_bits))/8;
1437 if (new_length < min_pack)
1440 min_pack=new_length;
1441 min_space_count=huff_counts->counts[(uint)
' '];
1446 huff_counts->counts[(uint)
' ']=min_space_count;
1447 huff_counts->bytes_packed=min_pack;
1452 huff_counts->field_type=field_type;
1453 huff_counts->min_space=0;
1454 huff_counts->length_bits=max_bit(max_space_length);
1457 huff_counts->field_type=field_type;
1458 huff_counts->min_space=(uint) min_pos;
1459 huff_counts->pack_type|=PACK_TYPE_SELECTED;
1460 huff_counts->length_bits=max_bit(max_space_length);
1473 DBUG_ENTER(
"make_huff_trees");
1476 MYF(MY_WME | MY_ZEROFILL))))
1479 for (tree=0 ; tree < trees ; tree++)
1481 if (make_huff_tree(huff_tree+tree,huff_counts+tree))
1484 my_free(huff_tree[tree].element_buffer);
1489 DBUG_RETURN(huff_tree);
1513 uint
i,found,bits_packed,first,last;
1514 my_off_t bytes_packed;
1518 if (huff_counts->tree_buff)
1521 found= (uint) (huff_counts->tree_pos - huff_counts->tree_buff) /
1522 huff_counts->field_length;
1523 first=0; last=found-1;
1528 for (i=found=0 ; i < 256 ; i++)
1530 if (huff_counts->counts[i])
1542 if (queue.max_elements < found)
1544 delete_queue(&queue);
1545 if (init_queue(&queue,found,0,0,compare_huff_elements,0))
1550 if (!huff_tree->element_buffer)
1552 if (!(huff_tree->element_buffer=
1560 (
HUFF_ELEMENT*) my_realloc((uchar*) huff_tree->element_buffer,
1564 huff_tree->element_buffer=
temp;
1567 huff_counts->tree=huff_tree;
1568 huff_tree->counts=huff_counts;
1569 huff_tree->min_chr=first;
1570 huff_tree->max_chr=last;
1571 huff_tree->char_bits=max_bit(last-first);
1572 huff_tree->offset_bits=max_bit(found-1)+1;
1574 if (huff_counts->tree_buff)
1576 huff_tree->elements=0;
1577 huff_tree->tree_pack_length=(1+15+16+5+5+
1578 (huff_tree->char_bits+1)*found+
1579 (huff_tree->offset_bits+1)*
1581 (uint) (huff_tree->counts->tree_pos-
1582 huff_tree->counts->tree_buff);
1593 tree_walk(&huff_counts->int_tree,
1594 (int (*)(
void*, element_count,
void*)) save_counts_in_queue,
1595 (uchar*) huff_tree, left_root_right);
1599 huff_tree->elements=found;
1600 huff_tree->tree_pack_length=(9+9+5+5+
1601 (huff_tree->char_bits+1)*found+
1602 (huff_tree->offset_bits+1)*
1613 for (i=first, found=0 ; i <= last ; i++)
1615 if (huff_counts->counts[i])
1617 new_huff_el=huff_tree->element_buffer+(found++);
1618 new_huff_el->count=huff_counts->counts[
i];
1619 new_huff_el->a.leaf.null=0;
1620 new_huff_el->a.leaf.element_nr=
i;
1621 queue.root[found]=(uchar*) new_huff_el;
1631 new_huff_el=huff_tree->element_buffer+(found++);
1632 new_huff_el->count=0;
1633 new_huff_el->a.leaf.null=0;
1635 new_huff_el->a.leaf.element_nr=huff_tree->min_chr=last-1;
1637 new_huff_el->a.leaf.element_nr=huff_tree->max_chr=last+1;
1638 queue.root[found]=(uchar*) new_huff_el;
1643 queue.elements=found;
1649 for (i=found/2 ; i > 0 ; i--)
1650 _downheap(&queue,i);
1653 bytes_packed=0; bits_packed=0;
1654 for (i=1 ; i < found ; i++)
1668 new_huff_el=huff_tree->element_buffer+found+i;
1670 new_huff_el->count=a->count+b->count;
1679 bits_packed+=(uint) (new_huff_el->count & 7);
1680 bytes_packed+=new_huff_el->count/8;
1682 new_huff_el->a.nod.left=a;
1683 new_huff_el->a.nod.right=b;
1688 queue.root[1]=(uchar*) new_huff_el;
1689 queue_replaced(&queue);
1692 huff_tree->bytes_packed=bytes_packed+(bits_packed+7)/8;
1696 static int compare_tree(
void* cmp_arg __attribute__((unused)),
1697 register const uchar *s,
register const uchar *t)
1700 for (length=global_count->field_length; length-- ;)
1702 return (
int) s[-1] - (int) t[-1];
1727 static int save_counts_in_queue(uchar *key, element_count count,
1732 new_huff_el=tree->element_buffer+(tree->elements++);
1733 new_huff_el->count=count;
1734 new_huff_el->a.leaf.null=0;
1735 new_huff_el->a.leaf.element_nr= (uint) (key- tree->counts->tree_buff) /
1736 tree->counts->field_length;
1737 queue.root[tree->elements]=(uchar*) new_huff_el;
1760 static my_off_t calc_packed_length(
HUFF_COUNTS *huff_counts,
1761 uint add_tree_lenght)
1763 uint
i,found,bits_packed,first,last;
1764 my_off_t bytes_packed;
1766 DBUG_ENTER(
"calc_packed_length");
1786 for (i=found=0 ; i < 256 ; i++)
1788 if (huff_counts->counts[i])
1794 queue.root[found]=(uchar*) &huff_counts->counts[i];
1805 queue.root[++found]=(uchar*) &huff_counts->counts[last ? 0 : 1];
1808 queue.elements=found;
1810 bytes_packed=0; bits_packed=0;
1812 if (add_tree_lenght)
1813 bytes_packed=(8+9+5+5+(max_bit(last-first)+1)*found+
1814 (max_bit(found-1)+1+1)*(found-2) +7)/8;
1820 for (i=(found+1)/2 ; i > 0 ; i--)
1821 _downheap(&queue,i);
1824 for (i=0 ; i < found-1 ; i++)
1835 a= (my_off_t*) queue_remove(&queue, 0);
1840 b= (my_off_t*) queue.root[1];
1842 new_huff_el= element_buffer + i;
1844 new_huff_el->count= *a + *b;
1853 bits_packed+=(uint) (new_huff_el->count & 7);
1854 bytes_packed+=new_huff_el->count/8;
1860 queue.root[1]=(uchar*) new_huff_el;
1861 queue_replaced(&queue);
1863 DBUG_RETURN(bytes_packed+(bits_packed+7)/8);
1869 static uint join_same_trees(
HUFF_COUNTS *huff_counts, uint trees)
1874 last_count=huff_counts+trees;
1875 for (tree_number=0, i=huff_counts ; i < last_count ; i++)
1877 if (!i->tree->tree_number)
1879 i->tree->tree_number= ++tree_number;
1882 for (j=i+1 ; j < last_count ; j++)
1884 if (! j->tree->tree_number && ! j->tree_buff)
1886 for (k=0 ; k < 256 ; k++)
1887 count.counts[k]=i->counts[k]+j->counts[k];
1888 if (calc_packed_length(&count,1) <=
1889 i->tree->bytes_packed + j->tree->bytes_packed+
1890 i->tree->tree_pack_length+j->tree->tree_pack_length+
1893 memcpy(i->counts, count.counts,
1894 sizeof(count.counts[0])*256);
1895 my_free(j->tree->element_buffer);
1896 j->tree->element_buffer=0;
1898 bmove((uchar*) i->counts,(uchar*) count.counts,
1899 sizeof(count.counts[0])*256);
1900 if (make_huff_tree(i->tree,i))
1907 DBUG_PRINT(
"info", (
"Original trees: %d After join: %d",
1908 trees, tree_number));
1910 printf(
"Original trees: %d After join: %d\n", trees, tree_number);
1928 static int make_huff_decode_table(
HUFF_TREE *huff_tree, uint trees)
1931 for ( ; trees-- ; huff_tree++)
1933 if (huff_tree->tree_number > 0)
1935 elements=huff_tree->counts->tree_buff ? huff_tree->elements : 256;
1936 if (!(huff_tree->code =
1937 (ulonglong*) my_malloc(elements*
1938 (
sizeof(ulonglong) +
sizeof(uchar)),
1939 MYF(MY_WME | MY_ZEROFILL))))
1941 huff_tree->code_len=(uchar*) (huff_tree->code+elements);
1942 make_traverse_code_tree(huff_tree, huff_tree->root,
1943 8 *
sizeof(ulonglong), LL(0));
1950 static void make_traverse_code_tree(
HUFF_TREE *huff_tree,
1955 if (!element->a.leaf.null)
1957 chr=element->a.leaf.element_nr;
1958 huff_tree->code_len[chr]= (uchar) (8 *
sizeof(ulonglong) -
size);
1959 huff_tree->code[chr]= (code >>
size);
1960 if (huff_tree->height < 8 *
sizeof(ulonglong) -
size)
1961 huff_tree->height= 8 *
sizeof(ulonglong) -
size;
1966 make_traverse_code_tree(huff_tree,element->a.nod.left,size,code);
1967 make_traverse_code_tree(huff_tree, element->a.nod.right, size,
1968 code + (((ulonglong) 1) << size));
1990 static char *bindigits(ulonglong
value, uint bits)
1992 static char digits[72];
1996 DBUG_ASSERT(idx <
sizeof(digits));
1998 *(ptr++)=
'0' + ((
char) (value >> (--idx)) & (char) 1);
2019 static char *hexdigits(ulonglong value)
2021 static char digits[20];
2023 uint idx= 2 *
sizeof(
value);
2025 DBUG_ASSERT(idx <
sizeof(digits));
2028 if ((*(ptr++)=
'0' + ((
char) (value >> (4 * (--idx))) & (
char) 0xf)) >
'9')
2029 *(ptr - 1)+=
'a' -
'9' - 1;
2038 static int write_header(
PACK_MRG_INFO *mrg,uint head_length,uint trees,
2039 my_off_t tot_elements,my_off_t filelength)
2041 uchar *buff= (uchar*) file_buffer.pos;
2043 memset(buff, 0, HEAD_LENGTH);
2044 memcpy(buff,myisam_pack_file_magic,4);
2045 int4store(buff+4,head_length);
2046 int4store(buff+8, mrg->min_pack_length);
2047 int4store(buff+12,mrg->max_pack_length);
2048 int4store(buff+16,tot_elements);
2049 int4store(buff+20,intervall_length);
2050 int2store(buff+24,trees);
2051 buff[26]=(char) mrg->ref_length;
2053 buff[27]= (uchar) mi_get_pointer_length((ulonglong) filelength,2);
2056 my_seek(file_buffer.file,0L,MY_SEEK_SET,MYF(0));
2057 return my_write(file_buffer.file,(
const uchar *) file_buffer.pos,HEAD_LENGTH,
2058 MYF(MY_WME | MY_NABP | MY_WAIT_IF_FULL)) != 0;
2063 static void write_field_info(
HUFF_COUNTS *counts, uint fields, uint trees)
2066 uint huff_tree_bits;
2067 huff_tree_bits=max_bit(trees ? trees-1 : 0);
2069 DBUG_PRINT(
"info", (
" "));
2070 DBUG_PRINT(
"info", (
"column types:"));
2071 DBUG_PRINT(
"info", (
"FIELD_NORMAL 0"));
2072 DBUG_PRINT(
"info", (
"FIELD_SKIP_ENDSPACE 1"));
2073 DBUG_PRINT(
"info", (
"FIELD_SKIP_PRESPACE 2"));
2074 DBUG_PRINT(
"info", (
"FIELD_SKIP_ZERO 3"));
2075 DBUG_PRINT(
"info", (
"FIELD_BLOB 4"));
2076 DBUG_PRINT(
"info", (
"FIELD_CONSTANT 5"));
2077 DBUG_PRINT(
"info", (
"FIELD_INTERVALL 6"));
2078 DBUG_PRINT(
"info", (
"FIELD_ZERO 7"));
2079 DBUG_PRINT(
"info", (
"FIELD_VARCHAR 8"));
2080 DBUG_PRINT(
"info", (
"FIELD_CHECK 9"));
2081 DBUG_PRINT(
"info", (
" "));
2082 DBUG_PRINT(
"info", (
"pack type as a set of flags:"));
2083 DBUG_PRINT(
"info", (
"PACK_TYPE_SELECTED 1"));
2084 DBUG_PRINT(
"info", (
"PACK_TYPE_SPACE_FIELDS 2"));
2085 DBUG_PRINT(
"info", (
"PACK_TYPE_ZERO_FILL 4"));
2086 DBUG_PRINT(
"info", (
" "));
2090 printf(
"column types:\n");
2091 printf(
"FIELD_NORMAL 0\n");
2092 printf(
"FIELD_SKIP_ENDSPACE 1\n");
2093 printf(
"FIELD_SKIP_PRESPACE 2\n");
2094 printf(
"FIELD_SKIP_ZERO 3\n");
2095 printf(
"FIELD_BLOB 4\n");
2096 printf(
"FIELD_CONSTANT 5\n");
2097 printf(
"FIELD_INTERVALL 6\n");
2098 printf(
"FIELD_ZERO 7\n");
2099 printf(
"FIELD_VARCHAR 8\n");
2100 printf(
"FIELD_CHECK 9\n");
2102 printf(
"pack type as a set of flags:\n");
2103 printf(
"PACK_TYPE_SELECTED 1\n");
2104 printf(
"PACK_TYPE_SPACE_FIELDS 2\n");
2105 printf(
"PACK_TYPE_ZERO_FILL 4\n");
2108 for (i=0 ; i++ < fields ; counts++)
2110 write_bits((ulonglong) (
int) counts->field_type, 5);
2111 write_bits(counts->pack_type,6);
2112 if (counts->pack_type & PACK_TYPE_ZERO_FILL)
2113 write_bits(counts->max_zero_fill,5);
2115 write_bits(counts->length_bits,5);
2116 write_bits((ulonglong) counts->tree->tree_number - 1, huff_tree_bits);
2117 DBUG_PRINT(
"info", (
"column: %3u type: %2u pack: %2u zero: %4u "
2118 "lbits: %2u tree: %2u length: %4u",
2119 i , counts->field_type, counts->pack_type,
2120 counts->max_zero_fill, counts->length_bits,
2121 counts->tree->tree_number, counts->field_length));
2123 printf(
"column: %3u type: %2u pack: %2u zero: %4u lbits: %2u "
2124 "tree: %2u length: %4u\n", i , counts->field_type,
2125 counts->pack_type, counts->max_zero_fill, counts->length_bits,
2126 counts->tree->tree_number, counts->field_length);
2136 static my_off_t write_huff_tree(
HUFF_TREE *huff_tree, uint trees)
2142 uint *packed_tree,*
offset,length;
2146 for (i=length=0 ; i < trees ; i++)
2147 if (huff_tree[i].tree_number > 0 && huff_tree[i].elements > length)
2148 length=huff_tree[
i].elements;
2153 if (!(packed_tree=(uint*) my_alloca(
sizeof(uint)*length*2)))
2155 my_error(EE_OUTOFMEMORY, MYF(ME_BELL+ME_FATALERROR),
2156 sizeof(uint)*length*2);
2160 DBUG_PRINT(
"info", (
" "));
2165 for (elements=0; trees-- ; huff_tree++)
2168 if (huff_tree->tree_number == 0)
2171 DBUG_PRINT(
"info", (
" "));
2175 elements+=huff_tree->elements;
2176 huff_tree->max_offset=2;
2178 if (huff_tree->elements <= 1)
2181 offset=make_offset_code_tree(huff_tree,huff_tree->root,packed_tree);
2184 huff_tree->offset_bits=max_bit(huff_tree->max_offset);
2190 if (huff_tree->max_offset >= IS_OFFSET)
2192 (void) fprintf(stderr,
"Tree offset got too big: %d, aborted\n",
2193 huff_tree->max_offset);
2194 my_afree((uchar*) packed_tree);
2198 DBUG_PRINT(
"info", (
"pos: %lu elements: %u tree-elements: %lu "
2200 (ulong) (file_buffer.pos - file_buffer.buffer),
2201 huff_tree->elements, (ulong) (offset - packed_tree),
2202 huff_tree->char_bits));
2203 if (!huff_tree->counts->tree_buff)
2207 write_bits(huff_tree->min_chr,8);
2208 write_bits(huff_tree->elements,9);
2209 write_bits(huff_tree->char_bits,5);
2210 write_bits(huff_tree->offset_bits,5);
2215 int_length=(uint) (huff_tree->counts->tree_pos -
2216 huff_tree->counts->tree_buff);
2219 write_bits(huff_tree->elements,15);
2220 write_bits(int_length,16);
2221 write_bits(huff_tree->char_bits,5);
2222 write_bits(huff_tree->offset_bits,5);
2223 intervall_length+=int_length;
2225 DBUG_PRINT(
"info", (
"tree: %2u elements: %4u char_bits: %2u "
2226 "offset_bits: %2u %s: %5u codelen: %2u",
2227 tree_no, huff_tree->elements, huff_tree->char_bits,
2228 huff_tree->offset_bits, huff_tree->counts->tree_buff ?
2229 "bufflen" :
"min_chr", huff_tree->counts->tree_buff ?
2230 int_length : huff_tree->min_chr, huff_tree->height));
2232 printf(
"tree: %2u elements: %4u char_bits: %2u offset_bits: %2u "
2233 "%s: %5u codelen: %2u\n", tree_no, huff_tree->elements,
2234 huff_tree->char_bits, huff_tree->offset_bits,
2235 huff_tree->counts->tree_buff ?
"bufflen" :
"min_chr",
2236 huff_tree->counts->tree_buff ? int_length :
2237 huff_tree->min_chr, huff_tree->height);
2240 length=(uint) (offset-packed_tree);
2241 if (length != huff_tree->elements*2-2)
2243 (void) fprintf(stderr,
"error: Huff-tree-length: %d != calc_length: %d\n",
2244 length, huff_tree->elements * 2 - 2);
2249 for (i=0 ; i < length ; i++)
2251 if (packed_tree[i] & IS_OFFSET)
2252 write_bits(packed_tree[i] - IS_OFFSET+ (1 << huff_tree->offset_bits),
2253 huff_tree->offset_bits+1);
2255 write_bits(packed_tree[i]-huff_tree->min_chr,huff_tree->char_bits+1);
2256 DBUG_PRINT(
"info", (
"tree[0x%04x]: %s0x%04x",
2257 i, (packed_tree[i] & IS_OFFSET) ?
2258 " -> " :
"", (packed_tree[i] & IS_OFFSET) ?
2259 packed_tree[i] - IS_OFFSET + i : packed_tree[i]));
2261 printf(
"tree[0x%04x]: %s0x%04x\n",
2262 i, (packed_tree[i] & IS_OFFSET) ?
" -> " :
"",
2263 (packed_tree[i] & IS_OFFSET) ?
2264 packed_tree[i] - IS_OFFSET + i : packed_tree[i]);
2271 codes= huff_tree->counts->tree_buff ? huff_tree->elements : 256;
2272 for (i= 0; i < codes; i++)
2279 if (! (len= huff_tree->code_len[i]))
2281 DBUG_PRINT(
"info", (
"code[0x%04x]: 0x%s bits: %2u bin: %s", i,
2282 hexdigits(huff_tree->code[i]), huff_tree->code_len[i],
2283 bindigits(huff_tree->code[i],
2284 huff_tree->code_len[i])));
2286 printf(
"code[0x%04x]: 0x%s bits: %2u bin: %s\n", i,
2287 hexdigits(huff_tree->code[i]), huff_tree->code_len[i],
2288 bindigits(huff_tree->code[i], huff_tree->code_len[i]));
2294 DBUG_EXECUTE_IF(
"forcechkerr1", len--;);
2295 DBUG_EXECUTE_IF(
"forcechkerr2", bits= 8 *
sizeof(code););
2296 DBUG_EXECUTE_IF(
"forcechkerr3", idx= length;);
2301 (void) fflush(stdout);
2302 (void) fprintf(stderr,
"error: code 0x%s with %u bits not found\n",
2303 hexdigits(huff_tree->code[i]), huff_tree->code_len[
i]);
2308 code|= (huff_tree->code[
i] >> (--len)) & 1;
2310 if (bits > 8 *
sizeof(code))
2312 (void) fflush(stdout);
2313 (void) fprintf(stderr,
"error: Huffman code too long: %u/%u\n",
2314 bits, (uint) (8 *
sizeof(code)));
2318 idx+= (uint) code & 1;
2321 (void) fflush(stdout);
2322 (void) fprintf(stderr,
"error: illegal tree offset: %u/%u\n",
2327 if (packed_tree[idx] & IS_OFFSET)
2328 idx+= packed_tree[idx] & ~IS_OFFSET;
2335 DBUG_EXECUTE_IF(
"forcechkerr4", packed_tree[idx]++;);
2336 if (packed_tree[idx] != i)
2338 (void) fflush(stdout);
2339 (void) fprintf(stderr,
"error: decoded value 0x%04x should be: 0x%04x\n",
2340 packed_tree[idx], i);
2349 if (huff_tree->counts->tree_buff)
2351 for (i=0 ; i < int_length ; i++)
2353 write_bits((ulonglong) (uchar) huff_tree->counts->tree_buff[i], 8);
2354 DBUG_PRINT(
"info", (
"column_values[0x%04x]: 0x%02x",
2355 i, (uchar) huff_tree->counts->tree_buff[i]));
2357 printf(
"column_values[0x%04x]: 0x%02x\n",
2358 i, (uchar) huff_tree->counts->tree_buff[i]);
2363 DBUG_PRINT(
"info", (
" "));
2366 my_afree((uchar*) packed_tree);
2369 (void) fprintf(stderr,
"Error: Generated decode trees are corrupt. Stop.\n");
2390 if (!element->a.nod.left->a.leaf.null)
2393 prev_offset[0] =(uint) element->a.nod.left->a.leaf.element_nr;
2402 prev_offset[0]= IS_OFFSET+2;
2403 offset=make_offset_code_tree(huff_tree,element->a.nod.left,offset+2);
2407 if (!element->a.nod.right->a.leaf.null)
2410 prev_offset[1]=element->a.nod.right->a.leaf.element_nr;
2419 uint temp=(uint) (offset-prev_offset-1);
2420 prev_offset[1]= IS_OFFSET+
temp;
2421 if (huff_tree->max_offset < temp)
2422 huff_tree->max_offset =
temp;
2423 return make_offset_code_tree(huff_tree,element->a.nod.right,offset);
2429 static uint max_bit(
register uint value)
2442 uint
i,max_calc_length,pack_ref_length,min_record_length,max_record_length,
2443 intervall,field_length,max_pack_length,pack_blob_length;
2444 my_off_t record_count;
2446 ulong length,pack_length;
2447 uchar *record,*pos,*end_pos,*record_pos,*start_pos;
2450 MI_INFO *isam_file=mrg->file[0];
2451 uint pack_version= (uint) isam_file->s->pack.version;
2452 DBUG_ENTER(
"compress_isam_file");
2455 if (!(record=(uchar*) my_alloca(isam_file->s->base.reclength)))
2458 end_count=huff_counts+isam_file->s->base.fields;
2459 min_record_length= (uint) ~0;
2460 max_record_length=0;
2471 for (i=max_calc_length=0 ; i < isam_file->s->base.fields ; i++)
2473 if (!(huff_counts[i].pack_type & PACK_TYPE_ZERO_FILL))
2474 huff_counts[i].max_zero_fill=0;
2475 if (huff_counts[i].field_type == FIELD_CONSTANT ||
2476 huff_counts[i].field_type == FIELD_ZERO ||
2477 huff_counts[i].field_type == FIELD_CHECK)
2479 if (huff_counts[i].field_type == FIELD_INTERVALL)
2480 max_calc_length+=huff_counts[
i].tree->height;
2481 else if (huff_counts[i].field_type == FIELD_BLOB ||
2482 huff_counts[i].field_type == FIELD_VARCHAR)
2483 max_calc_length+=huff_counts[
i].tree->height*huff_counts[
i].max_length + huff_counts[
i].length_bits +1;
2486 (huff_counts[
i].field_length - huff_counts[
i].max_zero_fill)*
2487 huff_counts[i].tree->height+huff_counts[i].length_bits;
2489 max_calc_length= (max_calc_length + 7) / 8;
2490 pack_ref_length= calc_pack_length(pack_version, max_calc_length);
2493 pack_blob_length= isam_file->s->base.blobs ?
2494 calc_pack_length(pack_version, mrg->max_blob_length) : 0;
2495 max_pack_length=pack_ref_length+pack_blob_length;
2497 DBUG_PRINT(
"fields", (
"==="));
2499 while ((error=mrg_rrnd(mrg,record)) != HA_ERR_END_OF_FILE)
2501 ulong tot_blob_length=0;
2504 if (flush_buffer((ulong) max_calc_length + (ulong) max_pack_length))
2506 record_pos= (uchar*) file_buffer.pos;
2507 file_buffer.pos+=max_pack_length;
2508 for (start_pos=record, count= huff_counts; count < end_count ; count++)
2510 end_pos=start_pos+(field_length=count->field_length);
2513 DBUG_PRINT(
"fields", (
"column: %3lu type: %2u pack: %2u zero: %4u "
2514 "lbits: %2u tree: %2u length: %4u",
2515 (ulong) (count - huff_counts + 1),
2517 count->pack_type, count->max_zero_fill,
2518 count->length_bits, count->tree->tree_number,
2519 count->field_length));
2522 if (count->pack_type & PACK_TYPE_SPACE_FIELDS)
2524 for (pos=start_pos ; *pos ==
' ' && pos < end_pos; pos++) ;
2527 DBUG_PRINT(
"fields",
2528 (
"PACK_TYPE_SPACE_FIELDS spaces only, bits: 1"));
2529 DBUG_PRINT(
"fields", (
"---"));
2534 DBUG_PRINT(
"fields",
2535 (
"PACK_TYPE_SPACE_FIELDS not only spaces, bits: 1"));
2538 end_pos-=count->max_zero_fill;
2539 field_length-=count->max_zero_fill;
2541 switch (count->field_type) {
2542 case FIELD_SKIP_ZERO:
2543 if (!memcmp((uchar*) start_pos,zero_string,field_length))
2545 DBUG_PRINT(
"fields", (
"FIELD_SKIP_ZERO zeroes only, bits: 1"));
2550 DBUG_PRINT(
"fields", (
"FIELD_SKIP_ZERO not only zeroes, bits: 1"));
2554 DBUG_PRINT(
"fields", (
"FIELD_NORMAL %lu bytes",
2555 (ulong) (end_pos - start_pos)));
2556 for ( ; start_pos < end_pos ; start_pos++)
2558 DBUG_PRINT(
"fields",
2559 (
"value: 0x%02x code: 0x%s bits: %2u bin: %s",
2561 hexdigits(tree->code[(uchar) *start_pos]),
2562 (uint) tree->code_len[(uchar) *start_pos],
2563 bindigits(tree->code[(uchar) *start_pos],
2564 (uint) tree->code_len[(uchar) *start_pos])));
2565 write_bits(tree->code[(uchar) *start_pos],
2566 (uint) tree->code_len[(uchar) *start_pos]);
2569 case FIELD_SKIP_ENDSPACE:
2570 for (pos=end_pos ; pos > start_pos && pos[-1] ==
' ' ; pos--) ;
2571 length= (ulong) (end_pos - pos);
2572 if (count->pack_type & PACK_TYPE_SELECTED)
2574 if (length > count->min_space)
2576 DBUG_PRINT(
"fields",
2577 (
"FIELD_SKIP_ENDSPACE more than min_space, bits: 1"));
2578 DBUG_PRINT(
"fields",
2579 (
"FIELD_SKIP_ENDSPACE skip %lu/%u bytes, bits: %2u",
2580 length, field_length, count->length_bits));
2582 write_bits(length,count->length_bits);
2586 DBUG_PRINT(
"fields",
2587 (
"FIELD_SKIP_ENDSPACE not more than min_space, "
2595 DBUG_PRINT(
"fields",
2596 (
"FIELD_SKIP_ENDSPACE skip %lu/%u bytes, bits: %2u",
2597 length, field_length, count->length_bits));
2598 write_bits(length,count->length_bits);
2601 DBUG_PRINT(
"fields", (
"FIELD_SKIP_ENDSPACE %lu bytes",
2602 (ulong) (pos - start_pos)));
2603 for ( ; start_pos < pos ; start_pos++)
2605 DBUG_PRINT(
"fields",
2606 (
"value: 0x%02x code: 0x%s bits: %2u bin: %s",
2608 hexdigits(tree->code[(uchar) *start_pos]),
2609 (uint) tree->code_len[(uchar) *start_pos],
2610 bindigits(tree->code[(uchar) *start_pos],
2611 (uint) tree->code_len[(uchar) *start_pos])));
2612 write_bits(tree->code[(uchar) *start_pos],
2613 (uint) tree->code_len[(uchar) *start_pos]);
2617 case FIELD_SKIP_PRESPACE:
2618 for (pos=start_pos ; pos < end_pos && pos[0] ==
' ' ; pos++) ;
2619 length= (ulong) (pos - start_pos);
2620 if (count->pack_type & PACK_TYPE_SELECTED)
2622 if (length > count->min_space)
2624 DBUG_PRINT(
"fields",
2625 (
"FIELD_SKIP_PRESPACE more than min_space, bits: 1"));
2626 DBUG_PRINT(
"fields",
2627 (
"FIELD_SKIP_PRESPACE skip %lu/%u bytes, bits: %2u",
2628 length, field_length, count->length_bits));
2630 write_bits(length,count->length_bits);
2634 DBUG_PRINT(
"fields",
2635 (
"FIELD_SKIP_PRESPACE not more than min_space, "
2643 DBUG_PRINT(
"fields",
2644 (
"FIELD_SKIP_PRESPACE skip %lu/%u bytes, bits: %2u",
2645 length, field_length, count->length_bits));
2646 write_bits(length,count->length_bits);
2649 DBUG_PRINT(
"fields", (
"FIELD_SKIP_PRESPACE %lu bytes",
2650 (ulong) (end_pos - start_pos)));
2651 for (start_pos=pos ; start_pos < end_pos ; start_pos++)
2653 DBUG_PRINT(
"fields",
2654 (
"value: 0x%02x code: 0x%s bits: %2u bin: %s",
2656 hexdigits(tree->code[(uchar) *start_pos]),
2657 (uint) tree->code_len[(uchar) *start_pos],
2658 bindigits(tree->code[(uchar) *start_pos],
2659 (uint) tree->code_len[(uchar) *start_pos])));
2660 write_bits(tree->code[(uchar) *start_pos],
2661 (uint) tree->code_len[(uchar) *start_pos]);
2664 case FIELD_CONSTANT:
2667 DBUG_PRINT(
"fields", (
"FIELD_CONSTANT/ZERO/CHECK"));
2670 case FIELD_INTERVALL:
2672 pos=(uchar*) tree_search(&count->int_tree, start_pos,
2673 count->int_tree.custom_arg);
2674 intervall=(uint) (pos - count->tree_buff)/field_length;
2675 DBUG_PRINT(
"fields", (
"FIELD_INTERVALL"));
2676 DBUG_PRINT(
"fields", (
"index: %4u code: 0x%s bits: %2u",
2677 intervall, hexdigits(tree->code[intervall]),
2678 (uint) tree->code_len[intervall]));
2679 write_bits(tree->code[intervall],(uint) tree->code_len[intervall]);
2684 ulong blob_length=_mi_calc_blob_length(field_length-
2685 portable_sizeof_char_ptr,
2690 DBUG_PRINT(
"fields", (
"FIELD_BLOB empty, bits: 1"));
2695 uchar *blob,*blob_end;
2696 DBUG_PRINT(
"fields", (
"FIELD_BLOB not empty, bits: 1"));
2699 DBUG_PRINT(
"fields", (
"FIELD_BLOB %lu bytes, bits: %2u",
2700 blob_length, count->length_bits));
2701 write_bits(blob_length,count->length_bits);
2702 memcpy(&blob, end_pos-portable_sizeof_char_ptr,
sizeof(
char*));
2703 blob_end=blob+blob_length;
2705 for ( ; blob < blob_end ; blob++)
2707 DBUG_PRINT(
"fields",
2708 (
"value: 0x%02x code: 0x%s bits: %2u bin: %s",
2709 (uchar) *blob, hexdigits(tree->code[(uchar) *blob]),
2710 (uint) tree->code_len[(uchar) *blob],
2711 bindigits(tree->code[(uchar) *start_pos],
2712 (uint)tree->code_len[(uchar) *start_pos])));
2713 write_bits(tree->code[(uchar) *blob],
2714 (uint) tree->code_len[(uchar) *blob]);
2716 tot_blob_length+=blob_length;
2723 uint var_pack_length= HA_VARCHAR_PACKLENGTH(count->field_length-1);
2724 ulong col_length= (var_pack_length == 1 ?
2725 (uint) *(uchar*) start_pos :
2726 uint2korr(start_pos));
2730 DBUG_PRINT(
"fields", (
"FIELD_VARCHAR empty, bits: 1"));
2735 uchar *end= start_pos + var_pack_length + col_length;
2736 DBUG_PRINT(
"fields", (
"FIELD_VARCHAR not empty, bits: 1"));
2739 DBUG_PRINT(
"fields", (
"FIELD_VARCHAR %lu bytes, bits: %2u",
2740 col_length, count->length_bits));
2741 write_bits(col_length,count->length_bits);
2743 for (start_pos+= var_pack_length ; start_pos < end ; start_pos++)
2745 DBUG_PRINT(
"fields",
2746 (
"value: 0x%02x code: 0x%s bits: %2u bin: %s",
2748 hexdigits(tree->code[(uchar) *start_pos]),
2749 (uint) tree->code_len[(uchar) *start_pos],
2750 bindigits(tree->code[(uchar) *start_pos],
2751 (uint)tree->code_len[(uchar) *start_pos])));
2752 write_bits(tree->code[(uchar) *start_pos],
2753 (uint) tree->code_len[(uchar) *start_pos]);
2760 case FIELD_enum_val_count:
2763 start_pos+=count->max_zero_fill;
2764 DBUG_PRINT(
"fields", (
"---"));
2767 length=(ulong) ((uchar*) file_buffer.pos - record_pos) - max_pack_length;
2768 pack_length= save_pack_length(pack_version, record_pos, length);
2769 if (pack_blob_length)
2770 pack_length+= save_pack_length(pack_version, record_pos + pack_length,
2772 DBUG_PRINT(
"fields", (
"record: %lu length: %lu blob-length: %lu "
2773 "length-bytes: %lu", (ulong) record_count, length,
2774 tot_blob_length, pack_length));
2775 DBUG_PRINT(
"fields", (
"==="));
2778 if (pack_length != max_pack_length)
2780 bmove(record_pos+pack_length,record_pos+max_pack_length,length);
2781 file_buffer.pos-= (max_pack_length-pack_length);
2783 if (length < (ulong) min_record_length)
2784 min_record_length=(uint) length;
2785 if (length > (ulong) max_record_length)
2786 max_record_length=(uint) length;
2788 if (write_loop && record_count % WRITE_COUNT == 0)
2790 printf(
"%lu\r", (ulong) record_count);
2791 (void) fflush(stdout);
2794 else if (error != HA_ERR_RECORD_DELETED)
2797 if (error == HA_ERR_END_OF_FILE)
2801 (void) fprintf(stderr,
"%s: Got error %d reading records\n",
2802 my_progname, error);
2805 printf(
"wrote %s records.\n", llstr((longlong) record_count, llbuf));
2807 my_afree((uchar*) record);
2808 mrg->ref_length=max_pack_length;
2809 mrg->min_pack_length=max_record_length ? min_record_length : 0;
2810 mrg->max_pack_length=max_record_length;
2811 DBUG_RETURN(error || error_on_write || flush_buffer(~(ulong) 0));
2815 static char *make_new_name(
char *new_name,
char *old_name)
2817 return fn_format(new_name,old_name,
"",DATA_TMP_EXT,2+4);
2820 static char *make_old_name(
char *new_name,
char *old_name)
2822 return fn_format(new_name,old_name,
"",OLD_EXT,2+4);
2827 static void init_file_buffer(File
file, pbool read_buffer)
2829 file_buffer.file=
file;
2830 file_buffer.buffer= (uchar*) my_malloc(ALIGN_SIZE(RECORD_CACHE_SIZE),
2832 file_buffer.end=file_buffer.buffer+ALIGN_SIZE(RECORD_CACHE_SIZE)-8;
2833 file_buffer.pos_in_file=0;
2838 file_buffer.pos=file_buffer.end;
2843 file_buffer.pos=file_buffer.buffer;
2844 file_buffer.bits=BITS_SAVED;
2846 file_buffer.bitbucket= 0;
2850 static int flush_buffer(ulong neaded_length)
2865 if ((file_buffer.pos < file_buffer.end) &&
2866 ((ulong) (file_buffer.end - file_buffer.pos) > neaded_length))
2868 length=(ulong) (file_buffer.pos-file_buffer.buffer);
2869 file_buffer.pos=file_buffer.buffer;
2870 file_buffer.pos_in_file+=length;
2873 if (error_on_write|| my_write(file_buffer.file,
2874 (
const uchar*) file_buffer.buffer,
2876 MYF(MY_WME | MY_NABP | MY_WAIT_IF_FULL)))
2882 if (neaded_length != ~(ulong) 0 &&
2883 (ulong) (file_buffer.end-file_buffer.buffer) < neaded_length)
2887 tmp= my_realloc((
char*) file_buffer.buffer, neaded_length,MYF(MY_WME));
2890 file_buffer.pos= ((uchar*) tmp +
2891 (ulong) (file_buffer.pos - file_buffer.buffer));
2892 file_buffer.buffer= (uchar*) tmp;
2893 file_buffer.end= (uchar*) (tmp+neaded_length-8);
2899 static void end_file_buffer(
void)
2901 my_free(file_buffer.buffer);
2906 static void write_bits(
register ulonglong value,
register uint bits)
2908 DBUG_ASSERT(((bits < 8 *
sizeof(value)) && ! (value >> bits)) ||
2909 (bits == 8 *
sizeof(value)));
2911 if ((file_buffer.bits-= (
int) bits) >= 0)
2913 file_buffer.bitbucket|= value << file_buffer.bits;
2917 reg3 ulonglong bit_buffer;
2918 bits= (uint) -file_buffer.bits;
2919 bit_buffer= (file_buffer.bitbucket |
2920 ((bits != 8 *
sizeof(value)) ? (value >> bits) : 0));
2921 #if BITS_SAVED == 64
2922 *file_buffer.pos++= (uchar) (bit_buffer >> 56);
2923 *file_buffer.pos++= (uchar) (bit_buffer >> 48);
2924 *file_buffer.pos++= (uchar) (bit_buffer >> 40);
2925 *file_buffer.pos++= (uchar) (bit_buffer >> 32);
2927 *file_buffer.pos++= (uchar) (bit_buffer >> 24);
2928 *file_buffer.pos++= (uchar) (bit_buffer >> 16);
2929 *file_buffer.pos++= (uchar) (bit_buffer >> 8);
2930 *file_buffer.pos++= (uchar) (bit_buffer);
2932 if (bits != 8 *
sizeof(value))
2933 value&= (((ulonglong) 1) << bits) - 1;
2934 if (file_buffer.pos >= file_buffer.end)
2935 (void) flush_buffer(~ (ulong) 0);
2936 file_buffer.bits=(int) (BITS_SAVED - bits);
2937 file_buffer.bitbucket= value << (BITS_SAVED - bits);
2944 static void flush_bits(
void)
2947 ulonglong bit_buffer;
2949 bits= file_buffer.bits & ~7;
2950 bit_buffer= file_buffer.bitbucket >> bits;
2951 bits= BITS_SAVED - bits;
2955 *file_buffer.pos++= (uchar) (bit_buffer >> bits);
2957 if (file_buffer.pos >= file_buffer.end)
2958 (void) flush_buffer(~ (ulong) 0);
2959 file_buffer.bits= BITS_SAVED;
2960 file_buffer.bitbucket= 0;
2972 uint options=mi_uint2korr(share->state.header.options);
2974 DBUG_ENTER(
"save_state");
2976 options|= HA_OPTION_COMPRESS_RECORD | HA_OPTION_READ_ONLY_DATA;
2977 mi_int2store(share->state.header.options,options);
2979 share->state.state.data_file_length=new_length;
2980 share->state.state.del=0;
2981 share->state.state.empty=0;
2982 share->state.dellink= HA_OFFSET_ERROR;
2983 share->state.split=(ha_rows) mrg->records;
2984 share->state.version=(ulong) time((time_t*) 0);
2985 if (! mi_is_all_keys_active(share->state.key_map, share->base.keys))
2992 share->state.state.key_file_length= new_length;
2999 mi_clear_all_keys_active(share->state.key_map);
3000 for (key=0 ; key < share->base.keys ; key++)
3001 share->state.key_root[key]= HA_OFFSET_ERROR;
3002 for (key=0 ; key < share->state.header.max_block_size_index ; key++)
3003 share->state.key_del[key]= HA_OFFSET_ERROR;
3004 isam_file->state->checksum=crc;
3006 share->state.open_count=0;
3007 share->global_changed=0;
3008 (
void) my_chsize(share->kfile, share->base.keystart, 0, MYF(0));
3009 if (share->base.keys)
3011 DBUG_RETURN(mi_state_info_write(share->kfile,&share->state,1+2));
3015 static int save_state_mrg(File file,
PACK_MRG_INFO *mrg,my_off_t new_length,
3019 MI_INFO *isam_file=mrg->file[0];
3021 DBUG_ENTER(
"save_state_mrg");
3023 state= isam_file->s->state;
3024 options= (mi_uint2korr(state.header.options) | HA_OPTION_COMPRESS_RECORD |
3025 HA_OPTION_READ_ONLY_DATA);
3026 mi_int2store(state.header.options,options);
3027 state.state.data_file_length=new_length;
3029 state.state.empty=0;
3030 state.state.records=state.split=(ha_rows) mrg->records;
3032 if (mrg->src_file_has_indexes_disabled)
3034 isam_file->s->state.state.key_file_length=
3035 MY_MAX(isam_file->s->state.state.key_file_length, new_length);
3037 state.dellink= HA_OFFSET_ERROR;
3038 state.version=(ulong) time((time_t*) 0);
3039 mi_clear_all_keys_active(state.key_map);
3040 state.state.checksum=crc;
3041 if (isam_file->s->base.keys)
3043 state.changed=STATE_CHANGED | STATE_NOT_ANALYZED;
3044 DBUG_RETURN (mi_state_info_write(file,&state,1+2));
3054 mi_extra(*mrg->current, HA_EXTRA_NO_CACHE, 0);
3067 isam_info= *(info->current=info->file);
3068 info->end=info->current+info->count;
3069 mi_reset(isam_info);
3070 mi_extra(isam_info, HA_EXTRA_CACHE, 0);
3071 filepos=isam_info->s->pack.header_length;
3075 isam_info= *info->current;
3076 filepos= isam_info->nextpos;
3081 isam_info->update&= HA_STATE_CHANGED;
3082 if (!(error=(*isam_info->s->read_rnd)(isam_info,(uchar*) buf,
3084 error != HA_ERR_END_OF_FILE)
3086 mi_extra(isam_info,HA_EXTRA_NO_CACHE, 0);
3087 if (info->current+1 == info->end)
3088 return(HA_ERR_END_OF_FILE);
3090 isam_info= *info->current;
3091 filepos=isam_info->s->pack.header_length;
3092 mi_reset(isam_info);
3093 mi_extra(isam_info,HA_EXTRA_CACHE, 0);
3102 for (i=0 ; i < mrg->count ; i++)
3103 error|=mi_close(mrg->file[i]);
3110 #if !defined(DBUG_OFF)
3153 my_off_t *cur_count_p;
3154 my_off_t *end_count_p;
3155 my_off_t **cur_sort_p;
3156 my_off_t **end_sort_p;
3157 my_off_t *sort_counts[256];
3159 DBUG_ENTER(
"fakebigcodes");
3161 for (count= huff_counts; count < end_count; count++)
3166 if (huff_counts->tree_buff)
3168 my_free(huff_counts->tree_buff);
3169 delete_tree(&huff_counts->int_tree);
3170 huff_counts->tree_buff= NULL;
3171 DBUG_PRINT(
"fakebigcodes", (
"freed distinct column values"));
3177 cur_count_p= count->counts;
3178 end_count_p= cur_count_p + 256;
3179 cur_sort_p= sort_counts;
3180 while (cur_count_p < end_count_p)
3181 *(cur_sort_p++)= cur_count_p++;
3182 (void) my_qsort(sort_counts, 256,
sizeof(my_off_t*), (qsort_cmp) fakecmp);
3187 cur_sort_p= sort_counts;
3188 #if SIZEOF_LONG_LONG > 4
3189 end_sort_p= sort_counts + 8 *
sizeof(ulonglong) - 1;
3191 end_sort_p= sort_counts + 8 *
sizeof(ulonglong) - 2;
3194 **(cur_sort_p++)= 1;
3196 while (cur_sort_p < end_sort_p)
3198 **(cur_sort_p++)= total;
3202 **(cur_sort_p++)= --total;
3206 end_sort_p= sort_counts + 256;
3207 while (cur_sort_p < end_sort_p)
3208 **(cur_sort_p++)= 1;
3228 static int fakecmp(my_off_t **count1, my_off_t **count2)
3230 return ((**count1 < **count2) ? 1 :
3231 (**count1 > **count2) ? -1 : 0);
3235 #include "mi_extrafunc.h"