~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to plugin/heap/hp_create.cc

  • Committer: Padraig O'Sullivan
  • Date: 2010-02-10 16:26:01 UTC
  • mto: This revision was merged to the branch mainline in revision 1294.
  • Revision ID: osullivan.padraig@gmail.com-20100210162601-itx2ndl397pc1wr6
Corrected an order of initialization in a few optimizer classes

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
 
18
18
#include <drizzled/common.h>
19
19
#include <drizzled/error.h>
 
20
#include "drizzled/my_error.h"
20
21
 
21
22
#include <string.h>
22
23
#include <algorithm>
24
25
using namespace std;
25
26
using namespace drizzled;
26
27
 
 
28
static int keys_compare(heap_rb_param *param, unsigned char *key1, unsigned char *key2);
27
29
static void init_block(HP_BLOCK *block,uint32_t chunk_length, uint32_t min_records,
28
30
                        uint32_t max_records);
29
31
 
38
40
/* Create a heap table */
39
41
 
40
42
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)
 
43
    uint32_t columns, HP_COLUMNDEF *columndef,
 
44
    uint32_t max_key_fieldnr, uint32_t key_part_size,
 
45
    uint32_t reclength, uint32_t keys_memory_size,
 
46
    uint32_t max_records, uint32_t min_records,
 
47
    HP_CREATE_INFO *create_info, HP_SHARE **res)
