~vlad-lesin/percona-server/mysql-5.0.33-original

« back to all changes in this revision

Viewing changes to heap/hp_create.c

  • Committer: Vlad Lesin
  • Date: 2012-07-31 09:21:34 UTC
  • Revision ID: vladislav.lesin@percona.com-20120731092134-zfodx022b7992wsi
VirginĀ 5.0.33

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
 
2
 
 
3
   This program is free software; you can redistribute it and/or modify
 
4
   it under the terms of the GNU General Public License as published by
 
5
   the Free Software Foundation; either version 2 of the License, or
 
6
   (at your option) any later version.
 
7
 
 
8
   This program is distributed in the hope that it will be useful,
 
9
   but WITHOUT ANY WARRANTY; without even the implied warranty of
 
10
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
11
   GNU General Public License for more details.
 
12
 
 
13
   You should have received a copy of the GNU General Public License
 
14
   along with this program; if not, write to the Free Software
 
15
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
 
16
 
 
17
#include "heapdef.h"
 
18
 
 
19
static int keys_compare(heap_rb_param *param, uchar *key1, uchar *key2);
 
20
static void init_block(HP_BLOCK *block,uint reclength,ulong min_records,
 
21
                       ulong max_records);
 
22
 
 
23
int heap_create(const char *name, uint keys, HP_KEYDEF *keydef,
 
24
                uint reclength, ulong max_records, ulong min_records,
 
25
                HP_CREATE_INFO *create_info)
 
