~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;
2385.3.11 by Olaf van der Spek
Move iocache header stuff to iocache.h
720
      if (info->rec_cache.block_write(*record - head_length,
1 by brian
clean slate
721
			 length+extra_length+del_length,filepos))
722
      goto err;
723
    }
2385.3.13 by Olaf van der Spek
Refactor iocache
724
    else if (info->rec_cache.write(*record-head_length, length+extra_length+del_length))
1 by brian
clean slate
725
      goto err;
726
  }
727
  else
728
  {
729
    info->rec_cache.seek_not_done=1;
481 by Brian Aker
Remove all of uchar.
730
    if (info->s->file_write(info,(unsigned char*) *record-head_length,length+extra_length+
1 by brian
clean slate
731
		  del_length,filepos,info->s->write_flag))
732
      goto err;
733
  }
212.6.12 by Mats Kindahl
Removing redundant use of casts in MyISAM storage for memcmp(), memcpy(), memset(), and memmove().
734
  memcpy(record_end, temp, extra_length + del_length);
1 by brian
clean slate
735
  *record=record_end;
736
  *reclength-=(length-head_length);
737
  *flag=6;
738
739
  if (del_length)
740
  {
741
    /* link the next delete block to this */
742
    if (update_backward_delete_link(info, next_delete_block,
743
				    info->s->state.dellink))
744
      goto err;
745
  }
746
51.1.98 by Jay Pipes
Removed/replaced DBUG symbols and TRUE/FALSE
747
  return(0);
1 by brian
clean slate
748
err:
51.1.98 by Jay Pipes
Removed/replaced DBUG symbols and TRUE/FALSE
749
  return(1);
1 by brian
clean slate
750
} /*_mi_write_part_record */
751
752
753
	/* update record from datafile */
754
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
755
static int update_dynamic_record(MI_INFO *info, internal::my_off_t filepos, unsigned char *record,
1 by brian
clean slate
756
				 ulong reclength)
757
{
758
  int flag;
482 by Brian Aker
Remove uint.
759
  uint32_t error;
1 by brian
clean slate
760
  ulong length;
761
  MI_BLOCK_INFO block_info;
762
763
  flag=block_info.second_read=0;
764
  /*
765
     Check if we have enough room for the record.
766
     First we do simplified check to make usual case faster.
767
     Then we do more precise check for the space left.
768
     Though it still is not absolutely precise, as
769
     we always use MI_MAX_DYN_BLOCK_HEADER while it can be
770
     less in the most of the cases.
771
  */
772
773
  /*
774
    compare with just the reclength as we're going
775
    to get some space from the old replaced record
776
  */
777
  if (unlikely(info->s->base.max_data_file_length -
778
        info->state->data_file_length < reclength))
779
  {
780
    /*
781
       let's read the old record's block to find out the length of the
782
       old record
783
    */
784
    if ((error=_mi_get_block_info(&block_info,info->dfile,filepos))
785
        & (BLOCK_DELETED | BLOCK_ERROR | BLOCK_SYNC_ERROR | BLOCK_FATAL_ERROR))
786
    {
787
      if (!(error & BLOCK_FATAL_ERROR))
1241.9.57 by Monty Taylor
Oy. Bigger change than I normally like - but this stuff is all intertwined.
788
        errno=HA_ERR_WRONG_IN_RECORD;
1 by brian
clean slate
789
      goto err;
790
    }
791
792
    /*
793
      if new record isn't longer, we can go on safely
794
    */
795
    if (block_info.rec_len < reclength)
796
    {
797
      if (info->s->base.max_data_file_length - info->state->data_file_length +
798
          info->state->empty - info->state->del * MI_MAX_DYN_BLOCK_HEADER <
799
          reclength - block_info.rec_len + MI_MAX_DYN_BLOCK_HEADER)
800
      {
1241.9.57 by Monty Taylor
Oy. Bigger change than I normally like - but this stuff is all intertwined.
801
        errno=HA_ERR_RECORD_FILE_FULL;
1 by brian
clean slate
802
        goto err;
803
      }
804
    }
805
    block_info.second_read=0;
806
  }
807
808
  while (reclength > 0)
809
  {
810
    if (filepos != info->s->state.dellink)
811
    {
812
      block_info.next_filepos= HA_OFFSET_ERROR;
813
      if ((error=_mi_get_block_info(&block_info,info->dfile,filepos))
814
	  & (BLOCK_DELETED | BLOCK_ERROR | BLOCK_SYNC_ERROR |
815
	     BLOCK_FATAL_ERROR))
816
      {
817
	if (!(error & BLOCK_FATAL_ERROR))
1241.9.57 by Monty Taylor
Oy. Bigger change than I normally like - but this stuff is all intertwined.
818
	  errno=HA_ERR_WRONG_IN_RECORD;
1 by brian
clean slate
819
	goto err;
820
      }
821
      length=(ulong) (block_info.filepos-filepos) + block_info.block_len;
822
      if (length < reclength)
823
      {
482 by Brian Aker
Remove uint.
824
	uint32_t tmp=MY_ALIGN(reclength - length + 3 +
1 by brian
clean slate
825
			  test(reclength >= 65520L),MI_DYN_ALIGN_SIZE);
826
	/* 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.
827
	tmp= min(length+tmp, MI_MAX_BLOCK_LENGTH)-length;
1 by brian
clean slate
828
	/* Check if we can extend this block */
829
	if (block_info.filepos + block_info.block_len ==
830
	    info->state->data_file_length &&
831
	    info->state->data_file_length <
832
	    info->s->base.max_data_file_length-tmp)
833
	{
834
	  /* extend file */
835
	  if (info->nextpos == info->state->data_file_length)
836
	    info->nextpos+= tmp;
837
	  info->state->data_file_length+= tmp;
838
	  info->update|= HA_STATE_WRITE_AT_END | HA_STATE_EXTEND_BLOCK;
839
	  length+=tmp;
840
	}
841
	else if (length < MI_MAX_BLOCK_LENGTH - MI_MIN_BLOCK_LENGTH)
842
	{
843
	  /*
844
	    Check if next block is a deleted block
845
	    Above we have MI_MIN_BLOCK_LENGTH to avoid the problem where
846
	    the next block is so small it can't be splited which could
847
	    casue problems
848
	  */
849
850
	  MI_BLOCK_INFO del_block;
851
	  del_block.second_read=0;
852
	  if (_mi_get_block_info(&del_block,info->dfile,
853
				 block_info.filepos + block_info.block_len) &
854
	      BLOCK_DELETED)
855
	  {
856
	    /* Use; Unlink it and extend the current block */
857
	    if (unlink_deleted_block(info,&del_block))
858
	      goto err;
859
	    if ((length+=del_block.block_len) > MI_MAX_BLOCK_LENGTH)
860
	    {
861
	      /*
862
		New block was too big, link overflow part back to
863
		delete list
864
	      */
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
865
	      internal::my_off_t next_pos;
1 by brian
clean slate
866
	      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.
867
	      set_if_bigger(rest_length, (ulong)MI_MIN_BLOCK_LENGTH);
1 by brian
clean slate
868
	      next_pos= del_block.filepos+ del_block.block_len - rest_length;
869
870
	      if (update_backward_delete_link(info, info->s->state.dellink,
871
					      next_pos))
51.1.98 by Jay Pipes
Removed/replaced DBUG symbols and TRUE/FALSE
872
		return(1);
1 by brian
clean slate
873
874
	      /* create delete link for data that didn't fit into the page */
875
	      del_block.header[0]=0;
876
	      mi_int3store(del_block.header+1, rest_length);
877
	      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:
878
	      memset(del_block.header+12, 255, 8);
481 by Brian Aker
Remove all of uchar.
879
	      if (info->s->file_write(info,(unsigned char*) del_block.header,20, next_pos,
1 by brian
clean slate
880
			    MYF(MY_NABP)))
51.1.98 by Jay Pipes
Removed/replaced DBUG symbols and TRUE/FALSE
881
		return(1);
1 by brian
clean slate
882
	      info->s->state.dellink= next_pos;
883
	      info->s->state.split++;
884
	      info->state->del++;
885
	      info->state->empty+= rest_length;
886
	      length-= rest_length;
887
	    }
888
	  }
889
	}
890
      }
891
    }
892
    else
893
    {
894
      if (_mi_find_writepos(info,reclength,&filepos,&length))
895
	goto err;
896
    }
897
    if (_mi_write_part_record(info,filepos,length,block_info.next_filepos,
898
			      &record,&reclength,&flag))
899
      goto err;
900
    if ((filepos=block_info.next_filepos) == HA_OFFSET_ERROR)
901
    {
902
      /* Start writing data on deleted blocks */
903
      filepos=info->s->state.dellink;
904
    }
905
  }
906
907
  if (block_info.next_filepos != HA_OFFSET_ERROR)
908
    if (delete_dynamic_record(info,block_info.next_filepos,1))
909
      goto err;
51.1.98 by Jay Pipes
Removed/replaced DBUG symbols and TRUE/FALSE
910
  return(0);
1 by brian
clean slate
911
err:
51.1.98 by Jay Pipes
Removed/replaced DBUG symbols and TRUE/FALSE
912
  return(1);
1 by brian
clean slate
913
}
914
915
916
	/* Pack a record. Return new reclength */
