~drizzle-trunk/drizzle/development

1 by brian
clean slate
1
/* Copyright (C) 2000-2006 MySQL AB
2
3
   This program is free software; you can redistribute it and/or modify
4
   it under the terms of the GNU General Public License as published by
5
   the Free Software Foundation; version 2 of the License.
6
7
   This program is distributed in the hope that it will be useful,
8
   but WITHOUT ANY WARRANTY; without even the implied warranty of
9
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10
   GNU General Public License for more details.
11
12
   You should have received a copy of the GNU General Public License
13
   along with this program; if not, write to the Free Software
1802.10.2 by Monty Taylor
Update all of the copyright headers to include the correct address.
14
   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA */
1 by brian
clean slate
15
16
/*
17
  Functions to handle space-packed-records and blobs
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
18
1 by brian
clean slate
19
  A row may be stored in one or more linked blocks.
20
  The block size is between MI_MIN_BLOCK_LENGTH and MI_MAX_BLOCK_LENGTH.
21
  Each block is aligned on MI_DYN_ALIGN_SIZE.
22
  The reson for the max block size is to not have too many different types
23
  of blocks.  For the differnet block types, look at _mi_get_block_info()
24
*/
25
1130.3.28 by Monty Taylor
Moved heapdef.h and myisamdef.h to *_priv.h for easier filtering for include guard check.
26
#include "myisam_priv.h"
1 by brian
clean slate
27
470 by Monty Taylor
Remove madvise decl.
28
#ifdef HAVE_SYS_TYPES
29
#include <sys/types.h>
30
#endif
31
#ifdef HAVE_SYS_MMAN_H
32
#include <sys/mman.h>
33
#endif
492.1.7 by Monty Taylor
Moved test() to its own file.
34
#include <drizzled/util/test.h>
2173.2.1 by Monty Taylor
Fixes incorrect usage of include
35
#include <drizzled/error.h>
470 by Monty Taylor
Remove madvise decl.
36
1241.9.1 by Monty Taylor
Removed global.h. Fixed all the headers.
37
#include <cassert>
1067.4.8 by Nathan Williams
Converted all usages of cmin/cmax in plugin directory to std::min/max.
38
#include <algorithm>
39
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
40
using namespace drizzled;
1067.4.8 by Nathan Williams
Converted all usages of cmin/cmax in plugin directory to std::min/max.
41
using namespace std;
42
1 by brian
clean slate
43
/* Enough for comparing if number is zero */
44
static char zero_string[]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
45
481 by Brian Aker
Remove all of uchar.
46
static int write_dynamic_record(MI_INFO *info,const unsigned char *record,
1 by brian
clean slate
47
				ulong reclength);
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
48
static int _mi_find_writepos(MI_INFO *info,ulong reclength,internal::my_off_t *filepos,
1 by brian
clean slate
49
			     ulong *length);
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
50
static int update_dynamic_record(MI_INFO *info,internal::my_off_t filepos,unsigned char *record,
1 by brian
clean slate
51
				 ulong reclength);
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
52
static int delete_dynamic_record(MI_INFO *info,internal::my_off_t filepos,
482 by Brian Aker
Remove uint.
53
				 uint32_t second_read);
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
54
static int _mi_cmp_buffer(int file, const unsigned char *buff, internal::my_off_t filepos,
482 by Brian Aker
Remove uint.
55
			  uint32_t length);
1 by brian
clean slate
56
57
	/* Interface function from MI_INFO */
58
59
60
/*
61
  Create mmaped area for MyISAM handler
62
63
  SYNOPSIS
64
    mi_dynmap_file()
65
    info		MyISAM handler
66
67
  RETURN
68
    0  ok
69
    1  error.
70
*/
71
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
72
bool mi_dynmap_file(MI_INFO *info, internal::my_off_t size)
1 by brian
clean slate
73
{
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
74
  if (size > (internal::my_off_t) (~((size_t) 0)) - MEMMAP_EXTRA_MARGIN)
1 by brian
clean slate
75
  {
51.1.98 by Jay Pipes
Removed/replaced DBUG symbols and TRUE/FALSE
76
    return(1);
1 by brian
clean slate
77
  }
78
  /*
79
    I wonder if it is good to use MAP_NORESERVE. From the Linux man page:
80
    MAP_NORESERVE
81
      Do not reserve swap space for this mapping. When swap space is
82
      reserved, one has the guarantee that it is possible to modify the
83
      mapping. When swap space is not reserved one might get SIGSEGV
84
      upon a write if no physical memory is available.
85
  */
481 by Brian Aker
Remove all of uchar.
86
  info->s->file_map= (unsigned char*)
1192.3.43 by Monty Taylor
Removed many, many checks for functions that do not need to be checked.
87
                  mmap(NULL, (size_t)(size + MEMMAP_EXTRA_MARGIN),
88
                       info->s->mode==O_RDONLY ? PROT_READ :
89
                       PROT_READ | PROT_WRITE,
90
                       MAP_SHARED | MAP_NORESERVE,
91
                       info->dfile, 0L);
481 by Brian Aker
Remove all of uchar.
92
  if (info->s->file_map == (unsigned char*) MAP_FAILED)
1 by brian
clean slate
93
  {
94
    info->s->file_map= NULL;
51.1.98 by Jay Pipes
Removed/replaced DBUG symbols and TRUE/FALSE
95
    return(1);
1 by brian
clean slate
96
  }
492.3.25 by Lee
Changes to get drizzle building on Solaris 10 (SPARC)
97
/* per krow we should look at removing the following code */
1192.3.43 by Monty Taylor
Removed many, many checks for functions that do not need to be checked.
98
#if !defined(TARGET_OS_SOLARIS)
1 by brian
clean slate
99
  madvise((char*) info->s->file_map, size, MADV_RANDOM);
100
#endif
101
  info->s->mmaped_length= size;
51.1.98 by Jay Pipes
Removed/replaced DBUG symbols and TRUE/FALSE
102
  return(0);
1 by brian
clean slate
103
}
104
105
106
/*
107
  Resize mmaped area for MyISAM handler
108
109
  SYNOPSIS
110
    mi_remap_file()
111
    info		MyISAM handler
112
113
  RETURN
114
*/
115
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
116
void mi_remap_file(MI_INFO *info, internal::my_off_t size)
1 by brian
clean slate
117
{
118
  if (info->s->file_map)
119
  {
1192.3.43 by Monty Taylor
Removed many, many checks for functions that do not need to be checked.
120
    munmap((char*) info->s->file_map,
121
           (size_t) info->s->mmaped_length + MEMMAP_EXTRA_MARGIN);
1 by brian
clean slate
122
    mi_dynmap_file(info, size);
123
  }
124
}
125
126
127
/*
128
  Read bytes from MySAM handler, using mmap or pread
129
130
  SYNOPSIS
131
    mi_mmap_pread()
132
    info		MyISAM handler
133
    Buffer              Input buffer
134
    Count               Count of bytes for read
135
    offset              Start position
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
136
    MyFlags
1 by brian
clean slate
137
138
  RETURN
139
    0  ok
140
*/
141
481 by Brian Aker
Remove all of uchar.
142
size_t mi_mmap_pread(MI_INFO *info, unsigned char *Buffer,
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
143
                    size_t Count, internal::my_off_t offset, myf MyFlags)
1 by brian
clean slate
144
{
145
  /*
146
    The following test may fail in the following cases:
147
    - We failed to remap a memory area (fragmented memory?)
148
    - This thread has done some writes, but not yet extended the
149
    memory mapped area.
150
  */
151
152
  if (info->s->mmaped_length >= offset + Count)
153
  {
154
    memcpy(Buffer, info->s->file_map + offset, Count);
155
    return 0;
156
  }
157
  else
158
  {
159
    return my_pread(info->dfile, Buffer, Count, offset, MyFlags);
160
  }
161
}
162
163
164
        /* wrapper for my_pread in case if mmap isn't used */
165
481 by Brian Aker
Remove all of uchar.
166
size_t mi_nommap_pread(MI_INFO *info, unsigned char *Buffer,
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
167
                       size_t Count, internal::my_off_t offset, myf MyFlags)
1 by brian
clean slate
168
{
169
  return my_pread(info->dfile, Buffer, Count, offset, MyFlags);
170
}
171
172
173
/*
174
  Write bytes to MySAM handler, using mmap or pwrite
175
176
  SYNOPSIS
177
    mi_mmap_pwrite()
178
    info		MyISAM handler
179
    Buffer              Output buffer
180
    Count               Count of bytes for write
181
    offset              Start position
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
182
    MyFlags
1 by brian
clean slate
183
184
  RETURN
185
    0  ok
186
    !=0  error.  In this case return error from pwrite
187
*/
188
481 by Brian Aker
Remove all of uchar.
189
size_t mi_mmap_pwrite(MI_INFO *info, const unsigned char *Buffer,
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
190
                      size_t Count, internal::my_off_t offset, myf MyFlags)
1 by brian
clean slate
191
{
192
193
  /*
194
    The following test may fail in the following cases:
195
    - We failed to remap a memory area (fragmented memory?)
196
    - This thread has done some writes, but not yet extended the
197
    memory mapped area.
198
  */
199
200
  if (info->s->mmaped_length >= offset + Count)
201
  {
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
202
    memcpy(info->s->file_map + offset, Buffer, Count);
1 by brian
clean slate
203
    return 0;
204
  }
205
  else
206
  {
207
    info->s->nonmmaped_inserts++;
208
    return my_pwrite(info->dfile, Buffer, Count, offset, MyFlags);
209
  }
210
211
}
212
213
214
        /* wrapper for my_pwrite in case if mmap isn't used */
215
481 by Brian Aker
Remove all of uchar.
216
size_t mi_nommap_pwrite(MI_INFO *info, const unsigned char *Buffer,
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
217
                      size_t Count, internal::my_off_t offset, myf MyFlags)
