~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to storage/heap/hp_create.cc

Moved the last of the libdrizzleclient calls into Protocol.

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