_packrec.c
上传用户:tsgydb
上传日期:2007-04-14
资源大小:10674k
文件大小:32k
源码类别:

MySQL数据库

开发平台:

Visual C++

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