1 by brian
clean slate
218
{
219
  return my_pwrite(info->dfile, Buffer, Count, offset, MyFlags);
220
}
221
222
481 by Brian Aker
Remove all of uchar.
223
int _mi_write_dynamic_record(MI_INFO *info, const unsigned char *record)
1 by brian
clean slate
224
{
225
  ulong reclength=_mi_rec_pack(info,info->rec_buff,record);
226
  return (write_dynamic_record(info,info->rec_buff,reclength));
227
}
228
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
229
int _mi_update_dynamic_record(MI_INFO *info, internal::my_off_t pos, const unsigned char *record)
1 by brian
clean slate
230
{
482 by Brian Aker
Remove uint.
231
  uint32_t length=_mi_rec_pack(info,info->rec_buff,record);
1 by brian
clean slate
232
  return (update_dynamic_record(info,pos,info->rec_buff,length));
233
}
234
481 by Brian Aker
Remove all of uchar.
235
int _mi_write_blob_record(MI_INFO *info, const unsigned char *record)
1 by brian
clean slate
236
{
481 by Brian Aker
Remove all of uchar.
237
  unsigned char *rec_buff;
1 by brian
clean slate
238
  int error;
239
  ulong reclength,reclength2,extra;
240
241
  extra= (ALIGN_SIZE(MI_MAX_DYN_BLOCK_HEADER)+MI_SPLIT_LENGTH+
242
	  MI_DYN_DELETE_BLOCK_HEADER+1);
243
  reclength= (info->s->base.pack_reclength +
244
	      _my_calc_total_blob_length(info,record)+ extra);
245
#ifdef NOT_USED					/* We now support big rows */
246
  if (reclength > MI_DYN_MAX_ROW_LENGTH)
247
  {
1241.9.57 by Monty Taylor
Oy. Bigger change than I normally like - but this stuff is all intertwined.
248
    errno=HA_ERR_TO_BIG_ROW;
1 by brian
clean slate
249
    return -1;
250
  }
251
#endif
656.1.1 by Monty Taylor
OOOh doggie. Got rid of my_alloca.
252
  if (!(rec_buff=(unsigned char*) malloc(reclength)))
1 by brian
clean slate
253
  {
1241.9.57 by Monty Taylor
Oy. Bigger change than I normally like - but this stuff is all intertwined.
254
    errno= HA_ERR_OUT_OF_MEM;
1 by brian
clean slate
255
    return(-1);
256
  }
257
  reclength2= _mi_rec_pack(info,rec_buff+ALIGN_SIZE(MI_MAX_DYN_BLOCK_HEADER),
258
			   record);
51.1.98 by Jay Pipes
Removed/replaced DBUG symbols and TRUE/FALSE
259
  assert(reclength2 <= reclength);
1 by brian
clean slate
260
  error=write_dynamic_record(info,rec_buff+ALIGN_SIZE(MI_MAX_DYN_BLOCK_HEADER),
261
			     reclength2);
656.1.1 by Monty Taylor
OOOh doggie. Got rid of my_alloca.
262
  free(rec_buff);
1 by brian
clean slate
263
  return(error);
264
}
265
266
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
267
int _mi_update_blob_record(MI_INFO *info, internal::my_off_t pos, const unsigned char *record)
1 by brian
clean slate
268
{
481 by Brian Aker
Remove all of uchar.
269
  unsigned char *rec_buff;
1 by brian
clean slate
270
  int error;
271
  ulong reclength,extra;
272
273
  extra= (ALIGN_SIZE(MI_MAX_DYN_BLOCK_HEADER)+MI_SPLIT_LENGTH+
274
	  MI_DYN_DELETE_BLOCK_HEADER);
275
  reclength= (info->s->base.pack_reclength+
276
	      _my_calc_total_blob_length(info,record)+ extra);
277
#ifdef NOT_USED					/* We now support big rows */
278
  if (reclength > MI_DYN_MAX_ROW_LENGTH)
279
  {
1241.9.57 by Monty Taylor
Oy. Bigger change than I normally like - but this stuff is all intertwined.
280
    errno=HA_ERR_TO_BIG_ROW;
1 by brian
clean slate
281
    return -1;
282
  }
283
#endif
656.1.1 by Monty Taylor
OOOh doggie. Got rid of my_alloca.
284
  if (!(rec_buff=(unsigned char*) malloc(reclength)))
1 by brian
clean slate
285
  {
1241.9.57 by Monty Taylor
Oy. Bigger change than I normally like - but this stuff is all intertwined.
286
    errno= HA_ERR_OUT_OF_MEM;
1 by brian
clean slate
287
    return(-1);
288
  }
289
  reclength=_mi_rec_pack(info,rec_buff+ALIGN_SIZE(MI_MAX_DYN_BLOCK_HEADER),
290
			 record);
291
  error=update_dynamic_record(info,pos,
292
			      rec_buff+ALIGN_SIZE(MI_MAX_DYN_BLOCK_HEADER),
293
			      reclength);
656.1.1 by Monty Taylor
OOOh doggie. Got rid of my_alloca.
294
  free(rec_buff);
1 by brian
clean slate
295
  return(error);
296
}
297
298
299
int _mi_delete_dynamic_record(MI_INFO *info)
300
{
301
  return delete_dynamic_record(info,info->lastpos,0);
302
}
303
304
305
	/* Write record to data-file */
306
481 by Brian Aker
Remove all of uchar.
307
static int write_dynamic_record(MI_INFO *info, const unsigned char *record,
1 by brian
clean slate
308
				ulong reclength)
309
{
310
  int flag;
311
  ulong length;
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
312
  internal::my_off_t filepos;
1 by brian
clean slate
313
314
  flag=0;
315
316
  /*
317
    Check if we have enough room for the new record.
318
    First we do simplified check to make usual case faster.
319
    Then we do more precise check for the space left.
320
    Though it still is not absolutely precise, as
321
    we always use MI_MAX_DYN_BLOCK_HEADER while it can be
322
    less in the most of the cases.
323
  */
324
325
  if (unlikely(info->s->base.max_data_file_length -
326
               info->state->data_file_length <
327
               reclength + MI_MAX_DYN_BLOCK_HEADER))
328
  {
329
    if (info->s->base.max_data_file_length - info->state->data_file_length +
330
        info->state->empty - info->state->del * MI_MAX_DYN_BLOCK_HEADER <
331
        reclength + MI_MAX_DYN_BLOCK_HEADER)
332
    {
1241.9.57 by Monty Taylor
Oy. Bigger change than I normally like - but this stuff is all intertwined.
333
      errno=HA_ERR_RECORD_FILE_FULL;
51.1.98 by Jay Pipes
Removed/replaced DBUG symbols and TRUE/FALSE
334
      return(1);
1 by brian
clean slate
335
    }
336
  }
337
338
  do
339
  {
340
    if (_mi_find_writepos(info,reclength,&filepos,&length))
341
      goto err;
342
    if (_mi_write_part_record(info,filepos,length,
343
                              (info->append_insert_at_end ?
344
                               HA_OFFSET_ERROR : info->s->state.dellink),
481 by Brian Aker
Remove all of uchar.
345
			      (unsigned char**) &record,&reclength,&flag))
1 by brian
clean slate
346
      goto err;
347
  } while (reclength);
348
51.1.98 by Jay Pipes
Removed/replaced DBUG symbols and TRUE/FALSE
349
  return(0);
1 by brian
clean slate
350
err:
51.1.98 by Jay Pipes
Removed/replaced DBUG symbols and TRUE/FALSE
351
  return(1);
1 by brian
clean slate
352
}
353
354
355
	/* Get a block for data ; The given data-area must be used !! */
356
357
static int _mi_find_writepos(MI_INFO *info,
358
			     ulong reclength, /* record length */
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
359
			     internal::my_off_t *filepos, /* Return file pos */
1 by brian
clean slate
360
			     ulong *length)   /* length of block at filepos */
361
{
362
  MI_BLOCK_INFO block_info;
363
  ulong tmp;
364
365
  if (info->s->state.dellink != HA_OFFSET_ERROR &&
366
      !info->append_insert_at_end)
367
  {
368
    /* Deleted blocks exists;  Get last used block */
369
    *filepos=info->s->state.dellink;
370
    block_info.second_read=0;
371
    info->rec_cache.seek_not_done=1;
372
    if (!(_mi_get_block_info(&block_info,info->dfile,info->s->state.dellink) &
373
	   BLOCK_DELETED))
374
    {
1241.9.57 by Monty Taylor
Oy. Bigger change than I normally like - but this stuff is all intertwined.
375
      errno=HA_ERR_WRONG_IN_RECORD;
51.1.98 by Jay Pipes
Removed/replaced DBUG symbols and TRUE/FALSE
376
      return(-1);
1 by brian
clean slate
377
    }
378
    info->s->state.dellink=block_info.next_filepos;
379
    info->state->del--;
380
    info->state->empty-= block_info.block_len;
381
    *length= block_info.block_len;
382
  }
383
  else
384
  {
385
    /* No deleted blocks;  Allocate a new block */
386
    *filepos=info->state->data_file_length;
387
    if ((tmp=reclength+3 + test(reclength >= (65520-3))) <
388
	info->s->base.min_block_length)
389
      tmp= info->s->base.min_block_length;
390
    else
391
      tmp= ((tmp+MI_DYN_ALIGN_SIZE-1) &
392
	    (~ (ulong) (MI_DYN_ALIGN_SIZE-1)));
393
    if (info->state->data_file_length >
394
	(info->s->base.max_data_file_length - tmp))
395
    {
1241.9.57 by Monty Taylor
Oy. Bigger change than I normally like - but this stuff is all intertwined.
396
      errno=HA_ERR_RECORD_FILE_FULL;
51.1.98 by Jay Pipes
Removed/replaced DBUG symbols and TRUE/FALSE
397
      return(-1);
1 by brian
clean slate
398
    }
399
    if (tmp > MI_MAX_BLOCK_LENGTH)
400
      tmp=MI_MAX_BLOCK_LENGTH;
401
    *length= tmp;
402
    info->state->data_file_length+= tmp;
403
    info->s->state.split++;
404
    info->update|=HA_STATE_WRITE_AT_END;
405
  }
51.1.98 by Jay Pipes
Removed/replaced DBUG symbols and TRUE/FALSE
406
  return(0);
1 by brian
clean slate
407
} /* _mi_find_writepos */
408
409
410
411
/*
412
  Unlink a deleted block from the deleted list.
413
  This block will be combined with the preceding or next block to form
414
  a big block.
415
*/
416
281 by Brian Aker
Converted myisam away from my_bool
417
static bool unlink_deleted_block(MI_INFO *info, MI_BLOCK_INFO *block_info)
1 by brian
clean slate
418
{
419
  if (block_info->filepos == info->s->state.dellink)
420
  {
421
    /* First deleted block;  We can just use this ! */
422
    info->s->state.dellink=block_info->next_filepos;
423
  }
424
  else
425
  {
426
    MI_BLOCK_INFO tmp;
427
    tmp.second_read=0;
428
    /* Unlink block from the previous block */
429
    if (!(_mi_get_block_info(&tmp,info->dfile,block_info->prev_filepos)
430
	  & BLOCK_DELETED))
51.1.98 by Jay Pipes
Removed/replaced DBUG symbols and TRUE/FALSE
431
      return(1);				/* Something is wrong */
1 by brian
clean slate
432
    mi_sizestore(tmp.header+4,block_info->next_filepos);
433
    if (info->s->file_write(info, tmp.header+4,8,
434
		  block_info->prev_filepos+4, MYF(MY_NABP)))
51.1.98 by Jay Pipes
Removed/replaced DBUG symbols and TRUE/FALSE
435
      return(1);
1 by brian
clean slate
436
    /* Unlink block from next block */
437
    if (block_info->next_filepos != HA_OFFSET_ERROR)
438
    {
439
      if (!(_mi_get_block_info(&tmp,info->dfile,block_info->next_filepos)
440
	    & BLOCK_DELETED))
51.1.98 by Jay Pipes
Removed/replaced DBUG symbols and TRUE/FALSE
441
	return(1);				/* Something is wrong */
1 by brian
clean slate
442
      mi_sizestore(tmp.header+12,block_info->prev_filepos);
443
      if (info->s->file_write(info, tmp.header+12,8,
444
		    block_info->next_filepos+12,
445
		    MYF(MY_NABP)))
51.1.98 by Jay Pipes
Removed/replaced DBUG symbols and TRUE/FALSE
446
	return(1);
1 by brian
clean slate
447
    }
448
  }
449
  /* We now have one less deleted block */
450
  info->state->del--;
451
  info->state->empty-= block_info->block_len;
452
  info->s->state.split--;
453
454
  /*
455
    If this was a block that we where accessing through table scan
456
    (mi_rrnd() or mi_scan(), then ensure that we skip over this block
457
    when doing next mi_rrnd() or mi_scan().
458
  */
459
  if (info->nextpos == block_info->filepos)
460
    info->nextpos+=block_info->block_len;
51.1.98 by Jay Pipes
Removed/replaced DBUG symbols and TRUE/FALSE
461
  return(0);
1 by brian
clean slate
462
}
463
464
465
/*
466
  Add a backward link to delete block
467
468
  SYNOPSIS
469
    update_backward_delete_link()
470
    info		MyISAM handler
471
    delete_block	Position to delete block to update.
472
			If this is 'HA_OFFSET_ERROR', nothing will be done
473
    filepos		Position to block that 'delete_block' should point to
474
475
  RETURN
476
    0  ok
477
    1  error.  In this case my_error is set.
478
*/
479
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
480
static int update_backward_delete_link(MI_INFO *info, internal::my_off_t delete_block,
481
				       internal::my_off_t filepos)
1 by brian
clean slate
482
{
483
  MI_BLOCK_INFO block_info;
484
485
  if (delete_block != HA_OFFSET_ERROR)
486
  {
487
    block_info.second_read=0;
488
    if (_mi_get_block_info(&block_info,info->dfile,delete_block)
489
	& BLOCK_DELETED)
490
    {
481 by Brian Aker
Remove all of uchar.
491
      unsigned char buff[8];
1 by brian
clean slate
492
      mi_sizestore(buff,filepos);
493
      if (info->s->file_write(info,buff, 8, delete_block+12, MYF(MY_NABP)))
51.1.98 by Jay Pipes
Removed/replaced DBUG symbols and TRUE/FALSE
494
	return(1);				/* Error on write */
1 by brian
clean slate
495
    }
496
    else
497
    {
1241.9.57 by Monty Taylor
Oy. Bigger change than I normally like - but this stuff is all intertwined.
498
      errno=HA_ERR_WRONG_IN_RECORD;
51.1.98 by Jay Pipes
Removed/replaced DBUG symbols and TRUE/FALSE
499
      return(1);				/* Wrong delete link */
1 by brian
clean slate
500
    }
501
  }
51.1.98 by Jay Pipes
Removed/replaced DBUG symbols and TRUE/FALSE
502
  return(0);
1 by brian
clean slate
503
}
504
505
	/* Delete datarecord from database */