917
482 by Brian Aker
Remove uint.
918
uint32_t _mi_rec_pack(MI_INFO *info, register unsigned char *to,
481 by Brian Aker
Remove all of uchar.
919
                  register const unsigned char *from)
1 by brian
clean slate
920
{
921
  uint		length,new_length,flag,bit,i;
481 by Brian Aker
Remove all of uchar.
922
  unsigned char		*pos,*end,*startpos,*packpos;
1 by brian
clean slate
923
  enum en_fieldtype type;
924
  register MI_COLUMNDEF *rec;
925
  MI_BLOB	*blob;
926
927
  flag=0 ; bit=1;
928
  startpos=packpos=to; to+= info->s->base.pack_bits; blob=info->blobs;
929
  rec=info->s->rec;
930
931
  for (i=info->s->base.fields ; i-- > 0; from+= length,rec++)
932
  {
933
    length=(uint) rec->length;
934
    if ((type = (enum en_fieldtype) rec->type) != FIELD_NORMAL)
935
    {
936
      if (type == FIELD_BLOB)
937
      {
938
	if (!blob->length)
939
	  flag|=bit;
940
	else
941
	{
942
	  char *temp_pos;
943
	  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().
944
	  memcpy(to,from,tmp_length);
212.6.3 by Mats Kindahl
Removing deprecated functions from code and replacing them with C99 equivalents:
945
	  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().
946
	  memcpy(to + tmp_length, temp_pos, blob->length);
1 by brian
clean slate
947
	  to+=tmp_length+blob->length;
948
	}
949
	blob++;
950
      }
951
      else if (type == FIELD_SKIP_ZERO)
952
      {
212.6.12 by Mats Kindahl
Removing redundant use of casts in MyISAM storage for memcmp(), memcpy(), memset(), and memmove().
953
	if (memcmp(from,zero_string,length) == 0)
1 by brian
clean slate
954
	  flag|=bit;
955
	else
956
	{
212.6.12 by Mats Kindahl
Removing redundant use of casts in MyISAM storage for memcmp(), memcpy(), memset(), and memmove().
957
	  memcpy(to, from, length);
958
          to+=length;
1 by brian
clean slate
959
	}
960
      }
961
      else if (type == FIELD_SKIP_ENDSPACE ||
962
	       type == FIELD_SKIP_PRESPACE)
963
      {
481 by Brian Aker
Remove all of uchar.
964
	pos= (unsigned char*) from; end= (unsigned char*) from + length;
1 by brian
clean slate
965
	if (type == FIELD_SKIP_ENDSPACE)
966
	{					/* Pack trailing spaces */
967
	  while (end > from && *(end-1) == ' ')
968
	    end--;
969
	}
970
	else
971
	{					/* Pack pref-spaces */
972
	  while (pos < end && *pos == ' ')
973
	    pos++;
974
	}
975
	new_length=(uint) (end-pos);
976
	if (new_length +1 + test(rec->length > 255 && new_length > 127)
977
	    < length)
978
	{
979
	  if (rec->length > 255 && new_length > 127)
980
	  {
481 by Brian Aker
Remove all of uchar.
981
            to[0]= (unsigned char) ((new_length & 127) + 128);
982
            to[1]= (unsigned char) (new_length >> 7);
1 by brian
clean slate
983
            to+=2;
984
          }
985
          else
481 by Brian Aker
Remove all of uchar.
986
            *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().
987
	  memcpy(to, pos, new_length);
988
          to+=new_length;
1 by brian
clean slate
989
	  flag|=bit;
990
	}
991
	else
992
	{
212.6.12 by Mats Kindahl
Removing redundant use of casts in MyISAM storage for memcmp(), memcpy(), memset(), and memmove().
993
	  memcpy(to, from, length);
994
          to+=length;
1 by brian
clean slate
995
	}
996
      }
997
      else if (type == FIELD_VARCHAR)
998
      {
1892.5.2 by Gustaf Thorslund
Replaced macros with functions/templates. Part of blueprint:
999
        uint32_t pack_length= ha_varchar_packlength(rec->length -1);
482 by Brian Aker
Remove uint.
1000
	uint32_t tmp_length;
1 by brian
clean slate
1001
        if (pack_length == 1)
1002
        {
481 by Brian Aker
Remove all of uchar.
1003
          tmp_length= (uint) *(unsigned char*) from;
1 by brian
clean slate
1004
          *to++= *from;
1005
        }
1006
        else
1007
        {
1008
          tmp_length= uint2korr(from);
1009
          store_key_length_inc(to,tmp_length);
1010
        }
212.6.12 by Mats Kindahl
Removing redundant use of casts in MyISAM storage for memcmp(), memcpy(), memset(), and memmove().
1011
        memcpy(to, from+pack_length, tmp_length);
1 by brian
clean slate
1012
        to+= tmp_length;
1013
        continue;
1014
      }
1015
      else
1016
      {
212.6.12 by Mats Kindahl
Removing redundant use of casts in MyISAM storage for memcmp(), memcpy(), memset(), and memmove().
1017
	memcpy(to, from, length);
1018
        to+=length;
1 by brian
clean slate
1019
	continue;				/* Normal field */
1020
      }
1021
      if ((bit= bit << 1) >= 256)
1022
      {
481 by Brian Aker
Remove all of uchar.
1023
        *packpos++= (unsigned char) flag;
1 by brian
clean slate
1024
	bit=1; flag=0;
1025
      }
1026
    }
1027
    else
1028
    {
212.6.12 by Mats Kindahl
Removing redundant use of casts in MyISAM storage for memcmp(), memcpy(), memset(), and memmove().
1029
      memcpy(to, from, length);
1030
      to+=length;
1 by brian
clean slate
1031
    }
1032
  }
1033
  if (bit != 1)
481 by Brian Aker
Remove all of uchar.
1034
    *packpos= (unsigned char) flag;
1 by brian
clean slate
1035
  if (info->s->calc_checksum)
481 by Brian Aker
Remove all of uchar.
1036
    *to++= (unsigned char) info->checksum;
51.1.98 by Jay Pipes
Removed/replaced DBUG symbols and TRUE/FALSE
1037
  return((uint) (to-startpos));
1 by brian
clean slate
1038
} /* _mi_rec_pack */
1039
1040
1041
1042
/*
1043
  Check if a record was correctly packed. Used only by myisamchk
1044
  Returns 0 if record is ok.
1045
*/
1046
481 by Brian Aker
Remove all of uchar.
1047
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
1048
                      ulong packed_length, bool with_checksum)
