~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to plugin/heap/hp_create.cc

  • Committer: Monty Taylor
  • Date: 2009-10-06 19:37:52 UTC
  • mto: This revision was merged to the branch mainline in revision 1184.
  • Revision ID: mordred@inaugust.com-20091006193752-4dx2c8u35j4em79g
Removed more server_includes.h from headers.

Show diffs side-by-side

added added

removed removed

Lines of Context:
14
14
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
15
15
 
16
16
#include "heapdef.h"
17
 
#include "libdrizzle/drizzle_com.h"
18
 
#include "drizzled/error.h"
19
 
 
20
 
static int keys_compare(heap_rb_param *param, uchar *key1, uchar *key2);
21
 
static void init_block(HP_BLOCK *block,uint chunk_length, uint32_t min_records,
 
17
 
 
18
#include <drizzled/common.h>
 
19
#include <drizzled/error.h>
 
20
 
 
21
#include <string.h>
 
22
#include <algorithm>
 
23
 
 
24
using namespace std;
 
25
 
 
26
static int keys_compare(heap_rb_param *param, unsigned char *key1, unsigned char *key2);
 
27
static void init_block(HP_BLOCK *block,uint32_t chunk_length, uint32_t min_records,
22
28
                        uint32_t max_records);
23
29
 
24
 
#define FIXED_REC_OVERHEAD (sizeof(uchar))
25
 
#define VARIABLE_REC_OVERHEAD (sizeof(uchar**) + sizeof(uchar))
26
 
 
 
30
#define FIXED_REC_OVERHEAD (sizeof(unsigned char))
 
31
#define VARIABLE_REC_OVERHEAD (sizeof(unsigned char**) + ALIGN_SIZE(sizeof(unsigned char)))
 
32
 
27
33
/* Minimum size that a chunk can take, 12 bytes on 32bit, 24 bytes on 64bit */
28
34
#define VARIABLE_MIN_CHUNK_SIZE \
29
 
        ((sizeof(uchar**) + VARIABLE_REC_OVERHEAD + sizeof(uchar**) - 1) & ~(sizeof(uchar**) - 1))
 
35
        ((sizeof(unsigned char**) + VARIABLE_REC_OVERHEAD + sizeof(unsigned char**) - 1) & ~(sizeof(unsigned char**) - 1))
30
36
 
31
37
 
32
38
/* Create a heap table */
33
39
 
34
 
int heap_create(const char *name, uint keys, HP_KEYDEF *keydef,
35
 
    uint columns, HP_COLUMNDEF *columndef,
36
 
    uint max_key_fieldnr, uint key_part_size,
37
 
    uint reclength, uint keys_memory_size,
 
40
int heap_create(const char *name, uint32_t keys, HP_KEYDEF *keydef,
 
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,
38
44
    uint32_t max_records, uint32_t min_records,
39
45
    HP_CREATE_INFO *create_info, HP_SHARE **res)
40
46
{
41
 
  uint i, j, key_segs, max_length, length;
 
47
  uint32_t i, j, key_segs, max_length, length;
42
48
  uint32_t max_rows_for_stated_memory;
43
49
  HP_SHARE *share= 0;
44
50
  HA_KEYSEG *keyseg;
51
57
      hp_free(share);
52
58
      share= 0;
53
59
    }
54
 
  }  
 
60
  }
55
61
 
56
62
  if (!share)