506
	/* info->rec_cache.seek_not_done is updated in cmp_record */
507
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
508
static int delete_dynamic_record(MI_INFO *info, internal::my_off_t filepos,
482 by Brian Aker
Remove uint.
509
				 uint32_t second_read)
1 by brian
clean slate
510
{
482 by Brian Aker
Remove uint.
511
  uint32_t length,b_type;
1 by brian
clean slate
512
  MI_BLOCK_INFO block_info,del_block;
513
  int error;
281 by Brian Aker
Converted myisam away from my_bool
514
  bool remove_next_block;
1 by brian
clean slate
515
516
  /* First add a link from the last block to the new one */
517
  error= update_backward_delete_link(info, info->s->state.dellink, filepos);
518
519
  block_info.second_read=second_read;
520
  do
521
  {
522
    /* Remove block at 'filepos' */
523
    if ((b_type=_mi_get_block_info(&block_info,info->dfile,filepos))
524
	& (BLOCK_DELETED | BLOCK_ERROR | BLOCK_SYNC_ERROR |
525
	   BLOCK_FATAL_ERROR) ||
526
	(length=(uint) (block_info.filepos-filepos) +block_info.block_len) <
527
	MI_MIN_BLOCK_LENGTH)
528
    {
1241.9.57 by Monty Taylor
Oy. Bigger change than I normally like - but this stuff is all intertwined.
529
      errno=HA_ERR_WRONG_IN_RECORD;
51.1.98 by Jay Pipes
Removed/replaced DBUG symbols and TRUE/FALSE
530
      return(1);
1 by brian
clean slate
531
    }
532
    /* Check if next block is a delete block */
533
    del_block.second_read=0;
534
    remove_next_block=0;
535
    if (_mi_get_block_info(&del_block,info->dfile,filepos+length) &
536
	BLOCK_DELETED && del_block.block_len+length < MI_DYN_MAX_BLOCK_LENGTH)
537
    {
538
      /* We can't remove this yet as this block may be the head block */
539
      remove_next_block=1;
540
      length+=del_block.block_len;
541
    }
542
543
    block_info.header[0]=0;
544
    mi_int3store(block_info.header+1,length);
545
    mi_sizestore(block_info.header+4,info->s->state.dellink);
546
    if (b_type & BLOCK_LAST)
212.6.3 by Mats Kindahl
Removing deprecated functions from code and replacing them with C99 equivalents:
547
      memset(block_info.header+12, 255, 8);
1 by brian
clean slate
548
    else
549
      mi_sizestore(block_info.header+12,block_info.next_filepos);
481 by Brian Aker
Remove all of uchar.
550
    if (info->s->file_write(info,(unsigned char*) block_info.header,20,filepos,
1 by brian
clean slate
551
		  MYF(MY_NABP)))
51.1.98 by Jay Pipes
Removed/replaced DBUG symbols and TRUE/FALSE
552
      return(1);
1 by brian
clean slate
553
    info->s->state.dellink = filepos;
554
    info->state->del++;
555
    info->state->empty+=length;
556
    filepos=block_info.next_filepos;
557
558
    /* Now it's safe to unlink the deleted block directly after this one */
559
    if (remove_next_block && unlink_deleted_block(info,&del_block))
560
      error=1;
561
  } while (!(b_type & BLOCK_LAST));
562
51.1.98 by Jay Pipes
Removed/replaced DBUG symbols and TRUE/FALSE
563
  return(error);
1 by brian
clean slate
564
}
565
566
567
	/* Write a block to datafile */
568
569
int _mi_write_part_record(MI_INFO *info,
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
570
			  internal::my_off_t filepos,	/* points at empty block */
1 by brian
clean slate
571
			  ulong length,		/* length of block */
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
572
			  internal::my_off_t next_filepos,/* Next empty block */
481 by Brian Aker
Remove all of uchar.
573
			  unsigned char **record,	/* pointer to record ptr */
1 by brian
clean slate
574
			  ulong *reclength,	/* length of *record */
575
			  int *flag)		/* *flag == 0 if header */
576
{
577
  ulong head_length,res_length,extra_length,long_block,del_length;
481 by Brian Aker
Remove all of uchar.
578
  unsigned char *pos,*record_end;
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
579
  internal::my_off_t  next_delete_block;
481 by Brian Aker
Remove all of uchar.
580
  unsigned char temp[MI_SPLIT_LENGTH+MI_DYN_DELETE_BLOCK_HEADER];
1 by brian
clean slate
581
582
  next_delete_block=HA_OFFSET_ERROR;
583
584
  res_length=extra_length=0;
585
  if (length > *reclength + MI_SPLIT_LENGTH)
586
  {						/* Splitt big block */
587
    res_length=MY_ALIGN(length- *reclength - MI_EXTEND_BLOCK_LENGTH,
588
			MI_DYN_ALIGN_SIZE);
589
    length-= res_length;			/* Use this for first part */
590
  }
591
  long_block= (length < 65520L && *reclength < 65520L) ? 0 : 1;
592
  if (length == *reclength+ 3 + long_block)
593
  {
594
    /* Block is exactly of the right length */
481 by Brian Aker
Remove all of uchar.
595
    temp[0]=(unsigned char) (1+ *flag)+(unsigned char) long_block;	/* Flag is 0 or 6 */
1 by brian
clean slate
596
    if (long_block)
597
    {
598
      mi_int3store(temp+1,*reclength);
599
      head_length=4;
600
    }
601
    else
602
    {
603
      mi_int2store(temp+1,*reclength);
604
      head_length=3;
605
    }
606
  }
607
  else if (length-long_block < *reclength+4)
608
  {						/* To short block */
609
    if (next_filepos == HA_OFFSET_ERROR)
610
      next_filepos= (info->s->state.dellink != HA_OFFSET_ERROR &&
611
                     !info->append_insert_at_end ?
612
                     info->s->state.dellink : info->state->data_file_length);
613
    if (*flag == 0)				/* First block */
614
    {
615
      if (*reclength > MI_MAX_BLOCK_LENGTH)
616
      {
617
	head_length= 16;
618
	temp[0]=13;
619
	mi_int4store(temp+1,*reclength);
620
	mi_int3store(temp+5,length-head_length);
481 by Brian Aker
Remove all of uchar.
621
	mi_sizestore((unsigned char*) temp+8,next_filepos);
1 by brian
clean slate
622
      }
623
      else
624
      {
625
	head_length=5+8+long_block*2;
481 by Brian Aker
Remove all of uchar.
626
	temp[0]=5+(unsigned char) long_block;
1 by brian
clean slate
627
	if (long_block)
628
	{
629
	  mi_int3store(temp+1,*reclength);
630
	  mi_int3store(temp+4,length-head_length);
481 by Brian Aker
Remove all of uchar.
631
	  mi_sizestore((unsigned char*) temp+7,next_filepos);
1 by brian
clean slate
632
	}
633
	else
634
	{
635
	  mi_int2store(temp+1,*reclength);
636
	  mi_int2store(temp+3,length-head_length);
481 by Brian Aker
Remove all of uchar.
637
	  mi_sizestore((unsigned char*) temp+5,next_filepos);
1 by brian
clean slate
638
	}
639
      }
640
    }
641
    else
642
    {
643
      head_length=3+8+long_block;
481 by Brian Aker
Remove all of uchar.
644
      temp[0]=11+(unsigned char) long_block;
1 by brian
clean slate
645
      if (long_block)
646
      {
647
	mi_int3store(temp+1,length-head_length);
481 by Brian Aker
Remove all of uchar.
648
	mi_sizestore((unsigned char*) temp+4,next_filepos);
1 by brian
clean slate
649
      }
650
      else
651
      {
652
	mi_int2store(temp+1,length-head_length);
481 by Brian Aker
Remove all of uchar.
653
	mi_sizestore((unsigned char*) temp+3,next_filepos);
1 by brian
clean slate
654
      }
655
    }
656
  }
657
  else
658
  {					/* Block with empty info last */
659
    head_length=4+long_block;
660
    extra_length= length- *reclength-head_length;
481 by Brian Aker
Remove all of uchar.
661
    temp[0]= (unsigned char) (3+ *flag)+(unsigned char) long_block; /* 3,4 or 9,10 */
1 by brian
clean slate
662
    if (long_block)
663
    {
664
      mi_int3store(temp+1,*reclength);
481 by Brian Aker
Remove all of uchar.
665
      temp[4]= (unsigned char) (extra_length);
1 by brian
clean slate
666
    }
667
    else
668
    {
669
      mi_int2store(temp+1,*reclength);
481 by Brian Aker
Remove all of uchar.
670
      temp[3]= (unsigned char) (extra_length);
1 by brian
clean slate
671
    }
672
    length=	  *reclength+head_length;	/* Write only what is needed */
673
  }
674
675
	/* Make a long block for one write */
676
  record_end= *record+length-head_length;
677
  del_length=(res_length ? MI_DYN_DELETE_BLOCK_HEADER : 0);
629.3.4 by Kristian Nielsen
Take Mats'es changes from bmove()->memcpy(), and fix all of them to be
678
  memmove(*record - head_length, temp, head_length);
1 by brian
clean slate
679
  memcpy(temp,record_end,(size_t) (extra_length+del_length));
212.6.12 by Mats Kindahl
Removing redundant use of casts in MyISAM storage for memcmp(), memcpy(), memset(), and memmove().
680
  memset(record_end, 0, extra_length);
1 by brian
clean slate
681
682
  if (res_length)
683
  {
684
    /* Check first if we can join this block with the next one */
685
    MI_BLOCK_INFO del_block;
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
686
    internal::my_off_t next_block=filepos+length+extra_length+res_length;
1 by brian
clean slate
687
688
    del_block.second_read=0;
689
    if (next_block < info->state->data_file_length &&
690
	info->s->state.dellink != HA_OFFSET_ERROR)
691
    {
692
      if ((_mi_get_block_info(&del_block,info->dfile,next_block)
693
	   & BLOCK_DELETED) &&
694
	  res_length + del_block.block_len < MI_DYN_MAX_BLOCK_LENGTH)
695
      {
696
	if (unlink_deleted_block(info,&del_block))
697
	  goto err;
698
	res_length+=del_block.block_len;
699
      }
700
    }
701
702
    /* Create a delete link of the last part of the block */
703
    pos=record_end+extra_length;
704
    pos[0]= '\0';
705
    mi_int3store(pos+1,res_length);
706
    mi_sizestore(pos+4,info->s->state.dellink);
212.6.3 by Mats Kindahl
Removing deprecated functions from code and replacing them with C99 equivalents:
707
    memset(pos+12, 255, 8);			/* End link */
1 by brian
clean slate
708
    next_delete_block=info->s->state.dellink;
709
    info->s->state.dellink= filepos+length+extra_length;
710
    info->state->del++;
711
    info->state->empty+=res_length;
712
    info->s->state.split++;
713
  }
714
  if (info->opt_flag & WRITE_CACHE_USED &&
715
      info->update & HA_STATE_WRITE_AT_END)
716
  {
717
    if (info->update & HA_STATE_EXTEND_BLOCK)
718
    {
719
      info->update&= ~HA_STATE_EXTEND_BLOCK;
481 by Brian Aker
Remove all of uchar.
720
      if (my_block_write(&info->rec_cache,(unsigned char*) *record-head_length,
1 by brian
clean slate
721
			 length+extra_length+del_length,filepos))
722
      goto err;
723
    }
481 by Brian Aker
Remove all of uchar.
724
    else if (my_b_write(&info->rec_cache,(unsigned char*) *record-head_length,
1 by brian
clean slate
725
			length+extra_length+del_length))
726
      goto err;
727
  }
728
  else
729
  {
730
    info->rec_cache.seek_not_done=1;
481 by Brian Aker
Remove all of uchar.
731
    if (info->s->file_write(info,(unsigned char*) *record-head_length,length+extra_length+
1 by brian
clean slate
732
		  del_length,filepos,info->s->write_flag))
733
      goto err;
734
  }
212.6.12 by Mats Kindahl
Removing redundant use of casts in MyISAM storage for memcmp(), memcpy(), memset(), and memmove().
735
  memcpy(record_end, temp, extra_length + del_length);
1 by brian
clean slate
736
  *record=record_end;
737
  *reclength-=(length-head_length);
738
  *flag=6;
739
740
  if (del_length)
741
  {
742
    /* link the next delete block to this */
743
    if (update_backward_delete_link(info, next_delete_block,
744
				    info->s->state.dellink))
745
      goto err;
746
  }
747
51.1.98 by Jay Pipes
Removed/replaced DBUG symbols and TRUE/FALSE
748
  return(0);
1 by brian
clean slate
749
err:
51.1.98 by Jay Pipes
Removed/replaced DBUG symbols and TRUE/FALSE
750
  return(1);
1 by brian
clean slate
751
} /*_mi_write_part_record */
752
753
754
	/* update record from datafile */
