~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to storage/myisam/mi_write.c

  • Committer: Monty Taylor
  • Date: 2008-10-30 18:44:27 UTC
  • mto: (520.4.35 devel)
  • mto: This revision was merged to the branch mainline in revision 572.
  • Revision ID: monty@inaugust.com-20081030184427-7cr1v6r5cqnuqm3v
Removed global sql_array.h.

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 */
 
14
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
15
15
 
16
16
/* Write a row to a MyISAM table */
17
17
 
18
 
#include "myisam_priv.h"
19
 
 
20
 
#include "drizzled/internal/m_string.h"
 
18
#include "myisamdef.h"
21
19
#include <drizzled/util/test.h>
22
20
 
23
 
using namespace drizzled;
24
21
 
25
22
#define MAX_POINTER_LENGTH 8
26
23
 
28
25
 
29
26
static int w_search(MI_INFO *info,MI_KEYDEF *keyinfo,
30
27
                    uint32_t comp_flag, unsigned char *key,
31
 
                    uint32_t key_length, internal::my_off_t pos, unsigned char *father_buff,
32
 
                    unsigned char *father_keypos, internal::my_off_t father_page,
 
28
                    uint32_t key_length, my_off_t pos, unsigned char *father_buff,
 
29
                    unsigned char *father_keypos, my_off_t father_page,
33
30
                    bool insert_last);
34
31
static int _mi_balance_page(MI_INFO *info,MI_KEYDEF *keyinfo,unsigned char *key,
35
32
                            unsigned char *curr_buff,unsigned char *father_buff,
36
 
                            unsigned char *father_keypos,internal::my_off_t father_page);
 
33
                            unsigned char *father_keypos,my_off_t father_page);
37
34
static unsigned char *_mi_find_last_pos(MI_KEYDEF *keyinfo, unsigned char *page,
38
35
                                unsigned char *key, uint32_t *return_key_length,
39
36
                                unsigned char **after_key);
49
46
  MYISAM_SHARE *share=info->s;
50
47
  uint32_t i;
51
48
  int save_errno;
52
 
  internal::my_off_t filepos;
 
49
  my_off_t filepos;
53
50
  unsigned char *buff;
54
51
  bool lock_tree= share->concurrent_insert;
55
52
 
56
53
  if (share->options & HA_OPTION_READ_ONLY_DATA)
57
54
  {
58
 
    return(errno=EACCES);
 
55
    return(my_errno=EACCES);
59
56
  }
60
57
  if (_mi_readinfo(info,F_WRLCK,1))
61
 
    return(errno);
 
58
    return(my_errno);
62
59
  filepos= ((share->state.dellink != HA_OFFSET_ERROR &&
63
60
             !info->append_insert_at_end) ?
64
61
            share->state.dellink :
68
65
      share->base.records == (ha_rows) 1 &&
69
66
      info->state->records == (ha_rows) 1)
70
67
  {                                             /* System file */
71
 
    errno=HA_ERR_RECORD_FILE_FULL;
 
68
    my_errno=HA_ERR_RECORD_FILE_FULL;
72
69
    goto err2;
73
70
  }
74
71
  if (info->state->key_file_length >= share->base.margin_key_file_length)
75
72
  {
76
 
    errno=HA_ERR_INDEX_FILE_FULL;
 
73
    my_errno=HA_ERR_INDEX_FILE_FULL;
77
74
    goto err2;
78
75
  }
79
76
  if (_mi_mark_file_changed(info))
100
97
                                  is_tree_inited(&info->bulk_insert[i])));
101
98
      if (local_lock_tree)
102
99
      {
 
100
        rw_wrlock(&share->key_root_lock[i]);
103
101
        share->keyinfo[i].version++;
104
102
      }
105
103
      {
106
104
        if (share->keyinfo[i].ck_insert(info,i,buff,
107
105
                        _mi_make_key(info,i,buff,record,filepos)))
108
106
        {
 
107
          if (local_lock_tree)
 
108
            rw_unlock(&share->key_root_lock[i]);
109
109
          goto err;
110
110
        }
111
111
      }
112
112
 
113
113
      /* The above changed info->lastkey2. Inform mi_rnext_same(). */
114
114
      info->update&= ~HA_STATE_RNEXT_SAME;
 
115
 
 
116
      if (local_lock_tree)
 
117
        rw_unlock(&share->key_root_lock[i]);
115
118
    }
116
119
  }
117
120
  if (share->calc_checksum)
130
133
  info->state->records++;
131
134
  info->lastpos=filepos;
132
135
  _mi_writeinfo(info, WRITEINFO_UPDATE_KEYFILE);
 
