~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to storage/myisam/mi_write.c

Moved my_handler to MyISAM.

Show diffs side-by-side

added added

removed removed

Lines of Context:
17
17
 
18
18
#include "myisamdef.h"
19
19
 
20
 
#include <mystrings/m_string.h>
21
 
#include <drizzled/util/test.h>
22
 
 
23
 
 
24
20
#define MAX_POINTER_LENGTH 8
25
21
 
26
22
        /* Functions declared in this file */
27
23
 
28
24
static int w_search(MI_INFO *info,MI_KEYDEF *keyinfo,
29
 
                    uint32_t comp_flag, unsigned char *key,
30
 
                    uint32_t key_length, my_off_t pos, unsigned char *father_buff,
31
 
                    unsigned char *father_keypos, my_off_t father_page,
32
 
                    bool insert_last);
33
 
static int _mi_balance_page(MI_INFO *info,MI_KEYDEF *keyinfo,unsigned char *key,
34
 
                            unsigned char *curr_buff,unsigned char *father_buff,
35
 
                            unsigned char *father_keypos,my_off_t father_page);
36
 
static unsigned char *_mi_find_last_pos(MI_KEYDEF *keyinfo, unsigned char *page,
37
 
                                unsigned char *key, uint32_t *return_key_length,
38
 
                                unsigned char **after_key);
39
 
int _mi_ck_write_tree(register MI_INFO *info, uint32_t keynr,unsigned char *key,
40
 
                      uint32_t key_length);
41
 
int _mi_ck_write_btree(register MI_INFO *info, uint32_t keynr,unsigned char *key,
42
 
                       uint32_t key_length);
 
25
                    uint comp_flag, uchar *key,
 
26
                    uint key_length, my_off_t pos, uchar *father_buff,
 
27
                    uchar *father_keypos, my_off_t father_page,
 
28
                    my_bool insert_last);
 
29
static int _mi_balance_page(MI_INFO *info,MI_KEYDEF *keyinfo,uchar *key,
 
30
                            uchar *curr_buff,uchar *father_buff,
 
31
                            uchar *father_keypos,my_off_t father_page);
 
32
static uchar *_mi_find_last_pos(MI_KEYDEF *keyinfo, uchar *page,
 
33
                                uchar *key, uint *return_key_length,
 
34
                                uchar **after_key);
 
35
int _mi_ck_write_tree(register MI_INFO *info, uint keynr,uchar *key,
 
36
                      uint key_length);
 
37
int _mi_ck_write_btree(register MI_INFO *info, uint keynr,uchar *key,
 
38
                       uint key_length);
43
39
 
44
40
        /* Write new record to database */
45
41
 
46
 
int mi_write(MI_INFO *info, unsigned char *record)
 
42
int mi_write(MI_INFO *info, uchar *record)
47
43
{
48
44
  MYISAM_SHARE *share=info->s;
49
 
  uint32_t i;
 
45
  uint i;
50
46
  int save_errno;
51
47
  my_off_t filepos;
52
 
  unsigned char *buff;
53
 
  bool lock_tree= share->concurrent_insert;
 
48
  uchar *buff;
 
49
  my_bool lock_tree= share->concurrent_insert;
 
50
  DBUG_ENTER("mi_write");
 
51
  DBUG_PRINT("enter",("isam: %d  data: %d",info->s->kfile,info->dfile));
54
52
 
 
53
  DBUG_EXECUTE_IF("myisam_pretend_crashed_table_on_usage",
 
54
                  mi_print_error(info->s, HA_ERR_CRASHED);
 
55
                  DBUG_RETURN(my_errno= HA_ERR_CRASHED););
55
56
  if (share->options & HA_OPTION_READ_ONLY_DATA)
56
57
  {
57
 
    return(my_errno=EACCES);
 
58
    DBUG_RETURN(my_errno=EACCES);
58
59
  }
59
60
  if (_mi_readinfo(info,F_WRLCK,1))
60
 
    return(my_errno);
 
61
    DBUG_RETURN(my_errno);
 
62
#if !defined(NO_LOCKING) && defined(USE_RECORD_LOCK)
 
63
  if (!info->locked && my_lock(info->dfile,F_WRLCK,0L,F_TO_EOF,
 
64
                               MYF(MY_SEEK_NOT_DONE) | info->lock_wait))
 
65
    goto err;
 
66
#endif
61
67
  filepos= ((share->state.dellink != HA_OFFSET_ERROR &&
62
68
             !info->append_insert_at_end) ?
63
69
            share->state.dellink :
94
100
  {
95
101
    if (mi_is_key_active(share->state.key_map, i))
96
102
    {
97
 
      bool local_lock_tree= (lock_tree &&
 
103
      my_bool local_lock_tree= (lock_tree &&
98
104
                                !(info->bulk_insert &&
99
105
                                  is_tree_inited(&info->bulk_insert[i])));
100
106
      if (local_lock_tree)
101
107
      {
102
 
        pthread_rwlock_wrlock(&share->key_root_lock[i]);
 
108
        rw_wrlock(&share->key_root_lock[i]);
103
109
        share->keyinfo[i].version++;
104
110
      }
105
111
      {
107
113
                        _mi_make_key(info,i,buff,record,filepos)))
108
114
        {
109
115
          if (local_lock_tree)
110
 
            pthread_rwlock_unlock(&share->key_root_lock[i]);
 
116
            rw_unlock(&share->key_root_lock[i]);
 
117
          DBUG_PRINT("error",("Got error: %d on write",my_errno));
111
118
          goto err;
112
119
        }
113
120
      }
116
123
      info->update&= ~HA_STATE_RNEXT_SAME;
117
124
 
118
125
      if (local_lock_tree)
119
 
        pthread_rwlock_unlock(&share->key_root_lock[i]);
 
126
        rw_unlock(&share->key_root_lock[i]);
120
127
    }
121
128
  }
122
129
  if (share->calc_checksum)
134
141
                 HA_STATE_ROW_CHANGED);