755
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
756
static int update_dynamic_record(MI_INFO *info, internal::my_off_t filepos, unsigned char *record,
1 by brian
clean slate
757
				 ulong reclength)
758
{
759
  int flag;
482 by Brian Aker
Remove uint.
760
  uint32_t error;
1 by brian
clean slate
761
  ulong length;
762
  MI_BLOCK_INFO block_info;
763
764
  flag=block_info.second_read=0;
765
  /*
766
     Check if we have enough room for the record.
767
     First we do simplified check to make usual case faster.
768
     Then we do more precise check for the space left.
769
     Though it still is not absolutely precise, as
770
     we always use MI_MAX_DYN_BLOCK_HEADER while it can be
771
     less in the most of the cases.
772
  */
773
774
  /*
775
    compare with just the reclength as we're going
776
    to get some space from the old replaced record
777
  */
778
  if (unlikely(info->s->base.max_data_file_length -
779
        info->state->data_file_length < reclength))
780
  {
781
    /*
782
       let's read the old record's block to find out the length of the
783
       old record
784
    */
785
    if ((error=_mi_get_block_info(&block_info,info->dfile,filepos))
786
        & (BLOCK_DELETED | BLOCK_ERROR | BLOCK_SYNC_ERROR | BLOCK_FATAL_ERROR))
787
    {
788
      if (!(error & BLOCK_FATAL_ERROR))
1241.9.57 by Monty Taylor
Oy. Bigger change than I normally like - but this stuff is all intertwined.
789
        errno=HA_ERR_WRONG_IN_RECORD;
1 by brian
clean slate
790
      goto err;
791
    }
792
793
    /*
794
      if new record isn't longer, we can go on safely
795
    */
796
    if (block_info.rec_len < reclength)
797
    {
798
      if (info->s->base.max_data_file_length - info->state->data_file_length +
799
          info->state->empty - info->state->del * MI_MAX_DYN_BLOCK_HEADER <
800
          reclength - block_info.rec_len + MI_MAX_DYN_BLOCK_HEADER)
801
      {
1241.9.57 by Monty Taylor
Oy. Bigger change than I normally like - but this stuff is all intertwined.
802
        errno=HA_ERR_RECORD_FILE_FULL;
1 by brian
clean slate
803
        goto err;
804
      }
805
    }
806
    block_info.second_read=0;
807
  }
808
809
  while (reclength > 0)
810
  {
811
    if (filepos != info->s->state.dellink)
812
    {
813
      block_info.next_filepos= HA_OFFSET_ERROR;
814
      if ((error=_mi_get_block_info(&block_info,info->dfile,filepos))
815
	  & (BLOCK_DELETED | BLOCK_ERROR | BLOCK_SYNC_ERROR |
816
	     BLOCK_FATAL_ERROR))
817
      {
818
	if (!(error & BLOCK_FATAL_ERROR))
1241.9.57 by Monty Taylor
Oy. Bigger change than I normally like - but this stuff is all intertwined.
819
	  errno=HA_ERR_WRONG_IN_RECORD;
1 by brian
clean slate
820
	goto err;
821
      }
822
      length=(ulong) (block_info.filepos-filepos) + block_info.block_len;
823
      if (length < reclength)
824
      {
482 by Brian Aker
Remove uint.
825
	uint32_t tmp=MY_ALIGN(reclength - length + 3 +
1 by brian
clean slate
826
			  test(reclength >= 65520L),MI_DYN_ALIGN_SIZE);
827
	/* Don't create a block bigger than MI_MAX_BLOCK_LENGTH */
1067.4.8 by Nathan Williams
Converted all usages of cmin/cmax in plugin directory to std::min/max.
828
	tmp= min(length+tmp, MI_MAX_BLOCK_LENGTH)-length;
1 by brian
clean slate
829
	/* Check if we can extend this block */
830
	if (block_info.filepos + block_info.block_len ==
831
	    info->state->data_file_length &&
832
	    info->state->data_file_length <
833
	    info->s->base.max_data_file_length-tmp)
834
	{
835
	  /* extend file */
836
	  if (info->nextpos == info->state->data_file_length)
837
	    info->nextpos+= tmp;
838
	  info->state->data_file_length+= tmp;
839
	  info->update|= HA_STATE_WRITE_AT_END | HA_STATE_EXTEND_BLOCK;
840
	  length+=tmp;
841
	}
842
	else if (length < MI_MAX_BLOCK_LENGTH - MI_MIN_BLOCK_LENGTH)
843
	{
844
	  /*
845
	    Check if next block is a deleted block
846
	    Above we have MI_MIN_BLOCK_LENGTH to avoid the problem where
847
	    the next block is so small it can't be splited which could
848
	    casue problems
849
	  */
850
851
	  MI_BLOCK_INFO del_block;
852
	  del_block.second_read=0;
853
	  if (_mi_get_block_info(&del_block,info->dfile,
854
				 block_info.filepos + block_info.block_len) &
855
	      BLOCK_DELETED)
856
	  {
857
	    /* Use; Unlink it and extend the current block */
858
	    if (unlink_deleted_block(info,&del_block))
859
	      goto err;
860
	    if ((length+=del_block.block_len) > MI_MAX_BLOCK_LENGTH)
861
	    {
862
	      /*
863
		New block was too big, link overflow part back to
864
		delete list
865
	      */
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
866
	      internal::my_off_t next_pos;
1 by brian
clean slate
867
	      ulong rest_length= length-MI_MAX_BLOCK_LENGTH;
937.2.6 by Stewart Smith
make set_if_bigger typesafe for C and C++. Fix up everywhere.
868
	      set_if_bigger(rest_length, (ulong)MI_MIN_BLOCK_LENGTH);
1 by brian
clean slate
869
	      next_pos= del_block.filepos+ del_block.block_len - rest_length;
870
871
	      if (update_backward_delete_link(info, info->s->state.dellink,
872
					      next_pos))
51.1.98 by Jay Pipes
Removed/replaced DBUG symbols and TRUE/FALSE
873
		return(1);
1 by brian
clean slate
874
875
	      /* create delete link for data that didn't fit into the page */
876
	      del_block.header[0]=0;
877
	      mi_int3store(del_block.header+1, rest_length);
878
	      mi_sizestore(del_block.header+4,info->s->state.dellink);
212.6.3 by Mats Kindahl
Removing deprecated functions from code and replacing them with C99 equivalents:
879
	      memset(del_block.header+12, 255, 8);
481 by Brian Aker
Remove all of uchar.
880
	      if (info->s->file_write(info,(unsigned char*) del_block.header,20, next_pos,
1 by brian
clean slate
881
			    MYF(MY_NABP)))
51.1.98 by Jay Pipes
Removed/replaced DBUG symbols and TRUE/FALSE
882
		return(1);
1 by brian
clean slate
883
	      info->s->state.dellink= next_pos;
884
	      info->s->state.split++;
885
	      info->state->del++;
886
	      info->state->empty+= rest_length;
887
	      length-= rest_length;
888
	    }
889
	  }
890
	}
891
      }
892
    }
893
    else
894
    {
895
      if (_mi_find_writepos(info,reclength,&filepos,&length))
896
	goto err;
897
    }
898
    if (_mi_write_part_record(info,filepos,length,block_info.next_filepos,
899
			      &record,&reclength,&flag))
900
      goto err;
901
    if ((filepos=block_info.next_filepos) == HA_OFFSET_ERROR)
902
    {
903
      /* Start writing data on deleted blocks */
904
      filepos=info->s->state.dellink;
905
    }
906
  }
907
908
  if (block_info.next_filepos != HA_OFFSET_ERROR)
909
    if (delete_dynamic_record(info,block_info.next_filepos,1))
910
      goto err;
51.1.98 by Jay Pipes
Removed/replaced DBUG symbols and TRUE/FALSE
911
  return(0);
1 by brian
clean slate
912
err:
51.1.98 by Jay Pipes
Removed/replaced DBUG symbols and TRUE/FALSE
913
  return(1);
1 by brian
clean slate
914
}
915
916
917
	/* Pack a record. Return new reclength */
918
482 by Brian Aker
Remove uint.
919
uint32_t _mi_rec_pack(MI_INFO *info, register unsigned char *to,
481 by Brian Aker
Remove all of uchar.
920
                  register const unsigned char *from)
