~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to storage/heap/hp_create.c

  • Committer: Monty Taylor
  • Date: 2008-07-26 16:22:28 UTC
  • mto: (236.1.42 codestyle)
  • mto: This revision was merged to the branch mainline in revision 261.
  • Revision ID: monty@inaugust.com-20080726162228-atatk41l6w4np70m
Added gettext calls in to my_getopt.c and drizzle.c

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 */
15
 
 
16
 
#include "heap_priv.h"
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
 
using namespace drizzled;
26
 
 
27
 
static void init_block(HP_BLOCK *block,uint32_t chunk_length, uint32_t min_records,
28
 
                        uint32_t max_records);
29
 
 
30
 
#define FIXED_REC_OVERHEAD (sizeof(unsigned char))
31
 
#define VARIABLE_REC_OVERHEAD (sizeof(unsigned char**) + ALIGN_SIZE(sizeof(unsigned char)))
32
 
 
33
 
/* Minimum size that a chunk can take, 12 bytes on 32bit, 24 bytes on 64bit */
34
 
#define VARIABLE_MIN_CHUNK_SIZE \
35
 
        ((sizeof(unsigned char**) + VARIABLE_REC_OVERHEAD + sizeof(unsigned char**) - 1) & ~(sizeof(unsigned char**) - 1))
36
 
 
 
14
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
 
15
 
 
16
#include "heapdef.h"
 
17
 
 
18
static int keys_compare(heap_rb_param *param, uchar *key1, uchar *key2);
 
19
static void init_block(HP_BLOCK *block,uint reclength,ulong min_records,
 
20
                       ulong max_records);
37
21
 
38
22
/* Create a heap table */
39
23
 
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)
 
24
int heap_create(const char *name, uint keys, HP_KEYDEF *keydef,
 
25
                uint reclength, ulong max_records, ulong min_records,
 
26
                HP_CREATE_INFO *create_info, HP_SHARE **res)
46
27
{
47
 
  uint32_t i, key_segs, max_length, length;
48
 
  uint32_t max_rows_for_stated_memory;
 
28
  uint i, j, key_segs, max_length, length;
49
29
  HP_SHARE *share= 0;
50
30
  HA_KEYSEG *keyseg;
51
31
 
52
 
  if (not create_info->internal_table)
 
32
  if (!create_info->internal_table)
53
33
  {
54
 
    THR_LOCK_heap.lock();
 
34
    pthread_mutex_lock(&THR_LOCK_heap);
55
35
    if ((share= hp_find_named_heap(name)) && share->open_count == 0)
56
36
    {
57
37
      hp_free(share);
58
38
      share= 0;
59
39
    }
60
 
  }
 
40
  }  
61
41
 
62
42
  if (!share)