1 by brian
clean slate
1049
{
1050
  uint		length,new_length,flag,bit,i;
481 by Brian Aker
Remove all of uchar.
1051
  unsigned char		*pos,*end,*packpos,*to;
1 by brian
clean slate
1052
  enum en_fieldtype type;
1053
  register MI_COLUMNDEF *rec;
1054
1055
  packpos=rec_buff; to= rec_buff+info->s->base.pack_bits;
1056
  rec=info->s->rec;
1057
  flag= *packpos; bit=1;
1058
1059
  for (i=info->s->base.fields ; i-- > 0; record+= length, rec++)
1060
  {
1061
    length=(uint) rec->length;
1062
    if ((type = (enum en_fieldtype) rec->type) != FIELD_NORMAL)
1063
    {
1064
      if (type == FIELD_BLOB)
1065
      {
482 by Brian Aker
Remove uint.
1066
	uint32_t blob_length=
1 by brian
clean slate
1067
	  _mi_calc_blob_length(length-portable_sizeof_char_ptr,record);
1068
	if (!blob_length && !(flag & bit))
1069
	  goto err;
1070
	if (blob_length)
1071
	  to+=length - portable_sizeof_char_ptr+ blob_length;
1072
      }
1073
      else if (type == FIELD_SKIP_ZERO)
1074
      {
212.6.12 by Mats Kindahl
Removing redundant use of casts in MyISAM storage for memcmp(), memcpy(), memset(), and memmove().
1075
	if (memcmp(record,zero_string,length) == 0)
1 by brian
clean slate
1076
	{
1077
	  if (!(flag & bit))
1078
	    goto err;
1079
	}
1080
	else
1081
	  to+=length;
1082
      }
1083
      else if (type == FIELD_SKIP_ENDSPACE ||
1084
	       type == FIELD_SKIP_PRESPACE)
1085
      {
481 by Brian Aker
Remove all of uchar.
1086
	pos= (unsigned char*) record; end= (unsigned char*) record + length;
1 by brian
clean slate
1087
	if (type == FIELD_SKIP_ENDSPACE)
1088
	{					/* Pack trailing spaces */
1089
	  while (end > record && *(end-1) == ' ')
1090
	    end--;
1091
	}
1092
	else
1093
	{					/* Pack pre-spaces */
1094
	  while (pos < end && *pos == ' ')
1095
	    pos++;
1096
	}
1097
	new_length=(uint) (end-pos);
1098
	if (new_length +1 + test(rec->length > 255 && new_length > 127)
1099
	    < length)
1100
	{
1101
	  if (!(flag & bit))
1102
	    goto err;
1103
	  if (rec->length > 255 && new_length > 127)
1104
	  {
481 by Brian Aker
Remove all of uchar.
1105
            if (to[0] != (unsigned char) ((new_length & 127) + 128) ||
1106
                to[1] != (unsigned char) (new_length >> 7))
1 by brian
clean slate
1107
              goto err;
1108
            to+=2;
1109
          }
481 by Brian Aker
Remove all of uchar.
1110
          else if (*to++ != (unsigned char) new_length)
1 by brian
clean slate
1111
	    goto err;
1112
	  to+=new_length;
1113
	}
1114
	else
1115
	  to+=length;
1116
      }
1117
      else if (type == FIELD_VARCHAR)
1118
      {
1892.5.2 by Gustaf Thorslund
Replaced macros with functions/templates. Part of blueprint:
1119
        uint32_t pack_length= ha_varchar_packlength(rec->length -1);
482 by Brian Aker
Remove uint.
1120
	uint32_t tmp_length;
1 by brian
clean slate
1121
        if (pack_length == 1)
1122
        {
481 by Brian Aker
Remove all of uchar.
1123
          tmp_length= (uint) *(unsigned char*) record;
1 by brian
clean slate
1124
          to+= 1+ tmp_length;
1125
          continue;
1126
        }
1127
        else
1128
        {
1129
          tmp_length= uint2korr(record);
1130
          to+= get_pack_length(tmp_length)+tmp_length;
1131
        }
1132
        continue;
1133
      }
1134
      else
1135
      {
1136
	to+=length;
1137
	continue;				/* Normal field */
1138
      }
1139
      if ((bit= bit << 1) >= 256)
1140
      {
1141
	flag= *++packpos;
1142
	bit=1;
1143
      }
1144
    }
1145
    else
1146
      to+= length;
1147
  }
1148
  if (packed_length != (uint) (to - rec_buff) + test(info->s->calc_checksum) ||
1149
      (bit != 1 && (flag & ~(bit - 1))))
1150
    goto err;
481 by Brian Aker
Remove all of uchar.
1151
  if (with_checksum && ((unsigned char) info->checksum != (unsigned char) *to))
1 by brian
clean slate
1152
  {
1153
    goto err;
1154
  }
51.1.98 by Jay Pipes
Removed/replaced DBUG symbols and TRUE/FALSE
1155
  return(0);
1 by brian
clean slate
1156
1157
err:
51.1.98 by Jay Pipes
Removed/replaced DBUG symbols and TRUE/FALSE
1158
  return(1);
1 by brian
clean slate
1159
}
1160
1161
1162
1163
	/* Unpacks a record */
1241.9.57 by Monty Taylor
Oy. Bigger change than I normally like - but this stuff is all intertwined.
1164
	/* Returns -1 and errno =HA_ERR_RECORD_DELETED if reclength isn't */
1 by brian
clean slate
1165
	/* right. Returns reclength (>0) if ok */
1166
481 by Brian Aker
Remove all of uchar.
1167
ulong _mi_rec_unpack(register MI_INFO *info, register unsigned char *to, unsigned char *from,
1 by brian
clean slate
1168
		     ulong found_length)