1 by brian
clean slate
921
{
922
  uint		length,new_length,flag,bit,i;
481 by Brian Aker
Remove all of uchar.
923
  unsigned char		*pos,*end,*startpos,*packpos;
1 by brian
clean slate
924
  enum en_fieldtype type;
925
  register MI_COLUMNDEF *rec;
926
  MI_BLOB	*blob;
927
928
  flag=0 ; bit=1;
929
  startpos=packpos=to; to+= info->s->base.pack_bits; blob=info->blobs;
930
  rec=info->s->rec;
931
932
  for (i=info->s->base.fields ; i-- > 0; from+= length,rec++)
933
  {
934
    length=(uint) rec->length;
935
    if ((type = (enum en_fieldtype) rec->type) != FIELD_NORMAL)
936
    {
937
      if (type == FIELD_BLOB)
938
      {
939
	if (!blob->length)
940
	  flag|=bit;
941
	else
942
	{
943
	  char *temp_pos;
944
	  size_t tmp_length=length-portable_sizeof_char_ptr;
212.6.12 by Mats Kindahl
Removing redundant use of casts in MyISAM storage for memcmp(), memcpy(), memset(), and memmove().
945
	  memcpy(to,from,tmp_length);
212.6.3 by Mats Kindahl
Removing deprecated functions from code and replacing them with C99 equivalents:
946
	  memcpy(&temp_pos,from+tmp_length,sizeof(char*));
212.6.12 by Mats Kindahl
Removing redundant use of casts in MyISAM storage for memcmp(), memcpy(), memset(), and memmove().
947
	  memcpy(to + tmp_length, temp_pos, blob->length);
1 by brian
clean slate
948
	  to+=tmp_length+blob->length;
949
	}
950
	blob++;
951
      }
952
      else if (type == FIELD_SKIP_ZERO)
953
      {
212.6.12 by Mats Kindahl
Removing redundant use of casts in MyISAM storage for memcmp(), memcpy(), memset(), and memmove().
954
	if (memcmp(from,zero_string,length) == 0)
1 by brian
clean slate
955
	  flag|=bit;
956
	else
957
	{
212.6.12 by Mats Kindahl
Removing redundant use of casts in MyISAM storage for memcmp(), memcpy(), memset(), and memmove().
958
	  memcpy(to, from, length);
959
          to+=length;
1 by brian
clean slate
960
	}
961
      }
962
      else if (type == FIELD_SKIP_ENDSPACE ||
963
	       type == FIELD_SKIP_PRESPACE)
964
      {
481 by Brian Aker
Remove all of uchar.
965
	pos= (unsigned char*) from; end= (unsigned char*) from + length;
1 by brian
clean slate
966
	if (type == FIELD_SKIP_ENDSPACE)
967
	{					/* Pack trailing spaces */
968
	  while (end > from && *(end-1) == ' ')
969
	    end--;
970
	}
971
	else
972
	{					/* Pack pref-spaces */
973
	  while (pos < end && *pos == ' ')
974
	    pos++;
975
	}
976
	new_length=(uint) (end-pos);
977
	if (new_length +1 + test(rec->length > 255 && new_length > 127)
978
	    < length)
979
	{
980
	  if (rec->length > 255 && new_length > 127)
981
	  {
481 by Brian Aker
Remove all of uchar.
982
            to[0]= (unsigned char) ((new_length & 127) + 128);
983
            to[1]= (unsigned char) (new_length >> 7);
1 by brian
clean slate
984
            to+=2;
985
          }
986
          else
481 by Brian Aker
Remove all of uchar.
987
            *to++= (unsigned char) new_length;
212.6.12 by Mats Kindahl
Removing redundant use of casts in MyISAM storage for memcmp(), memcpy(), memset(), and memmove().
988
	  memcpy(to, pos, new_length);
989
          to+=new_length;
1 by brian
clean slate
990
	  flag|=bit;
991
	}
992
	else
993
	{
212.6.12 by Mats Kindahl
Removing redundant use of casts in MyISAM storage for memcmp(), memcpy(), memset(), and memmove().
994
	  memcpy(to, from, length);
995
          to+=length;
1 by brian
clean slate
996
	}
997
      }
998
      else if (type == FIELD_VARCHAR)
999
      {
1892.5.2 by Gustaf Thorslund
Replaced macros with functions/templates. Part of blueprint:
1000
        uint32_t pack_length= ha_varchar_packlength(rec->length -1);
482 by Brian Aker
Remove uint.
1001
	uint32_t tmp_length;
1 by brian
clean slate
1002
        if (pack_length == 1)
1003
        {
481 by Brian Aker
Remove all of uchar.
1004
          tmp_length= (uint) *(unsigned char*) from;
1 by brian
clean slate
1005
          *to++= *from;
1006
        }
1007
        else
1008
        {
1009
          tmp_length= uint2korr(from);
1010
          store_key_length_inc(to,tmp_length);
1011
        }
212.6.12 by Mats Kindahl
Removing redundant use of casts in MyISAM storage for memcmp(), memcpy(), memset(), and memmove().
1012
        memcpy(to, from+pack_length, tmp_length);
1 by brian
clean slate
1013
        to+= tmp_length;
1014
        continue;
1015
      }
1016
      else
1017
      {
212.6.12 by Mats Kindahl
Removing redundant use of casts in MyISAM storage for memcmp(), memcpy(), memset(), and memmove().
1018
	memcpy(to, from, length);
1019
        to+=length;
1 by brian
clean slate
1020
	continue;				/* Normal field */
1021
      }
1022
      if ((bit= bit << 1) >= 256)
1023
      {
481 by Brian Aker
Remove all of uchar.
1024
        *packpos++= (unsigned char) flag;
1 by brian
clean slate
1025
	bit=1; flag=0;
1026
      }
1027
    }
1028
    else
1029
    {
212.6.12 by Mats Kindahl
Removing redundant use of casts in MyISAM storage for memcmp(), memcpy(), memset(), and memmove().
1030
      memcpy(to, from, length);
1031
      to+=length;
1 by brian
clean slate
1032
    }
1033
  }
1034
  if (bit != 1)
481 by Brian Aker
Remove all of uchar.
1035
    *packpos= (unsigned char) flag;
1 by brian
clean slate
1036
  if (info->s->calc_checksum)
481 by Brian Aker
Remove all of uchar.
1037
    *to++= (unsigned char) info->checksum;
51.1.98 by Jay Pipes
Removed/replaced DBUG symbols and TRUE/FALSE
1038
  return((uint) (to-startpos));
1 by brian
clean slate
1039
} /* _mi_rec_pack */
1040
1041
1042
1043
/*
1044
  Check if a record was correctly packed. Used only by myisamchk
1045
  Returns 0 if record is ok.
1046
*/
1047
481 by Brian Aker
Remove all of uchar.
1048
bool _mi_rec_check(MI_INFO *info,const unsigned char *record, unsigned char *rec_buff,
281 by Brian Aker
Converted myisam away from my_bool
1049
                      ulong packed_length, bool with_checksum)
1 by brian
clean slate
1050
{
1051
  uint		length,new_length,flag,bit,i;
481 by Brian Aker
Remove all of uchar.
1052
  unsigned char		*pos,*end,*packpos,*to;
1 by brian
clean slate
1053
  enum en_fieldtype type;
1054
  register MI_COLUMNDEF *rec;
1055
1056
  packpos=rec_buff; to= rec_buff+info->s->base.pack_bits;
1057
  rec=info->s->rec;
1058
  flag= *packpos; bit=1;
1059
1060
  for (i=info->s->base.fields ; i-- > 0; record+= length, rec++)
1061
  {
1062
    length=(uint) rec->length;
1063
    if ((type = (enum en_fieldtype) rec->type) != FIELD_NORMAL)
1064
    {
1065
      if (type == FIELD_BLOB)
1066
      {
482 by Brian Aker
Remove uint.
1067
	uint32_t blob_length=
1 by brian
clean slate
1068
	  _mi_calc_blob_length(length-portable_sizeof_char_ptr,record);
1069
	if (!blob_length && !(flag & bit))
1070
	  goto err;
1071
	if (blob_length)
1072
	  to+=length - portable_sizeof_char_ptr+ blob_length;
1073
      }
1074
      else if (type == FIELD_SKIP_ZERO)
1075
      {
212.6.12 by Mats Kindahl
Removing redundant use of casts in MyISAM storage for memcmp(), memcpy(), memset(), and memmove().
1076
	if (memcmp(record,zero_string,length) == 0)
1 by brian
clean slate
1077
	{
1078
	  if (!(flag & bit))
1079
	    goto err;
1080
	}
1081
	else
1082
	  to+=length;
1083
      }
1084
      else if (type == FIELD_SKIP_ENDSPACE ||
1085
	       type == FIELD_SKIP_PRESPACE)
1086
      {
481 by Brian Aker
Remove all of uchar.
1087
	pos= (unsigned char*) record; end= (unsigned char*) record + length;
1 by brian
clean slate
1088
	if (type == FIELD_SKIP_ENDSPACE)
1089
	{					/* Pack trailing spaces */
1090
	  while (end > record && *(end-1) == ' ')
1091
	    end--;
1092
	}
1093
	else
1094
	{					/* Pack pre-spaces */
1095
	  while (pos < end && *pos == ' ')
1096
	    pos++;
1097
	}
1098
	new_length=(uint) (end-pos);
1099
	if (new_length +1 + test(rec->length > 255 && new_length > 127)
1100
	    < length)
1101
	{
1102
	  if (!(flag & bit))
1103
	    goto err;
1104
	  if (rec->length > 255 && new_length > 127)
1105
	  {
481 by Brian Aker
Remove all of uchar.
1106
            if (to[0] != (unsigned char) ((new_length & 127) + 128) ||
1107
                to[1] != (unsigned char) (new_length >> 7))
1 by brian
clean slate
1108
              goto err;
1109
            to+=2;
1110
          }
481 by Brian Aker
Remove all of uchar.
1111
          else if (*to++ != (unsigned char) new_length)
1 by brian
clean slate
1112
	    goto err;
1113
	  to+=new_length;
1114
	}
1115
	else
1116
	  to+=length;
1117
      }
1118
      else if (type == FIELD_VARCHAR)
1119
      {
1892.5.2 by Gustaf Thorslund
Replaced macros with functions/templates. Part of blueprint:
1120
        uint32_t pack_length= ha_varchar_packlength(rec->length -1);
482 by Brian Aker
Remove uint.
1121
	uint32_t tmp_length;
1 by brian
clean slate
1122
        if (pack_length == 1)
1123
        {
481 by Brian Aker
Remove all of uchar.
1124
          tmp_length= (uint) *(unsigned char*) record;
1 by brian
clean slate
1125
          to+= 1+ tmp_length;
1126
          continue;
1127
        }
1128
        else
1129
        {
1130
          tmp_length= uint2korr(record);
1131
          to+= get_pack_length(tmp_length)+tmp_length;
1132
        }
1133
        continue;
1134
      }
1135
      else
1136
      {
1137
	to+=length;
1138
	continue;				/* Normal field */
1139
      }
1140
      if ((bit= bit << 1) >= 256)
1141
      {
1142
	flag= *++packpos;
1143
	bit=1;
1144
      }
1145
    }
1146
    else
1147
      to+= length;
1148
  }
1149
  if (packed_length != (uint) (to - rec_buff) + test(info->s->calc_checksum) ||
1150
      (bit != 1 && (flag & ~(bit - 1))))
1151
    goto err;
481 by Brian Aker
Remove all of uchar.
1152
  if (with_checksum && ((unsigned char) info->checksum != (unsigned char) *to))
1 by brian
clean slate
1153
  {
1154
    goto err;
1155
  }
51.1.98 by Jay Pipes
Removed/replaced DBUG symbols and TRUE/FALSE
1156
  return(0);
1 by brian
clean slate
1157
1158
err:
51.1.98 by Jay Pipes
Removed/replaced DBUG symbols and TRUE/FALSE
1159
  return(1);
1 by brian
clean slate
1160
}
1161
1162
1163
1164
	/* Unpacks a record */
1241.9.57 by Monty Taylor
Oy. Bigger change than I normally like - but this stuff is all intertwined.
1165
	/* Returns -1 and errno =HA_ERR_RECORD_DELETED if reclength isn't */
1 by brian
clean slate
1166
	/* right. Returns reclength (>0) if ok */
1167
481 by Brian Aker
Remove all of uchar.
1168
ulong _mi_rec_unpack(register MI_INFO *info, register unsigned char *to, unsigned char *from,
1 by brian
clean slate
1169
		     ulong found_length)
