~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
14
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
15
16
/* open a isam-database */
17
76 by Brian Aker
Next pass on fulltext.
18
#include "myisamdef.h"
212.5.18 by Monty Taylor
Moved m_ctype, m_string and my_bitmap. Removed t_ctype.
19
#include <mystrings/m_ctype.h>
612.2.13 by Monty Taylor
Work on removing global.h from headers that should be installed.
20
#include <mystrings/m_string.h>
492.1.7 by Monty Taylor
Moved test() to its own file.
21
#include <drizzled/util/test.h>
1 by brian
clean slate
22
612.2.13 by Monty Taylor
Work on removing global.h from headers that should be installed.
23
#include <string.h>
24
1 by brian
clean slate
25
static void setup_key_functions(MI_KEYDEF *keyinfo);
26
27
#define disk_pos_assert(pos, end_pos) \
28
if (pos > end_pos)             \
29
{                              \
30
  my_errno=HA_ERR_CRASHED;     \
31
  goto err;                    \
32
}
33
34
35
/******************************************************************************
36
** Return the shared struct if the table is already open.
37
** In MySQL the server will handle version issues.
38
******************************************************************************/
39
40
MI_INFO *test_if_reopen(char *filename)
41
{
42
  LIST *pos;
43
44
  for (pos=myisam_open_list ; pos ; pos=pos->next)
45
  {
46
    MI_INFO *info=(MI_INFO*) pos->data;
47
    MYISAM_SHARE *share=info->s;
48
    if (!strcmp(share->unique_file_name,filename) && share->last_version)
49
      return info;
50
  }
51
  return 0;
52
}
53
54
55
/******************************************************************************
56
  open a MyISAM database.
57
  See my_base.h for the handle_locking argument
58
  if handle_locking and HA_OPEN_ABORT_IF_CRASHED then abort if the table
59
  is marked crashed or if we are not using locking and the table doesn't
60
  have an open count of 0.
61
******************************************************************************/
62
482 by Brian Aker
Remove uint.
63
MI_INFO *mi_open(const char *name, int mode, uint32_t open_flags)
1 by brian
clean slate
64
{
65
  int lock_error,kfile,open_mode,save_errno,have_rtree=0;
482 by Brian Aker
Remove uint.
66
  uint32_t i,j,len,errpos,head_length,base_pos,offset,info_length,keys,
1 by brian
clean slate
67
    key_parts,unique_key_parts,fulltext_keys,uniques;
68
  char name_buff[FN_REFLEN], org_name[FN_REFLEN], index_name[FN_REFLEN],
69
       data_name[FN_REFLEN];
481 by Brian Aker
Remove all of uchar.
70
  unsigned char *disk_cache= NULL;
71
  unsigned char *disk_pos, *end_pos;
1 by brian
clean slate
72
  MI_INFO info,*m_info,*old_info;
73
  MYISAM_SHARE share_buff,*share;
74
  ulong rec_per_key_part[HA_MAX_POSSIBLE_KEY*MI_MAX_KEY_SEG];
75
  my_off_t key_root[HA_MAX_POSSIBLE_KEY],key_del[MI_MAX_KEY_BLOCK_SIZE];
151 by Brian Aker
Ulonglong to uint64_t
76
  uint64_t max_key_file_length, max_data_file_length;
1 by brian
clean slate
77
78
  kfile= -1;
79
  lock_error=1;
80
  errpos=0;
81
  head_length=sizeof(share_buff.state.header);
212.6.12 by Mats Kindahl
Removing redundant use of casts in MyISAM storage for memcmp(), memcpy(), memset(), and memmove().
82
  memset(&info, 0, sizeof(info));
1 by brian
clean slate
83
84
  my_realpath(name_buff, fn_format(org_name,name,"",MI_NAME_IEXT,
85
                                   MY_UNPACK_FILENAME),MYF(0));
86
  pthread_mutex_lock(&THR_LOCK_myisam);
87
  if (!(old_info=test_if_reopen(name_buff)))
88
  {
89
    share= &share_buff;
212.6.12 by Mats Kindahl
Removing redundant use of casts in MyISAM storage for memcmp(), memcpy(), memset(), and memmove().
90
    memset(&share_buff, 0, sizeof(share_buff));
1 by brian
clean slate
91
    share_buff.state.rec_per_key_part=rec_per_key_part;
92
    share_buff.state.key_root=key_root;
93
    share_buff.state.key_del=key_del;
481 by Brian Aker
Remove all of uchar.
94
    share_buff.key_cache= multi_key_cache_search((unsigned char*) name_buff,
1 by brian
clean slate
95
                                                 strlen(name_buff));
96
492.1.13 by Monty Taylor
Removed O_SHARE. I think it was only for OS/2.
97
    if ((kfile=my_open(name_buff,(open_mode=O_RDWR),MYF(0))) < 0)
1 by brian
clean slate
98
    {
99
      if ((errno != EROFS && errno != EACCES) ||
100
	  mode != O_RDONLY ||
492.1.13 by Monty Taylor
Removed O_SHARE. I think it was only for OS/2.
101
	  (kfile=my_open(name_buff,(open_mode=O_RDONLY),MYF(0))) < 0)
1 by brian
clean slate
102
	goto err;
103
    }
104
    share->mode=open_mode;
105
    errpos=1;
106
    if (my_read(kfile, share->state.header.file_version, head_length,
107
		MYF(MY_NABP)))
108
    {
109
      my_errno= HA_ERR_NOT_A_TABLE;
110
      goto err;
111
    }
212.6.12 by Mats Kindahl
Removing redundant use of casts in MyISAM storage for memcmp(), memcpy(), memset(), and memmove().
112
    if (memcmp(share->state.header.file_version, myisam_file_magic, 4))
1 by brian
clean slate
113
    {
114
      my_errno=HA_ERR_NOT_A_TABLE;
115
      goto err;
116
    }
117
    share->options= mi_uint2korr(share->state.header.options);
118
    if (share->options &
119
	~(HA_OPTION_PACK_RECORD | HA_OPTION_PACK_KEYS |
120
	  HA_OPTION_COMPRESS_RECORD | HA_OPTION_READ_ONLY_DATA |
121
	  HA_OPTION_TEMP_COMPRESS_RECORD | HA_OPTION_CHECKSUM |
122
          HA_OPTION_TMP_TABLE | HA_OPTION_DELAY_KEY_WRITE |
123
          HA_OPTION_RELIES_ON_SQL_LAYER))
124
    {
125
      my_errno=HA_ERR_OLD_FILE;
126
      goto err;
127
    }
128
    if ((share->options & HA_OPTION_RELIES_ON_SQL_LAYER) &&
129
        ! (open_flags & HA_OPEN_FROM_SQL_LAYER))
130
    {
131
      my_errno= HA_ERR_UNSUPPORTED;
132
      goto err;
133
    }
134
    /* Don't call realpath() if the name can't be a link */
135
    if (!strcmp(name_buff, org_name) ||
136
        my_readlink(index_name, org_name, MYF(0)) == -1)
641.4.3 by Toru Maesaka
Final pass of replacing MySQL's my_stpcpy() with appropriate libc calls
137
      (void) strcpy(index_name, org_name);
1 by brian
clean slate
138
    *strrchr(org_name, '.')= '\0';
139
    (void) fn_format(data_name,org_name,"",MI_NAME_DEXT,
140
                     MY_APPEND_EXT|MY_UNPACK_FILENAME|MY_RESOLVE_SYMLINKS);
141
142
    info_length=mi_uint2korr(share->state.header.header_length);
143
    base_pos=mi_uint2korr(share->state.header.base_pos);
481 by Brian Aker
Remove all of uchar.
144
    if (!(disk_cache= (unsigned char*) malloc(info_length+128)))
1 by brian
clean slate
145
    {
146
      my_errno=ENOMEM;
147
      goto err;
148
    }
149
    end_pos=disk_cache+info_length;
150
    errpos=2;
151
656.1.39 by Monty Taylor
Removed my_seek, my_tell, my_fwrite, my_fseek.
152
    lseek(kfile,0,SEEK_SET);
1 by brian
clean slate
153
    errpos=3;
154
    if (my_read(kfile,disk_cache,info_length,MYF(MY_NABP)))
155
    {
156
      my_errno=HA_ERR_CRASHED;
157
      goto err;
158
    }
159
    len=mi_uint2korr(share->state.header.state_info_length);
160
    keys=    (uint) share->state.header.keys;
161
    uniques= (uint) share->state.header.uniques;
162
    fulltext_keys= (uint) share->state.header.fulltext_keys;
163
    key_parts= mi_uint2korr(share->state.header.key_parts);
164
    unique_key_parts= mi_uint2korr(share->state.header.unique_key_parts);
165
    share->state_diff_length=len-MI_STATE_INFO_SIZE;
166
167
    mi_state_info_read(disk_cache, &share->state);
168
    len= mi_uint2korr(share->state.header.base_info_length);
169
    disk_pos= my_n_base_info_read(disk_cache + base_pos, &share->base);
170
    share->state.state_length=base_pos;
171
172
    if (!(open_flags & HA_OPEN_FOR_REPAIR) &&
173
	((share->state.changed & STATE_CRASHED) ||
174
	 ((open_flags & HA_OPEN_ABORT_IF_CRASHED) &&
77.1.96 by Monty Taylor
Removed skip-external-locking.
175
	  (share->state.open_count))))
1 by brian
clean slate
176
    {
177
      my_errno=((share->state.changed & STATE_CRASHED_ON_REPAIR) ?
178
		HA_ERR_CRASHED_ON_REPAIR : HA_ERR_CRASHED_ON_USAGE);
179
      goto err;
180
    }
181
182
    /* sanity check */
183
    if (share->base.keystart > 65535 || share->base.rec_reflength > 8)
184
    {
185
      my_errno=HA_ERR_CRASHED;
186
      goto err;
187
    }
188
189
    if (share->base.max_key_length > MI_MAX_KEY_BUFF || keys > MI_MAX_KEY ||
190
	key_parts > MI_MAX_KEY * MI_MAX_KEY_SEG)
191
    {
192
      my_errno=HA_ERR_UNSUPPORTED;
193
      goto err;
194
    }
195
196
    /* Correct max_file_length based on length of sizeof(off_t) */
197
    max_data_file_length=
198
      (share->options & (HA_OPTION_PACK_RECORD | HA_OPTION_COMPRESS_RECORD)) ?
151 by Brian Aker
Ulonglong to uint64_t
199
      (((uint64_t) 1 << (share->base.rec_reflength*8))-1) :
1 by brian
clean slate
200
      (mi_safe_mul(share->base.pack_reclength,
151 by Brian Aker
Ulonglong to uint64_t
201
		   (uint64_t) 1 << (share->base.rec_reflength*8))-1);
1 by brian
clean slate
202
    max_key_file_length=
203
      mi_safe_mul(MI_MIN_KEY_BLOCK_LENGTH,
151 by Brian Aker
Ulonglong to uint64_t
204
		  ((uint64_t) 1 << (share->base.key_reflength*8))-1);
1 by brian
clean slate
205
#if SIZEOF_OFF_T == 4
590.2.23 by Monty Taylor
Fixed a few things for solaris builds.
206
    set_if_smaller(max_data_file_length, INT32_MAX);
207
    set_if_smaller(max_key_file_length, INT32_MAX);
1 by brian
clean slate
208
#endif
209
    if (share->base.raid_type)
210
    {
211
      my_errno=HA_ERR_UNSUPPORTED;
212
      goto err;
213
    }
214
    share->base.max_data_file_length=(my_off_t) max_data_file_length;
215
    share->base.max_key_file_length=(my_off_t) max_key_file_length;
216
217
    if (share->options & HA_OPTION_COMPRESS_RECORD)
218
      share->base.max_key_length+=2;	/* For safety */
219
220
    /* Add space for node pointer */
221
    share->base.max_key_length+= share->base.key_reflength;
222
223
    if (!my_multi_malloc(MY_WME,
224
			 &share,sizeof(*share),
225
			 &share->state.rec_per_key_part,sizeof(long)*key_parts,
226
			 &share->keyinfo,keys*sizeof(MI_KEYDEF),
227
			 &share->uniqueinfo,uniques*sizeof(MI_UNIQUEDEF),
228
			 &share->keyparts,
229
			 (key_parts+unique_key_parts+keys+uniques) *
230
			 sizeof(HA_KEYSEG),
231
			 &share->rec,
232
			 (share->base.fields+1)*sizeof(MI_COLUMNDEF),
233
			 &share->blobs,sizeof(MI_BLOB)*share->base.blobs,
234
			 &share->unique_file_name,strlen(name_buff)+1,
235
			 &share->index_file_name,strlen(index_name)+1,
236
			 &share->data_file_name,strlen(data_name)+1,
237
			 &share->state.key_root,keys*sizeof(my_off_t),
238
			 &share->state.key_del,
239
			 (share->state.header.max_block_size_index*sizeof(my_off_t)),
658 by Brian Aker
Part removal of my_pthread.h
240
			 &share->key_root_lock,sizeof(pthread_rwlock_t)*keys,
241
			 &share->mmap_lock,sizeof(pthread_rwlock_t),
461 by Monty Taylor
Removed NullS. bu-bye.
242
			 NULL))
1 by brian
clean slate
243
      goto err;
244
    errpos=4;
245
    *share=share_buff;
212.6.12 by Mats Kindahl
Removing redundant use of casts in MyISAM storage for memcmp(), memcpy(), memset(), and memmove().
246
    memcpy(share->state.rec_per_key_part, rec_per_key_part,
247
           sizeof(long)*key_parts);
248
    memcpy(share->state.key_root, key_root,
249
           sizeof(my_off_t)*keys);
250
    memcpy(share->state.key_del, key_del,
251
           sizeof(my_off_t) * share->state.header.max_block_size_index);
641.4.3 by Toru Maesaka
Final pass of replacing MySQL's my_stpcpy() with appropriate libc calls
252
    strcpy(share->unique_file_name, name_buff);
1 by brian
clean slate
253
    share->unique_name_length= strlen(name_buff);
641.4.3 by Toru Maesaka
Final pass of replacing MySQL's my_stpcpy() with appropriate libc calls
254
    strcpy(share->index_file_name,  index_name);
255
    strcpy(share->data_file_name,   data_name);
1 by brian
clean slate
256
398.1.4 by Monty Taylor
Renamed max/min.
257
    share->blocksize=cmin(IO_SIZE,myisam_block_size);
1 by brian
clean slate
258
    {
259
      HA_KEYSEG *pos=share->keyparts;
260
      for (i=0 ; i < keys ; i++)
261
      {
262
        share->keyinfo[i].share= share;
263
	disk_pos=mi_keydef_read(disk_pos, &share->keyinfo[i]);
264
        disk_pos_assert(disk_pos + share->keyinfo[i].keysegs * HA_KEYSEG_SIZE,
265
 			end_pos);
266
	set_if_smaller(share->blocksize,share->keyinfo[i].block_length);
267
	share->keyinfo[i].seg=pos;
268
	for (j=0 ; j < share->keyinfo[i].keysegs; j++,pos++)
269
	{
270
	  disk_pos=mi_keyseg_read(disk_pos, pos);
271
          if (pos->flag & HA_BLOB_PART &&
272
              ! (share->options & (HA_OPTION_COMPRESS_RECORD |
273
                                   HA_OPTION_PACK_RECORD)))
274
          {
275
            my_errno= HA_ERR_CRASHED;
276
            goto err;
277
          }
278
	  if (pos->type == HA_KEYTYPE_TEXT ||
279
              pos->type == HA_KEYTYPE_VARTEXT1 ||
280
              pos->type == HA_KEYTYPE_VARTEXT2)
281
	  {
282
	    if (!pos->language)
283
	      pos->charset=default_charset_info;
284
	    else if (!(pos->charset= get_charset(pos->language, MYF(MY_WME))))
285
	    {
286
	      my_errno=HA_ERR_UNKNOWN_CHARSET;
287
	      goto err;
288
	    }
289
	  }
290
	  else if (pos->type == HA_KEYTYPE_BINARY)
291
	    pos->charset= &my_charset_bin;
292
	}
293
        setup_key_functions(share->keyinfo+i);
294
	share->keyinfo[i].end=pos;
295
	pos->type=HA_KEYTYPE_END;			/* End */
296
	pos->length=share->base.rec_reflength;
297
	pos->null_bit=0;
298
	pos->flag=0;					/* For purify */
299
	pos++;
300
      }
301
      for (i=0 ; i < uniques ; i++)
302
      {
303
	disk_pos=mi_uniquedef_read(disk_pos, &share->uniqueinfo[i]);
304
        disk_pos_assert(disk_pos + share->uniqueinfo[i].keysegs *
305
			HA_KEYSEG_SIZE, end_pos);
306
	share->uniqueinfo[i].seg=pos;
307
	for (j=0 ; j < share->uniqueinfo[i].keysegs; j++,pos++)
308
	{
309
	  disk_pos=mi_keyseg_read(disk_pos, pos);
310
	  if (pos->type == HA_KEYTYPE_TEXT ||
311
              pos->type == HA_KEYTYPE_VARTEXT1 ||
312
              pos->type == HA_KEYTYPE_VARTEXT2)
313
	  {
314
	    if (!pos->language)
315
	      pos->charset=default_charset_info;
316
	    else if (!(pos->charset= get_charset(pos->language, MYF(MY_WME))))
317
	    {
318
	      my_errno=HA_ERR_UNKNOWN_CHARSET;
319
	      goto err;
320
	    }
321
	  }
322
	}
323
	share->uniqueinfo[i].end=pos;
324
	pos->type=HA_KEYTYPE_END;			/* End */
325
	pos->null_bit=0;
326
	pos->flag=0;
327
	pos++;
328
      }
329
    }
330
331
    disk_pos_assert(disk_pos + share->base.fields *MI_COLUMNDEF_SIZE, end_pos);
332
    for (i=j=offset=0 ; i < share->base.fields ; i++)
333
    {
334
      disk_pos=mi_recinfo_read(disk_pos,&share->rec[i]);
335
      share->rec[i].pack_type=0;
336
      share->rec[i].huff_tree=0;
337
      share->rec[i].offset=offset;
338
      if (share->rec[i].type == (int) FIELD_BLOB)
339
      {
340
	share->blobs[j].pack_length=
341
	  share->rec[i].length-portable_sizeof_char_ptr;
342
	share->blobs[j].offset=offset;
343
	j++;
344
      }
345
      offset+=share->rec[i].length;
346
    }
347
    share->rec[i].type=(int) FIELD_LAST;	/* End marker */
348
    if (offset > share->base.reclength)
349
    {
350
      /* purecov: begin inspected */
351
      my_errno= HA_ERR_CRASHED;
352
      goto err;
353
      /* purecov: end */
354
    }
355
356
    if (! lock_error)
357
    {
358
      lock_error=1;			/* Database unlocked */
359
    }
360
361
    if (mi_open_datafile(&info, share, -1))
362
      goto err;
363
    errpos=5;
364
365
    share->kfile=kfile;
366
    share->this_process=(ulong) getpid();
367
    share->last_process= share->state.process;
368
    share->base.key_parts=key_parts;
369
    share->base.all_key_parts=key_parts+unique_key_parts;
370
    if (!(share->last_version=share->state.version))
371
      share->last_version=1;			/* Safety */
372
    share->rec_reflength=share->base.rec_reflength; /* May be changed */
373
    share->base.margin_key_file_length=(share->base.max_key_file_length -
374
					(keys ? MI_INDEX_BLOCK_MARGIN *
375
					 share->blocksize * keys : 0));
398.1.4 by Monty Taylor
Renamed max/min.
376
    share->blocksize=cmin(IO_SIZE,myisam_block_size);
1 by brian
clean slate
377
    share->data_file_type=STATIC_RECORD;
311 by Brian Aker
Sqlech issues with pack
378
    if (share->options & HA_OPTION_PACK_RECORD)
1 by brian
clean slate
379
      share->data_file_type = DYNAMIC_RECORD;
478 by Monty Taylor
Made my_alloc actually always use malloc.
380
    free(disk_cache);
381
    disk_cache= NULL;
1 by brian
clean slate
382
    mi_setup_functions(share);
163 by Brian Aker
Merge Monty's code.
383
    share->is_log_table= false;
1 by brian
clean slate
384
    thr_lock_init(&share->lock);
398.1.10 by Monty Taylor
Actually removed VOID() this time.
385
    pthread_mutex_init(&share->intern_lock,MY_MUTEX_INIT_FAST);
1 by brian
clean slate
386
    for (i=0; i<keys; i++)
658 by Brian Aker
Part removal of my_pthread.h
387
      pthread_rwlock_init(&share->key_root_lock[i], NULL);
388
    pthread_rwlock_init(&share->mmap_lock, NULL);
1 by brian
clean slate
389
    if (!thr_lock_inited)
390
    {
391
      /* Probably a single threaded program; Don't use concurrent inserts */
392
      myisam_concurrent_insert=0;
393
    }
394
    else if (myisam_concurrent_insert)
395
    {
396
      share->concurrent_insert=
397
	((share->options & (HA_OPTION_READ_ONLY_DATA | HA_OPTION_TMP_TABLE |
398
			   HA_OPTION_COMPRESS_RECORD |
399
			   HA_OPTION_TEMP_COMPRESS_RECORD)) ||
74 by Brian Aker
More removal of FT from MyISAM
400
	 (open_flags & HA_OPEN_TMP_TABLE) || have_rtree) ? 0 : 1;
1 by brian
clean slate
401
      if (share->concurrent_insert)
402
      {
146 by Brian Aker
my_bool cleanup.
403
	share->lock.get_status= mi_get_status;
404
	share->lock.copy_status= mi_copy_status;
405
	share->lock.update_status= mi_update_status;
1 by brian
clean slate
406
        share->lock.restore_status= mi_restore_status;
146 by Brian Aker
my_bool cleanup.
407
	share->lock.check_status= mi_check_status;
1 by brian
clean slate
408
      }
409
    }
410
    /*
411
      Memory mapping can only be requested after initializing intern_lock.
412
    */
413
    if (open_flags & HA_OPEN_MMAP)
414
    {
415
      info.s= share;
416
      mi_extra(&info, HA_EXTRA_MMAP, 0);
417
    }
418
  }
419
  else
420
  {
421
    share= old_info->s;
422
    if (mode == O_RDWR && share->mode == O_RDONLY)
423
    {
424
      my_errno=EACCES;				/* Can't open in write mode */
425
      goto err;
426
    }
427
    if (mi_open_datafile(&info, share, old_info->dfile))
428
      goto err;
429
    errpos=5;
430
    have_rtree= old_info->rtree_recursion_state != NULL;
431
  }
432
433
  /* alloc and set up private structure parts */
434
  if (!my_multi_malloc(MY_WME,
435
		       &m_info,sizeof(MI_INFO),
436
		       &info.blobs,sizeof(MI_BLOB)*share->base.blobs,
437
		       &info.buff,(share->base.max_key_block_length*2+
438
				   share->base.max_key_length),
439
		       &info.lastkey,share->base.max_key_length*3+1,
440
		       &info.first_mbr_key, share->base.max_key_length,
441
		       &info.filename,strlen(name)+1,
442
		       &info.rtree_recursion_state,have_rtree ? 1024 : 0,
461 by Monty Taylor
Removed NullS. bu-bye.
443
		       NULL))
1 by brian
clean slate
444
    goto err;
445
  errpos=6;
446
447
  if (!have_rtree)
448
    info.rtree_recursion_state= NULL;
449
641.4.3 by Toru Maesaka
Final pass of replacing MySQL's my_stpcpy() with appropriate libc calls
450
  strcpy(info.filename,name);
1 by brian
clean slate
451
  memcpy(info.blobs,share->blobs,sizeof(MI_BLOB)*share->base.blobs);
452
  info.lastkey2=info.lastkey+share->base.max_key_length;
453
454
  info.s=share;
455
  info.lastpos= HA_OFFSET_ERROR;
456
  info.update= (short) (HA_STATE_NEXT_FOUND+HA_STATE_PREV_FOUND);
457
  info.opt_flag=READ_CHECK_USED;
458
  info.this_unique= (ulong) info.dfile; /* Uniq number in process */
459
  if (share->data_file_type == COMPRESSED_RECORD)
460
    info.this_unique= share->state.unique;
461
  info.this_loop=0;				/* Update counter */
462
  info.last_unique= share->state.unique;
463
  info.last_loop=   share->state.update_count;
464
  if (mode == O_RDONLY)
465
    share->options|=HA_OPTION_READ_ONLY_DATA;
466
  info.lock_type=F_UNLCK;
467
  info.quick_mode=0;
468
  info.bulk_insert=0;
469
  info.errkey= -1;
470
  info.page_changed=1;
471
  pthread_mutex_lock(&share->intern_lock);
472
  info.read_record=share->read_record;
473
  share->reopen++;
474
  share->write_flag=MYF(MY_NABP | MY_WAIT_IF_FULL);
475
  if (share->options & HA_OPTION_READ_ONLY_DATA)
476
  {
477
    info.lock_type=F_RDLCK;
478
    share->r_locks++;
479
    share->tot_locks++;
480
  }
481
  if ((open_flags & HA_OPEN_TMP_TABLE) ||
482
      (share->options & HA_OPTION_TMP_TABLE))
483
  {
484
    share->temporary=share->delay_key_write=1;
485
    share->write_flag=MYF(MY_NABP);
486
    share->w_locks++;			/* We don't have to update status */
487
    share->tot_locks++;
488
    info.lock_type=F_WRLCK;
489
  }
490
  if (((open_flags & HA_OPEN_DELAY_KEY_WRITE) ||
491
      (share->options & HA_OPTION_DELAY_KEY_WRITE)) &&
492
      myisam_delay_key_write)
493
    share->delay_key_write=1;
494
  info.state= &share->state.state;	/* Change global values by default */
495
  pthread_mutex_unlock(&share->intern_lock);
496
497
  /* Allocate buffer for one record */
498
212.6.1 by Mats Kindahl
Replacing all bzero() calls with memset() calls and removing the bzero.c file.
499
  /* prerequisites: memset(info, 0) && info->s=share; are met. */
1 by brian
clean slate
500
  if (!mi_alloc_rec_buff(&info, -1, &info.rec_buff))
501
    goto err;
212.6.1 by Mats Kindahl
Replacing all bzero() calls with memset() calls and removing the bzero.c file.
502
  memset(info.rec_buff, 0, mi_get_rec_buff_len(&info, info.rec_buff));
1 by brian
clean slate
503
504
  *m_info=info;
505
  thr_lock_data_init(&share->lock,&m_info->lock,(void*) m_info);
506
  m_info->open_list.data=(void*) m_info;
507
  myisam_open_list=list_add(myisam_open_list,&m_info->open_list);
508
509
  pthread_mutex_unlock(&THR_LOCK_myisam);
51.1.103 by Jay Pipes
Removed/replaced DBUG symbols and TRUE/FALSE
510
  return(m_info);
1 by brian
clean slate
511
512
err:
478 by Monty Taylor
Made my_alloc actually always use malloc.
513
  if (disk_cache != NULL)
514
    free(disk_cache);
1 by brian
clean slate
515
  save_errno=my_errno ? my_errno : HA_ERR_END_OF_FILE;
516
  if ((save_errno == HA_ERR_CRASHED) ||
517
      (save_errno == HA_ERR_CRASHED_ON_USAGE) ||
518
      (save_errno == HA_ERR_CRASHED_ON_REPAIR))
519
    mi_report_error(save_errno, name);
520
  switch (errpos) {
521
  case 6:
481 by Brian Aker
Remove all of uchar.
522
    free((unsigned char*) m_info);
1 by brian
clean slate
523
    /* fall through */
524
  case 5:
398.1.10 by Monty Taylor
Actually removed VOID() this time.
525
    my_close(info.dfile,MYF(0));
1 by brian
clean slate
526
    if (old_info)
527
      break;					/* Don't remove open table */
528
    /* fall through */
529
  case 4:
481 by Brian Aker
Remove all of uchar.
530
    free((unsigned char*) share);
1 by brian
clean slate
531
    /* fall through */
532
  case 3:
533
    /* fall through */
534
  case 1:
398.1.10 by Monty Taylor
Actually removed VOID() this time.
535
    my_close(kfile,MYF(0));
1 by brian
clean slate
536
    /* fall through */
537
  case 0:
538
  default:
539
    break;
540
  }
541
  pthread_mutex_unlock(&THR_LOCK_myisam);
542
  my_errno=save_errno;
51.1.103 by Jay Pipes
Removed/replaced DBUG symbols and TRUE/FALSE
543
  return (NULL);
1 by brian
clean slate
544
} /* mi_open */
545
546
656.1.39 by Monty Taylor
Removed my_seek, my_tell, my_fwrite, my_fseek.
547
unsigned char *mi_alloc_rec_buff(MI_INFO *info, size_t length, unsigned char **buf)
1 by brian
clean slate
548
{
482 by Brian Aker
Remove uint.
549
  uint32_t extra;
205 by Brian Aker
uint32 -> uin32_t
550
  uint32_t old_length= 0;
1 by brian
clean slate
551
552
  if (! *buf || length > (old_length=mi_get_rec_buff_len(info, *buf)))
553
  {
481 by Brian Aker
Remove all of uchar.
554
    unsigned char *newptr = *buf;
1 by brian
clean slate
555
556
    /* to simplify initial init of info->rec_buf in mi_open and mi_extra */
557
    if (length == (ulong) -1)
558
    {
559
      if (info->s->options & HA_OPTION_COMPRESS_RECORD)
398.1.4 by Monty Taylor
Renamed max/min.
560
        length= cmax(info->s->base.pack_reclength, info->s->max_pack_length);
1 by brian
clean slate
561
      else
562
        length= info->s->base.pack_reclength;
398.1.4 by Monty Taylor
Renamed max/min.
563
      length= cmax(length, info->s->base.max_key_length);
1 by brian
clean slate
564
      /* Avoid unnecessary realloc */
565
      if (newptr && length == old_length)
566
	return newptr;
567
    }
568
569
    extra= ((info->s->options & HA_OPTION_PACK_RECORD) ?
570
	    ALIGN_SIZE(MI_MAX_DYN_BLOCK_HEADER)+MI_SPLIT_LENGTH+
571
	    MI_REC_BUFF_OFFSET : 0);
572
    if (extra && newptr)
573
      newptr-= MI_REC_BUFF_OFFSET;
656.1.44 by Monty Taylor
Added some return checking.
574
    void *tmpnewptr= NULL;
575
    if (!(tmpnewptr= realloc(newptr, length+extra+8))) 
1 by brian
clean slate
576
      return newptr;
656.1.44 by Monty Taylor
Added some return checking.
577
    newptr= tmpnewptr;
205 by Brian Aker
uint32 -> uin32_t
578
    *((uint32_t *) newptr)= (uint32_t) length;
1 by brian
clean slate
579
    *buf= newptr+(extra ?  MI_REC_BUFF_OFFSET : 0);
580
  }
581
  return *buf;
582
}
583
584
151 by Brian Aker
Ulonglong to uint64_t
585
uint64_t mi_safe_mul(uint64_t a, uint64_t b)
1 by brian
clean slate
586
{
151 by Brian Aker
Ulonglong to uint64_t
587
  uint64_t max_val= ~ (uint64_t) 0;		/* my_off_t is unsigned */
1 by brian
clean slate
588
589
  if (!a || max_val / a < b)
590
    return max_val;
591
  return a*b;
592
}
593
594
	/* Set up functions in structs */