135
142
  info->state->records++;
136
143
  info->lastpos=filepos;
137
 
  _mi_writeinfo(info, WRITEINFO_UPDATE_KEYFILE);
 
144
  myisam_log_record(MI_LOG_WRITE,info,record,filepos,0);
 
145
  VOID(_mi_writeinfo(info, WRITEINFO_UPDATE_KEYFILE));
 
146
  if (info->invalidator != 0)
 
147
  {
 
148
    DBUG_PRINT("info", ("invalidator... '%s' (update)", info->filename));
 
149
    (*info->invalidator)(info->filename);
 
150
    info->invalidator=0;
 
151
  }
138
152
 
139
153
  /*
140
154
    Update status of the table. We need to do so after each row write
147
161
  if (share->is_log_table)
148
162
    mi_update_status((void*) info);
149
163
 
150
 
  return(0);
 
164
  DBUG_RETURN(0);
151
165
 
152
166
err:
153
167
  save_errno=my_errno;
156
170
  {
157
171
    if (info->bulk_insert)
158
172
    {
159
 
      uint32_t j;
 
173
      uint j;
160
174
      for (j=0 ; j < share->base.keys ; j++)
161
175
        mi_flush_bulk_insert(info, j);
162
176
    }
165
179
    {
166
180
      if (mi_is_key_active(share->state.key_map, i))
167
181
      {
168
 
        bool local_lock_tree= (lock_tree &&
 
182
        my_bool local_lock_tree= (lock_tree &&
169
183
                                  !(info->bulk_insert &&
170
184
                                    is_tree_inited(&info->bulk_insert[i])));
171
185
        if (local_lock_tree)
172
 
          pthread_rwlock_wrlock(&share->key_root_lock[i]);
 
186
          rw_wrlock(&share->key_root_lock[i]);
173
187
        {
174
 
          uint32_t key_length=_mi_make_key(info,i,buff,record,filepos);
 
188
          uint key_length=_mi_make_key(info,i,buff,record,filepos);
175
189
          if (_mi_ck_delete(info,i,buff,key_length))
176
190
          {
177
191
            if (local_lock_tree)
178
 
              pthread_rwlock_unlock(&share->key_root_lock[i]);
 
192
              rw_unlock(&share->key_root_lock[i]);
179
193
            break;
180
194
          }
181
195
        }
182
196
        if (local_lock_tree)
183
 
          pthread_rwlock_unlock(&share->key_root_lock[i]);
 
197
          rw_unlock(&share->key_root_lock[i]);
184
198
      }
185
199
    }
186
200
  }
193
207
  my_errno=save_errno;
194
208
err2:
195
209
  save_errno=my_errno;
196
 
  _mi_writeinfo(info,WRITEINFO_UPDATE_KEYFILE);
197
 
  return(my_errno=save_errno);
 
210
  myisam_log_record(MI_LOG_WRITE,info,record,filepos,my_errno);
 
211
  VOID(_mi_writeinfo(info,WRITEINFO_UPDATE_KEYFILE));
 
212
  DBUG_RETURN(my_errno=save_errno);
198
213
} /* mi_write */
199
214
 
200
215
 
201
216
        /* Write one key to btree */
202
217
 
203
 
int _mi_ck_write(MI_INFO *info, uint32_t keynr, unsigned char *key, uint32_t key_length)
 
218
int _mi_ck_write(MI_INFO *info, uint keynr, uchar *key, uint key_length)
204
219
{
 
220
  DBUG_ENTER("_mi_ck_write");
 
221
 
205
222
  if (info->bulk_insert && is_tree_inited(&info->bulk_insert[keynr]))
206
223
  {
207
 
    return(_mi_ck_write_tree(info, keynr, key, key_length));
 
224
    DBUG_RETURN(_mi_ck_write_tree(info, keynr, key, key_length));
208
225
  }
209
226
  else
210
227
  {
211
 
    return(_mi_ck_write_btree(info, keynr, key, key_length));
 
228
    DBUG_RETURN(_mi_ck_write_btree(info, keynr, key, key_length));
212
229
  }
213
230
} /* _mi_ck_write */
214
231
 
217
234
 *                Normal insert code                                  *
218
235
 **********************************************************************/
219
236
 
220
 
int _mi_ck_write_btree(register MI_INFO *info, uint32_t keynr, unsigned char *key,
221
 
                       uint32_t key_length)
 
237
int _mi_ck_write_btree(register MI_INFO *info, uint keynr, uchar *key,
 
238
                       uint key_length)
222
239
{
223
 
  uint32_t error;
224
 
  uint32_t comp_flag;
 
240
  int error;
 
241
  uint comp_flag;
225
242
  MI_KEYDEF *keyinfo=info->s->keyinfo+keynr;
226
243
  my_off_t  *root=&info->s->state.key_root[keynr];
 
244
  DBUG_ENTER("_mi_ck_write_btree");
227
245
 
228
246
  if (keyinfo->flag & HA_SORT_ALLOWS_SAME)
229
247
    comp_flag=SEARCH_BIGGER;                    /* Put after same key */
238
256
 
239
257
  error=_mi_ck_real_write_btree(info, keyinfo, key, key_length,
240
258
                                root, comp_flag);
241
 
  return(error);
 
259
  if (info->ft1_to_ft2)
 
260
  {
 
261
    if (!error)
 
262
      error= _mi_ft_convert_to_ft2(info, keynr, key);
 
263
    delete_dynamic(info->ft1_to_ft2);
 
264
    my_free((uchar*)info->ft1_to_ft2, MYF(0));
 
265
    info->ft1_to_ft2=0;
 
266
  }
 
267
  DBUG_RETURN(error);
242
268
} /* _mi_ck_write_btree */
243
269
 