1170
{
482 by Brian Aker
Remove uint.
1171
  uint32_t flag,bit,length,rec_length,min_pack_length;
1 by brian
clean slate
1172
  enum en_fieldtype type;
481 by Brian Aker
Remove all of uchar.
1173
  unsigned char *from_end,*to_end,*packpos;
1 by brian
clean slate
1174
  register MI_COLUMNDEF *rec,*end_field;
1175
1176
  to_end=to + info->s->base.reclength;
1177
  from_end=from+found_length;
481 by Brian Aker
Remove all of uchar.
1178
  flag= (unsigned char) *from; bit=1; packpos=from;
1 by brian
clean slate
1179
  if (found_length < info->s->base.min_pack_length)
1180
    goto err;
1181
  from+= info->s->base.pack_bits;
1182
  min_pack_length=info->s->base.min_pack_length - info->s->base.pack_bits;
1183
1184
  for (rec=info->s->rec , end_field=rec+info->s->base.fields ;
1185
       rec < end_field ; to+= rec_length, rec++)
1186
  {
1187
    rec_length=rec->length;
1188
    if ((type = (enum en_fieldtype) rec->type) != FIELD_NORMAL &&
1189
	(type != FIELD_CHECK))
1190
    {
1191
      if (type == FIELD_VARCHAR)
1192
      {
1892.5.2 by Gustaf Thorslund
Replaced macros with functions/templates. Part of blueprint:
1193
        uint32_t pack_length= ha_varchar_packlength(rec_length-1);
1 by brian
clean slate
1194
        if (pack_length == 1)
1195
        {
481 by Brian Aker
Remove all of uchar.
1196
          length= (uint) *(unsigned char*) from;
1 by brian
clean slate
1197
          if (length > rec_length-1)
1198
            goto err;
1199
          *to= *from++;
1200
        }
1201
        else
1202
        {
1203
          get_key_length(length, from);
1204
          if (length > rec_length-2)
1205
            goto err;
1206
          int2store(to,length);
1207
        }
1208
        if (from+length > from_end)
1209
          goto err;
1210
        memcpy(to+pack_length, from, length);
1211
        from+= length;
1212
        min_pack_length--;
1213
        continue;
1214
      }
1215
      if (flag & bit)
1216
      {
1217
	if (type == FIELD_BLOB || type == FIELD_SKIP_ZERO)
212.6.12 by Mats Kindahl
Removing redundant use of casts in MyISAM storage for memcmp(), memcpy(), memset(), and memmove().
1218
	  memset(to, 0, rec_length);
1 by brian
clean slate
1219
	else if (type == FIELD_SKIP_ENDSPACE ||
1220
		 type == FIELD_SKIP_PRESPACE)
1221
	{
1222
	  if (rec->length > 255 && *from & 128)
1223
	  {
1224
	    if (from + 1 >= from_end)
1225
	      goto err;
481 by Brian Aker
Remove all of uchar.
1226
	    length= (*from & 127)+ ((uint) (unsigned char) *(from+1) << 7); from+=2;
1 by brian
clean slate
1227
	  }
1228
	  else
1229
	  {
1230
	    if (from == from_end)
1231
	      goto err;
481 by Brian Aker
Remove all of uchar.
1232
	    length= (unsigned char) *from++;
1 by brian
clean slate
1233
	  }
1234
	  min_pack_length--;
1235
	  if (length >= rec_length ||
1236
	      min_pack_length + length > (uint) (from_end - from))
1237
	    goto err;
1238
	  if (type == FIELD_SKIP_ENDSPACE)
1239
	  {
212.6.12 by Mats Kindahl
Removing redundant use of casts in MyISAM storage for memcmp(), memcpy(), memset(), and memmove().
1240
	    memcpy(to, from, length);
1241
	    memset(to+length, ' ', rec_length-length);
1 by brian
clean slate
1242
	  }
1243
	  else
1244
	  {
212.6.12 by Mats Kindahl
Removing redundant use of casts in MyISAM storage for memcmp(), memcpy(), memset(), and memmove().
1245
	    memset(to, ' ', rec_length-length);
1246
	    memcpy(to + rec_length - length, from, length);
1 by brian
clean slate
1247
	  }
1248
	  from+=length;
1249
	}
1250
      }
1251
      else if (type == FIELD_BLOB)
1252
      {
482 by Brian Aker
Remove uint.
1253
	uint32_t size_length=rec_length- portable_sizeof_char_ptr;
1 by brian
clean slate
1254
	ulong blob_length=_mi_calc_blob_length(size_length,from);
1255
        ulong from_left= (ulong) (from_end - from);
1256
        if (from_left < size_length ||
1257
            from_left - size_length < blob_length ||
1258
            from_left - size_length - blob_length < min_pack_length)
1259
          goto err;
212.6.12 by Mats Kindahl
Removing redundant use of casts in MyISAM storage for memcmp(), memcpy(), memset(), and memmove().
1260
	memcpy(to, from, size_length);
1 by brian
clean slate
1261
	from+=size_length;
212.6.12 by Mats Kindahl
Removing redundant use of casts in MyISAM storage for memcmp(), memcpy(), memset(), and memmove().
1262
	memcpy(to+size_length, &from, sizeof(char*));
1 by brian
clean slate
1263
	from+=blob_length;
1264
      }
1265
      else
1266
      {
1267
	if (type == FIELD_SKIP_ENDSPACE || type == FIELD_SKIP_PRESPACE)
1268
	  min_pack_length--;
1269
	if (min_pack_length + rec_length > (uint) (from_end - from))
1270
	  goto err;
212.6.12 by Mats Kindahl
Removing redundant use of casts in MyISAM storage for memcmp(), memcpy(), memset(), and memmove().
1271
        memcpy(to, from, rec_length);
1272
        from+=rec_length;
1 by brian
clean slate
1273
      }
1274
      if ((bit= bit << 1) >= 256)
1275
      {
481 by Brian Aker
Remove all of uchar.
1276
	flag= (unsigned char) *++packpos; bit=1;
1 by brian
clean slate
1277
      }
1278
    }
1279
    else
1280
    {
1281
      if (min_pack_length > (uint) (from_end - from))
1282
	goto err;
1283
      min_pack_length-=rec_length;
212.6.12 by Mats Kindahl
Removing redundant use of casts in MyISAM storage for memcmp(), memcpy(), memset(), and memmove().
1284
      memcpy(to, from, rec_length);
1 by brian
clean slate
1285
      from+=rec_length;
1286
    }
1287
  }
1288
  if (info->s->calc_checksum)
1289
    from++;
1290
  if (to == to_end && from == from_end && (bit == 1 || !(flag & ~(bit-1))))
51.1.98 by Jay Pipes
Removed/replaced DBUG symbols and TRUE/FALSE
1291
    return(found_length);
1 by brian
clean slate
1292
1293
err:
1241.9.57 by Monty Taylor
Oy. Bigger change than I normally like - but this stuff is all intertwined.
1294
  errno= HA_ERR_WRONG_IN_RECORD;
51.1.98 by Jay Pipes
Removed/replaced DBUG symbols and TRUE/FALSE
1295
  return(MY_FILE_ERROR);
1 by brian
clean slate
1296
} /* _mi_rec_unpack */
1297
1298
1299
	/* Calc length of blob. Update info in blobs->length */
1300
481 by Brian Aker
Remove all of uchar.
1301
ulong _my_calc_total_blob_length(MI_INFO *info, const unsigned char *record)
1 by brian
clean slate
1302
{
1303
  ulong length;
1304
  MI_BLOB *blob,*end;
1305
1306
  for (length=0, blob= info->blobs, end=blob+info->s->base.blobs ;
1307
       blob != end;
1308
       blob++)
1309
  {
1310
    blob->length=_mi_calc_blob_length(blob->pack_length,record + blob->offset);
1311
    length+=blob->length;
1312
  }
1313
  return length;
1314
}
1315
1316
482 by Brian Aker
Remove uint.
1317
ulong _mi_calc_blob_length(uint32_t length, const unsigned char *pos)
1 by brian
clean slate
1318
{
1319
  switch (length) {
1320
  case 1:
481 by Brian Aker
Remove all of uchar.
1321
    return (uint) (unsigned char) *pos;
1 by brian
clean slate
1322
  case 2:
1323
    return (uint) uint2korr(pos);
1324
  case 3:
1325
    return uint3korr(pos);
1326
  case 4:
1327
    return uint4korr(pos);
1328
  default:
1329
    break;
1330
  }
1331
  return 0; /* Impossible */
1332
}
1333
1334
482 by Brian Aker
Remove uint.
1335
void _my_store_blob_length(unsigned char *pos,uint32_t pack_length,uint32_t length)
1 by brian
clean slate
1336
{
1337
  switch (pack_length) {
1338
  case 1:
481 by Brian Aker
Remove all of uchar.
1339
    *pos= (unsigned char) length;
1 by brian
clean slate
1340
    break;
1341
  case 2:
1342
    int2store(pos,length);
1343
    break;
1344
  case 3:
1345
    int3store(pos,length);
1346
    break;
1347
  case 4:
1348
    int4store(pos,length);
1349
  default:
1350
    break;
1351
  }
1352
  return;
1353
}
1354
1355
1356
/*
1357
  Read record from datafile.
1358
1359
  SYNOPSIS
1360
    _mi_read_dynamic_record()
1361
      info                      MI_INFO pointer to table.
1362
      filepos                   From where to read the record.
1363
      buf                       Destination for record.
1364
1365
  NOTE
1366
1367
    If a write buffer is active, it needs to be flushed if its contents
1368
    intersects with the record to read. We always check if the position
1369
    of the first byte of the write buffer is lower than the position
1370
    past the last byte to read. In theory this is also true if the write
1371
    buffer is completely below the read segment. That is, if there is no
1372
    intersection. But this case is unusual. We flush anyway. Only if the
1373
    first byte in the write buffer is above the last byte to read, we do
1374
    not flush.
1375
1376
    A dynamic record may need several reads. So this check must be done
1377
    before every read. Reading a dynamic record starts with reading the
1378
    block header. If the record does not fit into the free space of the
1379
    header, the block may be longer than the header. In this case a
1380
    second read is necessary. These one or two reads repeat for every
1381
    part of the record.
1382
1383
  RETURN
1384
    0           OK
1385
    -1          Error
1386
*/
1387
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
1388
int _mi_read_dynamic_record(MI_INFO *info, internal::my_off_t filepos, unsigned char *buf)
1 by brian
clean slate
1389
{
1390
  int block_of_record;
482 by Brian Aker
Remove uint.
1391
  uint32_t b_type, left_length= 0;
481 by Brian Aker
Remove all of uchar.
1392
  unsigned char *to= NULL;
1 by brian
clean slate
1393
  MI_BLOCK_INFO block_info;
1241.9.1 by Monty Taylor
Removed global.h. Fixed all the headers.
1394
  int file;
1 by brian
clean slate
1395
1396
  if (filepos != HA_OFFSET_ERROR)
1397
  {
1398
    file=info->dfile;
1399
    block_of_record= 0;   /* First block of record is numbered as zero. */
1400
    block_info.second_read= 0;
1401
    do
1402
    {
1403
      /* A corrupted table can have wrong pointers. (Bug# 19835) */
1404
      if (filepos == HA_OFFSET_ERROR)
1405
        goto panic;
1406
      if (info->opt_flag & WRITE_CACHE_USED &&
1407
	  info->rec_cache.pos_in_file < filepos + MI_BLOCK_INFO_HEADER_LENGTH &&
1408
	  flush_io_cache(&info->rec_cache))
1409
	goto err;
1410
      info->rec_cache.seek_not_done=1;
1411
      if ((b_type= _mi_get_block_info(&block_info, file, filepos))
1412
	  & (BLOCK_DELETED | BLOCK_ERROR | BLOCK_SYNC_ERROR |
1413
	     BLOCK_FATAL_ERROR))
1414
      {
1415
	if (b_type & (BLOCK_SYNC_ERROR | BLOCK_DELETED))
1241.9.57 by Monty Taylor
Oy. Bigger change than I normally like - but this stuff is all intertwined.
1416
	  errno=HA_ERR_RECORD_DELETED;
1 by brian
clean slate
1417
	goto err;
1418
      }
1419
      if (block_of_record++ == 0)			/* First block */
1420
      {
1421
	if (block_info.rec_len > (uint) info->s->base.max_pack_length)
1422
	  goto panic;
1423
	if (info->s->base.blobs)
1424
	{
1425
	  if (!(to=mi_alloc_rec_buff(info, block_info.rec_len,
1426
				     &info->rec_buff)))
1427
	    goto err;
1428
	}
1429
	else
1430
	  to= info->rec_buff;
1431
	left_length=block_info.rec_len;
1432
      }
1433
      if (left_length < block_info.data_len || ! block_info.data_len)
1434
	goto panic;			/* Wrong linked record */
1435
      /* copy information that is already read */
1436
      {
482 by Brian Aker
Remove uint.
1437
        uint32_t offset= (uint) (block_info.filepos - filepos);
1438
        uint32_t prefetch_len= (sizeof(block_info.header) - offset);
1 by brian
clean slate
1439
        filepos+= sizeof(block_info.header);
1440
1441
        if (prefetch_len > block_info.data_len)
1442
          prefetch_len= block_info.data_len;
1443
        if (prefetch_len)
1444
        {
212.6.12 by Mats Kindahl
Removing redundant use of casts in MyISAM storage for memcmp(), memcpy(), memset(), and memmove().
1445
          memcpy(to, block_info.header + offset, prefetch_len);
1 by brian
clean slate
1446
          block_info.data_len-= prefetch_len;
1447
          left_length-= prefetch_len;
1448
          to+= prefetch_len;
1449
        }
1450
      }
1451
      /* read rest of record from file */
1452
      if (block_info.data_len)
1453
      {
1454
        if (info->opt_flag & WRITE_CACHE_USED &&
1455
            info->rec_cache.pos_in_file < filepos + block_info.data_len &&
1456
            flush_io_cache(&info->rec_cache))
1457
          goto err;
1458
        /*
1459
          What a pity that this method is not called 'file_pread' and that
1460
          there is no equivalent without seeking. We are at the right
1461
          position already. :(
1462
        */
481 by Brian Aker
Remove all of uchar.
1463
        if (info->s->file_read(info, (unsigned char*) to, block_info.data_len,
1 by brian
clean slate
1464
                               filepos, MYF(MY_NABP)))
1465
          goto panic;
1466
        left_length-=block_info.data_len;
1467
        to+=block_info.data_len;
1468
      }
1469
      filepos= block_info.next_filepos;
1470
    } while (left_length);
1471
1472
    info->update|= HA_STATE_AKTIV;	/* We have a aktive record */
1473
    fast_mi_writeinfo(info);
51.1.98 by Jay Pipes
Removed/replaced DBUG symbols and TRUE/FALSE
1474
    return(_mi_rec_unpack(info,buf,info->rec_buff,block_info.rec_len) !=
1 by brian
clean slate
1475
		MY_FILE_ERROR ? 0 : -1);
1476
  }
1477
  fast_mi_writeinfo(info);
51.1.98 by Jay Pipes
Removed/replaced DBUG symbols and TRUE/FALSE
1478
  return(-1);			/* Wrong data to read */
1 by brian
clean slate
1479
1480
panic:
1241.9.57 by Monty Taylor
Oy. Bigger change than I normally like - but this stuff is all intertwined.
1481
  errno=HA_ERR_WRONG_IN_RECORD;
1 by brian
clean slate
1482
err:
398.1.10 by Monty Taylor
Actually removed VOID() this time.
1483
  _mi_writeinfo(info,0);
51.1.98 by Jay Pipes
Removed/replaced DBUG symbols and TRUE/FALSE
1484
  return(-1);
1 by brian
clean slate
1485
}
1486
1487
	/* compare unique constraint between stored rows */