63
43
  {
64
 
    size_t chunk_dataspace_length;
65
 
    uint32_t chunk_length;
66
 
    uint32_t fixed_data_length, fixed_column_count;
67
44
    HP_KEYDEF *keyinfo;
68
 
 
69
 
    if (create_info->max_chunk_size)
70
 
    {
71
 
      uint32_t configured_chunk_size= create_info->max_chunk_size;
72
 
 
73
 
      /* User requested variable-size records, let's see if they're possible */
74
 
 
75
 
      if (configured_chunk_size < key_part_size)
76
 
      {
77
 
        /* Eventual chunk_size cannot be smaller than key data,
78
 
          which allows all keys to fit into the first chunk */
79
 
        my_error(ER_CANT_USE_OPTION_HERE, MYF(0), "block_size");
80
 
        THR_LOCK_heap.unlock();
81
 
        return(ER_CANT_USE_OPTION_HERE);
82
 
      }
83
 
 
84
 
      /* max_chunk_size is near the full reclength, let's use fixed size */
85
 
      chunk_dataspace_length= reclength;
86
 
    }
87
 
    else
88
 
    {
89
 
      /* if max_chunk_size is not specified, put the whole record in one chunk */
90
 
      chunk_dataspace_length= reclength;
91
 
    }
92
 
 
93
 
    {
94
 
      fixed_data_length= reclength;
95
 
      fixed_column_count= columns;
96
 
    }
97
 
 
 
45
    
98
46
    /*
99
 
      We store unsigned char* del_link inside the data area of deleted records,
100
 
      so the data length should be at least sizeof(unsigned char*)
 
47
      We have to store sometimes uchar* del_link in records,
 
48
      so the record length should be at least sizeof(uchar*)
101
49
    */
102
 
    set_if_bigger(chunk_dataspace_length, sizeof (unsigned char**));
103
 
 
104
 
    {
105
 
      chunk_length= chunk_dataspace_length + FIXED_REC_OVERHEAD;
106
 
    }
107
 
 
108
 
    /* Align chunk length to the next pointer */
109
 
    chunk_length= (uint) (chunk_length + sizeof(unsigned char**) - 1) & ~(sizeof(unsigned char**) - 1);
110
 
 
111
 
 
112
 
 
 
50
    set_if_bigger(reclength, sizeof (uchar*));
 
51
    
113
52
    for (i= key_segs= max_length= 0, keyinfo= keydef; i < keys; i++, keyinfo++)
114
53
    {
115
 
      memset(&keyinfo->block, 0, sizeof(keyinfo->block));
116
 
      for (uint32_t j= length= 0; j < keyinfo->keysegs; j++)
 
54
      bzero((char*) &keyinfo->block,sizeof(keyinfo->block));
 
55
      bzero((char*) &keyinfo->rb_tree ,sizeof(keyinfo->rb_tree));
 
56
      for (j= length= 0; j < keyinfo->keysegs; j++)
117
57
      {
118
58
        length+= keyinfo->seg[j].length;
119
59
        if (keyinfo->seg[j].null_bit)
121
61
          length++;
122
62
          if (!(keyinfo->flag & HA_NULL_ARE_EQUAL))
123
63
            keyinfo->flag|= HA_NULL_PART_KEY;
 
64
          if (keyinfo->algorithm == HA_KEY_ALG_BTREE)
 
65
            keyinfo->rb_tree.size_of_element++;
124
66
        }
125
67
        switch (keyinfo->seg[j].type) {
 
68
        case HA_KEYTYPE_SHORT_INT:
126
69
        case HA_KEYTYPE_LONG_INT:
 
70
        case HA_KEYTYPE_FLOAT:
127
71
        case HA_KEYTYPE_DOUBLE:
 
72
        case HA_KEYTYPE_USHORT_INT:
128
73
        case HA_KEYTYPE_ULONG_INT:
129
74
        case HA_KEYTYPE_LONGLONG:
130
75
        case HA_KEYTYPE_ULONGLONG:
 
76
        case HA_KEYTYPE_INT24:
 
77
        case HA_KEYTYPE_UINT24:
 
78
        case HA_KEYTYPE_INT8:
131
79
          keyinfo->seg[j].flag|= HA_SWAP_KEY;
132
80
          break;
133
81
        case HA_KEYTYPE_VARBINARY1:
159
107
        }
160
108
      }
161
109
      keyinfo->length= length;
 
110
      length+= keyinfo->rb_tree.size_of_element + 
 
111
               ((keyinfo->algorithm == HA_KEY_ALG_BTREE) ? sizeof(uchar*) : 0);
162
112
      if (length > max_length)
163
113
        max_length= length;
164
114
      key_segs+= keyinfo->keysegs;
 
115
      if (keyinfo->algorithm == HA_KEY_ALG_BTREE)
 
116
      {
 
117
        key_segs++; /* additional HA_KEYTYPE_END segment */
 
118
        if (keyinfo->flag & HA_VAR_LENGTH_KEY)
 
119
          keyinfo->get_key_length= hp_rb_var_key_length;
 
120
        else if (keyinfo->flag & HA_NULL_PART_KEY)
 
121
          keyinfo->get_key_length= hp_rb_null_key_length;
 
122
        else
 
123
          keyinfo->get_key_length= hp_rb_key_length;
 
124
      }
165
125
    }
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;
172
 
 
173
 
    /*
174
 
       Max_records is used for estimating block sizes and for enforcement.
175
 
       Calculate the very maximum number of rows (if everything was one chunk) and
176
 
       then take either that value or configured max_records (pick smallest one)
177
 
    */
178
 
    max_rows_for_stated_memory= (uint32_t)(create_info->max_table_size /
179
 
      (keys_memory_size + chunk_length));
180
 
    max_records = ((max_records && max_records < max_rows_for_stated_memory) ?
181
 
                      max_records : max_rows_for_stated_memory);
182
 
 
 
126
    if (!(share= (HP_SHARE*) my_malloc((uint) sizeof(HP_SHARE)+
 
127
                                       keys*sizeof(HP_KEYDEF)+
 
128
                                       key_segs*sizeof(HA_KEYSEG),
 
129
                                       MYF(MY_ZEROFILL))))
 