244
270
int _mi_ck_real_write_btree(MI_INFO *info, MI_KEYDEF *keyinfo,
245
 
    unsigned char *key, uint32_t key_length, my_off_t *root, uint32_t comp_flag)
 
271
    uchar *key, uint key_length, my_off_t *root, uint comp_flag)
246
272
{
247
273
  int error;
 
274
  DBUG_ENTER("_mi_ck_real_write_btree");
248
275
  /* key_length parameter is used only if comp_flag is SEARCH_FIND */
249
276
  if (*root == HA_OFFSET_ERROR ||
250
277
      (error=w_search(info, keyinfo, comp_flag, key, key_length,
251
 
                      *root, (unsigned char *) 0, (unsigned char*) 0,
 
278
                      *root, (uchar *) 0, (uchar*) 0,
252
279
                      (my_off_t) 0, 1)) > 0)
253
280
    error=_mi_enlarge_root(info,keyinfo,key,root);
254
 
  return(error);
 
281
  DBUG_RETURN(error);
255
282
} /* _mi_ck_real_write_btree */
256
283
 
257
284
 
258
285
        /* Make a new root with key as only pointer */
259
286
 
260
 
int _mi_enlarge_root(MI_INFO *info, MI_KEYDEF *keyinfo, unsigned char *key,
 
287
int _mi_enlarge_root(MI_INFO *info, MI_KEYDEF *keyinfo, uchar *key,
261
288
                     my_off_t *root)
262
289
{
263
 
  uint32_t t_length,nod_flag;
 
290
  uint t_length,nod_flag;
264
291
  MI_KEY_PARAM s_temp;
265
292
  MYISAM_SHARE *share=info->s;
 
293
  DBUG_ENTER("_mi_enlarge_root");
266
294
 
267
295
  nod_flag= (*root != HA_OFFSET_ERROR) ?  share->base.key_reflength : 0;
268
296
  _mi_kpointer(info,info->buff+2,*root); /* if nod */
269
 
  t_length=(*keyinfo->pack_key)(keyinfo,nod_flag,(unsigned char*) 0,
270
 
                                (unsigned char*) 0, (unsigned char*) 0, key,&s_temp);
 
297
  t_length=(*keyinfo->pack_key)(keyinfo,nod_flag,(uchar*) 0,
 
298
                                (uchar*) 0, (uchar*) 0, key,&s_temp);
271
299
  mi_putint(info->buff,t_length+2+nod_flag,nod_flag);
272
300
  (*keyinfo->store_key)(keyinfo,info->buff+2+nod_flag,&s_temp);
273
301
  info->buff_used=info->page_changed=1;         /* info->buff is used */
274
302
  if ((*root= _mi_new(info,keyinfo,DFLT_INIT_HITS)) == HA_OFFSET_ERROR ||
275
303
      _mi_write_keypage(info,keyinfo,*root,DFLT_INIT_HITS,info->buff))
276
 
    return(-1);
277
 
  return(0);
 
304
    DBUG_RETURN(-1);
 
305
  DBUG_RETURN(0);
278
306
} /* _mi_enlarge_root */
279
307
 
280
308
 
286
314
        */
287
315
 
288
316
static int w_search(register MI_INFO *info, register MI_KEYDEF *keyinfo,
289
 
                    uint32_t comp_flag, unsigned char *key, uint32_t key_length, my_off_t page,
290
 
                    unsigned char *father_buff, unsigned char *father_keypos,
291
 
                    my_off_t father_page, bool insert_last)
 
317
                    uint comp_flag, uchar *key, uint key_length, my_off_t page,
 
318
                    uchar *father_buff, uchar *father_keypos,
 
319
                    my_off_t father_page, my_bool insert_last)
292
320
{
293
321
  int error,flag;
294
 
  uint32_t nod_flag, search_key_length;
295
 
  unsigned char *temp_buff,*keypos;
296
 
  unsigned char keybuff[MI_MAX_KEY_BUFF];
297
 
  bool was_last_key;
 
322
  uint nod_flag, search_key_length;
 
323
  uchar *temp_buff,*keypos;
 
324
  uchar keybuff[MI_MAX_KEY_BUFF];
 
325
  my_bool was_last_key;
298
326
  my_off_t next_page, dupp_key_pos;
 
327
  DBUG_ENTER("w_search");
 
328
  DBUG_PRINT("enter",("page: %ld", (long) page));
299
329
 
300
330
  search_key_length= (comp_flag & SEARCH_FIND) ? key_length : USE_WHOLE_KEY;
301
 
  if (!(temp_buff= (unsigned char*) malloc(keyinfo->block_length+
302
 
                                           MI_MAX_KEY_BUFF*2)))
303
 
    return(-1);
 
331
  if (!(temp_buff= (uchar*) my_alloca((uint) keyinfo->block_length+
 
332
                                      MI_MAX_KEY_BUFF*2)))
 
333
    DBUG_RETURN(-1);
304
334
  if (!_mi_fetch_keypage(info,keyinfo,page,DFLT_INIT_HITS,temp_buff,0))
305
335
    goto err;
306
336
 
309
339
  nod_flag=mi_test_if_nod(temp_buff);
310
340
  if (flag == 0)
311
341
  {
312
 
    uint32_t tmp_key_length;
 
342
    uint tmp_key_length;
313
343
        /* get position to record with duplicated key */
314
344
    tmp_key_length=(*keyinfo->get_key)(keyinfo,nod_flag,&keypos,keybuff);
315
345
    if (tmp_key_length)
319
349
 
320
350
    {
321
351
      info->dupp_key_pos= dupp_key_pos;
322
 
      free(temp_buff);
 
352
      my_afree((uchar*) temp_buff);
323
353
      my_errno=HA_ERR_FOUND_DUPP_KEY;
324
 
      return(-1);
 
354
      DBUG_RETURN(-1);
325
355
    }
326
356
  }
327
357
  if (flag == MI_FOUND_WRONG_KEY)
328
 
    return(-1);
 
358
    DBUG_RETURN(-1);
329
359
  if (!was_last_key)
330
360
    insert_last=0;
331
361
  next_page=_mi_kpos(nod_flag,keypos);
338
368
    if (_mi_write_keypage(info,keyinfo,page,DFLT_INIT_HITS,temp_buff))
339
369
      goto err;
340
370
  }
