~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-07 01:33:54 UTC
  • Revision ID: brian@gaz-20100207013354-d2pg1n68u5c09pgo
Remove giant include header to its own file.

Show diffs side-by-side

added added

removed removed

Lines of Context:
13
13
   along with this program; if not, write to the Free Software
14
14
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
15
15
 
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,
 
16
#include "heap_priv.h"
 
17
 
 
18
#include <drizzled/common.h>
 
19
#include <drizzled/error.h>
 
20
#include "drizzled/my_error.h"
 
21
 
 
22
#include <string.h>
 
23
#include <algorithm>
 
24
 
 
25
using namespace std;
 
26
using namespace drizzled;
 
27
 
 
28
static int keys_compare(heap_rb_param *param, unsigned char *key1, unsigned char *key2);
 
29
static void init_block(HP_BLOCK *block,uint32_t chunk_length, uint32_t min_records,
22
30
                        uint32_t max_records);
23
31
 
24
 
#define FIXED_REC_OVERHEAD (sizeof(uchar))
25
 
#define VARIABLE_REC_OVERHEAD (sizeof(uchar**) + sizeof(uchar))
26
 
 
 
32
#define FIXED_REC_OVERHEAD (sizeof(unsigned char))
 
33
#define VARIABLE_REC_OVERHEAD (sizeof(unsigned char**) + ALIGN_SIZE(sizeof(unsigned char)))
 
34
 
27
35
/* Minimum size that a chunk can take, 12 bytes on 32bit, 24 bytes on 64bit */
28
36
#define VARIABLE_MIN_CHUNK_SIZE \
29
 
        ((sizeof(uchar**) + VARIABLE_REC_OVERHEAD + sizeof(uchar**) - 1) & ~(sizeof(uchar**) - 1))
 
37
        ((sizeof(unsigned char**) + VARIABLE_REC_OVERHEAD + sizeof(unsigned char**) - 1) & ~(sizeof(unsigned char**) - 1))
30
38
 
31
39
 
32
40
/* Create a heap table */
33
41
 
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,
 
42
int heap_create(const char *name, uint32_t keys, HP_KEYDEF *keydef,
 
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,
38
46
    uint32_t max_records, uint32_t min_records,
39
47
    HP_CREATE_INFO *create_info, HP_SHARE **res)
40
48
{
41
 
  uint i, j, key_segs, max_length, length;
 
49
  uint32_t i, j, key_segs, max_length, length;
42
50
  uint32_t max_rows_for_stated_memory;
43
51
  HP_SHARE *share= 0;
44
52
  HA_KEYSEG *keyseg;
51
59
      hp_free(share);
52
60
      share= 0;
53
61
    }
54
 
  }  
 
62
  }
55
63
 
56
64
  if (!share)