1169
{
482 by Brian Aker
Remove uint.
1170
  uint32_t flag,bit,length,rec_length,min_pack_length;
1 by brian
clean slate
1171
  enum en_fieldtype type;
481 by Brian Aker
Remove all of uchar.
1172
  unsigned char *from_end,*to_end,*packpos;
1 by brian
clean slate
1173
  register MI_COLUMNDEF *rec,*end_field;
1174
1175
  to_end=to + info->s->base.reclength;
1176
  from_end=from+found_length;
481 by Brian Aker
Remove all of uchar.
1177
  flag= (unsigned char) *from; bit=1; packpos=from;
1 by brian
clean slate
1178
  if (found_length < info->s->base.min_pack_length)
1179
    goto err;
1180
  from+= info->s->base.pack_bits;
1181
  min_pack_length=info->s->base.min_pack_length - info->s->base.pack_bits;
1182
1183
  for (rec=info->s->rec , end_field=rec+info->s->base.fields ;
1184
       rec < end_field ; to+= rec_length, rec++)
1185
  {
1186
    rec_length=rec->length;
1187
    if ((type = (enum en_fieldtype) rec->type) != FIELD_NORMAL &&
1188
	(type != FIELD_CHECK))
1189
    {
1190
      if (type == FIELD_VARCHAR)
1191
      {
1892.5.2 by Gustaf Thorslund
Replaced macros with functions/templates. Part of blueprint:
1192
        uint32_t pack_length= ha_varchar_packlength(rec_length-1);
1 by brian
clean slate
1193
        if (pack_length == 1)
1194
        {
481 by Brian Aker
Remove all of uchar.
1195
          length= (uint) *(unsigned char*) from;
1 by brian
clean slate
1196
          if (length > rec_length-1)
1197
            goto err;
1198
          *to= *from++;
1199
        }
1200
        else
1201
        {
1202
          get_key_length(length, from);
1203
          if (length > rec_length-2)
1204
            goto err;
1205
          int2store(to,length);
1206
        }
1207
        if (from+length > from_end)
1208
          goto err;
1209
        memcpy(to+pack_length, from, length);
1210
        from+= length;
1211
        min_pack_length--;
1212
        continue;
1213
      }
1214
      if (flag & bit)
1215
      {
1216
	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().
1217
	  memset(to, 0, rec_length);
1 by brian
clean slate
1218
	else if (type == FIELD_SKIP_ENDSPACE ||
1219
		 type == FIELD_SKIP_PRESPACE)
1220
	{
1221
	  if (rec->length > 255 && *from & 128)
1222
	  {
1223
	    if (from + 1 >= from_end)
1224
	      goto err;
481 by Brian Aker
Remove all of uchar.
1225
	    length= (*from & 127)+ ((uint) (unsigned char) *(from+1) << 7); from+=2;
1 by brian
clean slate
1226
	  }
1227
	  else
1228
	  {
1229
	    if (from == from_end)
1230
	      goto err;
481 by Brian Aker
Remove all of uchar.
1231
	    length= (unsigned char) *from++;
1 by brian
clean slate
1232
	  }
1233
	  min_pack_length--;
1234
	  if (length >= rec_length ||
1235
	      min_pack_length + length > (uint) (from_end - from))
1236
	    goto err;
1237
	  if (type == FIELD_SKIP_ENDSPACE)
1238
	  {
212.6.12 by Mats Kindahl
Removing redundant use of casts in MyISAM storage for memcmp(), memcpy(), memset(), and memmove().
1239
	    memcpy(to, from, length);
1240
	    memset(to+length, ' ', rec_length-length);
1 by brian
clean slate
1241
	  }
1242
	  else
1243
	  {
212.6.12 by Mats Kindahl
Removing redundant use of casts in MyISAM storage for memcmp(), memcpy(), memset(), and memmove().
1244
	    memset(to, ' ', rec_length-length);
1245
	    memcpy(to + rec_length - length, from, length);
1 by brian
clean slate
1246
	  }
1247
	  from+=length;
1248
	}
1249
      }
1250
      else if (type == FIELD_BLOB)
1251
      {
482 by Brian Aker
Remove uint.
1252
	uint32_t size_length=rec_length- portable_sizeof_char_ptr;
1 by brian
clean slate
1253
	ulong blob_length=_mi_calc_blob_length(size_length,from);
1254
        ulong from_left= (ulong) (from_end - from);
1255
        if (from_left < size_length ||
1256
            from_left - size_length < blob_length ||
1257
            from_left - size_length - blob_length < min_pack_length)
1258
          goto err;
212.6.12 by Mats Kindahl
Removing redundant use of casts in MyISAM storage for memcmp(), memcpy(), memset(), and memmove().
1259
	memcpy(to, from, size_length);
1 by brian
clean slate
1260
	from+=size_length;
212.6.12 by Mats Kindahl
Removing redundant use of casts in MyISAM storage for memcmp(), memcpy(), memset(), and memmove().
1261
	memcpy(to+size_length, &from, sizeof(char*));
1 by brian
clean slate
1262
	from+=blob_length;
1263
      }
1264
      else
1265
      {
1266
	if (type == FIELD_SKIP_ENDSPACE || type == FIELD_SKIP_PRESPACE)
1267
	  min_pack_length--;
1268
	if (min_pack_length + rec_length > (uint) (from_end - from))
1269
	  goto err;
212.6.12 by Mats Kindahl
Removing redundant use of casts in MyISAM storage for memcmp(), memcpy(), memset(), and memmove().
1270
        memcpy(to, from, rec_length);
1271
        from+=rec_length;
1 by brian
clean slate
1272
      }
1273
      if ((bit= bit << 1) >= 256)
1274
      {
481 by Brian Aker
Remove all of uchar.
1275
	flag= (unsigned char) *++packpos; bit=1;
1 by brian
clean slate
1276
      }
1277
    }
1278
    else
1279
    {
1280
      if (min_pack_length > (uint) (from_end - from))
1281
	goto err;
1282
      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().
1283
      memcpy(to, from, rec_length);
1 by brian
clean slate
1284
      from+=rec_length;
1285
    }
1286
  }
1287
  if (info->s->calc_checksum)
1288
    from++;
1289
  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
1290
    return(found_length);
1 by brian
clean slate
1291
1292
err:
1241.9.57 by Monty Taylor
Oy. Bigger change than I normally like - but this stuff is all intertwined.
1293
  errno= HA_ERR_WRONG_IN_RECORD;
51.1.98 by Jay Pipes
Removed/replaced DBUG symbols and TRUE/FALSE
1294
  return(MY_FILE_ERROR);
1 by brian
clean slate
1295
} /* _mi_rec_unpack */
1296
1297
1298
	/* Calc length of blob. Update info in blobs->length */