57
63
  {
58
 
    uint chunk_dataspace_length, chunk_length, is_variable_size;
59
 
    uint fixed_data_length, fixed_column_count;
 
64
    size_t chunk_dataspace_length;
 
65
    uint32_t chunk_length, is_variable_size;
 
66
    uint32_t fixed_data_length, fixed_column_count;
60
67
    HP_KEYDEF *keyinfo;
61
68
 
62
69
    if (create_info->max_chunk_size)
63
70
    {
64
 
      uint configured_chunk_size= create_info->max_chunk_size;
 
71
      uint32_t configured_chunk_size= create_info->max_chunk_size;
65
72
 
66
73
      /* User requested variable-size records, let's see if they're possible */
67
74
 
109
116
    if (is_variable_size)
110
117
    {
111
118
      /* Check whether we have any variable size records past key data */
112
 
      uint has_variable_fields= 0;
 
119
      uint32_t has_variable_fields= 0;
113
120
 
114
121
      fixed_data_length= key_part_size;
115
122
      fixed_column_count= max_key_fieldnr;
155
162
    }
156
163
 
157
164
    /*
158
 
      We store uchar* del_link inside the data area of deleted records,
159
 
      so the data length should be at least sizeof(uchar*)
 
165
      We store unsigned char* del_link inside the data area of deleted records,
 
166
      so the data length should be at least sizeof(unsigned char*)
160
167
    */
161
 
    set_if_bigger(chunk_dataspace_length, sizeof (uchar**));
 
168
    set_if_bigger(chunk_dataspace_length, sizeof (unsigned char**));
162
169
 
163
170
    if (is_variable_size)
164
171
    {
170
177
    }
171
178
 
172
179
    /* Align chunk length to the next pointer */
173
 
    chunk_length= (uint) (chunk_length + sizeof(uchar**) - 1) & ~(sizeof(uchar**) - 1);
174
 
 
175
 
 
176
 
    
 
180
    chunk_length= (uint) (chunk_length + sizeof(unsigned char**) - 1) & ~(sizeof(unsigned char**) - 1);
 
181
 
 
182
 
 
183
 
177
184
    for (i= key_segs= max_length= 0, keyinfo= keydef; i < keys; i++, keyinfo++)
178
185
    {
179
186
      memset(&keyinfo->block, 0, sizeof(keyinfo->block));
232
239
        }
233
240
      }
234
241
      keyinfo->length= length;
235
 
      length+= keyinfo->rb_tree.size_of_element + 
236
 
               ((keyinfo->algorithm == HA_KEY_ALG_BTREE) ? sizeof(uchar*) : 0);
 
242
      length+= keyinfo->rb_tree.size_of_element +
 
243
               ((keyinfo->algorithm == HA_KEY_ALG_BTREE) ? sizeof(unsigned char*) : 0);
237
244
      if (length > max_length)
238
245
        max_length= length;
239
246
      key_segs+= keyinfo->keysegs;
248
255
          keyinfo->get_key_length= hp_rb_key_length;
249
256
      }
250
257
    }
251
 
    if (!(share= (HP_SHARE*) my_malloc((uint) sizeof(HP_SHARE)+
252
 
                                       keys*sizeof(HP_KEYDEF)+
253
 
                                       columns*sizeof(HP_COLUMNDEF)+
254
 
                                       key_segs*sizeof(HA_KEYSEG),
255
 
                                       MYF(MY_ZEROFILL))))
256
 
      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));
257
276
 
258
277
    /*
259
278
       Max_records is used for estimating block sizes and for enforcement.
260
279
       Calculate the very maximum number of rows (if everything was one chunk) and
261
280
       then take either that value or configured max_records (pick smallest one)
262
281
    */
263
 
    max_rows_for_stated_memory= (ha_rows) (create_info->max_table_size /
 
282
    max_rows_for_stated_memory= (uint32_t)(create_info->max_table_size /
264
283
      (keys_memory_size + chunk_length));
265
 
    max_records = ((max_records && max_records < max_rows_for_stated_memory) ? 
 
284
    max_records = ((max_records && max_records < max_rows_for_stated_memory) ?
266
285
                      max_records : max_rows_for_stated_memory);
267
 
 
268
 
    share->column_defs= (HP_COLUMNDEF*) (share + 1);
 
286
 
269
287
    memcpy(share->column_defs, columndef, (size_t) (sizeof(columndef[0]) * columns));
270
288
 
271
 
    share->keydef= (HP_KEYDEF*) (share->column_defs + columns);    
272
289
    share->key_stat_version= 1;
273
 
    keyseg= (HA_KEYSEG*) (share->keydef + keys);
 
290
    keyseg= keys ? share->keydef->seg : NULL;
 
291
 
274
292
    init_block(&share->recordspace.block, chunk_length, min_records, max_records);
275
293
    /* Fix keys */
276
294
    memcpy(share->keydef, keydef, (size_t) (sizeof(keydef[0]) * keys));
285
303
      {
286
304
        /* additional HA_KEYTYPE_END keyseg */
287
305
        keyseg->type=     HA_KEYTYPE_END;
288
 
        keyseg->length=   sizeof(uchar*);
 
306
        keyseg->length=   sizeof(unsigned char*);
289
307
        keyseg->flag=     0;
290
308
        keyseg->null_bit= 0;
291
309
        keyseg++;
292
310
 
293
 
        init_tree(&keyinfo->rb_tree, 0, 0, sizeof(uchar*),
294
 
                  (qsort_cmp2)keys_compare, 1, NULL, NULL);
 
311
        init_tree(&keyinfo->rb_tree, 0, 0, sizeof(unsigned char*),
 
312
                  (qsort_cmp2)keys_compare, true, NULL, NULL);
295
313
        keyinfo->delete_key= hp_rb_delete_key;
296
314
        keyinfo->write_key= hp_rb_write_key;
297
315
      }
329
347
 
330
348
    if (is_variable_size) {
331
349
      share->recordspace.offset_link= chunk_dataspace_length;
332
 
      share->recordspace.offset_status= share->recordspace.offset_link + sizeof(uchar**);
 
350
      share->recordspace.offset_status= share->recordspace.offset_link + sizeof(unsigned char**);
333
351
    } else {
334
352
      share->recordspace.offset_link= 1<<22; /* Make it likely to fail if anyone uses this offset */
335
353
      share->recordspace.offset_status= chunk_dataspace_length;
336
354
    }
337
355
 
338
356
    /* Must be allocated separately for rename to work */
339
 
    if (!(share->name= my_strdup(name,MYF(0))))
 
357
    if (!(share->name= strdup(name)))
340
358
    {
341
 
      my_free((uchar*) share,MYF(0));
342
359
      goto err;
343
360
    }
344
361
    thr_lock_init(&share->lock);
345
 
    VOID(pthread_mutex_init(&share->intern_lock,MY_MUTEX_INIT_FAST));
 
362
    pthread_mutex_init(&share->intern_lock,MY_MUTEX_INIT_FAST);
346
363
    if (!create_info->internal_table)
347
364
    {
348
 
      share->open_list.data= (void*) share;
349
 
      heap_share_list= list_add(heap_share_list,&share->open_list);
 
365
      heap_share_list.push_front(share);
350
366
    }
351
367
    else
352
368
      share->delete_on_close= 1;
358
374
  return(0);
359
375
 
360
376
err:
 
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);
361
385
  if (!create_info->internal_table)
362
386
    pthread_mutex_unlock(&THR_LOCK_heap);
363
387
  return(1);
364
388
} /* heap_create */
365
389
 