57
65
  {
58
 
    uint chunk_dataspace_length, chunk_length, is_variable_size;
59
 
    uint fixed_data_length, fixed_column_count;
 
66
    size_t chunk_dataspace_length;
 
67
    uint32_t chunk_length, is_variable_size;
 
68
    uint32_t fixed_data_length, fixed_column_count;
60
69
    HP_KEYDEF *keyinfo;
61
70
 
62
71
    if (create_info->max_chunk_size)
63
72
    {
64
 
      uint configured_chunk_size= create_info->max_chunk_size;
 
73
      uint32_t configured_chunk_size= create_info->max_chunk_size;
65
74
 
66
75
      /* User requested variable-size records, let's see if they're possible */
67
76
 
109
118
    if (is_variable_size)
110
119
    {
111
120
      /* Check whether we have any variable size records past key data */
112
 
      uint has_variable_fields= 0;
 
121
      uint32_t has_variable_fields= 0;
113
122
 
114
123
      fixed_data_length= key_part_size;
115
124
      fixed_column_count= max_key_fieldnr;
155
164
    }
156
165
 
157
166
    /*
158
 
      We store uchar* del_link inside the data area of deleted records,
159
 
      so the data length should be at least sizeof(uchar*)
 
167
      We store unsigned char* del_link inside the data area of deleted records,
 
168
      so the data length should be at least sizeof(unsigned char*)
160
169
    */
161
 
    set_if_bigger(chunk_dataspace_length, sizeof (uchar**));
 
170
    set_if_bigger(chunk_dataspace_length, sizeof (unsigned char**));
162
171
 
163
172
    if (is_variable_size)
164
173
    {
170
179
    }
171
180
 
172
181
    /* Align chunk length to the next pointer */
173
 
    chunk_length= (uint) (chunk_length + sizeof(uchar**) - 1) & ~(sizeof(uchar**) - 1);
174
 
 
175
 
 
176
 
    
 
182
    chunk_length= (uint) (chunk_length + sizeof(unsigned char**) - 1) & ~(sizeof(unsigned char**) - 1);
 
183
 
 
184
 
 
185
 
177
186
    for (i= key_segs= max_length= 0, keyinfo= keydef; i < keys; i++, keyinfo++)
178
187
    {
179
188
      memset(&keyinfo->block, 0, sizeof(keyinfo->block));
190
199
            keyinfo->rb_tree.size_of_element++;
191
200
        }
192
201
        switch (keyinfo->seg[j].type) {
193
 
        case HA_KEYTYPE_SHORT_INT:
194
202
        case HA_KEYTYPE_LONG_INT:
195
 
        case HA_KEYTYPE_FLOAT:
196
203
        case HA_KEYTYPE_DOUBLE:
197
 
        case HA_KEYTYPE_USHORT_INT:
198
204
        case HA_KEYTYPE_ULONG_INT:
199
205
        case HA_KEYTYPE_LONGLONG:
200
206
        case HA_KEYTYPE_ULONGLONG:
201
 
        case HA_KEYTYPE_INT24:
202
207
        case HA_KEYTYPE_UINT24:
203
 
        case HA_KEYTYPE_INT8:
204
208
          keyinfo->seg[j].flag|= HA_SWAP_KEY;
205
209
          break;
206
210
        case HA_KEYTYPE_VARBINARY1:
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.
260
276
       Calculate the very maximum number of rows (if everything was one chunk) and
261
277
       then take either that value or configured max_records (pick smallest one)
262
278
    */
263
 
    max_rows_for_stated_memory= (ha_rows) (create_info->max_table_size /
 
279
    max_rows_for_stated_memory= (uint32_t)(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*),
294
 
                  (qsort_cmp2)keys_compare, 1, NULL, NULL);
 
308
        init_tree(&keyinfo->rb_tree, 0, 0, sizeof(unsigned char*),
 
309
                  (qsort_cmp2)keys_compare, true, NULL, NULL);
295
310
        keyinfo->delete_key= hp_rb_delete_key;
296
311
        keyinfo->write_key= hp_rb_write_key;
297
312
      }
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
400
  max_records= max(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;
388
409
  if (!records_in_block || records_in_block*recbuffer >
389
 
      (my_default_record_cache_size-sizeof(HP_PTRS)*HP_MAX_LEVELS))
390
 
    records_in_block= (my_default_record_cache_size - sizeof(HP_PTRS) *
 
410
      (internal::my_default_record_cache_size-sizeof(HP_PTRS)*HP_MAX_LEVELS))
 
411
    records_in_block= (internal::my_default_record_cache_size - sizeof(HP_PTRS) *
391
412
                      HP_MAX_LEVELS) / recbuffer + 1;
392
413
  block->records_in_block= records_in_block;
393
414
  block->recbuffer= recbuffer;
422
443
  }
423
444
  else
424
445
  {
425
 
    result= my_errno=ENOENT;
 
446
    result= errno=ENOENT;
426
447
  }
427
448
  pthread_mutex_unlock(&THR_LOCK_heap);
428
449
  return(result);
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->keydef && share->keydef->seg)
 
469
    free(share->keydef->seg);
 
470
  if (share->keydef)
 
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
}