1299
481 by Brian Aker
Remove all of uchar.
1300
ulong _my_calc_total_blob_length(MI_INFO *info, const unsigned char *record)
1 by brian
clean slate
1301
{
1302
  ulong length;
1303
  MI_BLOB *blob,*end;
1304
1305
  for (length=0, blob= info->blobs, end=blob+info->s->base.blobs ;
1306
       blob != end;
1307
       blob++)
1308
  {
1309
    blob->length=_mi_calc_blob_length(blob->pack_length,record + blob->offset);
1310
    length+=blob->length;
1311
  }
1312
  return length;
1313
}
1314
1315
482 by Brian Aker
Remove uint.
1316
ulong _mi_calc_blob_length(uint32_t length, const unsigned char *pos)
1 by brian
clean slate
1317
{
1318
  switch (length) {
1319
  case 1:
481 by Brian Aker
Remove all of uchar.
1320
    return (uint) (unsigned char) *pos;
1 by brian
clean slate
1321
  case 2:
1322
    return (uint) uint2korr(pos);
1323
  case 3:
1324
    return uint3korr(pos);
1325
  case 4:
1326
    return uint4korr(pos);
1327
  default:
1328
    break;
1329
  }
1330
  return 0; /* Impossible */
1331
}
1332
1333
482 by Brian Aker
Remove uint.
1334
void _my_store_blob_length(unsigned char *pos,uint32_t pack_length,uint32_t length)
1 by brian
clean slate
1335
{
1336
  switch (pack_length) {
1337
  case 1:
481 by Brian Aker
Remove all of uchar.
1338
    *pos= (unsigned char) length;
1 by brian
clean slate
1339
    break;
1340
  case 2:
1341
    int2store(pos,length);
1342
    break;
1343
  case 3:
1344
    int3store(pos,length);
1345
    break;
1346
  case 4:
1347
    int4store(pos,length);
1348
  default:
1349
    break;
1350
  }
1351
  return;
1352
}
1353
1354
1355
/*
1356
  Read record from datafile.
1357
1358
  SYNOPSIS
1359
    _mi_read_dynamic_record()
1360
      info                      MI_INFO pointer to table.
1361
      filepos                   From where to read the record.
1362
      buf                       Destination for record.
1363
1364
  NOTE
1365
1366
    If a write buffer is active, it needs to be flushed if its contents
1367
    intersects with the record to read. We always check if the position
1368
    of the first byte of the write buffer is lower than the position
1369
    past the last byte to read. In theory this is also true if the write
1370
    buffer is completely below the read segment. That is, if there is no
1371
    intersection. But this case is unusual. We flush anyway. Only if the
1372
    first byte in the write buffer is above the last byte to read, we do
1373
    not flush.
1374
1375
    A dynamic record may need several reads. So this check must be done
1376
    before every read. Reading a dynamic record starts with reading the
1377
    block header. If the record does not fit into the free space of the
1378
    header, the block may be longer than the header. In this case a
1379
    second read is necessary. These one or two reads repeat for every
1380
    part of the record.
1381
1382
  RETURN
1383
    0           OK
1384
    -1          Error
1385
*/
1386
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
1387
int _mi_read_dynamic_record(MI_INFO *info, internal::my_off_t filepos, unsigned char *buf)
1 by brian
clean slate
1388
{
1389
  int block_of_record;
482 by Brian Aker
Remove uint.
1390
  uint32_t b_type, left_length= 0;
481 by Brian Aker
Remove all of uchar.
1391
  unsigned char *to= NULL;
1 by brian
clean slate
1392
  MI_BLOCK_INFO block_info;
1241.9.1 by Monty Taylor
Removed global.h. Fixed all the headers.
1393
  int file;
1 by brian
clean slate
1394
1395
  if (filepos != HA_OFFSET_ERROR)
1396
  {
1397
    file=info->dfile;
1398
    block_of_record= 0;   /* First block of record is numbered as zero. */
1399
    block_info.second_read= 0;
1400
    do
1401
    {
1402
      /* A corrupted table can have wrong pointers. (Bug# 19835) */
1403
      if (filepos == HA_OFFSET_ERROR)
1404
        goto panic;
1405
      if (info->opt_flag & WRITE_CACHE_USED &&
1406
	  info->rec_cache.pos_in_file < filepos + MI_BLOCK_INFO_HEADER_LENGTH &&
2385.3.9 by Olaf van der Spek
Move flush() into iocache
1407
	  info->rec_cache.flush())
1 by brian
clean slate
1408
	goto err;
1409
      info->rec_cache.seek_not_done=1;
1410
      if ((b_type= _mi_get_block_info(&block_info, file, filepos))
1411
	  & (BLOCK_DELETED | BLOCK_ERROR | BLOCK_SYNC_ERROR |
1412
	     BLOCK_FATAL_ERROR))
1413
      {
1414
	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.
1415
	  errno=HA_ERR_RECORD_DELETED;
1 by brian
clean slate
1416
	goto err;
1417
      }
1418
      if (block_of_record++ == 0)			/* First block */
1419
      {
1420
	if (block_info.rec_len > (uint) info->s->base.max_pack_length)
1421
	  goto panic;
1422
	if (info->s->base.blobs)
1423
	{
1424
	  if (!(to=mi_alloc_rec_buff(info, block_info.rec_len,
1425
				     &info->rec_buff)))
1426
	    goto err;
1427
	}
1428
	else
1429
	  to= info->rec_buff;
1430
	left_length=block_info.rec_len;
1431
      }
1432
      if (left_length < block_info.data_len || ! block_info.data_len)
1433
	goto panic;			/* Wrong linked record */
1434
      /* copy information that is already read */
1435
      {
482 by Brian Aker
Remove uint.
1436
        uint32_t offset= (uint) (block_info.filepos - filepos);
1437
        uint32_t prefetch_len= (sizeof(block_info.header) - offset);
1 by brian
clean slate
1438
        filepos+= sizeof(block_info.header);
1439
1440
        if (prefetch_len > block_info.data_len)
1441
          prefetch_len= block_info.data_len;
1442
        if (prefetch_len)
1443
        {
212.6.12 by Mats Kindahl
Removing redundant use of casts in MyISAM storage for memcmp(), memcpy(), memset(), and memmove().
1444
          memcpy(to, block_info.header + offset, prefetch_len);
1 by brian
clean slate
1445
          block_info.data_len-= prefetch_len;
1446
          left_length-= prefetch_len;
1447
          to+= prefetch_len;
1448
        }
1449
      }
1450
      /* read rest of record from file */
1451
      if (block_info.data_len)
1452
      {
1453
        if (info->opt_flag & WRITE_CACHE_USED &&
1454
            info->rec_cache.pos_in_file < filepos + block_info.data_len &&
2385.3.9 by Olaf van der Spek
Move flush() into iocache
1455
            info->rec_cache.flush())
1 by brian
clean slate
1456
          goto err;
1457
        /*
1458
          What a pity that this method is not called 'file_pread' and that
1459
          there is no equivalent without seeking. We are at the right
1460
          position already. :(
1461
        */
481 by Brian Aker
Remove all of uchar.
1462
        if (info->s->file_read(info, (unsigned char*) to, block_info.data_len,
1 by brian
clean slate
1463
                               filepos, MYF(MY_NABP)))
1464
          goto panic;
1465
        left_length-=block_info.data_len;
1466
        to+=block_info.data_len;
1467
      }
1468
      filepos= block_info.next_filepos;
1469
    } while (left_length);
1470
1471
    info->update|= HA_STATE_AKTIV;	/* We have a aktive record */
1472
    fast_mi_writeinfo(info);
51.1.98 by Jay Pipes
Removed/replaced DBUG symbols and TRUE/FALSE
1473
    return(_mi_rec_unpack(info,buf,info->rec_buff,block_info.rec_len) !=
1 by brian
clean slate
1474
		MY_FILE_ERROR ? 0 : -1);
1475
  }
1476
  fast_mi_writeinfo(info);
51.1.98 by Jay Pipes
Removed/replaced DBUG symbols and TRUE/FALSE
1477
  return(-1);			/* Wrong data to read */
1 by brian
clean slate
1478
1479
panic:
1241.9.57 by Monty Taylor
Oy. Bigger change than I normally like - but this stuff is all intertwined.
1480
  errno=HA_ERR_WRONG_IN_RECORD;
1 by brian
clean slate
1481
err:
398.1.10 by Monty Taylor
Actually removed VOID() this time.
1482
  _mi_writeinfo(info,0);
51.1.98 by Jay Pipes
Removed/replaced DBUG symbols and TRUE/FALSE
1483
  return(-1);
1 by brian
clean slate
1484
}
1485
1486
	/* compare unique constraint between stored rows */
1487
1488
int _mi_cmp_dynamic_unique(MI_INFO *info, MI_UNIQUEDEF *def,
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
1489
			   const unsigned char *record, internal::my_off_t pos)
1 by brian
clean slate
1490
{
481 by Brian Aker
Remove all of uchar.
1491
  unsigned char *rec_buff,*old_record;
1 by brian
clean slate
1492
  int error;
1493
960.2.2 by Monty Taylor
Moved MyISAM files to C++ so we can continue to consolidate code.
1494
  if (!(old_record=(unsigned char *)malloc(info->s->base.reclength)))
51.1.98 by Jay Pipes
Removed/replaced DBUG symbols and TRUE/FALSE
1495
    return(1);
1 by brian
clean slate
1496
1497
  /* Don't let the compare destroy blobs that may be in use */
1498
  rec_buff=info->rec_buff;
1499
  if (info->s->base.blobs)
1500
    info->rec_buff=0;
1501
  error=_mi_read_dynamic_record(info,pos,old_record);
1502
  if (!error)
1503
    error=mi_unique_comp(def, record, old_record, def->null_are_equal);
1504
  if (info->s->base.blobs)
1505
  {
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.
1506
    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
1507
    free(rec_buff_ptr);
1 by brian
clean slate
1508
    info->rec_buff=rec_buff;
1509
  }
656.1.1 by Monty Taylor
OOOh doggie. Got rid of my_alloca.
1510
  free(old_record);
51.1.98 by Jay Pipes
Removed/replaced DBUG symbols and TRUE/FALSE
1511
  return(error);
1 by brian
clean slate
1512
}
1513
1514
1515
	/* Compare of record one disk with packed record in memory */