341
 
  free(temp_buff);
342
 
  return(error);
 
371
  my_afree((uchar*) temp_buff);
 
372
  DBUG_RETURN(error);
343
373
err:
344
 
  free(temp_buff);
345
 
  return (-1);
 
374
  my_afree((uchar*) temp_buff);
 
375
  DBUG_PRINT("exit",("Error: %d",my_errno));
 
376
  DBUG_RETURN (-1);
346
377
} /* w_search */
347
378
 
348
379
 
372
403
*/
373
404
 
374
405
int _mi_insert(register MI_INFO *info, register MI_KEYDEF *keyinfo,
375
 
               unsigned char *key, unsigned char *anc_buff, unsigned char *key_pos, unsigned char *key_buff,
376
 
               unsigned char *father_buff, unsigned char *father_key_pos, my_off_t father_page,
377
 
               bool insert_last)
 
406
               uchar *key, uchar *anc_buff, uchar *key_pos, uchar *key_buff,
 
407
               uchar *father_buff, uchar *father_key_pos, my_off_t father_page,
 
408
               my_bool insert_last)
378
409
{
379
 
  uint32_t a_length,nod_flag;
 
410
  uint a_length,nod_flag;
380
411
  int t_length;
381
 
  unsigned char *endpos, *prev_key;
 
412
  uchar *endpos, *prev_key;
382
413
  MI_KEY_PARAM s_temp;
 
414
  DBUG_ENTER("_mi_insert");
 
415
  DBUG_PRINT("enter",("key_pos: 0x%lx", (long) key_pos));
 
416
  DBUG_EXECUTE("key",_mi_print_key(DBUG_FILE,keyinfo->seg,key,USE_WHOLE_KEY););
383
417
 
384
418
  nod_flag=mi_test_if_nod(anc_buff);
385
419
  a_length=mi_getint(anc_buff);
386
420
  endpos= anc_buff+ a_length;
387
 
  prev_key=(key_pos == anc_buff+2+nod_flag ? (unsigned char*) 0 : key_buff);
 
421
  prev_key=(key_pos == anc_buff+2+nod_flag ? (uchar*) 0 : key_buff);
388
422
  t_length=(*keyinfo->pack_key)(keyinfo,nod_flag,
389
 
                                (key_pos == endpos ? (unsigned char*) 0 : key_pos),
 
423
                                (key_pos == endpos ? (uchar*) 0 : key_pos),
390
424
                                prev_key, prev_key,
391
425
                                key,&s_temp);
392
 
 
 
426
#ifndef DBUG_OFF
 
427
  if (key_pos != anc_buff+2+nod_flag && (keyinfo->flag &
 
428
                                         (HA_BINARY_PACK_KEY | HA_PACK_KEY)))
 
429
  {
 
430
    DBUG_DUMP("prev_key",(uchar*) key_buff,_mi_keylength(keyinfo,key_buff));
 
431
  }
 
432
  if (keyinfo->flag & HA_PACK_KEY)
 
433
  {
 
434
    DBUG_PRINT("test",("t_length: %d  ref_len: %d",
 
435
                       t_length,s_temp.ref_length));
 
436
    DBUG_PRINT("test",("n_ref_len: %d  n_length: %d  key_pos: 0x%lx",
 
437
                       s_temp.n_ref_length,s_temp.n_length, (long) s_temp.key));
 
438
  }
 
439
#endif
393
440
  if (t_length > 0)
394
441
  {
395
442
    if (t_length >= keyinfo->maxlength*2+MAX_POINTER_LENGTH)
396
443
    {
397
444
      mi_print_error(info->s, HA_ERR_CRASHED);
398
445
      my_errno=HA_ERR_CRASHED;
399
 
      return(-1);
 
446
      DBUG_RETURN(-1);
400
447
    }
401
 
    bmove_upp((unsigned char*) endpos+t_length,(unsigned char*) endpos,(uint) (endpos-key_pos));
 
448
    bmove_upp((uchar*) endpos+t_length,(uchar*) endpos,(uint) (endpos-key_pos));
402
449
  }
403
450
  else
404
451
  {
406
453
    {
407
454
      mi_print_error(info->s, HA_ERR_CRASHED);
408
455
      my_errno=HA_ERR_CRASHED;
409
 
      return(-1);
 
456
      DBUG_RETURN(-1);
410
457
    }
411
 
    memmove(key_pos, key_pos - t_length, endpos - key_pos + t_length);
 
458
    bmove(key_pos,key_pos-t_length,(uint) (endpos-key_pos)+t_length);
412
459
  }
413
460
  (*keyinfo->store_key)(keyinfo,key_pos,&s_temp);
414
461
  a_length+=t_length;
415
462
  mi_putint(anc_buff,a_length,nod_flag);
416
463
  if (a_length <= keyinfo->block_length)
417
464
  {
418
 
    return(0);                          /* There is room on page */
 
465
    DBUG_RETURN(0);                             /* There is room on page */
419
466
  }
420
467
  /* Page is full */
421
468
  if (nod_flag)
422
469
    insert_last=0;
423
470
  if (!(keyinfo->flag & (HA_VAR_LENGTH_KEY | HA_BINARY_PACK_KEY)) &&
424
471
      father_buff && !insert_last)
425
 
    return(_mi_balance_page(info,keyinfo,key,anc_buff,father_buff,
 
472
    DBUG_RETURN(_mi_balance_page(info,keyinfo,key,anc_buff,father_buff,
426
473
                                 father_key_pos,father_page));
427
 
  return(_mi_split_page(info,keyinfo,key,anc_buff,key_buff, insert_last));
 
474
  DBUG_RETURN(_mi_split_page(info,keyinfo,key,anc_buff,key_buff, insert_last));
428
475
} /* _mi_insert */
429
476
 
430
477
 
431
478
        /* split a full page in two and assign emerging item to key */
432
479
 
433
480
int _mi_split_page(register MI_INFO *info, register MI_KEYDEF *keyinfo,
434
 
                   unsigned char *key, unsigned char *buff, unsigned char *key_buff,
435
 
                   bool insert_last_key)
 
481
                   uchar *key, uchar *buff, uchar *key_buff,
 
482
                   my_bool insert_last_key)
436
483
{
437
 
  uint32_t length,a_length,key_ref_length,t_length,nod_flag,key_length;
438
 
  unsigned char *key_pos,*pos, *after_key= NULL;
 
484
  uint length,a_length,key_ref_length,t_length,nod_flag,key_length;
 
485
  uchar *key_pos,*pos, *after_key= NULL;
439
486
  my_off_t new_pos;
440
487
  MI_KEY_PARAM s_temp;
 
488
  DBUG_ENTER("mi_split_page");
 
489
  DBUG_DUMP("buff",(uchar*) buff,mi_getint(buff));
441
490
 
442
491
  if (info->s->keyinfo+info->lastinx == keyinfo)
443
492
    info->page_changed=1;                       /* Info->buff is used */
450
499
    key_pos=_mi_find_half_pos(nod_flag,keyinfo,buff,key_buff, &key_length,
451
500
                              &after_key);
452
501
  if (!key_pos)
453
 
    return(-1);
 
502
    DBUG_RETURN(-1);
454
503
 
455
504
  length=(uint) (key_pos-buff);
456
505
  a_length=mi_getint(buff);
459
508
  key_pos=after_key;
460
509
  if (nod_flag)
461
510
  {
 
511
    DBUG_PRINT("test",("Splitting nod"));
462
512
    pos=key_pos-nod_flag;
463
 
    memcpy(info->buff + 2, pos, nod_flag);
 
513
    memcpy((uchar*) info->buff+2,(uchar*) pos,(size_t) nod_flag);
464
514
  }
465
515
 
466
516
        /* Move middle item to key and pointer to new page */
467
517
  if ((new_pos=_mi_new(info,keyinfo,DFLT_INIT_HITS)) == HA_OFFSET_ERROR)
468
 
    return(-1);
 
518
    DBUG_RETURN(-1);
469
519
  _mi_kpointer(info,_mi_move_key(keyinfo,key,key_buff),new_pos);
470
520
 
471
521
        /* Store new page */
472
522
  if (!(*keyinfo->get_key)(keyinfo,nod_flag,&key_pos,key_buff))
473
 
    return(-1);
 
523
    DBUG_RETURN(-1);
474
524
 
475
 
  t_length=(*keyinfo->pack_key)(keyinfo,nod_flag,(unsigned char *) 0,
476
 
                                (unsigned char*) 0, (unsigned char*) 0,
 
525
  t_length=(*keyinfo->pack_key)(keyinfo,nod_flag,(uchar *) 0,
 
526
                                (uchar*) 0, (uchar*) 0,
477
527
                                key_buff, &s_temp);
478
528
  length=(uint) ((buff+a_length)-key_pos);
479
 
  memcpy(info->buff+key_ref_length+t_length, key_pos, length);
 
529
  memcpy((uchar*) info->buff+key_ref_length+t_length,(uchar*) key_pos,
 
530
         (size_t) length);
480
531
  (*keyinfo->store_key)(keyinfo,info->buff+key_ref_length,&s_temp);
481
532
  mi_putint(info->buff,length+t_length+key_ref_length,nod_flag);
482
533
 
483
534
  if (_mi_write_keypage(info,keyinfo,new_pos,DFLT_INIT_HITS,info->buff))
484
 
    return(-1);
485
 
  return(2);                            /* Middle key up */
 
535
    DBUG_RETURN(-1);
 
536
  DBUG_DUMP("key",(uchar*) key,_mi_keylength(keyinfo,key));
 
537
  DBUG_RETURN(2);                               /* Middle key up */
486
538
} /* _mi_split_page */
487
539
 
488
540
 
494
546
          after_key will contain the position to where the next key starts
495
547
        */
496
548
 
497
 
unsigned char *_mi_find_half_pos(uint32_t nod_flag, MI_KEYDEF *keyinfo, unsigned char *page,
498
 
                         unsigned char *key, uint32_t *return_key_length,
499
 
                         unsigned char **after_key)
 
549
uchar *_mi_find_half_pos(uint nod_flag, MI_KEYDEF *keyinfo, uchar *page,
 
550
                         uchar *key, uint *return_key_length,
 
551
                         uchar **after_key)
500
552
{
501
 
  uint32_t keys,length,key_ref_length;
502
 
  unsigned char *end,*lastpos;
 
553
  uint keys,length,key_ref_length;
 
554
  uchar *end,*lastpos;
 
555
  DBUG_ENTER("_mi_find_half_pos");
503
556
 
504
557
  key_ref_length=2+nod_flag;
505
558
  length=mi_getint(page)-key_ref_length;
514
567
    end=page+keys*key_ref_length;
515
568
    *after_key=end+key_ref_length;
516
569
    memcpy(key,end,key_ref_length);
517
 
    return(end);
 
570
    DBUG_RETURN(end);
518
571
  }
519
572
 
520
573
  end=page+length/2-key_ref_length;             /* This is aprox. half */
523
576
  {
524
577
    lastpos=page;
525
578
    if (!(length=(*keyinfo->get_key)(keyinfo,nod_flag,&page,key)))
526
 
      return(0);
 
579
      DBUG_RETURN(0);
527
580
  } while (page < end);
528
581
  *return_key_length=length;
529
582
  *after_key=page;
530
 
  return(lastpos);
 
583
  DBUG_PRINT("exit",("returns: 0x%lx  page: 0x%lx  half: 0x%lx",
 
584
                     (long) lastpos, (long) page, (long) end));
 
585
  DBUG_RETURN(lastpos);
531
586
} /* _mi_find_half_pos */
532
587
 
533
588
 
537
592
          key will contain the last key
538
593
        */
539
594
 
540
 
static unsigned char *_mi_find_last_pos(MI_KEYDEF *keyinfo, unsigned char *page,
541
 
                                unsigned char *key, uint32_t *return_key_length,
542
 
                                unsigned char **after_key)
 
595
static uchar *_mi_find_last_pos(MI_KEYDEF *keyinfo, uchar *page,
 
596
                                uchar *key, uint *return_key_length,
 
597
                                uchar **after_key)
543
598
{
544
 
  uint32_t keys;
545
 
  uint32_t length;
546
 
  uint32_t last_length= 0;
547
 
  uint32_t key_ref_length;
548
 
  unsigned char *end, *lastpos, *prevpos= NULL;
549
 
  unsigned char key_buff[MI_MAX_KEY_BUFF];
 
599
  uint keys, length, last_length, key_ref_length;
 
600
  uchar *end, *lastpos, *prevpos= NULL;
 
601
  uchar key_buff[MI_MAX_KEY_BUFF];
 
602
  DBUG_ENTER("_mi_find_last_pos");
550
603
 
551
604
  key_ref_length=2;
552
605
  length=mi_getint(page)-key_ref_length;
560
613
    end=page+keys*length;
561
614
    *after_key=end+length;
562
615
    memcpy(key,end,length);
563
 
    return(end);
 
616
    DBUG_RETURN(end);
564
617
  }
565
618
 
566
619
  end= page + length - key_ref_length;
576
629
    {
577
630
      mi_print_error(keyinfo->share, HA_ERR_CRASHED);
578
631
      my_errno=HA_ERR_CRASHED;
579
 
      return(0);
 
632
      DBUG_RETURN(0);
580
633
    }
581
634
  }