595
596
void mi_setup_functions(register MYISAM_SHARE *share)
597
{
311 by Brian Aker
Sqlech issues with pack
598
  if (share->options & HA_OPTION_PACK_RECORD)
1 by brian
clean slate
599
  {
600
    share->read_record=_mi_read_dynamic_record;
601
    share->read_rnd=_mi_read_rnd_dynamic_record;
602
    share->delete_record=_mi_delete_dynamic_record;
603
    share->compare_record=_mi_cmp_dynamic_record;
604
    share->compare_unique=_mi_cmp_dynamic_unique;
605
    share->calc_checksum= mi_checksum;
606
607
    /* add bits used to pack data to pack_reclength for faster allocation */
608
    share->base.pack_reclength+= share->base.pack_bits;
609
    if (share->base.blobs)
610
    {
611
      share->update_record=_mi_update_blob_record;
612
      share->write_record=_mi_write_blob_record;
613
    }
614
    else
615
    {
616
      share->write_record=_mi_write_dynamic_record;
617
      share->update_record=_mi_update_dynamic_record;
618
    }
619
  }
620
  else
621
  {
622
    share->read_record=_mi_read_static_record;
623
    share->read_rnd=_mi_read_rnd_static_record;
624
    share->delete_record=_mi_delete_static_record;
625
    share->compare_record=_mi_cmp_static_record;
626
    share->update_record=_mi_update_static_record;
627
    share->write_record=_mi_write_static_record;
628
    share->compare_unique=_mi_cmp_static_unique;
629
    share->calc_checksum= mi_static_checksum;
630
  }
631
  share->file_read= mi_nommap_pread;
632
  share->file_write= mi_nommap_pwrite;
633
  if (!(share->options & HA_OPTION_CHECKSUM))
634
    share->calc_checksum=0;
635
  return;
636
}
637
638
639
static void setup_key_functions(register MI_KEYDEF *keyinfo)
640
{
641
  {
642
    keyinfo->ck_insert = _mi_ck_write;
643
    keyinfo->ck_delete = _mi_ck_delete;
644
  }
645
  if (keyinfo->flag & HA_BINARY_PACK_KEY)
646
  {						/* Simple prefix compression */
647
    keyinfo->bin_search=_mi_seq_search;
648
    keyinfo->get_key=_mi_get_binary_pack_key;
649
    keyinfo->pack_key=_mi_calc_bin_pack_key_length;
650
    keyinfo->store_key=_mi_store_bin_pack_key;
651
  }
652
  else if (keyinfo->flag & HA_VAR_LENGTH_KEY)
653
  {
654
    keyinfo->get_key= _mi_get_pack_key;
655
    if (keyinfo->seg[0].flag & HA_PACK_KEY)
656
    {						/* Prefix compression */
657
      /*
658
        _mi_prefix_search() compares end-space against ASCII blank (' ').
659
        It cannot be used for character sets, that do not encode the
660
        blank character like ASCII does. UCS2 is an example. All
661
        character sets with a fixed width > 1 or a mimimum width > 1
662
        cannot represent blank like ASCII does. In these cases we have
663
        to use _mi_seq_search() for the search.
664
      */
665
      if (!keyinfo->seg->charset || use_strnxfrm(keyinfo->seg->charset) ||
666
          (keyinfo->seg->flag & HA_NULL_PART) ||
667
          (keyinfo->seg->charset->mbminlen > 1))
668
        keyinfo->bin_search=_mi_seq_search;
669
      else
670
        keyinfo->bin_search=_mi_prefix_search;
671
      keyinfo->pack_key=_mi_calc_var_pack_key_length;
672
      keyinfo->store_key=_mi_store_var_pack_key;
673
    }
674
    else
675
    {
676
      keyinfo->bin_search=_mi_seq_search;
677
      keyinfo->pack_key=_mi_calc_var_key_length; /* Variable length key */
678
      keyinfo->store_key=_mi_store_static_key;
679
    }
680
  }
681
  else
682
  {
683
    keyinfo->bin_search=_mi_bin_search;
684
    keyinfo->get_key=_mi_get_static_key;
685
    keyinfo->pack_key=_mi_calc_static_key_length;
686
    keyinfo->store_key=_mi_store_static_key;
687
  }
688
  return;
689
}
690
691
692
/*
693
   Function to save and store the header in the index file (.MYI)
694
*/
695
482 by Brian Aker
Remove uint.
696
uint32_t mi_state_info_write(File file, MI_STATE_INFO *state, uint32_t pWrite)
1 by brian
clean slate
697
{
481 by Brian Aker
Remove all of uchar.
698
  unsigned char  buff[MI_STATE_INFO_SIZE + MI_STATE_EXTRA_SIZE];
699
  unsigned char *ptr=buff;
1 by brian
clean slate
700
  uint	i, keys= (uint) state->header.keys,
701
	key_blocks=state->header.max_block_size_index;
702
212.6.3 by Mats Kindahl
Removing deprecated functions from code and replacing them with C99 equivalents:
703
  memcpy(ptr,&state->header,sizeof(state->header));
1 by brian
clean slate
704
  ptr+=sizeof(state->header);
705
706
  /* open_count must be first because of _mi_mark_file_changed ! */
707
  mi_int2store(ptr,state->open_count);		ptr +=2;
481 by Brian Aker
Remove all of uchar.
708
  *ptr++= (unsigned char)state->changed; *ptr++= state->sortkey;
1 by brian
clean slate
709
  mi_rowstore(ptr,state->state.records);	ptr +=8;
710
  mi_rowstore(ptr,state->state.del);		ptr +=8;
711
  mi_rowstore(ptr,state->split);		ptr +=8;
712
  mi_sizestore(ptr,state->dellink);		ptr +=8;
713
  mi_sizestore(ptr,state->state.key_file_length);	ptr +=8;
714
  mi_sizestore(ptr,state->state.data_file_length);	ptr +=8;
715
  mi_sizestore(ptr,state->state.empty);		ptr +=8;
716
  mi_sizestore(ptr,state->state.key_empty);	ptr +=8;
717
  mi_int8store(ptr,state->auto_increment);	ptr +=8;
151 by Brian Aker
Ulonglong to uint64_t
718
  mi_int8store(ptr,(uint64_t) state->state.checksum);ptr +=8;
1 by brian
clean slate
719
  mi_int4store(ptr,state->process);		ptr +=4;
720
  mi_int4store(ptr,state->unique);		ptr +=4;
721
  mi_int4store(ptr,state->status);		ptr +=4;
722
  mi_int4store(ptr,state->update_count);	ptr +=4;
723
724
  ptr+=state->state_diff_length;
725
726
  for (i=0; i < keys; i++)
727
  {
728
    mi_sizestore(ptr,state->key_root[i]);	ptr +=8;
729
  }
730
  for (i=0; i < key_blocks; i++)
731
  {
732
    mi_sizestore(ptr,state->key_del[i]);	ptr +=8;
733
  }
734
  if (pWrite & 2)				/* From isamchk */
735
  {
482 by Brian Aker
Remove uint.
736
    uint32_t key_parts= mi_uint2korr(state->header.key_parts);
1 by brian
clean slate
737
    mi_int4store(ptr,state->sec_index_changed); ptr +=4;
738
    mi_int4store(ptr,state->sec_index_used);	ptr +=4;
739
    mi_int4store(ptr,state->version);		ptr +=4;
740
    mi_int8store(ptr,state->key_map);		ptr +=8;
151 by Brian Aker
Ulonglong to uint64_t
741
    mi_int8store(ptr,(uint64_t) state->create_time);	ptr +=8;
742
    mi_int8store(ptr,(uint64_t) state->recover_time);	ptr +=8;
743
    mi_int8store(ptr,(uint64_t) state->check_time);	ptr +=8;
1 by brian
clean slate
744
    mi_sizestore(ptr,state->rec_per_key_rows);	ptr+=8;
745
    for (i=0 ; i < key_parts ; i++)
746
    {
747
      mi_int4store(ptr,state->rec_per_key_part[i]);  ptr+=4;
748
    }
749
  }
750
751
  if (pWrite & 1)
51.1.103 by Jay Pipes
Removed/replaced DBUG symbols and TRUE/FALSE
752
    return(my_pwrite(file, buff, (size_t) (ptr-buff), 0L,
1 by brian
clean slate
753
			  MYF(MY_NABP | MY_THREADSAFE)) != 0);
51.1.103 by Jay Pipes
Removed/replaced DBUG symbols and TRUE/FALSE
754
  return(my_write(file, buff, (size_t) (ptr-buff),
1 by brian
clean slate
755
		       MYF(MY_NABP)) != 0);
756
}
757
758
481 by Brian Aker
Remove all of uchar.
759
unsigned char *mi_state_info_read(unsigned char *ptr, MI_STATE_INFO *state)
1 by brian
clean slate
760
{
482 by Brian Aker
Remove uint.
761
  uint32_t i,keys,key_parts,key_blocks;
212.6.3 by Mats Kindahl
Removing deprecated functions from code and replacing them with C99 equivalents:
762
  memcpy(&state->header,ptr, sizeof(state->header));
1 by brian
clean slate
763
  ptr +=sizeof(state->header);
764
  keys=(uint) state->header.keys;
765
  key_parts=mi_uint2korr(state->header.key_parts);
766
  key_blocks=state->header.max_block_size_index;
767
768
  state->open_count = mi_uint2korr(ptr);	ptr +=2;
769
  state->changed= *ptr++;
770
  state->sortkey = (uint) *ptr++;
771
  state->state.records= mi_rowkorr(ptr);	ptr +=8;
772
  state->state.del = mi_rowkorr(ptr);		ptr +=8;
773
  state->split	= mi_rowkorr(ptr);		ptr +=8;
774
  state->dellink= mi_sizekorr(ptr);		ptr +=8;
775
  state->state.key_file_length = mi_sizekorr(ptr);	ptr +=8;
776
  state->state.data_file_length= mi_sizekorr(ptr);	ptr +=8;
777
  state->state.empty	= mi_sizekorr(ptr);	ptr +=8;
778
  state->state.key_empty= mi_sizekorr(ptr);	ptr +=8;
779
  state->auto_increment=mi_uint8korr(ptr);	ptr +=8;
780
  state->state.checksum=(ha_checksum) mi_uint8korr(ptr);	ptr +=8;
781
  state->process= mi_uint4korr(ptr);		ptr +=4;
782
  state->unique = mi_uint4korr(ptr);		ptr +=4;
783
  state->status = mi_uint4korr(ptr);		ptr +=4;
784
  state->update_count=mi_uint4korr(ptr);	ptr +=4;
785
786
  ptr+= state->state_diff_length;
787
788
  for (i=0; i < keys; i++)
789
  {
790
    state->key_root[i]= mi_sizekorr(ptr);	ptr +=8;
791
  }
792
  for (i=0; i < key_blocks; i++)
793
  {
794
    state->key_del[i] = mi_sizekorr(ptr);	ptr +=8;
795
  }
796
  state->sec_index_changed = mi_uint4korr(ptr); ptr +=4;
797
  state->sec_index_used =    mi_uint4korr(ptr); ptr +=4;
798
  state->version     = mi_uint4korr(ptr);	ptr +=4;
799
  state->key_map     = mi_uint8korr(ptr);	ptr +=8;
800
  state->create_time = (time_t) mi_sizekorr(ptr);	ptr +=8;
801
  state->recover_time =(time_t) mi_sizekorr(ptr);	ptr +=8;
802
  state->check_time =  (time_t) mi_sizekorr(ptr);	ptr +=8;
803
  state->rec_per_key_rows=mi_sizekorr(ptr);	ptr +=8;
804
  for (i=0 ; i < key_parts ; i++)
805
  {
806
    state->rec_per_key_part[i]= mi_uint4korr(ptr); ptr+=4;
807
  }
808
  return ptr;
809
}
810
811
482 by Brian Aker
Remove uint.
812
uint32_t mi_state_info_read_dsk(File file, MI_STATE_INFO *state, bool pRead)
1 by brian
clean slate
813
{
481 by Brian Aker
Remove all of uchar.
814
  unsigned char	buff[MI_STATE_INFO_SIZE + MI_STATE_EXTRA_SIZE];
1 by brian
clean slate
815
816
  if (!myisam_single_user)
817
  {
818
    if (pRead)
819
    {
820
      if (my_pread(file, buff, state->state_length,0L, MYF(MY_NABP)))
821
	return 1;
822
    }
823
    else if (my_read(file, buff, state->state_length,MYF(MY_NABP)))
824
      return 1;
825
    mi_state_info_read(buff, state);
826
  }
827
  return 0;
828
}
829
830
831
/****************************************************************************
832
**  store and read of MI_BASE_INFO
833
****************************************************************************/
834
482 by Brian Aker
Remove uint.
835
uint32_t mi_base_info_write(File file, MI_BASE_INFO *base)
1 by brian
clean slate
836
{
481 by Brian Aker
Remove all of uchar.
837
  unsigned char buff[MI_BASE_INFO_SIZE], *ptr=buff;
1 by brian
clean slate
838
839
  mi_sizestore(ptr,base->keystart);			ptr +=8;
840
  mi_sizestore(ptr,base->max_data_file_length);		ptr +=8;
841
  mi_sizestore(ptr,base->max_key_file_length);		ptr +=8;
842
  mi_rowstore(ptr,base->records);			ptr +=8;
843
  mi_rowstore(ptr,base->reloc);				ptr +=8;
844
  mi_int4store(ptr,base->mean_row_length);		ptr +=4;
845
  mi_int4store(ptr,base->reclength);			ptr +=4;
846
  mi_int4store(ptr,base->pack_reclength);		ptr +=4;
847
  mi_int4store(ptr,base->min_pack_length);		ptr +=4;
848
  mi_int4store(ptr,base->max_pack_length);		ptr +=4;
849
  mi_int4store(ptr,base->min_block_length);		ptr +=4;
850
  mi_int4store(ptr,base->fields);			ptr +=4;
851
  mi_int4store(ptr,base->pack_fields);			ptr +=4;
852
  *ptr++=base->rec_reflength;
853
  *ptr++=base->key_reflength;
854
  *ptr++=base->keys;
855
  *ptr++=base->auto_key;
856
  mi_int2store(ptr,base->pack_bits);			ptr +=2;
857
  mi_int2store(ptr,base->blobs);			ptr +=2;
858
  mi_int2store(ptr,base->max_key_block_length);		ptr +=2;
859
  mi_int2store(ptr,base->max_key_length);		ptr +=2;
860
  mi_int2store(ptr,base->extra_alloc_bytes);		ptr +=2;
861
  *ptr++= base->extra_alloc_procent;
489.1.6 by Monty Taylor
Removed RAID garbage.
862
  /* old raid info  slots */
863
  *ptr++= 0;
864
  mi_int2store(ptr,UINT16_C(0));			ptr +=2;
865
  mi_int4store(ptr,UINT32_C(0));         		ptr +=4;
866
212.6.1 by Mats Kindahl
Replacing all bzero() calls with memset() calls and removing the bzero.c file.
867
  memset(ptr, 0, 6);					ptr +=6; /* extra */
1 by brian
clean slate
868
  return my_write(file, buff, (size_t) (ptr-buff), MYF(MY_NABP)) != 0;
869
}
870
871
481 by Brian Aker
Remove all of uchar.
872
unsigned char *my_n_base_info_read(unsigned char *ptr, MI_BASE_INFO *base)
1 by brian
clean slate
873
{
874
  base->keystart = mi_sizekorr(ptr);			ptr +=8;
875
  base->max_data_file_length = mi_sizekorr(ptr);	ptr +=8;
876
  base->max_key_file_length = mi_sizekorr(ptr);		ptr +=8;
877
  base->records =  (ha_rows) mi_sizekorr(ptr);		ptr +=8;
878
  base->reloc = (ha_rows) mi_sizekorr(ptr);		ptr +=8;
879
  base->mean_row_length = mi_uint4korr(ptr);		ptr +=4;
880
  base->reclength = mi_uint4korr(ptr);			ptr +=4;
881
  base->pack_reclength = mi_uint4korr(ptr);		ptr +=4;
882
  base->min_pack_length = mi_uint4korr(ptr);		ptr +=4;
883
  base->max_pack_length = mi_uint4korr(ptr);		ptr +=4;
884
  base->min_block_length = mi_uint4korr(ptr);		ptr +=4;
885
  base->fields = mi_uint4korr(ptr);			ptr +=4;
886
  base->pack_fields = mi_uint4korr(ptr);		ptr +=4;
887
888
  base->rec_reflength = *ptr++;
889
  base->key_reflength = *ptr++;
890
  base->keys=		*ptr++;
891
  base->auto_key=	*ptr++;
892
  base->pack_bits = mi_uint2korr(ptr);			ptr +=2;
893
  base->blobs = mi_uint2korr(ptr);			ptr +=2;
894
  base->max_key_block_length= mi_uint2korr(ptr);	ptr +=2;
895
  base->max_key_length = mi_uint2korr(ptr);		ptr +=2;
896
  base->extra_alloc_bytes = mi_uint2korr(ptr);		ptr +=2;
897
  base->extra_alloc_procent = *ptr++;
489.1.6 by Monty Taylor
Removed RAID garbage.
898
899
  /* advance past raid_type (1) raid_chunks (2) and raid_chunksize (4) */
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
900
  ptr+= 7;
1 by brian
clean slate
901
902
  ptr+=6;
903
  return ptr;
904
}
905
906
/*--------------------------------------------------------------------------
907
  mi_keydef
908
---------------------------------------------------------------------------*/
909
482 by Brian Aker
Remove uint.
910
uint32_t mi_keydef_write(File file, MI_KEYDEF *keydef)
1 by brian
clean slate
911
{
481 by Brian Aker
Remove all of uchar.
912
  unsigned char buff[MI_KEYDEF_SIZE];
913
  unsigned char *ptr=buff;
1 by brian
clean slate
914
481 by Brian Aker
Remove all of uchar.
915
  *ptr++ = (unsigned char) keydef->keysegs;
1 by brian
clean slate
916
  *ptr++ = keydef->key_alg;			/* Rtree or Btree */
917
  mi_int2store(ptr,keydef->flag);		ptr +=2;
918
  mi_int2store(ptr,keydef->block_length);	ptr +=2;
919
  mi_int2store(ptr,keydef->keylength);		ptr +=2;
920
  mi_int2store(ptr,keydef->minlength);		ptr +=2;
921
  mi_int2store(ptr,keydef->maxlength);		ptr +=2;
922
  return my_write(file, buff, (size_t) (ptr-buff), MYF(MY_NABP)) != 0;
923
}
924
481 by Brian Aker
Remove all of uchar.
925
unsigned char *mi_keydef_read(unsigned char *ptr, MI_KEYDEF *keydef)
1 by brian
clean slate
926
{
927
   keydef->keysegs	= (uint) *ptr++;
928
   keydef->key_alg	= *ptr++;		/* Rtree or Btree */
929
930
   keydef->flag		= mi_uint2korr(ptr);	ptr +=2;
931
   keydef->block_length = mi_uint2korr(ptr);	ptr +=2;
932
   keydef->keylength	= mi_uint2korr(ptr);	ptr +=2;
933
   keydef->minlength	= mi_uint2korr(ptr);	ptr +=2;
934
   keydef->maxlength	= mi_uint2korr(ptr);	ptr +=2;
935
   keydef->block_size_index= keydef->block_length/MI_MIN_KEY_BLOCK_LENGTH-1;
936
   keydef->underflow_block_length=keydef->block_length/3;
937
   keydef->version	= 0;			/* Not saved */
938
   return ptr;
939
}
940
941
/***************************************************************************
942
**  mi_keyseg
943
***************************************************************************/
944
945
int mi_keyseg_write(File file, const HA_KEYSEG *keyseg)
946
{
481 by Brian Aker
Remove all of uchar.
947
  unsigned char buff[HA_KEYSEG_SIZE];
948
  unsigned char *ptr=buff;
1 by brian
clean slate
949
  ulong pos;
950
951
  *ptr++= keyseg->type;
952
  *ptr++= keyseg->language;
953
  *ptr++= keyseg->null_bit;
954
  *ptr++= keyseg->bit_start;
955
  *ptr++= keyseg->bit_end;
956
  *ptr++= keyseg->bit_length;
957
  mi_int2store(ptr,keyseg->flag);	ptr+=2;
958
  mi_int2store(ptr,keyseg->length);	ptr+=2;
959
  mi_int4store(ptr,keyseg->start);	ptr+=4;
960
  pos= keyseg->null_bit ? keyseg->null_pos : keyseg->bit_pos;
961
  mi_int4store(ptr, pos);
962
  ptr+=4;
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
963
1 by brian
clean slate
964
  return my_write(file, buff, (size_t) (ptr-buff), MYF(MY_NABP)) != 0;
965
}
966
967
481 by Brian Aker
Remove all of uchar.
968
unsigned char *mi_keyseg_read(unsigned char *ptr, HA_KEYSEG *keyseg)
1 by brian
clean slate
969
{
970
   keyseg->type		= *ptr++;
971
   keyseg->language	= *ptr++;
972
   keyseg->null_bit	= *ptr++;
973
   keyseg->bit_start	= *ptr++;
974
   keyseg->bit_end	= *ptr++;
975
   keyseg->bit_length   = *ptr++;
976
   keyseg->flag		= mi_uint2korr(ptr);  ptr +=2;
977
   keyseg->length	= mi_uint2korr(ptr);  ptr +=2;
978
   keyseg->start	= mi_uint4korr(ptr);  ptr +=4;
979
   keyseg->null_pos	= mi_uint4korr(ptr);  ptr +=4;
980
   keyseg->charset=0;				/* Will be filled in later */
981
   if (keyseg->null_bit)
206 by Brian Aker
Removed final uint dead types.
982
     keyseg->bit_pos= (uint16_t)(keyseg->null_pos + (keyseg->null_bit == 7));
1 by brian
clean slate
983
   else
984
   {
206 by Brian Aker
Removed final uint dead types.
985
     keyseg->bit_pos= (uint16_t)keyseg->null_pos;
1 by brian
clean slate
986
     keyseg->null_pos= 0;
987
   }
988
   return ptr;
989
}
990
991
/*--------------------------------------------------------------------------
992
  mi_uniquedef
993
---------------------------------------------------------------------------*/
994
482 by Brian Aker
Remove uint.
995
uint32_t mi_uniquedef_write(File file, MI_UNIQUEDEF *def)
1 by brian
clean slate
996
{
481 by Brian Aker
Remove all of uchar.
997
  unsigned char buff[MI_UNIQUEDEF_SIZE];
998
  unsigned char *ptr=buff;
1 by brian
clean slate
999
1000
  mi_int2store(ptr,def->keysegs);		ptr+=2;
481 by Brian Aker
Remove all of uchar.
1001
  *ptr++=  (unsigned char) def->key;
1002
  *ptr++ = (unsigned char) def->null_are_equal;
1 by brian
clean slate
1003
1004
  return my_write(file, buff, (size_t) (ptr-buff), MYF(MY_NABP)) != 0;
1005
}
1006
481 by Brian Aker
Remove all of uchar.
1007
unsigned char *mi_uniquedef_read(unsigned char *ptr, MI_UNIQUEDEF *def)
1 by brian
clean slate
1008
{
1009
   def->keysegs = mi_uint2korr(ptr);
1010
   def->key	= ptr[2];
1011
   def->null_are_equal=ptr[3];
1012
   return ptr+4;				/* 1 extra byte */
1013
}
1014
1015
/***************************************************************************
1016
**  MI_COLUMNDEF
1017
***************************************************************************/
1018
482 by Brian Aker
Remove uint.
1019
uint32_t mi_recinfo_write(File file, MI_COLUMNDEF *recinfo)
1 by brian
clean slate
1020
{
481 by Brian Aker
Remove all of uchar.
1021
  unsigned char buff[MI_COLUMNDEF_SIZE];
1022
  unsigned char *ptr=buff;
1 by brian
clean slate
1023
1024
  mi_int2store(ptr,recinfo->type);	ptr +=2;
1025
  mi_int2store(ptr,recinfo->length);	ptr +=2;
1026
  *ptr++ = recinfo->null_bit;
1027
  mi_int2store(ptr,recinfo->null_pos);	ptr+= 2;
1028
  return my_write(file, buff, (size_t) (ptr-buff), MYF(MY_NABP)) != 0;
1029
}
1030
481 by Brian Aker
Remove all of uchar.
1031
unsigned char *mi_recinfo_read(unsigned char *ptr, MI_COLUMNDEF *recinfo)
1 by brian
clean slate
1032
{
1033
   recinfo->type=  mi_sint2korr(ptr);	ptr +=2;
1034
   recinfo->length=mi_uint2korr(ptr);	ptr +=2;
206 by Brian Aker
Removed final uint dead types.
1035
   recinfo->null_bit= (uint8_t) *ptr++;
1 by brian
clean slate
1036
   recinfo->null_pos=mi_uint2korr(ptr); ptr +=2;
1037
   return ptr;
1038
}
1039
1040
/**************************************************************************
489.1.6 by Monty Taylor
Removed RAID garbage.
1041
Open data file
1 by brian
clean slate
1042
We can't use dup() here as the data file descriptors need to have different
1043
active seek-positions.
1044
1045
The argument file_to_dup is here for the future if there would on some OS
1046
exist a dup()-like call that would give us two different file descriptors.
1047
*************************************************************************/
1048
1049
int mi_open_datafile(MI_INFO *info, MYISAM_SHARE *share,
1050
                     File file_to_dup __attribute__((unused)))