1516
481 by Brian Aker
Remove all of uchar.
1517
int _mi_cmp_dynamic_record(register MI_INFO *info, register const unsigned char *record)
1 by brian
clean slate
1518
{
482 by Brian Aker
Remove uint.
1519
  uint32_t flag,reclength,b_type;
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
1520
  internal::my_off_t filepos;
481 by Brian Aker
Remove all of uchar.
1521
  unsigned char *buffer;
1 by brian
clean slate
1522
  MI_BLOCK_INFO block_info;
1523
1524
  if (info->opt_flag & WRITE_CACHE_USED)
1525
  {
1526
    info->update&= ~(HA_STATE_WRITE_AT_END | HA_STATE_EXTEND_BLOCK);
2385.3.9 by Olaf van der Spek
Move flush() into iocache
1527
    if (info->rec_cache.flush())
51.1.98 by Jay Pipes
Removed/replaced DBUG symbols and TRUE/FALSE
1528
      return(-1);
1 by brian
clean slate
1529
  }
1530
  info->rec_cache.seek_not_done=1;
1531
1532
	/* If nobody have touched the database we don't have to test rec */
1533
1534
  buffer=info->rec_buff;
1535
  if ((info->opt_flag & READ_CHECK_USED))
1536
  {						/* If check isn't disabled  */
1537
    if (info->s->base.blobs)
1538
    {
656.1.1 by Monty Taylor
OOOh doggie. Got rid of my_alloca.
1539
      if (!(buffer=(unsigned char*) malloc(info->s->base.pack_reclength+
1 by brian
clean slate
1540
				     _my_calc_total_blob_length(info,record))))
51.1.98 by Jay Pipes
Removed/replaced DBUG symbols and TRUE/FALSE
1541
	return(-1);
1 by brian
clean slate
1542
    }
1543
    reclength=_mi_rec_pack(info,buffer,record);
1544
    record= buffer;
1545
1546
    filepos=info->lastpos;
1547
    flag=block_info.second_read=0;
1548
    block_info.next_filepos=filepos;
1549
    while (reclength > 0)
1550
    {
1551
      if ((b_type=_mi_get_block_info(&block_info,info->dfile,
1552
				    block_info.next_filepos))
1553
	  & (BLOCK_DELETED | BLOCK_ERROR | BLOCK_SYNC_ERROR |
1554
	     BLOCK_FATAL_ERROR))
1555
      {
1556
	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.
1557
	  errno=HA_ERR_RECORD_CHANGED;
1 by brian
clean slate
1558
	goto err;
1559
      }
1560
      if (flag == 0)				/* First block */
1561
      {
1562
	flag=1;
1563
	if (reclength != block_info.rec_len)
1564
	{
1241.9.57 by Monty Taylor
Oy. Bigger change than I normally like - but this stuff is all intertwined.
1565
	  errno=HA_ERR_RECORD_CHANGED;
1 by brian
clean slate
1566
	  goto err;
1567
	}
1568
      } else if (reclength < block_info.data_len)
1569
      {
1241.9.57 by Monty Taylor
Oy. Bigger change than I normally like - but this stuff is all intertwined.
1570
	errno=HA_ERR_WRONG_IN_RECORD;
1 by brian
clean slate
1571
	goto err;
1572
      }
1573
      reclength-=block_info.data_len;
1574
      if (_mi_cmp_buffer(info->dfile,record,block_info.filepos,
1575
			 block_info.data_len))
1576
      {
1241.9.57 by Monty Taylor
Oy. Bigger change than I normally like - but this stuff is all intertwined.
1577
	errno=HA_ERR_RECORD_CHANGED;
1 by brian
clean slate
1578
	goto err;
1579
      }
1580
      flag=1;
1581
      record+=block_info.data_len;
1582
    }
1583
  }
1241.9.57 by Monty Taylor
Oy. Bigger change than I normally like - but this stuff is all intertwined.
1584
  errno=0;
1 by brian
clean slate
1585
err:
1586
  if (buffer != info->rec_buff)
656.1.1 by Monty Taylor
OOOh doggie. Got rid of my_alloca.
1587
    free((unsigned char*) buffer);
1241.9.57 by Monty Taylor
Oy. Bigger change than I normally like - but this stuff is all intertwined.
1588
  return(errno);
1 by brian
clean slate
1589
}
1590
1591
1592
	/* Compare file to buffert */
1593
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
1594
static int _mi_cmp_buffer(int file, const unsigned char *buff, internal::my_off_t filepos,
482 by Brian Aker
Remove uint.
1595
			  uint32_t length)
1 by brian
clean slate
1596
{
482 by Brian Aker
Remove uint.
1597
  uint32_t next_length;
481 by Brian Aker
Remove all of uchar.
1598
  unsigned char temp_buff[IO_SIZE*2];
1 by brian
clean slate
1599
1600
  next_length= IO_SIZE*2 - (uint) (filepos & (IO_SIZE-1));
1601
1602
  while (length > IO_SIZE*2)
1603
  {
1604
    if (my_pread(file,temp_buff,next_length,filepos, MYF(MY_NABP)) ||
1605
	memcmp(buff, temp_buff, next_length))
1606
      goto err;
1607
    filepos+=next_length;
1608
    buff+=next_length;
1609
    length-= next_length;
1610
    next_length=IO_SIZE*2;
1611
  }
1612
  if (my_pread(file,temp_buff,length,filepos,MYF(MY_NABP)))
1613
    goto err;
51.1.98 by Jay Pipes
Removed/replaced DBUG symbols and TRUE/FALSE
1614
  return(memcmp(buff,temp_buff,length));
1 by brian
clean slate
1615
err:
51.1.98 by Jay Pipes
Removed/replaced DBUG symbols and TRUE/FALSE
1616
  return(1);
1 by brian
clean slate
1617
}
1618
1619
1620
/*
1621
  Read record from datafile.
1622
1623
  SYNOPSIS
1624
    _mi_read_rnd_dynamic_record()
1625
      info                      MI_INFO pointer to table.
1626
      buf                       Destination for record.
1627
      filepos                   From where to read the record.
1628
      skip_deleted_blocks       If to repeat reading until a non-deleted
1629
                                record is found.
1630
1631
  NOTE
1632
1633
    If a write buffer is active, it needs to be flushed if its contents
1634
    intersects with the record to read. We always check if the position
1635
    of the first byte of the write buffer is lower than the position
1636
    past the last byte to read. In theory this is also true if the write
1637
    buffer is completely below the read segment. That is, if there is no
1638
    intersection. But this case is unusual. We flush anyway. Only if the
1639
    first byte in the write buffer is above the last byte to read, we do
1640
    not flush.
1641
1642
    A dynamic record may need several reads. So this check must be done
1643
    before every read. Reading a dynamic record starts with reading the
1644
    block header. If the record does not fit into the free space of the
1645
    header, the block may be longer than the header. In this case a
1646
    second read is necessary. These one or two reads repeat for every
1647
    part of the record.
1648
1649
  RETURN
1650
    0           OK
1651
    != 0        Error
1652
*/
1653
481 by Brian Aker
Remove all of uchar.
1654
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.
1655
				register internal::my_off_t filepos,
281 by Brian Aker
Converted myisam away from my_bool
1656
				bool skip_deleted_blocks)
