~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to storage/myisam/mi_write.c

  • Committer: Brian Aker
  • Date: 2008-07-07 16:07:49 UTC
  • mfrom: (80.1.1 food)
  • Revision ID: brian@tangent.org-20080707160749-qj89fnnwufz4xgop
Clean up install, we no longer have system tables.

Show diffs side-by-side

added added

removed removed

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