~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to plugin/heap/hp_create.cc

  • Committer: Brian Aker
  • Date: 2010-02-14 01:56:51 UTC
  • mto: (1273.16.5 fix_is)
  • mto: This revision was merged to the branch mainline in revision 1300.
  • Revision ID: brian@gaz-20100214015651-ror9j0xu7dccz0ct
Two fixes for "make dist"

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
 
  uint32_t i, key_segs, max_length, length;
 
48
  uint32_t i, j, 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
 
    THR_LOCK_heap.lock();
 
55
    pthread_mutex_lock(&THR_LOCK_heap);
55
56
    if ((share= hp_find_named_heap(name)) && share->open_count == 0)
56
57
    {
57
58
      hp_free(share);
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
 
        THR_LOCK_heap.unlock();
 
81
        pthread_mutex_unlock(&THR_LOCK_heap);
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));
116
 
      for (uint32_t j= length= 0; j < keyinfo->keysegs; j++)
 
188
      memset(&keyinfo->rb_tree , 0, sizeof(keyinfo->rb_tree));
 
189
      for (j= length= 0; j < keyinfo->keysegs; j++)
117
190
      {
118
191
        length+= keyinfo->seg[j].length;
119
192
        if (keyinfo->seg[j].null_bit)
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
 
    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;
 
254
    share= NULL;
 
255
    if (!(share= (HP_SHARE*) malloc(sizeof(HP_SHARE))))
 
256
      goto err;
 
257
 
 
258
    memset(share, 0, sizeof(HP_SHARE));
 
259
 
 
260
    if (keys && !(share->keydef= (HP_KEYDEF*) malloc(keys*sizeof(HP_KEYDEF))))
 
261
      goto err;
 
262
 
 
263
    memset(share->keydef, 0, keys*sizeof(HP_KEYDEF));
 
264
 
 
265
    if (keys && !(share->keydef->seg= (HA_KEYSEG*) malloc(key_segs*sizeof(HA_KEYSEG))))
 
266
      goto err;
 
267
    if (!(share->column_defs= (HP_COLUMNDEF*)
 
268
          malloc(columns*sizeof(HP_COLUMNDEF))))
 
269
      goto err;
 
270
 
 
271
    memset(share->column_defs, 0, columns*sizeof(HP_COLUMNDEF));
172
272
 
173
273
    /*
174
274
       Max_records is used for estimating block sizes and for enforcement.
180
280
    max_records = ((max_records && max_records < max_rows_for_stated_memory) ?
181
281
                      max_records : max_rows_for_stated_memory);
182
282
 
 
283
    memcpy(share->column_defs, columndef, (size_t) (sizeof(columndef[0]) * columns));
 
284
 
183
285
    share->key_stat_version= 1;
184
286
    keyseg= keys ? share->keydef->seg : NULL;
185
287
 
192
294
      memcpy(keyseg, keydef[i].seg,
193
295
             (size_t) (sizeof(keyseg[0]) * keydef[i].keysegs));
194
296
      keyseg+= keydef[i].keysegs;
 
297
 
 
298
      if (keydef[i].algorithm == HA_KEY_ALG_BTREE)
 
299
      {
 
300
        /* additional HA_KEYTYPE_END keyseg */
 
301
        keyseg->type=     HA_KEYTYPE_END;
 
302
        keyseg->length=   sizeof(unsigned char*);
 
303
        keyseg->flag=     0;
 
304
        keyseg->null_bit= 0;
 
305
        keyseg++;
 
306
 
 
307
        init_tree(&keyinfo->rb_tree, 0, 0, sizeof(unsigned char*),
 
308
                  (qsort_cmp2)keys_compare, true, NULL, NULL);
 
309
        keyinfo->delete_key= hp_rb_delete_key;
 
310
        keyinfo->write_key= hp_rb_write_key;
 
311
      }
 
312
      else
195
313
      {
196
314
        init_block(&keyinfo->block, sizeof(HASH_INFO), min_records,
197
315
                   max_records);
 
316
        keyinfo->delete_key= hp_delete_key;
 
317
        keyinfo->write_key= hp_write_key;
198
318
        keyinfo->hash_buckets= 0;
199
319
      }
200
320
      if ((keyinfo->flag & HA_AUTO_KEY) && create_info->with_auto_increment)
218
338
 
219
339
    share->recordspace.chunk_length= chunk_length;
220
340
    share->recordspace.chunk_dataspace_length= chunk_dataspace_length;
 
341
    share->recordspace.is_variable_size= is_variable_size;
221
342
    share->recordspace.total_data_length= 0;
222
343
 
