~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to plugin/heap/hp_create.cc

  • Committer: LinuxJedi
  • Date: 2010-09-09 06:14:45 UTC
  • mto: (1750.1.1 build)
  • mto: This revision was merged to the branch mainline in revision 1751.
  • Revision ID: linuxjedi@linuxjedi-laptop-20100909061445-1jz91d5eed932616
Fix another wrong header, grr...

Show diffs side-by-side

added added

removed removed

Lines of Context:
11
11
 
12
12
   You should have received a copy of the GNU General Public License
13
13
   along with this program; if not, write to the Free Software
14
 
   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA */
 
14
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
15
15
 
16
16
#include "heap_priv.h"
17
17
 
24
24
using namespace std;
25
25
using namespace drizzled;
26
26
 
 
27
static int keys_compare(heap_rb_param *param, unsigned char *key1, unsigned char *key2);
27
28
static void init_block(HP_BLOCK *block,uint32_t chunk_length, uint32_t min_records,
28
29
                        uint32_t max_records);
29
30
 
38
39
/* Create a heap table */
39
40
 
40
41
int heap_create(const char *name, uint32_t keys, HP_KEYDEF *keydef,
41
 
                uint32_t columns,
42
 
                uint32_t key_part_size,
43
 
                uint32_t reclength, uint32_t keys_memory_size,
44
 
                uint32_t max_records, uint32_t min_records,
45
 
                HP_CREATE_INFO *create_info, HP_SHARE **res)
 
42
    uint32_t columns, HP_COLUMNDEF *columndef,
 
43
    uint32_t max_key_fieldnr, uint32_t key_part_size,
 
44
    uint32_t reclength, uint32_t keys_memory_size,
 
45
    uint32_t max_records, uint32_t min_records,
 
46
    HP_CREATE_INFO *create_info, HP_SHARE **res)
