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