~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to plugin/memory/hp_write.cc

  • Committer: Brian Aker
  • Date: 2010-12-18 18:24:57 UTC
  • mfrom: (1999.6.3 trunk)
  • Revision ID: brian@tangent.org-20101218182457-yi1wd0so2hml1k1w
Merge in Lee's copyright header fix

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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
 
14
   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA */
15
15
 
16
16
/* Write a record to heap-databas */
17
17
 
18
 
#include "heapdef.h"
 
18
#include "heap_priv.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
 
28
30
static HASH_INFO *hp_find_free_hash(HP_SHARE *info, HP_BLOCK *block,
29
31
                                     uint32_t records);
30
32
 
31
 
int heap_write(HP_INFO *info, const uchar *record)
 
33
int heap_write(HP_INFO *info, const unsigned char *record)
32
34
{
33
35
  HP_KEYDEF *keydef, *end;
34
 
  uchar *pos;
35
 
  HP_SHARE *share=info->s;
36
 
  uint rec_length, chunk_count;
 
36
  unsigned char *pos;
 
37
  HP_SHARE *share=info->getShare();
37
38
 
38
39
  if ((share->records >= share->max_records && share->max_records) ||
39
40
    (share->recordspace.total_data_length + share->index_length >= share->max_table_size))
40
41
  {
41
 
    return(my_errno=HA_ERR_RECORD_FILE_FULL);
 
42
    return(errno=HA_ERR_RECORD_FILE_FULL);
42
43
  }
43
44
 
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);
 
45
  if (!(pos=hp_allocate_chunkset(&share->recordspace, 1)))
 
46
    return(errno);
48
47
  share->changed=1;
49
48
 
50
49
  for (keydef = share->keydef, end = keydef + share->keys; keydef < end;
51
50
       keydef++)
52
51
  {
53
 
    if ((*keydef->write_key)(info, keydef, record, pos))
 
52
    if (hp_write_key(info, keydef, record, pos))
54
53
      goto err;
55
54
  }
56
55
 
68
67
 
69
68
err:
70
69
  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
 
  }
81
70
  while (keydef >= share->keydef)
82
71
  {
83
 
    if ((*keydef->delete_key)(info, keydef, record, pos, 0))
 
72
    if (hp_delete_key(info, keydef, record, pos, 0))
84
73
      break;
85
74
    keydef--;
86
 
  } 
 
75
  }
87
76
 
88
77
  hp_free_chunks(&share->recordspace, pos);
89
78
 
90
 
  return(my_errno);
 
79
  return(errno);
91
80
} /* heap_write */
92
81
 
93
 
/* 
94
 
  Write a key to rb_tree-index 
95
 
*/
96
 
 
97
 
int hp_rb_write_key(HP_INFO *info, HP_KEYDEF *keyinfo, const uchar *record, 
98
 
                    uchar *recpos)
99
 
{
100
 
  heap_rb_param custom_arg;
101
 
  uint 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
 
 
126
82
/*
127
83
  Write a hash-key to the hash-index
128
84
  SYNOPSIS
129
85
    info     Heap table info
130
86
    keyinfo  Key info
131
87
    record   Table record to added
132
 
    recpos   Memory buffer where the table record will be stored if added 
 
88
    recpos   Memory buffer where the table record will be stored if added
133
89
             successfully
134
90
  NOTE
135
 
    Hash index uses HP_BLOCK structure as a 'growable array' of HASH_INFO 
 
91
    Hash index uses HP_BLOCK structure as a 'growable array' of HASH_INFO
136
92
    structs. Array size == number of entries in hash index.
137
93
    hp_mask(hp_rec_hashnr()) maps hash entries values to hash array positions.
138
94
    If there are several hash entries with the same hash array position P,
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 
 
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
141
97
    positions for which there is no record that should be located at that
142
98
    position. The order of elements in the list is arbitrary.
143
99
 
144
100
  RETURN
145
101
    0  - OK
146
102
    -1 - Out of memory
147
 
    HA_ERR_FOUND_DUPP_KEY - Duplicate record on unique key. The record was 
 
103
    HA_ERR_FOUND_DUPP_KEY - Duplicate record on unique key. The record was
148
104
    still added and the caller must call hp_delete_key for it.
149
105
*/
150
106
 
151
107
int hp_write_key(HP_INFO *info, HP_KEYDEF *keyinfo,
152
 
                 const uchar *record, uchar *recpos)
 
108
                 const unsigned char *record, unsigned char *recpos)
