Commit f1d5c048 authored by unknown's avatar unknown
Browse files

Bug#10932 - Building server with key limit of 128, makes test cases fail

This patch allows to configure MyISAM for 128 indexes per table.
The main problem is the key_map, wich is implemented as an ulonglong.
To get rid of the limit and keep the efficient and flexible
implementation, the highest bit is now used for all upper keys.
This means that the lower keys can be disabled and enabled 
individually as usual and the high keys can only be disabled and
enabled as a block. That way the existing test suite is still
applicable, while more keys work, though slightly less efficient.
To really get more than 64 keys, some defines need to be changed.
Another patch will address this.


include/my_bitmap.h:
  Bug#10932 - Building server with key limit of 128, makes test cases fail
  Added the declaration for a function that extends the highest bit value
  to all upper bits of a bigger bitmap.
include/myisam.h:
  Bug#10932 - Building server with key limit of 128, makes test cases fail
  Changed MI_MAX_POSSIBLE_KEY to what it was meant for.
  Added a bunch of macros to handle the MyISAM key_map.
myisam/mi_check.c:
  Bug#10932 - Building server with key limit of 128, makes test cases fail
  Changed key_map access to use the new macros.
myisam/mi_create.c:
  Bug#10932 - Building server with key limit of 128, makes test cases fail
  Changed key_map access to use the new macros.
myisam/mi_delete.c:
  Bug#10932 - Building server with key limit of 128, makes test cases fail
  Changed key_map access to use the new macros.
myisam/mi_extra.c:
  Bug#10932 - Building server with key limit of 128, makes test cases fail
  Changed key_map access to use the new macros.
myisam/mi_open.c:
  Bug#10932 - Building server with key limit of 128, makes test cases fail
  Changed key_map access to use the new macros.
  Changed pointer types from signed char* to unsigned char*.
myisam/mi_preload.c:
  Bug#10932 - Building server with key limit of 128, makes test cases fail
  Changed key_map access to use the new macros.
myisam/mi_rsame.c:
  Bug#10932 - Building server with key limit of 128, makes test cases fail
  Changed key_map access to use the new macros.
myisam/mi_rsamepos.c:
  Bug#10932 - Building server with key limit of 128, makes test cases fail
  Changed key_map access to use the new macros.
myisam/mi_search.c:
  Bug#10932 - Building server with key limit of 128, makes test cases fail
  Changed key_map access to use the new macros.
myisam/mi_update.c:
  Bug#10932 - Building server with key limit of 128, makes test cases fail
  Changed key_map access to use the new macros.
myisam/mi_write.c:
  Bug#10932 - Building server with key limit of 128, makes test cases fail
  Changed key_map access to use the new macros.
myisam/myisamchk.c:
  Bug#10932 - Building server with key limit of 128, makes test cases fail
  Changed key_map access to use the new macros.
myisam/myisamdef.h:
  Bug#10932 - Building server with key limit of 128, makes test cases fail
  Changed pointer types from signed char* to unsigned char*.
myisam/myisamlog.c:
  Bug#10932 - Building server with key limit of 128, makes test cases fail
  Changed key_map access to use the new macros.
myisam/myisampack.c:
  Bug#10932 - Building server with key limit of 128, makes test cases fail
  Changed key_map access to use the new macros.
myisam/sort.c:
  Bug#10932 - Building server with key limit of 128, makes test cases fail
  Changed key_map access to use the new macros.
mysys/my_bitmap.c:
  Bug#10932 - Building server with key limit of 128, makes test cases fail
  Added a function that extends the highest bit value
  to all upper bits of a bigger bitmap.
sql/ha_myisam.cc:
  Bug#10932 - Building server with key limit of 128, makes test cases fail
  Changed key_map access to use the new macros.
sql/sql_bitmap.h:
  Bug#10932 - Building server with key limit of 128, makes test cases fail
  Added a method that extends the highest bit value
  to all upper bits of a bigger bitmap.