1 by brian
clean slate
1657
{
1658
  int block_of_record, info_read, save_errno;
482 by Brian Aker
Remove uint.
1659
  uint32_t left_len,b_type;
481 by Brian Aker
Remove all of uchar.
1660
  unsigned char *to= NULL;
1 by brian
clean slate
1661
  MI_BLOCK_INFO block_info;
1662
  MYISAM_SHARE *share=info->s;
1663
1664
  info_read=0;
1665
1666
  if (info->lock_type == F_UNLCK)
1667
  {
1668
    info->tmp_lock_type=F_RDLCK;
1669
  }
1670
  else
1671
    info_read=1;				/* memory-keyinfoblock is ok */
1672
1673
  block_of_record= 0;   /* First block of record is numbered as zero. */
1674
  block_info.second_read= 0;
1675
  left_len=1;
1676
  do
1677
  {
1678
    if (filepos >= info->state->data_file_length)
1679
    {
1680
      if (!info_read)
1681
      {						/* Check if changed */
1682
	info_read=1;
1683
	info->rec_cache.seek_not_done=1;
1684
	if (mi_state_info_read_dsk(share->kfile,&share->state,1))
1685
	  goto panic;
1686
      }
1687
      if (filepos >= info->state->data_file_length)
1688
      {
1241.9.57 by Monty Taylor
Oy. Bigger change than I normally like - but this stuff is all intertwined.
1689
	errno= HA_ERR_END_OF_FILE;
1 by brian
clean slate
1690
	goto err;
1691
      }
1692
    }
1693
    if (info->opt_flag & READ_CACHE_USED)
1694
    {
481 by Brian Aker
Remove all of uchar.
1695
      if (_mi_read_cache(&info->rec_cache,(unsigned char*) block_info.header,filepos,
1 by brian
clean slate
1696
			 sizeof(block_info.header),
1697
			 (!block_of_record && skip_deleted_blocks ?
1698
                          READING_NEXT : 0) | READING_HEADER))
1699
	goto panic;
1700
      b_type=_mi_get_block_info(&block_info,-1,filepos);
1701
    }
1702
    else
1703
    {
1704
      if (info->opt_flag & WRITE_CACHE_USED &&
1705
	  info->rec_cache.pos_in_file < filepos + MI_BLOCK_INFO_HEADER_LENGTH &&
2385.3.9 by Olaf van der Spek
Move flush() into iocache
1706
	  info->rec_cache.flush())
1241.9.57 by Monty Taylor
Oy. Bigger change than I normally like - but this stuff is all intertwined.
1707
	return(errno);
1 by brian
clean slate
1708
      info->rec_cache.seek_not_done=1;
1709
      b_type=_mi_get_block_info(&block_info,info->dfile,filepos);
1710
    }
1711
1712
    if (b_type & (BLOCK_DELETED | BLOCK_ERROR | BLOCK_SYNC_ERROR |
1713
		  BLOCK_FATAL_ERROR))
1714
    {
1715
      if ((b_type & (BLOCK_DELETED | BLOCK_SYNC_ERROR))
1716
	  && skip_deleted_blocks)
1717
      {
1718
	filepos=block_info.filepos+block_info.block_len;
1719
	block_info.second_read=0;
1720
	continue;		/* Search after next_record */
1721
      }
1722
      if (b_type & (BLOCK_DELETED | BLOCK_SYNC_ERROR))
1723
      {
1241.9.57 by Monty Taylor
Oy. Bigger change than I normally like - but this stuff is all intertwined.
1724
	errno=HA_ERR_RECORD_DELETED;
1 by brian
clean slate
1725
	info->lastpos=block_info.filepos;
1726
	info->nextpos=block_info.filepos+block_info.block_len;
1727
      }
1728
      goto err;
1729
    }
1730
    if (block_of_record == 0)				/* First block */
1731
    {
1732
      if (block_info.rec_len > (uint) share->base.max_pack_length)
1733
	goto panic;
1734
      info->lastpos=filepos;
1735
      if (share->base.blobs)
1736
      {
1737
	if (!(to= mi_alloc_rec_buff(info, block_info.rec_len,
1738
				    &info->rec_buff)))
1739
	  goto err;
1740
      }
1741
      else
1742
	to= info->rec_buff;
1743
      left_len=block_info.rec_len;
1744
    }
1745
    if (left_len < block_info.data_len)
1746
      goto panic;				/* Wrong linked record */
1747
1748
    /* copy information that is already read */
1749
    {
482 by Brian Aker
Remove uint.
1750
      uint32_t offset=(uint) (block_info.filepos - filepos);
1751
      uint32_t tmp_length= (sizeof(block_info.header) - offset);
1 by brian
clean slate
1752
      filepos=block_info.filepos;
1753
1754
      if (tmp_length > block_info.data_len)
1755
	tmp_length= block_info.data_len;
1756
      if (tmp_length)
1757
      {
212.6.12 by Mats Kindahl
Removing redundant use of casts in MyISAM storage for memcmp(), memcpy(), memset(), and memmove().
1758
	memcpy(to, block_info.header+offset,tmp_length);
1 by brian
clean slate
1759
	block_info.data_len-=tmp_length;
1760
	left_len-=tmp_length;
1761
	to+=tmp_length;
1762
	filepos+=tmp_length;
1763
      }
1764
    }
1765
    /* read rest of record from file */
1766
    if (block_info.data_len)
1767
    {
1768
      if (info->opt_flag & READ_CACHE_USED)
1769
      {
481 by Brian Aker
Remove all of uchar.
1770
	if (_mi_read_cache(&info->rec_cache,(unsigned char*) to,filepos,
1 by brian
clean slate
1771
			   block_info.data_len,
1772
			   (!block_of_record && skip_deleted_blocks) ?
1773
                           READING_NEXT : 0))
1774
	  goto panic;
1775
      }
1776
      else
1777
      {
1778
        if (info->opt_flag & WRITE_CACHE_USED &&
1779
            info->rec_cache.pos_in_file <
1780
            block_info.filepos + block_info.data_len &&
2385.3.9 by Olaf van der Spek
Move flush() into iocache
1781
            info->rec_cache.flush())
1 by brian
clean slate
1782
          goto err;
656.1.39 by Monty Taylor
Removed my_seek, my_tell, my_fwrite, my_fseek.
1783
	/* lseek(info->dfile,filepos,SEEK_SET); */
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
1784
	if (internal::my_read(info->dfile,(unsigned char*) to,block_info.data_len,MYF(MY_NABP)))
1 by brian
clean slate
1785
	{
1241.9.57 by Monty Taylor
Oy. Bigger change than I normally like - but this stuff is all intertwined.
1786
	  if (errno == -1)
1787
	    errno= HA_ERR_WRONG_IN_RECORD;	/* Unexpected end of file */
1 by brian
clean slate
1788
	  goto err;
1789
	}
1790
      }
1791
    }
1792
    /*
1793
      Increment block-of-record counter. If it was the first block,
1794
      remember the position behind the block for the next call.
1795
    */
1796
    if (block_of_record++ == 0)
1797
    {
1798
      info->nextpos= block_info.filepos + block_info.block_len;
1799
      skip_deleted_blocks= 0;
1800
    }
1801
    left_len-=block_info.data_len;
1802
    to+=block_info.data_len;
1803
    filepos=block_info.next_filepos;
1804
  } while (left_len);
1805
1806
  info->update|= HA_STATE_AKTIV | HA_STATE_KEY_CHANGED;
1807
  fast_mi_writeinfo(info);
1808
  if (_mi_rec_unpack(info,buf,info->rec_buff,block_info.rec_len) !=
1809
      MY_FILE_ERROR)
51.1.98 by Jay Pipes
Removed/replaced DBUG symbols and TRUE/FALSE
1810
    return(0);
1241.9.57 by Monty Taylor
Oy. Bigger change than I normally like - but this stuff is all intertwined.
1811
  return(errno);			/* Wrong record */
1 by brian
clean slate
1812
1813
panic:
1241.9.57 by Monty Taylor
Oy. Bigger change than I normally like - but this stuff is all intertwined.
1814
  errno=HA_ERR_WRONG_IN_RECORD;		/* Something is fatal wrong */
1 by brian
clean slate
1815
err:
1241.9.57 by Monty Taylor
Oy. Bigger change than I normally like - but this stuff is all intertwined.
1816
  save_errno=errno;
398.1.10 by Monty Taylor
Actually removed VOID() this time.
1817
  _mi_writeinfo(info,0);
1241.9.57 by Monty Taylor
Oy. Bigger change than I normally like - but this stuff is all intertwined.
1818
  return(errno=save_errno);
1 by brian
clean slate
1819
}
1820
1821
1822
	/* Read and process header from a dynamic-record-file */