223
 
    {
 
344
    if (is_variable_size) {
 
345
      share->recordspace.offset_link= chunk_dataspace_length;
 
346
      share->recordspace.offset_status= share->recordspace.offset_link + sizeof(unsigned char**);
 
347
    } else {
224
348
      share->recordspace.offset_link= 1<<22; /* Make it likely to fail if anyone uses this offset */
225
349
      share->recordspace.offset_status= chunk_dataspace_length;
226
350
    }
227
351
 
228
352
    /* Must be allocated separately for rename to work */
229
 
    share->name.append(name);
 
353
    if (!(share->name= strdup(name)))
 
354
    {
 
355
      goto err;
 
356
    }
 
357
    thr_lock_init(&share->lock);
 
358
    pthread_mutex_init(&share->intern_lock,MY_MUTEX_INIT_FAST);
230
359
    if (!create_info->internal_table)
231
360
    {
232
361
      heap_share_list.push_front(share);
235
364
      share->delete_on_close= 1;
236
365
  }
237
366
  if (!create_info->internal_table)
238
 
    THR_LOCK_heap.unlock();
 
367
    pthread_mutex_unlock(&THR_LOCK_heap);
239
368
 
240
369
  *res= share;
241
370
  return(0);
242
371
 
243
372
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();
 
373
  if(share && share->keydef && share->keydef->seg)
 
374
    free(share->keydef->seg);
 
375
  if(share && share->keydef)
 
376
    free(share->keydef);
 
377
  if(share && share->column_defs)
 
378
    free(share->column_defs);
 
379
  if(share)
 
380
    free(share);
 
381
  if (!create_info->internal_table)
 
382
    pthread_mutex_unlock(&THR_LOCK_heap);
252
383
  return(1);
253
384
} /* heap_create */
254
385
 
255
386
 
 
387
static int keys_compare(heap_rb_param *param, unsigned char *key1, unsigned char *key2)
 
388
{
 
389
  uint32_t not_used[2];
 
390
  return ha_key_cmp(param->keyseg, key1, key2, param->key_length,
 
391
                    param->search_flag, not_used);
 
392
}
 
393
 
256
394
static void init_block(HP_BLOCK *block, uint32_t chunk_length, uint32_t min_records,
257
395
                       uint32_t max_records)
258
396
{
259
 
  uint32_t recbuffer,records_in_block;
 
397
  uint32_t i,recbuffer,records_in_block;
260
398
 
261
399
  max_records= max(min_records,max_records);
262
400
  if (!max_records)
275
413
  block->recbuffer= recbuffer;
276
414
  block->last_allocated= 0L;
277
415
 
278
 
  for (uint32_t i= 0; i <= HP_MAX_LEVELS; i++)
279
 
  {
 
416
  for (i= 0; i <= HP_MAX_LEVELS; i++)
280
417
    block->level_info[i].records_under_level=
281
418
      (!i ? 1 : i == 1 ? records_in_block :
282
419
       HP_PTRS_IN_NOD * block->level_info[i - 1].records_under_level);
283
 
  }
284
420
}
285
421
 
286
422
 
298
434
  int result;
299
435
  register HP_SHARE *share;
300
436
 
301
 
  THR_LOCK_heap.lock();
 
437
  pthread_mutex_lock(&THR_LOCK_heap);
302
438
  if ((share= hp_find_named_heap(name)))
303
439
  {
304
440
    heap_try_free(share);
308
444
  {
309
445
    result= errno=ENOENT;
310
446
  }
311
 
  THR_LOCK_heap.unlock();
 
447
  pthread_mutex_unlock(&THR_LOCK_heap);
312
448
  return(result);
313
449
}
314
450
 
315
451
 
 
452
void heap_drop_table(HP_INFO *info)
 
453
{
 
454
  pthread_mutex_lock(&THR_LOCK_heap);
 
455
  heap_try_free(info->s);
 
456
  pthread_mutex_unlock(&THR_LOCK_heap);
 
457
  return;
 
458
}
 
459
 
 
460
 
316
461
void hp_free(HP_SHARE *share)
317
462
{
318
463
  heap_share_list.remove(share);        /* If not internal table */
319
464
  hp_clear(share);                      /* Remove blocks from memory */
 
465
  thr_lock_delete(&share->lock);
 
466
  pthread_mutex_destroy(&share->intern_lock);
 
467
  if (share->keydef && share->keydef->seg)
 
468
    free(share->keydef->seg);
320
469
  if (share->keydef)
321
 
    delete [] share->keydef->seg;
322
 
  delete [] share->keydef;
323
 
  delete share;
 
470
    free(share->keydef);
 
471
  free(share->column_defs);
 
472
  free((unsigned char*) share->name);
 
473
  free((unsigned char*) share);
 
474
  return;
324
475
}