~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to plugin/heap/hp_create.cc

  • Committer: Jay Pipes
  • Date: 2009-09-15 21:01:42 UTC
  • mto: (1126.2.5 merge)
  • mto: This revision was merged to the branch mainline in revision 1128.
  • Revision ID: jpipes@serialcoder-20090915210142-x8mwiqn1q0vzjspp
Moves Alter_info out into its own header and source file, cleans up some related include mess in sql_lex.h, and renames Alter_info to AlterInfo.

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