~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to storage/heap/hp_write.c

  • Committer: Monty Taylor
  • Date: 2008-11-16 06:29:53 UTC
  • mto: (584.1.9 devel)
  • mto: This revision was merged to the branch mainline in revision 589.
  • Revision ID: monty@inaugust.com-20081116062953-ivdltjmfe009b5fr
Moved stuff into item/

Show diffs side-by-side

added added

removed removed

Lines of Context:
15
15
 
16
16
/* Write a record to heap-databas */
17
17
 
18
 
#include "heap_priv.h"
 
18
#include "heapdef.h"
19
19
#ifdef __WIN__
20
20
#include <fcntl.h>
21
21
#endif
25
25
#define HIGHFIND 4
26
26
#define HIGHUSED 8
27
27
 
28
 
using namespace drizzled;
29
 
 
30
28
static HASH_INFO *hp_find_free_hash(HP_SHARE *info, HP_BLOCK *block,
31
29
                                     uint32_t records);
32
30
 
34
32
{
35
33
  HP_KEYDEF *keydef, *end;
36
34
  unsigned char *pos;
37
 
  HP_SHARE *share=info->getShare();
 
35
  HP_SHARE *share=info->s;
 
36
  uint32_t rec_length, chunk_count;
38
37
 
39
38
  if ((share->records >= share->max_records && share->max_records) ||
40
39
    (share->recordspace.total_data_length + share->index_length >= share->max_table_size))
41
40
  {
42
 
    return(errno=HA_ERR_RECORD_FILE_FULL);
 
41
    return(my_errno=HA_ERR_RECORD_FILE_FULL);
43
42
  }
44
43
 
45
 
  if (!(pos=hp_allocate_chunkset(&share->recordspace, 1)))
46
 
    return(errno);
 
44
  rec_length = hp_get_encoded_data_length(share, record, &chunk_count);
 
45
 
 
46
  if (!(pos=hp_allocate_chunkset(&share->recordspace, chunk_count)))
 
47
    return(my_errno);
47
48
  share->changed=1;
48
49
 
49
50
  for (keydef = share->keydef, end = keydef + share->keys; keydef < end;
50
51
       keydef++)
51
52
  {
52
 
    if (hp_write_key(info, keydef, record, pos))
 
53
    if ((*keydef->write_key)(info, keydef, record, pos))
53
54
      goto err;
54
55
  }
55
56
 
67
68
 
68
69
err:
69
70
  info->errkey= keydef - share->keydef;
 
71
  /*
 
72
    We don't need to delete non-inserted key from rb-tree.  Also, if
 
73
    we got ENOMEM, the key wasn't inserted, so don't try to delete it
 
74
    either.  Otherwise for HASH index on HA_ERR_FOUND_DUPP_KEY the key
 
75
    was inserted and we have to delete it.
 
76
  */
 
77
  if (keydef->algorithm == HA_KEY_ALG_BTREE || my_errno == ENOMEM)
 
78
  {
 
79
    keydef--;
 
80
  }
70
81
  while (keydef >= share->keydef)
71
82
  {
72
 
    if (hp_delete_key(info, keydef, record, pos, 0))
 
83
    if ((*keydef->delete_key)(info, keydef, record, pos, 0))
73
84
      break;
74
85
    keydef--;
75
 
  }
 
86
  } 
76
87
 
77
88
  hp_free_chunks(&share->recordspace, pos);
78
89
 
79
 
  return(errno);
 
90
  return(my_errno);
80
91
} /* heap_write */
81
92
 
 
93
/* 
 
94
  Write a key to rb_tree-index 
 
95
*/
 
96
 
 
97
int hp_rb_write_key(HP_INFO *info, HP_KEYDEF *keyinfo, const unsigned char *record, 
 
98
                    unsigned char *recpos)
 
99
{
 
100
  heap_rb_param custom_arg;
 
101
  uint32_t old_allocated;
 
102
 
 
103
  custom_arg.keyseg= keyinfo->seg;
 
104
  custom_arg.key_length= hp_rb_make_key(keyinfo, info->recbuf, record, recpos);
 
105
  if (keyinfo->flag & HA_NOSAME)
 
106
  {
 
107
    custom_arg.search_flag= SEARCH_FIND | SEARCH_UPDATE;
 
108
    keyinfo->rb_tree.flag= TREE_NO_DUPS;
 
109
  }
 
110
  else
 
111
  {
 
112
    custom_arg.search_flag= SEARCH_SAME;
 
113
    keyinfo->rb_tree.flag= 0;
 
114
  }
 
115
  old_allocated= keyinfo->rb_tree.allocated;
 
116
  if (!tree_insert(&keyinfo->rb_tree, (void*)info->recbuf,
 
117
                   custom_arg.key_length, &custom_arg))
 
118
  {
 
119
    my_errno= HA_ERR_FOUND_DUPP_KEY;
 
120
    return 1;
 
121
  }
 
122
  info->s->index_length+= (keyinfo->rb_tree.allocated-old_allocated);
 
123
  return 0;
 
124
}
 
125
 