46
48
{
47
 
  uint32_t i, key_segs, max_length, length;
 
49
  uint32_t i, j, key_segs, max_length, length;
48
50
  uint32_t max_rows_for_stated_memory;
49
51
  HP_SHARE *share= 0;
50
52
  HA_KEYSEG *keyseg;
51
53
 
52
 
  if (not create_info->internal_table)
 
54
  if (!create_info->internal_table)
53
55
  {
54
 
    THR_LOCK_heap.lock();
 
56
    pthread_mutex_lock(&THR_LOCK_heap);
55
57
    if ((share= hp_find_named_heap(name)) && share->open_count == 0)
56
58
    {
57
59
      hp_free(share);
62
64
  if (!share)
63
65
  {
64
66
    size_t chunk_dataspace_length;
65
 
    uint32_t chunk_length;
 
67
    uint32_t chunk_length, is_variable_size;
66
68
    uint32_t fixed_data_length, fixed_column_count;
67
69
    HP_KEYDEF *keyinfo;
68
70
 
75
77
      if (configured_chunk_size < key_part_size)
76
78
      {
77
79
        /* Eventual chunk_size cannot be smaller than key data,
78
 
          which allows all keys to fit into the first chunk */
 
80
           which allows all keys to fit into the first chunk */
79
81
        my_error(ER_CANT_USE_OPTION_HERE, MYF(0), "block_size");
80
 
        THR_LOCK_heap.unlock();
 
82
        pthread_mutex_unlock(&THR_LOCK_heap);
81
83
        return(ER_CANT_USE_OPTION_HERE);
82
84
      }
83
85
 
84
 
      /* max_chunk_size is near the full reclength, let's use fixed size */
85
 
      chunk_dataspace_length= reclength;
 
86
      if ((reclength - configured_chunk_size) >= VARIABLE_MIN_CHUNK_SIZE<<1)
 
87
      {
 
88
        /* Allow variable size only if we're saving at least two smallest chunks */
 
89
        /* There has to be at least one field after indexed fields */
 
90
        /* Note that NULL bits are already included in key_part_size */
 
91
        is_variable_size= 1;
 
92
        chunk_dataspace_length= configured_chunk_size;
 
93
      }
 
94
      else
 
95
      {
 
96
        /* max_chunk_size is near the full reclength, let's use fixed size */
 
97
        is_variable_size= 0;
 
98
        chunk_dataspace_length= reclength;
 
99
      }
 
100
    }
 
101
    else if (create_info->is_dynamic)
 
102
    {
 
103
      /* User asked for dynamic records - use 256 as the chunk size */
 
104
      if ((key_part_size + VARIABLE_REC_OVERHEAD) > 256)
 
105
        chunk_dataspace_length= key_part_size;
 
106
      else
 
107
        chunk_dataspace_length= 256 - VARIABLE_REC_OVERHEAD;
 
108
 
 
109
      is_variable_size= 1;
86
110
    }
87
111
    else
88
112
    {
89
113
      /* if max_chunk_size is not specified, put the whole record in one chunk */
 
114
      is_variable_size= 0;
90
115
      chunk_dataspace_length= reclength;
91
116
    }
92
117
 
 
118
    if (is_variable_size)
 
119
    {
 
120
      /* Check whether we have any variable size records past key data */
 
121
      uint32_t has_variable_fields= 0;
 
122
 
 
123
      fixed_data_length= key_part_size;
 
124
      fixed_column_count= max_key_fieldnr;
 
125
 
 
126
      for (i= max_key_fieldnr; i < columns; i++)
 
127
      {
 
128
        HP_COLUMNDEF* column= columndef + i;
 
129
        if (column->type == DRIZZLE_TYPE_VARCHAR && column->length >= 32)
 
130
        {
 
131
            /* The field has to be >= 5.0.3 true VARCHAR and have substantial length */
 
132
            /* TODO: do we want to calculate minimum length? */
 
133
            has_variable_fields= 1;
 
134
            break;
 
135
        }
 
136
 
 
137
        if (has_variable_fields)
 
138
        {
 
139
          break;
 
140
        }
 
141
 
 
142
        if ((column->offset + column->length) <= chunk_dataspace_length)
 
143
        {
 
144
          /* Still no variable-size columns, add one fixed-length */
 
145
          fixed_column_count= i + 1;
 
146
          fixed_data_length= column->offset + column->length;
 
147
        }
 
148
      }
 
149
 
 
150
      if (!has_variable_fields)
 
151
      {
 
152
        /* There is no need to use variable-size records without variable-size columns */
 
153
        /* Reset sizes if it's not variable size anymore */
 
154
        is_variable_size= 0;
 
155
        chunk_dataspace_length= reclength;
 
156
        fixed_data_length= reclength;
 
157
        fixed_column_count= columns;
 
158
      }
 
159
    }
 
160
    else
93
161
    {
94
162
      fixed_data_length= reclength;
95
163
      fixed_column_count= columns;
101
169
    */
102
170
    set_if_bigger(chunk_dataspace_length, sizeof (unsigned char**));
103
171
 
 
172
    if (is_variable_size)
 
173
    {
 
174
      chunk_length= chunk_dataspace_length + VARIABLE_REC_OVERHEAD;
 
175
    }
 
176
    else
104
177
    {
105
178
      chunk_length= chunk_dataspace_length + FIXED_REC_OVERHEAD;
106
179
    }
113
186
    for (i= key_segs= max_length= 0, keyinfo= keydef; i < keys; i++, keyinfo++)
114
187
    {
115
188
      memset(&keyinfo->block, 0, sizeof(keyinfo->block));
116
 
      for (uint32_t j= length= 0; j < keyinfo->keysegs; j++)
 
189
      memset(&keyinfo->rb_tree , 0, sizeof(keyinfo->rb_tree));
 
190
      for (j= length= 0; j < keyinfo->keysegs; j++)
117
191
      {
118
192
        length+= keyinfo->seg[j].length;
119
193
        if (keyinfo->seg[j].null_bit)
121
195
          length++;
122
196
          if (!(keyinfo->flag & HA_NULL_ARE_EQUAL))
123
197
            keyinfo->flag|= HA_NULL_PART_KEY;
 
198
          if (keyinfo->algorithm == HA_KEY_ALG_BTREE)
 
199
            keyinfo->rb_tree.size_of_element++;
124
200
        }
125
201
        switch (keyinfo->seg[j].type) {
126
202
        case HA_KEYTYPE_LONG_INT:
128
204
        case HA_KEYTYPE_ULONG_INT:
129
205
        case HA_KEYTYPE_LONGLONG:
130
206
        case HA_KEYTYPE_ULONGLONG:
 
207
        case HA_KEYTYPE_UINT24:
131
208
          keyinfo->seg[j].flag|= HA_SWAP_KEY;
132
209
          break;
133
210
        case HA_KEYTYPE_VARBINARY1:
159
236
        }
160
237
      }
161
238
      keyinfo->length= length;
 
239
      length+= keyinfo->rb_tree.size_of_element +
 
240
               ((keyinfo->algorithm == HA_KEY_ALG_BTREE) ? sizeof(unsigned char*) : 0);
162
241
      if (length > max_length)
163
242
        max_length= length;
164
243
      key_segs+= keyinfo->keysegs;
 
244
      if (keyinfo->algorithm == HA_KEY_ALG_BTREE)
 
245
      {
 
246
        key_segs++; /* additional HA_KEYTYPE_END segment */
 
247
        if (keyinfo->flag & HA_VAR_LENGTH_KEY)
 
248
          keyinfo->get_key_length= hp_rb_var_key_length;
 
249
        else if (keyinfo->flag & HA_NULL_PART_KEY)
 
250
          keyinfo->get_key_length= hp_rb_null_key_length;
 
251
        else
 
252
          keyinfo->get_key_length= hp_rb_key_length;
 
253
      }
165
254
    }
166
 
    share= new HP_SHARE;
167
 
 
168
 
    if (keys && !(share->keydef= new HP_KEYDEF[keys]))
169
 
      goto err;
170
 
    if (keys && !(share->keydef->seg= new HA_KEYSEG[key_segs]))
171
 
      goto err;
 
255
    share= NULL;
 
256
    if (!(share= (HP_SHARE*) malloc(sizeof(HP_SHARE))))
 
257
      goto err;
 
258
 
 
259
    memset(share, 0, sizeof(HP_SHARE));
 
260
 
 
261
    if (keys && !(share->keydef= (HP_KEYDEF*) malloc(keys*sizeof(HP_KEYDEF))))
 
262
      goto err;
 
263
 
 
264
    memset(share->keydef, 0, keys*sizeof(HP_KEYDEF));
 
265
 
 
266
    if (keys && !(share->keydef->seg= (HA_KEYSEG*) malloc(key_segs*sizeof(HA_KEYSEG))))
 
267
      goto err;
 
268
    if (!(share->column_defs= (HP_COLUMNDEF*)
 
269
          malloc(columns*sizeof(HP_COLUMNDEF))))
 
270
      goto err;
 
271
 
 
272
    memset(share->column_defs, 0, columns*sizeof(HP_COLUMNDEF));
172
273
 
173
274
    /*
174
275
       Max_records is used for estimating block sizes and for enforcement.
180
281
    max_records = ((max_records && max_records < max_rows_for_stated_memory) ?
181
282
                      max_records : max_rows_for_stated_memory);
182
283
 
 
284
    memcpy(share->column_defs, columndef, (size_t) (sizeof(columndef[0]) * columns));
 
285
 
183
286
    share->key_stat_version= 1;
184
287
    keyseg= keys ? share->keydef->seg : NULL;
185
288
 
192
295
      memcpy(keyseg, keydef[i].seg,
193
296
             (size_t) (sizeof(keyseg[0]) * keydef[i].keysegs));
194
297
      keyseg+= keydef[i].keysegs;
 
298
 
 
299
      if (keydef[i].algorithm == HA_KEY_ALG_BTREE)
 
300
      {
 
301
        /* additional HA_KEYTYPE_END keyseg */
 
302
        keyseg->type=     HA_KEYTYPE_END;
 
303
        keyseg->length=   sizeof(unsigned char*);
 
304
        keyseg->flag=     0;
 
305
        keyseg->null_bit= 0;
 
306
        keyseg++;
 
307
 
 
308
        init_tree(&keyinfo->rb_tree, 0, 0, sizeof(unsigned char*),
 
309
                  (qsort_cmp2)keys_compare, true, NULL, NULL);
 
310
        keyinfo->delete_key= hp_rb_delete_key;
 
311
        keyinfo->write_key= hp_rb_write_key;
 
312
      }
 
313
      else
195
314
      {
196
315
        init_block(&keyinfo->block, sizeof(HASH_INFO), min_records,
197
316
                   max_records);
 
317
        keyinfo->delete_key= hp_delete_key;
 
318
        keyinfo->write_key= hp_write_key;
198
319
        keyinfo->hash_buckets= 0;
199
320
      }
200
321
      if ((keyinfo->flag & HA_AUTO_KEY) && create_info->with_auto_increment)
218
339
 
219
340
    share->recordspace.chunk_length= chunk_length;
220
341
    share->recordspace.chunk_dataspace_length= chunk_dataspace_length;
 
342
    share->recordspace.is_variable_size= is_variable_size;
221
343
    share->recordspace.total_data_length= 0;
222
344
 
223
 
    {
 
345
    if (is_variable_size) {
 
346
      share->recordspace.offset_link= chunk_dataspace_length;
 
347
      share->recordspace.offset_status= share->recordspace.offset_link + sizeof(unsigned char**);
 
348
    } else {
224
349
      share->recordspace.offset_link= 1<<22; /* Make it likely to fail if anyone uses this offset */
225
350
      share->recordspace.offset_status= chunk_dataspace_length;
226
351
    }
227
352
 
228
353
    /* Must be allocated separately for rename to work */
229
 
    share->name.append(name);
 
354
    if (!(share->name= strdup(name)))
 
355
    {
 
356
      goto err;
 
357
    }
 
358
    thr_lock_init(&share->lock);
 
359
    pthread_mutex_init(&share->intern_lock,MY_MUTEX_INIT_FAST);
230
360
    if (!create_info->internal_table)
231
361
    {
232
362
      heap_share_list.push_front(share);
235
365
      share->delete_on_close= 1;
236
366
  }
237
367
  if (!create_info->internal_table)
238
 
    THR_LOCK_heap.unlock();
 
368
    pthread_mutex_unlock(&THR_LOCK_heap);
239
369
 
240
370
  *res= share;
241
371
  return(0);
242
372
 
243
373
err:
244
 
  if (share && share->keydef && share->keydef->seg)
245
 
    delete [] share->keydef->seg;
246
 
  if (share && share->keydef)
247
 
    delete [] share->keydef;
248
 
  if (share)
249
 
    delete share;
250
 
  if (not create_info->internal_table)
251
 
    THR_LOCK_heap.unlock();
 
374
  if(share && share->keydef && share->keydef->seg)
 
375
    free(share->keydef->seg);
 
376
  if(share && share->keydef)
 
377
    free(share->keydef);
 
378
  if(share && share->column_defs)
 
379
    free(share->column_defs);
 
380
  if(share)
 
381
    free(share);
 
382
  if (!create_info->internal_table)
 
383
    pthread_mutex_unlock(&THR_LOCK_heap);
252
384
  return(1);
253
385
} /* heap_create */
254
386
 
255
387
 
 
388
static int keys_compare(heap_rb_param *param, unsigned char *key1, unsigned char *key2)
 
389
{
 
390
  uint32_t not_used[2];
 
391
  return ha_key_cmp(param->keyseg, key1, key2, param->key_length,
 
392
                    param->search_flag, not_used);
 
393
}
 
394
 
256
395
static void init_block(HP_BLOCK *block, uint32_t chunk_length, uint32_t min_records,
257
396
                       uint32_t max_records)
258
397
{
259
 
  uint32_t recbuffer,records_in_block;
 
398
  uint32_t i,recbuffer,records_in_block;
260
399
 
261
400
  max_records= max(min_records,max_records);
262
401
  if (!max_records)
275
414
  block->recbuffer= recbuffer;
276
415
  block->last_allocated= 0L;
277
416
 
278
 
  for (uint32_t i= 0; i <= HP_MAX_LEVELS; i++)
279
 
  {
 
417
  for (i= 0; i <= HP_MAX_LEVELS; i++)
280
418
    block->level_info[i].records_under_level=
281
419
      (!i ? 1 : i == 1 ? records_in_block :
282
420
       HP_PTRS_IN_NOD * block->level_info[i - 1].records_under_level);
283
 
  }
284
421
}
285
422
 
286
423
 
298
435
  int result;
299
436
  register HP_SHARE *share;
300
437
 
301
 
  THR_LOCK_heap.lock();
 
438
  pthread_mutex_lock(&THR_LOCK_heap);
302
439
  if ((share= hp_find_named_heap(name)))
303
440
  {
304
441
    heap_try_free(share);
308
445
  {
309
446
    result= errno=ENOENT;
310
447
  }
311
 
  THR_LOCK_heap.unlock();
 
448
  pthread_mutex_unlock(&THR_LOCK_heap);
312
449
  return(result);
313
450
}
314
451
 
315
452
 
 
453
void heap_drop_table(HP_INFO *info)
 
454
{
 
455
  pthread_mutex_lock(&THR_LOCK_heap);
 
456
  heap_try_free(info->s);
 
457
  pthread_mutex_unlock(&THR_LOCK_heap);
 
458
  return;
 
459
}
 
460
 
 
461
 
316
462
void hp_free(HP_SHARE *share)
317
463
{
318
464
  heap_share_list.remove(share);        /* If not internal table */
319
465
  hp_clear(share);                      /* Remove blocks from memory */
 
466
  thr_lock_delete(&share->lock);
 
467
  pthread_mutex_destroy(&share->intern_lock);
 
468
  if (share->keydef && share->keydef->seg)
 
469
    free(share->keydef->seg);
320
470
  if (share->keydef)
321
 
    delete [] share->keydef->seg;
322
 
  delete [] share->keydef;
323
 
  delete share;
 
471
    free(share->keydef);
 
472
  free(share->column_defs);
 
473
  free((unsigned char*) share->name);
 
474
  free((unsigned char*) share);
 
475
  return;
324
476
}