582
635
  *return_key_length=last_length;
583
636
  *after_key=lastpos;
584
 
  return(prevpos);
 
637
  DBUG_PRINT("exit",("returns: 0x%lx  page: 0x%lx  end: 0x%lx",
 
638
                     (long) prevpos,(long) page,(long) end));
 
639
  DBUG_RETURN(prevpos);
585
640
} /* _mi_find_last_pos */
586
641
 
587
642
 
589
644
        /* returns 0 if balance was done */
590
645
 
591
646
static int _mi_balance_page(register MI_INFO *info, MI_KEYDEF *keyinfo,
592
 
                            unsigned char *key, unsigned char *curr_buff, unsigned char *father_buff,
593
 
                            unsigned char *father_key_pos, my_off_t father_page)
 
647
                            uchar *key, uchar *curr_buff, uchar *father_buff,
 
648
                            uchar *father_key_pos, my_off_t father_page)
594
649
{
595
 
  bool right;
596
 
  uint32_t k_length,father_length,father_keylength,nod_flag,curr_keylength,
 
650
  my_bool right;
 
651
  uint k_length,father_length,father_keylength,nod_flag,curr_keylength,
597
652
       right_length,left_length,new_right_length,new_left_length,extra_length,
598
653
       length,keys;
599
 
  unsigned char *pos,*buff,*extra_buff;
 
654
  uchar *pos,*buff,*extra_buff;
600
655
  my_off_t next_page,new_pos;
601
 
  unsigned char tmp_part_key[MI_MAX_KEY_BUFF];
 
656
  uchar tmp_part_key[MI_MAX_KEY_BUFF];
 
657
  DBUG_ENTER("_mi_balance_page");
602
658
 
603
659
  k_length=keyinfo->keylength;
604
660
  father_length=mi_getint(father_buff);
615
671
    next_page= _mi_kpos(info->s->base.key_reflength,
616
672
                        father_key_pos+father_keylength);
617
673
    buff=info->buff;
 
674
    DBUG_PRINT("test",("use right page: %lu", (ulong) next_page));
618
675
  }