136
  if (info->invalidator != 0)
 
137
  {
 
138
    (*info->invalidator)(info->filename);
 
139
    info->invalidator=0;
 
140
  }
133
141
 
134
142
  /*
135
143
    Update status of the table. We need to do so after each row write
139
147
    not critical to use outdated share->is_log_table value (2) locking
140
148
    mutex here for every write is too expensive.
141
149
  */
142
 
  if (share->is_log_table) // Log table do not exist in Drizzle
143
 
    assert(0);
 
150
  if (share->is_log_table)
 
151
    mi_update_status((void*) info);
144
152
 
145
153
  return(0);
146
154
 
147
155
err:
148
 
  save_errno=errno;
149
 
  if (errno == HA_ERR_FOUND_DUPP_KEY || errno == HA_ERR_RECORD_FILE_FULL ||
150
 
      errno == HA_ERR_NULL_IN_SPATIAL || errno == HA_ERR_OUT_OF_MEM)
 
156
  save_errno=my_errno;
 
157
  if (my_errno == HA_ERR_FOUND_DUPP_KEY || my_errno == HA_ERR_RECORD_FILE_FULL ||
 
158
      my_errno == HA_ERR_NULL_IN_SPATIAL || my_errno == HA_ERR_OUT_OF_MEM)
151
159
  {
152
160
    if (info->bulk_insert)
153
161
    {
160
168
    {
161
169
      if (mi_is_key_active(share->state.key_map, i))
162
170
      {
 
171
        bool local_lock_tree= (lock_tree &&
 
172
                                  !(info->bulk_insert &&
 
173
                                    is_tree_inited(&info->bulk_insert[i])));
 
174
        if (local_lock_tree)
 
175
          rw_wrlock(&share->key_root_lock[i]);
163
176
        {
164
177
          uint32_t key_length=_mi_make_key(info,i,buff,record,filepos);
165
178
          if (_mi_ck_delete(info,i,buff,key_length))
166
179
          {
 
180
            if (local_lock_tree)
 
181
              rw_unlock(&share->key_root_lock[i]);
167
182
            break;
168
183
          }
169
184
        }
 
185
        if (local_lock_tree)
 
186
          rw_unlock(&share->key_root_lock[i]);
170
187
      }
171
188
    }
172
189
  }
176
193
    mi_mark_crashed(info);
177
194
  }
178
195
  info->update= (HA_STATE_CHANGED | HA_STATE_WRITTEN | HA_STATE_ROW_CHANGED);
179
 
  errno=save_errno;
 
196
  my_errno=save_errno;
180
197
err2:
181
 
  save_errno=errno;
 
198
  save_errno=my_errno;
182
199
  _mi_writeinfo(info,WRITEINFO_UPDATE_KEYFILE);
183
 
  return(errno=save_errno);
 
200
  return(my_errno=save_errno);
184
201
} /* mi_write */
185
202
 
186
203
 
209
226
  uint32_t error;
210
227
  uint32_t comp_flag;
211
228
  MI_KEYDEF *keyinfo=info->s->keyinfo+keynr;
212
 
  internal::my_off_t  *root=&info->s->state.key_root[keynr];
 
229
  my_off_t  *root=&info->s->state.key_root[keynr];
213
230
 
214
231
  if (keyinfo->flag & HA_SORT_ALLOWS_SAME)
215
232
    comp_flag=SEARCH_BIGGER;                    /* Put after same key */
228
245
} /* _mi_ck_write_btree */
229
246
 
230
247
int _mi_ck_real_write_btree(MI_INFO *info, MI_KEYDEF *keyinfo,
231
 
    unsigned char *key, uint32_t key_length, internal::my_off_t *root, uint32_t comp_flag)
 
248
    unsigned char *key, uint32_t key_length, my_off_t *root, uint32_t comp_flag)
232
249
{
233
250
  int error;
234
251
  /* key_length parameter is used only if comp_flag is SEARCH_FIND */
235
252
  if (*root == HA_OFFSET_ERROR ||
236
253
      (error=w_search(info, keyinfo, comp_flag, key, key_length,
237
254
                      *root, (unsigned char *) 0, (unsigned char*) 0,
238
 
                      (internal::my_off_t) 0, 1)) > 0)
 
255
                      (my_off_t) 0, 1)) > 0)
239
256
    error=_mi_enlarge_root(info,keyinfo,key,root);
240
257
  return(error);
241
258
} /* _mi_ck_real_write_btree */
244
261
        /* Make a new root with key as only pointer */
245
262
 
246
263
int _mi_enlarge_root(MI_INFO *info, MI_KEYDEF *keyinfo, unsigned char *key,
247
 
                     internal::my_off_t *root)
 
