mi_packrec.c
上传用户:romrleung
上传日期:2022-05-23
资源大小:18897k
文件大小:36k
源码类别:

MySQL数据库

开发平台:

Visual C++

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