1051
{
492.1.13 by Monty Taylor
Removed O_SHARE. I think it was only for OS/2.
1052
    info->dfile=my_open(share->data_file_name, share->mode,
1 by brian
clean slate
1053
			MYF(MY_WME));
1054
  return info->dfile >= 0 ? 0 : 1;
1055
}
1056
1057
1058
int mi_open_keyfile(MYISAM_SHARE *share)
1059
{
492.1.13 by Monty Taylor
Removed O_SHARE. I think it was only for OS/2.
1060
  if ((share->kfile=my_open(share->unique_file_name, share->mode,
1 by brian
clean slate
1061
                            MYF(MY_WME))) < 0)
1062
    return 1;
1063
  return 0;
1064
}
1065
1066
1067
/*
1068
  Disable all indexes.
1069
1070
  SYNOPSIS
1071
    mi_disable_indexes()
1072
    info        A pointer to the MyISAM storage engine MI_INFO struct.
1073
1074
  DESCRIPTION
1075
    Disable all indexes.
1076
1077
  RETURN
1078
    0  ok
1079
*/
1080
1081
int mi_disable_indexes(MI_INFO *info)
1082
{
1083
  MYISAM_SHARE *share= info->s;
1084
1085
  mi_clear_all_keys_active(share->state.key_map);
1086
  return 0;
1087
}
1088
1089
1090
/*
1091
  Enable all indexes
1092
1093
  SYNOPSIS
1094
    mi_enable_indexes()
1095
    info        A pointer to the MyISAM storage engine MI_INFO struct.
1096
1097
  DESCRIPTION
1098
    Enable all indexes. The indexes might have been disabled
1099
    by mi_disable_index() before.
1100
    The function works only if both data and indexes are empty,
1101
    otherwise a repair is required.
1102
    To be sure, call handler::delete_all_rows() before.
1103
1104
  RETURN
1105
    0  ok
1106
    HA_ERR_CRASHED data or index is non-empty.
1107
*/
1108
1109
int mi_enable_indexes(MI_INFO *info)
1110
{
1111
  int error= 0;
1112
  MYISAM_SHARE *share= info->s;
1113
1114
  if (share->state.state.data_file_length ||
1115
      (share->state.state.key_file_length != share->base.keystart))
1116
  {
1117
    mi_print_error(info->s, HA_ERR_CRASHED);
1118
    error= HA_ERR_CRASHED;
1119
  }
1120
  else
1121
    mi_set_all_keys_active(share->state.key_map, share->base.keys);
1122
  return error;
1123
}
1124
1125
1126
/*
1127
  Test if indexes are disabled.
1128
1129
  SYNOPSIS
1130
    mi_indexes_are_disabled()
1131
    info        A pointer to the MyISAM storage engine MI_INFO struct.
1132
1133
  DESCRIPTION
1134
    Test if indexes are disabled.
1135
1136
  RETURN
1137
    0  indexes are not disabled
1138
    1  all indexes are disabled
1139
    2  non-unique indexes are disabled
1140
*/
1141
1142
int mi_indexes_are_disabled(MI_INFO *info)
1143
{
1144
  MYISAM_SHARE *share= info->s;
1145
1146
  /*
1147
    No keys or all are enabled. keys is the number of keys. Left shifted
1148
    gives us only one bit set. When decreased by one, gives us all all bits
1149
    up to this one set and it gets unset.
1150
  */
1151
  if (!share->base.keys ||
1152
      (mi_is_all_keys_active(share->state.key_map, share->base.keys)))
1153
    return 0;
1154
1155
  /* All are disabled */
1156
  if (mi_is_any_key_active(share->state.key_map))
1157
    return 1;
1158
1159
  /*
1160
    We have keys. Some enabled, some disabled.
1161
    Don't check for any non-unique disabled but return directly 2
1162
  */
1163
  return 2;
1164
}
1165