26
{
 
27
  uint i, j, key_segs, max_length, length;
 
28
  HP_SHARE *share;
 
29
  HA_KEYSEG *keyseg;
 
30
  
 
31
  DBUG_ENTER("heap_create");
 
32
  pthread_mutex_lock(&THR_LOCK_heap);
 
33
 
 
34
  if ((share= hp_find_named_heap(name)) && share->open_count == 0)
 
35
  {
 
36
    hp_free(share);
 
37
    share= NULL;
 
38
  }
 
39
  
 
40
  if (!share)
 
41
  {
 
42
    HP_KEYDEF *keyinfo;
 
43
    DBUG_PRINT("info",("Initializing new table"));
 
44
    
 
45
    /*
 
46
      We have to store sometimes byte* del_link in records,
 
47
      so the record length should be at least sizeof(byte*)
 
48
    */
 
49
    set_if_bigger(reclength, sizeof (byte*));
 
50
    
 
51
    for (i= key_segs= max_length= 0, keyinfo= keydef; i < keys; i++, keyinfo++)
 
52
    {
 
53
      bzero((char*) &keyinfo->block,sizeof(keyinfo->block));
 
54
      bzero((char*) &keyinfo->rb_tree ,sizeof(keyinfo->rb_tree));
 
55
      for (j= length= 0; j < keyinfo->keysegs; j++)
 
56
      {
 
57
        length+= keyinfo->seg[j].length;
 
58
        if (keyinfo->seg[j].null_bit)
 
59
        {
 
60
          length++;
 
61
          if (!(keyinfo->flag & HA_NULL_ARE_EQUAL))
 
62
            keyinfo->flag|= HA_NULL_PART_KEY;
 
63
          if (keyinfo->algorithm == HA_KEY_ALG_BTREE)
 
64
            keyinfo->rb_tree.size_of_element++;
 
65
        }
 
66
        switch (keyinfo->seg[j].type) {
 
67
        case HA_KEYTYPE_SHORT_INT:
 
68
        case HA_KEYTYPE_LONG_INT:
 
69
        case HA_KEYTYPE_FLOAT:
 
70
        case HA_KEYTYPE_DOUBLE:
 
71
        case HA_KEYTYPE_USHORT_INT:
 
72
        case HA_KEYTYPE_ULONG_INT:
 
73
        case HA_KEYTYPE_LONGLONG:
 
74
        case HA_KEYTYPE_ULONGLONG:
 
75
        case HA_KEYTYPE_INT24:
 
76
        case HA_KEYTYPE_UINT24:
 
77
        case HA_KEYTYPE_INT8:
 
78
          keyinfo->seg[j].flag|= HA_SWAP_KEY;
 
79
          break;
 
80
        case HA_KEYTYPE_VARBINARY1:
 
81
          /* Case-insensitiveness is handled in coll->hash_sort */
 
82
          keyinfo->seg[j].type= HA_KEYTYPE_VARTEXT1;
 
83
          /* fall_through */
 
84
        case HA_KEYTYPE_VARTEXT1:
 
85
          if (!my_binary_compare(keyinfo->seg[j].charset))
 
86
            keyinfo->flag|= HA_END_SPACE_KEY;
 
87
          keyinfo->flag|= HA_VAR_LENGTH_KEY;
 
88
          length+= 2;
 
89
          /* Save number of bytes used to store length */
 
90
          keyinfo->seg[j].bit_start= 1;
 
91
          break;
 
92
        case HA_KEYTYPE_VARBINARY2:
 
93
          /* Case-insensitiveness is handled in coll->hash_sort */
 
94
          /* fall_through */
 
95
        case HA_KEYTYPE_VARTEXT2:
 
96
          if (!my_binary_compare(keyinfo->seg[j].charset))
 
97
            keyinfo->flag|= HA_END_SPACE_KEY;
 
98
          keyinfo->flag|= HA_VAR_LENGTH_KEY;
 
99
          length+= 2;
 
100
          /* Save number of bytes used to store length */
 
101
          keyinfo->seg[j].bit_start= 2;
 
102
          /*
 
103
            Make future comparison simpler by only having to check for
 
104
            one type
 
105
          */
 
106
          keyinfo->seg[j].type= HA_KEYTYPE_VARTEXT1;
 
107
          break;
 
108
        default:
 
109
          break;
 
110
        }
 
111
        if (keyinfo->seg[j].flag & HA_END_SPACE_ARE_EQUAL)
 
112
          keyinfo->flag|= HA_END_SPACE_KEY;
 
113
      }
 
114
      keyinfo->length= length;
 
115
      length+= keyinfo->rb_tree.size_of_element + 
 
116
               ((keyinfo->algorithm == HA_KEY_ALG_BTREE) ? sizeof(byte*) : 0);
 
117
      if (length > max_length)
 
118
        max_length= length;
 
119
      key_segs+= keyinfo->keysegs;
 
120
      if (keyinfo->algorithm == HA_KEY_ALG_BTREE)
 
121
      {
 
122
        key_segs++; /* additional HA_KEYTYPE_END segment */
 
123
        if (keyinfo->flag & HA_VAR_LENGTH_KEY)
 
124
          keyinfo->get_key_length= hp_rb_var_key_length;
 
125
        else if (keyinfo->flag & HA_NULL_PART_KEY)
 
126
          keyinfo->get_key_length= hp_rb_null_key_length;
 
127
        else
 
128
          keyinfo->get_key_length= hp_rb_key_length;
 
129
      }
 
130
    }
 
131
    if (!(share= (HP_SHARE*) my_malloc((uint) sizeof(HP_SHARE)+
 
132
                                       keys*sizeof(HP_KEYDEF)+
 
133
                                       key_segs*sizeof(HA_KEYSEG),
 
134
                                       MYF(MY_ZEROFILL))))
 
135
    {
 
136
      pthread_mutex_unlock(&THR_LOCK_heap);
 
137
      DBUG_RETURN(1);
 
138
    }
 
139
    share->keydef= (HP_KEYDEF*) (share + 1);
 
140
    share->key_stat_version= 1;
 
141
    keyseg= (HA_KEYSEG*) (share->keydef + keys);
 
142
    init_block(&share->block, reclength + 1, min_records, max_records);
 
143
        /* Fix keys */
 
144
    memcpy(share->keydef, keydef, (size_t) (sizeof(keydef[0]) * keys));
 
145
    for (i= 0, keyinfo= share->keydef; i < keys; i++, keyinfo++)
 
146
    {
 
147
      keyinfo->seg= keyseg;
 
148
      memcpy(keyseg, keydef[i].seg,
 
149
             (size_t) (sizeof(keyseg[0]) * keydef[i].keysegs));
 
150
      keyseg+= keydef[i].keysegs;
 
151
 
 
152
      if (keydef[i].algorithm == HA_KEY_ALG_BTREE)
 
153
      {
 
154
        /* additional HA_KEYTYPE_END keyseg */
 
155
        keyseg->type=     HA_KEYTYPE_END;
 
156
        keyseg->length=   sizeof(byte*);
 
157
        keyseg->flag=     0;
 
158
        keyseg->null_bit= 0;
 
159
        keyseg++;
 
160
 
 
161
        init_tree(&keyinfo->rb_tree, 0, 0, sizeof(byte*),
 
162
                  (qsort_cmp2)keys_compare, 1, NULL, NULL);
 
163
        keyinfo->delete_key= hp_rb_delete_key;
 
164
        keyinfo->write_key= hp_rb_write_key;
 
165
      }
 
166
      else
 
167
      {
 
168
        init_block(&keyinfo->block, sizeof(HASH_INFO), min_records,
 
169
                   max_records);
 
170
        keyinfo->delete_key= hp_delete_key;
 
171
        keyinfo->write_key= hp_write_key;
 
172
        keyinfo->hash_buckets= 0;
 
173
      }
 
174
      if ((keyinfo->flag & HA_AUTO_KEY) && create_info->with_auto_increment)
 
175
        share->auto_key= i + 1;
 
176
    }
 
177
    share->min_records= min_records;
 
178
    share->max_records= max_records;
 
179
    share->max_table_size= create_info->max_table_size;
 
180
    share->data_length= share->index_length= 0;
 
181
    share->reclength= reclength;
 
182
    share->blength= 1;
 
183
    share->keys= keys;
 
184
    share->max_key_length= max_length;
 
185
    share->changed= 0;
 
186
    share->auto_key= create_info->auto_key;
 
187
    share->auto_key_type= create_info->auto_key_type;
 
188
    share->auto_increment= create_info->auto_increment;
 
189
    /* Must be allocated separately for rename to work */
 
190
    if (!(share->name= my_strdup(name,MYF(0))))
 
191
    {
 
192
      my_free((gptr) share,MYF(0));
 
193
      pthread_mutex_unlock(&THR_LOCK_heap);
 
194
      DBUG_RETURN(1);
 
195
    }
 
196
#ifdef THREAD
 
197
    thr_lock_init(&share->lock);
 
198
    VOID(pthread_mutex_init(&share->intern_lock,MY_MUTEX_INIT_FAST));
 
199
#endif
 
200
    share->open_list.data= (void*) share;
 
201
    heap_share_list= list_add(heap_share_list,&share->open_list);
 
202
  }
 
203
  pthread_mutex_unlock(&THR_LOCK_heap);
 
204
  DBUG_RETURN(0);
 
205
} /* heap_create */
 