parent a2df1eb8
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -54,6 +54,7 @@ extern void bitmap_clear_all(MY_BITMAP *map);
extern void bitmap_clear_bit(MY_BITMAP *map, uint bitmap_bit);
extern void bitmap_free(MY_BITMAP *map);
extern void bitmap_intersect(MY_BITMAP *map, const MY_BITMAP *map2);
extern void bitmap_set_above(MY_BITMAP *map, uint from_byte, uint use_bit);
extern void bitmap_set_all(MY_BITMAP *map);
extern void bitmap_set_bit(MY_BITMAP *map, uint bitmap_bit);
extern void bitmap_set_prefix(MY_BITMAP *map, uint prefix_size);
+75 −6
Original line number Diff line number Diff line
@@ -35,14 +35,26 @@ extern "C" {

	/* defines used by myisam-funktions */

/* The following defines can be increased if necessary */
/*
  There is a hard limit for the maximum number of keys as there are only
  8 bits in the index file header for the number of keys in a table.
  This means that 0..255 keys can exist for a table. The idea of
  MI_MAX_POSSIBLE_KEY is to ensure that one can use myisamchk & tools on
  a MyISAM table for which one has more keys than MyISAM is normally
  compiled for. If you don't have this, you will get a core dump when
  running myisamchk compiled for 128 keys on a table with 255 keys.
*/
#define MI_MAX_POSSIBLE_KEY         255             /* For myisam_chk */
#define MI_MAX_POSSIBLE_KEY_BUFF    (1024+6+6)      /* For myisam_chk */
/*
  The following defines can be increased if necessary.
  BUT: MI_MAX_KEY must be <= MI_MAX_POSSIBLE_KEY.
*/
#define MI_MAX_KEY                  64              /* Max allowed keys */
#define MI_MAX_KEY_SEG              16              /* Max segments for key */
#define MI_MAX_KEY_LENGTH           1000

#define MI_MAX_KEY_BUFF  (MI_MAX_KEY_LENGTH+MI_MAX_KEY_SEG*6+8+8)
#define MI_MAX_POSSIBLE_KEY_BUFF (1024+6+6)	/* For myisam_chk */
#define MI_MAX_POSSIBLE_KEY	64		/* For myisam_chk */
#define MI_MAX_MSG_BUF      1024 /* used in CHECK TABLE, REPAIR TABLE */
#define MI_NAME_IEXT	".MYI"
#define MI_NAME_DEXT	".MYD"
@@ -56,6 +68,63 @@ extern "C" {

#define mi_portable_sizeof_char_ptr 8

/*
  In the following macros '_keyno_' is 0 .. keys-1.
  If there can be more keys than bits in the key_map, the highest bit
  is for all upper keys. They cannot be switched individually.
  This means that clearing of high keys is ignored, setting one high key
  sets all high keys.
*/
#define MI_KEYMAP_BITS      (8 * SIZEOF_LONG_LONG)
#define MI_KEYMAP_HIGH_MASK (ULL(1) << (MI_KEYMAP_BITS - 1))
#define mi_get_mask_all_keys_active(_keys_) \
                            (((_keys_) < MI_KEYMAP_BITS) ? \
                             ((ULL(1) << (_keys_)) - ULL(1)) : \
                             (~ ULL(0)))

#if MI_MAX_KEY > MI_KEYMAP_BITS

#define mi_is_key_active(_keymap_,_keyno_) \
                            (((_keyno_) < MI_KEYMAP_BITS) ? \
                             test((_keymap_) & (ULL(1) << (_keyno_))) : \
                             test((_keymap_) & MI_KEYMAP_HIGH_MASK))
#define mi_set_key_active(_keymap_,_keyno_) \
                            (_keymap_)|= (((_keyno_) < MI_KEYMAP_BITS) ? \
                                          (ULL(1) << (_keyno_)) : \
                                          MI_KEYMAP_HIGH_MASK)
#define mi_clear_key_active(_keymap_,_keyno_) \
                            (_keymap_)&= (((_keyno_) < MI_KEYMAP_BITS) ? \
                                          (~ (ULL(1) << (_keyno_))) : \
                                          (~ (ULL(0))) /*ignore*/ )

#else

#define mi_is_key_active(_keymap_,_keyno_) \
                            test((_keymap_) & (ULL(1) << (_keyno_)))
#define mi_set_key_active(_keymap_,_keyno_) \
                            (_keymap_)|= (ULL(1) << (_keyno_))
#define mi_clear_key_active(_keymap_,_keyno_) \
                            (_keymap_)&= (~ (ULL(1) << (_keyno_)))

#endif

#define mi_is_any_key_active(_keymap_) \
                            test((_keymap_))
#define mi_is_all_keys_active(_keymap_,_keys_) \
                            ((_keymap_) == mi_get_mask_all_keys_active(_keys_))
#define mi_set_all_keys_active(_keymap_,_keys_) \
                            (_keymap_)= mi_get_mask_all_keys_active(_keys_)
#define mi_clear_all_keys_active(_keymap_) \
                            (_keymap_)= 0
#define mi_intersect_keys_active(_to_,_from_) \
                            (_to_)&= (_from_)
#define mi_is_any_intersect_keys_active(_keymap1_,_keys_,_keymap2_) \
                            ((_keymap1_) & (_keymap2_) & \
                             mi_get_mask_all_keys_active(_keys_))
#define mi_copy_keys_active(_to_,_maxkeys_,_from_) \
                            (_to_)= (mi_get_mask_all_keys_active(_maxkeys_) & \
                                     (_from_))

	/* Param to/from mi_info */

typedef struct st_mi_isaminfo		/* Struct from h_info */
+16 −17
Original line number Diff line number Diff line
@@ -282,7 +282,7 @@ int chk_size(MI_CHECK *param, register MI_INFO *info)
  if ((skr=(my_off_t) info->state->key_file_length) != size)
  {
    /* Don't give error if file generated by myisampack */
    if (skr > size && info->s->state.key_map)
    if (skr > size && mi_is_any_key_active(info->s->state.key_map))
    {
      error=1;
      mi_check_print_error(param,
@@ -379,7 +379,7 @@ int chk_key(MI_CHECK *param, register MI_INFO *info)
       rec_per_key_part+=keyinfo->keysegs, key++, keyinfo++)
  {
    param->key_crc[key]=0;
    if (!(((ulonglong) 1 << key) & share->state.key_map))
    if (! mi_is_key_active(share->state.key_map, key))
    {
      /* Remember old statistics for key */
      memcpy((char*) rec_per_key_part,
@@ -507,7 +507,7 @@ int chk_key(MI_CHECK *param, register MI_INFO *info)
	     (int) ((my_off_t2double(key_totlength) -
		     my_off_t2double(all_keydata))*100.0/
		     my_off_t2double(key_totlength)));
    else if (all_totaldata != 0L && share->state.key_map)
    else if (all_totaldata != 0L && mi_is_any_key_active(share->state.key_map))
      puts("");
  }
  if (param->key_file_blocks != info->state->key_file_length &&
@@ -1034,7 +1034,7 @@ int chk_data_link(MI_CHECK *param, MI_INFO *info,int extend)
      for (key=0,keyinfo= info->s->keyinfo; key < info->s->base.keys;
	   key++,keyinfo++)
      {
	if ((((ulonglong) 1 << key) & info->s->state.key_map))
        if (mi_is_key_active(info->s->state.key_map, key))
	{
	  if(!(keyinfo->flag & HA_FULLTEXT))
	  {
@@ -1298,7 +1298,7 @@ int mi_repair(MI_CHECK *param, register MI_INFO *info,
  */

  if (param->testflag & T_CREATE_MISSING_KEYS)
    share->state.key_map= ((((ulonglong) 1L << share->base.keys)-1) &
    mi_copy_keys_active(share->state.key_map, share->base.keys,
                        param->keys_in_use);

  info->state->key_file_length=share->base.keystart;
@@ -1461,7 +1461,7 @@ static int writekeys(MI_CHECK *param, register MI_INFO *info, byte *buff,
  key=info->lastkey+info->s->base.max_key_length;
  for (i=0 ; i < info->s->base.keys ; i++)
  {
    if (((ulonglong) 1 << i) & info->s->state.key_map)
    if (mi_is_key_active(info->s->state.key_map, i))
    {
      if (info->s->keyinfo[i].flag & HA_FULLTEXT )
      {
@@ -1492,7 +1492,7 @@ static int writekeys(MI_CHECK *param, register MI_INFO *info, byte *buff,
    info->errkey=(int) i;			/* This key was found */
    while ( i-- > 0 )
    {
      if (((ulonglong) 1 << i) & info->s->state.key_map)
      if (mi_is_key_active(info->s->state.key_map, i))
      {
	if (info->s->keyinfo[i].flag & HA_FULLTEXT)
        {
@@ -1529,7 +1529,7 @@ int movepoint(register MI_INFO *info, byte *record, my_off_t oldpos,
  key=info->lastkey+info->s->base.max_key_length;
  for (i=0 ; i < info->s->base.keys; i++)
  {
    if (i != prot_key && (((ulonglong) 1 << i) & info->s->state.key_map))
    if (i != prot_key && mi_is_key_active(info->s->state.key_map, i))
    {
      key_length=_mi_make_key(info,i,key,record,oldpos);
      if (info->s->keyinfo[i].flag & HA_NOSAME)
@@ -1628,7 +1628,7 @@ int mi_sort_index(MI_CHECK *param, register MI_INFO *info, my_string name)
  for (key= 0,keyinfo= &share->keyinfo[0]; key < share->base.keys ;
       key++,keyinfo++)
  {
    if (!(((ulonglong) 1 << key) & share->state.key_map))
    if (! mi_is_key_active(info->s->state.key_map, key))
      continue;

    if (share->state.key_root[key] != HA_OFFSET_ERROR)
@@ -2023,7 +2023,7 @@ int mi_repair_by_sort(MI_CHECK *param, register MI_INFO *info,
    sort_param.read_cache=param->read_cache;
    sort_param.keyinfo=share->keyinfo+sort_param.key;
    sort_param.seg=sort_param.keyinfo->seg;
    if (!(((ulonglong) 1 << sort_param.key) & key_map))
    if (! mi_is_key_active(key_map, sort_param.key))
    {
      /* Remember old statistics for key */
      memcpy((char*) rec_per_key_part,
@@ -2084,7 +2084,7 @@ int mi_repair_by_sort(MI_CHECK *param, register MI_INFO *info,
    if (param->testflag & T_STATISTICS)
      update_key_parts(sort_param.keyinfo, rec_per_key_part, sort_param.unique,
		       (ulonglong) info->state->records);
    share->state.key_map|=(ulonglong) 1 << sort_param.key;
    mi_set_key_active(share->state.key_map, sort_param.key);

    if (sort_param.fix_datafile)
    {
@@ -2405,7 +2405,7 @@ int mi_repair_parallel(MI_CHECK *param, register MI_INFO *info,
    sort_param[i].key=key;
    sort_param[i].keyinfo=share->keyinfo+key;
    sort_param[i].seg=sort_param[i].keyinfo->seg;
    if (!(((ulonglong) 1 << key) & key_map))
    if (! mi_is_key_active(key_map, key))
    {
      /* Remember old statistics for key */
      memcpy((char*) rec_per_key_part,
@@ -3917,8 +3917,7 @@ void update_auto_increment_key(MI_CHECK *param, MI_INFO *info,
{
  byte *record;
  if (!info->s->base.auto_key ||
      !(((ulonglong) 1 << (info->s->base.auto_key-1)
	 & info->s->state.key_map)))
      ! mi_is_key_active(info->s->state.key_map, info->s->base.auto_key - 1))
  {
    if (!(param->testflag & T_VERY_SILENT))
      mi_check_print_info(param,
@@ -4070,7 +4069,7 @@ void mi_disable_non_unique_index(MI_INFO *info, ha_rows rows)
    if (!(key->flag & (HA_NOSAME | HA_SPATIAL | HA_AUTO_KEY)) &&
        ! mi_too_big_key_for_sort(key,rows) && info->s->base.auto_key != i+1)
    {
      share->state.key_map&= ~ ((ulonglong) 1 << i);
      mi_clear_key_active(share->state.key_map, i);
      info->update|= HA_STATE_CHANGED;
    }
  }
@@ -4094,7 +4093,7 @@ my_bool mi_test_if_sort_rep(MI_INFO *info, ha_rows rows,
    mi_repair_by_sort only works if we have at least one key. If we don't
    have any keys, we should use the normal repair.
  */
  if (!key_map)
  if (! mi_is_any_key_active(key_map))
    return FALSE;				/* Can't use sort */
  for (i=0 ; i < share->base.keys ; i++,key++)
  {
+1 −1
Original line number Diff line number Diff line
@@ -508,7 +508,7 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs,
  mi_int2store(share.state.header.key_parts,key_segs);
  mi_int2store(share.state.header.unique_key_parts,unique_key_parts);

  share.state.key_map = ((ulonglong) 1 << keys)-1;
  mi_set_all_keys_active(share.state.key_map, keys);
  share.base.keystart = share.state.state.key_file_length=
    MY_ALIGN(info_length, myisam_block_size);
  share.base.max_key_block_length=max_key_block_length;
+1 −1
Original line number Diff line number Diff line
@@ -74,7 +74,7 @@ int mi_delete(MI_INFO *info,const byte *record)
  old_key=info->lastkey2;
  for (i=0 ; i < share->base.keys ; i++ )
  {
    if (((ulonglong) 1 << i) & info->s->state.key_map)
    if (mi_is_key_active(info->s->state.key_map, i))
    {
      info->s->keyinfo[i].version++;
      if (info->s->keyinfo[i].flag & HA_FULLTEXT )
Loading