264
                     my_off_t *root)
248
265
{
249
266
  uint32_t t_length,nod_flag;
250
267
  MI_KEY_PARAM s_temp;
272
289
        */
273
290
 
274
291
static int w_search(register MI_INFO *info, register MI_KEYDEF *keyinfo,
275
 
                    uint32_t comp_flag, unsigned char *key, uint32_t key_length, internal::my_off_t page,
 
292
                    uint32_t comp_flag, unsigned char *key, uint32_t key_length, my_off_t page,
276
293
                    unsigned char *father_buff, unsigned char *father_keypos,
277
 
                    internal::my_off_t father_page, bool insert_last)
 
294
                    my_off_t father_page, bool insert_last)
278
295
{
279
296
  int error,flag;
280
297
  uint32_t nod_flag, search_key_length;
281
298
  unsigned char *temp_buff,*keypos;
282
299
  unsigned char keybuff[MI_MAX_KEY_BUFF];
283
300
  bool was_last_key;
284
 
  internal::my_off_t next_page, dupp_key_pos;
 
301
  my_off_t next_page, dupp_key_pos;
285
302
 
286
303
  search_key_length= (comp_flag & SEARCH_FIND) ? key_length : USE_WHOLE_KEY;
287
 
  if (!(temp_buff= (unsigned char*) malloc(keyinfo->block_length+
288
 
                                           MI_MAX_KEY_BUFF*2)))
 
304
  if (!(temp_buff= (unsigned char*) my_alloca((uint) keyinfo->block_length+
 
305
                                      MI_MAX_KEY_BUFF*2)))
289
306
    return(-1);
290
307
  if (!_mi_fetch_keypage(info,keyinfo,page,DFLT_INIT_HITS,temp_buff,0))
291
308
    goto err;
305
322
 
306
323
    {
307
324
      info->dupp_key_pos= dupp_key_pos;
308
 
      free(temp_buff);
309
 
      errno=HA_ERR_FOUND_DUPP_KEY;
 
325
      my_afree((unsigned char*) temp_buff);
 
326
      my_errno=HA_ERR_FOUND_DUPP_KEY;
310
327
      return(-1);
311
328
    }
312
329
  }
324
341
    if (_mi_write_keypage(info,keyinfo,page,DFLT_INIT_HITS,temp_buff))
325
342
      goto err;
326
343
  }
327
 
  free(temp_buff);
 
344
  my_afree((unsigned char*) temp_buff);
328
345
  return(error);
329
346
err:
330
 
  free(temp_buff);
 
347
  my_afree((unsigned char*) temp_buff);
331
348
  return (-1);
332
349
} /* w_search */
333
350
 
359
376
 
360
377
int _mi_insert(register MI_INFO *info, register MI_KEYDEF *keyinfo,
361
378
               unsigned char *key, unsigned char *anc_buff, unsigned char *key_pos, unsigned char *key_buff,
362
 
               unsigned char *father_buff, unsigned char *father_key_pos, internal::my_off_t father_page,
 
379
               unsigned char *father_buff, unsigned char *father_key_pos, my_off_t father_page,
363
380
               bool insert_last)
364
381
{
365
382
  uint32_t a_length,nod_flag;
381
398
    if (t_length >= keyinfo->maxlength*2+MAX_POINTER_LENGTH)
382
399
    {
383
400
      mi_print_error(info->s, HA_ERR_CRASHED);
384
 
      errno=HA_ERR_CRASHED;
 
401
      my_errno=HA_ERR_CRASHED;
385
402
      return(-1);
386
403
    }
387
 
    internal::bmove_upp((unsigned char*) endpos+t_length,(unsigned char*) endpos,(uint) (endpos-key_pos));
 
404
    bmove_upp((unsigned char*) endpos+t_length,(unsigned char*) endpos,(uint) (endpos-key_pos));
388
405
  }
389
406
  else
390
407
  {
391
408
    if (-t_length >= keyinfo->maxlength*2+MAX_POINTER_LENGTH)
392
409
    {
393
410
      mi_print_error(info->s, HA_ERR_CRASHED);
394
 
      errno=HA_ERR_CRASHED;
 
411
      my_errno=HA_ERR_CRASHED;
395
412
      return(-1);
396
413
    }
397
 
    memmove(key_pos, key_pos - t_length, endpos - key_pos + t_length);
 
414
    memcpy(key_pos, key_pos - t_length, endpos - key_pos + t_length);
398
415
  }
399
416
  (*keyinfo->store_key)(keyinfo,key_pos,&s_temp);
400
417
  a_length+=t_length;