1488
1489
int _mi_cmp_dynamic_unique(MI_INFO *info, MI_UNIQUEDEF *def,
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
1490
			   const unsigned char *record, internal::my_off_t pos)
1 by brian
clean slate
1491
{
481 by Brian Aker
Remove all of uchar.
1492
  unsigned char *rec_buff,*old_record;
1 by brian
clean slate
1493
  int error;
1494
960.2.2 by Monty Taylor
Moved MyISAM files to C++ so we can continue to consolidate code.
1495
  if (!(old_record=(unsigned char *)malloc(info->s->base.reclength)))
51.1.98 by Jay Pipes
Removed/replaced DBUG symbols and TRUE/FALSE
1496
    return(1);
1 by brian
clean slate
1497
1498
  /* Don't let the compare destroy blobs that may be in use */
1499
  rec_buff=info->rec_buff;
1500
  if (info->s->base.blobs)
1501
    info->rec_buff=0;
1502
  error=_mi_read_dynamic_record(info,pos,old_record);
1503
  if (!error)
1504
    error=mi_unique_comp(def, record, old_record, def->null_are_equal);
1505
  if (info->s->base.blobs)
1506
  {
477 by Monty Taylor
Removed my_free(). It turns out that it had been def'd to ignore the flags passed to it in the second arg anyway. Gotta love that.
1507
    void * rec_buff_ptr= mi_get_rec_buff_ptr(info, info->rec_buff);
2353.3.1 by Mark Atwood
fix cppcheck redundantIfDelete0 warnings. It is safe to deallocate a NULL pointer
1508
    free(rec_buff_ptr);
1 by brian
clean slate
1509
    info->rec_buff=rec_buff;
1510
  }
656.1.1 by Monty Taylor
OOOh doggie. Got rid of my_alloca.
1511
  free(old_record);
51.1.98 by Jay Pipes
Removed/replaced DBUG symbols and TRUE/FALSE
1512
  return(error);
1 by brian
clean slate
1513
}
1514
1515
1516
	/* Compare of record one disk with packed record in memory */
1517
481 by Brian Aker
Remove all of uchar.
1518
int _mi_cmp_dynamic_record(register MI_INFO *info, register const unsigned char *record)
1 by brian
clean slate
1519
{
482 by Brian Aker
Remove uint.
1520
  uint32_t flag,reclength,b_type;
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
1521
  internal::my_off_t filepos;
481 by Brian Aker
Remove all of uchar.
1522
  unsigned char *buffer;
1 by brian
clean slate
1523
  MI_BLOCK_INFO block_info;
1524
1525
  if (info->opt_flag & WRITE_CACHE_USED)
1526
  {
1527
    info->update&= ~(HA_STATE_WRITE_AT_END | HA_STATE_EXTEND_BLOCK);
1528
    if (flush_io_cache(&info->rec_cache))
51.1.98 by Jay Pipes
Removed/replaced DBUG symbols and TRUE/FALSE
1529
      return(-1);
1 by brian
clean slate
1530
  }
1531
  info->rec_cache.seek_not_done=1;
1532
1533
	/* If nobody have touched the database we don't have to test rec */
1534
1535
  buffer=info->rec_buff;
1536
  if ((info->opt_flag & READ_CHECK_USED))
1537
  {						/* If check isn't disabled  */
1538
    if (info->s->base.blobs)
1539
    {
656.1.1 by Monty Taylor
OOOh doggie. Got rid of my_alloca.
1540
      if (!(buffer=(unsigned char*) malloc(info->s->base.pack_reclength+
1 by brian
clean slate
1541
				     _my_calc_total_blob_length(info,record))))
51.1.98 by Jay Pipes
Removed/replaced DBUG symbols and TRUE/FALSE
1542
	return(-1);
1 by brian
clean slate
1543
    }
1544
    reclength=_mi_rec_pack(info,buffer,record);
1545
    record= buffer;
1546
1547
    filepos=info->lastpos;
1548
    flag=block_info.second_read=0;
1549
    block_info.next_filepos=filepos;
1550
    while (reclength > 0)
1551
    {
1552
      if ((b_type=_mi_get_block_info(&block_info,info->dfile,
1553
				    block_info.next_filepos))
1554
	  & (BLOCK_DELETED | BLOCK_ERROR | BLOCK_SYNC_ERROR |
1555
	     BLOCK_FATAL_ERROR))
1556
      {
1557
	if (b_type & (BLOCK_SYNC_ERROR | BLOCK_DELETED))
1241.9.57 by Monty Taylor
Oy. Bigger change than I normally like - but this stuff is all intertwined.
1558
	  errno=HA_ERR_RECORD_CHANGED;
1 by brian
clean slate
1559
	goto err;
1560
      }
1561
      if (flag == 0)				/* First block */
1562
      {
1563
	flag=1;
1564
	if (reclength != block_info.rec_len)
1565
	{
1241.9.57 by Monty Taylor
Oy. Bigger change than I normally like - but this stuff is all intertwined.
1566
	  errno=HA_ERR_RECORD_CHANGED;
1 by brian
clean slate
1567
	  goto err;
1568
	}
1569
      } else if (reclength < block_info.data_len)
1570
      {
1241.9.57 by Monty Taylor
Oy. Bigger change than I normally like - but this stuff is all intertwined.
1571
	errno=HA_ERR_WRONG_IN_RECORD;
1 by brian
clean slate
1572
	goto err;
1573
      }
1574
      reclength-=block_info.data_len;
1575
      if (_mi_cmp_buffer(info->dfile,record,block_info.filepos,
1576
			 block_info.data_len))
1577
      {
1241.9.57 by Monty Taylor
Oy. Bigger change than I normally like - but this stuff is all intertwined.
1578
	errno=HA_ERR_RECORD_CHANGED;
1 by brian
clean slate
1579
	goto err;
1580
      }
1581
      flag=1;
1582
      record+=block_info.data_len;
1583
    }
1584
  }
1241.9.57 by Monty Taylor
Oy. Bigger change than I normally like - but this stuff is all intertwined.
1585
  errno=0;
1 by brian
clean slate
1586
err:
1587
  if (buffer != info->rec_buff)
656.1.1 by Monty Taylor
OOOh doggie. Got rid of my_alloca.
1588
    free((unsigned char*) buffer);
1241.9.57 by Monty Taylor
Oy. Bigger change than I normally like - but this stuff is all intertwined.
1589
  return(errno);
1 by brian
clean slate
1590
}
1591
1592
1593
	/* Compare file to buffert */
1594
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
1595
static int _mi_cmp_buffer(int file, const unsigned char *buff, internal::my_off_t filepos,
482 by Brian Aker
Remove uint.
1596
			  uint32_t length)
1 by brian
clean slate
1597
{
482 by Brian Aker
Remove uint.
1598
  uint32_t next_length;
481 by Brian Aker
Remove all of uchar.
1599
  unsigned char temp_buff[IO_SIZE*2];
1 by brian
clean slate
1600
1601
  next_length= IO_SIZE*2 - (uint) (filepos & (IO_SIZE-1));
1602
1603
  while (length > IO_SIZE*2)
1604
  {
1605
    if (my_pread(file,temp_buff,next_length,filepos, MYF(MY_NABP)) ||
1606
	memcmp(buff, temp_buff, next_length))
1607
      goto err;
1608
    filepos+=next_length;
1609
    buff+=next_length;
1610
    length-= next_length;
1611
    next_length=IO_SIZE*2;
1612
  }
1613
  if (my_pread(file,temp_buff,length,filepos,MYF(MY_NABP)))
1614
    goto err;
51.1.98 by Jay Pipes
Removed/replaced DBUG symbols and TRUE/FALSE
1615
  return(memcmp(buff,temp_buff,length));
1 by brian
clean slate
1616
err:
51.1.98 by Jay Pipes
Removed/replaced DBUG symbols and TRUE/FALSE
1617
  return(1);
1 by brian
clean slate
1618
}
1619
1620
1621
/*
1622
  Read record from datafile.
1623
1624
  SYNOPSIS
1625
    _mi_read_rnd_dynamic_record()
1626
      info                      MI_INFO pointer to table.
1627
      buf                       Destination for record.
1628
      filepos                   From where to read the record.
1629
      skip_deleted_blocks       If to repeat reading until a non-deleted
1630
                                record is found.
1631
1632
  NOTE
1633
1634
    If a write buffer is active, it needs to be flushed if its contents
1635
    intersects with the record to read. We always check if the position
1636
    of the first byte of the write buffer is lower than the position
1637
    past the last byte to read. In theory this is also true if the write
1638
    buffer is completely below the read segment. That is, if there is no
1639
    intersection. But this case is unusual. We flush anyway. Only if the
1640
    first byte in the write buffer is above the last byte to read, we do
1641
    not flush.
1642
1643
    A dynamic record may need several reads. So this check must be done
1644
    before every read. Reading a dynamic record starts with reading the
1645
    block header. If the record does not fit into the free space of the
1646
    header, the block may be longer than the header. In this case a
1647
    second read is necessary. These one or two reads repeat for every
1648
    part of the record.
1649
1650
  RETURN
1651
    0           OK
1652
    != 0        Error
1653
*/
1654
481 by Brian Aker
Remove all of uchar.
1655
int _mi_read_rnd_dynamic_record(MI_INFO *info, unsigned char *buf,
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
1656
				register internal::my_off_t filepos,
281 by Brian Aker
Converted myisam away from my_bool
1657
				bool skip_deleted_blocks)