619
676
  else
620
677
  {
623
680
    next_page= _mi_kpos(info->s->base.key_reflength,father_key_pos);
624
681
                                        /* Fix that curr_buff is to left */
625
682
    buff=curr_buff; curr_buff=info->buff;
 
683
    DBUG_PRINT("test",("use left page: %lu", (ulong) next_page));
626
684
  }                                     /* father_key_pos ptr to parting key */
627
685
 
628
686
  if (!_mi_fetch_keypage(info,keyinfo,next_page,DFLT_INIT_HITS,info->buff,0))
629
687
    goto err;
 
688
  DBUG_DUMP("next",(uchar*) info->buff,mi_getint(info->buff));
630
689
 
631
690
        /* Test if there is room to share keys */
632
691
 
645
704
    if (left_length < new_left_length)
646
705
    {                                           /* Move keys buff -> leaf */
647
706
      pos=curr_buff+left_length;
648
 
      memcpy(pos, father_key_pos, k_length);
649
 
      length= new_left_length - left_length - k_length;
650
 
      memcpy(pos+k_length, buff+2, length);
 
707
      memcpy((uchar*) pos,(uchar*) father_key_pos, (size_t) k_length);
 
708
      memcpy((uchar*) pos+k_length, (uchar*) buff+2,
 
709
             (size_t) (length=new_left_length - left_length - k_length));
651
710
      pos=buff+2+length;
652
 
      memcpy(father_key_pos, pos, k_length);
653
 
      memmove(buff+2, pos+k_length, new_right_length);
 
711
      memcpy((uchar*) father_key_pos,(uchar*) pos,(size_t) k_length);
 
712
      bmove((uchar*) buff+2,(uchar*) pos+k_length,new_right_length);
654
713
    }