1823
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
1824
uint32_t _mi_get_block_info(MI_BLOCK_INFO *info, int file, internal::my_off_t filepos)
1 by brian
clean slate
1825
{
482 by Brian Aker
Remove uint.
1826
  uint32_t return_val=0;
481 by Brian Aker
Remove all of uchar.
1827
  unsigned char *header=info->header;
1 by brian
clean slate
1828
1829
  if (file >= 0)
1830
  {
1831
    /*
1832
      We do not use my_pread() here because we want to have the file
1833
      pointer set to the end of the header after this function.
1834
      my_pread() may leave the file pointer untouched.
1835
    */
656.1.39 by Monty Taylor
Removed my_seek, my_tell, my_fwrite, my_fseek.
1836
    lseek(file,filepos,SEEK_SET);
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
1837
    if (internal::my_read(file, header, sizeof(info->header),MYF(0)) !=
1 by brian
clean slate
1838
	sizeof(info->header))
1839
      goto err;
1840
  }
1841
  if (info->second_read)
1842
  {
1843
    if (info->header[0] <= 6 || info->header[0] == 13)
1844
      return_val=BLOCK_SYNC_ERROR;
1845
  }
1846
  else
1847
  {
1848
    if (info->header[0] > 6 && info->header[0] != 13)
1849
      return_val=BLOCK_SYNC_ERROR;
1850
  }
1851
  info->next_filepos= HA_OFFSET_ERROR; /* Dummy if no next block */
1852
1853
  switch (info->header[0]) {
1854
  case 0:
1855
    if ((info->block_len=(uint) mi_uint3korr(header+1)) <
1856
	MI_MIN_BLOCK_LENGTH ||
1857
	(info->block_len & (MI_DYN_ALIGN_SIZE -1)))
1858
      goto err;
1859
    info->filepos=filepos;
1860
    info->next_filepos=mi_sizekorr(header+4);
1861
    info->prev_filepos=mi_sizekorr(header+12);
1862
#if SIZEOF_OFF_T == 4
1863
    if ((mi_uint4korr(header+4) != 0 &&
365.2.8 by Monty Taylor
More MAX macros.
1864
	 (mi_uint4korr(header+4) != UINT32_MAX ||
1865
	  info->next_filepos != UINT32_MAX) ||
1 by brian
clean slate
1866
	(mi_uint4korr(header+12) != 0 &&
365.2.8 by Monty Taylor
More MAX macros.
1867
	 (mi_uint4korr(header+12) != UINT32_MAX ||
1868
	  info->prev_filepos != UINT32_MAX))
1 by brian
clean slate
1869
      goto err;
1870
#endif
1871
    return return_val | BLOCK_DELETED;		/* Deleted block */
1872
1873
  case 1:
1874
    info->rec_len=info->data_len=info->block_len=mi_uint2korr(header+1);
1875
    info->filepos=filepos+3;
1876
    return return_val | BLOCK_FIRST | BLOCK_LAST;
1877
  case 2:
1878
    info->rec_len=info->data_len=info->block_len=mi_uint3korr(header+1);
1879
    info->filepos=filepos+4;
1880
    return return_val | BLOCK_FIRST | BLOCK_LAST;
1881
1882
  case 13:
1883
    info->rec_len=mi_uint4korr(header+1);
1884
    info->block_len=info->data_len=mi_uint3korr(header+5);
1885
    info->next_filepos=mi_sizekorr(header+8);
1886
    info->second_read=1;
1887
    info->filepos=filepos+16;
1888
    return return_val | BLOCK_FIRST;
1889
1890
  case 3:
1891
    info->rec_len=info->data_len=mi_uint2korr(header+1);
1892
    info->block_len=info->rec_len+ (uint) header[3];
1893
    info->filepos=filepos+4;
1894
    return return_val | BLOCK_FIRST | BLOCK_LAST;
1895
  case 4:
1896
    info->rec_len=info->data_len=mi_uint3korr(header+1);
1897
    info->block_len=info->rec_len+ (uint) header[4];
1898
    info->filepos=filepos+5;
1899
    return return_val | BLOCK_FIRST | BLOCK_LAST;
1900
1901
  case 5:
1902
    info->rec_len=mi_uint2korr(header+1);
1903
    info->block_len=info->data_len=mi_uint2korr(header+3);
1904
    info->next_filepos=mi_sizekorr(header+5);
1905
    info->second_read=1;
1906
    info->filepos=filepos+13;
1907
    return return_val | BLOCK_FIRST;
1908
  case 6:
1909
    info->rec_len=mi_uint3korr(header+1);
1910
    info->block_len=info->data_len=mi_uint3korr(header+4);
1911
    info->next_filepos=mi_sizekorr(header+7);
1912
    info->second_read=1;
1913
    info->filepos=filepos+15;
1914
    return return_val | BLOCK_FIRST;
1915
1916
    /* The following blocks are identical to 1-6 without rec_len */
1917
  case 7:
1918
    info->data_len=info->block_len=mi_uint2korr(header+1);
1919
    info->filepos=filepos+3;
1920
    return return_val | BLOCK_LAST;
1921
  case 8:
1922
    info->data_len=info->block_len=mi_uint3korr(header+1);
1923
    info->filepos=filepos+4;
1924
    return return_val | BLOCK_LAST;
1925
1926
  case 9:
1927
    info->data_len=mi_uint2korr(header+1);
1928
    info->block_len=info->data_len+ (uint) header[3];
1929
    info->filepos=filepos+4;
1930
    return return_val | BLOCK_LAST;
1931
  case 10:
1932
    info->data_len=mi_uint3korr(header+1);
1933
    info->block_len=info->data_len+ (uint) header[4];
1934
    info->filepos=filepos+5;
1935
    return return_val | BLOCK_LAST;
1936
1937
  case 11:
1938
    info->data_len=info->block_len=mi_uint2korr(header+1);
1939
    info->next_filepos=mi_sizekorr(header+3);
1940
    info->second_read=1;
1941
    info->filepos=filepos+11;
1942
    return return_val;
1943
  case 12:
1944
    info->data_len=info->block_len=mi_uint3korr(header+1);
1945
    info->next_filepos=mi_sizekorr(header+4);
1946
    info->second_read=1;
1947
    info->filepos=filepos+12;
1948
    return return_val;
1949
  }
1950
1951
err:
1241.9.57 by Monty Taylor
Oy. Bigger change than I normally like - but this stuff is all intertwined.
1952
  errno=HA_ERR_WRONG_IN_RECORD;	 /* Garbage */
1 by brian
clean slate
1953
  return BLOCK_ERROR;
1954
}