#include "myisamdef.h"#include <queues.h>#include <my_tree.h>#include "mysys_err.h"#include <my_getopt.h>#include <assert.h>#include <help_start.h>#include <help_end.h>Include dependency graph for myisampack.c:

Go to the source code of this file.
Classes | |
| struct | st_file_buffer |
| struct | st_huff_counts |
| struct | st_huff_element |
| union | st_huff_element::un_element |
| struct | st_huff_element::un_element::st_nod |
| struct | st_huff_element::un_element::st_leaf |
| struct | st_huff_tree |
| struct | st_isam_mrg |
Defines | |
| #define | USE_MY_FUNC |
| #define | __GNU_LIBRARY__ |
| #define | BITS_SAVED 32 |
| #define | IS_OFFSET ((uint) 32768) |
| #define | HEAD_LENGTH 32 |
| #define | ALLOWED_JOIN_DIFF 256 |
| #define | DATA_TMP_EXT ".TMD" |
| #define | OLD_EXT ".OLD" |
| #define | WRITE_COUNT MY_HOW_OFTEN_TO_WRITE |
Typedefs | |
| typedef st_huff_counts | HUFF_COUNTS |
| typedef st_huff_element | HUFF_ELEMENT |
| typedef st_huff_tree | HUFF_TREE |
| typedef st_isam_mrg | PACK_MRG_INFO |
Enumerations | |
| enum | options_mp { OPT_CHARSETS_DIR_MP = 256, OPT_AUTO_CLOSE } |
Functions | |
| int | main (int argc, char **argv) |
| static void | get_options (int *argc, char ***argv) |
| static MI_INFO * | open_isam_file (char *name, int mode) |
| static bool | open_isam_files (PACK_MRG_INFO *mrg, char **names, uint count) |
| static int | compress (PACK_MRG_INFO *file, char *join_name) |
| static HUFF_COUNTS * | init_huff_count (MI_INFO *info, my_off_t records) |
| static void | free_counts_and_tree_and_queue (HUFF_TREE *huff_trees, uint trees, HUFF_COUNTS *huff_counts, uint fields) |
| static int | compare_tree (void *cmp_arg __attribute__((unused)), const uchar *s, const uchar *t) |
| static int | get_statistic (PACK_MRG_INFO *mrg, HUFF_COUNTS *huff_counts) |
| static void | check_counts (HUFF_COUNTS *huff_counts, uint trees, my_off_t records) |
| static int | test_space_compress (HUFF_COUNTS *huff_counts, my_off_t records, uint max_space_length, my_off_t *space_counts, my_off_t tot_space_count, enum en_fieldtype field_type) |
| static HUFF_TREE * | make_huff_trees (HUFF_COUNTS *huff_counts, uint trees) |
| static int | make_huff_tree (HUFF_TREE *tree, HUFF_COUNTS *huff_counts) |
| static int | compare_huff_elements (void *not_used, byte *a, byte *b) |
| static int | save_counts_in_queue (byte *key, element_count count, HUFF_TREE *tree) |
| static my_off_t | calc_packed_length (HUFF_COUNTS *huff_counts, uint flag) |
| static uint | join_same_trees (HUFF_COUNTS *huff_counts, uint trees) |
| static int | make_huff_decode_table (HUFF_TREE *huff_tree, uint trees) |
| static void | make_traverse_code_tree (HUFF_TREE *huff_tree, HUFF_ELEMENT *element, uint size, ulonglong code) |
| static int | write_header (PACK_MRG_INFO *isam_file, uint header_length, uint trees, my_off_t tot_elements, my_off_t filelength) |
| static void | write_field_info (HUFF_COUNTS *counts, uint fields, uint trees) |
| static my_off_t | write_huff_tree (HUFF_TREE *huff_tree, uint trees) |
| static uint * | make_offset_code_tree (HUFF_TREE *huff_tree, HUFF_ELEMENT *element, uint *offset) |
| static uint | max_bit (uint value) |
| static int | compress_isam_file (PACK_MRG_INFO *file, HUFF_COUNTS *huff_counts) |
| static char * | make_new_name (char *new_name, char *old_name) |
| static char * | make_old_name (char *new_name, char *old_name) |
| static void | init_file_buffer (File file, pbool read_buffer) |
| static int | flush_buffer (ulong neaded_length) |
| static void | end_file_buffer (void) |
| static void | write_bits (ulonglong value, uint bits) |
| static void | flush_bits (void) |
| static int | save_state (MI_INFO *isam_file, PACK_MRG_INFO *mrg, my_off_t new_length, ha_checksum crc) |
| static int | save_state_mrg (File file, PACK_MRG_INFO *isam_file, my_off_t new_length, ha_checksum crc) |
| static int | mrg_close (PACK_MRG_INFO *mrg) |
| static int | mrg_rrnd (PACK_MRG_INFO *info, byte *buf) |
| static void | mrg_reset (PACK_MRG_INFO *mrg) |
| static void | fakebigcodes (HUFF_COUNTS *huff_counts, HUFF_COUNTS *end_count) |
| static int | fakecmp (my_off_t **count1, my_off_t **count2) |
| static void | print_version (void) |
| static void | usage (void) |
| static my_bool | get_one_option (int optid, const struct my_option *opt __attribute__((unused)), char *argument) |
| static int | compare_huff_elements (void *not_used __attribute__((unused)), byte *a, byte *b) |
| static int | compare_tree (void *cmp_arg __attribute__((unused)), register const uchar *s, register const uchar *t) |
| static char * | bindigits (ulonglong value, uint bits) |
| static char * | hexdigits (ulonglong value) |
| static uint | max_bit (register uint value) |
| static void | write_bits (register ulonglong value, register uint bits) |
Variables | |
| static int | error_on_write = 0 |
| static int | test_only = 0 |
| static int | verbose = 0 |
| static int | silent = 0 |
| static int | write_loop = 0 |
| static int | force_pack = 0 |
| static int | isamchk_neaded = 0 |
| static int | tmpfile_createflag = O_RDWR | O_TRUNC | O_EXCL |
| static my_bool | backup |
| static my_bool | opt_wait |
| static uint | tree_buff_length = 65536 - MALLOC_OVERHEAD |
| static char | tmp_dir [FN_REFLEN] = {0} |
| static char * | join_table |
| static my_off_t | intervall_length |
| static ha_checksum | glob_crc |
| static struct st_file_buffer | file_buffer |
| static QUEUE | queue |
| static HUFF_COUNTS * | global_count |
| static char | zero_string [] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0} |
| static const char * | load_default_groups [] = { "myisampack",0 } |
| static struct my_option | my_long_options [] |
| #define __GNU_LIBRARY__ |
Definition at line 31 of file myisampack.c.
| #define ALLOWED_JOIN_DIFF 256 |
| #define BITS_SAVED 32 |
Definition at line 39 of file myisampack.c.
| #define DATA_TMP_EXT ".TMD" |
Definition at line 46 of file myisampack.c.
| #define HEAD_LENGTH 32 |
| #define IS_OFFSET ((uint) 32768) |
Definition at line 42 of file myisampack.c.
Referenced by make_offset_code_tree(), and write_huff_tree().
| #define OLD_EXT ".OLD" |
| #define USE_MY_FUNC |
Definition at line 20 of file myisampack.c.
| #define WRITE_COUNT MY_HOW_OFTEN_TO_WRITE |
Definition at line 48 of file myisampack.c.
| typedef struct st_huff_counts HUFF_COUNTS |
| typedef struct st_huff_element HUFF_ELEMENT |
Definition at line 77 of file myisampack.c.
| typedef struct st_huff_tree HUFF_TREE |
| typedef struct st_isam_mrg PACK_MRG_INFO |
| enum options_mp |
Definition at line 1960 of file myisampack.c.
References DBUG_ASSERT.
Referenced by compress_isam_file(), and write_huff_tree().
01961 { 01962 static char digits[72]; 01963 char *ptr= digits; 01964 uint idx= bits; 01965 01966 DBUG_ASSERT(idx < sizeof(digits)); 01967 while (idx) 01968 *(ptr++)= '0' + ((value >> (--idx)) & 1); 01969 *ptr= '\0'; 01970 return digits; 01971 }
Here is the caller graph for this function:

| static my_off_t calc_packed_length | ( | HUFF_COUNTS * | huff_counts, | |
| uint | flag | |||
| ) | [static] |
Definition at line 1730 of file myisampack.c.
References st_huff_counts::counts, and DBUG_ENTER.
Referenced by join_same_trees(), and test_space_compress().
01732 { 01733 uint i,found,bits_packed,first,last; 01734 my_off_t bytes_packed; 01735 HUFF_ELEMENT element_buffer[256]; 01736 DBUG_ENTER("calc_packed_length"); 01737 01738 /* 01739 WARNING: We use a small hack for efficiency: Instead of placing 01740 references to HUFF_ELEMENTs into the queue, we just insert 01741 references to the counts of the byte codes which appeared in this 01742 table column. During the Huffman algorithm they are successively 01743 replaced by references to HUFF_ELEMENTs. This works, because 01744 HUFF_ELEMENTs have the incidence count at their beginning. 01745 Regardless, wether the queue array contains references to counts of 01746 type my_off_t or references to HUFF_ELEMENTs which have the count of 01747 type my_off_t at their beginning, it always points to a count of the 01748 same type. 01749 01750 Instead of using queue_insert(), we just copy the references into 01751 the buffer of the priority queue. We insert in byte value order, but 01752 the order is in fact irrelevant here. We will establish the correct 01753 order later. 01754 */ 01755 first=last=0; 01756 for (i=found=0 ; i < 256 ; i++) 01757 { 01758 if (huff_counts->counts[i]) 01759 { 01760 if (! found++) 01761 first=i; 01762 last=i; 01763 /* We start with root[1], which is the queues top element. */ 01764 queue.root[found]=(byte*) &huff_counts->counts[i]; 01765 } 01766 } 01767 if (!found) 01768 DBUG_RETURN(0); /* Empty tree */ 01769 /* 01770 If there is only a single byte value in this field in all records, 01771 add a second element with zero incidence. This is required to enter 01772 the loop, which follows the Huffman algorithm. 01773 */ 01774 if (found < 2) 01775 queue.root[++found]=(byte*) &huff_counts->counts[last ? 0 : 1]; 01776 01777 /* Make a queue from the queue buffer. */ 01778 queue.elements=found; 01779 01780 bytes_packed=0; bits_packed=0; 01781 /* Add the length of the coding table, which would become part of the file. */ 01782 if (add_tree_lenght) 01783 bytes_packed=(8+9+5+5+(max_bit(last-first)+1)*found+ 01784 (max_bit(found-1)+1+1)*(found-2) +7)/8; 01785 01786 /* 01787 Make a priority queue from the queue. Construct its index so that we 01788 have a partially ordered tree. 01789 */ 01790 for (i=(found+1)/2 ; i > 0 ; i--) 01791 _downheap(&queue,i); 01792 01793 /* The Huffman algorithm. */ 01794 for (i=0 ; i < found-1 ; i++) 01795 { 01796 my_off_t *a; 01797 my_off_t *b; 01798 HUFF_ELEMENT *new_huff_el; 01799 01800 /* 01801 Pop the top element from the queue (the one with the least 01802 incidence). Popping from a priority queue includes a re-ordering 01803 of the queue, to get the next least incidence element to the top. 01804 */ 01805 a= (my_off_t*) queue_remove(&queue, 0); 01806 /* 01807 Copy the next least incidence element. The queue implementation 01808 reserves root[0] for temporary purposes. root[1] is the top. 01809 */ 01810 b= (my_off_t*) queue.root[1]; 01811 /* Create a new element in a local (automatic) buffer. */ 01812 new_huff_el= element_buffer + i; 01813 /* The new element gets the sum of the two least incidence elements. */ 01814 new_huff_el->count= *a + *b; 01815 /* 01816 The Huffman algorithm assigns another bit to the code for a byte 01817 every time that bytes incidence is combined (directly or indirectly) 01818 to a new element as one of the two least incidence elements. 01819 This means that one more bit per incidence of that byte is required 01820 in the resulting file. So we add the new combined incidence as the 01821 number of bits by which the result grows. 01822 */ 01823 bits_packed+=(uint) (new_huff_el->count & 7); 01824 bytes_packed+=new_huff_el->count/8; 01825 /* 01826 Replace the copied top element by the new element and re-order the 01827 queue. This successively replaces the references to counts by 01828 references to HUFF_ELEMENTs. 01829 */ 01830 queue.root[1]=(byte*) new_huff_el; 01831 queue_replaced(&queue); 01832 } 01833 DBUG_RETURN(bytes_packed+(bits_packed+7)/8); 01834 }
Here is the caller graph for this function:

| static void check_counts | ( | HUFF_COUNTS * | huff_counts, | |
| uint | trees, | |||
| my_off_t | records | |||
| ) | [static] |
Definition at line 1159 of file myisampack.c.
References bzero, DBUG_ENTER, FIELD_BLOB, FIELD_enum_val_count, st_huff_counts::field_type, FIELD_VARCHAR, int(), st_huff_counts::length_bits, max_bit(), and st_huff_counts::max_length.
Referenced by compress().
01161 { 01162 uint space_fields,fill_zero_fields,field_count[(int) FIELD_enum_val_count]; 01163 my_off_t old_length,new_length,length; 01164 DBUG_ENTER("check_counts"); 01165 01166 bzero((gptr) field_count,sizeof(field_count)); 01167 space_fields=fill_zero_fields=0; 01168 01169 for (; trees-- ; huff_counts++) 01170 { 01171 if (huff_counts->field_type == FIELD_BLOB) 01172 { 01173 huff_counts->length_bits=max_bit(huff_counts->max_length); 01174 goto found_pack; 01175 } 01176 else if (huff_counts->field_type == FIELD_VARCHAR) 01177 { 01178 huff_counts->length_bits=max_bit(huff_counts->max_length); 01179 goto found_pack; 01180 } 01181 else if (huff_counts->field_type == FIELD_CHECK) 01182 { 01183 huff_counts->bytes_packed=0; 01184 huff_counts->counts[0]=0; 01185 goto found_pack; 01186 } 01187 01188 huff_counts->field_type=FIELD_NORMAL; 01189 huff_counts->pack_type=0; 01190 01191 /* Check for zero-filled records (in this column), or zero records. */ 01192 if (huff_counts->zero_fields || ! records) 01193 { 01194 my_off_t old_space_count; 01195 /* 01196 If there are only zero filled records (in this column), 01197 or no records at all, we are done. 01198 */ 01199 if (huff_counts->zero_fields == records) 01200 { 01201 huff_counts->field_type= FIELD_ZERO; 01202 huff_counts->bytes_packed=0; 01203 huff_counts->counts[0]=0; 01204 goto found_pack; 01205 } 01206 /* Remeber the number of significant spaces. */ 01207 old_space_count=huff_counts->counts[' ']; 01208 /* Add all leading and trailing spaces. */ 01209 huff_counts->counts[' ']+= (huff_counts->tot_end_space + 01210 huff_counts->tot_pre_space + 01211 huff_counts->empty_fields * 01212 huff_counts->field_length); 01213 /* Check, what the compressed length of this would be. */ 01214 old_length=calc_packed_length(huff_counts,0)+records/8; 01215 /* Get the number of zero bytes. */ 01216 length=huff_counts->zero_fields*huff_counts->field_length; 01217 /* Add it to the counts. */ 01218 huff_counts->counts[0]+=length; 01219 /* Check, what the compressed length of this would be. */ 01220 new_length=calc_packed_length(huff_counts,0); 01221 /* If the compression without the zeroes would be shorter, we are done. */ 01222 if (old_length < new_length && huff_counts->field_length > 1) 01223 { 01224 huff_counts->field_type=FIELD_SKIP_ZERO; 01225 huff_counts->counts[0]-=length; 01226 huff_counts->bytes_packed=old_length- records/8; 01227 goto found_pack; 01228 } 01229 /* Remove the insignificant spaces, but keep the zeroes. */ 01230 huff_counts->counts[' ']=old_space_count; 01231 } 01232 /* Check, what the compressed length of this column would be. */ 01233 huff_counts->bytes_packed=calc_packed_length(huff_counts,0); 01234 01235 /* 01236 If there are enough empty records (in this column), 01237 treating them specially may pay off. 01238 */ 01239 if (huff_counts->empty_fields) 01240 { 01241 if (huff_counts->field_length > 2 && 01242 huff_counts->empty_fields + (records - huff_counts->empty_fields)* 01243 (1+max_bit(max(huff_counts->max_pre_space, 01244 huff_counts->max_end_space))) < 01245 records * max_bit(huff_counts->field_length)) 01246 { 01247 huff_counts->pack_type |= PACK_TYPE_SPACE_FIELDS; 01248 } 01249 else 01250 { 01251 length=huff_counts->empty_fields*huff_counts->field_length; 01252 if (huff_counts->tot_end_space || ! huff_counts->tot_pre_space) 01253 { 01254 huff_counts->tot_end_space+=length; 01255 huff_counts->max_end_space=huff_counts->field_length; 01256 if (huff_counts->field_length < 8) 01257 huff_counts->end_space[huff_counts->field_length]+= 01258 huff_counts->empty_fields; 01259 } 01260 if (huff_counts->tot_pre_space) 01261 { 01262 huff_counts->tot_pre_space+=length; 01263 huff_counts->max_pre_space=huff_counts->field_length; 01264 if (huff_counts->field_length < 8) 01265 huff_counts->pre_space[huff_counts->field_length]+= 01266 huff_counts->empty_fields; 01267 } 01268 } 01269 } 01270 01271 /* 01272 If there are enough trailing spaces (in this column), 01273 treating them specially may pay off. 01274 */ 01275 if (huff_counts->tot_end_space) 01276 { 01277 huff_counts->counts[' ']+=huff_counts->tot_pre_space; 01278 if (test_space_compress(huff_counts,records,huff_counts->max_end_space, 01279 huff_counts->end_space, 01280 huff_counts->tot_end_space,FIELD_SKIP_ENDSPACE)) 01281 goto found_pack; 01282 huff_counts->counts[' ']-=huff_counts->tot_pre_space; 01283 } 01284 01285 /* 01286 If there are enough leading spaces (in this column), 01287 treating them specially may pay off. 01288 */ 01289 if (huff_counts->tot_pre_space) 01290 { 01291 if (test_space_compress(huff_counts,records,huff_counts->max_pre_space, 01292 huff_counts->pre_space, 01293 huff_counts->tot_pre_space,FIELD_SKIP_PRESPACE)) 01294 goto found_pack; 01295 } 01296 01297 found_pack: /* Found field-packing */ 01298 01299 /* Test if we can use zero-fill */ 01300 01301 if (huff_counts->max_zero_fill && 01302 (huff_counts->field_type == FIELD_NORMAL || 01303 huff_counts->field_type == FIELD_SKIP_ZERO)) 01304 { 01305 huff_counts->counts[0]-=huff_counts->max_zero_fill* 01306 (huff_counts->field_type == FIELD_SKIP_ZERO ? 01307 records - huff_counts->zero_fields : records); 01308 huff_counts->pack_type|=PACK_TYPE_ZERO_FILL; 01309 huff_counts->bytes_packed=calc_packed_length(huff_counts,0); 01310 } 01311 01312 /* Test if intervall-field is better */ 01313 01314 if (huff_counts->tree_buff) 01315 { 01316 HUFF_TREE tree; 01317 01318 DBUG_EXECUTE_IF("forceintervall", 01319 huff_counts->bytes_packed= ~ (my_off_t) 0;); 01320 tree.element_buffer=0; 01321 if (!make_huff_tree(&tree,huff_counts) && 01322 tree.bytes_packed+tree.tree_pack_length < huff_counts->bytes_packed) 01323 { 01324 if (tree.elements == 1) 01325 huff_counts->field_type=FIELD_CONSTANT; 01326 else 01327 huff_counts->field_type=FIELD_INTERVALL; 01328 huff_counts->pack_type=0; 01329 } 01330 else 01331 { 01332 my_free((gptr) huff_counts->tree_buff,MYF(0)); 01333 delete_tree(&huff_counts->int_tree); 01334 huff_counts->tree_buff=0; 01335 } 01336 if (tree.element_buffer) 01337 my_free((gptr) tree.element_buffer,MYF(0)); 01338 } 01339 if (huff_counts->pack_type & PACK_TYPE_SPACE_FIELDS) 01340 space_fields++; 01341 if (huff_counts->pack_type & PACK_TYPE_ZERO_FILL) 01342 fill_zero_fields++; 01343 field_count[huff_counts->field_type]++; 01344 } 01345 DBUG_PRINT("info", ("normal: %3d empty-space: %3d " 01346 "empty-zero: %3d empty-fill: %3d", 01347 field_count[FIELD_NORMAL],space_fields, 01348 field_count[FIELD_SKIP_ZERO],fill_zero_fields)); 01349 DBUG_PRINT("info", ("pre-space: %3d end-space: %3d " 01350 "intervall-fields: %3d zero: %3d", 01351 field_count[FIELD_SKIP_PRESPACE], 01352 field_count[FIELD_SKIP_ENDSPACE], 01353 field_count[FIELD_INTERVALL], 01354 field_count[FIELD_ZERO])); 01355 if (verbose) 01356 VOID(printf("\nnormal: %3d empty-space: %3d " 01357 "empty-zero: %3d empty-fill: %3d\n" 01358 "pre-space: %3d end-space: %3d " 01359 "intervall-fields: %3d zero: %3d\n", 01360 field_count[FIELD_NORMAL],space_fields, 01361 field_count[FIELD_SKIP_ZERO],fill_zero_fields, 01362 field_count[FIELD_SKIP_PRESPACE], 01363 field_count[FIELD_SKIP_ENDSPACE], 01364 field_count[FIELD_INTERVALL], 01365 field_count[FIELD_ZERO])); 01366 DBUG_VOID_RETURN; 01367 }
Here is the call graph for this function:

Here is the caller graph for this function:

| static int compare_tree | ( | void *cmp_arg | __attribute__((unused)), | |
| register const uchar * | s, | |||
| register const uchar * | t | |||
| ) | [static] |
Definition at line 1666 of file myisampack.c.
References st_huff_counts::field_length, global_count, and int().
01668 { 01669 uint length; 01670 for (length=global_count->field_length; length-- ;) 01671 if (*s++ != *t++) 01672 return (int) s[-1] - (int) t[-1]; 01673 return 0; 01674 }
Here is the call graph for this function:

| static int compress | ( | PACK_MRG_INFO * | file, | |
| char * | join_name | |||
| ) | [static] |
Definition at line 487 of file myisampack.c.
References st_mi_isam_share::base, st_file_buffer::buffer, bzero, check_counts(), compare_huff_elements(), compress_isam_file(), st_isam_mrg::count, st_mi_status_info::data_file_length, DATA_TMP_EXT, DBUG_ENTER, DBUG_PRINT, DBUG_RETURN, st_myisam_info::dfile, st_mi_status_info::empty, end_file_buffer(), err, st_mi_base_info::fields, st_file_buffer::file, st_isam_mrg::file, file_buffer, st_myisam_info::filename, fn_format(), FN_REFLEN, free_counts_and_tree_and_queue(), get_statistic(), HEAD_LENGTH, init_file_buffer(), init_huff_count(), init_queue(), join_same_trees(), st_mi_base_info::keystart, st_mi_isam_share::kfile, make_huff_decode_table(), make_huff_trees(), make_new_name(), make_old_name(), st_isam_mrg::max_pack_length, MEMMAP_EXTRA_MARGIN, MI_NAME_DEXT, MI_NAME_IEXT, st_isam_mrg::min_pack_length, mrg_close(), my_close(), my_copy(), my_copystat(), MY_COPYTIME, my_create(), my_delete(), my_free, MY_HOLD_ORIGINAL_MODES, my_malloc(), MY_NABP, my_pread(), my_redel(), my_rename(), my_seek(), MY_SEEK_SET, MY_WAIT_IF_FULL, MY_WME, my_write, MYF, NORMAL_SAFEMALLOC, st_file_buffer::pos, st_file_buffer::pos_in_file, queue, QUICK_SAFEMALLOC, st_mi_status_info::records, st_isam_mrg::records, st_myisam_info::s, save_state(), save_state_mrg(), st_mi_state_info::state, st_mi_isam_share::state, strmov(), test_only, verbose, VOID, write_field_info(), write_header(), write_huff_tree(), and write_loop.
00488 { 00489 int error; 00490 File new_file,join_isam_file; 00491 MI_INFO *isam_file; 00492 MYISAM_SHARE *share; 00493 char org_name[FN_REFLEN],new_name[FN_REFLEN],temp_name[FN_REFLEN]; 00494 uint i,header_length,fields,trees,used_trees; 00495 my_off_t old_length,new_length,tot_elements; 00496 HUFF_COUNTS *huff_counts; 00497 HUFF_TREE *huff_trees; 00498 DBUG_ENTER("compress"); 00499 00500 isam_file=mrg->file[0]; /* Take this as an example */ 00501 share=isam_file->s; 00502 new_file=join_isam_file= -1; 00503 trees=fields=0; 00504 huff_trees=0; 00505 huff_counts=0; 00506 00507 /* Create temporary or join file */ 00508 00509 if (backup) 00510 VOID(fn_format(org_name,isam_file->filename,"",MI_NAME_DEXT,2)); 00511 else 00512 VOID(fn_format(org_name,isam_file->filename,"",MI_NAME_DEXT,2+4+16)); 00513 if (!test_only && result_table) 00514 { 00515 /* Make a new indexfile based on first file in list */ 00516 uint length; 00517 char *buff; 00518 strmov(org_name,result_table); /* Fix error messages */ 00519 VOID(fn_format(new_name,result_table,"",MI_NAME_IEXT,2)); 00520 if ((join_isam_file=my_create(new_name,0,tmpfile_createflag,MYF(MY_WME))) 00521 < 0) 00522 goto err; 00523 length=(uint) share->base.keystart; 00524 if (!(buff=my_malloc(length,MYF(MY_WME)))) 00525 goto err; 00526 if (my_pread(share->kfile,buff,length,0L,MYF(MY_WME | MY_NABP)) || 00527 my_write(join_isam_file,buff,length, 00528 MYF(MY_WME | MY_NABP | MY_WAIT_IF_FULL))) 00529 { 00530 my_free(buff,MYF(0)); 00531 goto err; 00532 } 00533 my_free(buff,MYF(0)); 00534 VOID(fn_format(new_name,result_table,"",MI_NAME_DEXT,2)); 00535 } 00536 else if (!tmp_dir[0]) 00537 VOID(make_new_name(new_name,org_name)); 00538 else 00539 VOID(fn_format(new_name,org_name,tmp_dir,DATA_TMP_EXT,1+2+4)); 00540 if (!test_only && 00541 (new_file=my_create(new_name,0,tmpfile_createflag,MYF(MY_WME))) < 0) 00542 goto err; 00543 00544 /* Start calculating statistics */ 00545 00546 mrg->records=0; 00547 for (i=0 ; i < mrg->count ; i++) 00548 mrg->records+=mrg->file[i]->s->state.state.records; 00549 00550 DBUG_PRINT("info", ("Compressing %s: (%lu records)", 00551 result_table ? new_name : org_name, 00552 (ulong) mrg->records)); 00553 if (write_loop || verbose) 00554 { 00555 VOID(printf("Compressing %s: (%lu records)\n", 00556 result_table ? new_name : org_name, (ulong) mrg->records)); 00557 } 00558 trees=fields=share->base.fields; 00559 huff_counts=init_huff_count(isam_file,mrg->records); 00560 QUICK_SAFEMALLOC; 00561 00562 /* 00563 Read the whole data file(s) for statistics. 00564 */ 00565 DBUG_PRINT("info", ("- Calculating statistics")); 00566 if (write_loop || verbose) 00567 VOID(printf("- Calculating statistics\n")); 00568 if (get_statistic(mrg,huff_counts)) 00569 goto err; 00570 NORMAL_SAFEMALLOC; 00571 old_length=0; 00572 for (i=0; i < mrg->count ; i++) 00573 old_length+= (mrg->file[i]->s->state.state.data_file_length - 00574 mrg->file[i]->s->state.state.empty); 00575 00576 /* 00577 Create a global priority queue in preparation for making 00578 temporary Huffman trees. 00579 */ 00580 if (init_queue(&queue,256,0,0,compare_huff_elements,0)) 00581 goto err; 00582 00583 /* 00584 Check each column if we should use pre-space-compress, end-space- 00585 compress, empty-field-compress or zero-field-compress. 00586 */ 00587 check_counts(huff_counts,fields,mrg->records); 00588 00589 /* 00590 Build a Huffman tree for each column. 00591 */ 00592 huff_trees=make_huff_trees(huff_counts,trees); 00593 00594 /* 00595 If the packed lengths of combined columns is less then the sum of 00596 the non-combined columns, then create common Huffman trees for them. 00597 We do this only for byte compressed columns, not for distinct values 00598 compressed columns. 00599 */ 00600 if ((int) (used_trees=join_same_trees(huff_counts,trees)) < 0) 00601 goto err; 00602 00603 /* 00604 Assign codes to all byte or column values. 00605 */ 00606 if (make_huff_decode_table(huff_trees,fields)) 00607 goto err; 00608 00609 /* Prepare a file buffer. */ 00610 init_file_buffer(new_file,0); 00611 00612 /* 00613 Reserve space in the target file for the fixed compressed file header. 00614 */ 00615 file_buffer.pos_in_file=HEAD_LENGTH; 00616 if (! test_only) 00617 VOID(my_seek(new_file,file_buffer.pos_in_file,MY_SEEK_SET,MYF(0))); 00618 00619 /* 00620 Write field infos: field type, pack type, length bits, tree number. 00621 */ 00622 write_field_info(huff_counts,fields,used_trees); 00623 00624 /* 00625 Write decode trees. 00626 */ 00627 if (!(tot_elements=write_huff_tree(huff_trees,trees))) 00628 goto err; 00629 00630 /* 00631 Calculate the total length of the compression info header. 00632 This includes the fixed compressed file header, the column compression 00633 type descriptions, and the decode trees. 00634 */ 00635 header_length=(uint) file_buffer.pos_in_file+ 00636 (uint) (file_buffer.pos-file_buffer.buffer); 00637 00638 /* 00639 Compress the source file into the target file. 00640 */ 00641 DBUG_PRINT("info", ("- Compressing file")); 00642 if (write_loop || verbose) 00643 VOID(printf("- Compressing file\n")); 00644 error=compress_isam_file(mrg,huff_counts); 00645 new_length=file_buffer.pos_in_file; 00646 if (!error && !test_only) 00647 { 00648 char buff[MEMMAP_EXTRA_MARGIN]; /* End marginal for memmap */ 00649 bzero(buff,sizeof(buff)); 00650 error=my_write(file_buffer.file,buff,sizeof(buff), 00651 MYF(MY_WME | MY_NABP | MY_WAIT_IF_FULL)) != 0; 00652 } 00653 00654 /* 00655 Write the fixed compressed file header. 00656 */ 00657 if (!error) 00658 error=write_header(mrg,header_length,used_trees,tot_elements, 00659 new_length); 00660 00661 /* Flush the file buffer. */ 00662 end_file_buffer(); 00663 00664 /* Display statistics. */ 00665 DBUG_PRINT("info", ("Min record length: %6d Max length: %6d " 00666 "Mean total length: %6ld\n", 00667 mrg->min_pack_length, mrg->max_pack_length, 00668 (ulong) (mrg->records ? (new_length/mrg->records) : 0))); 00669 if (verbose && mrg->records) 00670 VOID(printf("Min record length: %6d Max length: %6d " 00671 "Mean total length: %6ld\n", mrg->min_pack_length, 00672 mrg->max_pack_length, (ulong) (new_length/mrg->records))); 00673 00674 /* Close source and target file. */ 00675 if (!test_only) 00676 { 00677 error|=my_close(new_file,MYF(MY_WME)); 00678 if (!result_table) 00679 { 00680 error|=my_close(isam_file->dfile,MYF(MY_WME)); 00681 isam_file->dfile= -1; /* Tell mi_close file is closed */ 00682 } 00683 } 00684 00685 /* Cleanup. */ 00686 free_counts_and_tree_and_queue(huff_trees,trees,huff_counts,fields); 00687 if (! test_only && ! error) 00688 { 00689 if (result_table) 00690 { 00691 error=save_state_mrg(join_isam_file,mrg,new_length,glob_crc); 00692 } 00693 else 00694 { 00695 if (backup) 00696 { 00697 if (my_rename(org_name,make_old_name(temp_name,isam_file->filename), 00698 MYF(MY_WME))) 00699 error=1; 00700 else 00701 { 00702 if (tmp_dir[0]) 00703 error=my_copy(new_name,org_name,MYF(MY_WME)); 00704 else 00705 error=my_rename(new_name,org_name,MYF(MY_WME)); 00706 if (!error) 00707 { 00708 VOID(my_copystat(temp_name,org_name,MYF(MY_COPYTIME))); 00709 if (tmp_dir[0]) 00710 VOID(my_delete(new_name,MYF(MY_WME))); 00711 } 00712 } 00713 } 00714 else 00715 { 00716 if (tmp_dir[0]) 00717 { 00718 error=my_copy(new_name,org_name, 00719 MYF(MY_WME | MY_HOLD_ORIGINAL_MODES | MY_COPYTIME)); 00720 if (!error) 00721 VOID(my_delete(new_name,MYF(MY_WME))); 00722 } 00723 else 00724 error=my_redel(org_name,new_name,MYF(MY_WME | MY_COPYTIME)); 00725 } 00726 if (! error) 00727 error=save_state(isam_file,mrg,new_length,glob_crc); 00728 } 00729 } 00730 error|=mrg_close(mrg); 00731 if (join_isam_file >= 0) 00732 error|=my_close(join_isam_file,MYF(MY_WME)); 00733 if (error) 00734 { 00735 VOID(fprintf(stderr, "Aborting: %s is not compressed\n", org_name)); 00736 VOID(my_delete(new_name,MYF(MY_WME))); 00737 DBUG_RETURN(-1); 00738 } 00739 if (write_loop || verbose) 00740 { 00741 if (old_length) 00742 VOID(printf("%.4g%% \n", 00743 (((longlong) (old_length - new_length)) * 100.0 / 00744 (longlong) old_length))); 00745 else 00746 puts("Empty file saved in compressed format"); 00747 } 00748 DBUG_RETURN(0); 00749 00750 err: 00751 free_counts_and_tree_and_queue(huff_trees,trees,huff_counts,fields); 00752 if (new_file >= 0) 00753 VOID(my_close(new_file,MYF(0))); 00754 if (join_isam_file >= 0) 00755 VOID(my_close(join_isam_file,MYF(0))); 00756 mrg_close(mrg); 00757 VOID(fprintf(stderr, "Aborted: %s is not compressed\n", org_name)); 00758 DBUG_RETURN(-1); 00759 }
Here is the call graph for this function:

| static int compress_isam_file | ( | PACK_MRG_INFO * | file, | |
| HUFF_COUNTS * | huff_counts | |||
| ) | [static] |
Definition at line 2408 of file myisampack.c.
References st_mi_isam_share::base, bindigits(), st_mi_base_info::blobs, calc_pack_length(), st_huff_tree::code, st_huff_tree::code_len, count, DBUG_ENTER, DBUG_PRINT, FIELD_BLOB, FIELD_CHECK, FIELD_CONSTANT, FIELD_INTERVALL, st_huff_counts::field_length, FIELD_NORMAL, FIELD_SKIP_ENDSPACE, FIELD_SKIP_PRESPACE, FIELD_SKIP_ZERO, FIELD_VARCHAR, FIELD_ZERO, st_mi_base_info::fields, st_isam_mrg::file, file_buffer, flush_buffer(), HA_ERR_END_OF_FILE, st_huff_tree::height, hexdigits(), st_huff_counts::length_bits, st_isam_mrg::max_blob_length, st_huff_counts::max_length, st_huff_counts::max_zero_fill, memcmp(), mrg_reset(), mrg_rrnd(), my_alloca, st_mi_isam_share::pack, pack_type, PACK_TYPE_SELECTED, PACK_TYPE_SPACE_FIELDS, PACK_TYPE_ZERO_FILL, st_file_buffer::pos, st_mi_base_info::reclength, record_pos, st_myisam_info::s, st_huff_counts::tree, st_mi_isam_pack::version, and write_bits().
Referenced by compress().
02409 { 02410 int error; 02411 uint i,max_calc_length,pack_ref_length,min_record_length,max_record_length, 02412 intervall,field_length,max_pack_length,pack_blob_length; 02413 my_off_t record_count; 02414 char llbuf[32]; 02415 ulong length,pack_length; 02416 byte *record,*pos,*end_pos,*record_pos,*start_pos; 02417 HUFF_COUNTS *count,*end_count; 02418 HUFF_TREE *tree; 02419 MI_INFO *isam_file=mrg->file[0]; 02420 uint pack_version= (uint) isam_file->s->pack.version; 02421 DBUG_ENTER("compress_isam_file"); 02422 02423 /* Allocate a buffer for the records (excluding blobs). */ 02424 if (!(record=(byte*) my_alloca(isam_file->s->base.reclength))) 02425 return -1; 02426 02427 end_count=huff_counts+isam_file->s->base.fields; 02428 min_record_length= (uint) ~0; 02429 max_record_length=0; 02430 02431 /* 02432 Calculate the maximum number of bits required to pack the records. 02433 Remember to understand 'max_zero_fill' as 'min_zero_fill'. 02434 The tree height determines the maximum number of bits per value. 02435 Some fields skip leading or trailing spaces or zeroes. The skipped 02436 number of bytes is encoded by 'length_bits' bits. 02437 Empty blobs and varchar are encoded with a single 1 bit. Other blobs 02438 and varchar get a leading 0 bit. 02439 */ 02440 for (i=max_calc_length=0 ; i < isam_file->s->base.fields ; i++) 02441 { 02442 if (!(huff_counts[i].pack_type & PACK_TYPE_ZERO_FILL)) 02443 huff_counts[i].max_zero_fill=0; 02444 if (huff_counts[i].field_type == FIELD_CONSTANT || 02445 huff_counts[i].field_type == FIELD_ZERO || 02446 huff_counts[i].field_type == FIELD_CHECK) 02447 continue; 02448 if (huff_counts[i].field_type == FIELD_INTERVALL) 02449 max_calc_length+=huff_counts[i].tree->height; 02450 else if (huff_counts[i].field_type == FIELD_BLOB || 02451 huff_counts[i].field_type == FIELD_VARCHAR) 02452 max_calc_length+=huff_counts[i].tree->height*huff_counts[i].max_length + huff_counts[i].length_bits +1; 02453 else 02454 max_calc_length+= 02455 (huff_counts[i].field_length - huff_counts[i].max_zero_fill)* 02456 huff_counts[i].tree->height+huff_counts[i].length_bits; 02457 } 02458 max_calc_length= (max_calc_length + 7) / 8; 02459 pack_ref_length= calc_pack_length(pack_version, max_calc_length); 02460 record_count=0; 02461 /* 'max_blob_length' is the max length of all blobs of a record. */ 02462 pack_blob_length= isam_file->s->base.blobs ? 02463 calc_pack_length(pack_version, mrg->max_blob_length) : 0; 02464 max_pack_length=pack_ref_length+pack_blob_length; 02465 02466 DBUG_PRINT("fields", ("===")); 02467 mrg_reset(mrg); 02468 while ((error=mrg_rrnd(mrg,record)) != HA_ERR_END_OF_FILE) 02469 { 02470 ulong tot_blob_length=0; 02471 if (! error) 02472 { 02473 if (flush_buffer((ulong) max_calc_length + (ulong) max_pack_length)) 02474 break; 02475 record_pos= (byte*) file_buffer.pos; 02476 file_buffer.pos+=max_pack_length; 02477 for (start_pos=record, count= huff_counts; count < end_count ; count++) 02478 { 02479 end_pos=start_pos+(field_length=count->field_length); 02480 tree=count->tree; 02481 02482 DBUG_PRINT("fields", ("column: %3lu type: %2u pack: %2u zero: %4u " 02483 "lbits: %2u tree: %2u length: %4u", 02484 (ulong) (count - huff_counts + 1), 02485 count->field_type, 02486 count->pack_type, count->max_zero_fill, 02487 count->length_bits, count->tree->tree_number, 02488 count->field_length)); 02489 02490 /* Check if the column contains spaces only. */ 02491 if (count->pack_type & PACK_TYPE_SPACE_FIELDS) 02492 { 02493 for (pos=start_pos ; *pos == ' ' && pos < end_pos; pos++) ; 02494 if (pos == end_pos) 02495 { 02496 DBUG_PRINT("fields", 02497 ("PACK_TYPE_SPACE_FIELDS spaces only, bits: 1")); 02498 DBUG_PRINT("fields", ("---")); 02499 write_bits(1,1); 02500 start_pos=end_pos; 02501 continue; 02502 } 02503 DBUG_PRINT("fields", 02504 ("PACK_TYPE_SPACE_FIELDS not only spaces, bits: 1")); 02505 write_bits(0,1); 02506 } 02507 end_pos-=count->max_zero_fill; 02508 field_length-=count->max_zero_fill; 02509 02510 switch(count->field_type) { 02511 case FIELD_SKIP_ZERO: 02512 if (!memcmp((byte*) start_pos,zero_string,field_length)) 02513 { 02514 DBUG_PRINT("fields", ("FIELD_SKIP_ZERO zeroes only, bits: 1")); 02515 write_bits(1,1); 02516 start_pos=end_pos; 02517 break; 02518 } 02519 DBUG_PRINT("fields", ("FIELD_SKIP_ZERO not only zeroes, bits: 1")); 02520 write_bits(0,1); 02521 /* Fall through */ 02522 case FIELD_NORMAL: 02523 DBUG_PRINT("fields", ("FIELD_NORMAL %lu bytes", 02524 (ulong) (end_pos - start_pos))); 02525 for ( ; start_pos < end_pos ; start_pos++) 02526 { 02527 DBUG_PRINT("fields", 02528 ("value: 0x%02x code: 0x%s bits: %2u bin: %s", 02529 (uchar) *start_pos, 02530 hexdigits(tree->code[(uchar) *start_pos]), 02531 (uint) tree->code_len[(uchar) *start_pos], 02532 bindigits(tree->code[(uchar) *start_pos], 02533 (uint) tree->code_len[(uchar) *start_pos]))); 02534 write_bits(tree->code[(uchar) *start_pos], 02535 (uint) tree->code_len[(uchar) *start_pos]); 02536 } 02537 break; 02538 case FIELD_SKIP_ENDSPACE: 02539 for (pos=end_pos ; pos > start_pos && pos[-1] == ' ' ; pos--) ; 02540 length= (ulong) (end_pos - pos); 02541 if (count->pack_type & PACK_TYPE_SELECTED) 02542 { 02543 if (length > count->min_space) 02544 { 02545 DBUG_PRINT("fields", 02546 ("FIELD_SKIP_ENDSPACE more than min_space, bits: 1")); 02547 DBUG_PRINT("fields", 02548 ("FIELD_SKIP_ENDSPACE skip %lu/%u bytes, bits: %2u", 02549 length, field_length, count->length_bits)); 02550 write_bits(1,1); 02551 write_bits(length,count->length_bits); 02552 } 02553 else 02554 { 02555 DBUG_PRINT("fields", 02556 ("FIELD_SKIP_ENDSPACE not more than min_space, " 02557 "bits: 1")); 02558 write_bits(0,1); 02559 pos=end_pos; 02560 } 02561 } 02562 else 02563 { 02564 DBUG_PRINT("fields", 02565 ("FIELD_SKIP_ENDSPACE skip %lu/%u bytes, bits: %2u", 02566 length, field_length, count->length_bits)); 02567 write_bits(length,count->length_bits); 02568 } 02569 /* Encode all significant bytes. */ 02570 DBUG_PRINT("fields", ("FIELD_SKIP_ENDSPACE %lu bytes", 02571 (ulong) (pos - start_pos))); 02572 for ( ; start_pos < pos ; start_pos++) 02573 { 02574 DBUG_PRINT("fields", 02575 ("value: 0x%02x code: 0x%s bits: %2u bin: %s", 02576 (uchar) *start_pos, 02577 hexdigits(tree->code[(uchar) *start_pos]), 02578 (uint) tree->code_len[(uchar) *start_pos], 02579 bindigits(tree->code[(uchar) *start_pos], 02580 (uint) tree->code_len[(uchar) *start_pos]))); 02581 write_bits(tree->code[(uchar) *start_pos], 02582 (uint) tree->code_len[(uchar) *start_pos]); 02583 } 02584 start_pos=end_pos; 02585 break; 02586 case FIELD_SKIP_PRESPACE: 02587 for (pos=start_pos ; pos < end_pos && pos[0] == ' ' ; pos++) ; 02588 length= (ulong) (pos - start_pos); 02589 if (count->pack_type & PACK_TYPE_SELECTED) 02590 { 02591 if (length > count->min_space) 02592 { 02593 DBUG_PRINT("fields", 02594 ("FIELD_SKIP_PRESPACE more than min_space, bits: 1")); 02595 DBUG_PRINT("fields", 02596 ("FIELD_SKIP_PRESPACE skip %lu/%u bytes, bits: %2u", 02597 length, field_length, count->length_bits)); 02598 write_bits(1,1); 02599 write_bits(length,count->length_bits); 02600 } 02601 else 02602 { 02603 DBUG_PRINT("fields", 02604 ("FIELD_SKIP_PRESPACE not more than min_space, " 02605 "bits: 1")); 02606 pos=start_pos; 02607 write_bits(0,1); 02608 } 02609 } 02610 else 02611 { 02612 DBUG_PRINT("fields", 02613 ("FIELD_SKIP_PRESPACE skip %lu/%u bytes, bits: %2u", 02614 length, field_length, count->length_bits)); 02615 write_bits(length,count->length_bits); 02616 } 02617 /* Encode all significant bytes. */ 02618 DBUG_PRINT("fields", ("FIELD_SKIP_PRESPACE %lu bytes", 02619 (ulong) (end_pos - start_pos))); 02620 for (start_pos=pos ; start_pos < end_pos ; start_pos++) 02621 { 02622 DBUG_PRINT("fields", 02623 ("value: 0x%02x code: 0x%s bits: %2u bin: %s", 02624 (uchar) *start_pos, 02625 hexdigits(tree->code[(uchar) *start_pos]), 02626 (uint) tree->code_len[(uchar) *start_pos], 02627 bindigits(tree->code[(uchar) *start_pos], 02628 (uint) tree->code_len[(uchar) *start_pos]))); 02629 write_bits(tree->code[(uchar) *start_pos], 02630 (uint) tree->code_len[(uchar) *start_pos]); 02631 } 02632 break; 02633 case FIELD_CONSTANT: 02634 case FIELD_ZERO: 02635 case FIELD_CHECK: 02636 DBUG_PRINT("fields", ("FIELD_CONSTANT/ZERO/CHECK")); 02637 start_pos=end_pos; 02638 break; 02639 case FIELD_INTERVALL: 02640 global_count=count; 02641 pos=(byte*) tree_search(&count->int_tree, start_pos, 02642 count->int_tree.custom_arg); 02643 intervall=(uint) (pos - count->tree_buff)/field_length; 02644 DBUG_PRINT("fields", ("FIELD_INTERVALL")); 02645 DBUG_PRINT("fields", ("index: %4u code: 0x%s bits: %2u", 02646 intervall, hexdigits(tree->code[intervall]), 02647 (uint) tree->code_len[intervall])); 02648 write_bits(tree->code[intervall],(uint) tree->code_len[intervall]); 02649 start_pos=end_pos; 02650 break; 02651 case FIELD_BLOB: 02652 { 02653 ulong blob_length=_mi_calc_blob_length(field_length- 02654 mi_portable_sizeof_char_ptr, 02655 start_pos); 02656 /* Empty blobs are encoded with a single 1 bit. */ 02657 if (!blob_length) 02658 { 02659 DBUG_PRINT("fields", ("FIELD_BLOB empty, bits: 1")); 02660 write_bits(1,1); 02661 } 02662 else 02663 { 02664 byte *blob,*blob_end; 02665 DBUG_PRINT("fields", ("FIELD_BLOB not empty, bits: 1")); 02666 write_bits(0,1); 02667 /* Write the blob length. */ 02668 DBUG_PRINT("fields", ("FIELD_BLOB %lu bytes, bits: %2u", 02669 blob_length, count->length_bits)); 02670 write_bits(blob_length,count->length_bits); 02671 memcpy_fixed(&blob,end_pos-mi_portable_sizeof_char_ptr, 02672 sizeof(char*)); 02673 blob_end=blob+blob_length; 02674 /* Encode the blob bytes. */ 02675 for ( ; blob < blob_end ; blob++) 02676 { 02677 DBUG_PRINT("fields", 02678 ("value: 0x%02x code: 0x%s bits: %2u bin: %s", 02679 (uchar) *blob, hexdigits(tree->code[(uchar) *blob]), 02680 (uint) tree->code_len[(uchar) *blob], 02681 bindigits(tree->code[(uchar) *start_pos], 02682 (uint)tree->code_len[(uchar) *start_pos]))); 02683 write_bits(tree->code[(uchar) *blob], 02684 (uint) tree->code_len[(uchar) *blob]); 02685 } 02686 tot_blob_length+=blob_length; 02687 } 02688 start_pos= end_pos; 02689 break; 02690 } 02691 case FIELD_VARCHAR: 02692 { 02693 uint pack_length= HA_VARCHAR_PACKLENGTH(count->field_length-1); 02694 ulong col_length= (pack_length == 1 ? (uint) *(uchar*) start_pos : 02695 uint2korr(start_pos)); 02696 /* Empty varchar are encoded with a single 1 bit. */ 02697 if (!col_length) 02698 { 02699 DBUG_PRINT("fields", ("FIELD_VARCHAR empty, bits: 1")); 02700 write_bits(1,1); /* Empty varchar */ 02701 } 02702 else 02703 { 02704 byte *end=start_pos+pack_length+col_length; 02705 DBUG_PRINT("fields", ("FIELD_VARCHAR not empty, bits: 1")); 02706 write_bits(0,1); 02707 /* Write the varchar length. */ 02708 DBUG_PRINT("fields", ("FIELD_VARCHAR %lu bytes, bits: %2u", 02709 col_length, count->length_bits)); 02710 write_bits(col_length,count->length_bits); 02711 /* Encode the varchar bytes. */ 02712 for (start_pos+=pack_length ; start_pos < end ; start_pos++) 02713 { 02714 DBUG_PRINT("fields", 02715 ("value: 0x%02x code: 0x%s bits: %2u bin: %s", 02716 (uchar) *start_pos, 02717 hexdigits(tree->code[(uchar) *start_pos]), 02718 (uint) tree->code_len[(uchar) *start_pos], 02719 bindigits(tree->code[(uchar) *start_pos], 02720 (uint)tree->code_len[(uchar) *start_pos]))); 02721 write_bits(tree->code[(uchar) *start_pos], 02722 (uint) tree->code_len[(uchar) *start_pos]); 02723 } 02724 } 02725 start_pos= end_pos; 02726 break; 02727 } 02728 case FIELD_LAST: 02729 case FIELD_enum_val_count: 02730 abort(); /* Impossible */ 02731 } 02732 start_pos+=count->max_zero_fill; 02733 DBUG_PRINT("fields", ("---")); 02734 } 02735 flush_bits(); 02736 length=(ulong) ((byte*) file_buffer.pos - record_pos) - max_pack_length; 02737 pack_length= save_pack_length(pack_version, record_pos, length); 02738 if (pack_blob_length) 02739 pack_length+= save_pack_length(pack_version, record_pos + pack_length, 02740 tot_blob_length); 02741 DBUG_PRINT("fields", ("record: %lu length: %lu blob-length: %lu " 02742 "length-bytes: %lu", (ulong) record_count, length, 02743 tot_blob_length, pack_length)); 02744 DBUG_PRINT("fields", ("===")); 02745 02746 /* Correct file buffer if the header was smaller */ 02747 if (pack_length != max_pack_length) 02748 { 02749 bmove(record_pos+pack_length,record_pos+max_pack_length,length); 02750 file_buffer.pos-= (max_pack_length-pack_length); 02751 } 02752 if (length < (ulong) min_record_length) 02753 min_record_length=(uint) length; 02754 if (length > (ulong) max_record_length) 02755 max_record_length=(uint) length; 02756 record_count++; 02757 if (write_loop && record_count % WRITE_COUNT == 0) 02758 { 02759 VOID(printf("%lu\r", (ulong) record_count)); 02760 VOID(fflush(stdout)); 02761 } 02762 } 02763 else if (error != HA_ERR_RECORD_DELETED) 02764 break; 02765 } 02766 if (error == HA_ERR_END_OF_FILE) 02767 error=0; 02768 else 02769 { 02770 VOID(fprintf(stderr, "%s: Got error %d reading records\n", 02771 my_progname, error)); 02772 } 02773 if (verbose >= 2) 02774 VOID(printf("wrote %s records.\n", llstr((longlong) record_count, llbuf))); 02775 02776 my_afree((gptr) record); 02777 mrg->ref_length=max_pack_length; 02778 mrg->min_pack_length=max_record_length ? min_record_length : 0; 02779 mrg->max_pack_length=max_record_length; 02780 DBUG_RETURN(error || error_on_write || flush_buffer(~(ulong) 0)); 02781 }
Here is the call graph for this function:

Here is the caller graph for this function:

| static void end_file_buffer | ( | void | ) | [static] |
Definition at line 2868 of file myisampack.c.
References st_file_buffer::buffer, file_buffer, my_free, and MYF.
Referenced by compress().
02869 { 02870 my_free((gptr) file_buffer.buffer,MYF(0)); 02871 }
Here is the caller graph for this function:

| static void fakebigcodes | ( | HUFF_COUNTS * | huff_counts, | |
| HUFF_COUNTS * | end_count | |||
| ) | [static] |
Definition at line 3117 of file myisampack.c.
References count, DBUG_ENTER, DBUG_PRINT, delete_tree(), fakecmp(), st_huff_counts::int_tree, my_free, MYF, NULL, qsort(), qsort_cmp, and st_huff_counts::tree_buff.
03118 { 03119 HUFF_COUNTS *count; 03120 my_off_t *cur_count_p; 03121 my_off_t *end_count_p; 03122 my_off_t **cur_sort_p; 03123 my_off_t **end_sort_p; 03124 my_off_t *sort_counts[256]; 03125 my_off_t total; 03126 DBUG_ENTER("fakebigcodes"); 03127 03128 for (count= huff_counts; count < end_count; count++) 03129 { 03130 /* 03131 Remove distinct column values. 03132 */ 03133 if (huff_counts->tree_buff) 03134 { 03135 my_free((gptr) huff_counts->tree_buff, MYF(0)); 03136 delete_tree(&huff_counts->int_tree); 03137 huff_counts->tree_buff= NULL; 03138 DBUG_PRINT("fakebigcodes", ("freed distinct column values")); 03139 } 03140 03141 /* 03142 Sort counts by decreasing incidence. 03143 */ 03144 cur_count_p= count->counts; 03145 end_count_p= cur_count_p + 256; 03146 cur_sort_p= sort_counts; 03147 while (cur_count_p < end_count_p) 03148 *(cur_sort_p++)= cur_count_p++; 03149 (void) qsort(sort_counts, 256, sizeof(my_off_t*), (qsort_cmp) fakecmp); 03150 03151 /* 03152 Assign faked counts. 03153 */ 03154 cur_sort_p= sort_counts; 03155 #if SIZEOF_LONG_LONG > 4 03156 end_sort_p= sort_counts + 8 * sizeof(ulonglong) - 1; 03157 #else 03158 end_sort_p= sort_counts + 8 * sizeof(ulonglong) - 2; 03159 #endif 03160 /* Most frequent value gets a faked count of 1. */ 03161 **(cur_sort_p++)= 1; 03162 total= 1; 03163 while (cur_sort_p < end_sort_p) 03164 { 03165 **(cur_sort_p++)= total; 03166 total<<= 1; 03167 } 03168 /* Set the last value. */ 03169 **(cur_sort_p++)= --total; 03170 /* 03171 Set the remaining counts. 03172 */ 03173 end_sort_p= sort_counts + 256; 03174 while (cur_sort_p < end_sort_p) 03175 **(cur_sort_p++)= 1; 03176 } 03177 DBUG_VOID_RETURN; 03178 }
Here is the call graph for this function:

Definition at line 3195 of file myisampack.c.
Referenced by fakebigcodes().
Here is the caller graph for this function:

| static void flush_bits | ( | void | ) | [static] |
Definition at line 2913 of file myisampack.c.
References st_file_buffer::bitbucket, st_file_buffer::bits, BITS_SAVED, file_buffer, and st_file_buffer::pos.
Referenced by write_field_info(), and write_huff_tree().
02914 { 02915 int bits; 02916 ulonglong bit_buffer; 02917 02918 bits= file_buffer.bits & ~7; 02919 bit_buffer= file_buffer.bitbucket >> bits; 02920 bits= BITS_SAVED - bits; 02921 while (bits > 0) 02922 { 02923 bits-= 8; 02924 *file_buffer.pos++= (uchar) (bit_buffer >> bits); 02925 } 02926 file_buffer.bits= BITS_SAVED; 02927 file_buffer.bitbucket= 0; 02928 }
Here is the caller graph for this function:

| static int flush_buffer | ( | ulong | neaded_length | ) | [static] |
Definition at line 2819 of file myisampack.c.
References st_file_buffer::buffer, st_file_buffer::end, st_file_buffer::file, file_buffer, MY_NABP, my_realloc(), MY_WAIT_IF_FULL, MY_WME, my_write, MYF, st_file_buffer::pos, st_file_buffer::pos_in_file, and test_only.
Referenced by compress_isam_file(), and write_bits().
02820 { 02821 ulong length; 02822 02823 /* 02824 file_buffer.end is 8 bytes lower than the real end of the buffer. 02825 This is done so that the end-of-buffer condition does not need to be 02826 checked for every byte (see write_bits()). Consequently, 02827 file_buffer.pos can become greater than file_buffer.end. The 02828 algorithms in the other functions ensure that there will never be 02829 more than 8 bytes written to the buffer without an end-of-buffer 02830 check. So the buffer cannot be overrun. But we need to check for the 02831 near-to-buffer-end condition to avoid a negative result, which is 02832 casted to unsigned and thus becomes giant. 02833 */ 02834 if ((file_buffer.pos < file_buffer.end) && 02835 ((ulong) (file_buffer.end - file_buffer.pos) > neaded_length)) 02836 return 0; 02837 length=(ulong) (file_buffer.pos-file_buffer.buffer); 02838 file_buffer.pos=file_buffer.buffer; 02839 file_buffer.pos_in_file+=length; 02840 if (test_only) 02841 return 0; 02842 if (error_on_write|| my_write(file_buffer.file, 02843 (const byte*) file_buffer.buffer, 02844 length, 02845 MYF(MY_WME | MY_NABP | MY_WAIT_IF_FULL))) 02846 { 02847 error_on_write=1; 02848 return 1; 02849 } 02850 02851 if (neaded_length != ~(ulong) 0 && 02852 (ulong) (file_buffer.end-file_buffer.buffer) < neaded_length) 02853 { 02854 char *tmp; 02855 neaded_length+=256; /* some margin */ 02856 tmp= my_realloc((char*) file_buffer.buffer, neaded_length,MYF(MY_WME)); 02857 if (!tmp) 02858 return 1; 02859 file_buffer.pos= ((uchar*) tmp + 02860 (ulong) (file_buffer.pos - file_buffer.buffer)); 02861 file_buffer.buffer= (uchar*) tmp; 02862 file_buffer.end= (uchar*) (tmp+neaded_length-8); 02863 } 02864 return 0; 02865 }
Here is the call graph for this function:

Here is the caller graph for this function:

| static void free_counts_and_tree_and_queue | ( | HUFF_TREE * | huff_trees, | |
| uint | trees, | |||
| HUFF_COUNTS * | huff_counts, | |||
| uint | fields | |||
| ) | [static] |
Definition at line 804 of file myisampack.c.
References delete_queue(), delete_tree(), my_free, MYF, and queue.
Referenced by compress().
00807 { 00808 register uint i; 00809 00810 if (huff_trees) 00811 { 00812 for (i=0 ; i < trees ; i++) 00813 { 00814 if (huff_trees[i].element_buffer) 00815 my_free((gptr) huff_trees[i].element_buffer,MYF(0)); 00816 if (huff_trees[i].code) 00817 my_free((gptr) huff_trees[i].code,MYF(0)); 00818 } 00819 my_free((gptr) huff_trees,MYF(0)); 00820 } 00821 if (huff_counts) 00822 { 00823 for (i=0 ; i < fields ; i++) 00824 { 00825 if (huff_counts[i].tree_buff) 00826 { 00827 my_free((gptr) huff_counts[i].tree_buff,MYF(0)); 00828 delete_tree(&huff_counts[i].int_tree); 00829 } 00830 } 00831 my_free((gptr) huff_counts,MYF(0)); 00832 } 00833 delete_queue(&queue); /* This is safe to free */ 00834 return; 00835 }
Here is the call graph for this function:

Here is the caller graph for this function:

| static my_bool get_one_option | ( | int | optid, | |
| const struct my_option *opt | __attribute__((unused)), | |||
| char * | argument | |||
| ) | [static] |
Definition at line 322 of file myisampack.c.
References DBUG_PUSH, dirname_length(), exit, FN_LIBCHAR, force_pack, OPT_AUTO_CLOSE, print_version(), silent, strmov(), test_only, usage(), verbose, and write_loop.
00324 { 00325 uint length; 00326 00327 switch(optid) { 00328 #ifdef __NETWARE__ 00329 case OPT_AUTO_CLOSE: 00330 setscreenmode(SCR_AUTOCLOSE_ON_EXIT); 00331 break; 00332 #endif 00333 case 'f': 00334 force_pack= 1; 00335 tmpfile_createflag= O_RDWR | O_TRUNC; 00336 break; 00337 case 's': 00338 write_loop= verbose= 0; 00339 silent= 1; 00340 break; 00341 case 't': 00342 test_only= 1; 00343 /* Avoid to reset 'verbose' if it was already set > 1. */ 00344 if (! verbose) 00345 verbose= 1; 00346 break; 00347 case 'T': 00348 length= (uint) (strmov(tmp_dir, argument) - tmp_dir); 00349 if (length != dirname_length(tmp_dir)) 00350 { 00351 tmp_dir[length]=FN_LIBCHAR; 00352 tmp_dir[length+1]=0; 00353 } 00354 break; 00355 case 'v': 00356 verbose++; /* Allow for selecting the level of verbosity. */ 00357 silent= 0; 00358 break; 00359 case '#': 00360 DBUG_PUSH(argument ? argument : "d:t:o"); 00361 break; 00362 case 'V': 00363 print_version(); 00364 exit(0); 00365 case 'I': 00366 case '?': 00367 usage(); 00368 exit(0); 00369 } 00370 return 0; 00371 }
Here is the call graph for this function:

| static void get_options | ( | int * | argc, | |
| char *** | argv | |||
| ) | [static] |
Definition at line 376 of file myisampack.c.
References exit, get_one_option(), handle_options(), join_table, my_long_options, my_progname, usage(), and write_loop.
00377 { 00378 int ho_error; 00379 00380 my_progname= argv[0][0]; 00381 if (isatty(fileno(stdout))) 00382 write_loop=1; 00383 00384 if ((ho_error=handle_options(argc, argv, my_long_options, get_one_option))) 00385 exit(ho_error); 00386 00387 if (!*argc) 00388 { 00389 usage(); 00390 exit(1); 00391 } 00392 if (join_table) 00393 { 00394 backup=0; /* Not needed */ 00395 tmp_dir[0]=0; 00396 } 00397 return; 00398 }
Here is the call graph for this function:

| static int get_statistic | ( | PACK_MRG_INFO * | mrg, | |
| HUFF_COUNTS * | huff_counts | |||
| ) | [static] |
Definition at line 839 of file myisampack.c.
References st_mi_isam_share::base, count, DBUG_ENTER, FIELD_BLOB, FIELD_VARCHAR, st_mi_base_info::fields, st_isam_mrg::file, my_alloca, pos(), st_mi_base_info::reclength, reclength, and st_myisam_info::s.
Referenced by compress().
00840 { 00841 int error; 00842 uint length; 00843 ulong reclength,max_blob_length; 00844 byte *record,*pos,*next_pos,*end_pos,*start_pos; 00845 ha_rows record_count; 00846 my_bool static_row_size; 00847 HUFF_COUNTS *count,*end_count; 00848 TREE_ELEMENT *element; 00849 DBUG_ENTER("get_statistic"); 00850 00851 reclength=mrg->file[0]->s->base.reclength; 00852 record=(byte*) my_alloca(reclength); 00853 end_count=huff_counts+mrg->file[0]->s->base.fields; 00854 record_count=0; glob_crc=0; 00855 max_blob_length=0; 00856 00857 /* Check how to calculate checksum */ 00858 static_row_size=1; 00859 for (count=huff_counts ; count < end_count ; count++) 00860 { 00861 if (count->field_type == FIELD_BLOB || 00862 count->field_type == FIELD_VARCHAR) 00863 { 00864 static_row_size=0; 00865 break; 00866 } 00867 } 00868 00869 mrg_reset(mrg); 00870 while ((error=mrg_rrnd(mrg,record)) != HA_ERR_END_OF_FILE) 00871 { 00872 ulong tot_blob_length=0; 00873 if (! error) 00874 { 00875 /* glob_crc is a checksum over all bytes of all records. */ 00876 if (static_row_size) 00877 glob_crc+=mi_static_checksum(mrg->file[0],record); 00878 else 00879 glob_crc+=mi_checksum(mrg->file[0],record); 00880 00881 /* Count the incidence of values separately for every column. */ 00882 for (pos=record,count=huff_counts ; 00883 count < end_count ; 00884 count++, 00885 pos=next_pos) 00886 { 00887 next_pos=end_pos=(start_pos=pos)+count->field_length; 00888 00889 /* 00890 Put the whole column value in a tree if there is room for it. 00891 'int_tree' is used to quickly check for duplicate values. 00892 'tree_buff' collects as many distinct column values as 00893 possible. If the field length is > 1, it is tree_buff_length, 00894 else 2 bytes. Each value is 'field_length' bytes big. If there 00895 are more distinct column values than fit into the buffer, we 00896 give up with this tree. BLOBs and VARCHARs do not have a 00897 tree_buff as it can only be used with fixed length columns. 00898 For the special case of field length == 1, we handle only the 00899 case that there is only one distinct value in the table(s). 00900 Otherwise, we can have a maximum of 256 distinct values. This 00901 is then handled by the normal Huffman tree build. 00902 00903 Another limit for collecting distinct column values is the 00904 number of values itself. Since we would need to build a 00905 Huffman tree for the values, we are limited by the 'IS_OFFSET' 00906 constant. This constant expresses a bit which is used to 00907 determine if a tree element holds a final value or an offset 00908 to a child element. Hence, all values and offsets need to be 00909 smaller than 'IS_OFFSET'. A tree element is implemented with 00910 two integer values, one for the left branch and one for the 00911 right branch. For the extreme case that the first element 00912 points to the last element, the number of integers in the tree 00913 must be less or equal to IS_OFFSET. So the number of elements 00914 must be less or equal to IS_OFFSET / 2. 00915 00916 WARNING: At first, we insert a pointer into the record buffer 00917 as the key for the tree. If we got a new distinct value, which 00918 is really inserted into the tree, instead of being counted 00919 only, we will copy the column value from the record buffer to 00920 'tree_buff' and adjust the key pointer of the tree accordingly. 00921 */ 00922 if (count->tree_buff) 00923 { 00924 global_count=count; 00925 if (!(element=tree_insert(&count->int_tree,pos, 0, 00926 count->int_tree.custom_arg)) || 00927 (element->count == 1 && 00928 (count->tree_buff + tree_buff_length < 00929 count->tree_pos + count->field_length)) || 00930 (count->int_tree.elements_in_tree > IS_OFFSET / 2) || 00931 (count->field_length == 1 && 00932 count->int_tree.elements_in_tree > 1)) 00933 { 00934 delete_tree(&count->int_tree); 00935 my_free(count->tree_buff,MYF(0)); 00936 count->tree_buff=0; 00937 } 00938 else 00939 { 00940 /* 00941 If tree_insert() succeeds, it either creates a new element 00942 or increments the counter of an existing element. 00943 */ 00944 if (element->count == 1) 00945 { 00946 /* Copy the new column value into 'tree_buff'. */ 00947 memcpy(count->tree_pos,pos,(size_t) count->field_length); 00948 /* Adjust the key pointer in the tree. */ 00949 tree_set_pointer(element,count->tree_pos); 00950 /* Point behind the last column value so far. */ 00951 count->tree_pos+=count->field_length; 00952 } 00953 } 00954 } 00955 00956 /* Save character counters and space-counts and zero-field-counts */ 00957 if (count->field_type == FIELD_NORMAL || 00958 count->field_type == FIELD_SKIP_ENDSPACE) 00959 { 00960 /* Ignore trailing space. */ 00961 for ( ; end_pos > pos ; end_pos--) 00962 if (end_pos[-1] != ' ') 00963 break; 00964 /* Empty fields are just counted. Go to the next record. */ 00965 if (end_pos == pos) 00966 { 00967 count->empty_fields++; 00968 count->max_zero_fill=0; 00969 continue; 00970 } 00971 /* 00972 Count the total of all trailing spaces and the number of 00973 short trailing spaces. Remember the longest trailing space. 00974 */ 00975 length= (uint) (next_pos-end_pos); 00976 count->tot_end_space+=length; 00977 if (length < 8) 00978 count->end_space[length]++; 00979 if (count->max_end_space < length) 00980 count->max_end_space = length; 00981 } 00982 00983 if (count->field_type == FIELD_NORMAL || 00984 count->field_type == FIELD_SKIP_PRESPACE) 00985 { 00986 /* Ignore leading space. */ 00987 for (pos=start_pos; pos < end_pos ; pos++) 00988 if (pos[0] != ' ') 00989 break; 00990 /* Empty fields are just counted. Go to the next record. */ 00991 if (end_pos == pos) 00992 { 00993 count->empty_fields++; 00994 count->max_zero_fill=0; 00995 continue; 00996 } 00997 /* 00998 Count the total of all leading spaces and the number of 00999 short leading spaces. Remember the longest leading space. 01000 */ 01001 length= (uint) (pos-start_pos); 01002 count->tot_pre_space+=length; 01003 if (length < 8) 01004 count->pre_space[length]++; 01005 if (count->max_pre_space < length) 01006 count->max_pre_space = length; 01007 } 01008 01009 /* Calculate pos, end_pos, and max_length for variable length fields. */ 01010 if (count->field_type == FIELD_BLOB) 01011 { 01012 uint field_length=count->field_length -mi_portable_sizeof_char_ptr; 01013 ulong blob_length= _mi_calc_blob_length(field_length, start_pos); 01014 memcpy_fixed((char*) &pos, start_pos+field_length,sizeof(char*)); 01015 end_pos=pos+blob_length; 01016 tot_blob_length+=blob_length; 01017 set_if_bigger(count->max_length,blob_length); 01018 } 01019 else if (count->field_type == FIELD_VARCHAR) 01020 { 01021 uint pack_length= HA_VARCHAR_PACKLENGTH(count->field_length-1); 01022 length= (pack_length == 1 ? (uint) *(uchar*) start_pos : 01023 uint2korr(start_pos)); 01024 pos= start_pos+pack_length; 01025 end_pos= pos+length; 01026 set_if_bigger(count->max_length,length); 01027 } 01028 01029 /* Evaluate 'max_zero_fill' for short fields. */ 01030 if (count->field_length <= 8 && 01031 (count->field_type == FIELD_NORMAL || 01032 count->field_type == FIELD_SKIP_ZERO)) 01033 { 01034 uint i; 01035 /* Zero fields are just counted. Go to the next record. */ 01036 if (!memcmp((byte*) start_pos,zero_string,count->field_length)) 01037 { 01038 count->zero_fields++; 01039 continue; 01040 } 01041 /* 01042 max_zero_fill starts with field_length. It is decreased every 01043 time a shorter "zero trailer" is found. It is set to zero when 01044 an empty field is found (see above). This suggests that the 01045 variable should be called 'min_zero_fill'. 01046 */ 01047 for (i =0 ; i < count->max_zero_fill && ! end_pos[-1 - (int) i] ; 01048 i++) ; 01049 if (i < count->max_zero_fill) 01050 count->max_zero_fill=i; 01051 } 01052 01053 /* Ignore zero fields and check fields. */ 01054 if (count->field_type == FIELD_ZERO || 01055 count->field_type == FIELD_CHECK) 01056 continue; 01057 01058 /* 01059 Count the incidence of every byte value in the 01060 significant field value. 01061 */ 01062 for ( ; pos < end_pos ; pos++) 01063 count->counts[(uchar) *pos]++; 01064 01065 /* Step to next field. */ 01066 } 01067 01068 if (tot_blob_length > max_blob_length) 01069 max_blob_length=tot_blob_length; 01070 record_count++; 01071 if (write_loop && record_count % WRITE_COUNT == 0) 01072 { 01073 VOID(printf("%lu\r", (ulong) record_count)); 01074 VOID(fflush(stdout)); 01075 } 01076 } 01077 else if (error != HA_ERR_RECORD_DELETED) 01078 { 01079 VOID(fprintf(stderr, "Got error %d while reading rows", error)); 01080 break; 01081 } 01082 01083 /* Step to next record. */ 01084 } 01085 if (write_loop) 01086 { 01087 VOID(printf(" \r")); 01088 VOID(fflush(stdout)); 01089 } 01090 01091 /* 01092 If --debug=d,fakebigcodes is set, fake the counts to get big Huffman 01093 codes. 01094 */ 01095 DBUG_EXECUTE_IF("fakebigcodes", fakebigcodes(huff_counts, end_count);); 01096 01097 DBUG_PRINT("info", ("Found the following number of incidents " 01098 "of the byte codes:")); 01099 if (verbose >= 2) 01100 VOID(printf("Found the following number of incidents " 01101 "of the byte codes:\n")); 01102 for (count= huff_counts ; count < end_count; count++) 01103 { 01104 uint idx; 01105 my_off_t total_count; 01106 char llbuf[32]; 01107 01108 DBUG_PRINT("info", ("column: %3u", count - huff_counts + 1)); 01109 if (verbose >= 2) 01110 VOID(printf("column: %3u\n", count - huff_counts + 1)); 01111 if (count->tree_buff) 01112 { 01113 DBUG_PRINT("info", ("number of distinct values: %u", 01114 (count->tree_pos - count->tree_buff) / 01115 count->field_length)); 01116 if (verbose >= 2) 01117 VOID(printf("number of distinct values: %u\n", 01118 (count->tree_pos - count->tree_buff) / 01119 count->field_length)); 01120 } 01121 total_count= 0; 01122 for (idx= 0; idx < 256; idx++) 01123 { 01124 if (count->counts[idx]) 01125 { 01126 total_count+= count->counts[idx]; 01127 DBUG_PRINT("info", ("counts[0x%02x]: %12s", idx, 01128 llstr((longlong) count->counts[idx], llbuf))); 01129 if (verbose >= 2) 01130 VOID(printf("counts[0x%02x]: %12s\n", idx, 01131 llstr((longlong) count->counts[idx], llbuf))); 01132 } 01133 } 01134 DBUG_PRINT("info", ("total: %12s", llstr((longlong) total_count, 01135 llbuf))); 01136 if ((verbose >= 2) && total_count) 01137 { 01138 VOID(printf("total: %12s\n", 01139 llstr((longlong) total_count, llbuf))); 01140 } 01141 } 01142 01143 mrg->records=record_count; 01144 mrg->max_blob_length=max_blob_length; 01145 my_afree((gptr) record); 01146 DBUG_RETURN(error != HA_ERR_END_OF_FILE); 01147 }
Here is the call graph for this function:

Here is the caller graph for this function:

| static char* hexdigits | ( | ulonglong | value | ) | [static] |
Definition at line 1989 of file myisampack.c.
References DBUG_ASSERT.
Referenced by compress_isam_file(), and write_huff_tree().
01990 { 01991 static char digits[20]; 01992 char *ptr= digits; 01993 uint idx= 2 * sizeof(value); /* Two hex digits per byte. */ 01994 01995 DBUG_ASSERT(idx < sizeof(digits)); 01996 while (idx) 01997 { 01998 if ((*(ptr++)= '0' + ((value >> (4 * (--idx))) & 0xf)) > '9') 01999 *(ptr - 1)+= 'a' - '9' - 1; 02000 } 02001 *ptr= '\0'; 02002 return digits; 02003 }
Here is the caller graph for this function:

Definition at line 2796 of file myisampack.c.
References ALIGN_SIZE, st_file_buffer::bitbucket, st_file_buffer::bits, BITS_SAVED, st_file_buffer::buffer, st_file_buffer::end, st_file_buffer::file, file_buffer, my_malloc(), MY_WME, MYF, st_file_buffer::pos, st_file_buffer::pos_in_file, and RECORD_CACHE_SIZE.
Referenced by compress().
02797 { 02798 file_buffer.file=file; 02799 file_buffer.buffer= (uchar*) my_malloc(ALIGN_SIZE(RECORD_CACHE_SIZE), 02800 MYF(MY_WME)); 02801 file_buffer.end=file_buffer.buffer+ALIGN_SIZE(RECORD_CACHE_SIZE)-8; 02802 file_buffer.pos_in_file=0; 02803 error_on_write=0; 02804 if (read_buffer) 02805 { 02806 02807 file_buffer.pos=file_buffer.end; 02808 file_buffer.bits=0; 02809 } 02810 else 02811 { 02812 file_buffer.pos=file_buffer.buffer; 02813 file_buffer.bits=BITS_SAVED; 02814 } 02815 file_buffer.bitbucket= 0; 02816 }
Here is the call graph for this function:

Here is the caller graph for this function:

| static HUFF_COUNTS * init_huff_count | ( | MI_INFO * | info, | |
| my_off_t | records | |||
| ) | [static] |
Definition at line 763 of file myisampack.c.
References st_mi_isam_share::base, compare_tree(), count, FIELD_BLOB, FIELD_CONSTANT, FIELD_INTERVALL, FIELD_NORMAL, FIELD_SKIP_ZERO, FIELD_VARCHAR, FIELD_ZERO, st_mi_base_info::fields, init_tree(), st_columndef::length, my_malloc(), MY_WME, MY_ZEROFILL, MYF, NULL, st_mi_isam_share::rec, reg1, reg2, st_myisam_info::s, and st_columndef::type.
Referenced by compress().
00764 { 00765 reg2 uint i; 00766 reg1 HUFF_COUNTS *count; 00767 if ((count = (HUFF_COUNTS*) my_malloc(info->s->base.fields* 00768 sizeof(HUFF_COUNTS), 00769 MYF(MY_ZEROFILL | MY_WME)))) 00770 { 00771 for (i=0 ; i < info->s->base.fields ; i++) 00772 { 00773 enum en_fieldtype type; 00774 count[i].field_length=info->s->rec[i].length; 00775 type= count[i].field_type= (enum en_fieldtype) info->s->rec[i].type; 00776 if (type == FIELD_INTERVALL || 00777 type == FIELD_CONSTANT || 00778 type == FIELD_ZERO) 00779 type = FIELD_NORMAL; 00780 if (count[i].field_length <= 8 && 00781 (type == FIELD_NORMAL || 00782 type == FIELD_SKIP_ZERO)) 00783 count[i].max_zero_fill= count[i].field_length; 00784 /* 00785 For every column initialize a tree, which is used to detect distinct 00786 column values. 'int_tree' works together with 'tree_buff' and 00787 'tree_pos'. It's keys are implemented by pointers into 'tree_buff'. 00788 This is accomplished by '-1' as the element size. 00789 */ 00790 init_tree(&count[i].int_tree,0,0,-1,(qsort_cmp2) compare_tree,0, NULL, 00791 NULL); 00792 if (records && type != FIELD_BLOB && type != FIELD_VARCHAR) 00793 count[i].tree_pos=count[i].tree_buff = 00794 my_malloc(count[i].field_length > 1 ? tree_buff_length : 2, 00795 MYF(MY_WME)); 00796 } 00797 } 00798 return count; 00799 }
Here is the call graph for this function:

Here is the caller graph for this function:

| static uint join_same_trees | ( | HUFF_COUNTS * | huff_counts, | |
| uint | trees | |||
| ) | [static] |
Definition at line 1839 of file myisampack.c.
References ALLOWED_JOIN_DIFF, bmove(), st_huff_tree::bytes_packed, calc_packed_length(), count, st_huff_counts::counts, st_huff_tree::element_buffer, make_huff_tree(), memcpy_fixed, my_free, MYF, st_huff_counts::tree, st_huff_counts::tree_buff, st_huff_tree::tree_number, and st_huff_tree::tree_pack_length.
Referenced by compress().
01840 { 01841 uint k,tree_number; 01842 HUFF_COUNTS count,*i,*j,*last_count; 01843 01844 last_count=huff_counts+trees; 01845 for (tree_number=0, i=huff_counts ; i < last_count ; i++) 01846 { 01847 if (!i->tree->tree_number) 01848 { 01849 i->tree->tree_number= ++tree_number; 01850 if (i->tree_buff) 01851 continue; /* Don't join intervall */ 01852 for (j=i+1 ; j < last_count ; j++) 01853 { 01854 if (! j->tree->tree_number && ! j->tree_buff) 01855 { 01856 for (k=0 ; k < 256 ; k++) 01857 count.counts[k]=i->counts[k]+j->counts[k]; 01858 if (calc_packed_length(&count,1) <= 01859 i->tree->bytes_packed + j->tree->bytes_packed+ 01860 i->tree->tree_pack_length+j->tree->tree_pack_length+ 01861 ALLOWED_JOIN_DIFF) 01862 { 01863 memcpy_fixed((byte*) i->counts,(byte*) count.counts, 01864 sizeof(count.counts[0])*256); 01865 my_free((gptr) j->tree->element_buffer,MYF(0)); 01866 j->tree->element_buffer=0; 01867 j->tree=i->tree; 01868 bmove((byte*) i->counts,(byte*) count.counts, 01869 sizeof(count.counts[0])*256); 01870 if (make_huff_tree(i->tree,i)) 01871 return (uint) -1; 01872 } 01873 } 01874 } 01875 } 01876 } 01877 DBUG_PRINT("info", ("Original trees: %d After join: %d", 01878 trees, tree_number)); 01879 if (verbose) 01880 VOID(printf("Original trees: %d After join: %d\n", trees, tree_number)); 01881 return tree_number; /* Return trees left */ 01882 }
Here is the call graph for this function:

Here is the caller graph for this function:

| int main | ( | int | argc, | |
| char ** | argv | |||
| ) |
Definition at line 200 of file mysql_upgrade.c.
References basedir, create_check_file(), create_defaults_file(), DATADIR, datadir, DBUG_ENTER, DBUG_PROCESS, DBUG_PUSH, DBUG_RETURN, DEFAULT_MYSQL_HOME, defaults_group_suffix, error, exit, FN_REFLEN, get_defaults_options(), get_one_option(), get_tty_password(), handle_options(), info_flag, load_default_groups, load_defaults(), MY_CHECK_ERROR, my_close(), my_delete(), my_end(), my_getwd(), MY_GIVE_INFO, MY_INIT, my_long_options, my_open(), my_read, MYF, mysql_name, MYSQL_SERVER_VERSION, mysqlcheck_name, NullS, opt_force, opt_mysql_port, opt_mysql_unix_port, opt_password, opt_verbose, perror(), strcmp(), strlen(), strmake(), strxnmov(), test_file_exists(), test_file_exists_res(), tty_password, unpack_filename(), upgrade_defaults_created, and user.
00201 { 00202 char bindir[FN_REFLEN]; 00203 char *bindir_end, *buf_end; 00204 char datadir_buf[FN_REFLEN]; 00205 char mysqlcheck_line[FN_REFLEN], *mysqlcheck_end; 00206 char check_file_name[FN_REFLEN]; 00207 int check_file; 00208 char fix_priv_tables_cmd[FN_REFLEN], *fix_cmd_end; 00209 char script_line[FN_REFLEN]; 00210 int error; 00211 char *forced_defaults_file; 00212 char *forced_extra_defaults; 00213 char *defaults_group_suffix; 00214 char upgrade_defaults_path[FN_REFLEN], *defaults_to_use= 0; 00215 char port_socket[100], *port_socket_end; 00216 00217 MY_INIT(argv[0]); 00218 #ifdef __NETWARE__ 00219 setscreenmode(SCR_AUTOCLOSE_ON_EXIT); 00220 #endif 00221 00222 load_defaults("my", load_default_groups, &argc, &argv); 00223 00224 if ((error= handle_options(&argc, &argv, my_long_options, get_one_option))) 00225 exit(error); 00226 00227 if (tty_password) 00228 opt_password= get_tty_password(NullS); 00229 00230 /* Check if we want to force the use a specific default file */ 00231 get_defaults_options(argc, argv, 00232 &forced_defaults_file, &forced_extra_defaults, 00233 &defaults_group_suffix); 00234 00235 port_socket_end= port_socket; 00236 if (opt_mysql_port) 00237 port_socket_end= strxnmov(port_socket, sizeof(port_socket) - 1, " --port=", 00238 opt_mysql_port, NullS); 00239 if (opt_mysql_unix_port) 00240 port_socket_end= strxnmov(port_socket_end, 00241 sizeof(port_socket) - 00242 (int)(port_socket_end - port_socket) - 1, 00243 " --socket=", opt_mysql_unix_port, NullS); 00244 *port_socket_end= 0; 00245 00246 if (basedir) 00247 { 00248 bindir_end= strmake(bindir, basedir, sizeof(bindir)-1); 00249 } 00250 else 00251 { 00252 if (test_file_exists("./share/mysql/english", "errmsg.sys") 00253 && (test_file_exists("./bin", "mysqld") || 00254 test_file_exists("./libexec", "mysqld"))) 00255 { 00256 my_getwd(bindir, sizeof(bindir), MYF(0)); 00257 bindir_end= bindir + strlen(bindir); 00258 } 00259 else 00260 { 00261 bindir_end= strmake(bindir, DEFAULT_MYSQL_HOME, sizeof(bindir)-1); 00262 } 00263 } 00264 00265 if (!datadir) 00266 { 00267 datadir= datadir_buf; 00268 if (test_file_exists(bindir, "data/mysql")) 00269 { 00270 *strxnmov(datadir_buf, sizeof(datadir_buf)-1, bindir, "/data", NullS)= 0; 00271 } 00272 else if (test_file_exists(bindir, "var/mysql")) 00273 { 00274 *strxnmov(datadir_buf, sizeof(datadir_buf)-1, bindir, "/var", NullS)= 0; 00275 } 00276 else 00277 datadir= (char*) DATADIR; 00278 } 00279 00280 strmake(bindir_end, "/bin", sizeof(bindir) - (int) (bindir_end - bindir)-1); 00281 00282 if (!test_file_exists_res 00283 (bindir, mysqlcheck_name, mysqlcheck_line, &mysqlcheck_end)) 00284 { 00285 printf("Can't find program '%s'\n", mysqlcheck_line); 00286 puts("Please restart with --basedir=mysql-install-directory"); 00287 exit(1); 00288 } 00289 00290 if (!test_file_exists(datadir, "mysql/user.frm")) 00291 { 00292 puts 00293 ("Can't find data directory. Please restart with --datadir=path-to-data-dir"); 00294 exit(1); 00295 } 00296 00297 /* create the modified defaults file to be used by mysqlcheck */ 00298 /* and mysql tools */ 00299 *strxnmov(upgrade_defaults_path, sizeof(upgrade_defaults_path)-1, 00300 datadir, "/upgrade_defaults", NullS)= 0; 00301 unpack_filename(upgrade_defaults_path, upgrade_defaults_path); 00302 if ((error= 00303 create_defaults_file(upgrade_defaults_path, forced_extra_defaults))) 00304 goto err_exit; 00305 00306 defaults_to_use= upgrade_defaults_created ? 00307 upgrade_defaults_path : forced_extra_defaults; 00308 00309 if (test_file_exists_res(datadir, "mysql_upgrade_info", check_file_name, 00310 &buf_end) && !opt_force) 00311 { 00312 char chf_buffer[50]; 00313 int b_read; 00314 check_file= my_open(check_file_name, O_RDONLY, MYF(0)); 00315 b_read= my_read(check_file, chf_buffer, sizeof(chf_buffer)-1, MYF(0)); 00316 chf_buffer[b_read]= 0; 00317 my_close(check_file, MYF(0)); 00318 if (!strcmp(chf_buffer, MYSQL_SERVER_VERSION)) 00319 { 00320 if (opt_verbose) 00321 puts("mysql_upgrade already done for this version"); 00322 goto fix_priv_tables; 00323 } 00324 } 00325 00326 if (defaults_to_use) 00327 { 00328 mysqlcheck_end= strxnmov(mysqlcheck_end, 00329 sizeof(mysqlcheck_line) - (int) (mysqlcheck_end - 00330 mysqlcheck_line), 00331 " --defaults-extra-file=", defaults_to_use,NullS); 00332 } 00333 00334 mysqlcheck_end= strxnmov(mysqlcheck_end, 00335 sizeof(mysqlcheck_line) - 00336 (int) (mysqlcheck_end - mysqlcheck_line - 1), 00337 " --check-upgrade --all-databases --auto-repair --user=", 00338 user, port_socket, NullS); 00339 *mysqlcheck_end= 0; 00340 00341 if (opt_verbose) 00342 printf("Running %s\n", mysqlcheck_line); 00343 if ((error= system(mysqlcheck_line))) 00344 { 00345 printf("Error executing '%s'\n", mysqlcheck_line); 00346 goto err_exit; 00347 } 00348 00349 if ((error= create_check_file(check_file_name))) 00350 goto err_exit; 00351 00352 fix_priv_tables: 00353 if (!test_file_exists_res(bindir, mysql_name, 00354 fix_priv_tables_cmd, &fix_cmd_end)) 00355 { 00356 puts("Could not find MySQL command-line client (mysql)."); 00357 puts 00358 ("Please use --basedir to specify the directory where MySQL is installed."); 00359 error= 1; 00360 goto err_exit; 00361 } 00362 00363 if (!test_file_exists_res(basedir, 00364 "support_files/mysql_fix_privilege_tables.sql", 00365 script_line, &buf_end) 00366 && !test_file_exists_res(basedir, "share/mysql_fix_privilege_tables.sql", 00367 script_line, &buf_end) 00368 && !test_file_exists_res(basedir, 00369 "share/mysql/mysql_fix_privilege_tables.sql", 00370 script_line, &buf_end) 00371 && !test_file_exists_res(basedir, 00372 "scripts/mysql_fix_privilege_tables.sql", 00373 script_line, &buf_end) 00374 && !test_file_exists_res("/usr/local/mysql/share/mysql", 00375 "mysql_fix_privilege_tables.sql", script_line, 00376 &buf_end)) 00377 { 00378 puts("Could not find file mysql_fix_privilege_tables.sql"); 00379 puts 00380 ("Please use --basedir to specify the directory where MySQL is installed"); 00381 error= 1; 00382 goto err_exit; 00383 } 00384 00385 if (defaults_to_use) 00386 { 00387 fix_cmd_end= strxnmov(fix_cmd_end, 00388 sizeof(fix_priv_tables_cmd) - 00389 (int) (fix_cmd_end - fix_priv_tables_cmd - 1), 00390 " --defaults-extra-file=", defaults_to_use, NullS); 00391 } 00392 fix_cmd_end= strxnmov(fix_cmd_end, 00393 sizeof(fix_priv_tables_cmd) - (int) (fix_cmd_end - 00394 fix_priv_tables_cmd), 00395 " --user=", user, port_socket, " mysql < ", script_line, NullS); 00396 *fix_cmd_end= 0; 00397 00398 if ((error= system(fix_priv_tables_cmd))) 00399 { 00400 /* Problem is that the 'Duplicate column' error */ 00401 /* which is not a bug for the script makes 'mysql' return */ 00402 /* an error */ 00403 /* printf("Error executing '%s'\n", fix_priv_tables_cmd); */ 00404 } 00405 00406 err_exit: 00407 if (upgrade_defaults_created) 00408 my_delete(upgrade_defaults_path, MYF(0)); 00409 my_end(info_flag ? MY_CHECK_ERROR | MY_GIVE_INFO : 0); 00410 return error; 00411 } /* main */
Here is the call graph for this function:

Definition at line 1898 of file myisampack.c.
References st_huff_tree::code, st_huff_tree::code_len, st_huff_tree::counts, st_huff_tree::elements, LL, make_traverse_code_tree(), my_malloc(), MY_WME, MY_ZEROFILL, MYF, st_huff_tree::root, st_huff_counts::tree_buff, and st_huff_tree::tree_number.
Referenced by compress().
01899 { 01900 uint elements; 01901 for ( ; trees-- ; huff_tree++) 01902 { 01903 if (huff_tree->tree_number > 0) 01904 { 01905 elements=huff_tree->counts->tree_buff ? huff_tree->elements : 256; 01906 if (!(huff_tree->code = 01907 (ulonglong*) my_malloc(elements* 01908 (sizeof(ulonglong) + sizeof(uchar)), 01909 MYF(MY_WME | MY_ZEROFILL)))) 01910 return 1; 01911 huff_tree->code_len=(uchar*) (huff_tree->code+elements); 01912 make_traverse_code_tree(huff_tree, huff_tree->root, 01913 8 * sizeof(ulonglong), LL(0)); 01914 } 01915 } 01916 return 0; 01917 }
Here is the call graph for this function:

Here is the caller graph for this function:

| static int make_huff_tree | ( | HUFF_TREE * | tree, | |
| HUFF_COUNTS * | huff_counts | |||
| ) | [static] |
Definition at line 1481 of file myisampack.c.
References st_huff_counts::counts, st_huff_counts::field_length, st_huff_counts::tree_buff, and st_huff_counts::tree_pos.
Referenced by join_same_trees(), and make_huff_trees().
01482 { 01483 uint i,found,bits_packed,first,last; 01484 my_off_t bytes_packed; 01485 HUFF_ELEMENT *a,*b,*new_huff_el; 01486 01487 first=last=0; 01488 if (huff_counts->tree_buff) 01489 { 01490 /* Calculate the number of distinct values in tree_buff. */ 01491 found= (uint) (huff_counts->tree_pos - huff_counts->tree_buff) / 01492 huff_counts->field_length; 01493 first=0; last=found-1; 01494 } 01495 else 01496 { 01497 /* Count the number of byte codes found in the column. */ 01498 for (i=found=0 ; i < 256 ; i++) 01499 { 01500 if (huff_counts->counts[i]) 01501 { 01502 if (! found++) 01503 first=i; 01504 last=i; 01505 } 01506 } 01507 if (found < 2) 01508 found=2; 01509 } 01510 01511 /* When using 'tree_buff' we can have more that 256 values. */ 01512 if (queue.max_elements < found) 01513 { 01514 delete_queue(&queue); 01515 if (init_queue(&queue,found,0,0,compare_huff_elements,0)) 01516 return -1; 01517 } 01518 01519 /* Allocate or reallocate an element buffer for the Huffman tree. */ 01520 if (!huff_tree->element_buffer) 01521 { 01522 if (!(huff_tree->element_buffer= 01523 (HUFF_ELEMENT*) my_malloc(found*2*sizeof(HUFF_ELEMENT),MYF(MY_WME)))) 01524 return 1; 01525 } 01526 else 01527 { 01528 HUFF_ELEMENT *temp; 01529 if (!(temp= 01530 (HUFF_ELEMENT*) my_realloc((gptr) huff_tree->element_buffer, 01531 found*2*sizeof(HUFF_ELEMENT), 01532 MYF(MY_WME)))) 01533 return 1; 01534 huff_tree->element_buffer=temp; 01535 } 01536 01537 huff_counts->tree=huff_tree; 01538 huff_tree->counts=huff_counts; 01539 huff_tree->min_chr=first; 01540 huff_tree->max_chr=last; 01541 huff_tree->char_bits=max_bit(last-first); 01542 huff_tree->offset_bits=max_bit(found-1)+1; 01543 01544 if (huff_counts->tree_buff) 01545 { 01546 huff_tree->elements=0; 01547 huff_tree->tree_pack_length=(1+15+16+5+5+ 01548 (huff_tree->char_bits+1)*found+ 01549 (huff_tree->offset_bits+1)* 01550 (found-2)+7)/8 + 01551 (uint) (huff_tree->counts->tree_pos- 01552 huff_tree->counts->tree_buff); 01553 /* 01554 Put a HUFF_ELEMENT into the queue for every distinct column value. 01555 01556 tree_walk() calls save_counts_in_queue() for every element in 01557 'int_tree'. This takes elements from the target trees element 01558 buffer and places references to them into the buffer of the 01559 priority queue. We insert in column value order, but the order is 01560 in fact irrelevant here. We will establish the correct order 01561 later. 01562 */ 01563 tree_walk(&huff_counts->int_tree, 01564 (int (*)(void*, element_count,void*)) save_counts_in_queue, 01565 (gptr) huff_tree, left_root_right); 01566 } 01567 else 01568 { 01569 huff_tree->elements=found; 01570 huff_tree->tree_pack_length=(9+9+5+5+ 01571 (huff_tree->char_bits+1)*found+ 01572 (huff_tree->offset_bits+1)* 01573 (found-2)+7)/8; 01574 /* 01575 Put a HUFF_ELEMENT into the queue for every byte code found in the column. 01576 01577 The elements are taken from the target trees element buffer. 01578 Instead of using queue_insert(), we just place references to the 01579 elements into the buffer of the priority queue. We insert in byte 01580 value order, but the order is in fact irrelevant here. We will 01581 establish the correct order later. 01582 */ 01583 for (i=first, found=0 ; i <= last ; i++) 01584 { 01585 if (huff_counts->counts[i]) 01586 { 01587 new_huff_el=huff_tree->element_buffer+(found++); 01588 new_huff_el->count=huff_counts->counts[i]; 01589 new_huff_el->a.leaf.null=0; 01590 new_huff_el->a.leaf.element_nr=i; 01591 queue.root[found]=(byte*) new_huff_el; 01592 } 01593 } 01594 /* 01595 If there is only a single byte value in this field in all records, 01596 add a second element with zero incidence. This is required to enter 01597 the loop, which builds the Huffman tree. 01598 */ 01599 while (found < 2) 01600 { 01601 new_huff_el=huff_tree->element_buffer+(found++); 01602 new_huff_el->count=0; 01603 new_huff_el->a.leaf.null=0; 01604 if (last) 01605 new_huff_el->a.leaf.element_nr=huff_tree->min_chr=last-1; 01606 else 01607 new_huff_el->a.leaf.element_nr=huff_tree->max_chr=last+1; 01608 queue.root[found]=(byte*) new_huff_el; 01609 } 01610 } 01611 01612 /* Make a queue from the queue buffer. */ 01613 queue.elements=found; 01614 01615 /* 01616 Make a priority queue from the queue. Construct its index so that we 01617 have a partially ordered tree. 01618 */ 01619 for (i=found/2 ; i > 0 ; i--) 01620 _downheap(&queue,i); 01621 01622 /* The Huffman algorithm. */ 01623 bytes_packed=0; bits_packed=0; 01624 for (i=1 ; i < found ; i++) 01625 { 01626 /* 01627 Pop the top element from the queue (the one with the least incidence). 01628 Popping from a priority queue includes a re-ordering of the queue, 01629 to get the next least incidence element to the top. 01630 */ 01631 a=(HUFF_ELEMENT*) queue_remove(&queue,0); 01632 /* 01633 Copy the next least incidence element. The queue implementation 01634 reserves root[0] for temporary purposes. root[1] is the top. 01635 */ 01636 b=(HUFF_ELEMENT*) queue.root[1]; 01637 /* Get a new element from the element buffer. */ 01638 new_huff_el=huff_tree->element_buffer+found+i; 01639 /* The new element gets the sum of the two least incidence elements. */ 01640 new_huff_el->count=a->count+b->count; 01641 /* 01642 The Huffman algorithm assigns another bit to the code for a byte 01643 every time that bytes incidence is combined (directly or indirectly) 01644 to a new element as one of the two least incidence elements. 01645 This means that one more bit per incidence of that byte is required 01646 in the resulting file. So we add the new combined incidence as the 01647 number of bits by which the result grows. 01648 */ 01649 bits_packed+=(uint) (new_huff_el->count & 7); 01650 bytes_packed+=new_huff_el->count/8; 01651 /* The new element points to its children, lesser in left. */ 01652 new_huff_el->a.nod.left=a; 01653 new_huff_el->a.nod.right=b; 01654 /* 01655 Replace the copied top element by the new element and re-order the 01656 queue. 01657 */ 01658 queue.root[1]=(byte*) new_huff_el; 01659 queue_replaced(&queue); 01660 } 01661 huff_tree->root=(HUFF_ELEMENT*) queue.root[1]; 01662 huff_tree->bytes_packed=bytes_packed+(bits_packed+7)/8; 01663 return 0; 01664 }
Here is the caller graph for this function:

| static HUFF_TREE * make_huff_trees | ( | HUFF_COUNTS * | huff_counts, | |
| uint | trees | |||
| ) | [static] |
Definition at line 1439 of file myisampack.c.
References DBUG_ENTER, DBUG_RETURN, make_huff_tree(), my_free, my_malloc(), MY_WME, MY_ZEROFILL, and MYF.
Referenced by compress().
01440 { 01441 uint tree; 01442 HUFF_TREE *huff_tree; 01443 DBUG_ENTER("make_huff_trees"); 01444 01445 if (!(huff_tree=(HUFF_TREE*) my_malloc(trees*sizeof(HUFF_TREE), 01446 MYF(MY_WME | MY_ZEROFILL)))) 01447 DBUG_RETURN(0); 01448 01449 for (tree=0 ; tree < trees ; tree++) 01450 { 01451 if (make_huff_tree(huff_tree+tree,huff_counts+tree)) 01452 { 01453 while (tree--) 01454 my_free((gptr) huff_tree[tree].element_buffer,MYF(0)); 01455 my_free((gptr) huff_tree,MYF(0)); 01456 DBUG_RETURN(0); 01457 } 01458 } 01459 DBUG_RETURN(huff_tree); 01460 }
Here is the call graph for this function:

Here is the caller graph for this function:

| static char * make_new_name | ( | char * | new_name, | |
| char * | old_name | |||
| ) | [static] |
Definition at line 2784 of file myisampack.c.
References DATA_TMP_EXT, and fn_format().
Referenced by compress().
02785 { 02786 return fn_format(new_name,old_name,"",DATA_TMP_EXT,2+4); 02787 }
Here is the call graph for this function:

Here is the caller graph for this function:

| static uint * make_offset_code_tree | ( | HUFF_TREE * | huff_tree, | |
| HUFF_ELEMENT * | element, | |||
| uint * | offset | |||
| ) | [static] |
Definition at line 2345 of file myisampack.c.
References st_huff_element::a, st_huff_element::un_element::st_leaf::element_nr, IS_OFFSET, st_huff_element::un_element::leaf, st_huff_element::un_element::st_nod::left, st_huff_tree::max_offset, st_huff_element::un_element::nod, st_huff_element::un_element::st_leaf::null, and st_huff_element::un_element::st_nod::right.
Referenced by write_huff_tree().
02347 { 02348 uint *prev_offset; 02349 02350 prev_offset= offset; 02351 /* 02352 'a.leaf.null' takes the same place as 'a.nod.left'. If this is null, 02353 then there is no left child and, hence no right child either. This 02354 is a property of a binary tree. An element is either a node with two 02355 childs, or a leaf without childs. 02356 02357 The current element is always a node with two childs. Go left first. 02358 */ 02359 if (!element->a.nod.left->a.leaf.null) 02360 { 02361 /* Store the byte code or the index of the column value. */ 02362 prev_offset[0] =(uint) element->a.nod.left->a.leaf.element_nr; 02363 offset+=2; 02364 } 02365 else 02366 { 02367 /* 02368 Recursively traverse the tree to the left. Mark it as an offset to 02369 another tree node (in contrast to a byte code or column value index). 02370 */ 02371 prev_offset[0]= IS_OFFSET+2; 02372 offset=make_offset_code_tree(huff_tree,element->a.nod.left,offset+2); 02373 } 02374 02375 /* Now, check the right child. */ 02376 if (!element->a.nod.right->a.leaf.null) 02377 { 02378 /* Store the byte code or the index of the column value. */ 02379 prev_offset[1]=element->a.nod.right->a.leaf.element_nr; 02380 return offset; 02381 } 02382 else 02383 { 02384 /* 02385 Recursively traverse the tree to the right. Mark it as an offset to 02386 another tree node (in contrast to a byte code or column value index). 02387 */ 02388 uint temp=(uint) (offset-prev_offset-1); 02389 prev_offset[1]= IS_OFFSET+ temp; 02390 if (huff_tree->max_offset < temp) 02391 huff_tree->max_offset = temp; 02392 return make_offset_code_tree(huff_tree,element->a.nod.right,offset); 02393 } 02394 }
Here is the caller graph for this function:

| static char * make_old_name | ( | char * | new_name, | |
| char * | old_name | |||
| ) | [static] |
Definition at line 2789 of file myisampack.c.
References fn_format(), and OLD_EXT.
Referenced by compress().
Here is the call graph for this function:

Here is the caller graph for this function:

| static void make_traverse_code_tree | ( | HUFF_TREE * | huff_tree, | |
| HUFF_ELEMENT * | element, | |||
| uint | size, | |||
| ulonglong | code | |||
| ) | [static] |
Definition at line 1920 of file myisampack.c.
References st_huff_element::a, st_huff_tree::code, st_huff_tree::code_len, st_huff_element::un_element::st_leaf::element_nr, st_huff_tree::height, st_huff_element::un_element::leaf, st_huff_element::un_element::st_nod::left, st_huff_element::un_element::nod, st_huff_element::un_element::st_leaf::null, and st_huff_element::un_element::st_nod::right.
Referenced by make_huff_decode_table().
01923 { 01924 uint chr; 01925 if (!element->a.leaf.null) 01926 { 01927 chr=element->a.leaf.element_nr; 01928 huff_tree->code_len[chr]= (uchar) (8 * sizeof(ulonglong) - size); 01929 huff_tree->code[chr]= (code >> size); 01930 if (huff_tree->height < 8 * sizeof(ulonglong) - size) 01931 huff_tree->height= 8 * sizeof(ulonglong) - size; 01932 } 01933 else 01934 { 01935 size--; 01936 make_traverse_code_tree(huff_tree,element->a.nod.left,size,code); 01937 make_traverse_code_tree(huff_tree, element->a.nod.right, size, 01938 code + (((ulonglong) 1) << size)); 01939 } 01940 return; 01941 }
Here is the caller graph for this function:

| static int mrg_close | ( | PACK_MRG_INFO * | mrg | ) | [static] |
Definition at line 3065 of file myisampack.c.
References st_isam_mrg::count, st_isam_mrg::file, st_isam_mrg::free_file, mi_close(), my_free, and MYF.
Referenced by compress().
03066 { 03067 uint i; 03068 int error=0; 03069 for (i=0 ; i < mrg->count ; i++) 03070 error|=mi_close(mrg->file[i]); 03071 if (mrg->free_file) 03072 my_free((gptr) mrg->file,MYF(0)); 03073 return error; 03074 }
Here is the call graph for this function:

Here is the caller graph for this function:

| static void mrg_reset | ( | PACK_MRG_INFO * | mrg | ) | [static] |
Definition at line 3017 of file myisampack.c.
References st_isam_mrg::current, HA_EXTRA_NO_CACHE, and mi_extra().
Referenced by compress_isam_file().
03018 { 03019 if (mrg->current) 03020 { 03021 mi_extra(*mrg->current, HA_EXTRA_NO_CACHE, 0); 03022 mrg->current=0; 03023 } 03024 }
Here is the call graph for this function:

Here is the caller graph for this function:

| static int mrg_rrnd | ( | PACK_MRG_INFO * | info, | |
| byte * | buf | |||
| ) | [static] |
Definition at line 3026 of file myisampack.c.
References st_isam_mrg::count, st_isam_mrg::current, st_isam_mrg::end, st_isam_mrg::file, HA_ERR_END_OF_FILE, HA_EXTRA_CACHE, HA_EXTRA_NO_CACHE, HA_STATE_CHANGED, st_mi_isam_pack::header_length, mi_extra(), mi_reset(), st_myisam_info::nextpos, st_mi_isam_share::pack, st_mi_isam_share::read_rnd, st_myisam_info::s, and st_myisam_info::update.
Referenced by compress_isam_file().
03027 { 03028 int error; 03029 MI_INFO *isam_info; 03030 my_off_t filepos; 03031 03032 if (!info->current) 03033 { 03034 isam_info= *(info->current=info->file); 03035 info->end=info->current+info->count; 03036 mi_reset(isam_info); 03037 mi_extra(isam_info, HA_EXTRA_CACHE, 0); 03038 filepos=isam_info->s->pack.header_length; 03039 } 03040 else 03041 { 03042 isam_info= *info->current; 03043 filepos= isam_info->nextpos; 03044 } 03045 03046 for (;;) 03047 { 03048 isam_info->update&= HA_STATE_CHANGED; 03049 if (!(error=(*isam_info->s->read_rnd)(isam_info,(byte*) buf, 03050 filepos, 1)) || 03051 error != HA_ERR_END_OF_FILE) 03052 return (error); 03053 mi_extra(isam_info,HA_EXTRA_NO_CACHE, 0); 03054 if (info->current+1 == info->end) 03055 return(HA_ERR_END_OF_FILE); 03056 info->current++; 03057 isam_info= *info->current; 03058 filepos=isam_info->s->pack.header_length; 03059 mi_reset(isam_info); 03060 mi_extra(isam_info,HA_EXTRA_CACHE, 0); 03061 } 03062 }
Here is the call graph for this function:

Here is the caller graph for this function:

| static MI_INFO * open_isam_file | ( | char * | name, | |
| int | mode | |||
| ) | [static] |
Definition at line 401 of file myisampack.c.
References st_mi_status_info::data_file_length, DBUG_ENTER, DBUG_RETURN, F_WRLCK, force_pack, HA_OPEN_ABORT_IF_LOCKED, HA_OPEN_WAIT_IF_LOCKED, HA_OPTION_COMPRESS_RECORD, HA_OPTION_READ_ONLY_DATA, join_table, mi_close(), mi_lock_database(), mi_open(), my_errno, st_mi_isam_share::options, st_mi_status_info::records, st_myisam_info::s, st_mi_state_info::state, st_mi_isam_share::state, verbose, and VOID.
Referenced by open_isam_files().
00402 { 00403 MI_INFO *isam_file; 00404 MYISAM_SHARE *share; 00405 DBUG_ENTER("open_isam_file"); 00406 00407 if (!(isam_file=mi_open(name,mode, 00408 (opt_wait ? HA_OPEN_WAIT_IF_LOCKED : 00409 HA_OPEN_ABORT_IF_LOCKED)))) 00410 { 00411 VOID(fprintf(stderr, "%s gave error %d on open\n", name, my_errno)); 00412 DBUG_RETURN(0); 00413 } 00414 share=isam_file->s; 00415 if (share->options & HA_OPTION_COMPRESS_RECORD && !join_table) 00416 { 00417 if (!force_pack) 00418 { 00419 VOID(fprintf(stderr, "%s is already compressed\n", name)); 00420 VOID(mi_close(isam_file)); 00421 DBUG_RETURN(0); 00422 } 00423 if (verbose) 00424 puts("Recompressing already compressed table"); 00425 share->options&= ~HA_OPTION_READ_ONLY_DATA; /* We are modifing it */ 00426 } 00427 if (! force_pack && share->state.state.records != 0 && 00428 (share->state.state.records <= 1 || 00429 share->state.state.data_file_length < 1024)) 00430 { 00431 VOID(fprintf(stderr, "%s is too small to compress\n", name)); 00432 VOID(mi_close(isam_file)); 00433 DBUG_RETURN(0); 00434 } 00435 VOID(mi_lock_database(isam_file,F_WRLCK)); 00436 DBUG_RETURN(isam_file); 00437 }
Here is the call graph for this function:

Here is the caller graph for this function:

| static bool open_isam_files | ( | PACK_MRG_INFO * | mrg, | |
| char ** | names, | |||
| uint | count | |||
| ) | [static] |
Definition at line 440 of file myisampack.c.
References st_mi_isam_share::base, st_isam_mrg::count, st_isam_mrg::current, st_mi_base_info::fields, st_isam_mrg::file, st_isam_mrg::free_file, st_mi_state_info::key_map, st_mi_base_info::keys, st_columndef::length, mi_close(), mi_is_all_keys_active, MY_FAE, my_free, my_malloc(), my_progname, MYF, open_isam_file(), st_mi_isam_share::rec, st_mi_base_info::reclength, st_myisam_info::s, st_isam_mrg::src_file_has_indexes_disabled, st_mi_isam_share::state, st_columndef::type, and VOID.
00441 { 00442 uint i,j; 00443 mrg->count=0; 00444 mrg->current=0; 00445 mrg->file=(MI_INFO**) my_malloc(sizeof(MI_INFO*)*count,MYF(MY_FAE)); 00446 mrg->free_file=1; 00447 mrg->src_file_has_indexes_disabled= 0; 00448 for (i=0; i < count ; i++) 00449 { 00450 if (!(mrg->file[i]=open_isam_file(names[i],O_RDONLY))) 00451 goto error; 00452 00453 mrg->src_file_has_indexes_disabled|= 00454 ! mi_is_all_keys_active(mrg->file[i]->s->state.key_map, 00455 mrg->file[i]->s->base.keys); 00456 } 00457 /* Check that files are identical */ 00458 for (j=0 ; j < count-1 ; j++) 00459 { 00460 MI_COLUMNDEF *m1,*m2,*end; 00461 if (mrg->file[j]->s->base.reclength != mrg->file[j+1]->s->base.reclength || 00462 mrg->file[j]->s->base.fields != mrg->file[j+1]->s->base.fields) 00463 goto diff_file; 00464 m1=mrg->file[j]->s->rec; 00465 end=m1+mrg->file[j]->s->base.fields; 00466 m2=mrg->file[j+1]->s->rec; 00467 for ( ; m1 != end ; m1++,m2++) 00468 { 00469 if (m1->type != m2->type || m1->length != m2->length) 00470 goto diff_file; 00471 } 00472 } 00473 mrg->count=count; 00474 return 0; 00475 00476 diff_file: 00477 VOID(fprintf(stderr, "%s: Tables '%s' and '%s' are not identical\n", 00478 my_progname, names[j], names[j+1])); 00479 error: 00480 while (i--) 00481 mi_close(mrg->file[i]); 00482 my_free((gptr) mrg->file,MYF(0)); 00483 return 1; 00484 }
Here is the call graph for this function:

| static void print_version | ( | void | ) | [static] |
Definition at line 293 of file myisampack.c.
References MACHINE_TYPE, my_progname, NETWARE_SET_SCREEN_MODE, SYSTEM_TYPE, and VOID.
00294 { 00295 VOID(printf("%s Ver 1.23 for %s on %s\n", 00296 my_progname, SYSTEM_TYPE, MACHINE_TYPE)); 00297 NETWARE_SET_SCREEN_MODE(1); 00298 }
| static int save_counts_in_queue | ( | byte * | key, | |
| element_count | count, | |||
| HUFF_TREE * | tree | |||
| ) | [static] |
Definition at line 1697 of file myisampack.c.
References st_huff_element::a, st_huff_element::count, st_huff_tree::counts, st_huff_tree::element_buffer, st_huff_element::un_element::st_leaf::element_nr, st_huff_tree::elements, st_huff_counts::field_length, st_huff_element::un_element::leaf, st_huff_element::un_element::st_leaf::null, and st_huff_counts::tree_buff.
01699 { 01700 HUFF_ELEMENT *new_huff_el; 01701 01702 new_huff_el=tree->element_buffer+(tree->elements++); 01703 new_huff_el->count=count; 01704 new_huff_el->a.leaf.null=0; 01705 new_huff_el->a.leaf.element_nr= (uint) (key- tree->counts->tree_buff) / 01706 tree->counts->field_length; 01707 queue.root[tree->elements]=(byte*) new_huff_el; 01708 return 0; 01709 }
| static int save_state | ( | MI_INFO * | isam_file, | |
| PACK_MRG_INFO * | mrg, | |||
| my_off_t | new_length, | |||
| ha_checksum | crc | |||
| ) | [static] |
Definition at line 2935 of file myisampack.c.
References st_mi_isam_share::base, st_mi_isam_share::changed, st_mi_status_info::checksum, st_mi_status_info::data_file_length, DBUG_ENTER, DBUG_RETURN, st_mi_status_info::del, st_mi_state_info::dellink, st_mi_status_info::empty, st_mi_isam_share::global_changed, HA_OFFSET_ERROR, HA_OPTION_COMPRESS_RECORD, HA_OPTION_READ_ONLY_DATA, st_mi_state_info::header, isamchk_neaded, key, st_mi_state_info::key_del, st_mi_status_info::key_file_length, st_mi_state_info::key_map, st_mi_state_info::key_root, st_mi_base_info::keys, st_mi_base_info::keystart, st_mi_isam_share::kfile, st_mi_state_info::max_block_size_index, mi_clear_all_keys_active, mi_int2store, mi_is_all_keys_active, mi_state_info_write(), mi_uint2korr, my_chsize(), MYF, st_mi_state_info::open_count, st_mi_state_info::options, options(), st_isam_mrg::records, st_myisam_info::s, st_mi_state_info::split, st_myisam_info::state, st_mi_state_info::state, st_mi_isam_share::state, st_mi_state_info::version, and VOID.
Referenced by compress().
02937 { 02938 MYISAM_SHARE *share=isam_file->s; 02939 uint options=mi_uint2korr(share->state.header.options); 02940 uint key; 02941 DBUG_ENTER("save_state"); 02942 02943 options|= HA_OPTION_COMPRESS_RECORD | HA_OPTION_READ_ONLY_DATA; 02944 mi_int2store(share->state.header.options,options); 02945 02946 share->state.state.data_file_length=new_length; 02947 share->state.state.del=0; 02948 share->state.state.empty=0; 02949 share->state.dellink= HA_OFFSET_ERROR; 02950 share->state.split=(ha_rows) mrg->records; 02951 share->state.version=(ulong) time((time_t*) 0); 02952 if (! mi_is_all_keys_active(share->state.key_map, share->base.keys)) 02953 { 02954 /* 02955 Some indexes are disabled, cannot use current key_file_length value 02956 as an estimate of upper bound of index file size. Use packed data file 02957 size instead. 02958 */ 02959 share->state.state.key_file_length= new_length; 02960 } 02961 /* 02962 If there are no disabled indexes, keep key_file_length value from 02963 original file so "myisamchk -rq" can use this value (this is necessary 02964 because index size cannot be easily calculated for fulltext keys) 02965 */ 02966 mi_clear_all_keys_active(share->state.key_map); 02967 for (key=0 ; key < share->base.keys ; key++) 02968 share->state.key_root[key]= HA_OFFSET_ERROR; 02969 for (key=0 ; key < share->state.header.max_block_size_index ; key++) 02970 share->state.key_del[key]= HA_OFFSET_ERROR; 02971 isam_file->state->checksum=crc; /* Save crc here */ 02972 share->changed=1; /* Force write of header */ 02973 share->state.open_count=0; 02974 share->global_changed=0; 02975 VOID(my_chsize(share->kfile, share->base.keystart, 0, MYF(0))); 02976 if (share->base.keys) 02977 isamchk_neaded=1; 02978 DBUG_RETURN(mi_state_info_write(share->kfile,&share->state,1+2)); 02979 }
Here is the call graph for this function:

Here is the caller graph for this function:

| static int save_state_mrg | ( | File | file, | |
| PACK_MRG_INFO * | isam_file, | |||
| my_off_t | new_length, | |||
| ha_checksum | crc | |||
| ) | [static] |
Definition at line 2982 of file myisampack.c.
References st_mi_isam_share::base, st_mi_state_info::changed, st_mi_status_info::checksum, st_mi_status_info::data_file_length, DBUG_ENTER, DBUG_RETURN, st_mi_status_info::del, st_mi_state_info::dellink, st_mi_status_info::empty, st_isam_mrg::file, HA_OFFSET_ERROR, HA_OPTION_COMPRESS_RECORD, HA_OPTION_READ_ONLY_DATA, st_mi_state_info::header, isamchk_neaded, st_mi_status_info::key_file_length, st_mi_state_info::key_map, st_mi_base_info::keys, max, mi_clear_all_keys_active, mi_int2store, mi_state_info_write(), mi_uint2korr, st_mi_state_info::options, options(), st_isam_mrg::records, st_mi_status_info::records, st_myisam_info::s, st_mi_state_info::split, st_isam_mrg::src_file_has_indexes_disabled, st_mi_state_info::state, st_mi_isam_share::state, STATE_CHANGED, STATE_NOT_ANALYZED, and st_mi_state_info::version.
Referenced by compress().
02984 { 02985 MI_STATE_INFO state; 02986 MI_INFO *isam_file=mrg->file[0]; 02987 uint options; 02988 DBUG_ENTER("save_state_mrg"); 02989 02990 state= isam_file->s->state; 02991 options= (mi_uint2korr(state.header.options) | HA_OPTION_COMPRESS_RECORD | 02992 HA_OPTION_READ_ONLY_DATA); 02993 mi_int2store(state.header.options,options); 02994 state.state.data_file_length=new_length; 02995 state.state.del=0; 02996 state.state.empty=0; 02997 state.state.records=state.split=(ha_rows) mrg->records; 02998 /* See comment above in save_state about key_file_length handling. */ 02999 if (mrg->src_file_has_indexes_disabled) 03000 { 03001 isam_file->s->state.state.key_file_length= 03002 max(isam_file->s->state.state.key_file_length, new_length); 03003 } 03004 state.dellink= HA_OFFSET_ERROR; 03005 state.version=(ulong) time((time_t*) 0); 03006 mi_clear_all_keys_active(state.key_map); 03007 state.state.checksum=crc; 03008 if (isam_file->s->base.keys) 03009 isamchk_neaded=1; 03010 state.changed=STATE_CHANGED | STATE_NOT_ANALYZED; /* Force check of table */ 03011 DBUG_RETURN (mi_state_info_write(file,&state,1+2)); 03012 }
Here is the call graph for this function:

Here is the caller graph for this function:

| static int test_space_compress | ( | HUFF_COUNTS * | huff_counts, | |
| my_off_t | records, | |||
| uint | max_space_length, | |||
| my_off_t * | space_counts, | |||
| my_off_t | tot_space_count, | |||
| enum en_fieldtype | field_type | |||
| ) | [static] |
Definition at line 1372 of file myisampack.c.
References st_huff_counts::bytes_packed, calc_packed_length(), st_huff_counts::counts, st_huff_counts::field_type, st_huff_counts::length_bits, max_bit(), st_huff_counts::min_space, st_huff_counts::pack_type, PACK_TYPE_SELECTED, st_huff_counts::pre_space, and skip().
01375 { 01376 int min_pos; 01377 uint length_bits,i; 01378 my_off_t space_count,min_space_count,min_pack,new_length,skip; 01379 01380 length_bits=max_bit(max_space_length); 01381 01382 /* Default no end_space-packing */ 01383 space_count=huff_counts->counts[(uint) ' ']; 01384 min_space_count= (huff_counts->counts[(uint) ' ']+= tot_space_count); 01385 min_pack=calc_packed_length(huff_counts,0); 01386 min_pos= -2; 01387 huff_counts->counts[(uint) ' ']=space_count; 01388 01389 /* Test with allways space-count */ 01390 new_length=huff_counts->bytes_packed+length_bits*records/8; 01391 if (new_length+1 < min_pack) 01392 { 01393 min_pos= -1; 01394 min_pack=new_length; 01395 min_space_count=space_count; 01396 } 01397 /* Test with length-flag */ 01398 for (skip=0L, i=0 ; i < 8 ; i++) 01399 { 01400 if (space_counts[i]) 01401 { 01402 if (i) 01403 huff_counts->counts[(uint) ' ']+=space_counts[i]; 01404 skip+=huff_counts->pre_space[i]; 01405 new_length=calc_packed_length(huff_counts,0)+ 01406 (records+(records-skip)*(1+length_bits))/8; 01407 if (new_length < min_pack) 01408 { 01409 min_pos=(int) i; 01410 min_pack=new_length; 01411 min_space_count=huff_counts->counts[(uint) ' ']; 01412 } 01413 } 01414 } 01415 01416 huff_counts->counts[(uint) ' ']=min_space_count; 01417 huff_counts->bytes_packed=min_pack; 01418 switch (min_pos) { 01419 case -2: 01420 return(0); /* No space-compress */ 01421 case -1: /* Always space-count */ 01422 huff_counts->field_type=field_type; 01423 huff_counts->min_space=0; 01424 huff_counts->length_bits=max_bit(max_space_length); 01425 break; 01426 default: 01427 huff_counts->field_type=field_type; 01428 huff_counts->min_space=(uint) min_pos; 01429 huff_counts->pack_type|=PACK_TYPE_SELECTED; 01430 huff_counts->length_bits=max_bit(max_space_length); 01431 break; 01432 } 01433 return(1); /* Using space-compress */ 01434 }
Here is the call graph for this function:

| static void usage | ( | void | ) | [static] |
Definition at line 301 of file myisampack.c.
References my_long_options, my_print_help(), my_print_variables(), my_progname, print_defaults(), print_version(), and VOID.
00302 { 00303 print_version(); 00304 puts("Copyright (C) 2002 MySQL AB"); 00305 puts("This software comes with ABSOLUTELY NO WARRANTY. This is free software,"); 00306 puts("and you are welcome to modify and redistribute it under the GPL license\n"); 00307 00308 puts("Pack a MyISAM-table to take much less space."); 00309 puts("Keys are not updated, you must run myisamchk -rq on the datafile"); 00310 puts("afterwards to update the keys."); 00311 puts("You should give the .MYI file as the filename argument."); 00312 00313 VOID(printf("\nUsage: %s [OPTIONS] filename...\n", my_progname)); 00314 my_print_help(my_long_options); 00315 print_defaults("my", load_default_groups); 00316 my_print_variables(my_long_options); 00317 }
Here is the call graph for this function:

Definition at line 2875 of file myisampack.c.
References st_file_buffer::bitbucket, st_file_buffer::bits, BITS_SAVED, DBUG_ASSERT, st_file_buffer::end, file_buffer, flush_buffer(), int(), st_file_buffer::pos, reg3, and VOID.
02876 { 02877 DBUG_ASSERT(((bits < 8 * sizeof(value)) && ! (value >> bits)) || 02878 (bits == 8 * sizeof(value))); 02879 02880 if ((file_buffer.bits-= (int) bits) >= 0) 02881 { 02882 file_buffer.bitbucket|= value << file_buffer.bits; 02883 } 02884 else 02885 { 02886 reg3 ulonglong bit_buffer; 02887 bits= (uint) -file_buffer.bits; 02888 bit_buffer= (file_buffer.bitbucket | 02889 ((bits != 8 * sizeof(value)) ? (value >> bits) : 0)); 02890 #if BITS_SAVED == 64 02891 *file_buffer.pos++= (uchar) (bit_buffer >> 56); 02892 *file_buffer.pos++= (uchar) (bit_buffer >> 48); 02893 *file_buffer.pos++= (uchar) (bit_buffer >> 40); 02894 *file_buffer.pos++= (uchar) (bit_buffer >> 32); 02895 #endif 02896 *file_buffer.pos++= (uchar) (bit_buffer >> 24); 02897 *file_buffer.pos++= (uchar) (bit_buffer >> 16); 02898 *file_buffer.pos++= (uchar) (bit_buffer >> 8); 02899 *file_buffer.pos++= (uchar) (bit_buffer); 02900 02901 if (bits != 8 * sizeof(value)) 02902 value&= (((ulonglong) 1) << bits) - 1; 02903 if (file_buffer.pos >= file_buffer.end) 02904 VOID(flush_buffer(~ (ulong) 0)); 02905 file_buffer.bits=(int) (BITS_SAVED - bits); 02906 file_buffer.bitbucket= value << (BITS_SAVED - bits); 02907 } 02908 return; 02909 }
Here is the call graph for this function:

Referenced by compress_isam_file(), write_field_info(), and write_huff_tree().
Here is the caller graph for this function:

| static void write_field_info | ( | HUFF_COUNTS * | counts, | |
| uint | fields, | |||
| uint | trees | |||
| ) | [static] |
Definition at line 2033 of file myisampack.c.
References DBUG_PRINT, st_huff_counts::field_length, st_huff_counts::field_type, flush_bits(), st_huff_counts::length_bits, max_bit(), st_huff_counts::max_zero_fill, st_huff_counts::pack_type, PACK_TYPE_ZERO_FILL, reg1, st_huff_counts::tree, st_huff_tree::tree_number, verbose, VOID, and write_bits().
Referenced by compress().
02034 { 02035 reg1 uint i; 02036 uint huff_tree_bits; 02037 huff_tree_bits=max_bit(trees ? trees-1 : 0); 02038 02039 DBUG_PRINT("info", ("")); 02040 DBUG_PRINT("info", ("column types:")); 02041 DBUG_PRINT("info", ("FIELD_NORMAL 0")); 02042 DBUG_PRINT("info", ("FIELD_SKIP_ENDSPACE 1")); 02043 DBUG_PRINT("info", ("FIELD_SKIP_PRESPACE 2")); 02044 DBUG_PRINT("info", ("FIELD_SKIP_ZERO 3")); 02045 DBUG_PRINT("info", ("FIELD_BLOB 4")); 02046 DBUG_PRINT("info", ("FIELD_CONSTANT 5")); 02047 DBUG_PRINT("info", ("FIELD_INTERVALL 6")); 02048 DBUG_PRINT("info", ("FIELD_ZERO 7")); 02049 DBUG_PRINT("info", ("FIELD_VARCHAR 8")); 02050 DBUG_PRINT("info", ("FIELD_CHECK 9")); 02051 DBUG_PRINT("info", ("")); 02052 DBUG_PRINT("info", ("pack type as a set of flags:")); 02053 DBUG_PRINT("info", ("PACK_TYPE_SELECTED 1")); 02054 DBUG_PRINT("info", ("PACK_TYPE_SPACE_FIELDS 2")); 02055 DBUG_PRINT("info", ("PACK_TYPE_ZERO_FILL 4")); 02056 DBUG_PRINT("info", ("")); 02057 if (verbose >= 2) 02058 { 02059 VOID(printf("\n")); 02060 VOID(printf("column types:\n")); 02061 VOID(printf("FIELD_NORMAL 0\n")); 02062 VOID(printf("FIELD_SKIP_ENDSPACE 1\n")); 02063 VOID(printf("FIELD_SKIP_PRESPACE 2\n")); 02064 VOID(printf("FIELD_SKIP_ZERO 3\n")); 02065 VOID(printf("FIELD_BLOB 4\n")); 02066 VOID(printf("FIELD_CONSTANT 5\n")); 02067 VOID(printf("FIELD_INTERVALL 6\n")); 02068 VOID(printf("FIELD_ZERO 7\n")); 02069 VOID(printf("FIELD_VARCHAR 8\n")); 02070 VOID(printf("FIELD_CHECK 9\n")); 02071 VOID(printf("\n")); 02072 VOID(printf("pack type as a set of flags:\n")); 02073 VOID(printf("PACK_TYPE_SELECTED 1\n")); 02074 VOID(printf("PACK_TYPE_SPACE_FIELDS 2\n")); 02075 VOID(printf("PACK_TYPE_ZERO_FILL 4\n")); 02076 VOID(printf("\n")); 02077 } 02078 for (i=0 ; i++ < fields ; counts++) 02079 { 02080 write_bits((ulonglong) (int) counts->field_type, 5); 02081 write_bits(counts->pack_type,6); 02082 if (counts->pack_type & PACK_TYPE_ZERO_FILL) 02083 write_bits(counts->max_zero_fill,5); 02084 else 02085 write_bits(counts->length_bits,5); 02086 write_bits((ulonglong) counts->tree->tree_number - 1, huff_tree_bits); 02087 DBUG_PRINT("info", ("column: %3u type: %2u pack: %2u zero: %4u " 02088 "lbits: %2u tree: %2u length: %4u", 02089 i , counts->field_type, counts->pack_type, 02090 counts->max_zero_fill, counts->length_bits, 02091 counts->tree->tree_number, counts->field_length)); 02092 if (verbose >= 2) 02093 VOID(printf("column: %3u type: %2u pack: %2u zero: %4u lbits: %2u " 02094 "tree: %2u length: %4u\n", i , counts->field_type, 02095 counts->pack_type, counts->max_zero_fill, counts->length_bits, 02096 counts->tree->tree_number, counts->field_length)); 02097 } 02098 flush_bits(); 02099 return; 02100 }
Here is the call graph for this function:

Here is the caller graph for this function:

| static int write_header | ( | PACK_MRG_INFO * | isam_file, | |
| uint | header_length, | |||
| uint | trees, | |||
| my_off_t | tot_elements, | |||
| my_off_t | filelength | |||
| ) | [static] |
Definition at line 2008 of file myisampack.c.
References bzero, st_file_buffer::file, file_buffer, HEAD_LENGTH, int2store, int4store, st_isam_mrg::max_pack_length, memcpy_fixed, mi_get_pointer_length(), st_isam_mrg::min_pack_length, MY_NABP, my_seek(), MY_SEEK_SET, MY_WAIT_IF_FULL, MY_WME, my_write, MYF, myisam_pack_file_magic, st_file_buffer::pos, st_isam_mrg::ref_length, test_only, and VOID.
02010 { 02011 byte *buff= (byte*) file_buffer.pos; 02012 02013 bzero(buff,HEAD_LENGTH); 02014 memcpy_fixed(buff,myisam_pack_file_magic,4); 02015 int4store(buff+4,head_length); 02016 int4store(buff+8, mrg->min_pack_length); 02017 int4store(buff+12,mrg->max_pack_length); 02018 int4store(buff+16,tot_elements); 02019 int4store(buff+20,intervall_length); 02020 int2store(buff+24,trees); 02021 buff[26]=(char) mrg->ref_length; 02022 /* Save record pointer length */ 02023 buff[27]= (uchar) mi_get_pointer_length((ulonglong) filelength,2); 02024 if (test_only) 02025 return 0; 02026 VOID(my_seek(file_buffer.file,0L,MY_SEEK_SET,MYF(0))); 02027 return my_write(file_buffer.file,(const byte *) file_buffer.pos,HEAD_LENGTH, 02028 MYF(MY_WME | MY_NABP | MY_WAIT_IF_FULL)) != 0; 02029 }
Here is the call graph for this function:

Definition at line 2106 of file myisampack.c.
References bindigits(), st_file_buffer::buffer, st_huff_tree::char_bits, st_huff_tree::code, st_huff_tree::code_len, st_huff_tree::counts, DBUG_EXECUTE_IF, DBUG_PRINT, EE_OUTOFMEMORY, st_huff_tree::elements, file_buffer, flush_bits(), st_huff_tree::height, hexdigits(), IS_OFFSET, make_offset_code_tree(), max_bit(), st_huff_tree::max_offset, ME_BELL, st_huff_tree::min_chr, my_afree, my_alloca, my_error(), MYF, offset, st_huff_tree::offset_bits, st_file_buffer::pos, st_huff_tree::root, st_huff_counts::tree_buff, st_huff_tree::tree_number, st_huff_counts::tree_pos, verbose, VOID, and write_bits().
Referenced by compress().
02107 { 02108 uint i,int_length; 02109 uint tree_no; 02110 uint codes; 02111 uint errors= 0; 02112 uint *packed_tree,*offset,length; 02113 my_off_t elements; 02114 02115 /* Find the highest number of elements in the trees. */ 02116 for (i=length=0 ; i < trees ; i++) 02117 if (huff_tree[i].tree_number > 0 && huff_tree[i].elements > length) 02118 length=huff_tree[i].elements; 02119 /* 02120 Allocate a buffer for packing a decode tree. Two numbers per element 02121 (left child and right child). 02122 */ 02123 if (!(packed_tree=(uint*) my_alloca(sizeof(uint)*length*2))) 02124 { 02125 my_error(EE_OUTOFMEMORY,MYF(ME_BELL),sizeof(uint)*length*2); 02126 return 0; 02127 } 02128 02129 DBUG_PRINT("info", ("")); 02130 if (verbose >= 2) 02131 VOID(printf("\n")); 02132 tree_no= 0; 02133 intervall_length=0; 02134 for (elements=0; trees-- ; huff_tree++) 02135 { 02136 /* Skip columns that have been joined with other columns. */ 02137 if (huff_tree->tree_number == 0) 02138 continue; /* Deleted tree */ 02139 tree_no++; 02140 DBUG_PRINT("info", ("")); 02141 if (verbose >= 3) 02142 VOID(printf("\n")); 02143 /* Count the total number of elements (byte codes or column values). */ 02144 elements+=huff_tree->elements; 02145 huff_tree->max_offset=2; 02146 /* Build a tree of offsets and codes for decoding in 'packed_tree'. */ 02147 if (huff_tree->elements <= 1) 02148 offset=packed_tree; 02149 else 02150 offset=make_offset_code_tree(huff_tree,huff_tree->root,packed_tree); 02151 02152 /* This should be the same as 'length' above. */ 02153 huff_tree->offset_bits=max_bit(huff_tree->max_offset); 02154 02155 /* 02156 Since we check this during collecting the distinct column values, 02157 this should never happen. 02158 */ 02159 if (huff_tree->max_offset >= IS_OFFSET) 02160 { /* This should be impossible */ 02161 VOID(fprintf(stderr, "Tree offset got too big: %d, aborted\n", 02162 huff_tree->max_offset)); 02163 my_afree((gptr) packed_tree); 02164 return 0; 02165 } 02166 02167 DBUG_PRINT("info", ("pos: %lu elements: %u tree-elements: %lu " 02168 "char_bits: %u\n", 02169 (ulong) (file_buffer.pos - file_buffer.buffer), 02170 huff_tree->elements, (ulong) (offset - packed_tree), 02171 huff_tree->char_bits)); 02172 if (!huff_tree->counts->tree_buff) 02173 { 02174 /* We do a byte compression on this column. Mark with bit 0. */ 02175 write_bits(0,1); 02176 write_bits(huff_tree->min_chr,8); 02177 write_bits(huff_tree->elements,9); 02178 write_bits(huff_tree->char_bits,5); 02179 write_bits(huff_tree->offset_bits,5); 02180 int_length=0; 02181 } 02182 else 02183 { 02184 int_length=(uint) (huff_tree->counts->tree_pos - 02185 huff_tree->counts->tree_buff); 02186 /* We have distinct column values for this column. Mark with bit 1. */ 02187 write_bits(1,1); 02188 write_bits(huff_tree->elements,15); 02189 write_bits(int_length,16); 02190 write_bits(huff_tree->char_bits,5); 02191 write_bits(huff_tree->offset_bits,5); 02192 intervall_length+=int_length; 02193 } 02194 DBUG_PRINT("info", ("tree: %2u elements: %4u char_bits: %2u " 02195 "offset_bits: %2u %s: %5u codelen: %2u", 02196 tree_no, huff_tree->elements, huff_tree->char_bits, 02197 huff_tree->offset_bits, huff_tree->counts->tree_buff ? 02198 "bufflen" : "min_chr", huff_tree->counts->tree_buff ? 02199 int_length : huff_tree->min_chr, huff_tree->height)); 02200 if (verbose >= 2) 02201 VOID(printf("tree: %2u elements: %4u char_bits: %2u offset_bits: %2u " 02202 "%s: %5u codelen: %2u\n", tree_no, huff_tree->elements, 02203 huff_tree->char_bits, huff_tree->offset_bits, 02204 huff_tree->counts->tree_buff ? "bufflen" : "min_chr", 02205 huff_tree->counts->tree_buff ? int_length : 02206 huff_tree->min_chr, huff_tree->height)); 02207 02208 /* Check that the code tree length matches the element count. */ 02209 length=(uint) (offset-packed_tree); 02210 if (length != huff_tree->elements*2-2) 02211 { 02212 VOID(fprintf(stderr, "error: Huff-tree-length: %d != calc_length: %d\n", 02213 length, huff_tree->elements * 2 - 2)); 02214 errors++; 02215 break; 02216 } 02217 02218 for (i=0 ; i < length ; i++) 02219 { 02220 if (packed_tree[i] & IS_OFFSET) 02221 write_bits(packed_tree[i] - IS_OFFSET+ (1 << huff_tree->offset_bits), 02222 huff_tree->offset_bits+1); 02223 else 02224 write_bits(packed_tree[i]-huff_tree->min_chr,huff_tree->char_bits+1); 02225 DBUG_PRINT("info", ("tree[0x%04x]: %s0x%04x", 02226 i, (packed_tree[i] & IS_OFFSET) ? 02227 " -> " : "", (packed_tree[i] & IS_OFFSET) ? 02228 packed_tree[i] - IS_OFFSET + i : packed_tree[i])); 02229 if (verbose >= 3) 02230 VOID(printf("tree[0x%04x]: %s0x%04x\n", 02231 i, (packed_tree[i] & IS_OFFSET) ? " -> " : "", 02232 (packed_tree[i] & IS_OFFSET) ? 02233 packed_tree[i] - IS_OFFSET + i : packed_tree[i])); 02234 } 02235 flush_bits(); 02236 02237 /* 02238 Display coding tables and check their correctness. 02239 */ 02240 codes= huff_tree->counts->tree_buff ? huff_tree->elements : 256; 02241 for (i= 0; i < codes; i++) 02242 { 02243 ulonglong code; 02244 uint bits; 02245 uint len; 02246 uint idx; 02247 02248 if (! (len= huff_tree->code_len[i])) 02249 continue; 02250 DBUG_PRINT("info", ("code[0x%04x]: 0x%s bits: %2u bin: %s", i, 02251 hexdigits(huff_tree->code[i]), huff_tree->code_len[i], 02252 bindigits(huff_tree->code[i], 02253 huff_tree->code_len[i]))); 02254 if (verbose >= 3) 02255 VOID(printf("code[0x%04x]: 0x%s bits: %2u bin: %s\n", i, 02256 hexdigits(huff_tree->code[i]), huff_tree->code_len[i], 02257 bindigits(huff_tree->code[i], huff_tree->code_len[i]))); 02258 02259 /* Check that the encode table decodes correctly. */ 02260 code= 0; 02261 bits= 0; 02262 idx= 0; 02263 DBUG_EXECUTE_IF("forcechkerr1", len--;); 02264 DBUG_EXECUTE_IF("forcechkerr2", bits= 8 * sizeof(code);); 02265 DBUG_EXECUTE_IF("forcechkerr3", idx= length;); 02266 for (;;) 02267 { 02268 if (! len) 02269 { 02270 VOID(fflush(stdout)); 02271 VOID(fprintf(stderr, "error: code 0x%s with %u bits not found\n", 02272 hexdigits(huff_tree->code[i]), huff_tree->code_len[i])); 02273 errors++; 02274 break; 02275 } 02276 code<<= 1; 02277 code|= (huff_tree->code[i] >> (--len)) & 1; 02278 bits++; 02279 if (bits > 8 * sizeof(code)) 02280 { 02281 VOID(fflush(stdout)); 02282 VOID(fprintf(stderr, "error: Huffman code too long: %u/%u\n", 02283 bits, 8 * sizeof(code))); 02284 errors++; 02285 break; 02286 } 02287 idx+= code & 1; 02288 if (idx >= length) 02289 { 02290 VOID(fflush(stdout)); 02291 VOID(fprintf(stderr, "error: illegal tree offset: %u/%u\n", 02292 idx, length)); 02293 errors++; 02294 break; 02295 } 02296 if (packed_tree[idx] & IS_OFFSET) 02297 idx+= packed_tree[idx] & ~IS_OFFSET; 02298 else 02299 break; /* Hit a leaf. This contains the result value. */ 02300 } 02301 if (errors) 02302 break; 02303 02304 DBUG_EXECUTE_IF("forcechkerr4", packed_tree[idx]++;); 02305 if (packed_tree[idx] != i) 02306 { 02307 VOID(fflush(stdout)); 02308 VOID(fprintf(stderr, "error: decoded value 0x%04x should be: 0x%04x\n", 02309 packed_tree[idx], i)); 02310 errors++; 02311 break; 02312 } 02313 } /*end for (codes)*/ 02314 if (errors) 02315 break; 02316 02317 /* Write column values in case of distinct column value compression. */ 02318 if (huff_tree->counts->tree_buff) 02319 { 02320 for (i=0 ; i < int_length ; i++) 02321 { 02322 write_bits((ulonglong) (uchar) huff_tree->counts->tree_buff[i], 8); 02323 DBUG_PRINT("info", ("column_values[0x%04x]: 0x%02x", 02324 i, (uchar) huff_tree->counts->tree_buff[i])); 02325 if (verbose >= 3) 02326 VOID(printf("column_values[0x%04x]: 0x%02x\n", 02327 i, (uchar) huff_tree->counts->tree_buff[i])); 02328 } 02329 } 02330 flush_bits(); 02331 } 02332 DBUG_PRINT("info", ("")); 02333 if (verbose >= 2) 02334 VOID(printf("\n")); 02335 my_afree((gptr) packed_tree); 02336 if (errors) 02337 { 02338 VOID(fprintf(stderr, "Error: Generated decode trees are corrupt. Stop.\n")); 02339 return 0; 02340 } 02341 return elements; 02342 }
Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 186 of file myisampack.c.
Referenced by sp_head::add_used_tables_to_table_list(), agg_item_charsets(), Event_scheduler::check_system_tables(), db_drop_event(), fill_schema_events(), find_field_in_natural_join(), find_field_in_view(), Event_scheduler::load_named_event(), mark_common_columns(), mysql_make_view(), JOIN::optimize(), st_table_list::prep_where(), Item_in_subselect::select_in_like_transformer(), setup_conds(), setup_tables(), setup_wild(), Events::show_create_event(), store_natural_using_join_columns(), store_top_level_join_columns(), test_bug4236(), and Event_timed::update_fields().
int error_on_write = 0 [static] |
Definition at line 183 of file myisampack.c.
struct st_file_buffer file_buffer [static] |
Definition at line 197 of file myisampack.c.
Referenced by compress(), compress_isam_file(), end_file_buffer(), flush_bits(), flush_buffer(), init_file_buffer(), modify_defaults_file(), write_bits(), write_header(), and write_huff_tree().
int force_pack = 0 [static] |
ha_checksum glob_crc [static] |
Definition at line 196 of file myisampack.c.
HUFF_COUNTS* global_count [static] |
my_off_t intervall_length [static] |
Definition at line 195 of file myisampack.c.
Referenced by _mi_read_pack_info(), and read_huff_table().
int isamchk_neaded = 0 [static] |
char * join_table [static] |
Definition at line 194 of file myisampack.c.
Referenced by get_options(), open_isam_file(), and print_plan().
const char* load_default_groups[] = { "myisampack",0 } [static] |
Definition at line 201 of file myisampack.c.
struct my_option my_long_options[] [static] |
Definition at line 254 of file myisampack.c.
Definition at line 186 of file myisampack.c.
Definition at line 198 of file myisampack.c.
Referenced by Dbacc::abortOperation(), Dbacc::commitOperation(), compress(), delete_queue(), DbUtil::execUTIL_DESTORY_LOCK_REQ(), DbUtil::execUTIL_LOCK_REQ(), DbUtil::execUTIL_UNLOCK_REQ(), Dblqh::finishScanrec(), free_counts_and_tree_and_queue(), init_queue(), init_queue_ex(), merge_buffers(), merge_walk(), queue_fix(), queue_replaced(), reinit_queue(), Dbtc::releaseScanResources(), resize_queue(), reuse_freed_buff(), srv_que_round_robin(), srv_que_task_enqueue_low(), and srv_que_task_queue_check().
int silent = 0 [static] |
Definition at line 183 of file myisampack.c.
int test_only = 0 [static] |
Definition at line 183 of file myisampack.c.
Referenced by compress(), flush_buffer(), get_one_option(), and write_header().
char tmp_dir[FN_REFLEN] = {0} [static] |
Definition at line 194 of file myisampack.c.
int tmpfile_createflag = O_RDWR | O_TRUNC | O_EXCL [static] |
Definition at line 185 of file myisampack.c.
uint tree_buff_length = 65536 - MALLOC_OVERHEAD [static] |
Definition at line 193 of file myisampack.c.
int verbose = 0 [static] |
Definition at line 183 of file myisampack.c.
int write_loop = 0 [static] |
Definition at line 184 of file myisampack.c.
Referenced by compress(), get_one_option(), and get_options().
char zero_string[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0} [static] |
Definition at line 200 of file myisampack.c.
1.4.7