130
      goto err;
 
131
    share->keydef= (HP_KEYDEF*) (share + 1);
183
132
    share->key_stat_version= 1;
184
 
    keyseg= keys ? share->keydef->seg : NULL;
185
 
 
186
 
    init_block(&share->recordspace.block, chunk_length, min_records, max_records);
187
 
    /* Fix keys */
 
133
    keyseg= (HA_KEYSEG*) (share->keydef + keys);
 
134
    init_block(&share->block, reclength + 1, min_records, max_records);
 
135
        /* Fix keys */
188
136
    memcpy(share->keydef, keydef, (size_t) (sizeof(keydef[0]) * keys));
189
137
    for (i= 0, keyinfo= share->keydef; i < keys; i++, keyinfo++)
190
138
    {
192
140
      memcpy(keyseg, keydef[i].seg,
193
141
             (size_t) (sizeof(keyseg[0]) * keydef[i].keysegs));
194
142
      keyseg+= keydef[i].keysegs;
 
143
 
 
144
      if (keydef[i].algorithm == HA_KEY_ALG_BTREE)
 
145
      {
 
146
        /* additional HA_KEYTYPE_END keyseg */
 
147
        keyseg->type=     HA_KEYTYPE_END;
 
148
        keyseg->length=   sizeof(uchar*);
 
149
        keyseg->flag=     0;
 
150
        keyseg->null_bit= 0;
 
151
        keyseg++;
 
152
 
 
153
        init_tree(&keyinfo->rb_tree, 0, 0, sizeof(uchar*),
 
154
                  (qsort_cmp2)keys_compare, 1, NULL, NULL);
 
155
        keyinfo->delete_key= hp_rb_delete_key;
 
156
        keyinfo->write_key= hp_rb_write_key;
 
157
      }
 
158
      else
195
159
      {
196
160
        init_block(&keyinfo->block, sizeof(HASH_INFO), min_records,
197
161
                   max_records);
 
162
        keyinfo->delete_key= hp_delete_key;
 
163
        keyinfo->write_key= hp_write_key;
198
164
        keyinfo->hash_buckets= 0;
199
165
      }
200
166
      if ((keyinfo->flag & HA_AUTO_KEY) && create_info->with_auto_increment)
203
169
    share->min_records= min_records;
204
170
    share->max_records= max_records;
205
171
    share->max_table_size= create_info->max_table_size;
206
 
    share->index_length= 0;
 
172
    share->data_length= share->index_length= 0;
 
173
    share->reclength= reclength;
207
174
    share->blength= 1;
208
175
    share->keys= keys;
209
176
    share->max_key_length= max_length;
210
 
    share->column_count= columns;
211
177
    share->changed= 0;
212
178
    share->auto_key= create_info->auto_key;
213
179
    share->auto_key_type= create_info->auto_key_type;
214
180
    share->auto_increment= create_info->auto_increment;
215
 
 
216
 
    share->fixed_data_length= fixed_data_length;
217
 
    share->fixed_column_count= fixed_column_count;
218
 
 
219
 
    share->recordspace.chunk_length= chunk_length;
220
 
    share->recordspace.chunk_dataspace_length= chunk_dataspace_length;
221
 
    share->recordspace.total_data_length= 0;
222
 
 
223
 
    {
224
 
      share->recordspace.offset_link= 1<<22; /* Make it likely to fail if anyone uses this offset */
225
 
      share->recordspace.offset_status= chunk_dataspace_length;
226
 
    }
227
 
 
228
181
    /* Must be allocated separately for rename to work */
229
 
    share->name.append(name);
 
182
    if (!(share->name= my_strdup(name,MYF(0))))
 
183
    {
 
184
      my_free((uchar*) share,MYF(0));
 
185
      goto err;
 
186
    }
 
187
    thr_lock_init(&share->lock);
 
188
    VOID(pthread_mutex_init(&share->intern_lock,MY_MUTEX_INIT_FAST));
230
189
    if (!create_info->internal_table)
231
190
    {
232
 
      heap_share_list.push_front(share);
 
191
      share->open_list.data= (void*) share;
 
192
      heap_share_list= list_add(heap_share_list,&share->open_list);
233
193
    }
234
194
    else
235
195
      share->delete_on_close= 1;
236
196
  }
237
197
  if (!create_info->internal_table)
238
 
    THR_LOCK_heap.unlock();
 
198
    pthread_mutex_unlock(&THR_LOCK_heap);