655
714
    else
656
715
    {                                           /* Move keys -> buff */
657
716
 
658
 
      bmove_upp((unsigned char*) buff+new_right_length,(unsigned char*) buff+right_length,
 
717
      bmove_upp((uchar*) buff+new_right_length,(uchar*) buff+right_length,
659
718
                right_length-2);
660
719
      length=new_right_length-right_length-k_length;
661
 
      memcpy(buff+2+length,father_key_pos, k_length);
 
720
      memcpy((uchar*) buff+2+length,father_key_pos,(size_t) k_length);
662
721
      pos=curr_buff+new_left_length;
663
 
      memcpy(father_key_pos, pos, k_length);
664
 
      memcpy(buff+2, pos+k_length, length);
 
722
      memcpy((uchar*) father_key_pos,(uchar*) pos,(size_t) k_length);
 
723
      memcpy((uchar*) buff+2,(uchar*) pos+k_length,(size_t) length);
665
724
    }
666
725
 
667
726
    if (_mi_write_keypage(info,keyinfo,next_page,DFLT_INIT_HITS,info->buff) ||
668
727
        _mi_write_keypage(info,keyinfo,father_page,DFLT_INIT_HITS,father_buff))
669
728
      goto err;
670
 
    return(0);
 
729
    DBUG_RETURN(0);
671
730
  }
672
731
 
673
732
        /* curr_buff[] and buff[] are full, lets split and make new nod */
678
737
    new_left_length-=curr_keylength;
679
738
  extra_length=nod_flag+left_length+right_length-
680
739
    new_left_length-new_right_length-curr_keylength;
 
740
  DBUG_PRINT("info",("left_length: %d  right_length: %d  new_left_length: %d  new_right_length: %d  extra_length: %d",
 
741
                     left_length, right_length,
 
742
                     new_left_length, new_right_length,
 
743
                     extra_length));
681
744
  mi_putint(curr_buff,new_left_length,nod_flag);
682
745
  mi_putint(buff,new_right_length,nod_flag);
683
746
  mi_putint(extra_buff,extra_length+2,nod_flag);
684
747
 
685
748
  /* move first largest keys to new page  */
686
749
  pos=buff+right_length-extra_length;
687
 
  memcpy(extra_buff+2, pos, extra_length);
 
750
  memcpy((uchar*) extra_buff+2,pos,(size_t) extra_length);
688
751
  /* Save new parting key */
689
752
  memcpy(tmp_part_key, pos-k_length,k_length);
690
753
  /* Make place for new keys */
691
 
  bmove_upp((unsigned char*) buff+new_right_length,(unsigned char*) pos-k_length,
 
754
  bmove_upp((uchar*) buff+new_right_length,(uchar*) pos-k_length,
692
755
            right_length-extra_length-k_length-2);
693
756
  /* Copy keys from left page */
694
757
  pos= curr_buff+new_left_length;
695
 
  length= left_length - new_left_length - k_length;
696
 
  memcpy(buff+2, pos+k_length, length);
 
758
  memcpy((uchar*) buff+2,(uchar*) pos+k_length,
 
759
         (size_t) (length=left_length-new_left_length-k_length));
697
760
  /* Copy old parting key */
698
 
  memcpy(buff+2+length, father_key_pos, k_length);
 
761
  memcpy((uchar*) buff+2+length,father_key_pos,(size_t) k_length);
699
762
 
700
763
  /* Move new parting keys up to caller */
701
 
  memcpy((right ? key : father_key_pos), pos, k_length);
702
 
  memcpy((right ? father_key_pos : key), tmp_part_key, k_length);
 
764
  memcpy((uchar*) (right ? key : father_key_pos),pos,(size_t) k_length);
 
765
  memcpy((uchar*) (right ? father_key_pos : key),tmp_part_key, k_length);
703
766
 
704
767
  if ((new_pos=_mi_new(info,keyinfo,DFLT_INIT_HITS)) == HA_OFFSET_ERROR)
705
768
    goto err;
710
773
                        DFLT_INIT_HITS,extra_buff))
711
774
    goto err;
712
775
 
713
 
  return(1);                            /* Middle key up */
 
776
  DBUG_RETURN(1);                               /* Middle key up */
714
777
 
715
778
err:
716
 
  return(-1);
 
779
  DBUG_RETURN(-1);
717
780
} /* _mi_balance_page */
718
781
 
719
782
/**********************************************************************
722
785
 
723
786
typedef struct {
724
787
  MI_INFO *info;
725
 
  uint32_t keynr;
 
788
  uint keynr;
726
789
} bulk_insert_param;
727
790
 
728
 
int _mi_ck_write_tree(register MI_INFO *info, uint32_t keynr, unsigned char *key,
729
 
                      uint32_t key_length)
 
791
int _mi_ck_write_tree(register MI_INFO *info, uint keynr, uchar *key,
 
792
                      uint key_length)
730
793
{
731
794
  int error;
 
795
  DBUG_ENTER("_mi_ck_write_tree");
732
796
 
733
797
  error= tree_insert(&info->bulk_insert[keynr], key,
734
798
         key_length + info->s->rec_reflength,
735
799
         info->bulk_insert[keynr].custom_arg) ? 0 : HA_ERR_OUT_OF_MEM ;
736
800
 
737
 
  return(error);
 
801
  DBUG_RETURN(error);
738
802
} /* _mi_ck_write_tree */
739
803
 