422
439
{
423
440
  uint32_t length,a_length,key_ref_length,t_length,nod_flag,key_length;
424
441
  unsigned char *key_pos,*pos, *after_key= NULL;
425
 
  internal::my_off_t new_pos;
 
442
  my_off_t new_pos;
426
443
  MI_KEY_PARAM s_temp;
427
444
 
428
445
  if (info->s->keyinfo+info->lastinx == keyinfo)
561
578
    if (!(length=(*keyinfo->get_key)(keyinfo,0,&page,key_buff)))
562
579
    {
563
580
      mi_print_error(keyinfo->share, HA_ERR_CRASHED);
564
 
      errno=HA_ERR_CRASHED;
 
581
      my_errno=HA_ERR_CRASHED;
565
582
      return(0);
566
583
    }
567
584
  }
576
593
 
577
594
static int _mi_balance_page(register MI_INFO *info, MI_KEYDEF *keyinfo,
578
595
                            unsigned char *key, unsigned char *curr_buff, unsigned char *father_buff,
579
 
                            unsigned char *father_key_pos, internal::my_off_t father_page)
 
596
                            unsigned char *father_key_pos, my_off_t father_page)
580
597
{
581
598
  bool right;
582
599
  uint32_t k_length,father_length,father_keylength,nod_flag,curr_keylength,
583
600
       right_length,left_length,new_right_length,new_left_length,extra_length,
584
601
       length,keys;
585
602
  unsigned char *pos,*buff,*extra_buff;
586
 
  internal::my_off_t next_page,new_pos;
 
603
  my_off_t next_page,new_pos;
587
604
  unsigned char tmp_part_key[MI_MAX_KEY_BUFF];
588
605
 
589
606
  k_length=keyinfo->keylength;
636
653
      memcpy(pos+k_length, buff+2, length);
637
654
      pos=buff+2+length;
638
655
      memcpy(father_key_pos, pos, k_length);
639
 
      memmove(buff+2, pos+k_length, new_right_length);
 
656
      memcpy(buff+2, pos+k_length, new_right_length);
640
657
    }
641
658
    else
642
659
    {                                           /* Move keys -> buff */
643
660
 
644
 
      internal::bmove_upp((unsigned char*) buff+new_right_length,(unsigned char*) buff+right_length,
 
661
      bmove_upp((unsigned char*) buff+new_right_length,(unsigned char*) buff+right_length,
645
662
                right_length-2);
646
663
      length=new_right_length-right_length-k_length;
647
664
      memcpy(buff+2+length,father_key_pos, k_length);
674
691
  /* Save new parting key */
675
692
  memcpy(tmp_part_key, pos-k_length,k_length);
676
693
  /* Make place for new keys */
677
 
  internal::bmove_upp((unsigned char*) buff+new_right_length,(unsigned char*) pos-k_length,
 
694
  bmove_upp((unsigned char*) buff+new_right_length,(unsigned char*) pos-k_length,
678
695
            right_length-extra_length-k_length-2);
679
696
  /* Copy keys from left page */
680
697
  pos= curr_buff+new_left_length;
749
766
  case free_init:
750
767
    if (param->info->s->concurrent_insert)
751
768
    {
 
769
      rw_wrlock(&param->info->s->key_root_lock[param->keynr]);
752
770
      param->info->s->keyinfo[param->keynr].version++;
753
771
    }
754
772
    return 0;
759
777
    return _mi_ck_write_btree(param->info,param->keynr,lastkey,
760
778
                              keylen - param->info->s->rec_reflength);
761
779
  case free_end:
 
780
    if (param->info->s->concurrent_insert)
 
781
      rw_unlock(&param->info->s->key_root_lock[param->keynr]);
762
782
    return 0;
763
783
  }
764
784
  return -1;
798
818
    cache_size/=total_keylength*16;
799
819
 
800
820
  info->bulk_insert=(TREE *)
801
 
    malloc((sizeof(TREE)*share->base.keys+
802
 
           sizeof(bulk_insert_param)*num_keys));
 
821
    my_malloc((sizeof(TREE)*share->base.keys+
 
822
               sizeof(bulk_insert_param)*num_keys),MYF(0));
803
823
 
804
824
  if (!info->bulk_insert)
805
825
    return(HA_ERR_OUT_OF_MEM);
815
835
      init_tree(&info->bulk_insert[i],
816
836
                cache_size * key[i].maxlength,
817
837
                cache_size * key[i].maxlength, 0,
818
 
                (qsort_cmp2)keys_compare, false,
 
838
                (qsort_cmp2)keys_compare, 0,
819
839
                (tree_element_free) keys_free, (void *)params++);
820
840
    }
821
841
    else