~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to plugin/heap/hp_create.cc

  • Committer: Brian Aker
  • Date: 2010-01-22 00:53:13 UTC
  • Revision ID: brian@gaz-20100122005313-jmizcbcdi1lt4tcx
Revert db patch.

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