82
126
/*
83
127
  Write a hash-key to the hash-index
84
128
  SYNOPSIS
85
129
    info     Heap table info
86
130
    keyinfo  Key info
87
131
    record   Table record to added
88
 
    recpos   Memory buffer where the table record will be stored if added
 
132
    recpos   Memory buffer where the table record will be stored if added 
89
133
             successfully
90
134
  NOTE
91
 
    Hash index uses HP_BLOCK structure as a 'growable array' of HASH_INFO
 
135
    Hash index uses HP_BLOCK structure as a 'growable array' of HASH_INFO 
92
136
    structs. Array size == number of entries in hash index.
93
137
    hp_mask(hp_rec_hashnr()) maps hash entries values to hash array positions.
94
138
    If there are several hash entries with the same hash array position P,
95
 
    they are connected in a linked list via HASH_INFO::next_key. The first
96
 
    list element is located at position P, next elements are located at
 
139
    they are connected in a linked list via HASH_INFO::next_key. The first 
 
140
    list element is located at position P, next elements are located at 
97
141
    positions for which there is no record that should be located at that
98
142
    position. The order of elements in the list is arbitrary.
99
143
 
100
144
  RETURN
101
145
    0  - OK
102
146
    -1 - Out of memory
103
 
    HA_ERR_FOUND_DUPP_KEY - Duplicate record on unique key. The record was
 
147
    HA_ERR_FOUND_DUPP_KEY - Duplicate record on unique key. The record was 
104
148
    still added and the caller must call hp_delete_key for it.
105
149
*/
106
150
 
107
151
int hp_write_key(HP_INFO *info, HP_KEYDEF *keyinfo,
108
152
                 const unsigned char *record, unsigned char *recpos)
109
153
{
110
 
  HP_SHARE *share = info->getShare();
 
154
  HP_SHARE *share = info->s;
111
155
  int flag;
112
156
  uint32_t halfbuff,hashnr,first_index;
113
157
  unsigned char *ptr_to_rec= NULL,*ptr_to_rec2= NULL;
118
162
    return(-1);                         /* No more memory */
119
163
  halfbuff= (long) share->blength >> 1;
120
164
  pos= hp_find_hash(&keyinfo->block,(first_index=share->records-halfbuff));
121
 
 
 
165
  
122
166
  /*
123
167
    We're about to add one more hash array position, with hash_mask=#records.
124
 
    The number of hash positions will change and some entries might need to
125
 
    be relocated to the newly added position. Those entries are currently
126
 
    members of the list that starts at #first_index position (this is
 
168
    The number of hash positions will change and some entries might need to 
 
169
    be relocated to the newly added position. Those entries are currently 
 
170
    members of the list that starts at #first_index position (this is 
127
171
    guaranteed by properties of hp_mask(hp_rec_hashnr(X)) mapping function)
128
172
    At #first_index position currently there may be either:
129
173
    a) An entry with hashnr != first_index. We don't need to move it.
130
174
    or
131
175
    b) A list of items with hash_mask=first_index. The list contains entries
132
176
       of 2 types:
133
 
       1) entries that should be relocated to the list that starts at new
 
177
       1) entries that should be relocated to the list that starts at new 
134
178
          position we're adding ('uppper' list)
135
 
       2) entries that should be left in the list starting at #first_index
 
179
       2) entries that should be left in the list starting at #first_index 
136
180
          position ('lower' list)
137
181
  */
138
182
  if (pos != empty)                             /* If some records */
142
186
      hashnr = hp_rec_hashnr(keyinfo, pos->ptr_to_rec);
143
187
      if (flag == 0)
144
188
      {
145
 
        /*
146
 
          First loop, bail out if we're dealing with case a) from above
 
189
        /* 
 
190
          First loop, bail out if we're dealing with case a) from above 
147
191
          comment
148
192
        */
149
193
        if (hp_mask(hashnr, share->blength, share->records) != first_index)
161
205
        ptr_to_rec2 - same for upper list.
162
206
      */
163
207
      if (!(hashnr & halfbuff))
164
 
      {
 
208
      {                                         
165
209
        /* Key should be put into 'lower' list */
166
210
        if (!(flag & LOWFIND))
167
211
        {
177
221
          else
178
222
          {
179
223
            /*
180
 
              We can only get here at first iteration: key is at 'lower'
 
224
              We can only get here at first iteration: key is at 'lower' 
181
225
              position pos and should be left here.
182
226
            */
183
227
            flag=LOWFIND | LOWUSED;
225
269
      }
226
270
    }
227
271
    while ((pos=pos->next_key));
228
 
 
 
272
    
229
273
    if ((flag & (LOWFIND | HIGHFIND)) == (LOWFIND | HIGHFIND))
230
274
    {
231
275
      /*
286
330
      {
287
331
        if (! hp_rec_key_cmp(keyinfo, record, pos->ptr_to_rec, 1))
288
332
        {
289
 
          return(errno=HA_ERR_FOUND_DUPP_KEY);
 
333
          return(my_errno=HA_ERR_FOUND_DUPP_KEY);
290
334
        }
291
335
      } while ((pos=pos->next_key));
292
336
    }