46
47
{
47
48
  uint32_t i, key_segs, max_length, length;
48
49
  uint32_t max_rows_for_stated_memory;
49
50
  HP_SHARE *share= 0;
50
51
  HA_KEYSEG *keyseg;
51
52
 
52
 
  if (not create_info->internal_table)
 
53
  if (!create_info->internal_table)
53
54
  {
54
55
    THR_LOCK_heap.lock();
55
56
    if ((share= hp_find_named_heap(name)) && share->open_count == 0)
62
63
  if (!share)
63
64
  {
64
65
    size_t chunk_dataspace_length;
65
 
    uint32_t chunk_length;
 
66
    uint32_t chunk_length, is_variable_size;
66
67
    uint32_t fixed_data_length, fixed_column_count;
67
68
    HP_KEYDEF *keyinfo;
68
69
 
75
76
      if (configured_chunk_size < key_part_size)
76
77
      {
77
78
        /* Eventual chunk_size cannot be smaller than key data,
78
 
          which allows all keys to fit into the first chunk */
 
79
           which allows all keys to fit into the first chunk */
79
80
        my_error(ER_CANT_USE_OPTION_HERE, MYF(0), "block_size");
80
81
        THR_LOCK_heap.unlock();
81
82
        return(ER_CANT_USE_OPTION_HERE);
82
83
      }
83
84
 
84
 
      /* max_chunk_size is near the full reclength, let's use fixed size */
85
 
      chunk_dataspace_length= reclength;
 
85
      if ((reclength - configured_chunk_size) >= VARIABLE_MIN_CHUNK_SIZE<<1)
 
86
      {
 
87
        /* Allow variable size only if we're saving at least two smallest chunks */
 
88
        /* There has to be at least one field after indexed fields */
 
89
        /* Note that NULL bits are already included in key_part_size */
 
90
        is_variable_size= 1;
 
91
        chunk_dataspace_length= configured_chunk_size;
 
92
      }
 
93
      else
 
94
      {
 
95
        /* max_chunk_size is near the full reclength, let's use fixed size */
 
96
        is_variable_size= 0;
 
97
        chunk_dataspace_length= reclength;
 
98
      }
 
99
    }
 
100
    else if (create_info->is_dynamic)
 
101
    {
 
102
      /* User asked for dynamic records - use 256 as the chunk size */
 
103
      if ((key_part_size + VARIABLE_REC_OVERHEAD) > 256)
 
104
        chunk_dataspace_length= key_part_size;
 
105
      else
 
106
        chunk_dataspace_length= 256 - VARIABLE_REC_OVERHEAD;
 
107
 
 
108
      is_variable_size= 1;
86
109
    }
87
110
    else
88
111
    {
89
112
      /* if max_chunk_size is not specified, put the whole record in one chunk */
 
113
      is_variable_size= 0;
90
114
      chunk_dataspace_length= reclength;
91
115
    }
92
116
 
 
117
    if (is_variable_size)
 
118
    {
 
119
      /* Check whether we have any variable size records past key data */
 
120
      uint32_t has_variable_fields= 0;
 
121
 
 
122
      fixed_data_length= key_part_size;
 
123
      fixed_column_count= max_key_fieldnr;
 
124
 
 
125
      for (i= max_key_fieldnr; i < columns; i++)
 
126
      {
 
127
        HP_COLUMNDEF* column= columndef + i;
 
128
        if (column->type == DRIZZLE_TYPE_VARCHAR && column->length >= 32)
 
129
        {
 
130
            /* The field has to be >= 5.0.3 true VARCHAR and have substantial length */
 
131
            /* TODO: do we want to calculate minimum length? */
 
132
            has_variable_fields= 1;
 
133
            break;
 
134
        }
 
135
 
 
136
        if (has_variable_fields)
 
137
        {
 
138
          break;
 
139
        }
 
140
 
 
141
        if ((column->offset + column->length) <= chunk_dataspace_length)
 
142
        {
 
143
          /* Still no variable-size columns, add one fixed-length */
 
144
          fixed_column_count= i + 1;
 
145
          fixed_data_length= column->offset + column->length;
 
146
        }
 
147
      }
 
148
 
 
149
      if (!has_variable_fields)
 
150
      {
 
151
        /* There is no need to use variable-size records without variable-size columns */
 
152
        /* Reset sizes if it's not variable size anymore */
 
153
        is_variable_size= 0;
 
154
        chunk_dataspace_length= reclength;
 
155
        fixed_data_length= reclength;
 
156
        fixed_column_count= columns;
 
157
      }
 
158
    }
 
159
    else
93
160
    {
94
161
      fixed_data_length= reclength;
95
162
      fixed_column_count= columns;
101
168
    */
102
169
    set_if_bigger(chunk_dataspace_length, sizeof (unsigned char**));
103
170
 
 
171
    if (is_variable_size)
 
172
    {
 
173
      chunk_length= chunk_dataspace_length + VARIABLE_REC_OVERHEAD;
 
174
    }
 
175
    else
104
176
    {
105
177
      chunk_length= chunk_dataspace_length + FIXED_REC_OVERHEAD;
106
178
    }
113
185
    for (i= key_segs= max_length= 0, keyinfo= keydef; i < keys; i++, keyinfo++)
114
186
    {
115
187
      memset(&keyinfo->block, 0, sizeof(keyinfo->block));
 
188
      memset(&keyinfo->rb_tree , 0, sizeof(keyinfo->rb_tree));
116
189
      for (uint32_t j= length= 0; j < keyinfo->keysegs; j++)
117
190
      {
118
191
        length+= keyinfo->seg[j].length;
121
194
          length++;
122
195
          if (!(keyinfo->flag & HA_NULL_ARE_EQUAL))
123
196
            keyinfo->flag|= HA_NULL_PART_KEY;
 
197
          if (keyinfo->algorithm == HA_KEY_ALG_BTREE)
 
198
            keyinfo->rb_tree.size_of_element++;
124
199
        }
125
200
        switch (keyinfo->seg[j].type) {
126
201
        case HA_KEYTYPE_LONG_INT:
128
203
        case HA_KEYTYPE_ULONG_INT:
129
204
        case HA_KEYTYPE_LONGLONG:
130
205
        case HA_KEYTYPE_ULONGLONG:
 
206
        case HA_KEYTYPE_UINT24:
131
207
          keyinfo->seg[j].flag|= HA_SWAP_KEY;
132
208
          break;
133
209
        case HA_KEYTYPE_VARBINARY1:
159
235
        }
160
236
      }
161
237
      keyinfo->length= length;
 
238
      length+= keyinfo->rb_tree.size_of_element +
 
239
               ((keyinfo->algorithm == HA_KEY_ALG_BTREE) ? sizeof(unsigned char*) : 0);
162
240
      if (length > max_length)
163
241
        max_length= length;
164
242
      key_segs+= keyinfo->keysegs;
 
243
      if (keyinfo->algorithm == HA_KEY_ALG_BTREE)
 
244
      {
 
245
        key_segs++; /* additional HA_KEYTYPE_END segment */
 
246
        if (keyinfo->flag & HA_VAR_LENGTH_KEY)
 
247
          keyinfo->get_key_length= hp_rb_var_key_length;
 
248
        else if (keyinfo->flag & HA_NULL_PART_KEY)
 
249
          keyinfo->get_key_length= hp_rb_null_key_length;
 
250
        else
 
251
          keyinfo->get_key_length= hp_rb_key_length;
 
252
      }
165
253
    }
166
254
    share= new HP_SHARE;
167
255
 
169
257
      goto err;
170
258
    if (keys && !(share->keydef->seg= new HA_KEYSEG[key_segs]))
171
259
      goto err;
 
260
    if (!(share->column_defs= new HP_COLUMNDEF[columns]))
 
261
      goto err;
172
262
 
173
263
    /*
174
264
       Max_records is used for estimating block sizes and for enforcement.
192
282
      memcpy(keyseg, keydef[i].seg,
193
283
             (size_t) (sizeof(keyseg[0]) * keydef[i].keysegs));
194
284
      keyseg+= keydef[i].keysegs;
 
285
 
 
286
      if (keydef[i].algorithm == HA_KEY_ALG_BTREE)
 
287
      {
 
288
        /* additional HA_KEYTYPE_END keyseg */
 
289
        keyseg->type=     HA_KEYTYPE_END;
 
290
        keyseg->length=   sizeof(unsigned char*);
 
291
        keyseg->flag=     0;
 
292
        keyseg->null_bit= 0;
 
293
        keyseg++;
 
294
 
 
295
        init_tree(&keyinfo->rb_tree, 0, 0, sizeof(unsigned char*),
 
296
                  (qsort_cmp2)keys_compare, true, NULL, NULL);
 
297
        keyinfo->delete_key= hp_rb_delete_key;
 
298
        keyinfo->write_key= hp_rb_write_key;
 
299
      }
 
300
      else
195
301
      {
196
302
        init_block(&keyinfo->block, sizeof(HASH_INFO), min_records,
197
303
                   max_records);
 
304
        keyinfo->delete_key= hp_delete_key;
 
305
        keyinfo->write_key= hp_write_key;
198
306
        keyinfo->hash_buckets= 0;
199
307
      }
200
308
      if ((keyinfo->flag & HA_AUTO_KEY) && create_info->with_auto_increment)
218
326
 
219
327
    share->recordspace.chunk_length= chunk_length;
220
328
    share->recordspace.chunk_dataspace_length= chunk_dataspace_length;
 
329
    share->recordspace.is_variable_size= is_variable_size;
221
330
    share->recordspace.total_data_length= 0;
222
331
 
223
 
    {
 
332
    if (is_variable_size) {
 
333
      share->recordspace.offset_link= chunk_dataspace_length;
 
334
      share->recordspace.offset_status= share->recordspace.offset_link + sizeof(unsigned char**);
 
335
    } else {
224
336
      share->recordspace.offset_link= 1<<22; /* Make it likely to fail if anyone uses this offset */
225
337
      share->recordspace.offset_status= chunk_dataspace_length;
226
338
    }
227
339
 
228
340
    /* Must be allocated separately for rename to work */
229
341
    share->name.append(name);
 
342
    thr_lock_init(&share->lock);
230
343
    if (!create_info->internal_table)
231
344
    {
232
345
      heap_share_list.push_front(share);
245
358
    delete [] share->keydef->seg;
246
359
  if (share && share->keydef)
247
360
    delete [] share->keydef;
 
361
  if (share && share->column_defs)
 
362
    delete [] share->column_defs;
248
363
  if (share)
249
364
    delete share;
250
365
  if (not create_info->internal_table)
253
368
} /* heap_create */
254
369
 
255
370
 
 
371
static int keys_compare(heap_rb_param *param, unsigned char *key1, unsigned char *key2)
 
372
{
 
373
  uint32_t not_used[2];
 
374
  return ha_key_cmp(param->keyseg, key1, key2, param->key_length,
 
375
                    param->search_flag, not_used);
 
376
}
 
377
 
256
378
static void init_block(HP_BLOCK *block, uint32_t chunk_length, uint32_t min_records,
257
379
                       uint32_t max_records)
258
380
{
317
439
{
318
440
  heap_share_list.remove(share);        /* If not internal table */
319
441
  hp_clear(share);                      /* Remove blocks from memory */
 
442
  share->lock.deinit();
320
443
  if (share->keydef)
321
444
    delete [] share->keydef->seg;
322
445
  delete [] share->keydef;
 
446
  delete [] share->column_defs;
323
447
  delete share;
324
448
}