239
199
 
240
200
  *res= share;
241
201
  return(0);
242
202
 
243
203
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();
 
204
  if (!create_info->internal_table)
 
205
    pthread_mutex_unlock(&THR_LOCK_heap);
252
206
  return(1);
253
207
} /* heap_create */
254
208
 
255
209
 
256
 
static void init_block(HP_BLOCK *block, uint32_t chunk_length, uint32_t min_records,
257
 
                       uint32_t max_records)
258
 
{
259
 
  uint32_t recbuffer,records_in_block;
 
210
static int keys_compare(heap_rb_param *param, uchar *key1, uchar *key2)
 
211
{
 
212
  uint not_used[2];
 
213
  return ha_key_cmp(param->keyseg, key1, key2, param->key_length, 
 
214
                    param->search_flag, not_used);
 
215
}
 
216
 
 
217
static void init_block(HP_BLOCK *block, uint reclength, ulong min_records,
 
218
                       ulong max_records)
 
219
{
 
220
  uint i,recbuffer,records_in_block;
260
221
 
261
222
  max_records= max(min_records,max_records);
262
223
  if (!max_records)
263
224
    max_records= 1000;                  /* As good as quess as anything */
264
 
 
265
 
  /* we want to start each chunk at 8 bytes boundary, round recbuffer to the next 8 */
266
 
  recbuffer= (uint) (chunk_length + sizeof(unsigned char**) - 1) & ~(sizeof(unsigned char**) - 1);
 
225
  recbuffer= (uint) (reclength + sizeof(uchar**) - 1) & ~(sizeof(uchar**) - 1);
267
226
  records_in_block= max_records / 10;
268
227
  if (records_in_block < 10 && max_records)
269
228
    records_in_block= 10;
270
229
  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) *
 
230
      (my_default_record_cache_size-sizeof(HP_PTRS)*HP_MAX_LEVELS))
 
231
    records_in_block= (my_default_record_cache_size - sizeof(HP_PTRS) *
273
232
                      HP_MAX_LEVELS) / recbuffer + 1;
274
233
  block->records_in_block= records_in_block;
275
234
  block->recbuffer= recbuffer;
276
235
  block->last_allocated= 0L;
277
236
 
278
 
  for (uint32_t i= 0; i <= HP_MAX_LEVELS; i++)
279
 
  {
 
237
  for (i= 0; i <= HP_MAX_LEVELS; i++)
280
238
    block->level_info[i].records_under_level=
281
239
      (!i ? 1 : i == 1 ? records_in_block :
282
240
       HP_PTRS_IN_NOD * block->level_info[i - 1].records_under_level);
283
 
  }
284
241
}
285
242
 
286
243
 
298
255
  int result;
299
256
  register HP_SHARE *share;
300
257
 
301
 
  THR_LOCK_heap.lock();
 
258
  pthread_mutex_lock(&THR_LOCK_heap);
302
259
  if ((share= hp_find_named_heap(name)))
303
260
  {
304
261
    heap_try_free(share);
306
263
  }
307
264
  else
308
265
  {
309
 
    result= errno=ENOENT;
 
266
    result= my_errno=ENOENT;
310
267
  }
311
 
  THR_LOCK_heap.unlock();
 
268
  pthread_mutex_unlock(&THR_LOCK_heap);
312
269
  return(result);
313
270
}
314
271
 
315
272
 
 
273
void heap_drop_table(HP_INFO *info)
 
274
{
 
275
  pthread_mutex_lock(&THR_LOCK_heap);
 
276
  heap_try_free(info->s);
 
277
  pthread_mutex_unlock(&THR_LOCK_heap);
 
278
  return;
 
279
}
 
280
 
 
281
 
316
282
void hp_free(HP_SHARE *share)
317
283
{
318
 
  heap_share_list.remove(share);        /* If not internal table */
 
284
  if (share->open_list.data)                    /* If not internal table */
 
285
    heap_share_list= list_delete(heap_share_list, &share->open_list);
319
286
  hp_clear(share);                      /* Remove blocks from memory */
320
 
  if (share->keydef)
321
 
    delete [] share->keydef->seg;
322
 
  delete [] share->keydef;
323
 
  delete share;
 
287
  thr_lock_delete(&share->lock);
 
288
  VOID(pthread_mutex_destroy(&share->intern_lock));
 
289
  my_free((uchar*) share->name, MYF(0));
 
290
  my_free((uchar*) share, MYF(0));
 
291
  return;
324
292
}