740
804
 
741
805
/* typeof(_mi_keys_compare)=qsort_cmp2 */
742
806
 
743
 
static int keys_compare(bulk_insert_param *param, unsigned char *key1, unsigned char *key2)
 
807
static int keys_compare(bulk_insert_param *param, uchar *key1, uchar *key2)
744
808
{
745
 
  uint32_t not_used[2];
 
809
  uint not_used[2];
746
810
  return ha_key_cmp(param->info->s->keyinfo[param->keynr].seg,
747
811
                    key1, key2, USE_WHOLE_KEY, SEARCH_SAME,
748
812
                    not_used);
749
813
}
750
814
 
751
815
 
752
 
static int keys_free(unsigned char *key, TREE_FREE mode, bulk_insert_param *param)
 
816
static int keys_free(uchar *key, TREE_FREE mode, bulk_insert_param *param)
753
817
{
754
818
  /*
755
819
    Probably I can use info->lastkey here, but I'm not sure,
756
820
    and to be safe I'd better use local lastkey.
757
821
  */
758
 
  unsigned char lastkey[MI_MAX_KEY_BUFF];
759
 
  uint32_t keylen;
 
822
  uchar lastkey[MI_MAX_KEY_BUFF];
 
823
  uint keylen;
760
824
  MI_KEYDEF *keyinfo;
761
825
 
762
826
  switch (mode) {
763
827
  case free_init:
764
828
    if (param->info->s->concurrent_insert)
765
829
    {
766
 
      pthread_rwlock_wrlock(&param->info->s->key_root_lock[param->keynr]);
 
830
      rw_wrlock(&param->info->s->key_root_lock[param->keynr]);
767
831
      param->info->s->keyinfo[param->keynr].version++;
768
832
    }
769
833
    return 0;
775
839
                              keylen - param->info->s->rec_reflength);
776
840
  case free_end:
777
841
    if (param->info->s->concurrent_insert)
778
 
      pthread_rwlock_unlock(&param->info->s->key_root_lock[param->keynr]);
 
842
      rw_unlock(&param->info->s->key_root_lock[param->keynr]);
779
843
    return 0;
780
844
  }
781
845
  return -1;
782
846
}
783
847
 
784
848
 
785
 
int mi_init_bulk_insert(MI_INFO *info, uint32_t cache_size, ha_rows rows)
 
849
int mi_init_bulk_insert(MI_INFO *info, ulong cache_size, ha_rows rows)
786
850
{
787
851
  MYISAM_SHARE *share=info->s;
788
852
  MI_KEYDEF *key=share->keyinfo;
789
853
  bulk_insert_param *params;
790
 
  uint32_t i, num_keys, total_keylength;
791
 
  uint64_t key_map;
 
854
  uint i, num_keys, total_keylength;
 
855
  ulonglong key_map;
 
856
  DBUG_ENTER("_mi_init_bulk_insert");
 
857
  DBUG_PRINT("enter",("cache_size: %lu", cache_size));
792
858
 
793
 
  assert(!info->bulk_insert &&
 
859
  DBUG_ASSERT(!info->bulk_insert &&
794
860
              (!rows || rows >= MI_MIN_ROWS_TO_USE_BULK_INSERT));
795
861
 
796
862
  mi_clear_all_keys_active(key_map);
807
873
 
808
874
  if (num_keys==0 ||
809
875
      num_keys * MI_MIN_SIZE_BULK_INSERT_TREE > cache_size)
810
 
    return(0);
 
876
    DBUG_RETURN(0);
811
877
 
812
878
  if (rows && rows*total_keylength < cache_size)
813
 
    cache_size= (uint32_t)rows;
 
879
    cache_size= (ulong)rows;
814
880
  else
815
881
    cache_size/=total_keylength*16;
816
882
 
817
883
  info->bulk_insert=(TREE *)
818
 
    malloc((sizeof(TREE)*share->base.keys+
819
 
           sizeof(bulk_insert_param)*num_keys));
 
884
    my_malloc((sizeof(TREE)*share->base.keys+
 
885
               sizeof(bulk_insert_param)*num_keys),MYF(0));
820
886
 
821
887
  if (!info->bulk_insert)
822
 
    return(HA_ERR_OUT_OF_MEM);
 
888
    DBUG_RETURN(HA_ERR_OUT_OF_MEM);
823
889
 
824
890
  params=(bulk_insert_param *)(info->bulk_insert+share->base.keys);
825
891
  for (i=0 ; i < share->base.keys ; i++)
839
905
     info->bulk_insert[i].root=0;
840
906
  }
841
907
 
842
 
  return(0);
 
908
  DBUG_RETURN(0);
843
909
}
844
910
 
845
 
void mi_flush_bulk_insert(MI_INFO *info, uint32_t inx)
 
911
void mi_flush_bulk_insert(MI_INFO *info, uint inx)
846
912
{
847
913
  if (info->bulk_insert)
848
914
  {
855
921
{
856
922
  if (info->bulk_insert)
857
923
  {
858
 
    uint32_t i;
 
924
    uint i;
859
925
    for (i=0 ; i < info->s->base.keys ; i++)
860
926
    {
861
927
      if (is_tree_inited(& info->bulk_insert[i]))
863
929
        delete_tree(& info->bulk_insert[i]);
864
930
      }
865
931
    }
866
 
    free((void *)info->bulk_insert);
 
932
    my_free((void *)info->bulk_insert, MYF(0));
867
933
    info->bulk_insert=0;
868
934
  }
869
935
}