1 by brian
clean slate
1658
{
1659
  int block_of_record, info_read, save_errno;
482 by Brian Aker
Remove uint.
1660
  uint32_t left_len,b_type;
481 by Brian Aker
Remove all of uchar.
1661
  unsigned char *to= NULL;
1 by brian
clean slate
1662
  MI_BLOCK_INFO block_info;
1663
  MYISAM_SHARE *share=info->s;
1664
1665
  info_read=0;
1666
1667
  if (info->lock_type == F_UNLCK)
1668
  {
1669
    info->tmp_lock_type=F_RDLCK;
1670
  }
1671
  else
1672
    info_read=1;				/* memory-keyinfoblock is ok */
1673
1674
  block_of_record= 0;   /* First block of record is numbered as zero. */
1675
  block_info.second_read= 0;
1676
  left_len=1;
1677
  do
1678
  {
1679
    if (filepos >= info->state->data_file_length)
1680
    {
1681
      if (!info_read)
1682
      {						/* Check if changed */
1683
	info_read=1;
1684
	info->rec_cache.seek_not_done=1;
1685
	if (mi_state_info_read_dsk(share->kfile,&share->state,1))
1686
	  goto panic;
1687
      }
1688
      if (filepos >= info->state->data_file_length)
1689
      {
1241.9.57 by Monty Taylor
Oy. Bigger change than I normally like - but this stuff is all intertwined.
1690
	errno= HA_ERR_END_OF_FILE;
1 by brian
clean slate
1691
	goto err;
1692
      }
1693
    }
1694
    if (info->opt_flag & READ_CACHE_USED)
1695
    {
481 by Brian Aker
Remove all of uchar.
1696
      if (_mi_read_cache(&info->rec_cache,(unsigned char*) block_info.header,filepos,
1 by brian
clean slate
1697
			 sizeof(block_info.header),
1698
			 (!block_of_record && skip_deleted_blocks ?
1699
                          READING_NEXT : 0) | READING_HEADER))
1700
	goto panic;
1701
      b_type=_mi_get_block_info(&block_info,-1,filepos);
1702
    }
1703
    else
1704
    {
1705
      if (info->opt_flag & WRITE_CACHE_USED &&
1706
	  info->rec_cache.pos_in_file < filepos + MI_BLOCK_INFO_HEADER_LENGTH &&
1707
	  flush_io_cache(&info->rec_cache))
1241.9.57 by Monty Taylor
Oy. Bigger change than I normally like - but this stuff is all intertwined.
1708
	return(errno);
1 by brian
clean slate
1709
      info->rec_cache.seek_not_done=1;
1710
      b_type=_mi_get_block_info(&block_info,info->dfile,filepos);
1711
    }
1712
1713
    if (b_type & (BLOCK_DELETED | BLOCK_ERROR | BLOCK_SYNC_ERROR |
1714
		  BLOCK_FATAL_ERROR))
1715
    {
1716
      if ((b_type & (BLOCK_DELETED | BLOCK_SYNC_ERROR))
1717
	  && skip_deleted_blocks)
1718
      {
1719
	filepos=block_info.filepos+block_info.block_len;
1720
	block_info.second_read=0;
1721
	continue;		/* Search after next_record */
1722
      }
1723
      if (b_type & (BLOCK_DELETED | BLOCK_SYNC_ERROR))
1724
      {
1241.9.57 by Monty Taylor
Oy. Bigger change than I normally like - but this stuff is all intertwined.
1725
	errno=HA_ERR_RECORD_DELETED;
1 by brian
clean slate
1726
	info->lastpos=block_info.filepos;
1727
	info->nextpos=block_info.filepos+block_info.block_len;
1728
      }
1729
      goto err;
1730
    }
1731
    if (block_of_record == 0)				/* First block */
1732
    {
1733
      if (block_info.rec_len > (uint) share->base.max_pack_length)
1734
	goto panic;
1735
      info->lastpos=filepos;
1736
      if (share->base.blobs)
1737
      {
1738
	if (!(to= mi_alloc_rec_buff(info, block_info.rec_len,
1739
				    &info->rec_buff)))
1740
	  goto err;
1741
      }
1742
      else
1743
	to= info->rec_buff;
1744
      left_len=block_info.rec_len;
1745
    }
1746
    if (left_len < block_info.data_len)
1747
      goto panic;				/* Wrong linked record */
1748
1749
    /* copy information that is already read */
1750
    {
482 by Brian Aker
Remove uint.
1751
      uint32_t offset=(uint) (block_info.filepos - filepos);
1752
      uint32_t tmp_length= (sizeof(block_info.header) - offset);
1 by brian
clean slate
1753
      filepos=block_info.filepos;
1754
1755
      if (tmp_length > block_info.data_len)
1756
	tmp_length= block_info.data_len;
1757
      if (tmp_length)
1758
      {
212.6.12 by Mats Kindahl
Removing redundant use of casts in MyISAM storage for memcmp(), memcpy(), memset(), and memmove().
1759
	memcpy(to, block_info.header+offset,tmp_length);
1 by brian
clean slate
1760
	block_info.data_len-=tmp_length;
1761
	left_len-=tmp_length;
1762
	to+=tmp_length;
1763
	filepos+=tmp_length;
1764
      }
1765
    }
1766
    /* read rest of record from file */
1767
    if (block_info.data_len)
1768
    {
1769
      if (info->opt_flag & READ_CACHE_USED)
1770
      {
481 by Brian Aker
Remove all of uchar.
1771
	if (_mi_read_cache(&info->rec_cache,(unsigned char*) to,filepos,
1 by brian
clean slate
1772
			   block_info.data_len,
1773
			   (!block_of_record && skip_deleted_blocks) ?
1774
                           READING_NEXT : 0))
1775
	  goto panic;
1776
      }
1777
      else
1778
      {
1779
        if (info->opt_flag & WRITE_CACHE_USED &&
1780
            info->rec_cache.pos_in_file <
1781
            block_info.filepos + block_info.data_len &&
1782
            flush_io_cache(&info->rec_cache))
1783
          goto err;
656.1.39 by Monty Taylor
Removed my_seek, my_tell, my_fwrite, my_fseek.
1784
	/* lseek(info->dfile,filepos,SEEK_SET); */
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
1785
	if (internal::my_read(info->dfile,(unsigned char*) to,block_info.data_len,MYF(MY_NABP)))
1 by brian
clean slate
1786
	{
1241.9.57 by Monty Taylor
Oy. Bigger change than I normally like - but this stuff is all intertwined.
1787
	  if (errno == -1)
1788
	    errno= HA_ERR_WRONG_IN_RECORD;	/* Unexpected end of file */
1 by brian
clean slate
1789
	  goto err;
1790
	}
1791
      }
1792
    }
1793
    /*
1794
      Increment block-of-record counter. If it was the first block,
1795
      remember the position behind the block for the next call.
1796
    */
1797
    if (block_of_record++ == 0)
1798
    {
1799
      info->nextpos= block_info.filepos + block_info.block_len;
1800
      skip_deleted_blocks= 0;
1801
    }
1802
    left_len-=block_info.data_len;
1803
    to+=block_info.data_len;
1804
    filepos=block_info.next_filepos;
1805
  } while (left_len);
1806
1807
  info->update|= HA_STATE_AKTIV | HA_STATE_KEY_CHANGED;
1808
  fast_mi_writeinfo(info);
1809
  if (_mi_rec_unpack(info,buf,info->rec_buff,block_info.rec_len) !=
1810
      MY_FILE_ERROR)
51.1.98 by Jay Pipes
Removed/replaced DBUG symbols and TRUE/FALSE
1811
    return(0);
1241.9.57 by Monty Taylor
Oy. Bigger change than I normally like - but this stuff is all intertwined.
1812
  return(errno);			/* Wrong record */
1 by brian
clean slate
1813
1814
panic:
1241.9.57 by Monty Taylor
Oy. Bigger change than I normally like - but this stuff is all intertwined.
1815
  errno=HA_ERR_WRONG_IN_RECORD;		/* Something is fatal wrong */
1 by brian
clean slate
1816
err:
1241.9.57 by Monty Taylor
Oy. Bigger change than I normally like - but this stuff is all intertwined.
1817
  save_errno=errno;
398.1.10 by Monty Taylor
Actually removed VOID() this time.
1818
  _mi_writeinfo(info,0);
1241.9.57 by Monty Taylor
Oy. Bigger change than I normally like - but this stuff is all intertwined.
1819
  return(errno=save_errno);
1 by brian
clean slate
1820
}
1821
1822
1823
	/* Read and process header from a dynamic-record-file */
1824
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
1825
uint32_t _mi_get_block_info(MI_BLOCK_INFO *info, int file, internal::my_off_t filepos)
1 by brian
clean slate
1826
{
482 by Brian Aker
Remove uint.
1827
  uint32_t return_val=0;
481 by Brian Aker
Remove all of uchar.
1828
  unsigned char *header=info->header;
1 by brian
clean slate
1829
1830
  if (file >= 0)
1831
  {
1832
    /*
1833
      We do not use my_pread() here because we want to have the file
1834
      pointer set to the end of the header after this function.
1835
      my_pread() may leave the file pointer untouched.
1836
    */
656.1.39 by Monty Taylor
Removed my_seek, my_tell, my_fwrite, my_fseek.
1837
    lseek(file,filepos,SEEK_SET);
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
1838
    if (internal::my_read(file, header, sizeof(info->header),MYF(0)) !=
1 by brian
clean slate
1839
	sizeof(info->header))
1840
      goto err;
1841
  }
1842
  if (info->second_read)
1843
  {
1844
    if (info->header[0] <= 6 || info->header[0] == 13)
1845
      return_val=BLOCK_SYNC_ERROR;
1846
  }
1847
  else
1848
  {
1849
    if (info->header[0] > 6 && info->header[0] != 13)
1850
      return_val=BLOCK_SYNC_ERROR;
1851
  }
1852
  info->next_filepos= HA_OFFSET_ERROR; /* Dummy if no next block */
1853
1854
  switch (info->header[0]) {
1855
  case 0:
1856
    if ((info->block_len=(uint) mi_uint3korr(header+1)) <
1857
	MI_MIN_BLOCK_LENGTH ||
1858
	(info->block_len & (MI_DYN_ALIGN_SIZE -1)))
1859
      goto err;
1860
    info->filepos=filepos;
1861
    info->next_filepos=mi_sizekorr(header+4);
1862
    info->prev_filepos=mi_sizekorr(header+12);
1863
#if SIZEOF_OFF_T == 4
1864
    if ((mi_uint4korr(header+4) != 0 &&
365.2.8 by Monty Taylor
More MAX macros.
1865
	 (mi_uint4korr(header+4) != UINT32_MAX ||
1866
	  info->next_filepos != UINT32_MAX) ||
1 by brian
clean slate
1867
	(mi_uint4korr(header+12) != 0 &&
365.2.8 by Monty Taylor
More MAX macros.
1868
	 (mi_uint4korr(header+12) != UINT32_MAX ||
1869
	  info->prev_filepos != UINT32_MAX))
1 by brian
clean slate
1870
      goto err;
1871
#endif
1872
    return return_val | BLOCK_DELETED;		/* Deleted block */
1873
1874
  case 1:
1875
    info->rec_len=info->data_len=info->block_len=mi_uint2korr(header+1);
1876
    info->filepos=filepos+3;
1877
    return return_val | BLOCK_FIRST | BLOCK_LAST;
1878
  case 2:
1879
    info->rec_len=info->data_len=info->block_len=mi_uint3korr(header+1);
1880
    info->filepos=filepos+4;
1881
    return return_val | BLOCK_FIRST | BLOCK_LAST;
1882
1883
  case 13:
1884
    info->rec_len=mi_uint4korr(header+1);
1885
    info->block_len=info->data_len=mi_uint3korr(header+5);
1886
    info->next_filepos=mi_sizekorr(header+8);
1887
    info->second_read=1;
1888
    info->filepos=filepos+16;
1889
    return return_val | BLOCK_FIRST;
1890
1891
  case 3:
1892
    info->rec_len=info->data_len=mi_uint2korr(header+1);
1893
    info->block_len=info->rec_len+ (uint) header[3];
1894
    info->filepos=filepos+4;
1895
    return return_val | BLOCK_FIRST | BLOCK_LAST;
1896
  case 4:
1897
    info->rec_len=info->data_len=mi_uint3korr(header+1);
1898
    info->block_len=info->rec_len+ (uint) header[4];
1899
    info->filepos=filepos+5;
1900
    return return_val | BLOCK_FIRST | BLOCK_LAST;
1901
1902
  case 5:
1903
    info->rec_len=mi_uint2korr(header+1);
1904
    info->block_len=info->data_len=mi_uint2korr(header+3);
1905
    info->next_filepos=mi_sizekorr(header+5);
1906
    info->second_read=1;
1907
    info->filepos=filepos+13;
1908
    return return_val | BLOCK_FIRST;
1909
  case 6:
1910
    info->rec_len=mi_uint3korr(header+1);
1911
    info->block_len=info->data_len=mi_uint3korr(header+4);
1912
    info->next_filepos=mi_sizekorr(header+7);
1913
    info->second_read=1;
1914
    info->filepos=filepos+15;
1915
    return return_val | BLOCK_FIRST;
1916
1917
    /* The following blocks are identical to 1-6 without rec_len */
1918
  case 7:
1919
    info->data_len=info->block_len=mi_uint2korr(header+1);
1920
    info->filepos=filepos+3;
1921
    return return_val | BLOCK_LAST;
1922
  case 8:
1923
    info->data_len=info->block_len=mi_uint3korr(header+1);
1924
    info->filepos=filepos+4;
1925
    return return_val | BLOCK_LAST;
1926
1927
  case 9:
1928
    info->data_len=mi_uint2korr(header+1);
1929
    info->block_len=info->data_len+ (uint) header[3];
1930
    info->filepos=filepos+4;
1931
    return return_val | BLOCK_LAST;
1932
  case 10:
1933
    info->data_len=mi_uint3korr(header+1);
1934
    info->block_len=info->data_len+ (uint) header[4];
1935
    info->filepos=filepos+5;
1936
    return return_val | BLOCK_LAST;
1937
1938
  case 11:
1939
    info->data_len=info->block_len=mi_uint2korr(header+1);
1940
    info->next_filepos=mi_sizekorr(header+3);
1941
    info->second_read=1;
1942
    info->filepos=filepos+11;
1943
    return return_val;
1944
  case 12:
1945
    info->data_len=info->block_len=mi_uint3korr(header+1);
1946
    info->next_filepos=mi_sizekorr(header+4);
1947
    info->second_read=1;
1948
    info->filepos=filepos+12;
1949
    return return_val;
1950
  }
1951
1952
err:
1241.9.57 by Monty Taylor
Oy. Bigger change than I normally like - but this stuff is all intertwined.
1953
  errno=HA_ERR_WRONG_IN_RECORD;	 /* Garbage */
1 by brian
clean slate
1954
  return BLOCK_ERROR;
1955
}