153
109
{
154
 
  HP_SHARE *share = info->s;
 
110
  HP_SHARE *share = info->getShare();
155
111
  int flag;
156
112
  uint32_t halfbuff,hashnr,first_index;
157
 
  uchar *ptr_to_rec= NULL,*ptr_to_rec2= NULL;
 
113
  unsigned char *ptr_to_rec= NULL,*ptr_to_rec2= NULL;
158
114
  HASH_INFO *empty, *gpos= NULL, *gpos2= NULL, *pos;
159
115
 
160
116
  flag=0;
162
118
    return(-1);                         /* No more memory */
163
119
  halfbuff= (long) share->blength >> 1;
164
120
  pos= hp_find_hash(&keyinfo->block,(first_index=share->records-halfbuff));
165
 
  
 
121
 
166
122
  /*
167
123
    We're about to add one more hash array position, with hash_mask=#records.
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 
 
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
171
127
    guaranteed by properties of hp_mask(hp_rec_hashnr(X)) mapping function)
172
128
    At #first_index position currently there may be either:
173
129
    a) An entry with hashnr != first_index. We don't need to move it.
174
130
    or
175
131
    b) A list of items with hash_mask=first_index. The list contains entries
176
132
       of 2 types:
177
 
       1) entries that should be relocated to the list that starts at new 
 
133
       1) entries that should be relocated to the list that starts at new
178
134
          position we're adding ('uppper' list)
179
 
       2) entries that should be left in the list starting at #first_index 
 
135
       2) entries that should be left in the list starting at #first_index
180
136
          position ('lower' list)
181
137
  */
182
138
  if (pos != empty)                             /* If some records */
186
142
      hashnr = hp_rec_hashnr(keyinfo, pos->ptr_to_rec);
187
143
      if (flag == 0)
188
144
      {
189
 
        /* 
190
 
          First loop, bail out if we're dealing with case a) from above 
 
145
        /*
 
146
          First loop, bail out if we're dealing with case a) from above
191
147
          comment
192
148
        */
193
149
        if (hp_mask(hashnr, share->blength, share->records) != first_index)
205
161
        ptr_to_rec2 - same for upper list.
206
162
      */
207
163
      if (!(hashnr & halfbuff))
208
 
      {                                         
 
164
      {
209
165
        /* Key should be put into 'lower' list */
210
166
        if (!(flag & LOWFIND))
211
167
        {
221
177
          else
222
178
          {
223
179
            /*
224
 
              We can only get here at first iteration: key is at 'lower' 
 
180
              We can only get here at first iteration: key is at 'lower'
225
181
              position pos and should be left here.
226
182
            */
227
183
            flag=LOWFIND | LOWUSED;
269
225
      }
270
226
    }
271
227
    while ((pos=pos->next_key));
272
 
    
 
228
 
273
229
    if ((flag & (LOWFIND | HIGHFIND)) == (LOWFIND | HIGHFIND))
274
230
    {
275
231
      /*
330
286
      {
331
287
        if (! hp_rec_key_cmp(keyinfo, record, pos->ptr_to_rec, 1))
332
288
        {
333
 
          return(my_errno=HA_ERR_FOUND_DUPP_KEY);
 
289
          return(errno=HA_ERR_FOUND_DUPP_KEY);
334
290
        }
335
291
      } while ((pos=pos->next_key));
336
292
    }
343
299
static HASH_INFO *hp_find_free_hash(HP_SHARE *info,
344
300
                                     HP_BLOCK *block, uint32_t records)
345
301
{
346
 
  uint block_pos;
 
302
  uint32_t block_pos;
347
303
  size_t length;
348
304
 
349
305
  if (records < block->last_allocated)
355
311
    info->index_length+=length;
356
312
  }
357
313
  block->last_allocated=records+1;
358
 
  return((HASH_INFO*) ((uchar*) block->level_info[0].last_blocks+
 
314
  return((HASH_INFO*) ((unsigned char*) block->level_info[0].last_blocks+
359
315
                       block_pos*block->recbuffer));
360
316
}