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

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 "isamdef.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 & ((bit_type) 1 << --(BU)->bits) :
  25.      (fill_buffer(BU), (BU)->bits= BITS_SAVED-1,
  26.       (BU)->current_byte & ((bit_type) 1 << (BITS_SAVED-1))))
  27. #define skipp_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.   static void read_huff_table(BIT_BUFF *bit_buff,DECODE_TREE *decode_tree,
  36.       uint16 **decode_table,byte **intervall_buff,
  37.       uint16 *tmp_buff);
  38. static void make_quick_table(uint16 *to_table,uint16 *decode_table,
  39.      uint *next_free,uint value,uint bits,
  40.      uint max_bits);
  41. static void fill_quick_table(uint16 *table,uint bits, uint max_bits,
  42.      uint value);
  43. static uint copy_decode_table(uint16 *to_pos,uint offset,
  44.       uint16 *decode_table);
  45. static uint find_longest_bitstream(uint16 *table);
  46. static void (*get_unpack_function(N_RECINFO *rec))(N_RECINFO *field,
  47.    BIT_BUFF *buff,
  48.    uchar *to,
  49.    uchar *end);
  50. static void uf_zerofill_skipp_zero(N_RECINFO *rec,BIT_BUFF *bit_buff,
  51.    uchar *to,uchar *end);
  52. static void uf_skipp_zero(N_RECINFO *rec,BIT_BUFF *bit_buff,
  53.   uchar *to,uchar *end);
  54. static void uf_space_normal(N_RECINFO *rec,BIT_BUFF *bit_buff,
  55.     uchar *to,uchar *end);
  56. static void uf_space_endspace_selected(N_RECINFO *rec,BIT_BUFF *bit_buff,
  57.        uchar *to, uchar *end);
  58. static void uf_endspace_selected(N_RECINFO *rec,BIT_BUFF *bit_buff,
  59.  uchar *to,uchar *end);
  60. static void uf_space_endspace(N_RECINFO *rec,BIT_BUFF *bit_buff,
  61.       uchar *to,uchar *end);
  62. static void uf_endspace(N_RECINFO *rec,BIT_BUFF *bit_buff,
  63. uchar *to,uchar *end);
  64. static void uf_space_prespace_selected(N_RECINFO *rec,BIT_BUFF *bit_buff,
  65.        uchar *to, uchar *end);
  66. static void uf_prespace_selected(N_RECINFO *rec,BIT_BUFF *bit_buff,
  67.  uchar *to,uchar *end);
  68. static void uf_space_prespace(N_RECINFO *rec,BIT_BUFF *bit_buff,
  69.       uchar *to,uchar *end);
  70. static void uf_prespace(N_RECINFO *rec,BIT_BUFF *bit_buff,
  71. uchar *to,uchar *end);
  72. static void uf_zerofill_normal(N_RECINFO *rec,BIT_BUFF *bit_buff,
  73.        uchar *to,uchar *end);
  74. static void uf_constant(N_RECINFO *rec,BIT_BUFF *bit_buff,
  75. uchar *to,uchar *end);
  76. static void uf_intervall(N_RECINFO *rec,BIT_BUFF *bit_buff,
  77.  uchar *to,uchar *end);
  78. static void uf_zero(N_RECINFO *rec,BIT_BUFF *bit_buff,
  79.     uchar *to,uchar *end);
  80. static void decode_bytes(N_RECINFO *rec,BIT_BUFF *bit_buff,
  81.  uchar *to,uchar *end);
  82. static uint decode_pos(BIT_BUFF *bit_buff,DECODE_TREE *decode_tree);
  83. static void init_bit_buffer(BIT_BUFF *bit_buff,char *buffer,uint length);
  84. static uint fill_and_get_bits(BIT_BUFF *bit_buff,uint count);
  85. static void fill_buffer(BIT_BUFF *bit_buff);
  86. static uint max_bit(uint value);
  87. #ifdef HAVE_MMAP
  88. static void _nisam_mempack_get_block_info(BLOCK_INFO *info,uint ref_length,
  89.        uchar *header);
  90. #endif
  91. static uint mask[]=
  92. {
  93.    0x00000000,
  94.    0x00000001, 0x00000003, 0x00000007, 0x0000000f,
  95.    0x0000001f, 0x0000003f, 0x0000007f, 0x000000ff,
  96.    0x000001ff, 0x000003ff, 0x000007ff, 0x00000fff,
  97.    0x00001fff, 0x00003fff, 0x00007fff, 0x0000ffff,
  98. #if BITS_SAVED > 16
  99.    0x0001ffff, 0x0003ffff, 0x0007ffff, 0x000fffff,
  100.    0x001fffff, 0x003fffff, 0x007fffff, 0x00ffffff,
  101.    0x01ffffff, 0x03ffffff, 0x07ffffff, 0x0fffffff,
  102.    0x1fffffff, 0x3fffffff, 0x7fffffff, 0xffffffff,
  103. #endif
  104.  };
  105. /* Read all packed info, allocate memory and fix field structs */
  106. my_bool _nisam_read_pack_info(N_INFO *info, pbool fix_keys)
  107. {
  108.   File file;
  109.   int diff_length;
  110.   uint i,trees,huff_tree_bits,rec_reflength,length;
  111.   uint16 *decode_table,*tmp_buff;
  112.   ulong elements,intervall_length;
  113.   char *disk_cache,*intervall_buff;
  114.   uchar header[32];
  115.   ISAM_SHARE *share=info->s;
  116.   BIT_BUFF bit_buff;
  117.   DBUG_ENTER("_nisam_read_pack_info");
  118.   if (nisam_quick_table_bits < 4)
  119.     nisam_quick_table_bits=4;
  120.   else if (nisam_quick_table_bits > MAX_QUICK_TABLE_BITS)
  121.     nisam_quick_table_bits=MAX_QUICK_TABLE_BITS;
  122.   file=info->dfile;
  123.   my_errno=0;
  124.   if (my_read(file,(byte*) header,sizeof(header),MYF(MY_NABP)))
  125.   {
  126.     if (!my_errno)
  127.       my_errno=HA_ERR_END_OF_FILE;
  128.     DBUG_RETURN(1);
  129.   }
  130.   if (memcmp((byte*) header,(byte*) nisam_pack_file_magic,4))
  131.   {
  132.     my_errno=HA_ERR_WRONG_IN_RECORD;
  133.     DBUG_RETURN(1);
  134.   }
  135.   share->pack.header_length=uint4korr(header+4);
  136.   share->min_pack_length=(uint) uint4korr(header+8);
  137.   share->max_pack_length=(uint) uint4korr(header+12);
  138.   set_if_bigger(share->base.pack_reclength,share->max_pack_length);
  139.   elements=uint4korr(header+16);
  140.   intervall_length=uint4korr(header+20);
  141.   trees=uint2korr(header+24);
  142.   share->pack.ref_length=header[26];
  143.   rec_reflength=header[27];
  144.   diff_length=(int) rec_reflength - (int) share->base.rec_reflength;
  145.   if (fix_keys)
  146.     share->rec_reflength=rec_reflength;
  147.   share->base.min_block_length=share->min_pack_length+share->pack.ref_length;
  148.   if (!(share->decode_trees=(DECODE_TREE*)
  149. my_malloc((uint) (trees*sizeof(DECODE_TREE)+
  150.   intervall_length*sizeof(byte)),
  151.   MYF(MY_WME))))
  152.     DBUG_RETURN(1);
  153.   intervall_buff=(byte*) (share->decode_trees+trees);
  154.   length=(uint) (elements*2+trees*(1 << nisam_quick_table_bits));
  155.   if (!(share->decode_tables=(uint16*)
  156. my_malloc((length+512)*sizeof(uint16)+
  157.   (uint) (share->pack.header_length+7),
  158.   MYF(MY_WME | MY_ZEROFILL))))
  159.   {
  160.     my_free((gptr) share->decode_trees,MYF(0));
  161.     DBUG_RETURN(1);
  162.   }
  163.   tmp_buff=share->decode_tables+length;
  164.   disk_cache=(byte*) (tmp_buff+512);
  165.   if (my_read(file,disk_cache,
  166.       (uint) (share->pack.header_length-sizeof(header)),
  167.       MYF(MY_NABP)))
  168.   {
  169.     my_free((gptr) share->decode_trees,MYF(0));
  170.     my_free((gptr) share->decode_tables,MYF(0));
  171.     DBUG_RETURN(1);
  172.   }
  173.   huff_tree_bits=max_bit(trees ? trees-1 : 0);
  174.   init_bit_buffer(&bit_buff,disk_cache,
  175.   (uint) (share->pack.header_length-sizeof(header)));
  176. /* Read new info for each field */
  177.   for (i=0 ; i < share->base.fields ; i++)
  178.   {
  179.     share->rec[i].base_type=(enum en_fieldtype) get_bits(&bit_buff,4);
  180.     share->rec[i].pack_type=(uint) get_bits(&bit_buff,4);
  181.     share->rec[i].space_length_bits=get_bits(&bit_buff,4);
  182.     share->rec[i].huff_tree=share->decode_trees+(uint) get_bits(&bit_buff,
  183. huff_tree_bits);
  184.     share->rec[i].unpack=get_unpack_function(share->rec+i);
  185.   }
  186.   skipp_to_next_byte(&bit_buff);
  187.   decode_table=share->decode_tables;
  188.   for (i=0 ; i < trees ; i++)
  189.     read_huff_table(&bit_buff,share->decode_trees+i,&decode_table,
  190.     &intervall_buff,tmp_buff);
  191.   decode_table=(uint16*)
  192.     my_realloc((gptr) share->decode_tables,
  193.        (uint) ((byte*) decode_table - (byte*) share->decode_tables),
  194.        MYF(MY_HOLD_ON_ERROR));
  195.   {
  196.     my_ptrdiff_t diff=PTR_BYTE_DIFF(decode_table,share->decode_tables);
  197.     share->decode_tables=decode_table;
  198.     for (i=0 ; i < trees ; i++)
  199.       share->decode_trees[i].table=ADD_TO_PTR(share->decode_trees[i].table,
  200.       diff, uint16*);
  201.   }
  202. /* Fix record-ref-length for keys */
  203.   if (fix_keys)
  204.   {
  205.     for (i=0 ; i < share->base.keys ; i++)
  206.     {
  207.       share->keyinfo[i].base.keylength+=(uint16) diff_length;
  208.       share->keyinfo[i].base.minlength+=(uint16) diff_length;
  209.       share->keyinfo[i].base.maxlength+=(uint16) diff_length;
  210.       share->keyinfo[i].seg[share->keyinfo[i].base.keysegs].base.length=
  211. (uint16) rec_reflength;
  212.     }
  213.   }
  214.   if (bit_buff.error || bit_buff.pos < bit_buff.end)
  215.   { /* info_length was wrong */
  216.     my_errno=HA_ERR_WRONG_IN_RECORD;
  217.     my_free((gptr) share->decode_trees,MYF(0));
  218.     my_free((gptr) share->decode_tables,MYF(0));
  219.     DBUG_RETURN(1);
  220.   }
  221.   DBUG_RETURN(0);
  222. }
  223. /* Read on huff-code-table from datafile */
  224. static void read_huff_table(BIT_BUFF *bit_buff, DECODE_TREE *decode_tree,
  225.     uint16 **decode_table, byte **intervall_buff,
  226.     uint16 *tmp_buff)
  227. {
  228.   uint min_chr,elements,char_bits,offset_bits,size,intervall_length,table_bits,
  229.   next_free_offset;
  230.   uint16 *ptr,*end;
  231.   LINT_INIT(ptr);
  232.   if (!get_bits(bit_buff,1))
  233.   {
  234.     min_chr=get_bits(bit_buff,8);
  235.     elements=get_bits(bit_buff,9);
  236.     char_bits=get_bits(bit_buff,5);
  237.     offset_bits=get_bits(bit_buff,5);
  238.     intervall_length=0;
  239.     ptr=tmp_buff;
  240.   }
  241.   else
  242.   {
  243.     min_chr=0;
  244.     elements=get_bits(bit_buff,15);
  245.     intervall_length=get_bits(bit_buff,16);
  246.     char_bits=get_bits(bit_buff,5);
  247.     offset_bits=get_bits(bit_buff,5);
  248.     decode_tree->quick_table_bits=0;
  249.     ptr= *decode_table;
  250.   }
  251.   size=elements*2-2;
  252.   for (end=ptr+size ; ptr < end ; ptr++)
  253.   {
  254.     if (get_bit(bit_buff))
  255.       *ptr= (uint16) get_bits(bit_buff,offset_bits);
  256.     else
  257.       *ptr= (uint16) (IS_CHAR + (get_bits(bit_buff,char_bits) + min_chr));
  258.   }
  259.   skipp_to_next_byte(bit_buff);
  260.   decode_tree->table= *decode_table;
  261.   decode_tree->intervalls= *intervall_buff;
  262.   if (! intervall_length)
  263.   {
  264.     table_bits=find_longest_bitstream(tmp_buff);
  265.     if (table_bits > nisam_quick_table_bits)
  266.       table_bits=nisam_quick_table_bits;
  267.     next_free_offset= (1 << table_bits);
  268.     make_quick_table(*decode_table,tmp_buff,&next_free_offset,0,table_bits,
  269.      table_bits);
  270.     (*decode_table)+= next_free_offset;
  271.     decode_tree->quick_table_bits=table_bits;
  272.   }
  273.   else
  274.   {
  275.     (*decode_table)=end;
  276.     bit_buff->pos-= bit_buff->bits/8;
  277.     memcpy(*intervall_buff,bit_buff->pos,(size_t) intervall_length);
  278.     (*intervall_buff)+=intervall_length;
  279.     bit_buff->pos+=intervall_length;
  280.     bit_buff->bits=0;
  281.   }
  282.   return;
  283. }
  284. static void make_quick_table(uint16 *to_table, uint16 *decode_table, uint *next_free_offset, uint value, uint bits, uint max_bits)
  285. {
  286.   if (!bits--)
  287.   {
  288.     to_table[value]= (uint16) *next_free_offset;
  289.     *next_free_offset=copy_decode_table(to_table, *next_free_offset,
  290. decode_table);
  291.     return;
  292.   }
  293.   if (!(*decode_table & IS_CHAR))
  294.   {
  295.     make_quick_table(to_table,decode_table+ *decode_table,
  296.      next_free_offset,value,bits,max_bits);
  297.   }
  298.   else
  299.     fill_quick_table(to_table+value,bits,max_bits,(uint) *decode_table);
  300.   decode_table++;
  301.   value|= (1 << bits);
  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.   return;
  310. }
  311. static void fill_quick_table(uint16 *table, uint bits, uint max_bits, uint value)
  312. {
  313.   uint16 *end;
  314.   value|=(max_bits-bits) << 8;
  315.   for (end=table+ (1 << bits) ;
  316.        table < end ;
  317.        *table++ = (uint16) value | IS_CHAR) ;
  318. }
  319. static uint copy_decode_table(uint16 *to_pos, uint offset, uint16 *decode_table)
  320. {
  321.   uint prev_offset;
  322.   prev_offset= offset;
  323.   if (!(*decode_table & IS_CHAR))
  324.   {
  325.     to_pos[offset]=2;
  326.     offset=copy_decode_table(to_pos,offset+2,decode_table+ *decode_table);
  327.   }
  328.   else
  329.   {
  330.     to_pos[offset]= *decode_table;
  331.     offset+=2;
  332.   }
  333.   decode_table++;
  334.   if (!(*decode_table & IS_CHAR))
  335.   {
  336.     to_pos[prev_offset+1]=(uint16) (offset-prev_offset-1);
  337.     offset=copy_decode_table(to_pos,offset,decode_table+ *decode_table);
  338.   }
  339.   else
  340.     to_pos[prev_offset+1]= *decode_table;
  341.   return offset;
  342. }
  343. static uint find_longest_bitstream(uint16 *table)
  344. {
  345.   uint length=1,length2;
  346.   if (!(*table & IS_CHAR))
  347.     length=find_longest_bitstream(table+ *table)+1;
  348.   table++;
  349.   if (!(*table & IS_CHAR))
  350.   {
  351.     length2=find_longest_bitstream(table+ *table)+1;
  352.     length=max(length,length2);
  353.   }
  354.   return length;
  355. }
  356. /* Read record from datafile */
  357. /* Returns length of packed record, -1 if error */
  358. int _nisam_read_pack_record(N_INFO *info, ulong filepos, byte *buf)
  359. {
  360.   BLOCK_INFO block_info;
  361.   File file;
  362.   DBUG_ENTER("_nisam_read_pack_record");
  363.   if (filepos == NI_POS_ERROR)
  364.     DBUG_RETURN(-1); /* _search() didn't find record */
  365.   file=info->dfile;
  366.   if (_nisam_pack_get_block_info(&block_info,info->s->pack.ref_length,file,
  367.       filepos))
  368.     goto err;
  369.   if (my_read(file,(byte*) info->rec_buff,block_info.rec_len,MYF(MY_NABP)))
  370.     goto panic;
  371.   info->update|= HA_STATE_AKTIV;
  372.   DBUG_RETURN(_nisam_pack_rec_unpack(info,buf,info->rec_buff,
  373.      block_info.rec_len));
  374. panic:
  375.   my_errno=HA_ERR_WRONG_IN_RECORD;
  376. err:
  377.   DBUG_RETURN(-1);
  378. }
  379. int _nisam_pack_rec_unpack(register N_INFO *info, register byte *to,
  380.    byte *from, uint reclength)
  381. {
  382.   byte *end_field;
  383.   reg3 N_RECINFO *end;
  384.   N_RECINFO *current_field;
  385.   ISAM_SHARE *share=info->s;
  386.   DBUG_ENTER("_nisam_pack_rec_unpack");
  387.   init_bit_buffer(&info->bit_buff,from,reclength);
  388.   for (current_field=share->rec, end=current_field+share->base.fields ;
  389.        current_field < end ;
  390.        current_field++,to=end_field)
  391.   {
  392.     end_field=to+current_field->base.length;
  393.     (*current_field->unpack)(current_field,&info->bit_buff,(uchar*) to,
  394.      (uchar*) end_field);
  395.   }
  396.   if (! info->bit_buff.error &&
  397.       info->bit_buff.pos - info->bit_buff.bits/8 == info->bit_buff.end)
  398.     DBUG_RETURN(0);
  399.   my_errno=HA_ERR_WRONG_IN_RECORD;
  400.   info->update&= ~HA_STATE_AKTIV;
  401.   DBUG_RETURN(-1);
  402. } /* _nisam_pack_rec_unpack */
  403. /* Return function to unpack field */
  404. static void (*get_unpack_function(N_RECINFO *rec))(N_RECINFO *, BIT_BUFF *, uchar *, uchar *)
  405. {
  406.   switch (rec->base_type) {
  407.   case FIELD_SKIP_ZERO:
  408.     if (rec->pack_type & PACK_TYPE_ZERO_FILL)
  409.       return &uf_zerofill_skipp_zero;
  410.     return &uf_skipp_zero;
  411.   case FIELD_NORMAL:
  412.     if (rec->pack_type & PACK_TYPE_SPACE_FIELDS)
  413.       return &uf_space_normal;
  414.     if (rec->pack_type & PACK_TYPE_ZERO_FILL)
  415.       return &uf_zerofill_normal;
  416.     return &decode_bytes;
  417.   case FIELD_SKIP_ENDSPACE:
  418.     if (rec->pack_type & PACK_TYPE_SPACE_FIELDS)
  419.     {
  420.       if (rec->pack_type & PACK_TYPE_SELECTED)
  421. return &uf_space_endspace_selected;
  422.       return &uf_space_endspace;
  423.     }
  424.     if (rec->pack_type & PACK_TYPE_SELECTED)
  425.       return &uf_endspace_selected;
  426.     return &uf_endspace;
  427.   case FIELD_SKIP_PRESPACE:
  428.     if (rec->pack_type & PACK_TYPE_SPACE_FIELDS)
  429.     {
  430.       if (rec->pack_type & PACK_TYPE_SELECTED)
  431. return &uf_space_prespace_selected;
  432.       return &uf_space_prespace;
  433.     }
  434.     if (rec->pack_type & PACK_TYPE_SELECTED)
  435.       return &uf_prespace_selected;
  436.     return &uf_prespace;
  437.   case FIELD_CONSTANT:
  438.     return &uf_constant;
  439.   case FIELD_INTERVALL:
  440.     return &uf_intervall;
  441.   case FIELD_ZERO:
  442.     return &uf_zero;
  443.   case FIELD_BLOB: /* Write this sometimes.. */
  444.   case FIELD_LAST:
  445.   default:
  446.     return 0; /* This should never happend */
  447.   }
  448. }
  449. /* De different functions to unpack a field */
  450. static void uf_zerofill_skipp_zero(N_RECINFO *rec, BIT_BUFF *bit_buff, uchar *to, uchar *end)
  451. {
  452.   if (get_bit(bit_buff))
  453.     bzero((char*) to,(uint) (end-to));
  454.   else
  455.   {
  456. #ifdef WORDS_BIGENDIAN
  457.     bzero((char*) to,rec->space_length_bits);
  458.     decode_bytes(rec,bit_buff,to+rec->space_length_bits,end);
  459. #else
  460.     end-=rec->space_length_bits;
  461.     decode_bytes(rec,bit_buff,to,end);
  462.     bzero((byte*) end,rec->space_length_bits);
  463. #endif
  464.   }
  465. }
  466. static void uf_skipp_zero(N_RECINFO *rec, BIT_BUFF *bit_buff, uchar *to, uchar *end)
  467. {
  468.   if (get_bit(bit_buff))
  469.     bzero((char*) to,(uint) (end-to));
  470.   else
  471.     decode_bytes(rec,bit_buff,to,end);
  472. }
  473. static void uf_space_normal(N_RECINFO *rec, BIT_BUFF *bit_buff, uchar *to, uchar *end)
  474. {
  475.   if (get_bit(bit_buff))
  476.     bfill((byte*) to,(end-to),' ');
  477.   else
  478.     decode_bytes(rec,bit_buff,to,end);
  479. }
  480. static void uf_space_endspace_selected(N_RECINFO *rec, BIT_BUFF *bit_buff, uchar *to, uchar *end)
  481. {
  482.   uint spaces;
  483.   if (get_bit(bit_buff))
  484.     bfill((byte*) to,(end-to),' ');
  485.   else
  486.   {
  487.     if (get_bit(bit_buff))
  488.     {
  489.       if ((spaces=get_bits(bit_buff,rec->space_length_bits))+to > end)
  490.       {
  491. bit_buff->error=1;
  492. return;
  493.       }
  494.       if (to+spaces != end)
  495. decode_bytes(rec,bit_buff,to,end-spaces);
  496.       bfill((byte*) end-spaces,spaces,' ');
  497.     }
  498.     else
  499.       decode_bytes(rec,bit_buff,to,end);
  500.   }
  501. }
  502. static void uf_endspace_selected(N_RECINFO *rec, BIT_BUFF *bit_buff, uchar *to, uchar *end)
  503. {
  504.   uint spaces;
  505.   if (get_bit(bit_buff))
  506.   {
  507.     if ((spaces=get_bits(bit_buff,rec->space_length_bits))+to > end)
  508.     {
  509.       bit_buff->error=1;
  510.       return;
  511.     }
  512.     if (to+spaces != end)
  513.       decode_bytes(rec,bit_buff,to,end-spaces);
  514.     bfill((byte*) end-spaces,spaces,' ');
  515.   }
  516.   else
  517.     decode_bytes(rec,bit_buff,to,end);
  518. }
  519. static void uf_space_endspace(N_RECINFO *rec, BIT_BUFF *bit_buff, uchar *to, uchar *end)
  520. {
  521.   uint spaces;
  522.   if (get_bit(bit_buff))
  523.     bfill((byte*) to,(end-to),' ');
  524.   else
  525.   {
  526.     if ((spaces=get_bits(bit_buff,rec->space_length_bits))+to > end)
  527.     {
  528.       bit_buff->error=1;
  529.       return;
  530.     }
  531.     if (to+spaces != end)
  532.       decode_bytes(rec,bit_buff,to,end-spaces);
  533.     bfill((byte*) end-spaces,spaces,' ');
  534.   }
  535. }
  536. static void uf_endspace(N_RECINFO *rec, BIT_BUFF *bit_buff, uchar *to,
  537. uchar *end)
  538. {
  539.   uint spaces;
  540.   if ((spaces=get_bits(bit_buff,rec->space_length_bits))+to > end)
  541.   {
  542.     bit_buff->error=1;
  543.     return;
  544.   }
  545.   if (to+spaces != end)
  546.     decode_bytes(rec,bit_buff,to,end-spaces);
  547.   bfill((byte*) end-spaces,spaces,' ');
  548. }
  549. static void uf_space_prespace_selected(N_RECINFO *rec, BIT_BUFF *bit_buff, 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.       bfill((byte*) to,spaces,' ');
  564.       if (to+spaces != end)
  565. decode_bytes(rec,bit_buff,to+spaces,end);
  566.     }
  567.     else
  568.       decode_bytes(rec,bit_buff,to,end);
  569.   }
  570. }
  571. static void uf_prespace_selected(N_RECINFO *rec, BIT_BUFF *bit_buff, uchar *to, uchar *end)
  572. {
  573.   uint spaces;
  574.   if (get_bit(bit_buff))
  575.   {
  576.     if ((spaces=get_bits(bit_buff,rec->space_length_bits))+to > end)
  577.     {
  578.       bit_buff->error=1;
  579.       return;
  580.     }
  581.     bfill((byte*) to,spaces,' ');
  582.     if (to+spaces != end)
  583.       decode_bytes(rec,bit_buff,to+spaces,end);
  584.   }
  585.   else
  586.     decode_bytes(rec,bit_buff,to,end);
  587. }
  588. static void uf_space_prespace(N_RECINFO *rec, BIT_BUFF *bit_buff, uchar *to, uchar *end)
  589. {
  590.   uint spaces;
  591.   if (get_bit(bit_buff))
  592.     bfill((byte*) to,(end-to),' ');
  593.   else
  594.   {
  595.     if ((spaces=get_bits(bit_buff,rec->space_length_bits))+to > end)
  596.     {
  597.       bit_buff->error=1;
  598.       return;
  599.     }
  600.     bfill((byte*) to,spaces,' ');
  601.     if (to+spaces != end)
  602.       decode_bytes(rec,bit_buff,to+spaces,end);
  603.   }
  604. }
  605. static void uf_prespace(N_RECINFO *rec, BIT_BUFF *bit_buff, uchar *to, uchar *end)
  606. {
  607.   uint spaces;
  608.   if ((spaces=get_bits(bit_buff,rec->space_length_bits))+to > end)
  609.   {
  610.     bit_buff->error=1;
  611.     return;
  612.   }
  613.   bfill((byte*) to,spaces,' ');
  614.   if (to+spaces != end)
  615.     decode_bytes(rec,bit_buff,to+spaces,end);
  616. }
  617. static void uf_zerofill_normal(N_RECINFO *rec, BIT_BUFF *bit_buff, uchar *to, uchar *end)
  618. {
  619. #ifdef WORDS_BIGENDIAN
  620.   bzero((char*) to,rec->space_length_bits);
  621.   decode_bytes(rec,bit_buff,(uchar*) to+rec->space_length_bits,end);
  622. #else
  623.   end-=rec->space_length_bits;
  624.   decode_bytes(rec,bit_buff,(uchar*) to,end);
  625.   bzero((byte*) end,rec->space_length_bits);
  626. #endif
  627. }
  628. static void uf_constant(N_RECINFO *rec,
  629. BIT_BUFF *bit_buff __attribute__((unused)),
  630. uchar *to, uchar *end)
  631. {
  632.   memcpy(to,rec->huff_tree->intervalls,(size_t) (end-to));
  633. }
  634. static void uf_intervall(N_RECINFO *rec, BIT_BUFF *bit_buff, uchar *to, uchar *end)
  635. {
  636.   reg1 uint field_length=(uint) (end-to);
  637.   memcpy(to,rec->huff_tree->intervalls+field_length*decode_pos(bit_buff,
  638.        rec->huff_tree),
  639.  (size_t) field_length);
  640. }
  641. /*ARGSUSED*/
  642. static void uf_zero(N_RECINFO *rec __attribute__((unused)),
  643.     BIT_BUFF *bit_buff  __attribute__((unused)),
  644.     uchar *to, uchar *end)
  645. {
  646.   bzero((char*) to,(uint) (end-to));
  647. }
  648. /* Functions to decode of buffer of bits */
  649. #if BITS_SAVED == 64
  650. static void decode_bytes(rec,bit_buff,to,end)
  651. N_RECINFO *rec;
  652. BIT_BUFF *bit_buff;
  653. uchar *to,*end;
  654. {
  655.   reg1 uint bits,low_byte;
  656.   reg3 uint16 *pos;
  657.   reg4 uint table_bits,table_and;
  658.   DECODE_TREE *decode_tree;
  659.   decode_tree=rec->decode_tree;
  660.   bits=bit_buff->bits; /* Save in reg for quicker access */
  661.   table_bits=decode_tree->quick_table_bits;
  662.   table_and= (1 << table_bits)-1;
  663.   do
  664.   {
  665.     if (bits <= 32)
  666.     {
  667.       if (bit_buff->pos > bit_buff->end+4)
  668. return; /* Can't be right */
  669.       bit_buff->current_byte= (bit_buff->current_byte << 32) +
  670. ((((uint) bit_buff->pos[3])) +
  671.  (((uint) bit_buff->pos[2]) << 8) +
  672.  (((uint) bit_buff->pos[1]) << 16) +
  673.  (((uint) bit_buff->pos[0]) << 24));
  674.       bit_buff->pos+=4;
  675.       bits+=32;
  676.     }
  677. /* First use info in quick_table */
  678.     low_byte=(uint) (bit_buff->current_byte >> (bits - table_bits)) & table_and;
  679.     low_byte=decode_tree->table[low_byte];
  680.     if (low_byte & IS_CHAR)
  681.     {
  682.       *to++ = (low_byte & 255); /* Found char in quick table */
  683.       bits-=  ((low_byte >> 8) & 31); /* Remove bits used */
  684.     }
  685.     else
  686.     { /* Map through rest of decode-table */
  687.       pos=decode_tree->table+low_byte;
  688.       bits-=table_bits;
  689.       for (;;)
  690.       {
  691. low_byte=(uint) (bit_buff->current_byte >> (bits-8));
  692. decode_bytes_test_bit(0);
  693. decode_bytes_test_bit(1);
  694. decode_bytes_test_bit(2);
  695. decode_bytes_test_bit(3);
  696. decode_bytes_test_bit(4);
  697. decode_bytes_test_bit(5);
  698. decode_bytes_test_bit(6);
  699. decode_bytes_test_bit(7);
  700. bits-=8;
  701.       }
  702.       *to++ = *pos;
  703.     }
  704.   } while (to != end);
  705.   bit_buff->bits=bits;
  706.   return;
  707. }
  708. #else
  709. static void decode_bytes(N_RECINFO *rec, BIT_BUFF *bit_buff, uchar *to, uchar *end)
  710. {
  711.   reg1 uint bits,low_byte;
  712.   reg3 uint16 *pos;
  713.   reg4 uint table_bits,table_and;
  714.   DECODE_TREE *decode_tree;
  715.   decode_tree=rec->huff_tree;
  716.   bits=bit_buff->bits; /* Save in reg for quicker access */
  717.   table_bits=decode_tree->quick_table_bits;
  718.   table_and= (1 << table_bits)-1;
  719.   do
  720.   {
  721.     if (bits < table_bits)
  722.     {
  723.       if (bit_buff->pos > bit_buff->end+1)
  724. return; /* Can't be right */
  725. #if BITS_SAVED == 32
  726.       bit_buff->current_byte= (bit_buff->current_byte << 24) +
  727. (((uint) ((uchar) bit_buff->pos[2]))) +
  728.   (((uint) ((uchar) bit_buff->pos[1])) << 8) +
  729.     (((uint) ((uchar) bit_buff->pos[0])) << 16);
  730.       bit_buff->pos+=3;
  731.       bits+=24;
  732. #else
  733.       if (bits) /* We must have at leasts 9 bits */
  734.       {
  735. bit_buff->current_byte=  (bit_buff->current_byte << 8) +
  736.   (uint) ((uchar) bit_buff->pos[0]);
  737. bit_buff->pos++;
  738. bits+=8;
  739.       }
  740.       else
  741.       {
  742. bit_buff->current_byte= ((uint) ((uchar) bit_buff->pos[0]) << 8) +
  743.   ((uint) ((uchar) bit_buff->pos[1]));
  744. bit_buff->pos+=2;
  745. bits+=16;
  746.       }
  747. #endif
  748.     }
  749. /* First use info in quick_table */
  750.     low_byte=(bit_buff->current_byte >> (bits - table_bits)) & table_and;
  751.     low_byte=decode_tree->table[low_byte];
  752.     if (low_byte & IS_CHAR)
  753.     {
  754.       *to++ = (low_byte & 255); /* Found char in quick table */
  755.       bits-=  ((low_byte >> 8) & 31); /* Remove bits used */
  756.     }
  757.     else
  758.     { /* Map through rest of decode-table */
  759.       pos=decode_tree->table+low_byte;
  760.       bits-=table_bits;
  761.       for (;;)
  762.       {
  763. if (bits < 8)
  764. { /* We don't need to check end */
  765. #if BITS_SAVED == 32
  766.   bit_buff->current_byte= (bit_buff->current_byte << 24) +
  767.     (((uint) ((uchar) bit_buff->pos[2]))) +
  768.       (((uint) ((uchar) bit_buff->pos[1])) << 8) +
  769. (((uint) ((uchar) bit_buff->pos[0])) << 16);
  770.   bit_buff->pos+=3;
  771.   bits+=24;
  772. #else
  773.   bit_buff->current_byte=  (bit_buff->current_byte << 8) +
  774.     (uint) ((uchar) bit_buff->pos[0]);
  775.   bit_buff->pos+=1;
  776.   bits+=8;
  777. #endif
  778. }
  779. low_byte=(uint) (bit_buff->current_byte >> (bits-8));
  780. decode_bytes_test_bit(0);
  781. decode_bytes_test_bit(1);
  782. decode_bytes_test_bit(2);
  783. decode_bytes_test_bit(3);
  784. decode_bytes_test_bit(4);
  785. decode_bytes_test_bit(5);
  786. decode_bytes_test_bit(6);
  787. decode_bytes_test_bit(7);
  788. bits-=8;
  789.       }
  790.       *to++ = (uchar) *pos;
  791.     }
  792.   } while (to != end);
  793.   bit_buff->bits=bits;
  794.   return;
  795. }
  796. #endif /* BIT_SAVED == 64 */
  797. static uint decode_pos(BIT_BUFF *bit_buff, DECODE_TREE *decode_tree)
  798. {
  799.   uint16 *pos=decode_tree->table;
  800.   for (;;)
  801.   {
  802.     if (get_bit(bit_buff))
  803.       pos++;
  804.     if (*pos & IS_CHAR)
  805.       return (uint) (*pos & ~IS_CHAR);
  806.     pos+= *pos;
  807.   }
  808. }
  809. int _nisam_read_rnd_pack_record(N_INFO *info, byte *buf,
  810. register ulong filepos,
  811. int skipp_deleted_blocks)
  812. {
  813.   uint b_type;
  814.   BLOCK_INFO block_info;
  815.   ISAM_SHARE *share=info->s;
  816.   DBUG_ENTER("_nisam_read_rnd_pack_record");
  817.   if (filepos >= share->state.data_file_length)
  818.   {
  819.     my_errno= HA_ERR_END_OF_FILE;
  820.     goto err;
  821.   }
  822.   if (info->opt_flag & READ_CACHE_USED)
  823.   {
  824.     if (_nisam_read_cache(&info->rec_cache,(byte*) block_info.header,filepos,
  825.   share->pack.ref_length, skipp_deleted_blocks))
  826.       goto err;
  827.     b_type=_nisam_pack_get_block_info(&block_info,share->pack.ref_length,-1,
  828.       filepos);
  829.   }
  830.   else
  831.     b_type=_nisam_pack_get_block_info(&block_info,share->pack.ref_length,
  832.       info->dfile,filepos);
  833.   if (b_type)
  834.     goto err;
  835. #ifndef DBUG_OFF
  836.   if (block_info.rec_len > share->max_pack_length)
  837.   {
  838.     my_errno=HA_ERR_WRONG_IN_RECORD;
  839.     goto err;
  840.   }
  841. #endif
  842.   if (info->opt_flag & READ_CACHE_USED)
  843.   {
  844.     if (_nisam_read_cache(&info->rec_cache,(byte*) info->rec_buff,
  845.   block_info.filepos, block_info.rec_len,
  846.   skipp_deleted_blocks))
  847.       goto err;
  848.   }
  849.   else
  850.   {
  851.     if (my_read(info->dfile,(byte*) info->rec_buff,block_info.rec_len,
  852. MYF(MY_NABP)))
  853.       goto err;
  854.   }
  855.   info->packed_length=block_info.rec_len;
  856.   info->lastpos=filepos;
  857.   info->nextpos=block_info.filepos+block_info.rec_len;
  858.   info->update|= HA_STATE_AKTIV | HA_STATE_KEY_CHANGED;
  859.   DBUG_RETURN (_nisam_pack_rec_unpack(info,buf,info->rec_buff,
  860.       block_info.rec_len));
  861. err:
  862.   DBUG_RETURN(-1);
  863. }
  864. /* Read and process header from a huff-record-file */
  865. uint _nisam_pack_get_block_info(BLOCK_INFO *info, uint ref_length, File file,
  866. ulong filepos)
  867. {
  868.   uchar *header=info->header;
  869.   if (file >= 0)
  870.   {
  871.     VOID(my_seek(file,filepos,MY_SEEK_SET,MYF(0)));
  872.     if (my_read(file,(char*) header,ref_length,MYF(MY_NABP)))
  873.       return BLOCK_FATAL_ERROR;
  874.   }
  875.   DBUG_DUMP("header",(byte*) header,ref_length);
  876.   switch (ref_length) {
  877.   case 1:
  878.     info->rec_len=header[0];
  879.     info->filepos=filepos+1;
  880.     break;
  881.   case 2:
  882.     info->rec_len=uint2korr(header);
  883.     info->filepos=filepos+2;
  884.     break;
  885.   case 3:
  886.     info->rec_len=(uint) (uint3korr(header));
  887.     info->filepos=filepos+3;
  888.     break;
  889.   default: break;
  890.   }
  891.   return 0;
  892. }
  893. /* routines for bit buffer */
  894. /* Buffer must be 6 byte bigger */
  895. static void init_bit_buffer(BIT_BUFF *bit_buff, char *buffer, uint length)
  896. {
  897.   bit_buff->pos=(uchar*) buffer;
  898.   bit_buff->end=(uchar*) buffer+length;
  899.   bit_buff->bits=bit_buff->error=0;
  900.   bit_buff->current_byte=0; /* Avoid purify errors */
  901. }
  902. static uint fill_and_get_bits(BIT_BUFF *bit_buff, uint count)
  903. {
  904.   uint tmp;
  905.   count-=bit_buff->bits;
  906.   tmp=(bit_buff->current_byte & mask[bit_buff->bits]) << count;
  907.   fill_buffer(bit_buff);
  908.   bit_buff->bits=BITS_SAVED - count;
  909.   return tmp+(bit_buff->current_byte >> (BITS_SAVED - count));
  910. }
  911. /* Fill in empty bit_buff->current_byte from buffer */
  912. /* Sets bit_buff->error if buffer is exhausted */
  913. static void fill_buffer(BIT_BUFF *bit_buff)
  914. {
  915.   if (bit_buff->pos >= bit_buff->end)
  916.   {
  917.     bit_buff->error= 1;
  918.     bit_buff->current_byte=0;
  919.     return;
  920.   }
  921. #if BITS_SAVED == 64
  922.   bit_buff->current_byte=  ((((uint) ((uchar) bit_buff->pos[7]))) +
  923.      (((uint) ((uchar) bit_buff->pos[6])) << 8) +
  924.      (((uint) ((uchar) bit_buff->pos[5])) << 16) +
  925.      (((uint) ((uchar) bit_buff->pos[4])) << 24) +
  926.      ((ulonglong)
  927.       ((((uint) ((uchar) bit_buff->pos[3]))) +
  928.        (((uint) ((uchar) bit_buff->pos[2])) << 8) +
  929.        (((uint) ((uchar) bit_buff->pos[1])) << 16) +
  930.        (((uint) ((uchar) bit_buff->pos[0])) << 24)) << 32));
  931.   bit_buff->pos+=8;
  932. #else
  933. #if BITS_SAVED == 32
  934.   bit_buff->current_byte=  (((uint) ((uchar) bit_buff->pos[3])) +
  935.      (((uint) ((uchar) bit_buff->pos[2])) << 8) +
  936.      (((uint) ((uchar) bit_buff->pos[1])) << 16) +
  937.      (((uint) ((uchar) bit_buff->pos[0])) << 24));
  938.   bit_buff->pos+=4;
  939. #else
  940.   bit_buff->current_byte=  (uint) (((uint) ((uchar) bit_buff->pos[1]))+
  941.     (((uint) ((uchar) bit_buff->pos[0])) << 8));
  942.   bit_buff->pos+=2;
  943. #endif
  944. #endif
  945. }
  946. /* Get number of bits neaded to represent value */
  947. static uint max_bit(register uint value)
  948. {
  949.   reg2 uint power=1;
  950.   while ((value>>=1))
  951.     power++;
  952.   return (power);
  953. }
  954. /*****************************************************************************
  955. Some redefined functions to handle files when we are using memmap
  956. *****************************************************************************/
  957. #ifdef HAVE_MMAP
  958. #include <sys/mman.h>
  959. static int _nisam_read_mempack_record(N_INFO *info,ulong filepos,byte *buf);
  960. static int _nisam_read_rnd_mempack_record(N_INFO*, byte *,ulong, int);
  961. #ifndef MAP_NORESERVE
  962. #define MAP_NORESERVE 0 /* For irix */
  963. #endif
  964. #ifndef MAP_FAILED
  965. #define MAP_FAILED -1
  966. #endif
  967. my_bool _nisam_memmap_file(N_INFO *info)
  968. {
  969.   byte *file_map;
  970.   ISAM_SHARE *share=info->s;
  971.   DBUG_ENTER("_nisam_memmap_file");
  972.   if (!info->s->file_map)
  973.   {
  974.     if (my_seek(info->dfile,0L,MY_SEEK_END,MYF(0)) <
  975. share->state.data_file_length+MEMMAP_EXTRA_MARGIN)
  976.     {
  977.       DBUG_PRINT("warning",("File isn't extended for memmap"));
  978.       DBUG_RETURN(0);
  979.     }
  980.     file_map=(byte*)
  981.       mmap(0,share->state.data_file_length+MEMMAP_EXTRA_MARGIN,PROT_READ,
  982.    MAP_SHARED | MAP_NORESERVE,info->dfile,0L);
  983.     if (file_map == (byte*) MAP_FAILED)
  984.     {
  985.       DBUG_PRINT("warning",("mmap failed: errno: %d",errno));
  986.       my_errno=errno;
  987.       DBUG_RETURN(0);
  988.     }
  989.     info->s->file_map=file_map;
  990.   }
  991.   info->opt_flag|= MEMMAP_USED;
  992.   info->read_record=share->read_record=_nisam_read_mempack_record;
  993.   share->read_rnd=_nisam_read_rnd_mempack_record;
  994.   DBUG_RETURN(1);
  995. }
  996. void _nisam_unmap_file(N_INFO *info)
  997. {
  998.   if (info->s->file_map)
  999.     (void) munmap((caddr_t) info->s->file_map,
  1000.   (size_t) info->s->state.data_file_length+
  1001.   MEMMAP_EXTRA_MARGIN);
  1002. }
  1003. static void _nisam_mempack_get_block_info(BLOCK_INFO *info, uint ref_length,
  1004.   uchar *header)
  1005. {
  1006.   if (ref_length == 1) /* This is most usual */
  1007.     info->rec_len=header[0];
  1008.   else if (ref_length == 2)
  1009.     info->rec_len=uint2korr(header);
  1010.   else
  1011.     info->rec_len=(uint) (uint3korr(header));
  1012. }
  1013. static int _nisam_read_mempack_record(N_INFO *info, ulong filepos, byte *buf)
  1014. {
  1015.   BLOCK_INFO block_info;
  1016.   ISAM_SHARE *share=info->s;
  1017.   DBUG_ENTER("ni_read_mempack_record");
  1018.   if (filepos == NI_POS_ERROR)
  1019.     DBUG_RETURN(-1); /* _search() didn't find record */
  1020.   _nisam_mempack_get_block_info(&block_info,share->pack.ref_length,
  1021. (uchar*) share->file_map+filepos);
  1022.   DBUG_RETURN(_nisam_pack_rec_unpack(info,buf,share->file_map+
  1023.      share->pack.ref_length+filepos,
  1024.      block_info.rec_len));
  1025. }
  1026. /*ARGSUSED*/
  1027. static int _nisam_read_rnd_mempack_record(N_INFO *info, byte *buf,
  1028.   register ulong filepos,
  1029.   int skipp_deleted_blocks
  1030.   __attribute__((unused)))
  1031. {
  1032.   BLOCK_INFO block_info;
  1033.   ISAM_SHARE *share=info->s;
  1034.   DBUG_ENTER("_nisam_read_rnd_mempack_record");
  1035.   if (filepos >= share->state.data_file_length)
  1036.   {
  1037.     my_errno=HA_ERR_END_OF_FILE;
  1038.     goto err;
  1039.   }
  1040.   _nisam_mempack_get_block_info(&block_info,share->pack.ref_length,
  1041. (uchar*) share->file_map+filepos);
  1042. #ifndef DBUG_OFF
  1043.   if (block_info.rec_len > info->s->max_pack_length)
  1044.   {
  1045.     my_errno=HA_ERR_WRONG_IN_RECORD;
  1046.     goto err;
  1047.   }
  1048. #endif
  1049.   info->packed_length=block_info.rec_len;
  1050.   info->lastpos=filepos;
  1051.   info->nextpos=filepos+share->pack.ref_length+block_info.rec_len;
  1052.   info->update|= HA_STATE_AKTIV | HA_STATE_KEY_CHANGED;
  1053.   DBUG_RETURN (_nisam_pack_rec_unpack(info,buf,share->file_map+
  1054.       share->pack.ref_length+filepos,
  1055.       block_info.rec_len));
  1056. err:
  1057.   DBUG_RETURN(-1);
  1058. }
  1059. #endif /* HAVE_MMAP */