366
390
 
367
 
static int keys_compare(heap_rb_param *param, uchar *key1, uchar *key2)
 
391
static int keys_compare(heap_rb_param *param, unsigned char *key1, unsigned char *key2)
368
392
{
369
 
  uint not_used[2];
370
 
  return ha_key_cmp(param->keyseg, key1, key2, param->key_length, 
 
393
  uint32_t not_used[2];
 
394
  return ha_key_cmp(param->keyseg, key1, key2, param->key_length,
371
395
                    param->search_flag, not_used);
372
396
}
373
397
 
374
 
static void init_block(HP_BLOCK *block, uint chunk_length, uint32_t min_records,
 
398
static void init_block(HP_BLOCK *block, uint32_t chunk_length, uint32_t min_records,
375
399
                       uint32_t max_records)
376
400
{
377
 
  uint i,recbuffer,records_in_block;
 
401
  uint32_t i,recbuffer,records_in_block;
378
402
 
379
403
  max_records= max(min_records,max_records);
380
404
  if (!max_records)
381
405
    max_records= 1000;                  /* As good as quess as anything */
382
 
  
 
406
 
383
407
  /* we want to start each chunk at 8 bytes boundary, round recbuffer to the next 8 */
384
 
  recbuffer= (uint) (chunk_length + sizeof(uchar**) - 1) & ~(sizeof(uchar**) - 1);  
 
408
  recbuffer= (uint) (chunk_length + sizeof(unsigned char**) - 1) & ~(sizeof(unsigned char**) - 1);
385
409
  records_in_block= max_records / 10;
386
410
  if (records_in_block < 10 && max_records)
387
411
    records_in_block= 10;
440
464
 
441
465
void hp_free(HP_SHARE *share)
442
466
{
443
 
  if (share->open_list.data)                    /* If not internal table */
444
 
    heap_share_list= list_delete(heap_share_list, &share->open_list);
 
467
  heap_share_list.remove(share);        /* If not internal table */
445
468
  hp_clear(share);                      /* Remove blocks from memory */
446
469
  thr_lock_delete(&share->lock);
447
 
  VOID(pthread_mutex_destroy(&share->intern_lock));
448
 
  my_free((uchar*) share->name, MYF(0));
449
 
  my_free((uchar*) share, MYF(0));
 
470
  pthread_mutex_destroy(&share->intern_lock);
 
471
  if (share->keydef && share->keydef->seg)
 
472
    free(share->keydef->seg);
 
473
  if (share->keydef)
 
474
    free(share->keydef);
 
475
  free(share->column_defs);
 
476
  free((unsigned char*) share->name);
 
477
  free((unsigned char*) share);
450
478
  return;
451
479
}