206
 
 
207
static int keys_compare(heap_rb_param *param, uchar *key1, uchar *key2)
 
208
{
 
209
  uint not_used[2];
 
210
  return ha_key_cmp(param->keyseg, key1, key2, param->key_length, 
 
211
                    param->search_flag, not_used);
 
212
}
 
213
 
 
214
static void init_block(HP_BLOCK *block, uint reclength, ulong min_records,
 
215
                       ulong max_records)
 
216
{
 
217
  uint i,recbuffer,records_in_block;
 
218
 
 
219
  max_records= max(min_records,max_records);
 
220
  if (!max_records)
 
221
    max_records= 1000;                  /* As good as quess as anything */
 
222
  recbuffer= (uint) (reclength + sizeof(byte**) - 1) & ~(sizeof(byte**) - 1);
 
223
  records_in_block= max_records / 10;
 
224
  if (records_in_block < 10 && max_records)
 
225
    records_in_block= 10;
 
226
  if (!records_in_block || records_in_block*recbuffer >
 
227
      (my_default_record_cache_size-sizeof(HP_PTRS)*HP_MAX_LEVELS))
 
228
    records_in_block= (my_default_record_cache_size - sizeof(HP_PTRS) *
 
229
                      HP_MAX_LEVELS) / recbuffer + 1;
 
230
  block->records_in_block= records_in_block;
 
231
  block->recbuffer= recbuffer;
 
232
  block->last_allocated= 0L;
 
233
 
 
234
  for (i= 0; i <= HP_MAX_LEVELS; i++)
 
235
    block->level_info[i].records_under_level=
 
236
      (!i ? 1 : i == 1 ? records_in_block :
 
237
       HP_PTRS_IN_NOD * block->level_info[i - 1].records_under_level);
 
238
}
 
239
 
 
240
int heap_delete_table(const char *name)
 
241
{
 
242
  int result;
 
243
  reg1 HP_SHARE *share;
 
244
  DBUG_ENTER("heap_delete_table");
 
245
 
 
246
  pthread_mutex_lock(&THR_LOCK_heap);
 
247
  if ((share= hp_find_named_heap(name)))
 
248
  {
 
249
    if (share->open_count == 0)
 
250
      hp_free(share);
 
251
    else
 
252
     share->delete_on_close= 1;
 
253
    result= 0;
 
254
  }
 
255
  else
 
256
  {
 
257
    result= my_errno=ENOENT;
 
258
  }
 
259
  pthread_mutex_unlock(&THR_LOCK_heap);
 
260
  DBUG_RETURN(result);
 
261
}
 
262
 
 
263
void hp_free(HP_SHARE *share)
 
264
{
 
265
  heap_share_list= list_delete(heap_share_list, &share->open_list);
 
266
  hp_clear(share);                      /* Remove blocks from memory */
 
267
#ifdef THREAD
 
268
  thr_lock_delete(&share->lock);
 
269
  VOID(pthread_mutex_destroy(&share->intern_lock));
 
270
#endif
 
271
  my_free((gptr) share->name, MYF(0));
 
272
  my_free((gptr) share, MYF(0));
 
273
  return;
 
274
}