1
/* Copyright (C) 2006 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
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.
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.
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 */
16
/* open a isam-database */
18
#include "ma_fulltext.h"
19
#include "ma_sp_defs.h"
20
#include "ma_rt_index.h"
21
#include "ma_blockrec.h"
24
#if defined(MSDOS) || defined(__WIN__)
28
#include <process.h> /* Prototype for getpid */
32
static void setup_key_functions(MARIA_KEYDEF *keyinfo);
33
static my_bool maria_scan_init_dummy(MARIA_HA *info);
34
static void maria_scan_end_dummy(MARIA_HA *info);
35
static my_bool maria_once_init_dummy(MARIA_SHARE *, File);
36
static my_bool maria_once_end_dummy(MARIA_SHARE *);
37
static uchar *_ma_base_info_read(uchar *ptr, MARIA_BASE_INFO *base);
38
static uchar *_ma_state_info_read(uchar *ptr, MARIA_STATE_INFO *state);
40
#define get_next_element(to,pos,size) { memcpy((char*) to,pos,(size_t) size); \
44
#define disk_pos_assert(pos, end_pos) \
47
my_errno=HA_ERR_CRASHED; \
52
/******************************************************************************
53
** Return the shared struct if the table is already open.
54
** In MySQL the server will handle version issues.
55
******************************************************************************/
57
MARIA_HA *_ma_test_if_reopen(const char *filename)
61
for (pos=maria_open_list ; pos ; pos=pos->next)
63
MARIA_HA *info=(MARIA_HA*) pos->data;
64
MARIA_SHARE *share= info->s;
65
if (!strcmp(share->unique_file_name,filename) && share->last_version)
73
Open a new instance of an already opened Maria table
76
maria_clone_internal()
77
share Share of already open table
78
mode Mode of table (O_RDONLY | O_RDWR)
79
data_file Filedescriptor of data file to use < 0 if one should open
88
static MARIA_HA *maria_clone_internal(MARIA_SHARE *share, int mode,
93
MARIA_HA info,*m_info;
94
my_bitmap_map *changed_fields_bitmap;
95
DBUG_ENTER("maria_clone_internal");
98
bzero((uchar*) &info,sizeof(info));
100
if (mode == O_RDWR && share->mode == O_RDONLY)
102
my_errno=EACCES; /* Can't open in write mode */
106
info.dfile.file= data_file;
107
else if (_ma_open_datafile(&info, share, -1))
111
/* alloc and set up private structure parts */
112
if (!my_multi_malloc(MY_WME,
113
&m_info,sizeof(MARIA_HA),
114
&info.blobs,sizeof(MARIA_BLOB)*share->base.blobs,
115
&info.buff,(share->base.max_key_block_length*2+
116
share->base.max_key_length),
117
&info.lastkey_buff,share->base.max_key_length*2+1,
118
&info.first_mbr_key, share->base.max_key_length,
119
&info.maria_rtree_recursion_state,
120
share->have_rtree ? 1024 : 0,
121
&changed_fields_bitmap,
122
bitmap_buffer_size(share->base.fields),
127
memcpy(info.blobs,share->blobs,sizeof(MARIA_BLOB)*share->base.blobs);
128
info.lastkey_buff2= info.lastkey_buff + share->base.max_key_length;
129
info.last_key.data= info.lastkey_buff;
132
info.cur_row.lastpos= HA_OFFSET_ERROR;
133
info.update= (short) (HA_STATE_NEXT_FOUND+HA_STATE_PREV_FOUND);
134
info.opt_flag=READ_CHECK_USED;
135
info.this_unique= (ulong) info.dfile.file; /* Uniq number in process */
136
#ifdef EXTERNAL_LOCKING
137
if (share->data_file_type == COMPRESSED_RECORD)
138
info.this_unique= share->state.unique;
139
info.this_loop=0; /* Update counter */
140
info.last_unique= share->state.unique;
141
info.last_loop= share->state.update_count;
145
info.keyread_buff= info.buff + share->base.max_key_block_length;
147
info.lock_type= F_UNLCK;
148
if (share->options & HA_OPTION_TMP_TABLE)
149
info.lock_type= F_WRLCK;
151
_ma_set_data_pagecache_callbacks(&info.dfile, share);
152
bitmap_init(&info.changed_fields, changed_fields_bitmap,
153
share->base.fields, 0);
154
if ((*share->init)(&info))
157
/* The following should be big enough for all pinning purposes */
158
if (my_init_dynamic_array(&info.pinned_pages,
159
sizeof(MARIA_PINNED_PAGE),
160
max(share->base.blobs*2 + 4,
161
MARIA_MAX_TREE_LEVELS*3), 16))
165
pthread_mutex_lock(&share->intern_lock);
166
info.read_record= share->read_record;
168
share->write_flag=MYF(MY_NABP | MY_WAIT_IF_FULL);
169
if (share->options & HA_OPTION_READ_ONLY_DATA)
171
info.lock_type=F_RDLCK;
175
if ((share->options & HA_OPTION_DELAY_KEY_WRITE) &&
176
maria_delay_key_write)
177
share->delay_key_write=1;
179
if (!share->base.born_transactional) /* For transactional ones ... */
181
info.trn= &dummy_transaction_object; /* ... force crash if no trn given */
182
info.state= &share->state.state; /* Change global values by default */
186
info.state= &share->state.common;
187
*info.state= share->state.state; /* Initial values */
189
info.state_start= info.state; /* Initial values */
191
pthread_mutex_unlock(&share->intern_lock);
193
/* Allocate buffer for one record */
194
/* prerequisites: info->rec_buffer == 0 && info->rec_buff_size == 0 */
195
if (_ma_alloc_buffer(&info.rec_buff, &info.rec_buff_size,
196
share->base.default_rec_buff_size))
199
bzero(info.rec_buff, share->base.default_rec_buff_size);
203
thr_lock_data_init(&share->lock,&m_info->lock,(void*) m_info);
205
m_info->open_list.data=(void*) m_info;
206
maria_open_list=list_add(maria_open_list,&m_info->open_list);
211
save_errno=my_errno ? my_errno : HA_ERR_END_OF_FILE;
212
if ((save_errno == HA_ERR_CRASHED) ||
213
(save_errno == HA_ERR_CRASHED_ON_USAGE) ||
214
(save_errno == HA_ERR_CRASHED_ON_REPAIR))
215
_ma_report_error(save_errno, share->open_file_name);
218
(*share->end)(&info);
219
delete_dynamic(&info.pinned_pages);
220
my_free(m_info, MYF(0));
224
(void)(my_close(info.dfile.file, MYF(0)));
229
} /* maria_clone_internal */
232
/* Make a clone of a maria table */
234
MARIA_HA *maria_clone(MARIA_SHARE *share, int mode)
237
pthread_mutex_lock(&THR_LOCK_maria);
238
new_info= maria_clone_internal(share, mode,
239
share->data_file_type == BLOCK_RECORD ?
240
share->bitmap.file.file : -1);
241
pthread_mutex_unlock(&THR_LOCK_maria);
246
/******************************************************************************
249
See my_base.h for the handle_locking argument
250
if handle_locking and HA_OPEN_ABORT_IF_CRASHED then abort if the table
251
is marked crashed or if we are not using locking and the table doesn't
252
have an open count of 0.
253
******************************************************************************/
255
MARIA_HA *maria_open(const char *name, int mode, uint open_flags)
257
int kfile,open_mode,save_errno;
258
uint i,j,len,errpos,head_length,base_pos,info_length,keys,
259
key_parts,unique_key_parts,fulltext_keys,uniques;
260
char name_buff[FN_REFLEN], org_name[FN_REFLEN], index_name[FN_REFLEN],
261
data_name[FN_REFLEN];
262
uchar *disk_cache, *disk_pos, *end_pos;
263
MARIA_HA info,*m_info,*old_info;
264
MARIA_SHARE share_buff,*share;
265
double rec_per_key_part[HA_MAX_POSSIBLE_KEY*HA_MAX_KEY_SEG];
266
ulong nulls_per_key_part[HA_MAX_POSSIBLE_KEY*HA_MAX_KEY_SEG];
267
my_off_t key_root[HA_MAX_POSSIBLE_KEY];
268
ulonglong max_key_file_length, max_data_file_length;
269
my_bool versioning= 1;
271
DBUG_ENTER("maria_open");
276
head_length=sizeof(share_buff.state.header);
277
bzero((uchar*) &info,sizeof(info));
279
my_realpath(name_buff, fn_format(org_name,name,"",MARIA_NAME_IEXT,
280
MY_UNPACK_FILENAME),MYF(0));
281
pthread_mutex_lock(&THR_LOCK_maria);
283
if ((open_flags & HA_OPEN_COPY) ||
284
!(old_info=_ma_test_if_reopen(name_buff)))
287
bzero((uchar*) &share_buff,sizeof(share_buff));
288
share_buff.state.rec_per_key_part= rec_per_key_part;
289
share_buff.state.nulls_per_key_part= nulls_per_key_part;
290
share_buff.state.key_root=key_root;
291
share_buff.pagecache= multi_pagecache_search((uchar*) name_buff,
292
(uint) strlen(name_buff),
295
DBUG_EXECUTE_IF("maria_pretend_crashed_table_on_open",
296
if (strstr(name, "/t1"))
298
my_errno= HA_ERR_CRASHED;
301
if ((kfile=my_open(name_buff,(open_mode=O_RDWR) | O_SHARE,MYF(0))) < 0)
303
if ((errno != EROFS && errno != EACCES) ||
305
(kfile=my_open(name_buff,(open_mode=O_RDONLY) | O_SHARE,MYF(0))) < 0)
308
share->mode=open_mode;
310
if (my_pread(kfile,share->state.header.file_version, head_length, 0,
313
my_errno= HA_ERR_NOT_A_TABLE;
316
if (memcmp((uchar*) share->state.header.file_version,
317
(uchar*) maria_file_magic, 4))
319
DBUG_PRINT("error",("Wrong header in %s",name_buff));
320
DBUG_DUMP("error_dump", share->state.header.file_version,
322
my_errno=HA_ERR_NOT_A_TABLE;
325
share->options= mi_uint2korr(share->state.header.options);
327
~(HA_OPTION_PACK_RECORD | HA_OPTION_PACK_KEYS |
328
HA_OPTION_COMPRESS_RECORD | HA_OPTION_READ_ONLY_DATA |
329
HA_OPTION_TEMP_COMPRESS_RECORD | HA_OPTION_CHECKSUM |
330
HA_OPTION_TMP_TABLE | HA_OPTION_DELAY_KEY_WRITE |
331
HA_OPTION_RELIES_ON_SQL_LAYER | HA_OPTION_NULL_FIELDS |
332
HA_OPTION_PAGE_CHECKSUM))
334
DBUG_PRINT("error",("wrong options: 0x%lx", share->options));
335
my_errno=HA_ERR_NEW_FILE;
338
if ((share->options & HA_OPTION_RELIES_ON_SQL_LAYER) &&
339
! (open_flags & HA_OPEN_FROM_SQL_LAYER))
341
DBUG_PRINT("error", ("table cannot be opened from non-sql layer"));
342
my_errno= HA_ERR_UNSUPPORTED;
345
/* Don't call realpath() if the name can't be a link */
346
if (!strcmp(name_buff, org_name) ||
347
my_readlink(index_name, org_name, MYF(0)) == -1)
348
(void) strmov(index_name, org_name);
349
*strrchr(org_name, '.')= '\0';
350
(void) fn_format(data_name,org_name,"",MARIA_NAME_DEXT,
351
MY_APPEND_EXT|MY_UNPACK_FILENAME|MY_RESOLVE_SYMLINKS);
353
info_length=mi_uint2korr(share->state.header.header_length);
354
base_pos= mi_uint2korr(share->state.header.base_pos);
355
if (!(disk_cache= (uchar*) my_alloca(info_length+128)))
360
end_pos=disk_cache+info_length;
362
if (my_pread(kfile, disk_cache, info_length, 0L, MYF(MY_NABP)))
364
my_errno=HA_ERR_CRASHED;
367
len=mi_uint2korr(share->state.header.state_info_length);
368
keys= (uint) share->state.header.keys;
369
uniques= (uint) share->state.header.uniques;
370
fulltext_keys= (uint) share->state.header.fulltext_keys;
371
key_parts= mi_uint2korr(share->state.header.key_parts);
372
unique_key_parts= mi_uint2korr(share->state.header.unique_key_parts);
373
if (len != MARIA_STATE_INFO_SIZE)
375
DBUG_PRINT("warning",
376
("saved_state_info_length: %d state_info_length: %d",
377
len,MARIA_STATE_INFO_SIZE));
379
share->state_diff_length=len-MARIA_STATE_INFO_SIZE;
381
_ma_state_info_read(disk_cache, &share->state);
382
len= mi_uint2korr(share->state.header.base_info_length);
383
if (len != MARIA_BASE_INFO_SIZE)
385
DBUG_PRINT("warning",("saved_base_info_length: %d base_info_length: %d",
386
len,MARIA_BASE_INFO_SIZE));
388
disk_pos= _ma_base_info_read(disk_cache + base_pos, &share->base);
389
share->state.state_length=base_pos;
391
if (!(open_flags & HA_OPEN_FOR_REPAIR) &&
392
((share->state.changed & STATE_CRASHED) ||
393
((open_flags & HA_OPEN_ABORT_IF_CRASHED) &&
394
(my_disable_locking && share->state.open_count))))
396
DBUG_PRINT("error",("Table is marked as crashed. open_flags: %u "
397
"changed: %u open_count: %u !locking: %d",
398
open_flags, share->state.changed,
399
share->state.open_count, my_disable_locking));
400
my_errno=((share->state.changed & STATE_CRASHED_ON_REPAIR) ?
401
HA_ERR_CRASHED_ON_REPAIR : HA_ERR_CRASHED_ON_USAGE);
406
We can ignore testing uuid if STATE_NOT_MOVABLE is set, as in this
407
case the uuid will be set in _ma_mark_file_changed()
409
if ((share->state.changed & STATE_NOT_MOVABLE) &&
410
share->base.born_transactional &&
411
((!(open_flags & HA_OPEN_IGNORE_MOVED_STATE) &&
412
memcmp(share->base.uuid, maria_uuid, MY_UUID_SIZE)) ||
413
share->state.create_trid > trnman_get_max_trid()))
415
if (open_flags & HA_OPEN_FOR_REPAIR)
416
share->state.changed|= STATE_MOVED;
419
my_errno= HA_ERR_OLD_FILE;
425
if (share->base.keystart > 65535 || share->base.rec_reflength > 8)
427
my_errno=HA_ERR_CRASHED;
431
key_parts+=fulltext_keys*FT_SEGS;
432
if (share->base.max_key_length > maria_max_key_length() ||
433
keys > MARIA_MAX_KEY || key_parts > MARIA_MAX_KEY * HA_MAX_KEY_SEG)
435
DBUG_PRINT("error",("Wrong key info: Max_key_length: %d keys: %d key_parts: %d", share->base.max_key_length, keys, key_parts));
436
my_errno=HA_ERR_UNSUPPORTED;
440
/* Ensure we have space in the key buffer for transaction id's */
441
if (share->base.born_transactional)
442
share->base.max_key_length= ALIGN_SIZE(share->base.max_key_length +
443
MAX_PACK_TRANSID_SIZE);
446
If page cache is not initialized, then assume we will create the
447
page_cache after the table is opened!
448
This is only used by maria_check to allow it to check/repair tables
449
with different block sizes.
451
if (share->base.block_size != maria_block_size &&
452
share_buff.pagecache->inited != 0)
454
DBUG_PRINT("error", ("Wrong block size %u; Expected %u",
455
(uint) share->base.block_size,
456
(uint) maria_block_size));
457
my_errno=HA_ERR_UNSUPPORTED;
461
/* Correct max_file_length based on length of sizeof(off_t) */
462
max_data_file_length=
463
(share->options & (HA_OPTION_PACK_RECORD | HA_OPTION_COMPRESS_RECORD)) ?
464
(((ulonglong) 1 << (share->base.rec_reflength*8))-1) :
465
(_ma_safe_mul(share->base.pack_reclength,
466
(ulonglong) 1 << (share->base.rec_reflength*8))-1);
469
_ma_safe_mul(maria_block_size,
470
((ulonglong) 1 << (share->base.key_reflength*8))-1);
471
#if SIZEOF_OFF_T == 4
472
set_if_smaller(max_data_file_length, INT_MAX32);
473
set_if_smaller(max_key_file_length, INT_MAX32);
475
share->base.max_data_file_length=(my_off_t) max_data_file_length;
476
share->base.max_key_file_length=(my_off_t) max_key_file_length;
478
if (share->options & HA_OPTION_COMPRESS_RECORD)
479
share->base.max_key_length+=2; /* For safety */
480
/* Add space for node pointer */
481
share->base.max_key_length+= share->base.key_reflength;
483
if (!my_multi_malloc(MY_WME,
484
&share,sizeof(*share),
485
&share->state.rec_per_key_part,
486
sizeof(double) * key_parts,
487
&share->state.nulls_per_key_part,
488
sizeof(long)* key_parts,
489
&share->keyinfo,keys*sizeof(MARIA_KEYDEF),
490
&share->uniqueinfo,uniques*sizeof(MARIA_UNIQUEDEF),
492
(key_parts+unique_key_parts+keys+uniques) *
495
(share->base.fields+1)*sizeof(MARIA_COLUMNDEF),
496
&share->column_nr, share->base.fields*sizeof(uint16),
497
&share->blobs,sizeof(MARIA_BLOB)*share->base.blobs,
498
&share->unique_file_name,strlen(name_buff)+1,
499
&share->index_file_name,strlen(index_name)+1,
500
&share->data_file_name,strlen(data_name)+1,
501
&share->open_file_name,strlen(name)+1,
502
&share->state.key_root,keys*sizeof(my_off_t),
503
&share->mmap_lock,sizeof(rw_lock_t),
509
memcpy((char*) share->state.rec_per_key_part,
510
(char*) rec_per_key_part, sizeof(double)*key_parts);
511
memcpy((char*) share->state.nulls_per_key_part,
512
(char*) nulls_per_key_part, sizeof(long)*key_parts);
513
memcpy((char*) share->state.key_root,
514
(char*) key_root, sizeof(my_off_t)*keys);
515
strmov(share->unique_file_name, name_buff);
516
share->unique_name_length= (uint) strlen(name_buff);
517
strmov(share->index_file_name, index_name);
518
strmov(share->data_file_name, data_name);
519
strmov(share->open_file_name, name);
521
share->block_size= share->base.block_size; /* Convenience */
523
HA_KEYSEG *pos=share->keyparts;
524
for (i=0 ; i < keys ; i++)
526
share->keyinfo[i].share= share;
527
disk_pos=_ma_keydef_read(disk_pos, &share->keyinfo[i]);
528
share->keyinfo[i].key_nr= i;
529
disk_pos_assert(disk_pos + share->keyinfo[i].keysegs * HA_KEYSEG_SIZE,
531
if (share->keyinfo[i].key_alg == HA_KEY_ALG_RTREE)
532
share->have_rtree= 1;
533
share->keyinfo[i].seg=pos;
534
for (j=0 ; j < share->keyinfo[i].keysegs; j++,pos++)
536
disk_pos=_ma_keyseg_read(disk_pos, pos);
537
if (pos->type == HA_KEYTYPE_TEXT ||
538
pos->type == HA_KEYTYPE_VARTEXT1 ||
539
pos->type == HA_KEYTYPE_VARTEXT2)
542
pos->charset=default_charset_info;
543
else if (!(pos->charset= get_charset(pos->language, MYF(MY_WME))))
545
my_errno=HA_ERR_UNKNOWN_CHARSET;
549
else if (pos->type == HA_KEYTYPE_BINARY)
550
pos->charset= &my_charset_bin;
552
if (share->keyinfo[i].flag & HA_SPATIAL)
555
uint sp_segs=SPDIMS*2;
556
share->keyinfo[i].seg=pos-sp_segs;
557
share->keyinfo[i].keysegs--;
560
my_errno=HA_ERR_UNSUPPORTED;
564
else if (share->keyinfo[i].flag & HA_FULLTEXT)
567
DBUG_ASSERT(fulltext_keys);
570
share->keyinfo[i].seg=pos;
571
for (k=0; k < FT_SEGS; k++)
574
pos[0].language= pos[-1].language;
575
if (!(pos[0].charset= pos[-1].charset))
577
my_errno=HA_ERR_CRASHED;
583
if (!share->ft2_keyinfo.seg)
585
memcpy(&share->ft2_keyinfo, &share->keyinfo[i],
586
sizeof(MARIA_KEYDEF));
587
share->ft2_keyinfo.keysegs=1;
588
share->ft2_keyinfo.flag=0;
589
share->ft2_keyinfo.keylength=
590
share->ft2_keyinfo.minlength=
591
share->ft2_keyinfo.maxlength=HA_FT_WLEN+share->base.rec_reflength;
592
share->ft2_keyinfo.seg=pos-1;
593
share->ft2_keyinfo.end=pos;
594
setup_key_functions(& share->ft2_keyinfo);
597
setup_key_functions(share->keyinfo+i);
598
share->keyinfo[i].end=pos;
599
pos->type=HA_KEYTYPE_END; /* End */
600
pos->length=share->base.rec_reflength;
602
pos->flag=0; /* For purify */
605
if ((share->keyinfo[i].flag & HA_NOSAME) && i != 0)
608
We can't yet have versioning if there is more than one unique
614
for (i=0 ; i < uniques ; i++)
616
disk_pos=_ma_uniquedef_read(disk_pos, &share->uniqueinfo[i]);
617
disk_pos_assert(disk_pos + share->uniqueinfo[i].keysegs *
618
HA_KEYSEG_SIZE, end_pos);
619
share->uniqueinfo[i].seg=pos;
620
for (j=0 ; j < share->uniqueinfo[i].keysegs; j++,pos++)
622
disk_pos=_ma_keyseg_read(disk_pos, pos);
623
if (pos->type == HA_KEYTYPE_TEXT ||
624
pos->type == HA_KEYTYPE_VARTEXT1 ||
625
pos->type == HA_KEYTYPE_VARTEXT2)
628
pos->charset=default_charset_info;
629
else if (!(pos->charset= get_charset(pos->language, MYF(MY_WME))))
631
my_errno=HA_ERR_UNKNOWN_CHARSET;
636
share->uniqueinfo[i].end=pos;
637
pos->type=HA_KEYTYPE_END; /* End */
644
share->data_file_type= share->state.header.data_file_type;
645
share->base_length= (BASE_ROW_HEADER_SIZE +
646
share->base.is_nulls_extended +
647
share->base.null_bytes +
648
share->base.pack_bytes +
649
test(share->options & HA_OPTION_CHECKSUM));
650
share->keypage_header= ((share->base.born_transactional ?
651
LSN_STORE_SIZE + TRANSID_SIZE :
652
0) + KEYPAGE_KEYID_SIZE + KEYPAGE_FLAG_SIZE +
654
share->kfile.file= kfile;
656
if (open_flags & HA_OPEN_COPY)
659
this instance will be a temporary one used just to create a data
660
file for REPAIR. Don't do logging. This base information will not go
663
share->base.born_transactional= FALSE;
665
if (share->base.born_transactional)
667
share->page_type= PAGECACHE_LSN_PAGE;
668
if (share->state.create_rename_lsn == LSN_REPAIRED_BY_MARIA_CHK)
671
Was repaired with maria_chk, maybe later maria_pack-ed. Some sort of
672
import into the server. It starts its existence (from the point of
673
view of the server, including server's recovery) now.
675
if (((open_flags & HA_OPEN_FROM_SQL_LAYER) &&
676
(share->state.changed & STATE_NOT_MOVABLE)) || maria_in_recovery)
677
_ma_update_state_lsns_sub(share, translog_get_horizon(),
678
trnman_get_min_safe_trid(), TRUE, TRUE);
680
else if ((!LSN_VALID(share->state.create_rename_lsn) ||
681
!LSN_VALID(share->state.is_of_horizon) ||
682
(cmp_translog_addr(share->state.create_rename_lsn,
683
share->state.is_of_horizon) > 0) ||
684
!LSN_VALID(share->state.skip_redo_lsn) ||
685
(cmp_translog_addr(share->state.create_rename_lsn,
686
share->state.skip_redo_lsn) > 0)) &&
687
!(open_flags & HA_OPEN_FOR_REPAIR))
690
If in Recovery, it will not work. If LSN is invalid and not
691
LSN_REPAIRED_BY_MARIA_CHK, header must be corrupted.
692
In both cases, must repair.
694
my_errno=((share->state.changed & STATE_CRASHED_ON_REPAIR) ?
695
HA_ERR_CRASHED_ON_REPAIR : HA_ERR_CRASHED_ON_USAGE);
700
share->page_type= PAGECACHE_PLAIN_PAGE;
701
share->now_transactional= share->base.born_transactional;
703
/* Use pack_reclength as we don't want to modify base.pack_recklength */
704
if (share->state.header.org_data_file_type == DYNAMIC_RECORD)
706
/* add bits used to pack data to pack_reclength for faster allocation */
707
share->base.pack_reclength+= share->base.pack_bytes;
708
share->base.extra_rec_buff_size=
709
(ALIGN_SIZE(MARIA_MAX_DYN_BLOCK_HEADER) + MARIA_SPLIT_LENGTH +
710
MARIA_REC_BUFF_OFFSET);
712
if (share->data_file_type == COMPRESSED_RECORD)
714
/* Need some extra bytes for decode_bytes */
715
share->base.extra_rec_buff_size+= 7;
717
share->base.default_rec_buff_size= max(share->base.pack_reclength +
718
share->base.extra_rec_buff_size,
719
share->base.max_key_length);
721
disk_pos_assert(disk_pos + share->base.fields *MARIA_COLUMNDEF_SIZE,
723
for (i= j= 0 ; i < share->base.fields ; i++)
725
disk_pos=_ma_columndef_read(disk_pos,&share->columndef[i]);
726
share->columndef[i].pack_type=0;
727
share->columndef[i].huff_tree=0;
728
if (share->columndef[i].type == FIELD_BLOB)
730
share->blobs[j].pack_length=
731
share->columndef[i].length-portable_sizeof_char_ptr;
732
share->blobs[j].offset= share->columndef[i].offset;
736
share->columndef[i].type= FIELD_LAST; /* End marker */
737
disk_pos= _ma_column_nr_read(disk_pos, share->column_nr,
740
if ((share->data_file_type == BLOCK_RECORD ||
741
share->data_file_type == COMPRESSED_RECORD))
743
if (_ma_open_datafile(&info, share, -1))
745
data_file= info.dfile.file;
749
if (open_flags & HA_OPEN_DELAY_KEY_WRITE)
750
share->options|= HA_OPTION_DELAY_KEY_WRITE;
751
if (mode == O_RDONLY)
752
share->options|= HA_OPTION_READ_ONLY_DATA;
753
share->is_log_table= FALSE;
755
if (open_flags & HA_OPEN_TMP_TABLE)
757
share->options|= HA_OPTION_TMP_TABLE;
758
share->temporary= share->delay_key_write= 1;
759
share->write_flag=MYF(MY_NABP);
760
share->w_locks++; /* We don't have to update status */
764
_ma_set_index_pagecache_callbacks(&share->kfile, share);
765
share->this_process=(ulong) getpid();
766
#ifdef EXTERNAL_LOCKING
767
share->last_process= share->state.process;
769
share->base.key_parts=key_parts;
770
share->base.all_key_parts=key_parts+unique_key_parts;
771
if (!(share->last_version=share->state.version))
772
share->last_version=1; /* Safety */
773
share->rec_reflength=share->base.rec_reflength; /* May be changed */
774
share->base.margin_key_file_length=(share->base.max_key_file_length -
775
(keys ? MARIA_INDEX_BLOCK_MARGIN *
776
share->block_size * keys : 0));
777
share->block_size= share->base.block_size;
778
my_afree(disk_cache);
779
_ma_setup_functions(share);
780
if ((*share->once_init)(share, info.dfile.file))
782
if (share->now_transactional)
784
/* Setup initial state that is visible for all */
785
MARIA_STATE_HISTORY_CLOSED *history;
786
if ((history= (MARIA_STATE_HISTORY_CLOSED *)
787
hash_search(&maria_stored_state,
788
(uchar*) &share->state.create_rename_lsn, 0)))
790
/* Move history from hash to share */
791
share->state_history=
792
_ma_remove_not_visible_states(history->state_history, 0, 0);
793
history->state_history= 0;
794
(void) hash_delete(&maria_stored_state, (uchar*) history);
798
/* Table is not part of any active transaction; Create new history */
799
if (!(share->state_history= (MARIA_STATE_HISTORY *)
800
my_malloc(sizeof(*share->state_history), MYF(MY_WME))))
802
share->state_history->trid= 0; /* Visibly by all */
803
share->state_history->state= share->state.state;
804
share->state_history->next= 0;
808
thr_lock_init(&share->lock);
809
(void)(pthread_mutex_init(&share->intern_lock, MY_MUTEX_INIT_FAST));
810
(void)(pthread_cond_init(&share->intern_cond, 0));
811
for (i=0; i<keys; i++)
812
(void)(my_rwlock_init(&share->keyinfo[i].root_lock, NULL));
813
(void)(my_rwlock_init(&share->mmap_lock, NULL));
815
share->row_is_visible= _ma_row_visible_always;
816
if (!thr_lock_inited)
818
/* Probably a single threaded program; Don't use concurrent inserts */
819
maria_concurrent_insert=0;
821
else if (maria_concurrent_insert)
823
share->non_transactional_concurrent_insert=
824
((share->options & (HA_OPTION_READ_ONLY_DATA | HA_OPTION_TMP_TABLE |
825
HA_OPTION_COMPRESS_RECORD |
826
HA_OPTION_TEMP_COMPRESS_RECORD)) ||
827
(open_flags & HA_OPEN_TMP_TABLE) ||
828
share->data_file_type == BLOCK_RECORD ||
829
share->have_rtree) ? 0 : 1;
830
if (share->non_transactional_concurrent_insert ||
831
(!share->temporary && share->now_transactional && versioning))
833
share->lock_key_trees= 1;
834
if (share->data_file_type == BLOCK_RECORD)
836
DBUG_ASSERT(share->now_transactional);
837
share->have_versioning= 1;
838
share->row_is_visible= _ma_row_visible_transactional_table;
839
share->lock.get_status= _ma_block_get_status;
840
share->lock.update_status= _ma_block_update_status;
841
share->lock.check_status= _ma_block_check_status;
843
We can for the moment only allow multiple concurrent inserts
844
only if there is no auto-increment key. To lift this restriction
846
- Extend statement base replication to support auto-increment
848
- Fix that we allocate auto-increment in intervals and that
849
it's properly reset if the interval was not used
851
share->lock.allow_multiple_concurrent_insert=
852
share->base.auto_key == 0;
853
share->lock_restore_status= 0;
857
share->row_is_visible= _ma_row_visible_non_transactional_table;
858
share->lock.get_status= _ma_get_status;
859
share->lock.copy_status= _ma_copy_status;
860
share->lock.update_status= _ma_update_status;
861
share->lock.restore_status= _ma_restore_status;
862
share->lock.check_status= _ma_check_status;
863
share->lock_restore_status= _ma_restore_status;
869
Memory mapping can only be requested after initializing intern_lock.
871
if (open_flags & HA_OPEN_MMAP)
874
maria_extra(&info, HA_EXTRA_MMAP, 0);
880
if (share->data_file_type == BLOCK_RECORD)
881
data_file= share->bitmap.file.file; /* Only opened once */
884
if (!(m_info= maria_clone_internal(share, mode, data_file)))
887
pthread_mutex_unlock(&THR_LOCK_maria);
891
save_errno=my_errno ? my_errno : HA_ERR_END_OF_FILE;
892
if ((save_errno == HA_ERR_CRASHED) ||
893
(save_errno == HA_ERR_CRASHED_ON_USAGE) ||
894
(save_errno == HA_ERR_CRASHED_ON_REPAIR))
895
_ma_report_error(save_errno, name);
896
if (save_errno == HA_ERR_OLD_FILE) /* uuid is different ? */
897
save_errno= HA_ERR_CRASHED_ON_USAGE; /* the code to trigger auto-repair */
901
(void)(my_close(data_file, MYF(0)));
903
break; /* Don't remove open table */
904
(*share->once_end)(share);
907
my_free((uchar*) share,MYF(0));
912
my_afree((uchar*) disk_cache);
915
(void)(my_close(kfile,MYF(0)));
921
pthread_mutex_unlock(&THR_LOCK_maria);
922
my_errno= save_errno;
928
Reallocate a buffer, if the current buffer is not large enough
931
my_bool _ma_alloc_buffer(uchar **old_addr, size_t *old_size,
934
if (*old_size < new_size)
937
if (!(addr= (uchar*) my_realloc((uchar*) *old_addr, new_size,
938
MYF(MY_ALLOW_ZERO_PTR))))
947
ulonglong _ma_safe_mul(ulonglong a, ulonglong b)
949
ulonglong max_val= ~ (ulonglong) 0; /* my_off_t is unsigned */
951
if (!a || max_val / a < b)
956
/* Set up functions in structs */
958
void _ma_setup_functions(register MARIA_SHARE *share)
960
share->once_init= maria_once_init_dummy;
961
share->once_end= maria_once_end_dummy;
962
share->init= maria_scan_init_dummy;
963
share->end= maria_scan_end_dummy;
964
share->scan_init= maria_scan_init_dummy;/* Compat. dummy function */
965
share->scan_end= maria_scan_end_dummy;/* Compat. dummy function */
966
share->scan_remember_pos= _ma_def_scan_remember_pos;
967
share->scan_restore_pos= _ma_def_scan_restore_pos;
969
share->write_record_init= _ma_write_init_default;
970
share->write_record_abort= _ma_write_abort_default;
971
share->keypos_to_recpos= _ma_transparent_recpos;
972
share->recpos_to_keypos= _ma_transparent_recpos;
974
switch (share->data_file_type) {
975
case COMPRESSED_RECORD:
976
share->read_record= _ma_read_pack_record;
977
share->scan= _ma_read_rnd_pack_record;
978
share->once_init= _ma_once_init_pack_row;
979
share->once_end= _ma_once_end_pack_row;
981
Calculate checksum according to data in the original, not compressed,
984
if (share->state.header.org_data_file_type == STATIC_RECORD &&
985
! (share->options & HA_OPTION_NULL_FIELDS))
986
share->calc_checksum= _ma_static_checksum;
988
share->calc_checksum= _ma_checksum;
989
share->calc_write_checksum= share->calc_checksum;
992
share->read_record= _ma_read_dynamic_record;
993
share->scan= _ma_read_rnd_dynamic_record;
994
share->delete_record= _ma_delete_dynamic_record;
995
share->compare_record= _ma_cmp_dynamic_record;
996
share->compare_unique= _ma_cmp_dynamic_unique;
997
share->calc_checksum= share->calc_write_checksum= _ma_checksum;
998
if (share->base.blobs)
1000
share->update_record= _ma_update_blob_record;
1001
share->write_record= _ma_write_blob_record;
1005
share->write_record= _ma_write_dynamic_record;
1006
share->update_record= _ma_update_dynamic_record;
1010
share->read_record= _ma_read_static_record;
1011
share->scan= _ma_read_rnd_static_record;
1012
share->delete_record= _ma_delete_static_record;
1013
share->compare_record= _ma_cmp_static_record;
1014
share->update_record= _ma_update_static_record;
1015
share->write_record= _ma_write_static_record;
1016
share->compare_unique= _ma_cmp_static_unique;
1017
share->keypos_to_recpos= _ma_static_keypos_to_recpos;
1018
share->recpos_to_keypos= _ma_static_recpos_to_keypos;
1019
if (share->state.header.org_data_file_type == STATIC_RECORD &&
1020
! (share->options & HA_OPTION_NULL_FIELDS))
1021
share->calc_checksum= _ma_static_checksum;
1023
share->calc_checksum= _ma_checksum;
1026
share->once_init= _ma_once_init_block_record;
1027
share->once_end= _ma_once_end_block_record;
1028
share->init= _ma_init_block_record;
1029
share->end= _ma_end_block_record;
1030
share->write_record_init= _ma_write_init_block_record;
1031
share->write_record_abort= _ma_write_abort_block_record;
1032
share->scan_init= _ma_scan_init_block_record;
1033
share->scan_end= _ma_scan_end_block_record;
1034
share->scan= _ma_scan_block_record;
1035
share->scan_remember_pos= _ma_scan_remember_block_record;
1036
share->scan_restore_pos= _ma_scan_restore_block_record;
1037
share->read_record= _ma_read_block_record;
1038
share->delete_record= _ma_delete_block_record;
1039
share->compare_record= _ma_compare_block_record;
1040
share->update_record= _ma_update_block_record;
1041
share->write_record= _ma_write_block_record;
1042
share->compare_unique= _ma_cmp_block_unique;
1043
share->calc_checksum= _ma_checksum;
1044
share->keypos_to_recpos= _ma_transaction_keypos_to_recpos;
1045
share->recpos_to_keypos= _ma_transaction_recpos_to_keypos;
1048
write_block_record() will calculate the checksum; Tell maria_write()
1049
that it doesn't have to do this.
1051
share->calc_write_checksum= 0;
1054
share->file_read= _ma_nommap_pread;
1055
share->file_write= _ma_nommap_pwrite;
1056
share->calc_check_checksum= share->calc_checksum;
1058
if (!(share->options & HA_OPTION_CHECKSUM) &&
1059
share->data_file_type != COMPRESSED_RECORD)
1060
share->calc_checksum= share->calc_write_checksum= 0;
1065
static void setup_key_functions(register MARIA_KEYDEF *keyinfo)
1067
if (keyinfo->key_alg == HA_KEY_ALG_RTREE)
1069
#ifdef HAVE_RTREE_KEYS
1070
keyinfo->ck_insert = maria_rtree_insert;
1071
keyinfo->ck_delete = maria_rtree_delete;
1073
DBUG_ASSERT(0); /* maria_open should check it never happens */
1078
keyinfo->ck_insert = _ma_ck_write;
1079
keyinfo->ck_delete = _ma_ck_delete;
1081
if (keyinfo->flag & HA_SPATIAL)
1082
keyinfo->make_key= _ma_sp_make_key;
1084
keyinfo->make_key= _ma_make_key;
1086
if (keyinfo->flag & HA_BINARY_PACK_KEY)
1087
{ /* Simple prefix compression */
1088
keyinfo->bin_search= _ma_seq_search;
1089
keyinfo->get_key= _ma_get_binary_pack_key;
1090
keyinfo->skip_key= _ma_skip_binary_pack_key;
1091
keyinfo->pack_key= _ma_calc_bin_pack_key_length;
1092
keyinfo->store_key= _ma_store_bin_pack_key;
1094
else if (keyinfo->flag & HA_VAR_LENGTH_KEY)
1096
keyinfo->get_key= _ma_get_pack_key;
1097
keyinfo->skip_key= _ma_skip_pack_key;
1098
if (keyinfo->seg[0].flag & HA_PACK_KEY)
1099
{ /* Prefix compression */
1101
_ma_prefix_search() compares end-space against ASCII blank (' ').
1102
It cannot be used for character sets, that do not encode the
1103
blank character like ASCII does. UCS2 is an example. All
1104
character sets with a fixed width > 1 or a mimimum width > 1
1105
cannot represent blank like ASCII does. In these cases we have
1106
to use _ma_seq_search() for the search.
1108
if (!keyinfo->seg->charset || use_strnxfrm(keyinfo->seg->charset) ||
1109
(keyinfo->seg->flag & HA_NULL_PART) ||
1110
keyinfo->seg->charset->mbminlen > 1)
1111
keyinfo->bin_search= _ma_seq_search;
1113
keyinfo->bin_search= _ma_prefix_search;
1114
keyinfo->pack_key= _ma_calc_var_pack_key_length;
1115
keyinfo->store_key= _ma_store_var_pack_key;
1119
keyinfo->bin_search= _ma_seq_search;
1120
keyinfo->pack_key= _ma_calc_var_key_length; /* Variable length key */
1121
keyinfo->store_key= _ma_store_static_key;
1126
keyinfo->bin_search= _ma_bin_search;
1127
keyinfo->get_key= _ma_get_static_key;
1128
keyinfo->skip_key= _ma_skip_static_key;
1129
keyinfo->pack_key= _ma_calc_static_key_length;
1130
keyinfo->store_key= _ma_store_static_key;
1133
/* set keyinfo->write_comp_flag */
1134
if (keyinfo->flag & HA_SORT_ALLOWS_SAME)
1135
keyinfo->write_comp_flag=SEARCH_BIGGER; /* Put after same key */
1136
else if (keyinfo->flag & ( HA_NOSAME | HA_FULLTEXT))
1138
keyinfo->write_comp_flag= SEARCH_FIND | SEARCH_UPDATE; /* No duplicates */
1139
if (keyinfo->flag & HA_NULL_ARE_EQUAL)
1140
keyinfo->write_comp_flag|= SEARCH_NULL_ARE_EQUAL;
1143
keyinfo->write_comp_flag= SEARCH_SAME; /* Keys in rec-pos order */
1144
keyinfo->write_comp_flag|= SEARCH_INSERT;
1150
@brief Function to save and store the header in the index file (.MYI)
1152
Operates under MARIA_SHARE::intern_lock if requested.
1153
Sets MARIA_SHARE::MARIA_STATE_INFO::is_of_horizon if transactional table.
1154
Then calls _ma_state_info_write_sub().
1157
@param pWrite bitmap: if 1 is set my_pwrite() is used otherwise
1158
my_write(); if 2 is set, info about keys is written
1159
(should only be needed after ALTER TABLE
1160
ENABLE/DISABLE KEYS, and REPAIR/OPTIMIZE); if 4 is
1161
set, MARIA_SHARE::intern_lock is taken.
1163
@return Operation status
1168
uint _ma_state_info_write(MARIA_SHARE *share, uint pWrite)
1171
if (share->options & HA_OPTION_READ_ONLY_DATA)
1175
pthread_mutex_lock(&share->intern_lock);
1176
else if (maria_multi_threaded)
1178
safe_mutex_assert_owner(&share->intern_lock);
1180
if (share->base.born_transactional && translog_status == TRANSLOG_OK &&
1184
In a recovery, we want to set is_of_horizon to the LSN of the last
1185
record executed by Recovery, not the current EOF of the log (which
1186
is too new). Recovery does it by itself.
1188
share->state.is_of_horizon= translog_get_horizon();
1189
DBUG_PRINT("info", ("is_of_horizon set to LSN (%lu,0x%lx)",
1190
LSN_IN_PARTS(share->state.is_of_horizon)));
1192
res= _ma_state_info_write_sub(share->kfile.file, &share->state, pWrite);
1194
pthread_mutex_unlock(&share->intern_lock);
1200
@brief Function to save and store the header in the index file (.MYI).
1202
Shortcut to use instead of _ma_state_info_write() when appropriate.
1204
@param file descriptor of the index file to write
1205
@param state state information to write to the file
1206
@param pWrite bitmap: if 1 is set my_pwrite() is used otherwise
1207
my_write(); if 2 is set, info about keys is written
1208
(should only be needed after ALTER TABLE
1209
ENABLE/DISABLE KEYS, and REPAIR/OPTIMIZE).
1211
@return Operation status
1216
uint _ma_state_info_write_sub(File file, MARIA_STATE_INFO *state, uint pWrite)
1218
uchar buff[MARIA_STATE_INFO_SIZE + MARIA_STATE_EXTRA_SIZE];
1220
uint i, keys= (uint) state->header.keys;
1222
DBUG_ENTER("_ma_state_info_write_sub");
1224
memcpy_fixed(ptr,&state->header,sizeof(state->header));
1225
ptr+=sizeof(state->header);
1227
/* open_count must be first because of _ma_mark_file_changed ! */
1228
mi_int2store(ptr,state->open_count); ptr+= 2;
1229
/* changed must be second, because of _ma_mark_file_crashed */
1230
mi_int2store(ptr,state->changed); ptr+= 2;
1233
If you change the offset of these LSNs, note that some functions do a
1234
direct write of them without going through this function.
1236
lsn_store(ptr, state->create_rename_lsn); ptr+= LSN_STORE_SIZE;
1237
lsn_store(ptr, state->is_of_horizon); ptr+= LSN_STORE_SIZE;
1238
lsn_store(ptr, state->skip_redo_lsn); ptr+= LSN_STORE_SIZE;
1239
mi_rowstore(ptr,state->state.records); ptr+= 8;
1240
mi_rowstore(ptr,state->state.del); ptr+= 8;
1241
mi_rowstore(ptr,state->split); ptr+= 8;
1242
mi_sizestore(ptr,state->dellink); ptr+= 8;
1243
mi_sizestore(ptr,state->first_bitmap_with_space); ptr+= 8;
1244
mi_sizestore(ptr,state->state.key_file_length); ptr+= 8;
1245
mi_sizestore(ptr,state->state.data_file_length); ptr+= 8;
1246
mi_sizestore(ptr,state->state.empty); ptr+= 8;
1247
mi_sizestore(ptr,state->state.key_empty); ptr+= 8;
1248
mi_int8store(ptr,state->auto_increment); ptr+= 8;
1249
mi_int8store(ptr,(ulonglong) state->state.checksum); ptr+= 8;
1250
mi_int8store(ptr,state->create_trid); ptr+= 8;
1251
mi_int4store(ptr,state->status); ptr+= 4;
1252
mi_int4store(ptr,state->update_count); ptr+= 4;
1253
*ptr++= state->sortkey;
1254
*ptr++= 0; /* Reserved */
1255
ptr+= state->state_diff_length;
1257
for (i=0; i < keys; i++)
1259
mi_sizestore(ptr,state->key_root[i]); ptr+= 8;
1261
mi_sizestore(ptr,state->key_del); ptr+= 8;
1262
if (pWrite & 2) /* From maria_chk */
1264
uint key_parts= mi_uint2korr(state->header.key_parts);
1265
mi_int4store(ptr,state->sec_index_changed); ptr+= 4;
1266
mi_int4store(ptr,state->sec_index_used); ptr+= 4;
1267
mi_int4store(ptr,state->version); ptr+= 4;
1268
mi_int8store(ptr,state->key_map); ptr+= 8;
1269
mi_int8store(ptr,(ulonglong) state->create_time); ptr+= 8;
1270
mi_int8store(ptr,(ulonglong) state->recover_time); ptr+= 8;
1271
mi_int8store(ptr,(ulonglong) state->check_time); ptr+= 8;
1272
mi_sizestore(ptr, state->records_at_analyze); ptr+= 8;
1273
/* reserve place for some information per key */
1274
bzero(ptr, keys*4); ptr+= keys*4;
1275
for (i=0 ; i < key_parts ; i++)
1277
float8store(ptr, state->rec_per_key_part[i]); ptr+= 8;
1278
mi_int4store(ptr, state->nulls_per_key_part[i]); ptr+= 4;
1283
my_pwrite(file, buff, (size_t) (ptr-buff), 0L,
1284
MYF(MY_NABP | MY_THREADSAFE)) :
1285
my_write(file, buff, (size_t) (ptr-buff),
1287
DBUG_RETURN(res != 0);
1291
static uchar *_ma_state_info_read(uchar *ptr, MARIA_STATE_INFO *state)
1293
uint i,keys,key_parts;
1294
memcpy_fixed(&state->header,ptr, sizeof(state->header));
1295
ptr+= sizeof(state->header);
1296
keys= (uint) state->header.keys;
1297
key_parts= mi_uint2korr(state->header.key_parts);
1299
state->open_count = mi_uint2korr(ptr); ptr+= 2;
1300
state->changed= mi_uint2korr(ptr); ptr+= 2;
1301
state->create_rename_lsn= lsn_korr(ptr); ptr+= LSN_STORE_SIZE;
1302
state->is_of_horizon= lsn_korr(ptr); ptr+= LSN_STORE_SIZE;
1303
state->skip_redo_lsn= lsn_korr(ptr); ptr+= LSN_STORE_SIZE;
1304
state->state.records= mi_rowkorr(ptr); ptr+= 8;
1305
state->state.del = mi_rowkorr(ptr); ptr+= 8;
1306
state->split = mi_rowkorr(ptr); ptr+= 8;
1307
state->dellink= mi_sizekorr(ptr); ptr+= 8;
1308
state->first_bitmap_with_space= mi_sizekorr(ptr); ptr+= 8;
1309
state->state.key_file_length = mi_sizekorr(ptr); ptr+= 8;
1310
state->state.data_file_length= mi_sizekorr(ptr); ptr+= 8;
1311
state->state.empty = mi_sizekorr(ptr); ptr+= 8;
1312
state->state.key_empty= mi_sizekorr(ptr); ptr+= 8;
1313
state->auto_increment=mi_uint8korr(ptr); ptr+= 8;
1314
state->state.checksum=(ha_checksum) mi_uint8korr(ptr);ptr+= 8;
1315
state->create_trid= mi_uint8korr(ptr); ptr+= 8;
1316
state->status = mi_uint4korr(ptr); ptr+= 4;
1317
state->update_count=mi_uint4korr(ptr); ptr+= 4;
1318
state->sortkey= (uint) *ptr++;
1319
ptr++; /* reserved */
1321
ptr+= state->state_diff_length;
1323
for (i=0; i < keys; i++)
1325
state->key_root[i]= mi_sizekorr(ptr); ptr+= 8;
1327
state->key_del= mi_sizekorr(ptr); ptr+= 8;
1328
state->sec_index_changed = mi_uint4korr(ptr); ptr+= 4;
1329
state->sec_index_used = mi_uint4korr(ptr); ptr+= 4;
1330
state->version = mi_uint4korr(ptr); ptr+= 4;
1331
state->key_map = mi_uint8korr(ptr); ptr+= 8;
1332
state->create_time = (time_t) mi_sizekorr(ptr); ptr+= 8;
1333
state->recover_time =(time_t) mi_sizekorr(ptr); ptr+= 8;
1334
state->check_time = (time_t) mi_sizekorr(ptr); ptr+= 8;
1335
state->records_at_analyze= mi_sizekorr(ptr); ptr+= 8;
1336
ptr+= keys * 4; /* Skip reserved bytes */
1337
for (i=0 ; i < key_parts ; i++)
1339
float8get(state->rec_per_key_part[i], ptr); ptr+= 8;
1340
state->nulls_per_key_part[i]= mi_uint4korr(ptr); ptr+= 4;
1347
@brief Fills the state by reading its copy on disk.
1349
Should not be called for transactional tables, as their state on disk is
1350
rarely current and so is often misleading for a reader.
1351
Does nothing in single user mode.
1353
@param file file to read from
1354
@param state state which will be filled
1357
uint _ma_state_info_read_dsk(File file __attribute__((unused)),
1358
MARIA_STATE_INFO *state __attribute__((unused)))
1360
#ifdef EXTERNAL_LOCKING
1361
uchar buff[MARIA_STATE_INFO_SIZE + MARIA_STATE_EXTRA_SIZE];
1363
/* trick to detect transactional tables */
1364
DBUG_ASSERT(state->create_rename_lsn == LSN_IMPOSSIBLE);
1365
if (!maria_single_user)
1367
if (my_pread(file, buff, state->state_length, 0L, MYF(MY_NABP)))
1369
_ma_state_info_read(buff, state);
1376
/****************************************************************************
1377
** store and read of MARIA_BASE_INFO
1378
****************************************************************************/
1380
uint _ma_base_info_write(File file, MARIA_BASE_INFO *base)
1382
uchar buff[MARIA_BASE_INFO_SIZE], *ptr=buff;
1384
bmove(ptr, maria_uuid, MY_UUID_SIZE);
1386
mi_sizestore(ptr,base->keystart); ptr+= 8;
1387
mi_sizestore(ptr,base->max_data_file_length); ptr+= 8;
1388
mi_sizestore(ptr,base->max_key_file_length); ptr+= 8;
1389
mi_rowstore(ptr,base->records); ptr+= 8;
1390
mi_rowstore(ptr,base->reloc); ptr+= 8;
1391
mi_int4store(ptr,base->mean_row_length); ptr+= 4;
1392
mi_int4store(ptr,base->reclength); ptr+= 4;
1393
mi_int4store(ptr,base->pack_reclength); ptr+= 4;
1394
mi_int4store(ptr,base->min_pack_length); ptr+= 4;
1395
mi_int4store(ptr,base->max_pack_length); ptr+= 4;
1396
mi_int4store(ptr,base->min_block_length); ptr+= 4;
1397
mi_int2store(ptr,base->fields); ptr+= 2;
1398
mi_int2store(ptr,base->fixed_not_null_fields); ptr+= 2;
1399
mi_int2store(ptr,base->fixed_not_null_fields_length); ptr+= 2;
1400
mi_int2store(ptr,base->max_field_lengths); ptr+= 2;
1401
mi_int2store(ptr,base->pack_fields); ptr+= 2;
1402
mi_int2store(ptr,base->extra_options) ptr+= 2;
1403
mi_int2store(ptr,base->null_bytes); ptr+= 2;
1404
mi_int2store(ptr,base->original_null_bytes); ptr+= 2;
1405
mi_int2store(ptr,base->field_offsets); ptr+= 2;
1406
mi_int2store(ptr,0); ptr+= 2; /* reserved */
1407
mi_int2store(ptr,base->block_size); ptr+= 2;
1408
*ptr++= base->rec_reflength;
1409
*ptr++= base->key_reflength;
1411
*ptr++= base->auto_key;
1412
*ptr++= base->born_transactional;
1413
*ptr++= 0; /* Reserved */
1414
mi_int2store(ptr,base->pack_bytes); ptr+= 2;
1415
mi_int2store(ptr,base->blobs); ptr+= 2;
1416
mi_int2store(ptr,base->max_key_block_length); ptr+= 2;
1417
mi_int2store(ptr,base->max_key_length); ptr+= 2;
1418
mi_int2store(ptr,base->extra_alloc_bytes); ptr+= 2;
1419
*ptr++= base->extra_alloc_procent;
1420
bzero(ptr,16); ptr+= 16; /* extra */
1421
DBUG_ASSERT((ptr - buff) == MARIA_BASE_INFO_SIZE);
1422
return my_write(file, buff, (size_t) (ptr-buff), MYF(MY_NABP)) != 0;
1426
static uchar *_ma_base_info_read(uchar *ptr, MARIA_BASE_INFO *base)
1428
bmove(base->uuid, ptr, MY_UUID_SIZE); ptr+= MY_UUID_SIZE;
1429
base->keystart= mi_sizekorr(ptr); ptr+= 8;
1430
base->max_data_file_length= mi_sizekorr(ptr); ptr+= 8;
1431
base->max_key_file_length= mi_sizekorr(ptr); ptr+= 8;
1432
base->records= (ha_rows) mi_sizekorr(ptr); ptr+= 8;
1433
base->reloc= (ha_rows) mi_sizekorr(ptr); ptr+= 8;
1434
base->mean_row_length= mi_uint4korr(ptr); ptr+= 4;
1435
base->reclength= mi_uint4korr(ptr); ptr+= 4;
1436
base->pack_reclength= mi_uint4korr(ptr); ptr+= 4;
1437
base->min_pack_length= mi_uint4korr(ptr); ptr+= 4;
1438
base->max_pack_length= mi_uint4korr(ptr); ptr+= 4;
1439
base->min_block_length= mi_uint4korr(ptr); ptr+= 4;
1440
base->fields= mi_uint2korr(ptr); ptr+= 2;
1441
base->fixed_not_null_fields= mi_uint2korr(ptr); ptr+= 2;
1442
base->fixed_not_null_fields_length= mi_uint2korr(ptr);ptr+= 2;
1443
base->max_field_lengths= mi_uint2korr(ptr); ptr+= 2;
1444
base->pack_fields= mi_uint2korr(ptr); ptr+= 2;
1445
base->extra_options= mi_uint2korr(ptr); ptr+= 2;
1446
base->null_bytes= mi_uint2korr(ptr); ptr+= 2;
1447
base->original_null_bytes= mi_uint2korr(ptr); ptr+= 2;
1448
base->field_offsets= mi_uint2korr(ptr); ptr+= 2;
1450
base->block_size= mi_uint2korr(ptr); ptr+= 2;
1452
base->rec_reflength= *ptr++;
1453
base->key_reflength= *ptr++;
1455
base->auto_key= *ptr++;
1456
base->born_transactional= *ptr++;
1458
base->pack_bytes= mi_uint2korr(ptr); ptr+= 2;
1459
base->blobs= mi_uint2korr(ptr); ptr+= 2;
1460
base->max_key_block_length= mi_uint2korr(ptr); ptr+= 2;
1461
base->max_key_length= mi_uint2korr(ptr); ptr+= 2;
1462
base->extra_alloc_bytes= mi_uint2korr(ptr); ptr+= 2;
1463
base->extra_alloc_procent= *ptr++;
1468
/*--------------------------------------------------------------------------
1470
---------------------------------------------------------------------------*/
1472
my_bool _ma_keydef_write(File file, MARIA_KEYDEF *keydef)
1474
uchar buff[MARIA_KEYDEF_SIZE];
1477
*ptr++= (uchar) keydef->keysegs;
1478
*ptr++= keydef->key_alg; /* Rtree or Btree */
1479
mi_int2store(ptr,keydef->flag); ptr+= 2;
1480
mi_int2store(ptr,keydef->block_length); ptr+= 2;
1481
mi_int2store(ptr,keydef->keylength); ptr+= 2;
1482
mi_int2store(ptr,keydef->minlength); ptr+= 2;
1483
mi_int2store(ptr,keydef->maxlength); ptr+= 2;
1484
return my_write(file, buff, (size_t) (ptr-buff), MYF(MY_NABP)) != 0;
1487
uchar *_ma_keydef_read(uchar *ptr, MARIA_KEYDEF *keydef)
1489
keydef->keysegs = (uint) *ptr++;
1490
keydef->key_alg = *ptr++; /* Rtree or Btree */
1492
keydef->flag = mi_uint2korr(ptr); ptr+= 2;
1493
keydef->block_length = mi_uint2korr(ptr); ptr+= 2;
1494
keydef->keylength = mi_uint2korr(ptr); ptr+= 2;
1495
keydef->minlength = mi_uint2korr(ptr); ptr+= 2;
1496
keydef->maxlength = mi_uint2korr(ptr); ptr+= 2;
1497
keydef->underflow_block_length=keydef->block_length/3;
1498
keydef->version = 0; /* Not saved */
1499
keydef->parser = &ft_default_parser;
1500
keydef->ftparser_nr = 0;
1504
/***************************************************************************
1506
***************************************************************************/
1508
my_bool _ma_keyseg_write(File file, const HA_KEYSEG *keyseg)
1510
uchar buff[HA_KEYSEG_SIZE];
1514
*ptr++= keyseg->type;
1515
*ptr++= keyseg->language;
1516
*ptr++= keyseg->null_bit;
1517
*ptr++= keyseg->bit_start;
1518
*ptr++= keyseg->bit_end;
1519
*ptr++= keyseg->bit_length;
1520
mi_int2store(ptr,keyseg->flag); ptr+= 2;
1521
mi_int2store(ptr,keyseg->length); ptr+= 2;
1522
mi_int4store(ptr,keyseg->start); ptr+= 4;
1523
pos= keyseg->null_bit ? keyseg->null_pos : keyseg->bit_pos;
1524
mi_int4store(ptr, pos);
1527
return my_write(file, buff, (size_t) (ptr-buff), MYF(MY_NABP)) != 0;
1531
uchar *_ma_keyseg_read(uchar *ptr, HA_KEYSEG *keyseg)
1533
keyseg->type = *ptr++;
1534
keyseg->language = *ptr++;
1535
keyseg->null_bit = *ptr++;
1536
keyseg->bit_start = *ptr++;
1537
keyseg->bit_end = *ptr++;
1538
keyseg->bit_length = *ptr++;
1539
keyseg->flag = mi_uint2korr(ptr); ptr+= 2;
1540
keyseg->length = mi_uint2korr(ptr); ptr+= 2;
1541
keyseg->start = mi_uint4korr(ptr); ptr+= 4;
1542
keyseg->null_pos = mi_uint4korr(ptr); ptr+= 4;
1543
keyseg->charset=0; /* Will be filled in later */
1544
if (keyseg->null_bit)
1545
keyseg->bit_pos= (uint16)(keyseg->null_pos + (keyseg->null_bit == 7));
1548
keyseg->bit_pos= (uint16)keyseg->null_pos;
1549
keyseg->null_pos= 0;
1554
/*--------------------------------------------------------------------------
1556
---------------------------------------------------------------------------*/
1558
my_bool _ma_uniquedef_write(File file, MARIA_UNIQUEDEF *def)
1560
uchar buff[MARIA_UNIQUEDEF_SIZE];
1563
mi_int2store(ptr,def->keysegs); ptr+=2;
1564
*ptr++= (uchar) def->key;
1565
*ptr++ = (uchar) def->null_are_equal;
1567
return my_write(file, buff, (size_t) (ptr-buff), MYF(MY_NABP)) != 0;
1570
uchar *_ma_uniquedef_read(uchar *ptr, MARIA_UNIQUEDEF *def)
1572
def->keysegs = mi_uint2korr(ptr);
1574
def->null_are_equal=ptr[3];
1575
return ptr+4; /* 1 extra uchar */
1578
/***************************************************************************
1580
***************************************************************************/
1582
my_bool _ma_columndef_write(File file, MARIA_COLUMNDEF *columndef)
1584
uchar buff[MARIA_COLUMNDEF_SIZE];
1587
mi_int2store(ptr,(ulong) columndef->column_nr); ptr+= 2;
1588
mi_int2store(ptr,(ulong) columndef->offset); ptr+= 2;
1589
mi_int2store(ptr,columndef->type); ptr+= 2;
1590
mi_int2store(ptr,columndef->length); ptr+= 2;
1591
mi_int2store(ptr,columndef->fill_length); ptr+= 2;
1592
mi_int2store(ptr,columndef->null_pos); ptr+= 2;
1593
mi_int2store(ptr,columndef->empty_pos); ptr+= 2;
1595
(*ptr++)= columndef->null_bit;
1596
(*ptr++)= columndef->empty_bit;
1597
ptr[0]= ptr[1]= ptr[2]= ptr[3]= 0; ptr+= 4; /* For future */
1598
return my_write(file, buff, (size_t) (ptr-buff), MYF(MY_NABP)) != 0;
1601
uchar *_ma_columndef_read(uchar *ptr, MARIA_COLUMNDEF *columndef)
1603
columndef->column_nr= mi_uint2korr(ptr); ptr+= 2;
1604
columndef->offset= mi_uint2korr(ptr); ptr+= 2;
1605
columndef->type= mi_sint2korr(ptr); ptr+= 2;
1606
columndef->length= mi_uint2korr(ptr); ptr+= 2;
1607
columndef->fill_length= mi_uint2korr(ptr); ptr+= 2;
1608
columndef->null_pos= mi_uint2korr(ptr); ptr+= 2;
1609
columndef->empty_pos= mi_uint2korr(ptr); ptr+= 2;
1610
columndef->null_bit= (uint8) *ptr++;
1611
columndef->empty_bit= (uint8) *ptr++;
1616
my_bool _ma_column_nr_write(File file, uint16 *offsets, uint columns)
1618
uchar *buff, *ptr, *end;
1619
size_t size= columns*2;
1622
if (!(buff= (uchar*) my_alloca(size)))
1624
for (ptr= buff, end= ptr + size; ptr < end ; ptr+= 2, offsets++)
1625
int2store(ptr, *offsets);
1626
res= my_write(file, buff, size, MYF(MY_NABP)) != 0;
1632
uchar *_ma_column_nr_read(uchar *ptr, uint16 *offsets, uint columns)
1635
size_t size= columns*2;
1636
for (end= ptr + size; ptr < end ; ptr+=2, offsets++)
1637
*offsets= uint2korr(ptr);
1642
@brief Set callbacks for data pages
1645
We don't use pagecache_file_init here, as we want to keep the
1649
void _ma_set_data_pagecache_callbacks(PAGECACHE_FILE *file,
1652
file->callback_data= (uchar*) share;
1653
file->flush_log_callback= &maria_flush_log_for_page_none; /* Do nothing */
1655
if (share->temporary)
1657
file->read_callback= &maria_page_crc_check_none;
1658
file->write_callback= &maria_page_filler_set_none;
1662
file->read_callback= &maria_page_crc_check_data;
1663
if (share->options & HA_OPTION_PAGE_CHECKSUM)
1664
file->write_callback= &maria_page_crc_set_normal;
1666
file->write_callback= &maria_page_filler_set_normal;
1667
if (share->now_transactional)
1668
file->flush_log_callback= maria_flush_log_for_page;
1674
@brief Set callbacks for index pages
1677
We don't use pagecache_file_init here, as we want to keep the
1681
void _ma_set_index_pagecache_callbacks(PAGECACHE_FILE *file,
1684
file->callback_data= (uchar*) share;
1685
file->flush_log_callback= &maria_flush_log_for_page_none; /* Do nothing */
1686
file->write_fail= maria_page_write_failure;
1688
if (share->temporary)
1690
file->read_callback= &maria_page_crc_check_none;
1691
file->write_callback= &maria_page_filler_set_none;
1695
file->read_callback= &maria_page_crc_check_index;
1696
if (share->options & HA_OPTION_PAGE_CHECKSUM)
1697
file->write_callback= &maria_page_crc_set_index;
1699
file->write_callback= &maria_page_filler_set_normal;
1701
if (share->now_transactional)
1702
file->flush_log_callback= maria_flush_log_for_page;
1707
/**************************************************************************
1709
We can't use dup() here as the data file descriptors need to have different
1710
active seek-positions.
1712
The argument file_to_dup is here for the future if there would on some OS
1713
exist a dup()-like call that would give us two different file descriptors.
1714
*************************************************************************/
1716
int _ma_open_datafile(MARIA_HA *info, MARIA_SHARE *share,
1717
File file_to_dup __attribute__((unused)))
1719
info->dfile.file= share->bitmap.file.file=
1720
my_open(share->data_file_name, share->mode | O_SHARE,
1722
return info->dfile.file >= 0 ? 0 : 1;
1726
int _ma_open_keyfile(MARIA_SHARE *share)
1729
Modifications to share->kfile should be under intern_lock to protect
1730
against a concurrent checkpoint.
1732
pthread_mutex_lock(&share->intern_lock);
1733
share->kfile.file= my_open(share->unique_file_name,
1734
share->mode | O_SHARE,
1736
pthread_mutex_unlock(&share->intern_lock);
1737
return (share->kfile.file < 0);
1742
Disable all indexes.
1745
maria_disable_indexes()
1746
info A pointer to the MARIA storage engine MARIA_HA struct.
1749
Disable all indexes.
1755
int maria_disable_indexes(MARIA_HA *info)
1757
MARIA_SHARE *share= info->s;
1759
maria_clear_all_keys_active(share->state.key_map);
1768
maria_enable_indexes()
1769
info A pointer to the MARIA storage engine MARIA_HA struct.
1772
Enable all indexes. The indexes might have been disabled
1773
by maria_disable_index() before.
1774
The function works only if both data and indexes are empty,
1775
otherwise a repair is required.
1776
To be sure, call handler::delete_all_rows() before.
1780
HA_ERR_CRASHED data or index is non-empty.
1783
int maria_enable_indexes(MARIA_HA *info)
1786
MARIA_SHARE *share= info->s;
1787
DBUG_ENTER("maria_enable_indexes");
1789
if ((share->state.state.data_file_length !=
1790
(share->data_file_type == BLOCK_RECORD ? share->block_size : 0)) ||
1791
(share->state.state.key_file_length != share->base.keystart))
1793
DBUG_PRINT("error", ("data_file_length: %lu key_file_length: %lu",
1794
(ulong) share->state.state.data_file_length,
1795
(ulong) share->state.state.key_file_length));
1796
maria_print_error(info->s, HA_ERR_CRASHED);
1797
error= HA_ERR_CRASHED;
1800
maria_set_all_keys_active(share->state.key_map, share->base.keys);
1806
Test if indexes are disabled.
1809
maria_indexes_are_disabled()
1810
info A pointer to the MARIA storage engine MARIA_HA struct.
1813
Test if indexes are disabled.
1816
0 indexes are not disabled
1817
1 all indexes are disabled
1818
2 non-unique indexes are disabled
1821
int maria_indexes_are_disabled(MARIA_HA *info)
1823
MARIA_SHARE *share= info->s;
1826
No keys or all are enabled. keys is the number of keys. Left shifted
1827
gives us only one bit set. When decreased by one, gives us all all bits
1828
up to this one set and it gets unset.
1830
if (!share->base.keys ||
1831
(maria_is_all_keys_active(share->state.key_map, share->base.keys)))
1834
/* All are disabled */
1835
if (maria_is_any_key_active(share->state.key_map))
1839
We have keys. Some enabled, some disabled.
1840
Don't check for any non-unique disabled but return directly 2
1846
static my_bool maria_scan_init_dummy(MARIA_HA *info __attribute__((unused)))
1851
static void maria_scan_end_dummy(MARIA_HA *info __attribute__((unused)))
1855
static my_bool maria_once_init_dummy(MARIA_SHARE *share
1856
__attribute__((unused)),
1857
File dfile __attribute__((unused)))
1862
static my_bool maria_once_end_dummy(MARIA_SHARE *share __attribute__((unused)))