home *** CD-ROM | disk | FTP | other *** search
/ Chip 2001 January / Chip_2001-01_cd1.bin / tema / mysql / mysql-3.23.28g-win-source.exe / myisam / mi_packrec.c < prev    next >
C/C++ Source or Header  |  2000-08-31  |  36KB  |  1,313 lines

  1. /* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
  2.    
  3.    This program is free software; you can redistribute it and/or modify
  4.    it under the terms of the GNU General Public License as published by
  5.    the Free Software Foundation; either version 2 of the License, or
  6.    (at your option) any later version.
  7.    
  8.    This program is distributed in the hope that it will be useful,
  9.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  10.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  11.    GNU General Public License for more details.
  12.    
  13.    You should have received a copy of the GNU General Public License
  14.    along with this program; if not, write to the Free Software
  15.    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
  16.  
  17.     /* Functions to compressed records */
  18.  
  19. #include "myisamdef.h"
  20.  
  21. #define IS_CHAR ((uint) 32768)        /* Bit if char (not offset) in tree */
  22.  
  23. #if INT_MAX > 65536L
  24. #define BITS_SAVED 32
  25. #define MAX_QUICK_TABLE_BITS 9        /* Because we may shift in 24 bits */
  26. #else
  27. #define BITS_SAVED 16
  28. #define MAX_QUICK_TABLE_BITS 6
  29. #endif
  30.  
  31. #define get_bit(BU) ((BU)->bits ? \
  32.              (BU)->current_byte & ((mi_bit_type) 1 << --(BU)->bits) :\
  33.              (fill_buffer(BU), (BU)->bits= BITS_SAVED-1,\
  34.               (BU)->current_byte & ((mi_bit_type) 1 << (BITS_SAVED-1))))
  35. #define skipp_to_next_byte(BU) ((BU)->bits&=~7)
  36. #define get_bits(BU,count) (((BU)->bits >= count) ? (((BU)->current_byte >> ((BU)->bits-=count)) & mask[count]) : fill_and_get_bits(BU,count))
  37.  
  38. #define decode_bytes_test_bit(bit) \
  39.   if (low_byte & (1 << (7-bit))) \
  40.     pos++; \
  41.   if (*pos & IS_CHAR) \
  42.   { bits-=(bit+1); break; } \
  43.   pos+= *pos
  44.  
  45.  
  46. static void read_huff_table(MI_BIT_BUFF *bit_buff,MI_DECODE_TREE *decode_tree,
  47.                 uint16 **decode_table,byte **intervall_buff,
  48.                 uint16 *tmp_buff);
  49. static void make_quick_table(uint16 *to_table,uint16 *decode_table,
  50.                  uint *next_free,uint value,uint bits,
  51.                  uint max_bits);
  52. static void fill_quick_table(uint16 *table,uint bits, uint max_bits,
  53.                  uint value);
  54. static uint copy_decode_table(uint16 *to_pos,uint offset,
  55.                   uint16 *decode_table);
  56. static uint find_longest_bitstream(uint16 *table);
  57. static void (*get_unpack_function(MI_COLUMNDEF *rec))(MI_COLUMNDEF *field,
  58.                             MI_BIT_BUFF *buff,
  59.                             uchar *to,
  60.                             uchar *end);
  61. static void uf_zerofill_skipp_zero(MI_COLUMNDEF *rec,MI_BIT_BUFF *bit_buff,
  62.                    uchar *to,uchar *end);
  63. static void uf_skipp_zero(MI_COLUMNDEF *rec,MI_BIT_BUFF *bit_buff,
  64.               uchar *to,uchar *end);
  65. static void uf_space_normal(MI_COLUMNDEF *rec,MI_BIT_BUFF *bit_buff,
  66.                 uchar *to,uchar *end);
  67. static void uf_space_endspace_selected(MI_COLUMNDEF *rec,MI_BIT_BUFF *bit_buff,
  68.                        uchar *to, uchar *end);
  69. static void uf_endspace_selected(MI_COLUMNDEF *rec,MI_BIT_BUFF *bit_buff,
  70.                  uchar *to,uchar *end);
  71. static void uf_space_endspace(MI_COLUMNDEF *rec,MI_BIT_BUFF *bit_buff,
  72.                   uchar *to,uchar *end);
  73. static void uf_endspace(MI_COLUMNDEF *rec,MI_BIT_BUFF *bit_buff,
  74.             uchar *to,uchar *end);
  75. static void uf_space_prespace_selected(MI_COLUMNDEF *rec,MI_BIT_BUFF *bit_buff,
  76.                        uchar *to, uchar *end);
  77. static void uf_prespace_selected(MI_COLUMNDEF *rec,MI_BIT_BUFF *bit_buff,
  78.                  uchar *to,uchar *end);
  79. static void uf_space_prespace(MI_COLUMNDEF *rec,MI_BIT_BUFF *bit_buff,
  80.                   uchar *to,uchar *end);
  81. static void uf_prespace(MI_COLUMNDEF *rec,MI_BIT_BUFF *bit_buff,
  82.             uchar *to,uchar *end);
  83. static void uf_zerofill_normal(MI_COLUMNDEF *rec,MI_BIT_BUFF *bit_buff,
  84.                    uchar *to,uchar *end);
  85. static void uf_constant(MI_COLUMNDEF *rec,MI_BIT_BUFF *bit_buff,
  86.             uchar *to,uchar *end);
  87. static void uf_intervall(MI_COLUMNDEF *rec,MI_BIT_BUFF *bit_buff,
  88.              uchar *to,uchar *end);
  89. static void uf_zero(MI_COLUMNDEF *rec,MI_BIT_BUFF *bit_buff,
  90.             uchar *to,uchar *end);
  91. static void uf_blob(MI_COLUMNDEF *rec, MI_BIT_BUFF *bit_buff,
  92.             uchar *to, uchar *end);
  93. static void uf_varchar(MI_COLUMNDEF *rec, MI_BIT_BUFF *bit_buff,
  94.                uchar *to, uchar *end);
  95. static void decode_bytes(MI_COLUMNDEF *rec,MI_BIT_BUFF *bit_buff,
  96.              uchar *to,uchar *end);
  97. static uint decode_pos(MI_BIT_BUFF *bit_buff,MI_DECODE_TREE *decode_tree);
  98. static void init_bit_buffer(MI_BIT_BUFF *bit_buff,uchar *buffer,uint length);
  99. static uint fill_and_get_bits(MI_BIT_BUFF *bit_buff,uint count);
  100. static void fill_buffer(MI_BIT_BUFF *bit_buff);
  101. static uint max_bit(uint value);
  102. #ifdef HAVE_MMAP
  103. static uchar *_mi_mempack_get_block_info(MI_INFO *myisam,MI_BLOCK_INFO *info,
  104.                      uchar *header);
  105. #endif
  106.  
  107. static mi_bit_type mask[]=
  108. {
  109.    0x00000000,
  110.    0x00000001, 0x00000003, 0x00000007, 0x0000000f,
  111.    0x0000001f, 0x0000003f, 0x0000007f, 0x000000ff,
  112.    0x000001ff, 0x000003ff, 0x000007ff, 0x00000fff,
  113.    0x00001fff, 0x00003fff, 0x00007fff, 0x0000ffff,
  114. #if BITS_SAVED > 16
  115.    0x0001ffff, 0x0003ffff, 0x0007ffff, 0x000fffff,
  116.    0x001fffff, 0x003fffff, 0x007fffff, 0x00ffffff,
  117.    0x01ffffff, 0x03ffffff, 0x07ffffff, 0x0fffffff,
  118.    0x1fffffff, 0x3fffffff, 0x7fffffff, 0xffffffff,
  119. #endif
  120.  };
  121.  
  122.  
  123.     /* Read all packed info, allocate memory and fix field structs */
  124.  
  125. my_bool _mi_read_pack_info(MI_INFO *info, pbool fix_keys)
  126. {
  127.   File file;
  128.   int diff_length;
  129.   uint i,trees,huff_tree_bits,rec_reflength,length;
  130.   uint16 *decode_table,*tmp_buff;
  131.   ulong elements,intervall_length;
  132.   char *disk_cache,*intervall_buff;
  133.   uchar header[32];
  134.   MYISAM_SHARE *share=info->s;
  135.   MI_BIT_BUFF bit_buff;
  136.   DBUG_ENTER("_mi_read_pack_info");
  137.  
  138.   if (myisam_quick_table_bits < 4)
  139.     myisam_quick_table_bits=4;
  140.   else if (myisam_quick_table_bits > MAX_QUICK_TABLE_BITS)
  141.     myisam_quick_table_bits=MAX_QUICK_TABLE_BITS;
  142.  
  143.   file=info->dfile;
  144.   my_errno=0;
  145.   if (my_read(file,(byte*) header,sizeof(header),MYF(MY_NABP)))
  146.   {
  147.     if (!my_errno)
  148.       my_errno=HA_ERR_END_OF_FILE;
  149.     DBUG_RETURN(1);
  150.   }
  151.   if (memcmp((byte*) header,(byte*) myisam_pack_file_magic,4))
  152.   {
  153.     my_errno=HA_ERR_WRONG_IN_RECORD;
  154.     DBUG_RETURN(1);
  155.   }
  156.   share->pack.header_length=    uint4korr(header+4);
  157.   share->min_pack_length=(uint) uint4korr(header+8);
  158.   share->max_pack_length=(uint) uint4korr(header+12);
  159.   set_if_bigger(share->base.pack_reclength,share->max_pack_length);
  160.   elements=uint4korr(header+16);
  161.   intervall_length=uint4korr(header+20);
  162.   trees=uint2korr(header+24);
  163.   share->pack.ref_length=header[26];
  164.   rec_reflength=header[27];
  165.   diff_length=(int) rec_reflength - (int) share->base.rec_reflength;
  166.   if (fix_keys)
  167.     share->rec_reflength=rec_reflength;
  168.   share->base.min_block_length=share->min_pack_length+share->pack.ref_length;
  169.  
  170.   if (!(share->decode_trees=(MI_DECODE_TREE*)
  171.     my_malloc((uint) (trees*sizeof(MI_DECODE_TREE)+
  172.               intervall_length*sizeof(byte)),
  173.           MYF(MY_WME))))
  174.     DBUG_RETURN(1);
  175.   intervall_buff=(byte*) (share->decode_trees+trees);
  176.  
  177.   length=(uint) (elements*2+trees*(1 << myisam_quick_table_bits));
  178.   if (!(share->decode_tables=(uint16*)
  179.     my_malloc((length+512)*sizeof(uint16)+
  180.           (uint) (share->pack.header_length+7),
  181.           MYF(MY_WME | MY_ZEROFILL))))
  182.   {
  183.     my_free((gptr) share->decode_trees,MYF(0));
  184.     DBUG_RETURN(1);
  185.   }
  186.   tmp_buff=share->decode_tables+length;
  187.   disk_cache=(byte*) (tmp_buff+512);
  188.  
  189.   if (my_read(file,disk_cache,
  190.           (uint) (share->pack.header_length-sizeof(header)),
  191.           MYF(MY_NABP)))
  192.   {
  193.     my_free((gptr) share->decode_trees,MYF(0));
  194.     my_free((gptr) share->decode_tables,MYF(0));
  195.     DBUG_RETURN(1);
  196.   }
  197.  
  198.   huff_tree_bits=max_bit(trees ? trees-1 : 0);
  199.   init_bit_buffer(&bit_buff, (uchar*) disk_cache,
  200.           (uint) (share->pack.header_length-sizeof(header)));
  201.     /* Read new info for each field */
  202.   for (i=0 ; i < share->base.fields ; i++)
  203.   {
  204.     share->rec[i].base_type=(enum en_fieldtype) get_bits(&bit_buff,5);
  205.     share->rec[i].pack_type=(uint) get_bits(&bit_buff,6);
  206.     share->rec[i].space_length_bits=get_bits(&bit_buff,5);
  207.     share->rec[i].huff_tree=share->decode_trees+(uint) get_bits(&bit_buff,
  208.                                 huff_tree_bits);
  209.     share->rec[i].unpack=get_unpack_function(share->rec+i);
  210.   }
  211.   skipp_to_next_byte(&bit_buff);
  212.   decode_table=share->decode_tables;
  213.   for (i=0 ; i < trees ; i++)
  214.     read_huff_table(&bit_buff,share->decode_trees+i,&decode_table,
  215.             &intervall_buff,tmp_buff);
  216.   decode_table=(uint16*)
  217.     my_realloc((gptr) share->decode_tables,
  218.            (uint) ((byte*) decode_table - (byte*) share->decode_tables),
  219.            MYF(MY_HOLD_ON_ERROR));
  220.   {
  221.     long diff=PTR_BYTE_DIFF(decode_table,share->decode_tables);
  222.     share->decode_tables=decode_table;
  223.     for (i=0 ; i < trees ; i++)
  224.       share->decode_trees[i].table=ADD_TO_PTR(share->decode_trees[i].table,
  225.                           diff,
  226.                           uint16*);
  227.   }
  228.  
  229.     /* Fix record-ref-length for keys */
  230.   if (fix_keys)
  231.   {
  232.     for (i=0 ; i < share->base.keys ; i++)
  233.     {
  234.       share->keyinfo[i].keylength+=(uint16) diff_length;
  235.       share->keyinfo[i].minlength+=(uint16) diff_length;
  236.       share->keyinfo[i].maxlength+=(uint16) diff_length;
  237.       share->keyinfo[i].seg[share->keyinfo[i].keysegs].length=
  238.     (uint16) rec_reflength;
  239.     }
  240.   }
  241.  
  242.   if (bit_buff.error || bit_buff.pos < bit_buff.end)
  243.   {                    /* info_length was wrong */
  244.     my_errno=HA_ERR_WRONG_IN_RECORD;
  245.     my_free((gptr) share->decode_trees,MYF(0));
  246.     my_free((gptr) share->decode_tables,MYF(0));
  247.     DBUG_RETURN(1);
  248.   }
  249.   DBUG_RETURN(0);
  250. }
  251.  
  252.  
  253.     /* Read on huff-code-table from datafile */
  254.  
  255. static void read_huff_table(MI_BIT_BUFF *bit_buff, MI_DECODE_TREE *decode_tree,
  256.                 uint16 **decode_table, byte **intervall_buff,
  257.                 uint16 *tmp_buff)
  258. {
  259.   uint min_chr,elements,char_bits,offset_bits,size,intervall_length,table_bits,
  260.   next_free_offset;
  261.   uint16 *ptr,*end;
  262.  
  263.   LINT_INIT(ptr);
  264.   if (!get_bits(bit_buff,1))
  265.   {
  266.     min_chr=get_bits(bit_buff,8);
  267.     elements=get_bits(bit_buff,9);
  268.     char_bits=get_bits(bit_buff,5);
  269.     offset_bits=get_bits(bit_buff,5);
  270.     intervall_length=0;
  271.     ptr=tmp_buff;
  272.   }
  273.   else
  274.   {
  275.     min_chr=0;
  276.     elements=get_bits(bit_buff,15);
  277.     intervall_length=get_bits(bit_buff,16);
  278.     char_bits=get_bits(bit_buff,5);
  279.     offset_bits=get_bits(bit_buff,5);
  280.     decode_tree->quick_table_bits=0;
  281.     ptr= *decode_table;
  282.   }
  283.   size=elements*2-2;
  284.  
  285.   for (end=ptr+size ; ptr < end ; ptr++)
  286.   {
  287.     if (get_bit(bit_buff))
  288.       *ptr= (uint16) get_bits(bit_buff,offset_bits);
  289.     else
  290.       *ptr= (uint16) (IS_CHAR + (get_bits(bit_buff,char_bits) + min_chr));
  291.   }
  292.   skipp_to_next_byte(bit_buff);
  293.  
  294.   decode_tree->table= *decode_table;
  295.   decode_tree->intervalls= *intervall_buff;
  296.   if (! intervall_length)
  297.   {
  298.     table_bits=find_longest_bitstream(tmp_buff);
  299.     if (table_bits > myisam_quick_table_bits)
  300.       table_bits=myisam_quick_table_bits;
  301.     next_free_offset= (1 << table_bits);
  302.     make_quick_table(*decode_table,tmp_buff,&next_free_offset,0,table_bits,
  303.              table_bits);
  304.     (*decode_table)+= next_free_offset;
  305.     decode_tree->quick_table_bits=table_bits;
  306.   }
  307.   else
  308.   {
  309.     (*decode_table)=end;
  310.     bit_buff->pos-= bit_buff->bits/8;
  311.     memcpy(*intervall_buff,bit_buff->pos,(size_t) intervall_length);
  312.     (*intervall_buff)+=intervall_length;
  313.     bit_buff->pos+=intervall_length;
  314.     bit_buff->bits=0;
  315.   }
  316.   return;
  317. }
  318.  
  319.  
  320. static void make_quick_table(uint16 *to_table, uint16 *decode_table,
  321.                  uint *next_free_offset, uint value, uint bits,
  322.                  uint max_bits)
  323. {
  324.   if (!bits--)
  325.   {
  326.     to_table[value]= (uint16) *next_free_offset;
  327.     *next_free_offset=copy_decode_table(to_table, *next_free_offset,
  328.                     decode_table);
  329.     return;
  330.   }
  331.   if (!(*decode_table & IS_CHAR))
  332.   {
  333.     make_quick_table(to_table,decode_table+ *decode_table,
  334.              next_free_offset,value,bits,max_bits);
  335.   }
  336.   else
  337.     fill_quick_table(to_table+value,bits,max_bits,(uint) *decode_table);
  338.   decode_table++;
  339.   value|= (1 << bits);
  340.   if (!(*decode_table & IS_CHAR))
  341.   {
  342.     make_quick_table(to_table,decode_table+ *decode_table,
  343.              next_free_offset,value,bits,max_bits);
  344.   }
  345.   else
  346.     fill_quick_table(to_table+value,bits,max_bits,(uint) *decode_table);
  347.   return;
  348. }
  349.  
  350.  
  351. static void fill_quick_table(uint16 *table, uint bits, uint max_bits,
  352.                  uint value)
  353. {
  354.   uint16 *end;
  355.   value|=(max_bits-bits) << 8;
  356.   for (end=table+ (1 << bits) ;
  357.        table < end ;
  358.        *table++ = (uint16) value | IS_CHAR) ;
  359. }
  360.  
  361.  
  362. static uint copy_decode_table(uint16 *to_pos, uint offset,
  363.                   uint16 *decode_table)
  364. {
  365.   uint prev_offset;
  366.   prev_offset= offset;
  367.  
  368.   if (!(*decode_table & IS_CHAR))
  369.   {
  370.     to_pos[offset]=2;
  371.     offset=copy_decode_table(to_pos,offset+2,decode_table+ *decode_table);
  372.   }
  373.   else
  374.   {
  375.     to_pos[offset]= *decode_table;
  376.     offset+=2;
  377.   }
  378.   decode_table++;
  379.  
  380.   if (!(*decode_table & IS_CHAR))
  381.   {
  382.     to_pos[prev_offset+1]=(uint16) (offset-prev_offset-1);
  383.     offset=copy_decode_table(to_pos,offset,decode_table+ *decode_table);
  384.   }
  385.   else
  386.     to_pos[prev_offset+1]= *decode_table;
  387.   return offset;
  388. }
  389.  
  390.  
  391. static uint find_longest_bitstream(uint16 *table)
  392. {
  393.   uint length=1,length2;
  394.   if (!(*table & IS_CHAR))
  395.     length=find_longest_bitstream(table+ *table)+1;
  396.   table++;
  397.   if (!(*table & IS_CHAR))
  398.   {
  399.     length2=find_longest_bitstream(table+ *table)+1;
  400.     length=max(length,length2);
  401.   }
  402.   return length;
  403. }
  404.  
  405.  
  406.     /* Read record from datafile */
  407.     /* Returns length of packed record, -1 if error */
  408.  
  409. int _mi_read_pack_record(MI_INFO *info, my_off_t filepos, byte *buf)
  410. {
  411.   MI_BLOCK_INFO block_info;
  412.   File file;
  413.   DBUG_ENTER("mi_read_pack_record");
  414.  
  415.   if (filepos == HA_OFFSET_ERROR)
  416.     DBUG_RETURN(-1);            /* _search() didn't find record */
  417.  
  418.   file=info->dfile;
  419.   if (_mi_pack_get_block_info(info, &block_info, file, filepos,
  420.                   info->rec_buff))
  421.     goto err;
  422.   if (my_read(file,(byte*) info->rec_buff + block_info.offset ,
  423.           block_info.rec_len - block_info.offset, MYF(MY_NABP)))
  424.     goto panic;
  425.   info->update|= HA_STATE_AKTIV;
  426.   DBUG_RETURN(_mi_pack_rec_unpack(info,buf,info->rec_buff,block_info.rec_len));
  427. panic:
  428.   my_errno=HA_ERR_WRONG_IN_RECORD;
  429. err:
  430.   DBUG_RETURN(-1);
  431. }
  432.  
  433.  
  434.  
  435. int _mi_pack_rec_unpack(register MI_INFO *info, register byte *to, byte *from,
  436.             ulong reclength)
  437. {
  438.   byte *end_field;
  439.   reg3 MI_COLUMNDEF *end;
  440.   MI_COLUMNDEF *current_field;
  441.   MYISAM_SHARE *share=info->s;
  442.   DBUG_ENTER("_mi_pack_rec_unpack");
  443.  
  444.   init_bit_buffer(&info->bit_buff, (uchar*) from,reclength);
  445.  
  446.   for (current_field=share->rec, end=current_field+share->base.fields ;
  447.        current_field < end ;
  448.        current_field++,to=end_field)
  449.   {
  450.     end_field=to+current_field->length;
  451.     (*current_field->unpack)(current_field,&info->bit_buff,(uchar*) to,
  452.                  (uchar*) end_field);
  453.   }
  454.   if (! info->bit_buff.error &&
  455.       info->bit_buff.pos - info->bit_buff.bits/8 == info->bit_buff.end)
  456.     DBUG_RETURN(0);
  457.   info->update&= ~HA_STATE_AKTIV;
  458.   DBUG_RETURN(my_errno=HA_ERR_WRONG_IN_RECORD);
  459. } /* _mi_pack_rec_unpack */
  460.  
  461.  
  462.     /* Return function to unpack field */
  463.  
  464. static void (*get_unpack_function(MI_COLUMNDEF *rec))
  465. (MI_COLUMNDEF *, MI_BIT_BUFF *, uchar *, uchar *)
  466. {
  467.   switch (rec->base_type) {
  468.   case FIELD_SKIPP_ZERO:
  469.     if (rec->pack_type & PACK_TYPE_ZERO_FILL)
  470.       return &uf_zerofill_skipp_zero;
  471.     return &uf_skipp_zero;
  472.   case FIELD_NORMAL:
  473.     if (rec->pack_type & PACK_TYPE_SPACE_FIELDS)
  474.       return &uf_space_normal;
  475.     if (rec->pack_type & PACK_TYPE_ZERO_FILL)
  476.       return &uf_zerofill_normal;
  477.     return &decode_bytes;
  478.   case FIELD_SKIPP_ENDSPACE:
  479.     if (rec->pack_type & PACK_TYPE_SPACE_FIELDS)
  480.     {
  481.       if (rec->pack_type & PACK_TYPE_SELECTED)
  482.     return &uf_space_endspace_selected;
  483.       return &uf_space_endspace;
  484.     }
  485.     if (rec->pack_type & PACK_TYPE_SELECTED)
  486.       return &uf_endspace_selected;
  487.     return &uf_endspace;
  488.   case FIELD_SKIPP_PRESPACE:
  489.     if (rec->pack_type & PACK_TYPE_SPACE_FIELDS)
  490.     {
  491.       if (rec->pack_type & PACK_TYPE_SELECTED)
  492.     return &uf_space_prespace_selected;
  493.       return &uf_space_prespace;
  494.     }
  495.     if (rec->pack_type & PACK_TYPE_SELECTED)
  496.       return &uf_prespace_selected;
  497.     return &uf_prespace;
  498.   case FIELD_CONSTANT:
  499.     return &uf_constant;
  500.   case FIELD_INTERVALL:
  501.     return &uf_intervall;
  502.   case FIELD_ZERO:
  503.   case FIELD_CHECK:
  504.     return &uf_zero;
  505.   case FIELD_BLOB:
  506.     return &uf_blob;
  507.   case FIELD_VARCHAR:
  508.     return &uf_varchar;
  509.   case FIELD_LAST:
  510.   default:
  511.     return 0;            /* This should never happend */
  512.   }
  513. }
  514.  
  515.     /* De different functions to unpack a field */
  516.  
  517. static void uf_zerofill_skipp_zero(MI_COLUMNDEF *rec, MI_BIT_BUFF *bit_buff,
  518.                    uchar *to, uchar *end)
  519. {
  520.   if (get_bit(bit_buff))
  521.     bzero((char*) to,(uint) (end-to));
  522.   else
  523.   {
  524.     end-=rec->space_length_bits;
  525.     decode_bytes(rec,bit_buff,to,end);
  526.     bzero((char*) end,rec->space_length_bits);
  527.   }
  528. }
  529.  
  530. static void uf_skipp_zero(MI_COLUMNDEF *rec, MI_BIT_BUFF *bit_buff, uchar *to,
  531.               uchar *end)
  532. {
  533.   if (get_bit(bit_buff))
  534.     bzero((char*) to,(uint) (end-to));
  535.   else
  536.     decode_bytes(rec,bit_buff,to,end);
  537. }
  538.  
  539. static void uf_space_normal(MI_COLUMNDEF *rec, MI_BIT_BUFF *bit_buff, uchar *to,
  540.                 uchar *end)
  541. {
  542.   if (get_bit(bit_buff))
  543.     bfill((byte*) to,(end-to),' ');
  544.   else
  545.     decode_bytes(rec,bit_buff,to,end);
  546. }
  547.  
  548. static void uf_space_endspace_selected(MI_COLUMNDEF *rec, MI_BIT_BUFF *bit_buff,
  549.                        uchar *to, uchar *end)
  550. {
  551.   uint spaces;
  552.   if (get_bit(bit_buff))
  553.     bfill((byte*) to,(end-to),' ');
  554.   else
  555.   {
  556.     if (get_bit(bit_buff))
  557.     {
  558.       if ((spaces=get_bits(bit_buff,rec->space_length_bits))+to > end)
  559.       {
  560.     bit_buff->error=1;
  561.     return;
  562.       }
  563.       if (to+spaces != end)
  564.     decode_bytes(rec,bit_buff,to,end-spaces);
  565.       bfill((byte*) end-spaces,spaces,' ');
  566.     }
  567.     else
  568.       decode_bytes(rec,bit_buff,to,end);
  569.   }
  570. }
  571.  
  572. static void uf_endspace_selected(MI_COLUMNDEF *rec, MI_BIT_BUFF *bit_buff,
  573.                  uchar *to, uchar *end)
  574. {
  575.   uint spaces;
  576.   if (get_bit(bit_buff))
  577.   {
  578.     if ((spaces=get_bits(bit_buff,rec->space_length_bits))+to > end)
  579.     {
  580.       bit_buff->error=1;
  581.       return;
  582.     }
  583.     if (to+spaces != end)
  584.       decode_bytes(rec,bit_buff,to,end-spaces);
  585.     bfill((byte*) end-spaces,spaces,' ');
  586.   }
  587.   else
  588.     decode_bytes(rec,bit_buff,to,end);
  589. }
  590.  
  591. static void uf_space_endspace(MI_COLUMNDEF *rec, MI_BIT_BUFF *bit_buff, uchar *to,
  592.                   uchar *end)
  593. {
  594.   uint spaces;
  595.   if (get_bit(bit_buff))
  596.     bfill((byte*) to,(end-to),' ');
  597.   else
  598.   {
  599.     if ((spaces=get_bits(bit_buff,rec->space_length_bits))+to > end)
  600.     {
  601.       bit_buff->error=1;
  602.       return;
  603.     }
  604.     if (to+spaces != end)
  605.       decode_bytes(rec,bit_buff,to,end-spaces);
  606.     bfill((byte*) end-spaces,spaces,' ');
  607.   }
  608. }
  609.  
  610. static void uf_endspace(MI_COLUMNDEF *rec, MI_BIT_BUFF *bit_buff, uchar *to,
  611.             uchar *end)
  612. {
  613.   uint spaces;
  614.   if ((spaces=get_bits(bit_buff,rec->space_length_bits))+to > end)
  615.   {
  616.     bit_buff->error=1;
  617.     return;
  618.   }
  619.   if (to+spaces != end)
  620.     decode_bytes(rec,bit_buff,to,end-spaces);
  621.   bfill((byte*) end-spaces,spaces,' ');
  622. }
  623.  
  624. static void uf_space_prespace_selected(MI_COLUMNDEF *rec, MI_BIT_BUFF *bit_buff,
  625.                        uchar *to, uchar *end)
  626. {
  627.   uint spaces;
  628.   if (get_bit(bit_buff))
  629.     bfill((byte*) to,(end-to),' ');
  630.   else
  631.   {
  632.     if (get_bit(bit_buff))
  633.     {
  634.       if ((spaces=get_bits(bit_buff,rec->space_length_bits))+to > end)
  635.       {
  636.     bit_buff->error=1;
  637.     return;
  638.       }
  639.       bfill((byte*) to,spaces,' ');
  640.       if (to+spaces != end)
  641.     decode_bytes(rec,bit_buff,to+spaces,end);
  642.     }
  643.     else
  644.       decode_bytes(rec,bit_buff,to,end);
  645.   }
  646. }
  647.  
  648.  
  649. static void uf_prespace_selected(MI_COLUMNDEF *rec, MI_BIT_BUFF *bit_buff,
  650.                  uchar *to, uchar *end)
  651. {
  652.   uint spaces;
  653.   if (get_bit(bit_buff))
  654.   {
  655.     if ((spaces=get_bits(bit_buff,rec->space_length_bits))+to > end)
  656.     {
  657.       bit_buff->error=1;
  658.       return;
  659.     }
  660.     bfill((byte*) to,spaces,' ');
  661.     if (to+spaces != end)
  662.       decode_bytes(rec,bit_buff,to+spaces,end);
  663.   }
  664.   else
  665.     decode_bytes(rec,bit_buff,to,end);
  666. }
  667.  
  668.  
  669. static void uf_space_prespace(MI_COLUMNDEF *rec, MI_BIT_BUFF *bit_buff, uchar *to,
  670.                   uchar *end)
  671. {
  672.   uint spaces;
  673.   if (get_bit(bit_buff))
  674.     bfill((byte*) to,(end-to),' ');
  675.   else
  676.   {
  677.     if ((spaces=get_bits(bit_buff,rec->space_length_bits))+to > end)
  678.     {
  679.       bit_buff->error=1;
  680.       return;
  681.     }
  682.     bfill((byte*) to,spaces,' ');
  683.     if (to+spaces != end)
  684.       decode_bytes(rec,bit_buff,to+spaces,end);
  685.   }
  686. }
  687.  
  688. static void uf_prespace(MI_COLUMNDEF *rec, MI_BIT_BUFF *bit_buff, uchar *to,
  689.             uchar *end)
  690. {
  691.   uint spaces;
  692.   if ((spaces=get_bits(bit_buff,rec->space_length_bits))+to > end)
  693.   {
  694.     bit_buff->error=1;
  695.     return;
  696.   }
  697.   bfill((byte*) to,spaces,' ');
  698.   if (to+spaces != end)
  699.     decode_bytes(rec,bit_buff,to+spaces,end);
  700. }
  701.  
  702. static void uf_zerofill_normal(MI_COLUMNDEF *rec, MI_BIT_BUFF *bit_buff, uchar *to,
  703.                    uchar *end)
  704. {
  705.   end-=rec->space_length_bits;
  706.   decode_bytes(rec,bit_buff,(uchar*) to,end);
  707.   bzero((char*) end,rec->space_length_bits);
  708. }
  709.  
  710. static void uf_constant(MI_COLUMNDEF *rec,
  711.             MI_BIT_BUFF *bit_buff __attribute__((unused)),
  712.             uchar *to,
  713.             uchar *end)
  714. {
  715.   memcpy(to,rec->huff_tree->intervalls,(size_t) (end-to));
  716. }
  717.  
  718. static void uf_intervall(MI_COLUMNDEF *rec, MI_BIT_BUFF *bit_buff, uchar *to,
  719.              uchar *end)
  720. {
  721.   reg1 uint field_length=(uint) (end-to);
  722.   memcpy(to,rec->huff_tree->intervalls+field_length*decode_pos(bit_buff,
  723.                                    rec->huff_tree),
  724.      (size_t) field_length);
  725. }
  726.  
  727.  
  728. /*ARGSUSED*/
  729. static void uf_zero(MI_COLUMNDEF *rec __attribute__((unused)),
  730.             MI_BIT_BUFF *bit_buff __attribute__((unused)),
  731.             uchar *to, uchar *end)
  732. {
  733.   bzero((char*) to,(uint) (end-to));
  734. }
  735.  
  736. static void uf_blob(MI_COLUMNDEF *rec, MI_BIT_BUFF *bit_buff,
  737.             uchar *to, uchar *end)
  738. {
  739.   if (get_bit(bit_buff))
  740.     bzero((byte*) to,(end-to));
  741.   else
  742.   {
  743.     ulong length=get_bits(bit_buff,rec->space_length_bits);
  744.     uint pack_length=(uint) (end-to)-mi_portable_sizeof_char_ptr;
  745.     decode_bytes(rec,bit_buff,bit_buff->blob_pos,bit_buff->blob_pos+length);
  746.     _my_store_blob_length((byte*) to,pack_length,length);
  747.     memcpy_fixed((char*) to+pack_length,(char*) &bit_buff->blob_pos,
  748.          sizeof(char*));
  749.     bit_buff->blob_pos+=length;
  750.   }
  751. }
  752.  
  753. static void uf_varchar(MI_COLUMNDEF *rec, MI_BIT_BUFF *bit_buff,
  754.                uchar *to, uchar *end __attribute__((unused)))
  755. {
  756.   if (get_bit(bit_buff))
  757.     to[0]=to[1]=0;                /* Zero lengths */
  758.   else
  759.   {
  760.     ulong length=get_bits(bit_buff,rec->space_length_bits);
  761.     int2store(to,length);
  762.     decode_bytes(rec,bit_buff,to+2,to+2+length);
  763.   }
  764. }
  765.  
  766.     /* Functions to decode of buffer of bits */
  767.  
  768. #if BITS_SAVED == 64
  769.  
  770. static void decode_bytes(MI_COLUMNDEF *rec,MI_BIT_BUFF *bit_buff,uchar *to,
  771.              uchar *end)
  772. {
  773.   reg1 uint bits,low_byte;
  774.   reg3 uint16 *pos;
  775.   reg4 uint table_bits,table_and;
  776.   MI_DECODE_TREE *decode_tree;
  777.  
  778.   decode_tree=rec->decode_tree;
  779.   bits=bit_buff->bits;            /* Save in reg for quicker access */
  780.   table_bits=decode_tree->quick_table_bits;
  781.   table_and= (1 << table_bits)-1;
  782.  
  783.   do
  784.   {
  785.     if (bits <= 32)
  786.     {
  787.       if (bit_buff->pos > bit_buff->end+4)
  788.     return;                /* Can't be right */
  789.       bit_buff->current_byte= (bit_buff->current_byte << 32) +
  790.     ((((uint) bit_buff->pos[3])) +
  791.      (((uint) bit_buff->pos[2]) << 8) +
  792.      (((uint) bit_buff->pos[1]) << 16) +
  793.      (((uint) bit_buff->pos[0]) << 24));
  794.       bit_buff->pos+=4;
  795.       bits+=32;
  796.     }
  797.     /* First use info in quick_table */
  798.     low_byte=(uint) (bit_buff->current_byte >> (bits - table_bits)) & table_and;
  799.     low_byte=decode_tree->table[low_byte];
  800.     if (low_byte & IS_CHAR)
  801.     {
  802.       *to++ = (low_byte & 255);        /* Found char in quick table */
  803.       bits-=  ((low_byte >> 8) & 31);    /* Remove bits used */
  804.     }
  805.     else
  806.     {                    /* Map through rest of decode-table */
  807.       pos=decode_tree->table+low_byte;
  808.       bits-=table_bits;
  809.       for (;;)
  810.       {
  811.     low_byte=(uint) (bit_buff->current_byte >> (bits-8));
  812.     decode_bytes_test_bit(0);
  813.     decode_bytes_test_bit(1);
  814.     decode_bytes_test_bit(2);
  815.     decode_bytes_test_bit(3);
  816.     decode_bytes_test_bit(4);
  817.     decode_bytes_test_bit(5);
  818.     decode_bytes_test_bit(6);
  819.     decode_bytes_test_bit(7);
  820.     bits-=8;
  821.       }
  822.       *to++ = *pos;
  823.     }
  824.   } while (to != end);
  825.  
  826.   bit_buff->bits=bits;
  827.   return;
  828. }
  829.  
  830. #else
  831.  
  832. static void decode_bytes(MI_COLUMNDEF *rec, MI_BIT_BUFF *bit_buff, uchar *to, uchar *end)
  833. {
  834.   reg1 uint bits,low_byte;
  835.   reg3 uint16 *pos;
  836.   reg4 uint table_bits,table_and;
  837.   MI_DECODE_TREE *decode_tree;
  838.  
  839.   decode_tree=rec->huff_tree;
  840.   bits=bit_buff->bits;            /* Save in reg for quicker access */
  841.   table_bits=decode_tree->quick_table_bits;
  842.   table_and= (1 << table_bits)-1;
  843.  
  844.   do
  845.   {
  846.     if (bits < table_bits)
  847.     {
  848.       if (bit_buff->pos > bit_buff->end+1)
  849.     return;                /* Can't be right */
  850. #if BITS_SAVED == 32
  851.       bit_buff->current_byte= (bit_buff->current_byte << 24) +
  852.     (((uint) ((uchar) bit_buff->pos[2]))) +
  853.       (((uint) ((uchar) bit_buff->pos[1])) << 8) +
  854.         (((uint) ((uchar) bit_buff->pos[0])) << 16);
  855.       bit_buff->pos+=3;
  856.       bits+=24;
  857. #else
  858.       if (bits)                /* We must have at leasts 9 bits */
  859.       {
  860.     bit_buff->current_byte=  (bit_buff->current_byte << 8) +
  861.       (uint) ((uchar) bit_buff->pos[0]);
  862.     bit_buff->pos++;
  863.     bits+=8;
  864.       }
  865.       else
  866.       {
  867.     bit_buff->current_byte= ((uint) ((uchar) bit_buff->pos[0]) << 8) +
  868.       ((uint) ((uchar) bit_buff->pos[1]));
  869.     bit_buff->pos+=2;
  870.     bits+=16;
  871.       }
  872. #endif
  873.     }
  874.     /* First use info in quick_table */
  875.     low_byte=(bit_buff->current_byte >> (bits - table_bits)) & table_and;
  876.     low_byte=decode_tree->table[low_byte];
  877.     if (low_byte & IS_CHAR)
  878.     {
  879.       *to++ = (low_byte & 255);        /* Found char in quick table */
  880.       bits-=  ((low_byte >> 8) & 31);    /* Remove bits used */
  881.     }
  882.     else
  883.     {                    /* Map through rest of decode-table */
  884.       pos=decode_tree->table+low_byte;
  885.       bits-=table_bits;
  886.       for (;;)
  887.       {
  888.     if (bits < 8)
  889.     {                /* We don't need to check end */
  890. #if BITS_SAVED == 32
  891.       bit_buff->current_byte= (bit_buff->current_byte << 24) +
  892.         (((uint) ((uchar) bit_buff->pos[2]))) +
  893.           (((uint) ((uchar) bit_buff->pos[1])) << 8) +
  894.         (((uint) ((uchar) bit_buff->pos[0])) << 16);
  895.       bit_buff->pos+=3;
  896.       bits+=24;
  897. #else
  898.       bit_buff->current_byte=  (bit_buff->current_byte << 8) +
  899.         (uint) ((uchar) bit_buff->pos[0]);
  900.       bit_buff->pos+=1;
  901.       bits+=8;
  902. #endif
  903.     }
  904.     low_byte=(uint) (bit_buff->current_byte >> (bits-8));
  905.     decode_bytes_test_bit(0);
  906.     decode_bytes_test_bit(1);
  907.     decode_bytes_test_bit(2);
  908.     decode_bytes_test_bit(3);
  909.     decode_bytes_test_bit(4);
  910.     decode_bytes_test_bit(5);
  911.     decode_bytes_test_bit(6);
  912.     decode_bytes_test_bit(7);
  913.     bits-=8;
  914.       }
  915.       *to++ = (uchar) *pos;
  916.     }
  917.   } while (to != end);
  918.  
  919.   bit_buff->bits=bits;
  920.   return;
  921. }
  922. #endif /* BIT_SAVED == 64 */
  923.  
  924.  
  925. static uint decode_pos(MI_BIT_BUFF *bit_buff, MI_DECODE_TREE *decode_tree)
  926. {
  927.   uint16 *pos=decode_tree->table;
  928.   for (;;)
  929.   {
  930.     if (get_bit(bit_buff))
  931.       pos++;
  932.     if (*pos & IS_CHAR)
  933.       return (uint) (*pos & ~IS_CHAR);
  934.     pos+= *pos;
  935.   }
  936. }
  937.  
  938.  
  939. int _mi_read_rnd_pack_record(MI_INFO *info, byte *buf,
  940.                  register my_off_t filepos,
  941.                  my_bool skip_deleted_blocks)
  942. {
  943.   uint b_type;
  944.   MI_BLOCK_INFO block_info;
  945.   MYISAM_SHARE *share=info->s;
  946.   DBUG_ENTER("_mi_read_rnd_pack_record");
  947.  
  948.   if (filepos >= info->state->data_file_length)
  949.   {
  950.     my_errno= HA_ERR_END_OF_FILE;
  951.     goto err;
  952.   }
  953.  
  954.   if (info->opt_flag & READ_CACHE_USED)
  955.   {
  956.     if (_mi_read_cache(&info->rec_cache,(byte*) block_info.header,filepos,
  957.               share->pack.ref_length, skip_deleted_blocks))
  958.       goto err;
  959.     b_type=_mi_pack_get_block_info(info,&block_info,-1, filepos, NullS);
  960.   }
  961.   else
  962.     b_type=_mi_pack_get_block_info(info,&block_info,info->dfile,filepos,
  963.                    info->rec_buff);
  964.   if (b_type)
  965.     goto err;
  966. #ifndef DBUG_OFF
  967.   if (block_info.rec_len > share->max_pack_length)
  968.   {
  969.     my_errno=HA_ERR_WRONG_IN_RECORD;
  970.     goto err;
  971.   }
  972. #endif
  973.  
  974.   if (info->opt_flag & READ_CACHE_USED)
  975.   {
  976.     if (_mi_read_cache(&info->rec_cache,(byte*) info->rec_buff,
  977.               block_info.filepos, block_info.rec_len,
  978.               skip_deleted_blocks))
  979.       goto err;
  980.   }
  981.   else
  982.   {
  983.     if (my_read(info->dfile,(byte*) info->rec_buff + block_info.offset,
  984.         block_info.rec_len-block_info.offset,
  985.         MYF(MY_NABP)))
  986.       goto err;
  987.   }
  988.   info->packed_length=block_info.rec_len;
  989.   info->lastpos=filepos;
  990.   info->nextpos=block_info.filepos+block_info.rec_len;
  991.   info->update|= HA_STATE_AKTIV | HA_STATE_KEY_CHANGED;
  992.  
  993.   DBUG_RETURN (_mi_pack_rec_unpack(info,buf,info->rec_buff,
  994.                    block_info.rec_len));
  995.  err:
  996.   DBUG_RETURN(my_errno);
  997. }
  998.  
  999.  
  1000.     /* Read and process header from a huff-record-file */
  1001.  
  1002. uint _mi_pack_get_block_info(MI_INFO *myisam, MI_BLOCK_INFO *info, File file,
  1003.                  my_off_t filepos, char *rec_buff)
  1004. {
  1005.   uchar *header=info->header;
  1006.   uint head_length,ref_length;
  1007.   LINT_INIT(ref_length);
  1008.  
  1009.   if (file >= 0)
  1010.   {
  1011.     ref_length=myisam->s->pack.ref_length;
  1012.     /*
  1013.       We can't use my_pread() here because mi_rad_pack_record assumes
  1014.       position is ok
  1015.     */
  1016.     VOID(my_seek(file,filepos,MY_SEEK_SET,MYF(0)));
  1017.     if (my_read(file,(char*) header,ref_length,MYF(MY_NABP)))
  1018.       return BLOCK_FATAL_ERROR;
  1019.     DBUG_DUMP("header",(byte*) header,ref_length);
  1020.   }
  1021.   if (header[0] < 254)
  1022.   {
  1023.     info->rec_len=header[0];
  1024.     head_length=1;
  1025.   }
  1026.   else if (header[0] == 254)
  1027.   {
  1028.     info->rec_len=uint2korr(header+1);
  1029.     head_length=3;
  1030.   }
  1031.   else
  1032.   {
  1033.     info->rec_len=uint3korr(header+1);
  1034.     head_length=4;
  1035.   }
  1036.   if (myisam->s->base.blobs)
  1037.   {
  1038.     if (header[head_length] < 254)
  1039.     {
  1040.       info->blob_len=header[head_length];
  1041.       head_length++;
  1042.     }
  1043.     else if (header[head_length] == 254)
  1044.     {
  1045.       info->blob_len=uint2korr(header+head_length+1);
  1046.       head_length+=3;
  1047.     }
  1048.     else
  1049.     {
  1050.       info->blob_len=uint3korr(header+head_length+1);
  1051.       head_length+=4;
  1052.     }
  1053.     if (!(mi_fix_rec_buff_for_blob(myisam,info->rec_len + info->blob_len)))
  1054.       return BLOCK_FATAL_ERROR;            /* not enough memory */
  1055.     myisam->bit_buff.blob_pos=(uchar*) myisam->rec_buff+info->rec_len;
  1056.     myisam->blob_length=info->blob_len;
  1057.   }
  1058.   info->filepos=filepos+head_length;
  1059.   if (file > 0)
  1060.   {
  1061.     info->offset=min(info->rec_len, ref_length - head_length);
  1062.     memcpy(rec_buff, header+head_length, info->offset);
  1063.   }
  1064.   return 0;
  1065. }
  1066.  
  1067.  
  1068.     /* rutines for bit buffer */
  1069.     /* Note buffer must be 6 byte bigger than longest row */
  1070.  
  1071. static void init_bit_buffer(MI_BIT_BUFF *bit_buff, uchar *buffer, uint length)
  1072. {
  1073.   bit_buff->pos=buffer;
  1074.   bit_buff->end=buffer+length;
  1075.   bit_buff->bits=bit_buff->error=0;
  1076.   bit_buff->current_byte=0;            /* Avoid purify errors */
  1077. }
  1078.  
  1079. static uint fill_and_get_bits(MI_BIT_BUFF *bit_buff, uint count)
  1080. {
  1081.   uint tmp;
  1082.   count-=bit_buff->bits;
  1083.   tmp=(bit_buff->current_byte & mask[bit_buff->bits]) << count;
  1084.   fill_buffer(bit_buff);
  1085.   bit_buff->bits=BITS_SAVED - count;
  1086.   return tmp+(bit_buff->current_byte >> (BITS_SAVED - count));
  1087. }
  1088.  
  1089.     /* Fill in empty bit_buff->current_byte from buffer */
  1090.     /* Sets bit_buff->error if buffer is exhausted */
  1091.  
  1092. static void fill_buffer(MI_BIT_BUFF *bit_buff)
  1093. {
  1094.   if (bit_buff->pos >= bit_buff->end)
  1095.   {
  1096.     bit_buff->error= 1;
  1097.     bit_buff->current_byte=0;
  1098.     return;
  1099.   }
  1100. #if BITS_SAVED == 64
  1101.   bit_buff->current_byte=  ((((uint) ((uchar) bit_buff->pos[7]))) +
  1102.                  (((uint) ((uchar) bit_buff->pos[6])) << 8) +
  1103.                  (((uint) ((uchar) bit_buff->pos[5])) << 16) +
  1104.                  (((uint) ((uchar) bit_buff->pos[4])) << 24) +
  1105.                  ((ulonglong)
  1106.                   ((((uint) ((uchar) bit_buff->pos[3]))) +
  1107.                    (((uint) ((uchar) bit_buff->pos[2])) << 8) +
  1108.                    (((uint) ((uchar) bit_buff->pos[1])) << 16) +
  1109.                    (((uint) ((uchar) bit_buff->pos[0])) << 24)) << 32));
  1110.   bit_buff->pos+=8;
  1111. #else
  1112. #if BITS_SAVED == 32
  1113.   bit_buff->current_byte=  (((uint) ((uchar) bit_buff->pos[3])) +
  1114.                  (((uint) ((uchar) bit_buff->pos[2])) << 8) +
  1115.                  (((uint) ((uchar) bit_buff->pos[1])) << 16) +
  1116.                  (((uint) ((uchar) bit_buff->pos[0])) << 24));
  1117.   bit_buff->pos+=4;
  1118. #else
  1119.   bit_buff->current_byte=  (uint) (((uint) ((uchar) bit_buff->pos[1]))+
  1120.                     (((uint) ((uchar) bit_buff->pos[0])) << 8));
  1121.   bit_buff->pos+=2;
  1122. #endif
  1123. #endif
  1124. }
  1125.  
  1126.     /* Get number of bits neaded to represent value */
  1127.  
  1128. static uint max_bit(register uint value)
  1129. {
  1130.   reg2 uint power=1;
  1131.  
  1132.   while ((value>>=1))
  1133.     power++;
  1134.   return (power);
  1135. }
  1136.  
  1137.  
  1138. /*****************************************************************************
  1139.     Some redefined functions to handle files when we are using memmap
  1140. *****************************************************************************/
  1141.  
  1142. #ifdef HAVE_MMAP
  1143.  
  1144. #include <sys/mman.h>
  1145.  
  1146. static int _mi_read_mempack_record(MI_INFO *info,my_off_t filepos,byte *buf);
  1147. static int _mi_read_rnd_mempack_record(MI_INFO*, byte *,my_off_t, my_bool);
  1148.  
  1149. #ifndef MAP_NORESERVE
  1150. #define MAP_NORESERVE 0        /* For irix */
  1151. #endif
  1152. #ifndef MAP_FAILED
  1153. #define MAP_FAILED -1
  1154. #endif
  1155.  
  1156. my_bool _mi_memmap_file(MI_INFO *info)
  1157. {
  1158.   byte *file_map;
  1159.   MYISAM_SHARE *share=info->s;
  1160.   DBUG_ENTER("mi_memmap_file");
  1161.  
  1162.   if (!info->s->file_map)
  1163.   {
  1164.     if (my_seek(info->dfile,0L,MY_SEEK_END,MYF(0)) <
  1165.     share->state.state.data_file_length+MEMMAP_EXTRA_MARGIN)
  1166.     {
  1167.       DBUG_PRINT("warning",("File isn't extended for memmap"));
  1168.       DBUG_RETURN(0);
  1169.     }
  1170.     file_map=(byte*)
  1171.       mmap(0,share->state.state.data_file_length+MEMMAP_EXTRA_MARGIN,PROT_READ,
  1172.        MAP_SHARED | MAP_NORESERVE,info->dfile,0L);
  1173.     if (file_map == (byte*) MAP_FAILED)
  1174.     {
  1175.       DBUG_PRINT("warning",("mmap failed: errno: %d",errno));
  1176.       my_errno=errno;
  1177.       DBUG_RETURN(0);
  1178.     }
  1179.     info->s->file_map=file_map;
  1180.   }
  1181.   info->opt_flag|= MEMMAP_USED;
  1182.   info->read_record=share->read_record=_mi_read_mempack_record;
  1183.   share->read_rnd=_mi_read_rnd_mempack_record;
  1184.   DBUG_RETURN(1);
  1185. }
  1186.  
  1187.  
  1188. void _mi_unmap_file(MI_INFO *info)
  1189. {
  1190.   VOID(munmap((caddr_t) info->s->file_map,
  1191.           (size_t) info->s->state.state.data_file_length+
  1192.           MEMMAP_EXTRA_MARGIN));
  1193. }
  1194.  
  1195.  
  1196. static uchar *_mi_mempack_get_block_info(MI_INFO *myisam,MI_BLOCK_INFO *info,
  1197.                      uchar *header)
  1198. {
  1199.   if (header[0] < 254)
  1200.     info->rec_len= *header++;
  1201.   else if (header[0] == 254)
  1202.   {
  1203.     info->rec_len=uint2korr(header+1);
  1204.     header+=3;
  1205.   }
  1206.   else
  1207.   {
  1208.     info->rec_len=uint3korr(header+1);
  1209.     header+=4;
  1210.   }
  1211.   if (myisam->s->base.blobs)
  1212.   {
  1213.     if (header[0] < 254)
  1214.     {
  1215.       info->blob_len= *header++;
  1216.     }
  1217.     else if (header[0] == 254)
  1218.     {
  1219.       info->blob_len=uint2korr(header+1);
  1220.       header+=3;
  1221.     }
  1222.     else
  1223.     {
  1224.       info->blob_len=uint3korr(header+1);
  1225.       header+=4;
  1226.     }
  1227.     /* mi_fix_rec_buff_for_blob sets my_errno on error */
  1228.     if (!(mi_fix_rec_buff_for_blob(myisam,info->blob_len)))
  1229.       return 0;                /* not enough memory */
  1230.     myisam->bit_buff.blob_pos=(uchar*) myisam->rec_buff;
  1231.   }
  1232.   return header;
  1233. }
  1234.  
  1235.  
  1236. static int _mi_read_mempack_record(MI_INFO *info, my_off_t filepos, byte *buf)
  1237. {
  1238.   MI_BLOCK_INFO block_info;
  1239.   MYISAM_SHARE *share=info->s;
  1240.   byte *pos;
  1241.   DBUG_ENTER("mi_read_mempack_record");
  1242.  
  1243.   if (filepos == HA_OFFSET_ERROR)
  1244.     DBUG_RETURN(-1);            /* _search() didn't find record */
  1245.  
  1246.   if (!(pos= (byte*) _mi_mempack_get_block_info(info,&block_info,
  1247.                         (uchar*) share->file_map+
  1248.                         filepos)))
  1249.     DBUG_RETURN(-1);
  1250.   DBUG_RETURN(_mi_pack_rec_unpack(info, buf, pos, block_info.rec_len));
  1251. }
  1252.  
  1253.  
  1254. /*ARGSUSED*/
  1255. static int _mi_read_rnd_mempack_record(MI_INFO *info, byte *buf,
  1256.                        register my_off_t filepos,
  1257.                        my_bool skip_deleted_blocks
  1258.                        __attribute__((unused)))
  1259. {
  1260.   MI_BLOCK_INFO block_info;
  1261.   MYISAM_SHARE *share=info->s;
  1262.   byte *pos,*start;
  1263.   DBUG_ENTER("_mi_read_rnd_mempack_record");
  1264.  
  1265.   if (filepos >= share->state.state.data_file_length)
  1266.   {
  1267.     my_errno=HA_ERR_END_OF_FILE;
  1268.     goto err;
  1269.   }
  1270.   if (!(pos= (byte*) _mi_mempack_get_block_info(info,&block_info,
  1271.                         (uchar*)
  1272.                         (start=share->file_map+
  1273.                          filepos))))
  1274.     goto err;
  1275. #ifndef DBUG_OFF
  1276.   if (block_info.rec_len > info->s->max_pack_length)
  1277.   {
  1278.     my_errno=HA_ERR_WRONG_IN_RECORD;
  1279.     goto err;
  1280.   }
  1281. #endif
  1282.   info->packed_length=block_info.rec_len;
  1283.   info->lastpos=filepos;
  1284.   info->nextpos=filepos+(uint) (pos-start)+block_info.rec_len;
  1285.   info->update|= HA_STATE_AKTIV | HA_STATE_KEY_CHANGED;
  1286.  
  1287.   DBUG_RETURN (_mi_pack_rec_unpack(info,buf,pos, block_info.rec_len));
  1288.  err:
  1289.   DBUG_RETURN(my_errno);
  1290. }
  1291.  
  1292. #endif /* HAVE_MMAP */
  1293.  
  1294.     /* Save length of row */
  1295.  
  1296. uint save_pack_length(byte *block_buff,ulong length)
  1297. {
  1298.   if (length < 254)
  1299.   {
  1300.     *(uchar*) block_buff= (uchar) length;
  1301.     return 1;
  1302.   }
  1303.   if (length <= 65535)
  1304.   {
  1305.     *(uchar*) block_buff=254;
  1306.     int2store(block_buff+1,(uint) length);
  1307.     return 3;
  1308.   }
  1309.   *(uchar*) block_buff=255;
  1310.   int3store(block_buff+1,(ulong) length);
  1311.   return 4;
  1312. }
  1313.