diff options
Diffstat (limited to 'storage/maria')
62 files changed, 8602 insertions, 2817 deletions
diff --git a/storage/maria/Makefile.am b/storage/maria/Makefile.am index d4315b4d446..b2936143c36 100644 --- a/storage/maria/Makefile.am +++ b/storage/maria/Makefile.am @@ -28,7 +28,7 @@ bin_PROGRAMS = maria_chk maria_pack maria_ftdump maria_chk_DEPENDENCIES= $(LIBRARIES) maria_pack_DEPENDENCIES=$(LIBRARIES) noinst_PROGRAMS = ma_test1 ma_test2 ma_test3 ma_rt_test ma_sp_test -noinst_HEADERS = maria_def.h ma_rt_index.h ma_rt_key.h ma_rt_mbr.h ma_sp_defs.h ma_fulltext.h ma_ftdefs.h ma_ft_test1.h ma_ft_eval.h +noinst_HEADERS = maria_def.h ma_blockrec.h ma_rt_index.h ma_rt_key.h ma_rt_mbr.h ma_sp_defs.h ma_fulltext.h ma_ftdefs.h ma_ft_test1.h ma_ft_eval.h ma_test1_DEPENDENCIES= $(LIBRARIES) ma_test2_DEPENDENCIES= $(LIBRARIES) ma_test3_DEPENDENCIES= $(LIBRARIES) @@ -42,6 +42,7 @@ libmaria_a_SOURCES = ma_init.c ma_open.c ma_extra.c ma_info.c ma_rkey.c \ ma_search.c ma_page.c ma_key.c ma_locking.c \ ma_rrnd.c ma_scan.c ma_cache.c \ ma_statrec.c ma_packrec.c ma_dynrec.c \ + ma_blockrec.c ma_bitmap.c \ ma_update.c ma_write.c ma_unique.c \ ma_delete.c \ ma_rprev.c ma_rfirst.c ma_rlast.c ma_rsame.c \ diff --git a/storage/maria/ma_bitmap.c b/storage/maria/ma_bitmap.c new file mode 100644 index 00000000000..5ed5a776658 --- /dev/null +++ b/storage/maria/ma_bitmap.c @@ -0,0 +1,1704 @@ +/* Copyright (C) 2007 Michael Widenius + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +/* + Bitmap handling (for records in block) + + The data file starts with a bitmap page, followed by as many data + pages as the bitmap can cover. After this there is a new bitmap page + and more data pages etc. + + The bitmap code assumes there is always an active bitmap page and thus + that there is at least one bitmap page in the file + + Structure of bitmap page: + + Fixed size records (to be implemented later): + + 2 bits are used to indicate: + + 0 Empty + 1 50-75 % full (at least room for 2 records) + 2 75-100 % full (at least room for one record) + 3 100 % full (no more room for records) + + Assuming 8K pages, this will allow us to map: + 8192 (bytes per page) * 4 (pages mapped per byte) * 8192 (page size)= 256M + + (For Maria this will be 7*4 * 8192 = 224K smaller because of LSN) + + Note that for fixed size rows, we can't add more columns without doing + a full reorganization of the table. The user can always force a dynamic + size row format by specifying ROW_FORMAT=dynamic. + + + Dynamic size records: + + 3 bits are used to indicate + + 0 Empty page + 1 0-30 % full (at least room for 3 records) + 2 30-60 % full (at least room for 2 records) + 3 60-90 % full (at least room for one record) + 4 100 % full (no more room for records) + 5 Tail page, 0-40 % full + 6 Tail page, 40-80 % full + 7 Full tail page or full blob page + + Assuming 8K pages, this will allow us to map: + 8192 (bytes per page) * 8 bits/byte / 3 bits/page * 8192 (page size)= 170.7M + + Note that values 1-3 may be adjust for each individual table based on + 'min record length'. Tail pages are for overflow data which can be of + any size and thus doesn't have to be adjusted for different tables. + If we add more columns to the table, some of the originally calculated + 'cut off' points may not be optimal, but they shouldn't be 'drasticly + wrong'. + + When allocating data from the bitmap, we are trying to do it in a + 'best fit' manner. Blobs and varchar blocks are given out in large + continuous extents to allow fast access to these. Before allowing a + row to 'flow over' to other blocks, we will compact the page and use + all space on it. If there is many rows in the page, we will ensure + there is *LEFT_TO_GROW_ON_SPLIT* bytes left on the page to allow other + rows to grow. + + The bitmap format allows us to extend the row file in big chunks, if needed. + + When calculating the size for a packed row, we will calculate the following + things separately: + - Row header + null_bits + empty_bits fixed size segments etc. + - Size of all char/varchar fields + - Size of each blob field + + The bitmap handler will get all the above information and return + either one page or a set of pages to put the different parts. + + Bitmaps are read on demand in response to insert/delete/update operations. + The following bitmap pointers will be cached and stored on disk on close: + - Current insert_bitmap; When inserting new data we will first try to + fill this one. + - First bitmap which is not completely full. This is updated when we + free data with an update or delete. + + While flushing out bitmaps, we will cache the status of the bitmap in memory + to avoid having to read a bitmap for insert of new data that will not + be of any use + - Total empty space + - Largest number of continuous pages + + Bitmap ONLY goes to disk in the following scenarios + - The file is closed (and we flush all changes to disk) + - On checkpoint + (Ie: When we do a checkpoint, we have to ensure that all bitmaps are + put on disk even if they are not in the page cache). + - When explicitely requested (for example on backup or after recvoery, + to simplify things) + +*/ + +#include "maria_def.h" +#include "ma_blockrec.h" + +/* Number of pages to store blob parts */ +#define BLOB_SEGMENT_MIN_SIZE 128 + +#define FULL_HEAD_PAGE 4 +#define FULL_TAIL_PAGE 7 + +static inline my_bool write_changed_bitmap(MARIA_SHARE *share, + MARIA_FILE_BITMAP *bitmap) +{ + return (key_cache_write(share->key_cache, + bitmap->file, bitmap->page * bitmap->block_size, 0, + (byte*) bitmap->map, + bitmap->block_size, bitmap->block_size, 1)); +} + +/* + Initialize bitmap. This is called the first time a file is opened +*/ + +my_bool _ma_bitmap_init(MARIA_SHARE *share, File file) +{ + uint aligned_bit_blocks; + uint max_page_size; + MARIA_FILE_BITMAP *bitmap= &share->bitmap; + uint size= share->block_size; +#ifndef DBUG_OFF + /* We want to have a copy of the bitmap to be able to print differences */ + size*= 2; +#endif + + if (!(bitmap->map= (uchar*) my_malloc(size, MYF(MY_WME)))) + return 1; + + bitmap->file= file; + bitmap->changed= 0; + bitmap->block_size= share->block_size; + /* Size needs to be alligned on 6 */ + aligned_bit_blocks= share->block_size / 6; + bitmap->total_size= aligned_bit_blocks * 6; + /* + In each 6 bytes, we have 6*8/3 = 16 pages covered + The +1 is to add the bitmap page, as this doesn't have to be covered + */ + bitmap->pages_covered= aligned_bit_blocks * 16 + 1; + + /* Update size for bits */ + /* TODO; Make this dependent of the row size */ + max_page_size= share->block_size - PAGE_OVERHEAD_SIZE; + bitmap->sizes[0]= max_page_size; /* Empty page */ + bitmap->sizes[1]= max_page_size - max_page_size * 30 / 100; + bitmap->sizes[2]= max_page_size - max_page_size * 60 / 100; + bitmap->sizes[3]= max_page_size - max_page_size * 90 / 100; + bitmap->sizes[4]= 0; /* Full page */ + bitmap->sizes[5]= max_page_size - max_page_size * 40 / 100; + bitmap->sizes[6]= max_page_size - max_page_size * 80 / 100; + bitmap->sizes[7]= 0; + + pthread_mutex_init(&share->bitmap.bitmap_lock, MY_MUTEX_INIT_SLOW); + + /* + Start by reading first page (assume table scan) + Later code is simpler if it can assume we always have an active bitmap. + */ + if (_ma_read_bitmap_page(share, bitmap, (ulonglong) 0)) + return(1); + return 0; +} + + +/* + Free data allocated by _ma_bitmap_init +*/ + +my_bool _ma_bitmap_end(MARIA_SHARE *share) +{ + my_bool res= 0; + _ma_flush_bitmap(share); + pthread_mutex_destroy(&share->bitmap.bitmap_lock); + my_free((byte*) share->bitmap.map, MYF(MY_ALLOW_ZERO_PTR)); + return res; +} + + +/* + Flush bitmap to disk +*/ + +my_bool _ma_flush_bitmap(MARIA_SHARE *share) +{ + my_bool res= 0; + if (share->bitmap.changed) + { + pthread_mutex_lock(&share->bitmap.bitmap_lock); + if (share->bitmap.changed) + { + res= write_changed_bitmap(share, &share->bitmap); + share->bitmap.changed= 0; + } + pthread_mutex_unlock(&share->bitmap.bitmap_lock); + } + return res; +} + + +/* + Return bitmap pattern for the smallest head block that can hold 'size' + + SYNOPSIS + size_to_head_pattern() + bitmap Bitmap + size Requested size + + RETURN + 0-3 For a description of the bitmap sizes, see the header +*/ + +static uint size_to_head_pattern(MARIA_FILE_BITMAP *bitmap, uint size) +{ + if (size <= bitmap->sizes[3]) + return 3; + if (size <= bitmap->sizes[2]) + return 2; + if (size <= bitmap->sizes[1]) + return 1; + DBUG_ASSERT(size <= bitmap->sizes[0]); + return 0; +} + + +/* + Return bitmap pattern for block where there is size bytes free +*/ + +uint _ma_free_size_to_head_pattern(MARIA_FILE_BITMAP *bitmap, uint size) +{ + if (size < bitmap->sizes[3]) + return 4; + if (size < bitmap->sizes[2]) + return 3; + if (size < bitmap->sizes[1]) + return 2; + return (size < bitmap->sizes[0]) ? 1 : 0; +} + + +/* + Return bitmap pattern for the smallest tail block that can hold 'size' + + SYNOPSIS + size_to_tail_pattern() + bitmap Bitmap + size Requested size + + RETURN + 0, 5 or 6 For a description of the bitmap sizes, see the header +*/ + +static uint size_to_tail_pattern(MARIA_FILE_BITMAP *bitmap, uint size) +{ + if (size <= bitmap->sizes[6]) + return 6; + if (size <= bitmap->sizes[5]) + return 5; + DBUG_ASSERT(size <= bitmap->sizes[0]); + return 0; +} + + +static uint free_size_to_tail_pattern(MARIA_FILE_BITMAP *bitmap, uint size) +{ + if (size >= bitmap->sizes[0]) + return 0; /* Revert to empty page */ + if (size < bitmap->sizes[6]) + return 7; + if (size < bitmap->sizes[5]) + return 6; + return 5; +} + + +/* + Return size guranteed to be available on a page + + SYNOPSIS + pattern_to_head_size + bitmap Bitmap + pattern Pattern (0-7) + + RETURN + 0 - block_size +*/ + +static inline uint pattern_to_size(MARIA_FILE_BITMAP *bitmap, uint pattern) +{ + DBUG_ASSERT(pattern <= 7); + return bitmap->sizes[pattern]; +} + + +/* + Print bitmap for debugging +*/ + +#ifndef DBUG_OFF + +const char *bits_to_txt[]= +{ + "empty", "00-30% full", "30-60% full", "60-90% full", "full", + "tail 00-40 % full", "tail 40-80 % full", "tail/blob full" +}; + +static void _ma_print_bitmap(MARIA_FILE_BITMAP *bitmap) +{ + uchar *pos, *end, *org_pos; + ulong page; + + end= bitmap->map+ bitmap->used_size; + DBUG_LOCK_FILE; + fprintf(DBUG_FILE,"\nBitmap page changes at page %lu\n", + (ulong) bitmap->page); + + page= (ulong) bitmap->page+1; + for (pos= bitmap->map, org_pos= bitmap->map+bitmap->block_size ; pos < end ; + pos+= 6, org_pos+= 6) + { + ulonglong bits= uint6korr(pos); /* 6 bytes = 6*8/3= 16 patterns */ + ulonglong org_bits= uint6korr(org_pos); + uint i; + if (bits != org_bits) + { + for (i= 0; i < 16 ; i++, bits>>= 3, org_bits>>= 3) + { + if ((bits & 7) != (org_bits & 7)) + fprintf(DBUG_FILE, "Page: %8lu %s -> %s\n", page+i, + bits_to_txt[org_bits & 7], bits_to_txt[bits & 7]); + } + } + page+= 16; + } + fputc('\n', DBUG_FILE); + DBUG_UNLOCK_FILE; + memcpy(bitmap->map+ bitmap->block_size, bitmap->map, bitmap->block_size); +} + +#endif /* DBUG_OFF */ + + +/*************************************************************************** + Reading & writing bitmap pages +***************************************************************************/ + +/* + Read a given bitmap page + + SYNOPSIS + read_bitmap_page() + info Maria handler + bitmap Bitmap handler + page Page to read + + TODO + Update 'bitmap->used_size' to real size of used bitmap + + RETURN + 0 ok + 1 error (Error writing old bitmap or reading bitmap page) +*/ + +my_bool _ma_read_bitmap_page(MARIA_SHARE *share, MARIA_FILE_BITMAP *bitmap, + ulonglong page) +{ + my_off_t position= page * bitmap->block_size; + my_bool res; + DBUG_ENTER("_ma_read_bitmap_page"); + DBUG_ASSERT(page % bitmap->pages_covered == 0); + + bitmap->page= page; + if (position >= share->state.state.data_file_length) + { + share->state.state.data_file_length= position + bitmap->block_size; + bzero(bitmap->map, bitmap->block_size); + bitmap->used_size= 0; + DBUG_RETURN(0); + } + bitmap->used_size= bitmap->total_size; + res= key_cache_read(share->key_cache, + bitmap->file, position, 0, + (byte*) bitmap->map, + bitmap->block_size, bitmap->block_size, 0) == 0; +#ifndef DBUG_OFF + if (!res) + memcpy(bitmap->map+ bitmap->block_size, bitmap->map, bitmap->block_size); +#endif + DBUG_RETURN(res); +} + + +/* + Change to another bitmap page + + SYNOPSIS + _ma_change_bitmap_page() + info Maria handler + bitmap Bitmap handler + page Bitmap page to read + + NOTES + If old bitmap was changed, write it out before reading new one + We return empty bitmap if page is outside of file size + + RETURN + 0 ok + 1 error (Error writing old bitmap or reading bitmap page) +*/ + +static my_bool _ma_change_bitmap_page(MARIA_HA *info, + MARIA_FILE_BITMAP *bitmap, + ulonglong page) +{ + DBUG_ENTER("_ma_change_bitmap_page"); + DBUG_ASSERT(page % bitmap->pages_covered == 0); + + if (bitmap->changed) + { + if (write_changed_bitmap(info->s, bitmap)) + DBUG_RETURN(1); + bitmap->changed= 0; + } + DBUG_RETURN(_ma_read_bitmap_page(info->s, bitmap, page)); +} + + +/* + Read next suitable bitmap + + SYNOPSIS + move_to_next_bitmap() + bitmap Bitmap handle + + TODO + Add cache of bitmaps to not read something that is not usable + + RETURN + 0 ok + 1 error (either couldn't save old bitmap or read new one +*/ + +static my_bool move_to_next_bitmap(MARIA_HA *info, MARIA_FILE_BITMAP *bitmap) +{ + ulonglong page= bitmap->page; + MARIA_STATE_INFO *state= &info->s->state; + DBUG_ENTER("move_to_next_bitmap"); + + if (state->first_bitmap_with_space != ~(ulonglong) 0 && + state->first_bitmap_with_space != page) + { + page= state->first_bitmap_with_space; + state->first_bitmap_with_space= ~(ulonglong) 0; + } + else + page+= bitmap->pages_covered; + DBUG_RETURN(_ma_change_bitmap_page(info, bitmap, page)); +} + + +/**************************************************************************** + Allocate data in bitmaps +****************************************************************************/ + +/* + Store data in 'block' and mark the place used in the bitmap + + SYNOPSIS + fill_block() + bitmap Bitmap handle + block Store data about what we found + best_data Pointer to best 6 byte aligned area in bitmap->map + best_pos Which bit in *best_data the area starts + 0 = first bit pattern, 1 second bit pattern etc + fill_pattern Bitmap pattern to store in best_data[best_pos] +*/ + +static void fill_block(MARIA_FILE_BITMAP *bitmap, + MARIA_BITMAP_BLOCK *block, + uchar *best_data, uint best_pos, uint best_bits, + uint fill_pattern) +{ + uint page, offset, tmp; + uchar *data; + + /* For each 6 bytes we have 6*8/3= 16 patterns */ + page= (best_data - bitmap->map) / 6 * 16 + best_pos; + block->page= bitmap->page + 1 + page; + block->page_count= 1 + TAIL_BIT; + block->empty_space= pattern_to_size(bitmap, best_bits); + block->sub_blocks= 1; + block->org_bitmap_value= best_bits; + block->used= BLOCKUSED_TAIL; + + /* + Mark place used by reading/writing 2 bytes at a time to handle + bitmaps in overlapping bytes + */ + best_pos*= 3; + data= best_data+ best_pos / 8; + offset= best_pos & 7; + tmp= uint2korr(data); + tmp= (tmp & ~(7 << offset)) | (fill_pattern << offset); + int2store(data, tmp); + bitmap->changed= 1; + DBUG_EXECUTE("bitmap", _ma_print_bitmap(bitmap);); +} + + +/* + Allocate data for head block + + SYNOPSIS + allocate_head() + bitmap bitmap + size Size of block we need to find + block Store found information here + + RETURN + 0 ok (block is updated) + 1 error (no space in bitmap; block is not touched) +*/ + + +static my_bool allocate_head(MARIA_FILE_BITMAP *bitmap, uint size, + MARIA_BITMAP_BLOCK *block) +{ + uint min_bits= size_to_head_pattern(bitmap, size); + uchar *data= bitmap->map, *end= data + bitmap->used_size; + uchar *best_data= 0; + uint best_bits= (uint) -1, best_pos; + DBUG_ENTER("allocate_head"); + + LINT_INIT(best_pos); + DBUG_ASSERT(size <= FULL_PAGE_SIZE(bitmap->block_size)); + + for (; data < end; data += 6) + { + ulonglong bits= uint6korr(data); /* 6 bytes = 6*8/3= 16 patterns */ + uint i; + + /* + Skip common patterns + We can skip empty pages (if we already found a match) or + anything matching the following pattern as this will be either + a full page or a tail page + */ + if ((!bits && best_data) || + ((bits & LL(04444444444444444)) == LL(04444444444444444))) + continue; + for (i= 0; i < 16 ; i++, bits >>= 3) + { + uint pattern= bits & 7; + if (pattern <= min_bits) + { + if (pattern == min_bits) + { + /* Found perfect match */ + best_bits= min_bits; + best_data= data; + best_pos= i; + goto found; + } + if ((int) pattern > (int) best_bits) + { + best_bits= pattern; + best_data= data; + best_pos= i; + } + } + } + } + if (!best_data) + { + if (bitmap->used_size == bitmap->total_size) + DBUG_RETURN(1); + /* Allocate data at end of bitmap */ + bitmap->used_size+= 6; + best_data= data; + best_pos= best_bits= 0; + } + +found: + fill_block(bitmap, block, best_data, best_pos, best_bits, FULL_HEAD_PAGE); + DBUG_RETURN(0); +} + + +/* + Allocate data for tail block + + SYNOPSIS + allocate_tail() + bitmap bitmap + size Size of block we need to find + block Store found information here + + RETURN + 0 ok (block is updated) + 1 error (no space in bitmap; block is not touched) +*/ + + +static my_bool allocate_tail(MARIA_FILE_BITMAP *bitmap, uint size, + MARIA_BITMAP_BLOCK *block) +{ + uint min_bits= size_to_tail_pattern(bitmap, size); + uchar *data= bitmap->map, *end= data + bitmap->used_size; + uchar *best_data= 0; + uint best_bits= (uint) -1, best_pos; + DBUG_ENTER("allocate_tail"); + DBUG_PRINT("enter", ("size: %u", size)); + + LINT_INIT(best_pos); + DBUG_ASSERT(size <= FULL_PAGE_SIZE(bitmap->block_size)); + + for (; data < end; data += 6) + { + ulonglong bits= uint6korr(data); /* 6 bytes = 6*8/3= 16 patterns */ + uint i; + + /* + Skip common patterns + We can skip empty pages (if we already found a match) or + the following patterns: 1-4 or 7 + */ + + if ((!bits && best_data) || bits == LL(0xffffffffffff)) + continue; + for (i= 0; i < 16; i++, bits >>= 3) + { + uint pattern= bits & 7; + if (pattern <= min_bits && (!pattern || pattern >= 5)) + { + if (pattern == min_bits) + { + best_bits= min_bits; + best_data= data; + best_pos= i; + goto found; + } + if ((int) pattern > (int) best_bits) + { + best_bits= pattern; + best_data= data; + best_pos= i; + } + } + } + } + if (!best_data) + { + if (bitmap->used_size == bitmap->total_size) + DBUG_RETURN(1); + /* Allocate data at end of bitmap */ + bitmap->used_size+= 6; + best_pos= best_bits= 0; + } + +found: + fill_block(bitmap, block, best_data, best_pos, best_bits, FULL_TAIL_PAGE); + DBUG_RETURN(0); +} + + +/* + Allocate data for full blocks + + SYNOPSIS + allocate_full_pages() + bitmap bitmap + pages_needed Total size in pages (bitmap->total_size) we would like to have + block Store found information here + full_page 1 if we are not allowed to split extent + + IMPLEMENTATION + We will return the smallest area >= size. If there is no such + block, we will return the biggest area that satisfies + area_size >= min(BLOB_SEGMENT_MIN_SIZE*full_page_size, size) + + To speed up searches, we will only consider areas that has at least 16 free + pages starting on an even boundary. When finding such an area, we will + extend it with all previous and following free pages. This will ensure + we don't get holes between areas + + RETURN + # Blocks used + 0 error (no space in bitmap; block is not touched) +*/ + +static ulong allocate_full_pages(MARIA_FILE_BITMAP *bitmap, + ulong pages_needed, + MARIA_BITMAP_BLOCK *block, my_bool full_page) +{ + uchar *data= bitmap->map, *data_end= data + bitmap->used_size; + uchar *page_end= data + bitmap->total_size; + uchar *best_data= 0; + uint min_size; + uint best_area_size, best_prefix_area_size, best_suffix_area_size; + uint page, size; + ulonglong best_prefix_bits; + DBUG_ENTER("allocate_full_pages"); + DBUG_PRINT("enter", ("pages_needed: %lu", pages_needed)); + + /* Following variables are only used if best_data is set */ + LINT_INIT(best_prefix_bits); + LINT_INIT(best_prefix_area_size); + LINT_INIT(best_suffix_area_size); + + min_size= pages_needed; + if (!full_page && min_size > BLOB_SEGMENT_MIN_SIZE) + min_size= BLOB_SEGMENT_MIN_SIZE; + best_area_size= ~(uint) 0; + + for (; data < page_end; data+= 6) + { + ulonglong bits= uint6korr(data); /* 6 bytes = 6*8/3= 16 patterns */ + uchar *data_start; + ulonglong prefix_bits= 0; + uint area_size, prefix_area_size, suffix_area_size; + + /* Find area with at least 16 free pages */ + if (bits) + continue; + data_start= data; + /* Find size of area */ + for (data+=6 ; data < data_end ; data+= 6) + { + if ((bits= uint6korr(data))) + break; + } + area_size= (data - data_start) / 6 * 16; + if (area_size >= best_area_size) + continue; + prefix_area_size= suffix_area_size= 0; + if (!bits) + { + /* + End of page; All the rest of the bits on page are part of area + This is needed because bitmap->used_size only covers the set bits + in the bitmap. + */ + area_size+= (page_end - data) / 6 * 16; + if (area_size >= best_area_size) + break; + data= page_end; + } + else + { + /* Add bits at end of page */ + for (; !(bits & 7); bits >>= 3) + suffix_area_size++; + area_size+= suffix_area_size; + } + if (data_start != bitmap->map) + { + /* Add bits before page */ + bits= prefix_bits= uint6korr(data_start - 6); + DBUG_ASSERT(bits != 0); + /* 111 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 */ + if (!(bits & LL(07000000000000000))) + { + data_start-= 6; + do + { + prefix_area_size++; + bits<<= 3; + } while (!(bits & LL(07000000000000000))); + area_size+= prefix_area_size; + /* Calculate offset to page from data_start */ + prefix_area_size= 16 - prefix_area_size; + } + } + if (area_size >= min_size && area_size <= best_area_size) + { + best_data= data_start; + best_area_size= area_size; + best_prefix_bits= prefix_bits; + best_prefix_area_size= prefix_area_size; + best_suffix_area_size= suffix_area_size; + + /* Prefer to put data in biggest possible area */ + if (area_size <= pages_needed) + min_size= area_size; + else + min_size= pages_needed; + } + } + if (!best_data) + DBUG_RETURN(0); /* No room on page */ + + /* + Now allocate min(pages_needed, area_size), starting from + best_start + best_prefix_area_size + */ + if (best_area_size > pages_needed) + best_area_size= pages_needed; + + /* For each 6 bytes we have 6*8/3= 16 patterns */ + page= ((best_data - bitmap->map) * 8) / 3 + best_prefix_area_size; + block->page= bitmap->page + 1 + page; + block->page_count= best_area_size; + block->empty_space= 0; + block->sub_blocks= 1; + block->org_bitmap_value= 0; + block->used= 0; + DBUG_PRINT("info", ("page: %lu page_count: %u", + (ulong) block->page, block->page_count)); + + if (best_prefix_area_size) + { + ulonglong tmp; + /* Convert offset back to bits */ + best_prefix_area_size= 16 - best_prefix_area_size; + if (best_area_size < best_prefix_area_size) + { + tmp= (LL(1) << best_area_size*3) - 1; + best_area_size= best_prefix_area_size; /* for easy end test */ + } + else + tmp= (LL(1) << best_prefix_area_size*3) - 1; + tmp<<= (16 - best_prefix_area_size) * 3; + DBUG_ASSERT((best_prefix_bits & tmp) == 0); + best_prefix_bits|= tmp; + int6store(best_data, best_prefix_bits); + if (!(best_area_size-= best_prefix_area_size)) + { + DBUG_EXECUTE("bitmap", _ma_print_bitmap(bitmap);); + DBUG_RETURN(block->page_count); + } + best_data+= 6; + } + best_area_size*= 3; /* Bits to set */ + size= best_area_size/8; /* Bytes to set */ + bfill(best_data, size, 255); + best_data+= size; + if ((best_area_size-= size * 8)) + { + /* fill last byte */ + *best_data|= (uchar) ((1 << best_area_size) -1); + best_data++; + } + if (data_end < best_data) + bitmap->used_size= (uint) (best_data - bitmap->map); + bitmap->changed= 1; + DBUG_EXECUTE("bitmap", _ma_print_bitmap(bitmap);); + DBUG_RETURN(block->page_count); +} + + +/**************************************************************************** + Find right bitmaps where to store data +****************************************************************************/ + +/* + Find right bitmap and position for head block + + RETURN + 0 ok + 1 error +*/ + +static my_bool find_head(MARIA_HA *info, uint length, uint position) +{ + MARIA_FILE_BITMAP *bitmap= &info->s->bitmap; + MARIA_BITMAP_BLOCK *block; + /* There is always place for head blocks in bitmap_blocks */ + block= dynamic_element(&info->bitmap_blocks, position, MARIA_BITMAP_BLOCK *); + + while (allocate_head(bitmap, length, block)) + if (move_to_next_bitmap(info, bitmap)) + return 1; + return 0; +} + + +/* + Find right bitmap and position for tail + + RETURN + 0 ok + 1 error +*/ + +static my_bool find_tail(MARIA_HA *info, uint length, uint position) +{ + MARIA_FILE_BITMAP *bitmap= &info->s->bitmap; + MARIA_BITMAP_BLOCK *block; + DBUG_ENTER("find_tail"); + + /* Needed, as there is no error checking in dynamic_element */ + if (allocate_dynamic(&info->bitmap_blocks, position)) + DBUG_RETURN(1); + block= dynamic_element(&info->bitmap_blocks, position, MARIA_BITMAP_BLOCK *); + + while (allocate_tail(bitmap, length, block)) + if (move_to_next_bitmap(info, bitmap)) + DBUG_RETURN(1); + DBUG_RETURN(0); +} + + +/* + Find right bitmap and position for full blocks in one extent + + NOTES + This is used to allocate the main extent after the 'head' block + + RETURN + 0 ok + 1 error +*/ + +static my_bool find_mid(MARIA_HA *info, ulong pages, uint position) +{ + MARIA_FILE_BITMAP *bitmap= &info->s->bitmap; + MARIA_BITMAP_BLOCK *block; + block= dynamic_element(&info->bitmap_blocks, position, MARIA_BITMAP_BLOCK *); + + while (allocate_full_pages(bitmap, pages, block, 1)) + { + if (move_to_next_bitmap(info, bitmap)) + return 1; + } + return 0; +} + + +/* + Find right bitmap and position for putting a blob + + NOTES + The extents are stored last in info->bitmap_blocks + + IMPLEMENTATION + Allocate all full pages for the block + optionally one tail + + RETURN + 0 ok + 1 error +*/ + +static my_bool find_blob(MARIA_HA *info, ulong length) +{ + MARIA_FILE_BITMAP *bitmap= &info->s->bitmap; + uint full_page_size= FULL_PAGE_SIZE(info->s->block_size); + ulong pages; + uint rest_length, used; + uint first_block_pos; + MARIA_BITMAP_BLOCK *first_block= 0; + DBUG_ENTER("find_blob"); + DBUG_PRINT("enter", ("length: %lu", length)); + + pages= length / full_page_size; + rest_length= (uint) (length - pages * full_page_size); + if (rest_length >= MAX_TAIL_SIZE(info->s->block_size)) + { + pages++; + rest_length= 0; + } + + if (pages) + { + MARIA_BITMAP_BLOCK *block; + if (allocate_dynamic(&info->bitmap_blocks, + info->bitmap_blocks.elements + + pages / BLOB_SEGMENT_MIN_SIZE + 2)) + DBUG_RETURN(1); + first_block_pos= info->bitmap_blocks.elements; + block= dynamic_element(&info->bitmap_blocks, info->bitmap_blocks.elements, + MARIA_BITMAP_BLOCK*); + first_block= block; + do + { + used= allocate_full_pages(bitmap, + (pages >= 65535 ? 65535 : (uint) pages), block, + 0); + if (!used && move_to_next_bitmap(info, bitmap)) + DBUG_RETURN(1); + info->bitmap_blocks.elements++; + block++; + } while ((pages-= used) != 0); + } + if (rest_length && find_tail(info, rest_length, + info->bitmap_blocks.elements++)) + DBUG_RETURN(1); + if (first_block) + first_block->sub_blocks= info->bitmap_blocks.elements - first_block_pos; + DBUG_RETURN(0); +} + + +static my_bool allocate_blobs(MARIA_HA *info, MARIA_ROW *row) +{ + ulong *length, *end; + uint elements; + /* + Reserve size for: + head block + one extent + tail block + */ + elements= info->bitmap_blocks.elements; + for (length= row->blob_lengths, end= length + info->s->base.blobs; + length < end; length++) + { + if (*length && find_blob(info, *length)) + return 1; + } + row->extents_count= (info->bitmap_blocks.elements - elements); + return 0; +} + + +static void use_head(MARIA_HA *info, ulonglong page, uint size, + uint block_position) +{ + MARIA_FILE_BITMAP *bitmap= &info->s->bitmap; + MARIA_BITMAP_BLOCK *block; + uchar *data; + uint offset, tmp, offset_page; + + block= dynamic_element(&info->bitmap_blocks, block_position, + MARIA_BITMAP_BLOCK*); + block->page= page; + block->page_count= 1 + TAIL_BIT; + block->empty_space= size; + block->sub_blocks= 1; + block->used= BLOCKUSED_TAIL; + + /* + Mark place used by reading/writing 2 bytes at a time to handle + bitmaps in overlapping bytes + */ + offset_page= (uint) (page - bitmap->page - 1) * 3; + offset= offset_page & 7; + data= bitmap->map + offset_page / 8; + tmp= uint2korr(data); + block->org_bitmap_value= (tmp >> offset) & 7; + tmp= (tmp & ~(7 << offset)) | (FULL_HEAD_PAGE << offset); + int2store(data, tmp); + bitmap->changed= 1; + DBUG_EXECUTE("bitmap", _ma_print_bitmap(bitmap);); +} + + +/* + Find out where to split the row; +*/ + +static uint find_where_to_split_row(MARIA_SHARE *share, MARIA_ROW *row, + uint extents_length, uint split_size) +{ + uint row_length= row->base_length; + uint *lengths, *lengths_end; + + DBUG_ASSERT(row_length < split_size); + /* + Store first in all_field_lengths the different parts that are written + to the row. This needs to be in same order as in + ma_block_rec.c::write_block_record() + */ + row->null_field_lengths[-3]= extents_length; + row->null_field_lengths[-2]= share->base.fixed_not_null_fields_length; + row->null_field_lengths[-1]= row->field_lengths_length; + for (lengths= row->null_field_lengths - EXTRA_LENGTH_FIELDS, + lengths_end= (lengths + share->base.pack_fields - share->base.blobs + + EXTRA_LENGTH_FIELDS); lengths < lengths_end; lengths++) + { + if (row_length + *lengths > split_size) + break; + row_length+= *lengths; + } + return row_length; +} + + +static my_bool write_rest_of_head(MARIA_HA *info, uint position, + ulong rest_length) +{ + MARIA_SHARE *share= info->s; + uint full_page_size= FULL_PAGE_SIZE(share->block_size); + MARIA_BITMAP_BLOCK *block; + + if (position == 0) + { + /* Write out full pages */ + uint pages= rest_length / full_page_size; + + rest_length%= full_page_size; + if (rest_length >= MAX_TAIL_SIZE(share->block_size)) + { + /* Put tail on a full page */ + pages++; + rest_length= 0; + } + if (find_mid(info, rest_length / full_page_size, 1)) + return 1; + /* + Insert empty block after full pages, to allow write_block_record() to + split segment into used + free page + */ + block= dynamic_element(&info->bitmap_blocks, 2, MARIA_BITMAP_BLOCK*); + block->page_count= 0; + block->used= 0; + } + if (rest_length) + { + if (find_tail(info, rest_length, ELEMENTS_RESERVED_FOR_MAIN_PART - 1)) + return 1; + } + else + { + /* Empty tail block */ + block= dynamic_element(&info->bitmap_blocks, + ELEMENTS_RESERVED_FOR_MAIN_PART - 1, + MARIA_BITMAP_BLOCK *); + block->page_count= 0; + block->used= 0; + } + return 0; +} + + +/* + Find where to store one row + + SYNPOSIS + _ma_bitmap_find_place() + info Maria handler + row Information about row to write + blocks Store data about allocated places here + + RETURN + 0 ok + 1 error +*/ + +my_bool _ma_bitmap_find_place(MARIA_HA *info, MARIA_ROW *row, + MARIA_BITMAP_BLOCKS *blocks) +{ + MARIA_SHARE *share= info->s; + my_bool res= 1; + uint full_page_size, position, max_page_size; + uint head_length, row_length, rest_length, extents_length; + DBUG_ENTER("_ma_bitmap_find_place"); + + blocks->count= 0; + blocks->tail_page_skipped= blocks->page_skipped= 0; + row->extents_count= 0; + /* + Reserver place for the following blocks: + - Head block + - Full page block + - Marker block to allow write_block_record() to split full page blocks + into full and free part + - Tail block + */ + + info->bitmap_blocks.elements= ELEMENTS_RESERVED_FOR_MAIN_PART; + max_page_size= (share->block_size - PAGE_OVERHEAD_SIZE); + + pthread_mutex_lock(&share->bitmap.bitmap_lock); + + if (row->total_length <= max_page_size) + { + /* Row fits in one page */ + position= ELEMENTS_RESERVED_FOR_MAIN_PART - 1; + if (find_head(info, (uint) row->total_length, position)) + goto abort; + goto end; + } + + /* + First allocate all blobs (so that we can find out the needed size for + the main block. + */ + if (row->blob_length && allocate_blobs(info, row)) + goto abort; + + extents_length= row->extents_count * ROW_EXTENT_SIZE; + if ((head_length= (row->head_length + extents_length)) <= max_page_size) + { + /* Main row part fits into one page */ + position= ELEMENTS_RESERVED_FOR_MAIN_PART - 1; + if (find_head(info, head_length, position)) + goto abort; + goto end; + } + + /* Allocate enough space */ + head_length+= ELEMENTS_RESERVED_FOR_MAIN_PART * ROW_EXTENT_SIZE; + + /* The first segment size is stored in 'row_length' */ + row_length= find_where_to_split_row(share, row, extents_length, + max_page_size); + + full_page_size= FULL_PAGE_SIZE(share->block_size); + position= 0; + if (head_length - row_length <= full_page_size) + position= ELEMENTS_RESERVED_FOR_MAIN_PART -2; /* Only head and tail */ + if (find_head(info, row_length, position)) + goto abort; + rest_length= head_length - row_length; + if (write_rest_of_head(info, position, rest_length)) + goto abort; + +end: + blocks->block= dynamic_element(&info->bitmap_blocks, position, + MARIA_BITMAP_BLOCK*); + blocks->block->sub_blocks= ELEMENTS_RESERVED_FOR_MAIN_PART - position; + /* First block's page_count is for all blocks */ + blocks->count= info->bitmap_blocks.elements - position; + res= 0; + +abort: + pthread_mutex_unlock(&share->bitmap.bitmap_lock); + DBUG_RETURN(res); +} + + +/* + Find where to put row on update (when head page is already defined) + + SYNPOSIS + _ma_bitmap_find_new_place() + info Maria handler + row Information about row to write + page On which page original row was stored + free_size Free size on head page + blocks Store data about allocated places here + + NOTES + This function is only called when the new row can't fit in the space of + the old row in the head page. + + This is essently same as _ma_bitmap_find_place() except that + we don't call find_head() to search in bitmaps where to put the page. + + RETURN + 0 ok + 1 error +*/ + +my_bool _ma_bitmap_find_new_place(MARIA_HA *info, MARIA_ROW *row, + ulonglong page, uint free_size, + MARIA_BITMAP_BLOCKS *blocks) +{ + MARIA_SHARE *share= info->s; + my_bool res= 1; + uint full_page_size, position; + uint head_length, row_length, rest_length, extents_length; + DBUG_ENTER("_ma_bitmap_find_new_place"); + + blocks->count= 0; + blocks->tail_page_skipped= blocks->page_skipped= 0; + row->extents_count= 0; + info->bitmap_blocks.elements= ELEMENTS_RESERVED_FOR_MAIN_PART; + + pthread_mutex_lock(&share->bitmap.bitmap_lock); + if (share->bitmap.page != page / share->bitmap.pages_covered && + _ma_change_bitmap_page(info, &share->bitmap, + page / share->bitmap.pages_covered)) + goto abort; + + /* + First allocate all blobs (so that we can find out the needed size for + the main block. + */ + if (row->blob_length && allocate_blobs(info, row)) + goto abort; + + extents_length= row->extents_count * ROW_EXTENT_SIZE; + if ((head_length= (row->head_length + extents_length)) <= free_size) + { + /* Main row part fits into one page */ + position= ELEMENTS_RESERVED_FOR_MAIN_PART - 1; + use_head(info, page, head_length, position); + goto end; + } + + /* Allocate enough space */ + head_length+= ELEMENTS_RESERVED_FOR_MAIN_PART * ROW_EXTENT_SIZE; + + /* The first segment size is stored in 'row_length' */ + row_length= find_where_to_split_row(share, row, extents_length, free_size); + + full_page_size= FULL_PAGE_SIZE(share->block_size); + position= 0; + if (head_length - row_length <= full_page_size) + position= ELEMENTS_RESERVED_FOR_MAIN_PART -2; /* Only head and tail */ + use_head(info, page, row_length, position); + rest_length= head_length - row_length; + + if (write_rest_of_head(info, position, rest_length)) + goto abort; + +end: + blocks->block= dynamic_element(&info->bitmap_blocks, position, + MARIA_BITMAP_BLOCK*); + blocks->block->sub_blocks= ELEMENTS_RESERVED_FOR_MAIN_PART - position; + /* First block's page_count is for all blocks */ + blocks->count= info->bitmap_blocks.elements - position; + res= 0; + +abort: + pthread_mutex_unlock(&share->bitmap.bitmap_lock); + DBUG_RETURN(res); +} + + +/**************************************************************************** + Clear and reset bits +****************************************************************************/ + +static my_bool set_page_bits(MARIA_HA *info, MARIA_FILE_BITMAP *bitmap, + ulonglong page, uint fill_pattern) +{ + ulonglong bitmap_page; + uint offset_page, offset, tmp, org_tmp; + uchar *data; + DBUG_ENTER("set_page_bits"); + + bitmap_page= page / bitmap->pages_covered; + if (bitmap_page != bitmap->page && + _ma_change_bitmap_page(info, bitmap, bitmap_page)) + DBUG_RETURN(1); + + /* Find page number from start of bitmap */ + offset_page= page - bitmap->page - 1; + /* + Mark place used by reading/writing 2 bytes at a time to handle + bitmaps in overlapping bytes + */ + offset_page*= 3; + offset= offset_page & 7; + data= bitmap->map + offset_page / 8; + org_tmp= tmp= uint2korr(data); + tmp= (tmp & ~(7 << offset)) | (fill_pattern << offset); + if (tmp == org_tmp) + DBUG_RETURN(0); /* No changes */ + int2store(data, tmp); + + bitmap->changed= 1; + DBUG_EXECUTE("bitmap", _ma_print_bitmap(bitmap);); + if (fill_pattern != 3 && fill_pattern != 7 && + page < info->s->state.first_bitmap_with_space) + info->s->state.first_bitmap_with_space= page; + DBUG_RETURN(0); +} + + +/* + Get bitmap pattern for a given page + + SYNOPSIS + + get_page_bits() + info Maria handler + bitmap Bitmap handler + page Page number + + RETURN + 0-7 Bitmap pattern + ~0 Error (couldn't read page) +*/ + +static uint get_page_bits(MARIA_HA *info, MARIA_FILE_BITMAP *bitmap, + ulonglong page) +{ + ulonglong bitmap_page; + uint offset_page, offset, tmp; + uchar *data; + DBUG_ENTER("get_page_bits"); + + bitmap_page= page / bitmap->pages_covered; + if (bitmap_page != bitmap->page && + _ma_change_bitmap_page(info, bitmap, bitmap_page)) + DBUG_RETURN(~ (uint) 0); + + /* Find page number from start of bitmap */ + offset_page= page - bitmap->page - 1; + /* + Mark place used by reading/writing 2 bytes at a time to handle + bitmaps in overlapping bytes + */ + offset_page*= 3; + offset= offset_page & 7; + data= bitmap->map + offset_page / 8; + tmp= uint2korr(data); + DBUG_RETURN((tmp >> offset) & 7); +} + + +/* + Mark all pages in a region as free + + SYNOPSIS + reset_full_page_bits() + info Maria handler + bitmap Bitmap handler + page Start page + page_count Number of pages + + NOTES + We assume that all pages in region is covered by same bitmap + One must have a lock on info->s->bitmap.bitmap_lock + + RETURN + 0 ok + 1 Error (when reading bitmap) +*/ + +my_bool _ma_reset_full_page_bits(MARIA_HA *info, MARIA_FILE_BITMAP *bitmap, + ulonglong page, uint page_count) +{ + ulonglong bitmap_page; + uint offset, bit_start, bit_count, tmp; + uchar *data; + DBUG_ENTER("_ma_reset_full_page_bits"); + DBUG_PRINT("enter", ("page: %lu page_count: %u", (ulong) page, page_count)); + safe_mutex_assert_owner(&info->s->bitmap.bitmap_lock); + + bitmap_page= page / bitmap->pages_covered; + if (bitmap_page != bitmap->page && + _ma_change_bitmap_page(info, bitmap, bitmap_page)) + DBUG_RETURN(1); + + /* Find page number from start of bitmap */ + page= page - bitmap->page - 1; + + /* Clear bits from 'page * 3' -> '(page + page_count) * 3' */ + bit_start= page * 3; + bit_count= page_count * 3; + + data= bitmap->map + bit_start / 8; + offset= bit_start & 7; + + tmp= (255 << offset); /* Bits to keep */ + if (bit_count + offset < 8) + { + /* Only clear bits between 'offset' and 'offset+bit_count-1' */ + tmp^= (255 << (offset + bit_count)); + } + *data&= ~tmp; + + if ((int) (bit_count-= (8 - offset)) > 0) + { + uint fill; + data++; + /* + -1 is here to avoid one 'if' statement and to let the following code + handle the last byte + */ + if ((fill= (bit_count - 1) / 8)) + { + bzero(data, fill); + data+= fill; + } + bit_count-= fill * 8; /* Bits left to clear */ + tmp= (1 << bit_count) - 1; + *data&= ~tmp; + } + if (bitmap->page < (ulonglong) info->s->state.first_bitmap_with_space) + info->s->state.first_bitmap_with_space= bitmap->page; + bitmap->changed= 1; + DBUG_EXECUTE("bitmap", _ma_print_bitmap(bitmap);); + DBUG_RETURN(0); +} + + +/* + Correct bitmap pages to reflect the true allocation + + SYNOPSIS + _ma_bitmap_release_unused() + info Maria handle + blocks Bitmap blocks + + IMPLEMENTATION + If block->used & BLOCKUSED_TAIL is set: + If block->used & BLOCKUSED_USED is set, then the bits for the + corresponding page is set according to block->empty_space + If block->used & BLOCKUSED_USED is not set, then the bits for + the corresponding page is set to org_bitmap_value; + + If block->used & BLOCKUSED_TAIL is not set: + if block->used is not set, the bits for the corresponding page are + cleared + + For the first block (head block) the logic is same as for a tail block + + RETURN + 0 ok + 1 error (Couldn't write or read bitmap page) +*/ + +my_bool _ma_bitmap_release_unused(MARIA_HA *info, MARIA_BITMAP_BLOCKS *blocks) +{ + MARIA_BITMAP_BLOCK *block= blocks->block, *end= block + blocks->count; + MARIA_FILE_BITMAP *bitmap= &info->s->bitmap; + uint bits, current_bitmap_value; + DBUG_ENTER("_ma_bitmap_release_unused"); + + /* + We can skip FULL_HEAD_PAGE (4) as the page was marked as 'full' + when we allocated space in the page + */ + current_bitmap_value= FULL_HEAD_PAGE; + + pthread_mutex_lock(&info->s->bitmap.bitmap_lock); + + /* First handle head block */ + if (block->used & BLOCKUSED_USED) + { + DBUG_PRINT("info", ("head empty_space: %u", block->empty_space)); + bits= _ma_free_size_to_head_pattern(bitmap, block->empty_space); + if (block->used & BLOCKUSED_USE_ORG_BITMAP) + current_bitmap_value= block->org_bitmap_value; + } + else + bits= block->org_bitmap_value; + if (bits != current_bitmap_value && + set_page_bits(info, bitmap, block->page, bits)) + goto err; + + + /* Handle all full pages and tail pages (for head page and blob) */ + for (block++; block < end; block++) + { + if (block->used & BLOCKUSED_TAIL) + { + if (block->used & BLOCKUSED_USED) + { + DBUG_PRINT("info", ("tail empty_space: %u", block->empty_space)); + bits= free_size_to_tail_pattern(bitmap, block->empty_space); + } + else + bits= block->org_bitmap_value; + if (bits != FULL_TAIL_PAGE && + set_page_bits(info, bitmap, block->page, bits)) + goto err; + } + if (!(block->used & BLOCKUSED_USED) && + _ma_reset_full_page_bits(info, bitmap, + block->page, block->page_count)) + goto err; + } + pthread_mutex_unlock(&info->s->bitmap.bitmap_lock); + DBUG_RETURN(0); + +err: + pthread_mutex_unlock(&info->s->bitmap.bitmap_lock); + DBUG_RETURN(1); +} + + +/* + Free full pages from bitmap + + SYNOPSIS + _ma_bitmap_free_full_pages() + info Maria handle + extents Extents (as stored on disk) + count Number of extents + + IMPLEMENTATION + Mark all full pages (not tails) from extents as free + + RETURN + 0 ok + 1 error (Couldn't write or read bitmap page) +*/ + +my_bool _ma_bitmap_free_full_pages(MARIA_HA *info, const byte *extents, + uint count) +{ + DBUG_ENTER("_ma_bitmap_free_full_pages"); + + pthread_mutex_lock(&info->s->bitmap.bitmap_lock); + for (; count--; extents += ROW_EXTENT_SIZE) + { + ulonglong page= uint5korr(extents); + uint page_count= uint2korr(extents + ROW_EXTENT_PAGE_SIZE); + if (!(page_count & TAIL_BIT)) + { + if (_ma_reset_full_page_bits(info, &info->s->bitmap, page, page_count)) + { + pthread_mutex_unlock(&info->s->bitmap.bitmap_lock); + DBUG_RETURN(1); + } + } + } + pthread_mutex_unlock(&info->s->bitmap.bitmap_lock); + DBUG_RETURN(0); +} + + + +my_bool _ma_bitmap_set(MARIA_HA *info, ulonglong pos, my_bool head, + uint empty_space) +{ + MARIA_FILE_BITMAP *bitmap= &info->s->bitmap; + uint bits; + my_bool res; + DBUG_ENTER("_ma_bitmap_set"); + + pthread_mutex_lock(&info->s->bitmap.bitmap_lock); + bits= (head ? + _ma_free_size_to_head_pattern(bitmap, empty_space) : + free_size_to_tail_pattern(bitmap, empty_space)); + res= set_page_bits(info, bitmap, pos, bits); + pthread_mutex_unlock(&info->s->bitmap.bitmap_lock); + DBUG_RETURN(res); +} + + +/* + Check that bitmap pattern is correct for a page + + NOTES + Used in maria_chk + + RETURN + 0 ok + 1 error +*/ + +my_bool _ma_check_bitmap_data(MARIA_HA *info, + enum en_page_type page_type, ulonglong page, + uint empty_space, uint *bitmap_pattern) +{ + uint bits; + switch (page_type) { + case UNALLOCATED_PAGE: + case MAX_PAGE_TYPE: + bits= 0; + break; + case HEAD_PAGE: + bits= _ma_free_size_to_head_pattern(&info->s->bitmap, empty_space); + break; + case TAIL_PAGE: + bits= free_size_to_tail_pattern(&info->s->bitmap, empty_space); + break; + case BLOB_PAGE: + bits= FULL_TAIL_PAGE; + break; + } + return (*bitmap_pattern= get_page_bits(info, &info->s->bitmap, page)) != + bits; +} + + +/* + Check that bitmap pattern is correct for a page + + NOTES + Used in maria_chk + + RETURN + 0 ok + 1 error +*/ + +my_bool _ma_check_if_right_bitmap_type(MARIA_HA *info, + enum en_page_type page_type, + ulonglong page, + uint *bitmap_pattern) +{ + if ((*bitmap_pattern= get_page_bits(info, &info->s->bitmap, page)) > 7) + return 1; /* Couldn't read page */ + switch (page_type) { + case HEAD_PAGE: + return *bitmap_pattern < 1 || *bitmap_pattern > 4; + case TAIL_PAGE: + return *bitmap_pattern < 5; + case BLOB_PAGE: + return *bitmap_pattern != 7; + default: + break; + } + DBUG_ASSERT(0); + return 1; +} diff --git a/storage/maria/ma_blockrec.c b/storage/maria/ma_blockrec.c new file mode 100644 index 00000000000..6eac151d76e --- /dev/null +++ b/storage/maria/ma_blockrec.c @@ -0,0 +1,2742 @@ +/* Copyright (C) 2007 Michael Widenius + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +/* + Storage of records in block + + Maria will have a LSN at start of each page (including the bitmap page) + Maria will for each row have the additional information: + + TRANSID Transaction ID that last updated row (6 bytes) + VER_PTR Version pointer that points on the UNDO entry that + contains last version of the row versions (7 bytes) + + The different page types that are in a data file are: + + Bitmap pages Map of free pages in the next extent (8129 page size + gives us 256M of mapped pages / bitmap) + Head page Start of rows are stored on this page. + A rowid always points to a head page + Blob page This page is totally filled with data from one blob or by + a set of long VARCHAR/CHAR fields + Tail page This contains the last part from different rows, blobs + or varchar fields. + + The data file starts with a bitmap page, followed by as many data + pages as the bitmap can cover. After this there is a new bitmap page + and more data pages etc. + + For information about the bitmap page, see ma_bitmap.c + + Structure of data and tail page: + + The page has a row directory at end of page to allow us to do deletes + without having to reorganize the page. It also allows us to store some + extra bytes after each row to allow them to grow without having to move + around other rows + + Page header: + + LSN 7 bytes Log position for last page change + PAGE_TYPE 1 byte 1 for head / 2 for tail / 3 for blob + NO 1 byte Number of row/tail entries on page + empty space 2 bytes Empty space on page + + The upmost bit in PAGE_TYPE is set to 1 if the data on the page + can be compacted to get more space. (PAGE_CAN_BE_COMPACTED) + + Row data + + Row directory of NO entires, that consist of the following for each row + (in reverse order; ie, first record is stored last): + + Position 2 bytes Position of row on page + Length 2 bytes Length of entry + + For Position and Length, the 1 upmost bit of the position and the 1 + upmost bit of the length could be used for some states of the row (in + other words, we should try to keep these reserved) + + eof flag 1 byte Reserved for full page read testing + + ---------------- + + Structure of blob pages: + + LSN 7 bytes Log position for last page change + PAGE_TYPE 1 byte 3 + + data + + ----------------- + + Row data structure: + + Flag 1 byte Marker of which header field exists + TRANSID 6 bytes TRANSID of changing transaction + (optional, added on insert and first + update/delete) + VER_PTR 7 bytes Pointer to older version in log + (undo record) + (optional, added after first + update/delete) + DELETE_TRANSID 6 bytes (optional). TRANSID of original row. + Added on delete. + Nulls_extended 1 byte To allow us to add new DEFAULT NULL + fields (optional, added after first + change of row after alter table) + Number of ROW_EXTENT's 1-3 byte Length encoded, optional + This is the number of extents the + row is split into + First row_extent 7 byte Pointer to first row extent (optional) + + Total length of length array 1-3 byte Only used if we have + char/varchar/blob fields. + Row checksum 1 byte Only if table created with checksums + Null_bits .. One bit for each NULL field + Empty_bits .. One bit for each NOT NULL field. This bit is + 0 if the value is 0 or empty string. + + field_offsets 2 byte/offset + For each 32 field, there is one offset that + points to where the field information starts + in the block. This is to provide fast access + to later field in the row when we only need + to return a small set of fields. + + Things marked above as 'optional' will only be present if the corresponding + bit is set in 'Flag' field. + + Data in the following order: + (Field order is precalculated when table is created) + + Critical fixed length, not null, fields. (Note, these can't be dropped) + Fixed length, null fields + + Length array, 1-4 byte per field for all CHAR/VARCHAR/BLOB fields. + Number of bytes used in length array per entry is depending on max length + for field. + + ROW_EXTENT's + CHAR data (space stripped) + VARCHAR data + BLOB data + + Fields marked in null_bits or empty_bits are not stored in data part or + length array. + + If row doesn't fit into the given block, then the first EXTENT will be + stored last on the row. This is done so that we don't break any field + data in the middle. + + We first try to store the full row into one block. If that's not possible + we move out each big blob into their own extents. If this is not enough we + move out a concatenation of all varchars to their own extent. + + Each blob and the concatenated char/varchar fields are stored the following + way: + - Store the parts in as many full-contiguous pages as possible. + - The last part, that doesn't fill a full page, is stored in tail page. + + When doing an insert of a new row, we don't have to have + VER_PTR in the row. This will make rows that are not changed stored + efficiently. On update and delete we would add TRANSID (if it was an old + committed row) and VER_PTR to + the row. On row page compaction we can easily detect rows where + TRANSID was committed before the the longest running transaction + started and we can then delete TRANSID and VER_PTR from the row to + gain more space. + + If a row is deleted in Maria, we change TRANSID to current transid and + change VER_PTR to point to the undo record for the delete. The undo + record must contain the original TRANSID, so that another transaction + can use this to check if they should use the found row or go to the + previous row pointed to by the VER_PTR in the undo row. + + Description of the different parts: + + Flag is coded as: + + Description bit + TRANS_ID_exists 0 + VER_PTR_exists 1 + Row is deleted 2 (Means that DELETE_TRANSID exists) + Nulls_extended_exists 3 + Row is split 7 This means that 'Number_of_row_extents' exists + + + This would be a way to get more space on a page when doing page + compaction as we don't need to store TRANSID that have committed + before the smallest running transaction we have in memory. + + Nulls_extended is the number of new DEFAULT NULL fields in the row + compared to the number of DEFAULT NULL fields when the first version + of the table was created. If Nulls_extended doesn't exist in the row, + we know it's 0 as this must be one of the original rows from when the + table was created first time. This coding allows us to add 255*8 = + 2048 new fields without requiring a full alter table. + + Empty_bits is used to allow us to store 0, 0.0, empty string, empty + varstring and empty blob efficiently. (This is very good for data + warehousing where NULL's are often regarded as evil). Having this + bitmap also allows us to drop information of a field during a future + delete if field was deleted with ALTER TABLE DROP COLUMN. To be able + to handle DROP COLUMN, we must store in the index header the fields + that has been dropped. When unpacking a row we will ignore dropped + fields. When storing a row, we will mark a dropped field either with a + null in the null bit map or in the empty_bits and not store any data + for it. + + One ROW_EXTENT is coded as: + + START_PAGE 5 bytes + PAGE_COUNT 2 bytes. High bit is used to indicate tail page/ + end of blob + With 8K pages, we can cover 256M in one extent. This coding gives us a + maximum file size of 2^40*8192 = 8192 tera + + As an example of ROW_EXTENT handling, assume a row with one integer + field (value 5), two big VARCHAR fields (size 250 and 8192*3), and 2 + big BLOB fields that we have updated. + + The record format for storing this into an empty file would be: + + Page 1: + + 00 00 00 00 00 00 00 LSN + 01 Only one row in page + xx xx Empty space on page + + 10 Flag: row split, VER_PTR exists + 01 00 00 00 00 00 TRANSID 1 + 00 00 00 00 00 01 00 VER_PTR to first block in LOG file 1 + 5 Number of row extents + 02 00 00 00 00 03 00 VARCHAR's are stored in full pages 2,3,4 + 0 No null fields + 0 No empty fields + 05 00 00 00 00 00 80 Tail page for VARCHAR, rowid 0 + 06 00 00 00 00 80 00 First blob, stored at page 6-133 + 05 00 00 00 00 01 80 Tail of first blob (896 bytes) at page 5 + 86 00 00 00 00 80 00 Second blob, stored at page 134-262 + 05 00 00 00 00 02 80 Tail of second blob (896 bytes) at page 5 + 05 00 5 integer + FA Length of first varchar field (size 250) + 00 60 Length of second varchar field (size 8192*3) + 00 60 10 First medium BLOB, 1M + 01 00 10 00 Second BLOB, 1M + xx xx xx xx xx xx Varchars are stored here until end of page + + ..... until end of page + + 09 00 F4 1F 00 (Start position 9, length 8180, end byte) +*/ + +#define SANITY_CHECKS + +#include "maria_def.h" +#include "ma_blockrec.h" + +typedef struct st_maria_extent_cursor +{ + byte *extent; + byte *data_start; /* For error checking */ + MARIA_RECORD_POS *tail_positions; + my_off_t page; + uint extent_count, page_count; + uint tail; /* <> 0 if current extent is a tail page */ + my_bool first_extent; +} MARIA_EXTENT_CURSOR; + + +static my_bool delete_tails(MARIA_HA *info, MARIA_RECORD_POS *tails); +static my_bool delete_head_or_tail(MARIA_HA *info, + ulonglong page, uint record_number, + my_bool head); +static void _ma_print_directory(byte *buff, uint block_size); + +/**************************************************************************** + Initialization +****************************************************************************/ + +/* + Initialize data needed for block structures +*/ + + +/* Size of the different header elements for a row */ + +static uchar header_sizes[]= +{ + TRANSID_SIZE, + VERPTR_SIZE, + TRANSID_SIZE, /* Delete transid */ + 1 /* Null extends */ +}; + +/* + Calculate array of all used headers + + Used to speed up: + + size= 1; + if (flag & 1) + size+= TRANSID_SIZE; + if (flag & 2) + size+= VERPTR_SIZE; + if (flag & 4) + size+= TRANSID_SIZE + if (flag & 8) + size+= 1; + + NOTES + This is called only once at startup of Maria +*/ + +static uchar total_header_size[1 << array_elements(header_sizes)]; +#define PRECALC_HEADER_BITMASK (array_elements(total_header_size) -1) + +void _ma_init_block_record_data(void) +{ + uint i; + bzero(total_header_size, sizeof(total_header_size)); + total_header_size[0]= FLAG_SIZE; /* Flag byte */ + for (i= 1; i < array_elements(total_header_size); i++) + { + uint size= FLAG_SIZE, j, bit; + for (j= 0; (bit= (1 << j)) <= i; j++) + { + if (i & bit) + size+= header_sizes[j]; + } + total_header_size[i]= size; + } +} + + +my_bool _ma_once_init_block_row(MARIA_SHARE *share, File data_file) +{ + + share->base.max_data_file_length= + (((ulonglong) 1 << ((share->base.rec_reflength-1)*8))-1) * + share->block_size; +#if SIZEOF_OFF_T == 4 + set_if_smaller(max_data_file_length, INT_MAX32); +#endif + return _ma_bitmap_init(share, data_file); +} + + +my_bool _ma_once_end_block_row(MARIA_SHARE *share) +{ + int res= _ma_bitmap_end(share); + if (flush_key_blocks(share->key_cache, share->bitmap.file, + share->temporary ? FLUSH_IGNORE_CHANGED : + FLUSH_RELEASE)) + res= 1; + if (share->bitmap.file >= 0 && my_close(share->bitmap.file, MYF(MY_WME))) + res= 1; + return res; +} + + +/* Init info->cur_row structure */ + +my_bool _ma_init_block_row(MARIA_HA *info) +{ + MARIA_ROW *row= &info->cur_row, *new_row= &info->new_row; + DBUG_ENTER("_ma_init_block_row"); + + if (!my_multi_malloc(MY_WME, + &row->empty_bits_buffer, info->s->base.pack_bytes, + &row->field_lengths, info->s->base.max_field_lengths, + &row->blob_lengths, sizeof(ulong) * info->s->base.blobs, + &row->null_field_lengths, (sizeof(uint) * + (info->s->base.fields - + info->s->base.blobs)), + &row->tail_positions, (sizeof(MARIA_RECORD_POS) * + (info->s->base.blobs + 2)), + &new_row->empty_bits_buffer, info->s->base.pack_bytes, + &new_row->field_lengths, + info->s->base.max_field_lengths, + &new_row->blob_lengths, + sizeof(ulong) * info->s->base.blobs, + &new_row->null_field_lengths, (sizeof(uint) * + (info->s->base.fields - + info->s->base.blobs)), + NullS, 0)) + DBUG_RETURN(1); + if (my_init_dynamic_array(&info->bitmap_blocks, + sizeof(MARIA_BITMAP_BLOCK), + ELEMENTS_RESERVED_FOR_MAIN_PART, 16)) + my_free((char*) &info->bitmap_blocks, MYF(0)); + row->base_length= new_row->base_length= info->s->base_length; + DBUG_RETURN(0); +} + +void _ma_end_block_row(MARIA_HA *info) +{ + DBUG_ENTER("_ma_end_block_row"); + my_free((gptr) info->cur_row.empty_bits_buffer, MYF(MY_ALLOW_ZERO_PTR)); + delete_dynamic(&info->bitmap_blocks); + my_free((gptr) info->cur_row.extents, MYF(MY_ALLOW_ZERO_PTR)); + DBUG_VOID_RETURN; +} + + +/**************************************************************************** + Helper functions +****************************************************************************/ + +static inline uint empty_pos_after_row(byte *dir) +{ + byte *prev; + /* + Find previous used entry. (There is always a previous entry as + the directory never starts with a deleted entry) + */ + for (prev= dir - DIR_ENTRY_SIZE ; + prev[0] == 0 && prev[1] == 0 ; + prev-= DIR_ENTRY_SIZE) + {} + return (uint) uint2korr(prev); +} + + +static my_bool check_if_zero(byte *pos, uint length) +{ + byte *end; + for (end= pos+ length; pos != end ; pos++) + if (pos[0] != 0) + return 1; + return 0; +} + + +/* + Find free postion in directory + + SYNOPSIS + find_free_position() + buff Page + block_size Size of page + res_rownr Store index to free position here + res_length Store length of found segment here + empty_space Store length of empty space on disk here. This is + all empty space, including the found block. + + NOTES + If there is a free directory entry (entry with postion == 0), + then use it and change it to be the size of the empty block + after the previous entry. This guarantees that all row entries + are stored on disk in inverse directory order, which makes life easier for + 'compact_page()' and to know if there is free space after any block. + + If there is no free entry (entry with postion == 0), then we create + a new one. + + We will update the offset and the length of the found dir entry to + match the position and empty space found. + + buff[EMPTY_SPACE_OFFSET] is NOT updated but left up to the caller + + RETURN + 0 Error (directory full) + # Pointer to directory entry on page +*/ + +static byte *find_free_position(byte *buff, uint block_size, uint *res_rownr, + uint *res_length, uint *empty_space) +{ + uint max_entry= (uint) ((uchar*) buff)[DIR_ENTRY_OFFSET]; + uint entry, length, first_pos; + byte *dir, *end; + + dir= (buff + block_size - DIR_ENTRY_SIZE * max_entry - PAGE_SUFFIX_SIZE); + end= buff + block_size - PAGE_SUFFIX_SIZE - DIR_ENTRY_SIZE; + + first_pos= PAGE_HEADER_SIZE; + *empty_space= uint2korr(buff + EMPTY_SPACE_OFFSET); + + /* Search after first empty position */ + for (entry= 0 ; dir <= end ; end-= DIR_ENTRY_SIZE, entry--) + { + if (end[0] == 0 && end[1] == 0) /* Found not used entry */ + { + length= empty_pos_after_row(end) - first_pos; + int2store(end, first_pos); /* Update dir entry */ + int2store(end + 2, length); + *res_rownr= entry; + *res_length= length; + return end; + } + first_pos= uint2korr(end) + uint2korr(end + 2); + } + /* No empty places in dir; create a new one */ + if (max_entry == MAX_ROWS_PER_PAGE) + return 0; + buff[DIR_ENTRY_OFFSET]= (byte) (uchar) max_entry+1; + dir-= DIR_ENTRY_SIZE; + length= (uint) (dir - buff - first_pos); + DBUG_ASSERT(length <= *empty_space - DIR_ENTRY_SIZE); + int2store(dir, first_pos); + int2store(dir+2, length); /* Current max length */ + *res_rownr= max_entry; + *res_length= length; + + /* Reduce directory entry size from free space size */ + (*empty_space)-= DIR_ENTRY_SIZE; + return dir; + +} + +/**************************************************************************** + Updating records +****************************************************************************/ + +/* + Calculate length of all the different field parts +*/ + +static void calc_record_size(MARIA_HA *info, const byte *record, + MARIA_ROW *row) +{ + MARIA_SHARE *share= info->s; + byte *field_length_data; + MARIA_COLUMNDEF *rec, *end_field; + uint blob_count= 0, *null_field_lengths= row->null_field_lengths; + + row->normal_length= row->char_length= row->varchar_length= + row->blob_length= row->extents_count= 0; + + /* Create empty bitmap and calculate length of each varlength/char field */ + bzero(row->empty_bits_buffer, share->base.pack_bytes); + row->empty_bits= row->empty_bits_buffer; + field_length_data= row->field_lengths; + for (rec= share->rec + share->base.fixed_not_null_fields, + end_field= share->rec + share->base.fields; + rec < end_field; rec++, null_field_lengths++) + { + if ((record[rec->null_pos] & rec->null_bit)) + { + if (rec->type != FIELD_BLOB) + *null_field_lengths= 0; + continue; + } + switch ((enum en_fieldtype) rec->type) { + case FIELD_CHECK: + case FIELD_NORMAL: /* Fixed length field */ + case FIELD_ZERO: + DBUG_ASSERT(rec->empty_bit == 0); + /* fall through */ + case FIELD_SKIP_PRESPACE: /* Not packed */ + row->normal_length+= rec->length; + *null_field_lengths= rec->length; + break; + case FIELD_SKIP_ZERO: /* Fixed length field */ + if (memcmp(record+ rec->null_pos, maria_zero_string, + rec->length) == 0) + { + row->empty_bits[rec->empty_pos] |= rec->empty_bit; + *null_field_lengths= 0; + } + else + { + row->normal_length+= rec->length; + *null_field_lengths= rec->length; + } + break; + case FIELD_SKIP_ENDSPACE: /* CHAR */ + { + const char *pos, *end; + for (pos= record + rec->offset, end= pos + rec->length; + end > pos && end[-1] == ' '; end--) + ; + if (pos == end) /* If empty string */ + { + row->empty_bits[rec->empty_pos]|= rec->empty_bit; + *null_field_lengths= 0; + } + else + { + uint length= (end - pos); + if (rec->length <= 255) + *field_length_data++= (byte) (uchar) length; + else + { + int2store(field_length_data, length); + field_length_data+= 2; + } + row->char_length+= length; + *null_field_lengths= length; + } + break; + } + case FIELD_VARCHAR: + { + uint length; + const byte *field_pos= record + rec->offset; + /* 256 is correct as this includes the length byte */ + if (rec->length <= 256) + { + if (!(length= (uint) (uchar) *field_pos)) + { + row->empty_bits[rec->empty_pos]|= rec->empty_bit; + *null_field_lengths= 0; + break; + } + *field_length_data++= *field_pos; + } + else + { + if (!(length= uint2korr(field_pos))) + { + row->empty_bits[rec->empty_pos]|= rec->empty_bit; + break; + } + field_length_data[0]= field_pos[0]; + field_length_data[1]= field_pos[1]; + field_length_data+= 2; + } + row->varchar_length+= length; + *null_field_lengths= length; + break; + } + case FIELD_BLOB: + { + const byte *field_pos= record + rec->offset; + uint size_length= rec->length - maria_portable_sizeof_char_ptr; + ulong blob_length= _ma_calc_blob_length(size_length, field_pos); + if (!blob_length) + { + row->empty_bits[rec->empty_pos]|= rec->empty_bit; + row->blob_lengths[blob_count++]= 0; + break; + } + row->blob_length+= blob_length; + row->blob_lengths[blob_count++]= blob_length; + memcpy(field_length_data, field_pos, size_length); + field_length_data+= size_length; + break; + } + default: + DBUG_ASSERT(0); + } + } + row->field_lengths_length= (uint) (field_length_data - row->field_lengths); + row->head_length= (row->base_length + + share->base.fixed_not_null_fields_length + + row->field_lengths_length + + size_to_store_key_length(row->field_lengths_length) + + row->normal_length + + row->char_length + row->varchar_length); + row->total_length= (row->head_length + row->blob_length); + if (row->total_length < share->base.min_row_length) + row->total_length= share->base.min_row_length; +} + + +/* + Compact page by removing all space between rows + + IMPLEMENTATION + Move up all rows to start of page. + Move blocks that are directly after each other with one memmove. + + TODO LATER + Remove TRANSID from rows that are visible to all transactions + + SYNOPSIS + compact_page() + buff Page to compact + block_size Size of page + recnr Put empty data after this row +*/ + + +void compact_page(byte *buff, uint block_size, uint rownr) +{ + uint max_entry= (uint) ((uchar *) buff)[DIR_ENTRY_OFFSET]; + uint page_pos, next_free_pos, start_of_found_block, diff, end_of_found_block; + byte *dir, *end; + DBUG_ENTER("compact_page"); + DBUG_PRINT("enter", ("rownr: %u", rownr)); + DBUG_ASSERT(max_entry > 0 && + max_entry < (block_size - PAGE_HEADER_SIZE - + PAGE_SUFFIX_SIZE) / DIR_ENTRY_SIZE); + + /* Move all entries before and including rownr up to start of page */ + dir= buff + block_size - DIR_ENTRY_SIZE * (rownr+1) - PAGE_SUFFIX_SIZE; + end= buff + block_size - DIR_ENTRY_SIZE - PAGE_SUFFIX_SIZE; + page_pos= next_free_pos= start_of_found_block= PAGE_HEADER_SIZE; + diff= 0; + for (; dir <= end ; end-= DIR_ENTRY_SIZE) + { + uint offset= uint2korr(end); + + if (offset) + { + uint row_length= uint2korr(end + 2); + DBUG_ASSERT(offset >= page_pos); + DBUG_ASSERT(buff + offset + row_length <= dir); + + if (offset != next_free_pos) + { + uint length= (next_free_pos - start_of_found_block); + /* + There was empty space before this and prev block + Check if we have to move prevous block up to page start + */ + if (page_pos != start_of_found_block) + { + /* move up previous block */ + memmove(buff + page_pos, buff + start_of_found_block, length); + } + page_pos+= length; + /* next continous block starts here */ + start_of_found_block= offset; + diff= offset - page_pos; + } + int2store(end, offset - diff); /* correct current pos */ + next_free_pos= offset + row_length; + } + } + if (page_pos != start_of_found_block) + { + uint length= (next_free_pos - start_of_found_block); + memmove(buff + page_pos, buff + start_of_found_block, length); + } + start_of_found_block= uint2korr(dir); + + if (rownr != max_entry - 1) + { + /* Move all entries after rownr to end of page */ + uint rownr_length; + next_free_pos= end_of_found_block= page_pos= + block_size - DIR_ENTRY_SIZE * max_entry - PAGE_SUFFIX_SIZE; + diff= 0; + /* End points to entry before 'rownr' */ + for (dir= buff + end_of_found_block ; dir <= end ; dir+= DIR_ENTRY_SIZE) + { + uint offset= uint2korr(dir); + uint row_length= uint2korr(dir + 2); + uint row_end= offset + row_length; + if (!offset) + continue; + DBUG_ASSERT(offset >= start_of_found_block && row_end <= next_free_pos); + + if (row_end != next_free_pos) + { + uint length= (end_of_found_block - next_free_pos); + if (page_pos != end_of_found_block) + { + /* move next block down */ + memmove(buff + page_pos - length, buff + next_free_pos, length); + } + page_pos-= length; + /* next continous block starts here */ + end_of_found_block= row_end; + diff= page_pos - row_end; + } + int2store(dir, offset + diff); /* correct current pos */ + next_free_pos= offset; + } + if (page_pos != end_of_found_block) + { + uint length= (end_of_found_block - next_free_pos); + memmove(buff + page_pos - length, buff + next_free_pos, length); + next_free_pos= page_pos- length; + } + /* Extend rownr block to cover hole */ + rownr_length= next_free_pos - start_of_found_block; + int2store(dir+2, rownr_length); + } + else + { + /* Extend last block cover whole page */ + uint length= (uint) (dir - buff) - start_of_found_block; + int2store(dir+2, length); + + buff[PAGE_TYPE_OFFSET]&= ~(byte) PAGE_CAN_BE_COMPACTED; + } + DBUG_EXECUTE("directory", _ma_print_directory(buff, block_size);); + DBUG_VOID_RETURN; +} + + + +/* + Read or initialize new head or tail page + + SYNOPSIS + get_head_or_tail_page() + info Maria handler + block Block to read + buff Suggest this buffer to key cache + length Minimum space needed + page_type HEAD_PAGE || TAIL_PAGE + res Store result position here + + NOTES + We don't decremented buff[EMPTY_SPACE_OFFSET] with the allocated data + as we don't know how much data the caller will actually use. + + RETURN + 0 ok All slots in 'res' are updated + 1 error my_errno is set +*/ + +struct st_row_pos_info +{ + byte *buff; /* page buffer */ + byte *data; /* Place for data */ + byte *dir; /* Directory */ + uint length; /* Length for data */ + uint offset; /* Offset to directory */ + uint empty_space; /* Space left on page */ +}; + +static my_bool get_head_or_tail_page(MARIA_HA *info, + MARIA_BITMAP_BLOCK *block, + byte *buff, uint length, uint page_type, + struct st_row_pos_info *res) +{ + uint block_size; + DBUG_ENTER("get_head_or_tail_page"); + + block_size= info->s->block_size; + if (block->org_bitmap_value == 0) /* Empty block */ + { + /* New page */ + bzero(buff, PAGE_HEADER_SIZE); + + /* + We zero the rest of the block to avoid getting old memory information + to disk and to allow the file to be compressed better if archived. + The rest of the code does not assume the block is zeroed above + PAGE_OVERHEAD_SIZE + */ + bzero(buff+ PAGE_HEADER_SIZE + length, + block_size - length - PAGE_HEADER_SIZE - DIR_ENTRY_SIZE - + PAGE_SUFFIX_SIZE); + buff[PAGE_TYPE_OFFSET]= (byte) page_type; + buff[DIR_ENTRY_OFFSET]= 1; + res->buff= buff; + res->empty_space= res->length= (block_size - PAGE_OVERHEAD_SIZE); + res->data= (buff + PAGE_HEADER_SIZE); + res->dir= res->data + res->length; + /* Store poistion to the first row */ + int2store(res->dir, PAGE_HEADER_SIZE); + res->offset= 0; + DBUG_ASSERT(length <= res->length); + } + else + { + byte *dir; + /* Read old page */ + if (!(res->buff= key_cache_read(info->s->key_cache, + info->dfile, + (my_off_t) block->page * block_size, 0, + buff, block_size, block_size, 0))) + DBUG_RETURN(1); + DBUG_ASSERT((res->buff[PAGE_TYPE_OFFSET] & PAGE_TYPE_MASK) == page_type); + if (!(dir= find_free_position(buff, block_size, &res->offset, + &res->length, &res->empty_space))) + { + if (res->length < length) + { + if (res->empty_space + res->length < length) + { + compact_page(res->buff, block_size, res->offset); + /* All empty space are now after current position */ + res->length= res->empty_space= uint2korr(dir+2); + } + if (res->length < length) + goto crashed; /* Wrong bitmap information */ + } + } + res->dir= dir; + res->data= res->buff + uint2korr(dir); + } + DBUG_RETURN(0); + +crashed: + my_errno= HA_ERR_WRONG_IN_RECORD; /* File crashed */ + DBUG_RETURN(1); +} + + +/* + Write tail of non-blob-data or blob + + SYNOPSIS + write_tail() + info Maria handler + block Block to tail page + row_part Data to write to page + length Length of data + + NOTES + block->page_count is updated to the directory offset for the tail + so that we can store the position in the row extent information + + RETURN + 0 ok + block->page_count is set to point (dir entry + TAIL_BIT) + + 1 error; In this case my_errno is set to the error +*/ + +static my_bool write_tail(MARIA_HA *info, + MARIA_BITMAP_BLOCK *block, + byte *row_part, uint length) +{ + MARIA_SHARE *share= share= info->s; + uint block_size= share->block_size, empty_space; + struct st_row_pos_info row_pos; + my_off_t position; + DBUG_ENTER("write_tail"); + DBUG_PRINT("enter", ("page: %lu length: %u", + (ulong) block->page, length)); + + info->keybuff_used= 1; + if (get_head_or_tail_page(info, block, info->keyread_buff, length, + TAIL_PAGE, &row_pos)) + DBUG_RETURN(1); + + memcpy(row_pos.data, row_part, length); + int2store(row_pos.dir + 2, length); + empty_space= row_pos.empty_space - length; + int2store(row_pos.buff + EMPTY_SPACE_OFFSET, empty_space); + block->page_count= row_pos.offset + TAIL_BIT; + /* + If there is less directory entries free than number of possible tails + we can write for a row, we mark the page full to ensure that we don't + during _ma_bitmap_find_place() allocate more entires on the tail page + than it can hold + */ + block->empty_space= ((uint) ((uchar*) row_pos.buff)[DIR_ENTRY_OFFSET] <= + MAX_ROWS_PER_PAGE - 1 - info->s->base.blobs ? + empty_space : 0); + block->used= BLOCKUSED_USED | BLOCKUSED_TAIL; + + /* Increase data file size, if extended */ + position= (my_off_t) block->page * block_size; + if (info->state->data_file_length <= position) + info->state->data_file_length= position + block_size; + DBUG_RETURN(key_cache_write(share->key_cache, + info->dfile, position, 0, + row_pos.buff, block_size, block_size, 1)); +} + + +/* + Write full pages + + SYNOPSIS + write_full_pages() + info Maria handler + block Where to write data + data Data to write + length Length of data + +*/ + +static my_bool write_full_pages(MARIA_HA *info, + MARIA_BITMAP_BLOCK *block, + byte *data, ulong length) +{ + my_off_t page; + MARIA_SHARE *share= share= info->s; + uint block_size= share->block_size; + uint data_size= FULL_PAGE_SIZE(block_size); + byte *buff= info->keyread_buff; + uint page_count; + my_off_t position; + DBUG_ENTER("write_full_pages"); + DBUG_PRINT("enter", ("length: %lu page: %lu page_count: %lu", + length, (ulong) block->page, block->page_count)); + + info->keybuff_used= 1; + page= block->page; + page_count= block->page_count; + + position= (my_off_t) (page + page_count) * block_size; + if (info->state->data_file_length < position) + info->state->data_file_length= position; + + /* Increase data file size, if extended */ + + for (; length; data+= data_size) + { + uint copy_length; + if (!page_count--) + { + block++; + page= block->page; + page_count= block->page_count - 1; + DBUG_PRINT("info", ("page: %lu page_count: %lu", + (ulong) block->page, block->page_count)); + + position= (page + page_count + 1) * block_size; + if (info->state->data_file_length < position) + info->state->data_file_length= position; + } + bzero(buff, LSN_SIZE); + buff[PAGE_TYPE_OFFSET]= (byte) BLOB_PAGE; + copy_length= min(data_size, length); + memcpy(buff + LSN_SIZE + PAGE_TYPE_SIZE, data, copy_length); + length-= copy_length; + + if (key_cache_write(share->key_cache, + info->dfile, (my_off_t) page * block_size, 0, + buff, block_size, block_size, 1)) + DBUG_RETURN(1); + page++; + block->used= BLOCKUSED_USED; + } + DBUG_RETURN(0); +} + + + + +/* + Store packed extent data + + SYNOPSIS + store_extent_info() + to Store first packed data here + row_extents_second_part Store rest here + first_block First block to store + count Number of blocks + + NOTES + We don't have to store the position for the head block +*/ + +static void store_extent_info(byte *to, + byte *row_extents_second_part, + MARIA_BITMAP_BLOCK *first_block, + uint count) +{ + MARIA_BITMAP_BLOCK *block, *end_block; + uint copy_length; + my_bool first_found= 0; + + for (block= first_block, end_block= first_block+count ; + block < end_block; block++) + { + /* The following is only false for marker blocks */ + if (likely(block->used)) + { + int5store(to, block->page); + int2store(to + 5, block->page_count); + to+= ROW_EXTENT_SIZE; + if (!first_found) + { + first_found= 1; + to= row_extents_second_part; + } + } + } + copy_length= (count -1) * ROW_EXTENT_SIZE; + /* + In some unlikely cases we have allocated to many blocks. Clear this + data. + */ + bzero(to, (my_size_t) (row_extents_second_part + copy_length - to)); +} + +/* + Write a record to a (set of) pages +*/ + +static my_bool write_block_record(MARIA_HA *info, const byte *record, + MARIA_ROW *row, + MARIA_BITMAP_BLOCKS *bitmap_blocks, + struct st_row_pos_info *row_pos) +{ + byte *data, *end_of_data, *tmp_data_used, *tmp_data; + byte *row_extents_first_part, *row_extents_second_part; + byte *field_length_data; + byte *page_buff; + MARIA_BITMAP_BLOCK *block, *head_block; + MARIA_SHARE *share; + MARIA_COLUMNDEF *rec, *end_field; + uint block_size, flag; + ulong *blob_lengths; + my_off_t position; + my_bool row_extents_in_use; + DBUG_ENTER("write_block_record"); + + LINT_INIT(row_extents_first_part); + LINT_INIT(row_extents_second_part); + + share= info->s; + head_block= bitmap_blocks->block; + block_size= share->block_size; + + info->cur_row.lastpos= ma_recordpos(head_block->page, row_pos->offset); + page_buff= row_pos->buff; + data= row_pos->data; + end_of_data= data + row_pos->length; + + /* Write header */ + flag= share->base.default_row_flag; + row_extents_in_use= 0; + if (unlikely(row->total_length > row_pos->length)) + { + /* Need extent */ + if (bitmap_blocks->count <= 1) + goto crashed; /* Wrong in bitmap */ + flag|= ROW_FLAG_EXTENTS; + row_extents_in_use= 1; + } + /* For now we have only a minimum header */ + *data++= (uchar) flag; + if (unlikely(flag & ROW_FLAG_NULLS_EXTENDED)) + *data++= (uchar) (share->base.null_bytes - + share->base.original_null_bytes); + if (row_extents_in_use) + { + /* Store first extent in header */ + store_key_length_inc(data, bitmap_blocks->count - 1); + row_extents_first_part= data; + data+= ROW_EXTENT_SIZE; + } + if (share->base.pack_fields) + store_key_length_inc(data, row->field_lengths_length); + if (share->calc_checksum) + *(data++)= (byte) info->cur_row.checksum; + memcpy(data, record, share->base.null_bytes); + data+= share->base.null_bytes; + memcpy(data, row->empty_bits, share->base.pack_bytes); + data+= share->base.pack_bytes; + + /* + Allocate a buffer of rest of data (except blobs) + + To avoid double copying of data, we copy as many columns that fits into + the page. The rest goes into info->packed_row. + + Using an extra buffer, instead of doing continous writes to different + pages, uses less code and we don't need to have to do a complex call + for every data segment we want to store. + */ + if (_ma_alloc_buffer(&info->rec_buff, &info->rec_buff_size, + row->head_length)) + DBUG_RETURN(1); + + tmp_data_used= 0; /* Either 0 or last used byte in 'data' */ + tmp_data= data; + + if (row_extents_in_use) + { + uint copy_length= (bitmap_blocks->count - 2) * ROW_EXTENT_SIZE; + if (!tmp_data_used && tmp_data + copy_length > end_of_data) + { + tmp_data_used= tmp_data; + tmp_data= info->rec_buff; + } + row_extents_second_part= tmp_data; + /* + We will copy the extents here when we have figured out the tail + positions. + */ + tmp_data+= copy_length; + } + + /* Copy fields that has fixed lengths (primary key etc) */ + for (rec= share->rec, end_field= rec + share->base.fixed_not_null_fields; + rec < end_field; rec++) + { + if (!tmp_data_used && tmp_data + rec->length > end_of_data) + { + tmp_data_used= tmp_data; + tmp_data= info->rec_buff; + } + memcpy(tmp_data, record + rec->offset, rec->length); + tmp_data+= rec->length; + } + + /* Copy length of data for variable length fields */ + if (!tmp_data_used && tmp_data + row->field_lengths_length > end_of_data) + { + tmp_data_used= tmp_data; + tmp_data= info->rec_buff; + } + field_length_data= row->field_lengths; + memcpy(tmp_data, field_length_data, row->field_lengths_length); + tmp_data+= row->field_lengths_length; + + /* Copy variable length fields and fields with null/zero */ + for (end_field= share->rec + share->base.fields - share->base.blobs; + rec < end_field ; + rec++) + { + const byte *field_pos; + ulong length; + if ((record[rec->null_pos] & rec->null_bit) || + (row->empty_bits[rec->empty_pos] & rec->empty_bit)) + continue; + + field_pos= record + rec->offset; + switch ((enum en_fieldtype) rec->type) { + case FIELD_NORMAL: /* Fixed length field */ + case FIELD_SKIP_PRESPACE: + case FIELD_SKIP_ZERO: /* Fixed length field */ + length= rec->length; + break; + case FIELD_SKIP_ENDSPACE: /* CHAR */ + /* Char that is space filled */ + if (rec->length <= 255) + length= (uint) (uchar) *field_length_data++; + else + { + length= uint2korr(field_length_data); + field_length_data+= 2; + } + break; + case FIELD_VARCHAR: + if (rec->length <= 256) + { + length= (uint) (uchar) *field_length_data++; + field_pos++; /* Skip length byte */ + } + else + { + length= uint2korr(field_length_data); + field_length_data+= 2; + field_pos+= 2; + } + break; + default: /* Wrong data */ + DBUG_ASSERT(0); + break; + } + if (!tmp_data_used && tmp_data + length > end_of_data) + { + /* Data didn't fit in page; Change to use tmp buffer */ + tmp_data_used= tmp_data; + tmp_data= info->rec_buff; + } + memcpy((char*) tmp_data, (char*) field_pos, length); + tmp_data+= length; + } + + block= head_block + head_block->sub_blocks; /* Point to first blob data */ + + end_field= rec + share->base.blobs; + blob_lengths= row->blob_lengths; + if (!tmp_data_used) + { + /* Still room on page; Copy as many blobs we can into this page */ + data= tmp_data; + for (; rec < end_field && *blob_lengths < (ulong) (end_of_data - data); + rec++, blob_lengths++) + { + byte *tmp_pos; + uint length; + if (!*blob_lengths) /* Null or "" */ + continue; + length= rec->length - maria_portable_sizeof_char_ptr; + memcpy_fixed((byte*) &tmp_pos, record + rec->offset + length, + sizeof(char*)); + memcpy(data, tmp_pos, *blob_lengths); + data+= *blob_lengths; + /* Skip over tail page that was to be used to store blob */ + block++; + bitmap_blocks->tail_page_skipped= 1; + } + if (head_block->sub_blocks > 1) + { + /* We have allocated pages that where not used */ + bitmap_blocks->page_skipped= 1; + } + } + else + data= tmp_data_used; /* Get last used on page */ + + { + /* Update page directory */ + uint length= (uint) (data - row_pos->data); + DBUG_PRINT("info", ("head length: %u", length)); + if (length < info->s->base.min_row_length) + length= info->s->base.min_row_length; + + int2store(row_pos->dir + 2, length); + /* update empty space at start of block */ + row_pos->empty_space-= length; + int2store(page_buff + EMPTY_SPACE_OFFSET, row_pos->empty_space); + /* Mark in bitmaps how the current page was actually used */ + head_block->empty_space= row_pos->empty_space; + if (page_buff[DIR_ENTRY_OFFSET] == (char) MAX_ROWS_PER_PAGE) + head_block->empty_space= 0; /* Page is full */ + head_block->used= BLOCKUSED_USED; + } + + /* + Now we have to write tail pages, as we need to store the position + to them in the row extent header. + + We first write out all blob tails, to be able to store them in + the current page or 'tmp_data'. + + Then we write the tail of the non-blob fields (The position to the + tail page is stored either in row header, the extents in the head + page or in the first full page of the non-blob data. It's never in + the tail page of the non-blob data) + */ + + if (row_extents_in_use) + { + if (rec != end_field) /* If blob fields */ + { + MARIA_COLUMNDEF *save_rec= rec; + MARIA_BITMAP_BLOCK *save_block= block; + MARIA_BITMAP_BLOCK *end_block; + ulong *save_blob_lengths= blob_lengths; + + for (; rec < end_field; rec++, blob_lengths++) + { + byte *blob_pos; + if (!*blob_lengths) /* Null or "" */ + continue; + if (block[block->sub_blocks - 1].used & BLOCKUSED_TAIL) + { + uint length; + length= rec->length - maria_portable_sizeof_char_ptr; + memcpy_fixed((byte *) &blob_pos, record + rec->offset + length, + sizeof(char*)); + length= *blob_lengths % FULL_PAGE_SIZE(block_size); /* tail size */ + if (write_tail(info, block + block->sub_blocks-1, + blob_pos + *blob_lengths - length, + length)) + goto disk_err; + } + for (end_block= block + block->sub_blocks; block < end_block; block++) + { + /* + Set only a bit, to not cause bitmap code to belive a block is full + when there is still a lot of entries in it + */ + block->used|= BLOCKUSED_USED; + } + } + rec= save_rec; + block= save_block; + blob_lengths= save_blob_lengths; + } + + if (tmp_data_used) /* non blob data overflows */ + { + MARIA_BITMAP_BLOCK *cur_block, *end_block; + MARIA_BITMAP_BLOCK *head_tail_block= 0; + ulong length; + ulong data_length= (tmp_data - info->rec_buff); + +#ifdef SANITY_CHECK + if (cur_block->sub_blocks == 1) + goto crashed; /* no reserved full or tails */ +#endif + + /* + Find out where to write tail for non-blob fields. + + Problem here is that the bitmap code may have allocated more + space than we need. We have to handle the following cases: + + - Bitmap code allocated a tail page we don't need. + - The last full page allocated needs to be changed to a tail page + (Because we put more data than we thought on the head page) + + The reserved pages in bitmap_blocks for the main page has one of + the following allocations: + - Full pages, with following blocks: + # * full pages + empty page ; To be used if we change last full to tail page. This + has 'count' = 0. + tail page (optional, if last full page was part full) + - One tail page + */ + + cur_block= head_block + 1; + end_block= head_block + head_block->sub_blocks; + while (data_length >= (length= (cur_block->page_count * + FULL_PAGE_SIZE(block_size)))) + { +#ifdef SANITY_CHECK + if ((cur_block == end_block) || (cur_block->used & BLOCKUSED_BIT)) + goto crashed; +#endif + data_length-= length; + (cur_block++)->used= BLOCKUSED_USED; + } + if (data_length) + { +#ifdef SANITY_CHECK + if ((cur_block == end_block)) + goto crashed; +#endif + if (cur_block->used & BLOCKUSED_TAIL) + { + DBUG_ASSERT(data_length < MAX_TAIL_SIZE(block_size)); + /* tail written to full tail page */ + cur_block->used= BLOCKUSED_USED; + head_tail_block= cur_block; + } + else if (data_length > length - MAX_TAIL_SIZE(block_size)) + { + /* tail written to full page */ + cur_block->used= BLOCKUSED_USED; + if ((cur_block != end_block - 1) && + (end_block[-1].used & BLOCKUSED_TAIL)) + bitmap_blocks->tail_page_skipped= 1; + } + else + { + /* + cur_block is a full block, followed by an empty and optional + tail block. Change cur_block to a tail block or split it + into full blocks and tail blocks. + */ + DBUG_ASSERT(cur_block[1].page_count == 0); + if (cur_block->page_count == 1) + { + /* convert full block to tail block */ + cur_block->used= BLOCKUSED_USED | BLOCKUSED_TAIL; + head_tail_block= cur_block; + } + else + { + DBUG_ASSERT(data_length < length - FULL_PAGE_SIZE(block_size)); + DBUG_PRINT("info", ("Splitting blocks into full and tail")); + cur_block[1].page= (cur_block->page + cur_block->page_count - 1); + cur_block[1].page_count= 1; + cur_block[1].used= 1; + cur_block->page_count--; + cur_block->used= BLOCKUSED_USED | BLOCKUSED_TAIL; + head_tail_block= cur_block + 1; + } + if (end_block[-1].used & BLOCKUSED_TAIL) + bitmap_blocks->tail_page_skipped= 1; + } + } + else + { + /* Must be an empty or tail page */ + DBUG_ASSERT(cur_block->page_count == 0 || + cur_block->used & BLOCKUSED_TAIL); + if (end_block[-1].used & BLOCKUSED_TAIL) + bitmap_blocks->tail_page_skipped= 1; + } + + /* + Write all extents into page or tmp_buff + + Note that we still don't have a correct position for the tail + of the non-blob fields. + */ + store_extent_info(row_extents_first_part, + row_extents_second_part, + head_block+1, bitmap_blocks->count - 1); + if (head_tail_block) + { + ulong data_length= (tmp_data - info->rec_buff); + uint length; + byte *extent_data; + + length= (uint) (data_length % FULL_PAGE_SIZE(block_size)); + if (write_tail(info, head_tail_block, data + data_length - length, + length)) + goto disk_err; + tmp_data-= length; /* Remove the tail */ + + /* Store the tail position for the non-blob fields */ + if (head_tail_block == head_block + 1) + extent_data= row_extents_first_part; + else + extent_data= row_extents_second_part + + ((head_tail_block - head_block) - 2) * ROW_EXTENT_SIZE; + int5store(extent_data, head_tail_block->page); + int2store(extent_data + 5, head_tail_block->page_count); + } + } + else + store_extent_info(row_extents_first_part, + row_extents_second_part, + head_block+1, bitmap_blocks->count - 1); + } + /* Increase data file size, if extended */ + position= (my_off_t) head_block->page * block_size; + if (info->state->data_file_length <= position) + info->state->data_file_length= position + block_size; + if (key_cache_write(share->key_cache, + info->dfile, position, 0, + page_buff, share->block_size, share->block_size, 1)) + goto disk_err; + + if (tmp_data_used) + { + /* Write data stored in info->rec_buff to pages */ + DBUG_ASSERT(bitmap_blocks->count != 0); + if (write_full_pages(info, bitmap_blocks->block + 1, info->rec_buff, + (ulong) (tmp_data - info->rec_buff))) + goto disk_err; + } + + /* Write rest of blobs (data, but no tails as they are already written) */ + for (; rec < end_field; rec++, blob_lengths++) + { + byte *blob_pos; + uint length; + ulong blob_length; + if (!*blob_lengths) /* Null or "" */ + continue; + length= rec->length - maria_portable_sizeof_char_ptr; + memcpy_fixed((byte*) &blob_pos, record + rec->offset + length, + sizeof(char*)); + /* remove tail part */ + blob_length= *blob_lengths; + if (block[block->sub_blocks - 1].used & BLOCKUSED_TAIL) + blob_length-= (blob_length % FULL_PAGE_SIZE(block_size)); + + if (write_full_pages(info, block, blob_pos, blob_length)) + goto disk_err; + block+= block->sub_blocks; + } + /* Release not used space in used pages */ + if (_ma_bitmap_release_unused(info, bitmap_blocks)) + goto disk_err; + DBUG_RETURN(0); + +crashed: + my_errno= HA_ERR_WRONG_IN_RECORD; /* File crashed */ +disk_err: + /* Something was wrong with data on record */ + DBUG_RETURN(1); +} + + +/* + Write a record (to get the row id for it) + + SYNOPSIS + _ma_write_init_block_record() + info Maria handler + record Record to write + + NOTES + This is done BEFORE we write the keys to the row! + + RETURN + HA_OFFSET_ERROR Something went wrong + # Rowid for row +*/ + +MARIA_RECORD_POS _ma_write_init_block_record(MARIA_HA *info, + const byte *record) +{ + MARIA_BITMAP_BLOCKS *blocks= &info->cur_row.insert_blocks; + struct st_row_pos_info row_pos; + DBUG_ENTER("_ma_write_init_block_record"); + + calc_record_size(info, record, &info->cur_row); + if (_ma_bitmap_find_place(info, &info->cur_row, blocks)) + DBUG_RETURN(HA_OFFSET_ERROR); /* Error reding bitmap */ + if (get_head_or_tail_page(info, blocks->block, info->buff, + info->s->base.min_row_length, HEAD_PAGE, &row_pos)) + DBUG_RETURN(HA_OFFSET_ERROR); + info->cur_row.lastpos= ma_recordpos(blocks->block->page, row_pos.offset); + if (info->s->calc_checksum) + info->cur_row.checksum= (info->s->calc_checksum)(info,record); + if (write_block_record(info, record, &info->cur_row, blocks, &row_pos)) + DBUG_RETURN(HA_OFFSET_ERROR); /* Error reading bitmap */ + DBUG_PRINT("exit", ("Rowid: %lu", (ulong) info->cur_row.lastpos)); + DBUG_RETURN(info->cur_row.lastpos); +} + + +/* + Dummy function for (*info->s->write_record)() + + Nothing to do here, as we already wrote the record in + _ma_write_init_block_record() +*/ + +my_bool _ma_write_block_record(MARIA_HA *info __attribute__ ((unused)), + const byte *record __attribute__ ((unused)) +) +{ + return 0; /* Row already written */ +} + + +/* + Remove row written by _ma_write_block_record + + SYNOPSIS + _ma_abort_write_block_record() + info Maria handler + + INFORMATION + This is called in case we got a duplicate unique key while + writing keys. + + RETURN + 0 ok + 1 error +*/ + +my_bool _ma_write_abort_block_record(MARIA_HA *info) +{ + my_bool res= 0; + MARIA_BITMAP_BLOCKS *blocks= &info->cur_row.insert_blocks; + MARIA_BITMAP_BLOCK *block, *end; + DBUG_ENTER("_ma_abort_write_block_record"); + + if (delete_head_or_tail(info, + ma_recordpos_to_page(info->cur_row.lastpos), + ma_recordpos_to_offset(info->cur_row.lastpos), 1)) + res= 1; + for (block= blocks->block + 1, end= block + blocks->count - 1; block < end; + block++) + { + if (block->used & BLOCKUSED_TAIL) + { + /* + block->page_count is set to the tail directory entry number in + write_block_record() + */ + if (delete_head_or_tail(info, block->page, block->page_count & ~TAIL_BIT, + 0)) + res= 1; + } + else + { + pthread_mutex_lock(&info->s->bitmap.bitmap_lock); + if (_ma_reset_full_page_bits(info, &info->s->bitmap, block->page, + block->page_count)) + res= 1; + pthread_mutex_unlock(&info->s->bitmap.bitmap_lock); + } + } + DBUG_RETURN(res); +} + + +/* + Update a record + + NOTES + For the moment, we assume that info->curr_row.extents is always updated + when a row is read. In the future we may decide to read this on demand + for rows split into many extents. +*/ + +my_bool _ma_update_block_record(MARIA_HA *info, MARIA_RECORD_POS record_pos, + const byte *record) +{ + MARIA_BITMAP_BLOCKS *blocks= &info->cur_row.insert_blocks; + byte *buff; + MARIA_ROW *cur_row= &info->cur_row, *new_row= &info->new_row; + uint rownr, org_empty_size, head_length; + uint block_size= info->s->block_size; + byte *dir; + ulonglong page; + struct st_row_pos_info row_pos; + DBUG_ENTER("_ma_update_block_record"); + DBUG_PRINT("enter", ("rowid: %lu", (long) record_pos)); + + calc_record_size(info, record, new_row); + page= ma_recordpos_to_page(record_pos); + + if (!(buff= key_cache_read(info->s->key_cache, + info->dfile, (my_off_t) page * block_size, 0, + info->buff, block_size, block_size, 0))) + DBUG_RETURN(1); + org_empty_size= uint2korr(buff + EMPTY_SPACE_OFFSET); + rownr= ma_recordpos_to_offset(record_pos); + dir= (buff + block_size - DIR_ENTRY_SIZE * rownr - + DIR_ENTRY_SIZE - PAGE_SUFFIX_SIZE); + + if ((org_empty_size + cur_row->head_length) >= new_row->total_length) + { + uint empty, offset, length; + MARIA_BITMAP_BLOCK block; + + /* + We can fit the new row in the same page as the original head part + of the row + */ + block.org_bitmap_value= _ma_free_size_to_head_pattern(&info->s->bitmap, + org_empty_size); + offset= uint2korr(dir); + length= uint2korr(dir + 2); + empty= 0; + if (new_row->total_length > length) + { + /* See if there is empty space after */ + if (rownr != (uint) ((uchar *) buff)[DIR_ENTRY_OFFSET] - 1) + empty= empty_pos_after_row(dir) - (offset + length); + if (new_row->total_length > length + empty) + { + compact_page(buff, info->s->block_size, rownr); + org_empty_size= 0; + length= uint2korr(dir + 2); + } + } + row_pos.buff= buff; + row_pos.offset= rownr; + row_pos.empty_space= org_empty_size + length; + row_pos.dir= dir; + row_pos.data= buff + uint2korr(dir); + row_pos.length= length + empty; + blocks->block= █ + blocks->count= 1; + block.page= page; + block.sub_blocks= 1; + block.used= BLOCKUSED_USED | BLOCKUSED_USE_ORG_BITMAP; + block.empty_space= row_pos.empty_space; + /* Update cur_row, if someone calls update at once again */ + cur_row->head_length= new_row->total_length; + if (_ma_bitmap_free_full_pages(info, cur_row->extents, + cur_row->extents_count)) + DBUG_RETURN(1); + DBUG_RETURN(write_block_record(info, record, new_row, blocks, &row_pos)); + } + /* + Allocate all size in block for record + QQ: Need to improve this to do compact if we can fit one more blob into + the head page + */ + head_length= uint2korr(dir + 2); + if (buff[PAGE_TYPE_OFFSET] & PAGE_CAN_BE_COMPACTED && org_empty_size && + (head_length < new_row->head_length || + (new_row->total_length <= head_length && + org_empty_size + head_length >= new_row->total_length))) + { + compact_page(buff, info->s->block_size, rownr); + org_empty_size= 0; + head_length= uint2korr(dir + 2); + } + + /* Delete old row */ + if (delete_tails(info, cur_row->tail_positions)) + DBUG_RETURN(1); + if (_ma_bitmap_free_full_pages(info, cur_row->extents, + cur_row->extents_count)) + DBUG_RETURN(1); + if (_ma_bitmap_find_new_place(info, new_row, page, head_length, blocks)) + DBUG_RETURN(1); + + row_pos.buff= buff; + row_pos.offset= rownr; + row_pos.empty_space= org_empty_size + head_length; + row_pos.dir= dir; + row_pos.data= buff + uint2korr(dir); + row_pos.length= head_length; + DBUG_RETURN(write_block_record(info, record, new_row, blocks, &row_pos)); +} + + +/* + Delete a head a tail part + + SYNOPSIS + delete_head_or_tail() + info Maria handler + page Page (not file offset!) on which the row is + head 1 if this is a head page + + NOTES + Uses info->keyread_buff + + RETURN + 0 ok + 1 error +*/ + +static my_bool delete_head_or_tail(MARIA_HA *info, + ulonglong page, uint record_number, + my_bool head) +{ + MARIA_SHARE *share= info->s; + uint number_of_records, empty_space, length; + uint block_size= share->block_size; + byte *buff, *dir; + my_off_t position; + DBUG_ENTER("delete_head_or_tail"); + + info->keybuff_used= 1; + if (!(buff= key_cache_read(share->key_cache, + info->dfile, page * block_size, 0, + info->keyread_buff, + block_size, block_size, 0))) + DBUG_RETURN(1); + + number_of_records= (uint) ((uchar *) buff)[DIR_ENTRY_OFFSET]; +#ifdef SANITY_CHECKS + if (record_number >= number_of_records || + record_number > MAX_ROWS_PER_PAGE || + record_number > ((block_size - LSN_SIZE - PAGE_TYPE_SIZE - 1 - + PAGE_SUFFIX_SIZE) / (DIR_ENTRY_SIZE + MIN_TAIL_SIZE))) + { + DBUG_PRINT("error", ("record_number: %u number_of_records: %u", + record_number, number_of_records)); + DBUG_RETURN(1); + } +#endif + + dir= (buff + block_size - DIR_ENTRY_SIZE * record_number - + DIR_ENTRY_SIZE - PAGE_SUFFIX_SIZE); + dir[0]= dir[1]= 0; /* Delete entry */ + length= uint2korr(dir + 2); + empty_space= uint2korr(buff + EMPTY_SPACE_OFFSET); + + if (record_number == number_of_records - 1) + { + /* Delete this entry and all following empty directory entries */ + byte *end= buff + block_size - PAGE_SUFFIX_SIZE; + do + { + number_of_records--; + dir+= DIR_ENTRY_SIZE; + empty_space+= DIR_ENTRY_SIZE; + } while (dir < end && dir[0] == 0 && dir[1] == 0); + buff[DIR_ENTRY_OFFSET]= (byte) (uchar) number_of_records; + } + empty_space+= length; + if (number_of_records != 0) + { + int2store(buff + EMPTY_SPACE_OFFSET, empty_space); + buff[PAGE_TYPE_OFFSET]|= (byte) PAGE_CAN_BE_COMPACTED; + position= (my_off_t) page * block_size; + if (key_cache_write(share->key_cache, + info->dfile, position, 0, + buff, block_size, block_size, 1)) + DBUG_RETURN(1); + } + else + { + DBUG_ASSERT(empty_space >= info->s->bitmap.sizes[0]); + } + DBUG_PRINT("info", ("empty_space: %u", empty_space)); + DBUG_RETURN(_ma_bitmap_set(info, page, head, empty_space)); +} + + +/* + delete all tails + + SYNOPSIS + delete_tails() + info Handler + tails Pointer to vector of tail positions, ending with 0 + + NOTES + Uses info->keyread_buff + + RETURN + 0 ok + 1 error +*/ + +static my_bool delete_tails(MARIA_HA *info, MARIA_RECORD_POS *tails) +{ + my_bool res= 0; + DBUG_ENTER("delete_tails"); + for (; *tails; tails++) + { + if (delete_head_or_tail(info, + ma_recordpos_to_page(*tails), + ma_recordpos_to_offset(*tails), 0)) + res= 1; + } + DBUG_RETURN(res); +} + + +/* + Delete a record + + NOTES + For the moment, we assume that info->cur_row.extents is always updated + when a row is read. In the future we may decide to read this on demand + for rows with many splits. +*/ + +my_bool _ma_delete_block_record(MARIA_HA *info) +{ + DBUG_ENTER("_ma_delete_block_record"); + if (delete_head_or_tail(info, + ma_recordpos_to_page(info->cur_row.lastpos), + ma_recordpos_to_offset(info->cur_row.lastpos), + 1) || + delete_tails(info, info->cur_row.tail_positions)) + DBUG_RETURN(1); + DBUG_RETURN(_ma_bitmap_free_full_pages(info, info->cur_row.extents, + info->cur_row.extents_count)); +} + + +/**************************************************************************** + Reading of records +****************************************************************************/ + +/* + Read position to record from record directory at end of page + + SYNOPSIS + get_record_position() + buff page buffer + block_size block size for page + record_number Record number in index + end_of_data pointer to end of data for record + + RETURN + 0 Error in data + # Pointer to start of record. + In this case *end_of_data is set. +*/ + +static byte *get_record_position(byte *buff, uint block_size, + uint record_number, byte **end_of_data) +{ + uint number_of_records= (uint) ((uchar *) buff)[DIR_ENTRY_OFFSET]; + byte *dir; + byte *data; + uint offset, length; + +#ifdef SANITY_CHECKS + if (record_number >= number_of_records || + record_number > MAX_ROWS_PER_PAGE || + record_number > ((block_size - PAGE_HEADER_SIZE - PAGE_SUFFIX_SIZE) / + (DIR_ENTRY_SIZE + MIN_TAIL_SIZE))) + { + DBUG_PRINT("error", + ("Wrong row number: record_number: %u number_of_records: %u", + record_number, number_of_records)); + return 0; + } +#endif + + dir= (buff + block_size - DIR_ENTRY_SIZE * record_number - + DIR_ENTRY_SIZE - PAGE_SUFFIX_SIZE); + offset= uint2korr(dir); + length= uint2korr(dir + 2); +#ifdef SANITY_CHECKS + if (offset < PAGE_HEADER_SIZE || + offset + length > (block_size - + number_of_records * DIR_ENTRY_SIZE - + PAGE_SUFFIX_SIZE)) + { + DBUG_PRINT("error", + ("Wrong row position: record_number: %u offset: %u " + "length: %u number_of_records: %u", + record_number, offset, length, number_of_records)); + return 0; + } +#endif + data= buff + offset; + *end_of_data= data + length; + return data; +} + + +/* + Init extent + + NOTES + extent is a cursor over which pages to read +*/ + +static void init_extent(MARIA_EXTENT_CURSOR *extent, byte *extent_info, + uint extents, MARIA_RECORD_POS *tail_positions) +{ + uint page_count; + extent->extent= extent_info; + extent->extent_count= extents; + extent->page= uint5korr(extent_info); /* First extent */ + page_count= uint2korr(extent_info+5); + extent->page_count= page_count & ~TAIL_BIT; + extent->tail= page_count & TAIL_BIT; + extent->tail_positions= tail_positions; +} + + +/* + Read next extent + + SYNOPSIS + read_next_extent() + info Maria handler + extent Pointer to current extent (this is updated to point + to next) + end_of_data Pointer to end of data in read block (out) + + NOTES + New block is read into info->buff + + RETURN + 0 Error; my_errno is set + # Pointer to start of data in read block + In this case end_of_data is updated to point to end of data. +*/ + +static byte *read_next_extent(MARIA_HA *info, MARIA_EXTENT_CURSOR *extent, + byte **end_of_data) +{ + MARIA_SHARE *share= info->s; + byte *buff, *data; + DBUG_ENTER("read_next_extent"); + + if (!extent->page_count) + { + uint page_count; + if (!--extent->extent_count) + goto crashed; + extent->extent+= ROW_EXTENT_SIZE; + extent->page= uint5korr(extent->extent); + page_count= uint2korr(extent->extent+ROW_EXTENT_PAGE_SIZE); + extent->tail= page_count & TAIL_BIT; + extent->page_count= (page_count & ~TAIL_BIT); + extent->first_extent= 0; + DBUG_PRINT("info",("New extent. Page: %lu page_count: %u tail_flag: %d", + (ulong) extent->page, extent->page_count, + extent->tail != 0)); + } + + if (info->cur_row.empty_bits != info->cur_row.empty_bits_buffer) + { + /* + First read of extents: Move data from info->buff to + internals buffers. + */ + memcpy(info->cur_row.empty_bits_buffer, info->cur_row.empty_bits, + share->base.pack_bytes); + info->cur_row.empty_bits= info->cur_row.empty_bits_buffer; + } + + if (!(buff= key_cache_read(share->key_cache, + info->dfile, extent->page * share->block_size, 0, + info->buff, + share->block_size, share->block_size, 0))) + { + /* check if we tried to read over end of file (ie: bad data in record) */ + if ((extent->page + 1) * share->block_size > info->state->data_file_length) + goto crashed; + DBUG_RETURN(0); + } + if (!extent->tail) + { + /* Full data page */ + DBUG_ASSERT((buff[PAGE_TYPE_OFFSET] & PAGE_TYPE_MASK) == BLOB_PAGE); + extent->page++; /* point to next page */ + extent->page_count--; + *end_of_data= buff + share->block_size; + info->cur_row.full_page_count++; /* For maria_chk */ + DBUG_RETURN(extent->data_start= buff + LSN_SIZE + PAGE_TYPE_SIZE); + } + /* Found tail. page_count is in this case the position in the tail page */ + + DBUG_ASSERT((buff[PAGE_TYPE_OFFSET] & PAGE_TYPE_MASK) == TAIL_PAGE); + *(extent->tail_positions++)= ma_recordpos(extent->page, + extent->page_count); + info->cur_row.tail_count++; /* For maria_chk */ + + if (!(data= get_record_position(buff, share->block_size, + extent->page_count, + end_of_data))) + goto crashed; + extent->data_start= data; + extent->page_count= 0; /* No more data in extent */ + DBUG_RETURN(data); + + +crashed: + my_errno= HA_ERR_WRONG_IN_RECORD; /* File crashed */ + DBUG_PRINT("error", ("wrong extent information")); + DBUG_RETURN(0); +} + + +/* + Read data that may be split over many blocks + + SYNOPSIS + read_long_data() + info Maria handler + to Store result string here (this is allocated) + extent Pointer to current extent position + data Current position in buffer + end_of_data End of data in buffer + + NOTES + When we have to read a new buffer, it's read into info->buff + + This loop is implemented by goto's instead of a for() loop as + the code is notable smaller and faster this way (and it's not nice + to jump into a for loop() or into a 'then' clause) + + RETURN + 0 ok + 1 error +*/ + +static my_bool read_long_data(MARIA_HA *info, byte *to, ulong length, + MARIA_EXTENT_CURSOR *extent, + byte **data, byte **end_of_data) +{ + DBUG_ENTER("read_long_data"); + DBUG_PRINT("enter", ("length: %lu", length)); + DBUG_ASSERT(*data <= *end_of_data); + + for(;;) + { + uint left_length; + left_length= (uint) (*end_of_data - *data); + if (likely(left_length >= length)) + { + memcpy(to, *data, length); + (*data)+= length; + DBUG_RETURN(0); + } + memcpy(to, *data, left_length); + to+= left_length; + length-= left_length; + if (!(*data= read_next_extent(info, extent, end_of_data))) + break; + } + DBUG_RETURN(1); +} + + +/* + Read a record from page (helper function for _ma_read_block_record()) + + SYNOPSIS + _ma_read_block_record2() + info Maria handler + record Store record here + data Start of head data for row + end_of_data End of data for row + + NOTES + The head page is already read by caller + Following data is update in info->cur_row: + + cur_row.head_length is set to size of entry in head block + cur_row.tail_positions is set to point to all tail blocks + cur_row.extents points to extents data + cur_row.extents_counts contains number of extents + cur_row.empty_bits points to empty bits part in read record + cur_row.field_lengths contains packed length of all fields + + RETURN + 0 ok + # Error code +*/ + +int _ma_read_block_record2(MARIA_HA *info, byte *record, + byte *data, byte *end_of_data) +{ + MARIA_SHARE *share= info->s; + byte *field_length_data, *blob_buffer, *start_of_data; + uint flag, null_bytes, cur_null_bytes, row_extents, field_lengths; + my_bool found_blob= 0; + MARIA_EXTENT_CURSOR extent; + MARIA_COLUMNDEF *rec, *end_field; + DBUG_ENTER("_ma_read_block_record2"); + + LINT_INIT(field_lengths); + LINT_INIT(field_length_data); + LINT_INIT(blob_buffer); + + start_of_data= data; + flag= (uint) (uchar) data[0]; + cur_null_bytes= share->base.original_null_bytes; + null_bytes= share->base.null_bytes; + info->cur_row.head_length= (uint) (end_of_data - data); + info->cur_row.full_page_count= info->cur_row.tail_count= 0; + + /* Skip trans header (for now, until we have MVCC csupport) */ + data+= total_header_size[(flag & PRECALC_HEADER_BITMASK)]; + if (flag & ROW_FLAG_NULLS_EXTENDED) + cur_null_bytes+= data[-1]; + + row_extents= 0; + if (flag & ROW_FLAG_EXTENTS) + { + uint row_extent_size; + /* + Record is split over many data pages. + Get number of extents and first extent + */ + get_key_length(row_extents, data); + info->cur_row.extents_count= row_extents; + row_extent_size= row_extents * ROW_EXTENT_SIZE; + if (info->cur_row.extents_buffer_length < row_extent_size && + _ma_alloc_buffer(&info->cur_row.extents, + &info->cur_row.extents_buffer_length, + row_extent_size)) + DBUG_RETURN(my_errno); + memcpy(info->cur_row.extents, data, ROW_EXTENT_SIZE); + data+= ROW_EXTENT_SIZE; + init_extent(&extent, info->cur_row.extents, row_extents, + info->cur_row.tail_positions); + } + else + { + info->cur_row.extents_count= 0; + (*info->cur_row.tail_positions)= 0; + extent.page_count= 0; + extent.extent_count= 1; + } + extent.first_extent= 1; + + if (share->base.max_field_lengths) + { + get_key_length(field_lengths, data); +#ifdef SANITY_CHECKS + if (field_lengths > share->base.max_field_lengths) + goto err; +#endif + } + + if (share->calc_checksum) + info->cur_row.checksum= (uint) (uchar) *data++; + /* data now points on null bits */ + memcpy(record, data, cur_null_bytes); + if (unlikely(cur_null_bytes != null_bytes)) + { + /* + This only happens if we have added more NULL columns with + ALTER TABLE and are fetching an old, not yet modified old row + */ + bzero(record + cur_null_bytes, (uint) (null_bytes - cur_null_bytes)); + } + data+= null_bytes; + info->cur_row.empty_bits= (byte*) data; /* Pointer to empty bitmask */ + data+= share->base.pack_bytes; + + /* TODO: Use field offsets, instead of just skipping them */ + data+= share->base.field_offsets * FIELD_OFFSET_SIZE; + + /* + Read row extents (note that first extent was already read into + info->cur_row.extents above) + */ + if (row_extents) + { + if (read_long_data(info, info->cur_row.extents + ROW_EXTENT_SIZE, + (row_extents - 1) * ROW_EXTENT_SIZE, + &extent, &data, &end_of_data)) + DBUG_RETURN(my_errno); + } + + /* + Data now points to start of fixed length field data that can't be null + or 'empty'. Note that these fields can't be split over blocks + */ + for (rec= share->rec, end_field= rec + share->base.fixed_not_null_fields; + rec < end_field; rec++) + { + uint rec_length= rec->length; + if (data >= end_of_data && + !(data= read_next_extent(info, &extent, &end_of_data))) + goto err; + memcpy(record + rec->offset, data, rec_length); + data+= rec_length; + } + + /* Read array of field lengths. This may be stored in several extents */ + if (share->base.max_field_lengths) + { + field_length_data= info->cur_row.field_lengths; + if (read_long_data(info, field_length_data, field_lengths, &extent, + &data, &end_of_data)) + DBUG_RETURN(my_errno); + } + + /* Read variable length data. Each of these may be split over many extents */ + for (end_field= share->rec + share->base.fields; rec < end_field; rec++) + { + enum en_fieldtype type= (enum en_fieldtype) rec->type; + byte *field_pos= record + rec->offset; + /* First check if field is present in record */ + if (record[rec->null_pos] & rec->null_bit) + continue; + else if (info->cur_row.empty_bits[rec->empty_pos] & rec->empty_bit) + { + if (type == FIELD_SKIP_ENDSPACE) + bfill(record + rec->offset, rec->length, ' '); + else + bzero(record + rec->offset, rec->fill_length); + continue; + } + switch (type) { + case FIELD_NORMAL: /* Fixed length field */ + case FIELD_SKIP_PRESPACE: + case FIELD_SKIP_ZERO: /* Fixed length field */ + if (data >= end_of_data && + !(data= read_next_extent(info, &extent, &end_of_data))) + goto err; + memcpy(field_pos, data, rec->length); + data+= rec->length; + break; + case FIELD_SKIP_ENDSPACE: /* CHAR */ + { + /* Char that is space filled */ + uint length; + if (rec->length <= 255) + length= (uint) (uchar) *field_length_data++; + else + { + length= uint2korr(field_length_data); + field_length_data+= 2; + } +#ifdef SANITY_CHECKS + if (length > rec->length) + goto err; +#endif + if (read_long_data(info, field_pos, length, &extent, &data, + &end_of_data)) + DBUG_RETURN(my_errno); + bfill(field_pos + length, rec->length - length, ' '); + break; + } + case FIELD_VARCHAR: + { + ulong length; + if (rec->length <= 256) + { + length= (uint) (uchar) (*field_pos++= *field_length_data++); + } + else + { + length= uint2korr(field_length_data); + field_pos[0]= field_length_data[0]; + field_pos[1]= field_length_data[1]; + field_pos+= 2; + field_length_data+= 2; + } + if (read_long_data(info, field_pos, length, &extent, &data, + &end_of_data)) + DBUG_RETURN(my_errno); + break; + } + case FIELD_BLOB: + { + uint size_length= rec->length - maria_portable_sizeof_char_ptr; + ulong blob_length= _ma_calc_blob_length(size_length, field_length_data); + + if (!found_blob) + { + /* Calculate total length for all blobs */ + ulong blob_lengths= 0; + byte *length_data= field_length_data; + MARIA_COLUMNDEF *blob_field= rec; + + found_blob= 1; + for (; blob_field < end_field; blob_field++) + { + uint size_length; + if ((record[blob_field->null_pos] & blob_field->null_bit) || + (info->cur_row.empty_bits[blob_field->empty_pos] & + blob_field->empty_bit)) + continue; + size_length= blob_field->length - maria_portable_sizeof_char_ptr; + blob_lengths+= _ma_calc_blob_length(size_length, length_data); + length_data+= size_length; + } + DBUG_PRINT("info", ("Total blob length: %lu", blob_lengths)); + if (_ma_alloc_buffer(&info->rec_buff, &info->rec_buff_size, + blob_lengths)) + DBUG_RETURN(my_errno); + blob_buffer= info->rec_buff; + } + + memcpy(field_pos, field_length_data, size_length); + memcpy_fixed(field_pos + size_length, (byte *) & blob_buffer, + sizeof(char*)); + field_length_data+= size_length; + + /* + After we have read one extent, then each blob is in it's own extent + */ + if (extent.first_extent && (ulong) (end_of_data - data) < blob_length) + end_of_data= data; /* Force read of next extent */ + + if (read_long_data(info, blob_buffer, blob_length, &extent, &data, + &end_of_data)) + DBUG_RETURN(my_errno); + blob_buffer+= blob_length; + break; + } +#ifdef EXTRA_DEBUG + default: + DBUG_ASSERT(0); /* purecov: deadcode */ + goto err; +#endif + } + continue; + } + + if (row_extents) + { + DBUG_PRINT("info", ("Row read: page_count: %lu extent_count: %lu", + extent.page_count, extent.extent_count)); + *extent.tail_positions= 0; /* End marker */ + if (extent.page_count) + goto err; + if (extent.extent_count > 1) + if (check_if_zero(extent.extent, + (extent.extent_count-1) * ROW_EXTENT_SIZE)) + goto err; + } + else + { + DBUG_PRINT("info", ("Row read")); + if (data != end_of_data && (uint) (end_of_data - start_of_data) >= + info->s->base.min_row_length) + goto err; + } + + info->update|= HA_STATE_AKTIV; /* We have a aktive record */ + DBUG_RETURN(0); + +err: + /* Something was wrong with data on record */ + DBUG_PRINT("error", ("Found record with wrong data")); + DBUG_RETURN((my_errno= HA_ERR_WRONG_IN_RECORD)); +} + + +/* + Read a record based on record position + + SYNOPSIS + _ma_read_block_record() + info Maria handler + record Store record here + record_pos Record position +*/ + +int _ma_read_block_record(MARIA_HA *info, byte *record, + MARIA_RECORD_POS record_pos) +{ + byte *data, *end_of_data, *buff; + my_off_t page; + uint offset; + uint block_size= info->s->block_size; + DBUG_ENTER("_ma_read_block_record"); + DBUG_PRINT("enter", ("rowid: %lu", (long) record_pos)); + + page= ma_recordpos_to_page(record_pos) * block_size; + offset= ma_recordpos_to_offset(record_pos); + + if (!(buff= key_cache_read(info->s->key_cache, + info->dfile, page, 0, info->buff, + block_size, block_size, 1))) + DBUG_RETURN(1); + DBUG_ASSERT((buff[PAGE_TYPE_OFFSET] & PAGE_TYPE_MASK) == HEAD_PAGE); + if (!(data= get_record_position(buff, block_size, offset, &end_of_data))) + { + my_errno= HA_ERR_WRONG_IN_RECORD; /* File crashed */ + DBUG_PRINT("error", ("Wrong directory entry in data block")); + DBUG_RETURN(1); + } + DBUG_RETURN(_ma_read_block_record2(info, record, data, end_of_data)); +} + + +/* compare unique constraint between stored rows */ + +my_bool _ma_cmp_block_unique(MARIA_HA *info, MARIA_UNIQUEDEF *def, + const byte *record, MARIA_RECORD_POS pos) +{ + byte *org_rec_buff, *old_record; + my_size_t org_rec_buff_size; + int error; + DBUG_ENTER("_ma_cmp_block_unique"); + + if (!(old_record= my_alloca(info->s->base.reclength))) + DBUG_RETURN(1); + + /* Don't let the compare destroy blobs that may be in use */ + org_rec_buff= info->rec_buff; + org_rec_buff_size= info->rec_buff_size; + if (info->s->base.blobs) + { + /* Force realloc of record buffer*/ + info->rec_buff= 0; + info->rec_buff_size= 0; + } + error= _ma_read_block_record(info, old_record, pos); + if (!error) + error= _ma_unique_comp(def, record, old_record, def->null_are_equal); + if (info->s->base.blobs) + { + my_free(info->rec_buff, MYF(MY_ALLOW_ZERO_PTR)); + info->rec_buff= org_rec_buff; + info->rec_buff_size= org_rec_buff_size; + } + DBUG_PRINT("exit", ("result: %d", error)); + my_afree(old_record); + DBUG_RETURN(error != 0); +} + + +/**************************************************************************** + Table scan +****************************************************************************/ + +/* + Allocate buffers for table scan + + SYNOPSIS + _ma_scan_init_block_record(MARIA_HA *info) + + IMPLEMENTATION + We allocate one buffer for the current bitmap and one buffer for the + current page +*/ + +my_bool _ma_scan_init_block_record(MARIA_HA *info) +{ + byte *ptr; + if (!(ptr= (byte *) my_malloc(info->s->block_size * 2, MYF(MY_WME)))) + return (1); + info->scan.bitmap_buff= ptr; + info->scan.page_buff= ptr + info->s->block_size; + info->scan.bitmap_end= info->scan.bitmap_buff + info->s->bitmap.total_size; + + /* Set scan variables to get _ma_scan_block() to start with reading bitmap */ + info->scan.number_of_rows= 0; + info->scan.bitmap_pos= info->scan.bitmap_end; + info->scan.bitmap_page= (ulong) - (long) info->s->bitmap.pages_covered; + /* + We have to flush bitmap as we will read the bitmap from the page cache + while scanning rows + */ + return _ma_flush_bitmap(info->s); +} + + +/* Free buffers allocated by _ma_scan_block_init() */ + +void _ma_scan_end_block_record(MARIA_HA *info) +{ + my_free(info->scan.bitmap_buff, MYF(0)); + info->scan.bitmap_buff= 0; +} + + +/* + Read next record while scanning table + + SYNOPSIS + _ma_scan_block_record() + info Maria handler + record Store found here + record_pos Value stored in info->cur_row.next_pos after last call + skip_deleted + + NOTES + - One must have called mi_scan() before this + - In this version, we don't actually need record_pos, we as easily + use a variable in info->scan + + IMPLEMENTATION + Current code uses a lot of goto's to separate the different kind of + states we may be in. This gives us a minimum of executed if's for + the normal cases. I tried several different ways to code this, but + the current one was in the end the most readable and fastest. + + RETURN + 0 ok + # Error code +*/ + +int _ma_scan_block_record(MARIA_HA *info, byte *record, + MARIA_RECORD_POS record_pos, + my_bool skip_deleted __attribute__ ((unused))) +{ + uint block_size; + my_off_t filepos; + DBUG_ENTER("_ma_scan_block_record"); + +restart_record_read: + /* Find next row in current page */ + if (likely(record_pos < info->scan.number_of_rows)) + { + uint length, offset; + byte *data, *end_of_data; + + while (!(offset= uint2korr(info->scan.dir))) + { + info->scan.dir-= DIR_ENTRY_SIZE; + record_pos++; +#ifdef SANITY_CHECKS + if (info->scan.dir < info->scan.dir_end) + goto err; +#endif + } + /* found row */ + info->cur_row.lastpos= info->scan.row_base_page + record_pos; + info->cur_row.nextpos= record_pos + 1; + data= info->scan.page_buff + offset; + length= uint2korr(info->scan.dir + 2); + end_of_data= data + length; + info->scan.dir-= DIR_ENTRY_SIZE; /* Point to previous row */ +#ifdef SANITY_CHECKS + if (end_of_data > info->scan.dir_end || + offset < PAGE_HEADER_SIZE || length < info->s->base.min_block_length) + goto err; +#endif + DBUG_PRINT("info", ("rowid: %lu", (ulong) info->cur_row.lastpos)); + DBUG_RETURN(_ma_read_block_record2(info, record, data, end_of_data)); + } + + /* Find next head page in current bitmap */ +restart_bitmap_scan: + block_size= info->s->block_size; + if (likely(info->scan.bitmap_pos < info->scan.bitmap_end)) + { + byte *data= info->scan.bitmap_pos; + longlong bits= info->scan.bits; + uint bit_pos= info->scan.bit_pos; + + do + { + while (likely(bits)) + { + uint pattern= bits & 7; + bits >>= 3; + bit_pos++; + if (pattern > 0 && pattern <= 4) + { + /* Found head page; Read it */ + ulong page; + info->scan.bitmap_pos= data; + info->scan.bits= bits; + info->scan.bit_pos= bit_pos; + page= (info->scan.bitmap_page + 1 + + (data - info->scan.bitmap_buff) / 6 * 16 + bit_pos - 1); + info->scan.row_base_page= ma_recordpos(page, 0); + if (!(key_cache_read(info->s->key_cache, + info->dfile, + (my_off_t) page * block_size, + 0, info->scan.page_buff, + block_size, block_size, 0))) + DBUG_RETURN(my_errno); + if (((info->scan.page_buff[PAGE_TYPE_OFFSET] & PAGE_TYPE_MASK) != + HEAD_PAGE) || + (info->scan.number_of_rows= + (uint) (uchar) info->scan.page_buff[DIR_ENTRY_OFFSET]) == 0) + { + DBUG_PRINT("error", ("Wrong page header")); + DBUG_RETURN((my_errno= HA_ERR_WRONG_IN_RECORD)); + } + info->scan.dir= (info->scan.page_buff + block_size - + PAGE_SUFFIX_SIZE - DIR_ENTRY_SIZE); + info->scan.dir_end= (info->scan.dir - + (info->scan.number_of_rows - 1) * + DIR_ENTRY_SIZE); + record_pos= 0; + goto restart_record_read; + } + } + for (data+= 6; data < info->scan.bitmap_end; data+= 6) + { + bits= uint6korr(data); + if (bits && ((bits & LL(04444444444444444)) != LL(04444444444444444))) + break; + } + bit_pos= 0; + } while (data < info->scan.bitmap_end); + } + + /* Read next bitmap */ + info->scan.bitmap_page+= info->s->bitmap.pages_covered; + filepos= (my_off_t) info->scan.bitmap_page * block_size; + if (unlikely(filepos >= info->state->data_file_length)) + { + DBUG_RETURN((my_errno= HA_ERR_END_OF_FILE)); + } + if (!(key_cache_read(info->s->key_cache, info->dfile, filepos, + 0, info->scan.bitmap_buff, block_size, block_size, 0))) + DBUG_RETURN(my_errno); + /* Skip scanning 'bits' in bitmap scan code */ + info->scan.bitmap_pos= info->scan.bitmap_buff - 6; + info->scan.bits= 0; + goto restart_bitmap_scan; + +err: + DBUG_PRINT("error", ("Wrong data on page")); + DBUG_RETURN((my_errno= HA_ERR_WRONG_IN_RECORD)); +} + + +/* + Compare a row against a stored one + + NOTES + Not implemented, as block record is not supposed to be used in a shared + global environment +*/ + +my_bool _ma_compare_block_record(MARIA_HA *info __attribute__ ((unused)), + const byte *record __attribute__ ((unused))) +{ + return 0; +} + + +#ifndef DBUG_OFF + +static void _ma_print_directory(byte *buff, uint block_size) +{ + uint max_entry= (uint) ((uchar *) buff)[DIR_ENTRY_OFFSET], row= 0; + uint end_of_prev_row= PAGE_HEADER_SIZE; + byte *dir, *end; + + dir= buff + block_size - DIR_ENTRY_SIZE * max_entry - PAGE_SUFFIX_SIZE; + end= buff + block_size - DIR_ENTRY_SIZE - PAGE_SUFFIX_SIZE; + + DBUG_LOCK_FILE; + fprintf(DBUG_FILE,"Directory dump (pos:length):\n"); + + for (row= 1; dir <= end ; end-= DIR_ENTRY_SIZE, row++) + { + uint offset= uint2korr(end); + uint length= uint2korr(end+2); + fprintf(DBUG_FILE, " %4u:%4u", offset, offset ? length : 0); + if (!(row % (80/12))) + fputc('\n', DBUG_FILE); + if (offset) + { + DBUG_ASSERT(offset >= end_of_prev_row); + end_of_prev_row= offset + length; + } + } + fputc('\n', DBUG_FILE); + fflush(DBUG_FILE); + DBUG_UNLOCK_FILE; +} +#endif /* DBUG_OFF */ + diff --git a/storage/maria/ma_blockrec.h b/storage/maria/ma_blockrec.h new file mode 100644 index 00000000000..ec99dbfcae2 --- /dev/null +++ b/storage/maria/ma_blockrec.h @@ -0,0 +1,160 @@ +/* Copyright (C) 2007 Michael Widenius + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +/* + Storage of records in block +*/ + +#define LSN_SIZE 7 +#define DIRCOUNT_SIZE 1 /* Stores number of rows on page */ +#define EMPTY_SPACE_SIZE 2 /* Stores empty space on page */ +#define PAGE_TYPE_SIZE 1 +#define PAGE_SUFFIX_SIZE 0 /* Bytes for page suffix */ +#define PAGE_HEADER_SIZE (LSN_SIZE + DIRCOUNT_SIZE + EMPTY_SPACE_SIZE +\ + PAGE_TYPE_SIZE) +#define PAGE_OVERHEAD_SIZE (PAGE_HEADER_SIZE + DIR_ENTRY_SIZE + \ + PAGE_SUFFIX_SIZE) +#define BLOCK_RECORD_POINTER_SIZE 6 + +#define FULL_PAGE_SIZE(block_size) ((block_size) - LSN_SIZE - PAGE_TYPE_SIZE) + +#define ROW_EXTENT_PAGE_SIZE 5 +#define ROW_EXTENT_COUNT_SIZE 2 +#define ROW_EXTENT_SIZE (ROW_EXTENT_PAGE_SIZE + ROW_EXTENT_COUNT_SIZE) +#define TAIL_BIT 0x8000 /* Bit in page_count to signify tail */ +#define ELEMENTS_RESERVED_FOR_MAIN_PART 4 +#define EXTRA_LENGTH_FIELDS 3 + +#define FLAG_SIZE 1 +#define TRANSID_SIZE 6 +#define VERPTR_SIZE 7 +#define DIR_ENTRY_SIZE 4 +#define FIELD_OFFSET_SIZE 2 + +/* Minimum header size needed for a new row */ +#define BASE_ROW_HEADER_SIZE FLAG_SIZE +#define TRANS_ROW_EXTRA_HEADER_SIZE TRANSID_SIZE + +#define PAGE_TYPE_MASK 127 +enum en_page_type { UNALLOCATED_PAGE, HEAD_PAGE, TAIL_PAGE, BLOB_PAGE, MAX_PAGE_TYPE }; + +#define PAGE_TYPE_OFFSET LSN_SIZE +#define DIR_ENTRY_OFFSET LSN_SIZE+PAGE_TYPE_SIZE +#define EMPTY_SPACE_OFFSET (DIR_ENTRY_OFFSET + DIRCOUNT_SIZE) + +#define PAGE_CAN_BE_COMPACTED 128 /* Bit in PAGE_TYPE */ + +/* Bits used for flag byte (one byte, first in record) */ +#define ROW_FLAG_TRANSID 1 +#define ROW_FLAG_VER_PTR 2 +#define ROW_FLAG_DELETE_TRANSID 4 +#define ROW_FLAG_NULLS_EXTENDED 8 +#define ROW_FLAG_EXTENTS 128 +#define ROW_FLAG_ALL (1+2+4+8+128) + +/* Variables that affects how data pages are utilized */ +#define MIN_TAIL_SIZE 32 + +/* Fixed part of Max possible header size; See table in ma_blockrec.c */ +#define MAX_FIXED_HEADER_SIZE (FLAG_SIZE + 3 + ROW_EXTENT_SIZE + 3) +#define TRANS_MAX_FIXED_HEADER_SIZE (MAX_FIXED_HEADER_SIZE + \ + FLAG_SIZE + TRANSID_SIZE + VERPTR_SIZE + \ + TRANSID_SIZE) + +/* We use 1 byte in record header to store number of directory entries */ +#define MAX_ROWS_PER_PAGE 255 + +/* Bits for MARIA_BITMAP_BLOCKS->used */ +#define BLOCKUSED_USED 1 +#define BLOCKUSED_USE_ORG_BITMAP 2 +#define BLOCKUSED_TAIL 4 + +/* defines that affects allocation (density) of data */ + +/* If we fill up a block to 75 %, don't create a new tail page for it */ +#define MAX_TAIL_SIZE(block_size) ((block_size) *3 / 4) + +/* Functions to convert MARIA_RECORD_POS to/from page:offset */ + +static inline MARIA_RECORD_POS ma_recordpos(ulonglong page, uint offset) +{ + return (MARIA_RECORD_POS) ((page << 8) | offset); +} + +static inline my_off_t ma_recordpos_to_page(MARIA_RECORD_POS record_pos) +{ + return record_pos >> 8; +} + +static inline my_off_t ma_recordpos_to_offset(MARIA_RECORD_POS record_pos) +{ + return record_pos & 255; +} + +/* ma_blockrec.c */ +void _ma_init_block_record_data(void); +my_bool _ma_once_init_block_row(MARIA_SHARE *share, File dfile); +my_bool _ma_once_end_block_row(MARIA_SHARE *share); +my_bool _ma_init_block_row(MARIA_HA *info); +void _ma_end_block_row(MARIA_HA *info); + +my_bool _ma_update_block_record(MARIA_HA *info, MARIA_RECORD_POS pos, + const byte *record); +my_bool _ma_delete_block_record(MARIA_HA *info); +int _ma_read_block_record(MARIA_HA *info, byte *record, + MARIA_RECORD_POS record_pos); +int _ma_read_block_record2(MARIA_HA *info, byte *record, + byte *data, byte *end_of_data); +int _ma_scan_block_record(MARIA_HA *info, byte *record, + MARIA_RECORD_POS, my_bool); +my_bool _ma_cmp_block_unique(MARIA_HA *info, MARIA_UNIQUEDEF *def, + const byte *record, MARIA_RECORD_POS pos); +my_bool _ma_scan_init_block_record(MARIA_HA *info); +void _ma_scan_end_block_record(MARIA_HA *info); + +MARIA_RECORD_POS _ma_write_init_block_record(MARIA_HA *info, + const byte *record); +my_bool _ma_write_block_record(MARIA_HA *info, const byte *record); +my_bool _ma_write_abort_block_record(MARIA_HA *info); +my_bool _ma_compare_block_record(register MARIA_HA *info, + register const byte *record); + +/* ma_bitmap.c */ +my_bool _ma_bitmap_init(MARIA_SHARE *share, File file); +my_bool _ma_bitmap_end(MARIA_SHARE *share); +my_bool _ma_flush_bitmap(MARIA_SHARE *share); +my_bool _ma_read_bitmap_page(MARIA_SHARE *share, MARIA_FILE_BITMAP *bitmap, + ulonglong page); +my_bool _ma_bitmap_find_place(MARIA_HA *info, MARIA_ROW *row, + MARIA_BITMAP_BLOCKS *result_blocks); +my_bool _ma_bitmap_release_unused(MARIA_HA *info, MARIA_BITMAP_BLOCKS *blocks); +my_bool _ma_bitmap_free_full_pages(MARIA_HA *info, const byte *extents, + uint count); +my_bool _ma_bitmap_set(MARIA_HA *info, ulonglong pos, my_bool head, + uint empty_space); +my_bool _ma_reset_full_page_bits(MARIA_HA *info, MARIA_FILE_BITMAP *bitmap, + ulonglong page, uint page_count); +uint _ma_free_size_to_head_pattern(MARIA_FILE_BITMAP *bitmap, uint size); +my_bool _ma_bitmap_find_new_place(MARIA_HA *info, MARIA_ROW *new_row, + ulonglong page, uint free_size, + MARIA_BITMAP_BLOCKS *result_blocks); +my_bool _ma_check_bitmap_data(MARIA_HA *info, + enum en_page_type page_type, ulonglong page, + uint empty_space, uint *bitmap_pattern); +my_bool _ma_check_if_right_bitmap_type(MARIA_HA *info, + enum en_page_type page_type, + ulonglong page, + uint *bitmap_pattern); diff --git a/storage/maria/ma_check.c b/storage/maria/ma_check.c index 69d863e6366..3fece3687e1 100644 --- a/storage/maria/ma_check.c +++ b/storage/maria/ma_check.c @@ -28,43 +28,43 @@ #include <sys/mman.h> #endif #include "ma_rt_index.h" +#include "ma_blockrec.h" -#ifndef USE_RAID -#define my_raid_create(A,B,C,D,E,F,G) my_create(A,B,C,G) -#define my_raid_delete(A,B,C) my_delete(A,B) -#endif - - /* Functions defined in this file */ +/* Functions defined in this file */ -static int check_k_link(HA_CHECK *param, MARIA_HA *info,uint nr); +static int check_k_link(HA_CHECK *param, MARIA_HA *info, my_off_t next_link); static int chk_index(HA_CHECK *param, MARIA_HA *info,MARIA_KEYDEF *keyinfo, - my_off_t page, uchar *buff, ha_rows *keys, + my_off_t page, byte *buff, ha_rows *keys, ha_checksum *key_checksum, uint level); static uint isam_key_length(MARIA_HA *info,MARIA_KEYDEF *keyinfo); static ha_checksum calc_checksum(ha_rows count); static int writekeys(HA_CHECK *param, MARIA_HA *info,byte *buff, my_off_t filepos); -static int sort_one_index(HA_CHECK *param, MARIA_HA *info,MARIA_KEYDEF *keyinfo, +static int sort_one_index(HA_CHECK *param, MARIA_HA *info, + MARIA_KEYDEF *keyinfo, my_off_t pagepos, File new_file); -static int sort_key_read(MARIA_SORT_PARAM *sort_param,void *key); -static int sort_maria_ft_key_read(MARIA_SORT_PARAM *sort_param,void *key); +static int sort_key_read(MARIA_SORT_PARAM *sort_param, byte *key); +static int sort_maria_ft_key_read(MARIA_SORT_PARAM *sort_param, byte *key); static int sort_get_next_record(MARIA_SORT_PARAM *sort_param); -static int sort_key_cmp(MARIA_SORT_PARAM *sort_param, const void *a,const void *b); -static int sort_maria_ft_key_write(MARIA_SORT_PARAM *sort_param, const void *a); -static int sort_key_write(MARIA_SORT_PARAM *sort_param, const void *a); +static int sort_key_cmp(MARIA_SORT_PARAM *sort_param, const void *a, + const void *b); +static int sort_maria_ft_key_write(MARIA_SORT_PARAM *sort_param, + const byte *a); +static int sort_key_write(MARIA_SORT_PARAM *sort_param, const byte *a); static my_off_t get_record_for_key(MARIA_HA *info,MARIA_KEYDEF *keyinfo, - uchar *key); + const byte *key); static int sort_insert_key(MARIA_SORT_PARAM *sort_param, reg1 SORT_KEY_BLOCKS *key_block, - uchar *key, my_off_t prev_block); + const byte *key, my_off_t prev_block); static int sort_delete_record(MARIA_SORT_PARAM *sort_param); /*static int _ma_flush_pending_blocks(HA_CHECK *param);*/ static SORT_KEY_BLOCKS *alloc_key_blocks(HA_CHECK *param, uint blocks, uint buffer_length); static ha_checksum maria_byte_checksum(const byte *buf, uint length); static void set_data_file_type(MARIA_SORT_INFO *sort_info, MARIA_SHARE *share); +static void restore_data_file_type(MARIA_SHARE *share); -void mariachk_init(HA_CHECK *param) +void maria_chk_init(HA_CHECK *param) { bzero((gptr) param,sizeof(*param)); param->opt_follow_links=1; @@ -182,7 +182,7 @@ int maria_chk_del(HA_CHECK *param, register MARIA_HA *info, uint test_flag) else { param->record_checksum+=(ha_checksum) next_link; - next_link= _ma_rec_pos(info->s,(uchar*) buff+1); + next_link= _ma_rec_pos(info->s, buff+1); empty+=info->s->base.pack_reclength; } } @@ -223,18 +223,14 @@ wrong: /* Check delete links in index file */ -static int check_k_link(HA_CHECK *param, register MARIA_HA *info, uint nr) +static int check_k_link(HA_CHECK *param, register MARIA_HA *info, + my_off_t next_link) { - my_off_t next_link; - uint block_size=(nr+1)*MARIA_MIN_KEY_BLOCK_LENGTH; + uint block_size= info->s->block_size; ha_rows records; char llbuff[21],*buff; DBUG_ENTER("check_k_link"); - if (param->testflag & T_VERBOSE) - printf("block_size %4d:",block_size); - - next_link=info->s->state.key_del[nr]; records= (ha_rows) (info->state->key_file_length / block_size); while (next_link != HA_OFFSET_ERROR && records > 0) { @@ -243,12 +239,12 @@ static int check_k_link(HA_CHECK *param, register MARIA_HA *info, uint nr) if (param->testflag & T_VERBOSE) printf("%16s",llstr(next_link,llbuff)); if (next_link > info->state->key_file_length || - next_link & (info->s->blocksize-1)) + next_link & (info->s->block_size-1)) DBUG_RETURN(1); if (!(buff=key_cache_read(info->s->key_cache, info->s->kfile, next_link, DFLT_INIT_HITS, (byte*) info->buff, - maria_block_size, block_size, 1))) + block_size, block_size, 1))) DBUG_RETURN(1); next_link=mi_sizekorr(buff); records--; @@ -274,9 +270,10 @@ int maria_chk_size(HA_CHECK *param, register MARIA_HA *info) char buff[22],buff2[22]; DBUG_ENTER("maria_chk_size"); - if (!(param->testflag & T_SILENT)) puts("- check file-size"); + if (!(param->testflag & T_SILENT)) + puts("- check file-size"); - /* The following is needed if called externally (not from mariachk) */ + /* The following is needed if called externally (not from maria_chk) */ flush_key_blocks(info->s->key_cache, info->s->kfile, FLUSH_FORCE_WRITE); @@ -291,7 +288,7 @@ int maria_chk_size(HA_CHECK *param, register MARIA_HA *info) "Size of indexfile is: %-8s Should be: %s", llstr(size,buff), llstr(skr,buff2)); } - else + else if (!(param->testflag & T_VERY_SILENT)) _ma_check_print_warning(param, "Size of indexfile is: %-8s Should be: %s", llstr(size,buff), llstr(skr,buff2)); @@ -341,7 +338,7 @@ int maria_chk_size(HA_CHECK *param, register MARIA_HA *info) } /* maria_chk_size */ - /* Check keys */ +/* Check keys */ int maria_chk_key(HA_CHECK *param, register MARIA_HA *info) { @@ -359,23 +356,22 @@ int maria_chk_key(HA_CHECK *param, register MARIA_HA *info) puts("- check key delete-chain"); param->key_file_blocks=info->s->base.keystart; - for (key=0 ; key < info->s->state.header.max_block_size_index ; key++) - if (check_k_link(param,info,key)) - { - if (param->testflag & T_VERBOSE) puts(""); - _ma_check_print_error(param,"key delete-link-chain corrupted"); - DBUG_RETURN(-1); - } + if (check_k_link(param, info, info->s->state.key_del)) + { + if (param->testflag & T_VERBOSE) puts(""); + _ma_check_print_error(param,"key delete-link-chain corrupted"); + DBUG_RETURN(-1); + } if (!(param->testflag & T_SILENT)) puts("- check index reference"); all_keydata=all_totaldata=key_totlength=0; old_record_checksum=0; init_checksum=param->record_checksum; - if (!(share->options & - (HA_OPTION_PACK_RECORD | HA_OPTION_COMPRESS_RECORD))) - old_record_checksum=calc_checksum(info->state->records+info->state->del-1)* - share->base.pack_reclength; + if (share->data_file_type == STATIC_RECORD) + old_record_checksum= (calc_checksum(info->state->records + + info->state->del-1) * + share->base.pack_reclength); rec_per_key_part= param->rec_per_key_part; for (key= 0,keyinfo= &share->keyinfo[0]; key < share->base.keys ; rec_per_key_part+=keyinfo->keysegs, key++, keyinfo++) @@ -433,11 +429,10 @@ int maria_chk_key(HA_CHECK *param, register MARIA_HA *info) result= -1; continue; } - if (found_keys - full_text_keys == 1 && - ((share->options & - (HA_OPTION_PACK_RECORD | HA_OPTION_COMPRESS_RECORD)) || - (param->testflag & T_DONT_CHECK_CHECKSUM))) - old_record_checksum=param->record_checksum; + if ((found_keys - full_text_keys == 1 && + !(share->data_file_type == STATIC_RECORD)) || + (param->testflag & T_DONT_CHECK_CHECKSUM)) + old_record_checksum= param->record_checksum; else if (old_record_checksum != param->record_checksum) { if (key) @@ -456,7 +451,7 @@ int maria_chk_key(HA_CHECK *param, register MARIA_HA *info) /* Check that auto_increment key is bigger than max key value */ ulonglong auto_increment; info->lastinx=key; - _ma_read_key_record(info, 0L, info->rec_buff); + _ma_read_key_record(info, info->rec_buff, 0); auto_increment= ma_retrieve_auto_increment(info, info->rec_buff); if (auto_increment > info->s->state.auto_increment) { @@ -479,7 +474,7 @@ int maria_chk_key(HA_CHECK *param, register MARIA_HA *info) if (!maria_rkey(info, info->rec_buff, key, (const byte*) info->lastkey, keyinfo->seg->length, HA_READ_KEY_EXACT)) { - /* Don't count this as a real warning, as mariachk can't correct it */ + /* Don't count this as a real warning, as maria_chk can't correct it */ uint save=param->warning_printed; _ma_check_print_warning(param, "Found row where the auto_increment column has the value 0"); @@ -528,21 +523,22 @@ do_stat: } /* maria_chk_key */ -static int chk_index_down(HA_CHECK *param, MARIA_HA *info, MARIA_KEYDEF *keyinfo, - my_off_t page, uchar *buff, ha_rows *keys, - ha_checksum *key_checksum, uint level) +static int chk_index_down(HA_CHECK *param, MARIA_HA *info, + MARIA_KEYDEF *keyinfo, + my_off_t page, byte *buff, ha_rows *keys, + ha_checksum *key_checksum, uint level) { char llbuff[22],llbuff2[22]; - if (page > info->state->key_file_length || (page & (info->s->blocksize -1))) + if (page > info->state->key_file_length || (page & (info->s->block_size -1))) { my_off_t max_length=my_seek(info->s->kfile,0L,MY_SEEK_END,MYF(0)); _ma_check_print_error(param,"Wrong pagepointer: %s at page: %s", llstr(page,llbuff),llstr(page,llbuff2)); - if (page+info->s->blocksize > max_length) + if (page+info->s->block_size > max_length) goto err; info->state->key_file_length=(max_length & - ~ (my_off_t) (info->s->blocksize-1)); + ~ (my_off_t) (info->s->block_size-1)); } if (!_ma_fetch_keypage(info,keyinfo,page, DFLT_INIT_HITS,buff,0)) { @@ -577,10 +573,10 @@ err: static void maria_collect_stats_nonulls_first(HA_KEYSEG *keyseg, ulonglong *notnull, - uchar *key) + const byte *key) { uint first_null, kp; - first_null= ha_find_null(keyseg, key) - keyseg; + first_null= ha_find_null(keyseg, (uchar*) key) - keyseg; /* All prefix tuples that don't include keypart_{first_null} are not-null tuples (and all others aren't), increment counters for them. @@ -617,7 +613,8 @@ void maria_collect_stats_nonulls_first(HA_KEYSEG *keyseg, ulonglong *notnull, static int maria_collect_stats_nonulls_next(HA_KEYSEG *keyseg, ulonglong *notnull, - uchar *prev_key, uchar *last_key) + const byte *prev_key, + const byte *last_key) { uint diffs[2]; uint first_null_seg, kp; @@ -631,12 +628,12 @@ int maria_collect_stats_nonulls_next(HA_KEYSEG *keyseg, ulonglong *notnull, last_key that is NULL or different from corresponding value in prev_key. */ - ha_key_cmp(keyseg, prev_key, last_key, USE_WHOLE_KEY, + ha_key_cmp(keyseg, (uchar*) prev_key, (uchar*) last_key, USE_WHOLE_KEY, SEARCH_FIND | SEARCH_NULL_ARE_NOT_EQUAL, diffs); seg= keyseg + diffs[0] - 1; /* Find first NULL in last_key */ - first_null_seg= ha_find_null(seg, last_key + diffs[1]) - keyseg; + first_null_seg= ha_find_null(seg, (uchar*) last_key + diffs[1]) - keyseg; for (kp= 0; kp < first_null_seg; kp++) notnull[kp]++; @@ -652,12 +649,12 @@ int maria_collect_stats_nonulls_next(HA_KEYSEG *keyseg, ulonglong *notnull, /* Check if index is ok */ static int chk_index(HA_CHECK *param, MARIA_HA *info, MARIA_KEYDEF *keyinfo, - my_off_t page, uchar *buff, ha_rows *keys, + my_off_t page, byte *buff, ha_rows *keys, ha_checksum *key_checksum, uint level) { int flag; uint used_length,comp_flag,nod_flag,key_length=0; - uchar key[HA_MAX_POSSIBLE_KEY_BUFF],*temp_buff,*keypos,*old_keypos,*endpos; + byte key[HA_MAX_POSSIBLE_KEY_BUFF],*temp_buff,*keypos,*old_keypos,*endpos; my_off_t next_page,record; char llbuff[22]; uint diff_pos[2]; @@ -668,7 +665,7 @@ static int chk_index(HA_CHECK *param, MARIA_HA *info, MARIA_KEYDEF *keyinfo, if (keyinfo->flag & HA_SPATIAL) DBUG_RETURN(0); - if (!(temp_buff=(uchar*) my_alloca((uint) keyinfo->block_length))) + if (!(temp_buff=(byte*) my_alloca((uint) keyinfo->block_length))) { _ma_check_print_error(param,"Not enough memory for keyblock"); DBUG_RETURN(-1); @@ -698,8 +695,8 @@ static int chk_index(HA_CHECK *param, MARIA_HA *info, MARIA_KEYDEF *keyinfo, { if (*_ma_killed_ptr(param)) goto err; - memcpy((char*) info->lastkey,(char*) key,key_length); - info->lastkey_length=key_length; + memcpy(info->lastkey, key, key_length); + info->lastkey_length= key_length; if (nod_flag) { next_page= _ma_kpos(nod_flag,keypos); @@ -713,21 +710,24 @@ static int chk_index(HA_CHECK *param, MARIA_HA *info, MARIA_KEYDEF *keyinfo, break; if (keypos > endpos) { - _ma_check_print_error(param,"Wrong key block length at page: %s",llstr(page,llbuff)); + _ma_check_print_error(param,"Wrong key block length at page: %s", + llstr(page,llbuff)); goto err; } if ((*keys)++ && - (flag=ha_key_cmp(keyinfo->seg,info->lastkey,key,key_length, - comp_flag, diff_pos)) >=0) + (flag=ha_key_cmp(keyinfo->seg, (uchar*) info->lastkey, (uchar*) key, + key_length, comp_flag, diff_pos)) >=0) { - DBUG_DUMP("old",(byte*) info->lastkey, info->lastkey_length); - DBUG_DUMP("new",(byte*) key, key_length); - DBUG_DUMP("new_in_page",(char*) old_keypos,(uint) (keypos-old_keypos)); + DBUG_DUMP("old", info->lastkey, info->lastkey_length); + DBUG_DUMP("new", key, key_length); + DBUG_DUMP("new_in_page", old_keypos, (uint) (keypos-old_keypos)); if (comp_flag & SEARCH_FIND && flag == 0) - _ma_check_print_error(param,"Found duplicated key at page %s",llstr(page,llbuff)); + _ma_check_print_error(param,"Found duplicated key at page %s", + llstr(page,llbuff)); else - _ma_check_print_error(param,"Key in wrong position at page %s",llstr(page,llbuff)); + _ma_check_print_error(param,"Key in wrong position at page %s", + llstr(page,llbuff)); goto err; } if (param->testflag & T_STATISTICS) @@ -735,14 +735,14 @@ static int chk_index(HA_CHECK *param, MARIA_HA *info, MARIA_KEYDEF *keyinfo, if (*keys != 1L) /* not first_key */ { if (param->stats_method == MI_STATS_METHOD_NULLS_NOT_EQUAL) - ha_key_cmp(keyinfo->seg,info->lastkey,key,USE_WHOLE_KEY, - SEARCH_FIND | SEARCH_NULL_ARE_NOT_EQUAL, + ha_key_cmp(keyinfo->seg, (uchar*) info->lastkey, (uchar*) key, + USE_WHOLE_KEY, SEARCH_FIND | SEARCH_NULL_ARE_NOT_EQUAL, diff_pos); else if (param->stats_method == MI_STATS_METHOD_IGNORE_NULLS) { diff_pos[0]= maria_collect_stats_nonulls_next(keyinfo->seg, - param->notnull_count, - info->lastkey, key); + param->notnull_count, + info->lastkey, key); } param->unique_count[diff_pos[0]-1]++; } @@ -795,7 +795,7 @@ static int chk_index(HA_CHECK *param, MARIA_HA *info, MARIA_KEYDEF *keyinfo, DBUG_DUMP("new_in_page",(char*) old_keypos,(uint) (keypos-old_keypos)); goto err; } - param->record_checksum+=(ha_checksum) record; + param->record_checksum+= (ha_checksum) record; } if (keypos != endpos) { @@ -852,355 +852,844 @@ static uint isam_key_length(MARIA_HA *info, register MARIA_KEYDEF *keyinfo) } /* key_length */ - /* Check that record-link is ok */ -int maria_chk_data_link(HA_CHECK *param, MARIA_HA *info,int extend) +static void record_pos_to_txt(MARIA_HA *info, my_off_t recpos, + char *buff) { - int error,got_error,flag; - uint key,left_length,b_type,field; - ha_rows records,del_blocks; - my_off_t used,empty,pos,splits,start_recpos, - del_length,link_used,start_block; - byte *record,*to; - char llbuff[22],llbuff2[22],llbuff3[22]; - ha_checksum intern_record_checksum; - ha_checksum key_checksum[HA_MAX_POSSIBLE_KEY]; - my_bool static_row_size; - MARIA_KEYDEF *keyinfo; - MARIA_BLOCK_INFO block_info; - DBUG_ENTER("maria_chk_data_link"); - - if (!(param->testflag & T_SILENT)) + if (info->s->data_file_type != BLOCK_RECORD) + llstr(recpos, buff); + else { - if (extend) - puts("- check records and index references"); - else - puts("- check record links"); + my_off_t page= ma_recordpos_to_page(recpos); + uint row= ma_recordpos_to_offset(recpos); + char *end= longlong10_to_str(page, buff, 10); + *(end++)= ':'; + longlong10_to_str(row, end, 10); } +} - if (!(record= (byte*) my_malloc(info->s->base.pack_reclength,MYF(0)))) + +/* + Check that keys in records exist in index tree + + SYNOPSIS + check_keys_in_record() + param Check paramenter + info Maria handler + extend Type of check (extended or normal) + start_recpos Position to row + record Record buffer + + NOTES + This function also calculates record checksum & number of rows +*/ + +static int check_keys_in_record(HA_CHECK *param, MARIA_HA *info, int extend, + my_off_t start_recpos, byte *record) +{ + MARIA_KEYDEF *keyinfo; + char llbuff[22+4]; + uint key; + + param->tmp_record_checksum+= (ha_checksum) start_recpos; + param->records++; + if (param->testflag & T_WRITE_LOOP && param->records % WRITE_COUNT == 0) { - _ma_check_print_error(param,"Not enough memory for record"); - DBUG_RETURN(-1); + printf("%s\r", llstr(param->records, llbuff)); + VOID(fflush(stdout)); } - records=del_blocks=0; - used=link_used=splits=del_length=0; - intern_record_checksum=param->glob_crc=0; - LINT_INIT(left_length); LINT_INIT(start_recpos); LINT_INIT(to); - got_error=error=0; - empty=info->s->pack.header_length; - /* Check how to calculate checksum of rows */ - static_row_size=1; - if (info->s->data_file_type == COMPRESSED_RECORD) + /* Check if keys match the record */ + for (key=0, keyinfo= info->s->keyinfo; key < info->s->base.keys; + key++,keyinfo++) { - for (field=0 ; field < info->s->base.fields ; field++) + if (maria_is_key_active(info->s->state.key_map, key)) { - if (info->s->rec[field].base_type == FIELD_BLOB || - info->s->rec[field].base_type == FIELD_VARCHAR) + if(!(keyinfo->flag & HA_FULLTEXT)) { - static_row_size=0; - break; + uint key_length= _ma_make_key(info,key,info->lastkey,record, + start_recpos); + if (extend) + { + /* We don't need to lock the key tree here as we don't allow + concurrent threads when running maria_chk + */ + int search_result= +#ifdef HAVE_RTREE_KEYS + (keyinfo->flag & HA_SPATIAL) ? + maria_rtree_find_first(info, key, info->lastkey, key_length, + MBR_EQUAL | MBR_DATA) : +#endif + _ma_search(info,keyinfo,info->lastkey,key_length, + SEARCH_SAME, info->s->state.key_root[key]); + if (search_result) + { + record_pos_to_txt(info, start_recpos, llbuff); + _ma_check_print_error(param,"Record at: %14s Can't find key for index: %2d", + llbuff,key+1); + if (param->err_count++ > MAXERR || !(param->testflag & T_VERBOSE)) + return -1; + } + } + else + param->tmp_key_crc[key]+= + maria_byte_checksum((byte*) info->lastkey, key_length); } } } + return 0; +} + + +/* + Functions to loop through all rows and check if they are ok + + NOTES + One function for each record format - pos=my_b_tell(¶m->read_cache); - bzero((char*) key_checksum, info->s->base.keys * sizeof(key_checksum[0])); + RESULT + 0 ok + -1 Interrupted by user + 1 Error +*/ + +static int check_static_record(HA_CHECK *param, MARIA_HA *info, int extend, + byte *record) +{ + my_off_t start_recpos, pos; + char llbuff[22]; + + pos= 0; while (pos < info->state->data_file_length) { if (*_ma_killed_ptr(param)) - goto err2; - switch (info->s->data_file_type) { - case STATIC_RECORD: - if (my_b_read(¶m->read_cache,(byte*) record, - info->s->base.pack_reclength)) - goto err; - start_recpos=pos; - pos+=info->s->base.pack_reclength; - splits++; - if (*record == '\0') + return -1; + if (my_b_read(¶m->read_cache,(byte*) record, + info->s->base.pack_reclength)) + { + _ma_check_print_error(param, + "got error: %d when reading datafile at position: %s", + my_errno, llstr(pos, llbuff)); + return 1; + } + start_recpos= pos; + pos+= info->s->base.pack_reclength; + param->splits++; + if (*record == '\0') + { + param->del_blocks++; + param->del_length+= info->s->base.pack_reclength; + continue; /* Record removed */ + } + param->glob_crc+= _ma_static_checksum(info,record); + param->used+= info->s->base.pack_reclength; + if (check_keys_in_record(param, info, extend, start_recpos, record)) + return 1; + } + return 0; +} + + +static int check_dynamic_record(HA_CHECK *param, MARIA_HA *info, int extend, + byte *record) +{ + MARIA_BLOCK_INFO block_info; + my_off_t start_recpos, start_block, pos; + byte *to; + ulong left_length; + uint b_type; + char llbuff[22],llbuff2[22],llbuff3[22]; + DBUG_ENTER("check_dynamic_record"); + + pos= 0; + while (pos < info->state->data_file_length) + { + my_bool got_error= 0; + int flag; + if (*_ma_killed_ptr(param)) + DBUG_RETURN(-1); + + flag= block_info.second_read=0; + block_info.next_filepos=pos; + do + { + if (_ma_read_cache(¶m->read_cache,(byte*) block_info.header, + (start_block=block_info.next_filepos), + sizeof(block_info.header), + (flag ? 0 : READING_NEXT) | READING_HEADER)) { - del_blocks++; - del_length+=info->s->base.pack_reclength; - continue; /* Record removed */ + _ma_check_print_error(param, + "got error: %d when reading datafile at position: %s", + my_errno, llstr(start_block, llbuff)); + DBUG_RETURN(1); } - param->glob_crc+= _ma_static_checksum(info,record); - used+=info->s->base.pack_reclength; - break; - case DYNAMIC_RECORD: - flag=block_info.second_read=0; - block_info.next_filepos=pos; - do + + if (start_block & (MARIA_DYN_ALIGN_SIZE-1)) { - if (_ma_read_cache(¶m->read_cache,(byte*) block_info.header, - (start_block=block_info.next_filepos), - sizeof(block_info.header), - (flag ? 0 : READING_NEXT) | READING_HEADER)) - goto err; - if (start_block & (MARIA_DYN_ALIGN_SIZE-1)) - { - _ma_check_print_error(param,"Wrong aligned block at %s", - llstr(start_block,llbuff)); - goto err2; - } - b_type= _ma_get_block_info(&block_info,-1,start_block); - if (b_type & (BLOCK_DELETED | BLOCK_ERROR | BLOCK_SYNC_ERROR | - BLOCK_FATAL_ERROR)) - { - if (b_type & BLOCK_SYNC_ERROR) - { - if (flag) - { - _ma_check_print_error(param,"Unexpected byte: %d at link: %s", - (int) block_info.header[0], - llstr(start_block,llbuff)); - goto err2; - } - pos=block_info.filepos+block_info.block_len; - goto next; - } - if (b_type & BLOCK_DELETED) - { - if (block_info.block_len < info->s->base.min_block_length) - { - _ma_check_print_error(param, - "Deleted block with impossible length %lu at %s", - block_info.block_len,llstr(pos,llbuff)); - goto err2; - } - if ((block_info.next_filepos != HA_OFFSET_ERROR && - block_info.next_filepos >= info->state->data_file_length) || - (block_info.prev_filepos != HA_OFFSET_ERROR && - block_info.prev_filepos >= info->state->data_file_length)) - { - _ma_check_print_error(param,"Delete link points outside datafile at %s", - llstr(pos,llbuff)); - goto err2; - } - del_blocks++; - del_length+=block_info.block_len; - pos=block_info.filepos+block_info.block_len; - splits++; - goto next; - } - _ma_check_print_error(param,"Wrong bytesec: %d-%d-%d at linkstart: %s", - block_info.header[0],block_info.header[1], - block_info.header[2], - llstr(start_block,llbuff)); - goto err2; - } - if (info->state->data_file_length < block_info.filepos+ - block_info.block_len) - { - _ma_check_print_error(param, - "Recordlink that points outside datafile at %s", - llstr(pos,llbuff)); - got_error=1; - break; - } - splits++; - if (!flag++) /* First block */ - { - start_recpos=pos; - pos=block_info.filepos+block_info.block_len; - if (block_info.rec_len > (uint) info->s->base.max_pack_length) - { - _ma_check_print_error(param,"Found too long record (%lu) at %s", - (ulong) block_info.rec_len, - llstr(start_recpos,llbuff)); - got_error=1; - break; - } - if (info->s->base.blobs) - { - if (!(to= _ma_alloc_rec_buff(info, block_info.rec_len, - &info->rec_buff))) - { - _ma_check_print_error(param, - "Not enough memory (%lu) for blob at %s", - (ulong) block_info.rec_len, - llstr(start_recpos,llbuff)); - got_error=1; - break; - } - } - else - to= info->rec_buff; - left_length=block_info.rec_len; - } - if (left_length < block_info.data_len) - { - _ma_check_print_error(param,"Found too long record (%lu) at %s", - (ulong) block_info.data_len, - llstr(start_recpos,llbuff)); - got_error=1; - break; - } - if (_ma_read_cache(¶m->read_cache,(byte*) to,block_info.filepos, - (uint) block_info.data_len, - flag == 1 ? READING_NEXT : 0)) - goto err; - to+=block_info.data_len; - link_used+= block_info.filepos-start_block; - used+= block_info.filepos - start_block + block_info.data_len; - empty+=block_info.block_len-block_info.data_len; - left_length-=block_info.data_len; - if (left_length) - { - if (b_type & BLOCK_LAST) - { - _ma_check_print_error(param, - "Wrong record length %s of %s at %s", - llstr(block_info.rec_len-left_length,llbuff), - llstr(block_info.rec_len, llbuff2), - llstr(start_recpos,llbuff3)); - got_error=1; - break; - } - if (info->state->data_file_length < block_info.next_filepos) - { - _ma_check_print_error(param, - "Found next-recordlink that points outside datafile at %s", - llstr(block_info.filepos,llbuff)); - got_error=1; - break; - } - } - } while (left_length); - if (! got_error) + _ma_check_print_error(param,"Wrong aligned block at %s", + llstr(start_block,llbuff)); + DBUG_RETURN(1); + } + b_type= _ma_get_block_info(&block_info,-1,start_block); + if (b_type & (BLOCK_DELETED | BLOCK_ERROR | BLOCK_SYNC_ERROR | + BLOCK_FATAL_ERROR)) { - if (_ma_rec_unpack(info,record,info->rec_buff,block_info.rec_len) == - MY_FILE_ERROR) - { - _ma_check_print_error(param,"Found wrong record at %s", - llstr(start_recpos,llbuff)); - got_error=1; - } - else - { - info->checksum=_ma_checksum(info,record); - if (param->testflag & (T_EXTEND | T_MEDIUM | T_VERBOSE)) - { - if (_ma_rec_check(info,record, info->rec_buff,block_info.rec_len, - test(info->s->calc_checksum))) - { - _ma_check_print_error(param,"Found wrong packed record at %s", - llstr(start_recpos,llbuff)); - got_error=1; - } - } - if (!got_error) - param->glob_crc+= info->checksum; - } + if (b_type & BLOCK_SYNC_ERROR) + { + if (flag) + { + _ma_check_print_error(param,"Unexpected byte: %d at link: %s", + (int) block_info.header[0], + llstr(start_block,llbuff)); + DBUG_RETURN(1); + } + pos=block_info.filepos+block_info.block_len; + goto next; + } + if (b_type & BLOCK_DELETED) + { + if (block_info.block_len < info->s->base.min_block_length) + { + _ma_check_print_error(param, + "Deleted block with impossible length %lu at %s", + block_info.block_len,llstr(pos,llbuff)); + DBUG_RETURN(1); + } + if ((block_info.next_filepos != HA_OFFSET_ERROR && + block_info.next_filepos >= info->state->data_file_length) || + (block_info.prev_filepos != HA_OFFSET_ERROR && + block_info.prev_filepos >= info->state->data_file_length)) + { + _ma_check_print_error(param,"Delete link points outside datafile at %s", + llstr(pos,llbuff)); + DBUG_RETURN(1); + } + param->del_blocks++; + param->del_length+= block_info.block_len; + param->splits++; + pos= block_info.filepos+block_info.block_len; + goto next; + } + _ma_check_print_error(param,"Wrong bytesec: %d-%d-%d at linkstart: %s", + block_info.header[0],block_info.header[1], + block_info.header[2], + llstr(start_block,llbuff)); + DBUG_RETURN(1); } - else if (!flag) - pos=block_info.filepos+block_info.block_len; - break; - case COMPRESSED_RECORD: - if (_ma_read_cache(¶m->read_cache,(byte*) block_info.header, pos, - info->s->pack.ref_length, READING_NEXT)) - goto err; - start_recpos=pos; - splits++; - VOID(_ma_pack_get_block_info(info,&block_info, -1, start_recpos)); - pos=block_info.filepos+block_info.rec_len; - if (block_info.rec_len < (uint) info->s->min_pack_length || - block_info.rec_len > (uint) info->s->max_pack_length) + if (info->state->data_file_length < block_info.filepos+ + block_info.block_len) { - _ma_check_print_error(param, - "Found block with wrong recordlength: %d at %s", - block_info.rec_len, llstr(start_recpos,llbuff)); - got_error=1; - break; + _ma_check_print_error(param, + "Recordlink that points outside datafile at %s", + llstr(pos,llbuff)); + got_error=1; + break; } - if (_ma_read_cache(¶m->read_cache,(byte*) info->rec_buff, - block_info.filepos, block_info.rec_len, READING_NEXT)) - goto err; - if (_ma_pack_rec_unpack(info,record,info->rec_buff,block_info.rec_len)) + param->splits++; + if (!flag++) /* First block */ { - _ma_check_print_error(param,"Found wrong record at %s", - llstr(start_recpos,llbuff)); - got_error=1; + start_recpos=pos; + pos=block_info.filepos+block_info.block_len; + if (block_info.rec_len > (uint) info->s->base.max_pack_length) + { + _ma_check_print_error(param,"Found too long record (%lu) at %s", + (ulong) block_info.rec_len, + llstr(start_recpos,llbuff)); + got_error=1; + break; + } + if (info->s->base.blobs) + { + if (_ma_alloc_buffer(&info->rec_buff, &info->rec_buff_size, + block_info.rec_len + + info->s->base.extra_rec_buff_size)) + + { + _ma_check_print_error(param, + "Not enough memory (%lu) for blob at %s", + (ulong) block_info.rec_len, + llstr(start_recpos,llbuff)); + got_error=1; + break; + } + } + to= info->rec_buff; + left_length= block_info.rec_len; + } + if (left_length < block_info.data_len) + { + _ma_check_print_error(param,"Found too long record (%lu) at %s", + (ulong) block_info.data_len, + llstr(start_recpos,llbuff)); + got_error=1; + break; + } + if (_ma_read_cache(¶m->read_cache,(byte*) to,block_info.filepos, + (uint) block_info.data_len, + flag == 1 ? READING_NEXT : 0)) + { + _ma_check_print_error(param, + "got error: %d when reading datafile at position: %s", my_errno, llstr(block_info.filepos, llbuff)); + + DBUG_RETURN(1); + } + to+=block_info.data_len; + param->link_used+= block_info.filepos-start_block; + param->used+= block_info.filepos - start_block + block_info.data_len; + param->empty+= block_info.block_len-block_info.data_len; + left_length-= block_info.data_len; + if (left_length) + { + if (b_type & BLOCK_LAST) + { + _ma_check_print_error(param, + "Wrong record length %s of %s at %s", + llstr(block_info.rec_len-left_length,llbuff), + llstr(block_info.rec_len, llbuff2), + llstr(start_recpos,llbuff3)); + got_error=1; + break; + } + if (info->state->data_file_length < block_info.next_filepos) + { + _ma_check_print_error(param, + "Found next-recordlink that points outside datafile at %s", + llstr(block_info.filepos,llbuff)); + got_error=1; + break; + } + } + } while (left_length); + + if (! got_error) + { + if (_ma_rec_unpack(info,record,info->rec_buff,block_info.rec_len) == + MY_FILE_ERROR) + { + _ma_check_print_error(param,"Found wrong record at %s", + llstr(start_recpos,llbuff)); + got_error=1; + } + else + { + info->cur_row.checksum= _ma_checksum(info,record); + if (param->testflag & (T_EXTEND | T_MEDIUM | T_VERBOSE)) + { + if (_ma_rec_check(info,record, info->rec_buff,block_info.rec_len, + test(info->s->calc_checksum))) + { + _ma_check_print_error(param,"Found wrong packed record at %s", + llstr(start_recpos,llbuff)); + got_error= 1; + } + } + param->glob_crc+= info->cur_row.checksum; + } + + if (! got_error) + { + if (check_keys_in_record(param, info, extend, start_recpos, record)) + DBUG_RETURN(1); } - if (static_row_size) - param->glob_crc+= _ma_static_checksum(info,record); else - param->glob_crc+= _ma_checksum(info,record); - link_used+= (block_info.filepos - start_recpos); - used+= (pos-start_recpos); - } /* switch */ + { + if (param->err_count++ > MAXERR || !(param->testflag & T_VERBOSE)) + DBUG_RETURN(1); + } + } + else if (!flag) + pos= block_info.filepos+block_info.block_len; +next:; + } + DBUG_RETURN(0); +} + + +static int check_compressed_record(HA_CHECK *param, MARIA_HA *info, int extend, + byte *record) +{ + my_off_t start_recpos, pos; + char llbuff[22]; + bool got_error= 0; + MARIA_BLOCK_INFO block_info; + DBUG_ENTER("check_compressed_record"); + + pos= info->s->pack.header_length; /* Skip header */ + while (pos < info->state->data_file_length) + { + if (*_ma_killed_ptr(param)) + DBUG_RETURN(-1); + + if (_ma_read_cache(¶m->read_cache,(byte*) block_info.header, pos, + info->s->pack.ref_length, READING_NEXT)) + { + _ma_check_print_error(param, + "got error: %d when reading datafile at position: %s", + my_errno, llstr(pos, llbuff)); + DBUG_RETURN(1); + } + + start_recpos= pos; + param->splits++; + VOID(_ma_pack_get_block_info(info,&block_info, -1, start_recpos)); + pos=block_info.filepos+block_info.rec_len; + if (block_info.rec_len < (uint) info->s->min_pack_length || + block_info.rec_len > (uint) info->s->max_pack_length) + { + _ma_check_print_error(param, + "Found block with wrong recordlength: %d at %s", + block_info.rec_len, llstr(start_recpos,llbuff)); + got_error=1; + goto end; + } + if (_ma_read_cache(¶m->read_cache,(byte*) info->rec_buff, + block_info.filepos, block_info.rec_len, READING_NEXT)) + { + _ma_check_print_error(param, + "got error: %d when reading datafile at position: %s", + my_errno, llstr(block_info.filepos, llbuff)); + DBUG_RETURN(1); + } + if (_ma_pack_rec_unpack(info,record,info->rec_buff,block_info.rec_len)) + { + _ma_check_print_error(param,"Found wrong record at %s", + llstr(start_recpos,llbuff)); + got_error=1; + goto end; + } + param->glob_crc+= (*info->s->calc_checksum)(info,record); + param->link_used+= (block_info.filepos - start_recpos); + param->used+= (pos-start_recpos); + +end: if (! got_error) { - intern_record_checksum+=(ha_checksum) start_recpos; - records++; - if (param->testflag & T_WRITE_LOOP && records % WRITE_COUNT == 0) + if (check_keys_in_record(param, info, extend, start_recpos, record)) + DBUG_RETURN(1); + } + else + { + got_error= 0; /* Reset for next loop */ + if (param->err_count++ > MAXERR || !(param->testflag & T_VERBOSE)) + DBUG_RETURN(1); + } + } + DBUG_RETURN(0); +} + + +/* + Check if layout on a page is ok +*/ + +static int check_page_layout(HA_CHECK *param, MARIA_HA *info, + my_off_t page_pos, byte *page, + uint row_count, uint head_empty, + uint *real_rows_found) +{ + uint empty, last_row_end, row, first_dir_entry; + byte *dir_entry; + char llbuff[22]; + DBUG_ENTER("check_page_layout"); + + empty= 0; + last_row_end= PAGE_HEADER_SIZE; + *real_rows_found= 0; + + dir_entry= page+ info->s->block_size - PAGE_SUFFIX_SIZE; + first_dir_entry= info->s->block_size - row_count* DIR_ENTRY_SIZE; + for (row= 0 ; row < row_count ; row++) + { + uint pos, length; + dir_entry-= DIR_ENTRY_SIZE; + pos= uint2korr(dir_entry); + if (!pos) + { + if (row == row_count -1) { - printf("%s\r", llstr(records,llbuff)); VOID(fflush(stdout)); + _ma_check_print_error(param, + "Page %9s: First entry in directory is 0", + llstr(page_pos, llbuff)); + if (param->err_count++ > MAXERR || !(param->testflag & T_VERBOSE)) + DBUG_RETURN(1); } + continue; /* Deleted row */ + } + (*real_rows_found)++; + length= uint2korr(dir_entry+2); + param->used+= length; + if (pos < last_row_end) + { + _ma_check_print_error(param, + "Page %9s: Row %3u overlapps with previous row", + llstr(page_pos, llbuff), row); + DBUG_RETURN(1); + } + empty+= (pos - last_row_end); + last_row_end= pos + length; + if (last_row_end > first_dir_entry) + { + _ma_check_print_error(param, + "Page %9s: Row %3u overlapps with directory", + llstr(page_pos, llbuff), row); + DBUG_RETURN(1); + } + } + empty+= (first_dir_entry - last_row_end); + + if (empty != head_empty) + { + _ma_check_print_error(param, + "Page %9s: Wrong empty size. Stored: %5u Actual: %5u", + llstr(page_pos, llbuff), head_empty, empty); + DBUG_RETURN(param->err_count++ > MAXERR || !(param->testflag & T_VERBOSE)); + } + DBUG_RETURN(0); +} + + +/* + Check all rows on head page + + NOTES + Before this, we have already called check_page_layout(), so + we know the block is logicaly correct (even if the rows may not be that) + + RETURN + 0 ok + 1 error +*/ - /* Check if keys match the record */ - for (key=0,keyinfo= info->s->keyinfo; key < info->s->base.keys; - key++,keyinfo++) +static my_bool check_head_page(HA_CHECK *param, MARIA_HA *info, byte *record, + int extend, my_off_t page_pos, byte *page_buff, + uint row_count) +{ + byte *dir_entry; + uint row; + char llbuff[22], llbuff2[22]; + DBUG_ENTER("check_head_page"); + + dir_entry= page_buff+ info->s->block_size - PAGE_SUFFIX_SIZE; + for (row= 0 ; row < row_count ; row++) + { + uint pos, length, flag; + dir_entry-= DIR_ENTRY_SIZE; + pos= uint2korr(dir_entry); + if (!pos) + continue; + length= uint2korr(dir_entry+2); + if (length < info->s->base.min_block_length) + { + _ma_check_print_error(param, + "Page %9s: Row %3u is too short (%d bytes)", + llstr(page_pos, llbuff), row, length); + DBUG_RETURN(1); + } + flag= (uint) (uchar) page_buff[pos]; + if (flag & ~(ROW_FLAG_ALL)) + _ma_check_print_error(param, + "Page %9s: Row %3u has wrong flag: %d", + llstr(page_pos, llbuff), row, flag); + + DBUG_PRINT("info", ("rowid: %s page: %lu row: %u", + llstr(ma_recordpos(page_pos/info->s->block_size, row), + llbuff), + (ulong) (page_pos / info->s->block_size), row)); + if (_ma_read_block_record2(info, record, page_buff+pos, + page_buff+pos+length)) + { + _ma_check_print_error(param, + "Page %9s: Row %3d is crashed", + llstr(page_pos, llbuff), row); + if (param->err_count++ > MAXERR || !(param->testflag & T_VERBOSE)) + DBUG_RETURN(1); + continue; + } + if (info->s->calc_checksum) + { + info->cur_row.checksum= _ma_checksum(info, record); + param->glob_crc+= info->cur_row.checksum; + } + if (info->cur_row.extents_count) + { + byte *extents= info->cur_row.extents; + uint i; + /* Check that bitmap has the right marker for the found extents */ + for (i= 0 ; i < info->cur_row.extents_count ; i++) { - if (maria_is_key_active(info->s->state.key_map, key)) - { - if(!(keyinfo->flag & HA_FULLTEXT)) - { - uint key_length= _ma_make_key(info,key,info->lastkey,record, - start_recpos); - if (extend) - { - /* We don't need to lock the key tree here as we don't allow - concurrent threads when running mariachk - */ - int search_result= -#ifdef HAVE_RTREE_KEYS - (keyinfo->flag & HA_SPATIAL) ? - maria_rtree_find_first(info, key, info->lastkey, key_length, - MBR_EQUAL | MBR_DATA) : -#endif - _ma_search(info,keyinfo,info->lastkey,key_length, - SEARCH_SAME, info->s->state.key_root[key]); - if (search_result) - { - _ma_check_print_error(param,"Record at: %10s Can't find key for index: %2d", - llstr(start_recpos,llbuff),key+1); - if (error++ > MAXERR || !(param->testflag & T_VERBOSE)) - goto err2; - } - } - else - key_checksum[key]+=maria_byte_checksum((byte*) info->lastkey, - key_length); - } - } + uint page, page_count, page_type; + page= uint5korr(extents); + page_count= uint2korr(extents+5); + extents+= ROW_EXTENT_SIZE; + page_type= BLOB_PAGE; + if (page_count & TAIL_BIT) + { + page_count= 1; + page_type= TAIL_PAGE; + } + for ( ; page_count--; page++) + { + uint bitmap_pattern; + if (_ma_check_if_right_bitmap_type(info, page_type, page, + &bitmap_pattern)) + { + _ma_check_print_error(param, + "Page %9s: Row: %3d has an extent with wrong information in bitmap: Page %9s Page_type: %d Bitmap: %d", + llstr(page_pos, llbuff), row, + llstr(page * info->s->bitmap.block_size, + llbuff2), + page_type, + bitmap_pattern); + if (param->err_count++ > MAXERR || !(param->testflag & T_VERBOSE)) + DBUG_RETURN(1); + } + } } } - else + param->full_page_count+= info->cur_row.full_page_count; + param->tail_count+= info->cur_row.tail_count; + if (check_keys_in_record(param, info, extend, + ma_recordpos(page_pos/info->s->block_size, row), + record)) + DBUG_RETURN(1); + } + DBUG_RETURN(0); +} + + + +static int check_block_record(HA_CHECK *param, MARIA_HA *info, int extend, + byte *record) +{ + my_off_t pos; + byte *page_buff, *bitmap_buff, *data; + char llbuff[22], llbuff2[22]; + uint block_size= info->s->block_size; + ha_rows full_page_count, tail_count; + my_bool full_dir; + uint offset_page, offset; + + if (_ma_scan_init_block_record(info)) + { + _ma_check_print_error(param, "got error %d when initializing scan", + my_errno); + return 1; + } + bitmap_buff= info->scan.bitmap_buff; + page_buff= info->scan.page_buff; + full_page_count= tail_count= 0; + param->full_page_count= param->tail_count= 0; + param->used= param->link_used= 0; + + for (pos= 0; + pos < info->state->data_file_length; + pos+= block_size) + { + uint row_count, real_row_count, empty_space, page_type, bitmap_pattern; + LINT_INIT(row_count); + LINT_INIT(empty_space); + + if (*_ma_killed_ptr(param)) + { + _ma_scan_end_block_record(info); + return -1; + } + if (((pos / block_size) % info->s->bitmap.pages_covered) == 0) + { + /* Bitmap page */ + if (_ma_read_cache(¶m->read_cache, bitmap_buff, pos, + block_size, READING_NEXT)) + { + _ma_check_print_error(param, + "Page %9s: Got error: %d when reading datafile", + my_errno, llstr(pos, llbuff)); + goto err; + } + param->used+= block_size; + param->link_used+= block_size; + continue; + } + /* Skip pages marked as empty in bitmap */ + offset_page= (((pos / block_size) % info->s->bitmap.pages_covered) -1) * 3; + offset= offset_page & 7; + data= bitmap_buff + offset_page / 8; + bitmap_pattern= uint2korr(data); + param->splits++; + if (!((bitmap_pattern >> offset) & 7)) + { + param->empty+= block_size; + param->del_blocks++; + continue; + } + + if (_ma_read_cache(¶m->read_cache, page_buff, pos, + block_size, READING_NEXT)) + { + _ma_check_print_error(param, + "Page %9s: Got error: %d when reading datafile", + my_errno, llstr(pos, llbuff)); + goto err; + } + page_type= page_buff[PAGE_TYPE_OFFSET] & PAGE_TYPE_MASK; + if (page_type == UNALLOCATED_PAGE || page_type >= MAX_PAGE_TYPE) + { + _ma_check_print_error(param, + "Page %9s: Found wrong page type %d\n", + llstr(pos, llbuff), page_type); + if (param->err_count++ > MAXERR || !(param->testflag & T_VERBOSE)) + goto err; + } + switch ((enum en_page_type) page_type) { + case UNALLOCATED_PAGE: + case MAX_PAGE_TYPE: + DBUG_PRINT("warning", + ("Found page with wrong page type: %d", page_type)); + DBUG_ASSERT(0); + break; + case HEAD_PAGE: + row_count= ((uchar*) page_buff)[DIR_ENTRY_OFFSET]; + empty_space= uint2korr(page_buff + EMPTY_SPACE_OFFSET); + param->used+= (PAGE_HEADER_SIZE + PAGE_SUFFIX_SIZE + + row_count * DIR_ENTRY_SIZE); + param->link_used+= (PAGE_HEADER_SIZE + PAGE_SUFFIX_SIZE + + row_count * DIR_ENTRY_SIZE); + full_dir= row_count == MAX_ROWS_PER_PAGE; + break; + case TAIL_PAGE: + row_count= ((uchar*) page_buff)[DIR_ENTRY_OFFSET]; + empty_space= uint2korr(page_buff + EMPTY_SPACE_OFFSET); + param->used+= (PAGE_HEADER_SIZE + PAGE_SUFFIX_SIZE + + row_count * DIR_ENTRY_SIZE); + param->link_used+= (PAGE_HEADER_SIZE + PAGE_SUFFIX_SIZE + + row_count * DIR_ENTRY_SIZE); + full_dir= row_count == MAX_ROWS_PER_PAGE; + break; + case BLOB_PAGE: + full_page_count++; + full_dir= 0; + empty_space= block_size; /* for error reporting */ + param->link_used+= (LSN_SIZE + PAGE_TYPE_SIZE); + param->used+= block_size; + break; + } + if (_ma_check_bitmap_data(info, page_type, pos / block_size, + full_dir ? 0 : empty_space, + &bitmap_pattern)) + { + _ma_check_print_error(param, + "Page %9s: Wrong data in bitmap. Page_type: %d empty_space: %u Bitmap: %d", + llstr(pos, llbuff), page_type, empty_space, + bitmap_pattern); + if (param->err_count++ > MAXERR || !(param->testflag & T_VERBOSE)) + goto err; + } + if ((enum en_page_type) page_type == BLOB_PAGE) + continue; + param->empty+= empty_space; + if (check_page_layout(param, info, pos, page_buff, row_count, + empty_space, &real_row_count)) + goto err; + if ((enum en_page_type) page_type == TAIL_PAGE) { - got_error=0; - if (error++ > MAXERR || !(param->testflag & T_VERBOSE)) - goto err2; + tail_count+= real_row_count; + continue; } - next:; /* Next record */ + if (check_head_page(param, info, record, extend, pos, page_buff, + row_count)) + goto err; } + + _ma_scan_end_block_record(info); + + if (full_page_count != param->full_page_count) + _ma_check_print_error(param, "Full page count read through records was %s but we found %s pages while scanning table", + llstr(param->full_page_count, llbuff), + llstr(full_page_count, llbuff2)); + if (tail_count != param->tail_count) + _ma_check_print_error(param, "Tail count read through records was %s but we found %s tails while scanning table", + llstr(param->tail_count, llbuff), + llstr(tail_count, llbuff2)); + + /* Update splits to avoid warning */ + info->s->state.split= param->splits; + info->state->del= param->del_blocks; + return param->error_printed != 0; + +err: + _ma_scan_end_block_record(info); + return 1; +} + + + /* Check that record-link is ok */ + +int maria_chk_data_link(HA_CHECK *param, MARIA_HA *info,int extend) +{ + int error; + byte *record; + char llbuff[22],llbuff2[22],llbuff3[22]; + DBUG_ENTER("maria_chk_data_link"); + + if (!(param->testflag & T_SILENT)) + { + if (extend) + puts("- check records and index references"); + else + puts("- check record links"); + } + + if (!(record= (byte*) my_malloc(info->s->base.pack_reclength,MYF(0)))) + { + _ma_check_print_error(param,"Not enough memory for record"); + DBUG_RETURN(-1); + } + param->records= param->del_blocks= 0; + param->used= param->link_used= param->splits= param->del_length= 0; + param->tmp_record_checksum= param->glob_crc= 0; + param->err_count= 0; + LINT_INIT(left_length); LINT_INIT(start_recpos); LINT_INIT(to); + error= 0; + param->empty= info->s->pack.header_length; + + bzero((char*) param->tmp_key_crc, + info->s->base.keys * sizeof(param->tmp_key_crc[0])); + + switch (info->s->data_file_type) { + case BLOCK_RECORD: + error= check_block_record(param, info, extend, record); + break; + case STATIC_RECORD: + error= check_static_record(param, info, extend, record); + break; + case DYNAMIC_RECORD: + error= check_dynamic_record(param, info, extend, record); + break; + case COMPRESSED_RECORD: + error= check_compressed_record(param, info, extend, record); + break; + } /* switch */ + + if (error) + goto err; + if (param->testflag & T_WRITE_LOOP) { VOID(fputs(" \r",stdout)); VOID(fflush(stdout)); } - if (records != info->state->records) + if (param->records != info->state->records) { - _ma_check_print_error(param,"Record-count is not ok; is %-10s Should be: %s", - llstr(records,llbuff), llstr(info->state->records,llbuff2)); + _ma_check_print_error(param, + "Record-count is not ok; found %-10s Should be: %s", + llstr(param->records,llbuff), + llstr(info->state->records,llbuff2)); error=1; } else if (param->record_checksum && - param->record_checksum != intern_record_checksum) + param->record_checksum != param->tmp_record_checksum) { _ma_check_print_error(param, - "Keypointers and record positions doesn't match"); + "Key pointers and record positions doesn't match"); error=1; } else if (param->glob_crc != info->state->checksum && @@ -1213,9 +1702,10 @@ int maria_chk_data_link(HA_CHECK *param, MARIA_HA *info,int extend) } else if (!extend) { + uint key; for (key=0 ; key < info->s->base.keys; key++) { - if (key_checksum[key] != param->key_crc[key] && + if (param->tmp_key_crc[key] != param->key_crc[key] && !(info->s->keyinfo[key].flag & (HA_FULLTEXT | HA_SPATIAL))) { _ma_check_print_error(param,"Checksum for key: %2d doesn't match checksum for records", @@ -1225,68 +1715,83 @@ int maria_chk_data_link(HA_CHECK *param, MARIA_HA *info,int extend) } } - if (del_length != info->state->empty) + if (param->del_length != info->state->empty) { _ma_check_print_warning(param, "Found %s deleted space. Should be %s", - llstr(del_length,llbuff2), + llstr(param->del_length,llbuff2), llstr(info->state->empty,llbuff)); } - if (used+empty+del_length != info->state->data_file_length) + if (param->used + param->empty + param->del_length != + info->state->data_file_length) { _ma_check_print_warning(param, - "Found %s record-data and %s unused data and %s deleted-data", - llstr(used,llbuff),llstr(empty,llbuff2), - llstr(del_length,llbuff3)); + "Found %s record data and %s unused data and %s deleted data", + llstr(param->used, llbuff), + llstr(param->empty,llbuff2), + llstr(param->del_length,llbuff3)); _ma_check_print_warning(param, - "Total %s, Should be: %s", - llstr((used+empty+del_length),llbuff), + "Total %s Should be: %s", + llstr((param->used+param->empty+param->del_length), + llbuff), llstr(info->state->data_file_length,llbuff2)); } - if (del_blocks != info->state->del) + if (param->del_blocks != info->state->del) { _ma_check_print_warning(param, "Found %10s deleted blocks Should be: %s", - llstr(del_blocks,llbuff), + llstr(param->del_blocks,llbuff), llstr(info->state->del,llbuff2)); } - if (splits != info->s->state.split) + if (param->splits != info->s->state.split) { _ma_check_print_warning(param, "Found %10s parts Should be: %s parts", - llstr(splits,llbuff), + llstr(param->splits, llbuff), llstr(info->s->state.split,llbuff2)); } if (param->testflag & T_INFO) { if (param->warning_printed || param->error_printed) puts(""); - if (used != 0 && ! param->error_printed) + if (param->used != 0 && ! param->error_printed) { - printf("Records:%18s M.recordlength:%9lu Packed:%14.0f%%\n", - llstr(records,llbuff), (long)((used-link_used)/records), - (info->s->base.blobs ? 0.0 : - (ulonglong2double((ulonglong) info->s->base.reclength*records)- - my_off_t2double(used))/ - ulonglong2double((ulonglong) info->s->base.reclength*records)*100.0)); - printf("Recordspace used:%9.0f%% Empty space:%12d%% Blocks/Record: %6.2f\n", - (ulonglong2double(used-link_used)/ulonglong2double(used-link_used+empty)*100.0), - (!records ? 100 : (int) (ulonglong2double(del_length+empty)/ - my_off_t2double(used)*100.0)), - ulonglong2double(splits - del_blocks) / records); + if (param->records) + { + printf("Records:%18s M.recordlength:%9lu Packed:%14.0f%%\n", + llstr(param->records,llbuff), + (long)((param->used - param->link_used)/param->records), + (info->s->base.blobs ? 0.0 : + (ulonglong2double((ulonglong) info->s->base.reclength * + param->records)- + my_off_t2double(param->used))/ + ulonglong2double((ulonglong) info->s->base.reclength * + param->records)*100.0)); + printf("Recordspace used:%9.0f%% Empty space:%12d%% Blocks/Record: %6.2f\n", + (ulonglong2double(param->used - param->link_used)/ + ulonglong2double(param->used-param->link_used+param->empty)*100.0), + (!param->records ? 100 : + (int) (ulonglong2double(param->del_length+param->empty)/ + my_off_t2double(param->used)*100.0)), + ulonglong2double(param->splits - param->del_blocks) / + param->records); + } + else + printf("Records:%18s\n", "0"); } printf("Record blocks:%12s Delete blocks:%10s\n", - llstr(splits-del_blocks,llbuff),llstr(del_blocks,llbuff2)); + llstr(param->splits - param->del_blocks, llbuff), + llstr(param->del_blocks, llbuff2)); printf("Record data: %12s Deleted data: %10s\n", - llstr(used-link_used,llbuff),llstr(del_length,llbuff2)); + llstr(param->used - param->link_used,llbuff), + llstr(param->del_length, llbuff2)); printf("Lost space: %12s Linkdata: %10s\n", - llstr(empty,llbuff),llstr(link_used,llbuff2)); + llstr(param->empty, llbuff),llstr(param->link_used, llbuff2)); } my_free((gptr) record,MYF(0)); DBUG_RETURN (error); + err: - _ma_check_print_error(param,"got error: %d when reading datafile at record: %s",my_errno, llstr(records,llbuff)); - err2: my_free((gptr) record,MYF(0)); param->testflag|=T_RETRY_WITHOUT_QUICK; DBUG_RETURN(1); @@ -1297,7 +1802,7 @@ int maria_chk_data_link(HA_CHECK *param, MARIA_HA *info,int extend) /* Save new datafile-name in temp_filename */ int maria_repair(HA_CHECK *param, register MARIA_HA *info, - my_string name, int rep_quick) + my_string name, int rep_quick) { int error,got_error; uint i; @@ -1348,7 +1853,8 @@ int maria_repair(HA_CHECK *param, register MARIA_HA *info, info->opt_flag|=WRITE_CACHE_USED; if (!(sort_param.record=(byte*) my_malloc((uint) share->base.pack_reclength, MYF(0))) || - !_ma_alloc_rec_buff(info, -1, &sort_param.rec_buff)) + _ma_alloc_buffer(&sort_param.rec_buff, &sort_param.rec_buff_size, + info->s->base.default_rec_buff_size)) { _ma_check_print_error(param, "Not enough memory for extra record"); goto err; @@ -1357,14 +1863,11 @@ int maria_repair(HA_CHECK *param, register MARIA_HA *info, if (!rep_quick) { /* Get real path for data file */ - if ((new_file=my_raid_create(fn_format(param->temp_filename, - share->data_file_name, "", - DATA_TMP_EXT, 2+4), - 0,param->tmpfile_createflag, - share->base.raid_type, - share->base.raid_chunks, - share->base.raid_chunksize, - MYF(0))) < 0) + if ((new_file= my_create(fn_format(param->temp_filename, + share->data_file_name, "", + DATA_TMP_EXT, 2+4), + 0,param->tmpfile_createflag, + MYF(0))) < 0) { _ma_check_print_error(param,"Can't create new tempfile: '%s'", param->temp_filename); @@ -1376,10 +1879,7 @@ int maria_repair(HA_CHECK *param, register MARIA_HA *info, info->s->state.dellink= HA_OFFSET_ERROR; info->rec_cache.file=new_file; if (param->testflag & T_UNPACK) - { - share->options&= ~HA_OPTION_COMPRESS_RECORD; - mi_int2store(share->state.header.options,share->options); - } + restore_data_file_type(share); } sort_info.info=info; sort_info.param = param; @@ -1411,8 +1911,7 @@ int maria_repair(HA_CHECK *param, register MARIA_HA *info, share->state.key_root[i]= HA_OFFSET_ERROR; /* Drop the delete chain. */ - for (i=0 ; i < share->state.header.max_block_size_index ; i++) - share->state.key_del[i]= HA_OFFSET_ERROR; + share->state.key_del= HA_OFFSET_ERROR; /* If requested, activate (enable) all keys in key_map. In this case, @@ -1436,7 +1935,7 @@ int maria_repair(HA_CHECK *param, register MARIA_HA *info, _ma_check_print_info(param,"Duplicate key %2d for record at %10s against new record at %10s", info->errkey+1, llstr(sort_param.start_recpos,llbuff), - llstr(info->dupp_key_pos,llbuff2)); + llstr(info->dup_key_pos,llbuff2)); if (param->testflag & T_VERBOSE) { VOID(_ma_make_key(info,(uint) info->errkey,info->lastkey, @@ -1530,8 +2029,7 @@ err: my_close(new_file,MYF(0)); info->dfile=new_file= -1; if (maria_change_to_newfile(share->data_file_name,MARIA_NAME_DEXT, - DATA_TMP_EXT, share->base.raid_chunks, - (param->testflag & T_BACKUP_DATA ? + DATA_TMP_EXT, (param->testflag & T_BACKUP_DATA ? MYF(MY_REDEL_MAKE_BACKUP): MYF(0))) || _ma_open_datafile(info,share,-1)) got_error=1; @@ -1545,26 +2043,20 @@ err: if (new_file >= 0) { VOID(my_close(new_file,MYF(0))); - VOID(my_raid_delete(param->temp_filename,info->s->base.raid_chunks, - MYF(MY_WME))); + VOID(my_delete(param->temp_filename, MYF(MY_WME))); info->rec_cache.file=-1; /* don't flush data to new_file, it's closed */ } maria_mark_crashed_on_repair(info); } - my_free(_ma_get_rec_buff_ptr(info, sort_param.rec_buff), - MYF(MY_ALLOW_ZERO_PTR)); + my_free(sort_param.rec_buff, MYF(MY_ALLOW_ZERO_PTR)); my_free(sort_param.record,MYF(MY_ALLOW_ZERO_PTR)); my_free(sort_info.buff,MYF(MY_ALLOW_ZERO_PTR)); VOID(end_io_cache(¶m->read_cache)); info->opt_flag&= ~(READ_CACHE_USED | WRITE_CACHE_USED); VOID(end_io_cache(&info->rec_cache)); got_error|=_ma_flush_blocks(param, share->key_cache, share->kfile); - if (!got_error && param->testflag & T_UNPACK) - { - share->state.header.options[0]&= (uchar) ~HA_OPTION_COMPRESS_RECORD; - share->pack.header_length=0; - share->data_file_type=sort_info.new_data_file_type; - } + if (!got_error && (param->testflag & T_UNPACK)) + restore_data_file_type(share); share->state.changed|= (STATE_NOT_OPTIMIZED_KEYS | STATE_NOT_SORTED_PAGES | STATE_NOT_ANALYZED); DBUG_RETURN(got_error); @@ -1577,10 +2069,10 @@ static int writekeys(HA_CHECK *param, register MARIA_HA *info, byte *buff, my_off_t filepos) { register uint i; - uchar *key; + byte *key; DBUG_ENTER("writekeys"); - key=info->lastkey+info->s->base.max_key_length; + key= info->lastkey+info->s->base.max_key_length; for (i=0 ; i < info->s->base.keys ; i++) { if (maria_is_key_active(info->s->state.key_map, i)) @@ -1632,7 +2124,7 @@ static int writekeys(HA_CHECK *param, register MARIA_HA *info, byte *buff, } /* Remove checksum that was added to glob_crc in sort_get_next_record */ if (param->calc_checksum) - param->glob_crc-= info->checksum; + param->glob_crc-= info->cur_row.checksum; DBUG_PRINT("error",("errno: %d",my_errno)); DBUG_RETURN(-1); } /* writekeys */ @@ -1640,15 +2132,16 @@ static int writekeys(HA_CHECK *param, register MARIA_HA *info, byte *buff, /* Change all key-pointers that points to a records */ -int maria_movepoint(register MARIA_HA *info, byte *record, my_off_t oldpos, - my_off_t newpos, uint prot_key) +int maria_movepoint(register MARIA_HA *info, byte *record, + MARIA_RECORD_POS oldpos, MARIA_RECORD_POS newpos, + uint prot_key) { register uint i; - uchar *key; + byte *key; uint key_length; DBUG_ENTER("maria_movepoint"); - key=info->lastkey+info->s->base.max_key_length; + key= info->lastkey+info->s->base.max_key_length; for (i=0 ; i < info->s->base.keys; i++) { if (i != prot_key && maria_is_key_active(info->s->state.key_map, i)) @@ -1764,7 +2257,7 @@ int maria_sort_index(HA_CHECK *param, register MARIA_HA *info, my_string name) index_pos[key]= HA_OFFSET_ERROR; /* No blocks */ } - /* Flush key cache for this file if we are calling this outside mariachk */ + /* Flush key cache for this file if we are calling this outside maria_chk */ flush_key_blocks(share->key_cache,share->kfile, FLUSH_IGNORE_CHANGED); share->state.version=(ulong) time((time_t*) 0); @@ -1779,8 +2272,8 @@ int maria_sort_index(HA_CHECK *param, register MARIA_HA *info, my_string name) VOID(my_close(share->kfile,MYF(MY_WME))); share->kfile = -1; VOID(my_close(new_file,MYF(MY_WME))); - if (maria_change_to_newfile(share->index_file_name,MARIA_NAME_IEXT,INDEX_TMP_EXT,0, - MYF(0)) || + if (maria_change_to_newfile(share->index_file_name, MARIA_NAME_IEXT, + INDEX_TMP_EXT, MYF(0)) || _ma_open_keyfile(share)) goto err2; info->lock_type= F_UNLCK; /* Force maria_readinfo to lock */ @@ -1795,8 +2288,7 @@ int maria_sort_index(HA_CHECK *param, register MARIA_HA *info, my_string name) info->update= (short) (HA_STATE_CHANGED | HA_STATE_ROW_CHANGED); for (key=0 ; key < info->s->base.keys ; key++) info->s->state.key_root[key]=index_pos[key]; - for (key=0 ; key < info->s->state.header.max_block_size_index ; key++) - info->s->state.key_del[key]= HA_OFFSET_ERROR; + info->s->state.key_del= HA_OFFSET_ERROR; info->s->state.changed&= ~STATE_NOT_SORTED_PAGES; DBUG_RETURN(0); @@ -1811,12 +2303,13 @@ err2: /* Sort records recursive using one index */ -static int sort_one_index(HA_CHECK *param, MARIA_HA *info, MARIA_KEYDEF *keyinfo, +static int sort_one_index(HA_CHECK *param, MARIA_HA *info, + MARIA_KEYDEF *keyinfo, my_off_t pagepos, File new_file) { uint length,nod_flag,used_length, key_length; - uchar *buff,*keypos,*endpos; - uchar key[HA_MAX_POSSIBLE_KEY_BUFF]; + byte *buff,*keypos,*endpos; + byte key[HA_MAX_POSSIBLE_KEY_BUFF]; my_off_t new_page_pos,next_page; char llbuff[22]; DBUG_ENTER("sort_one_index"); @@ -1824,7 +2317,7 @@ static int sort_one_index(HA_CHECK *param, MARIA_HA *info, MARIA_KEYDEF *keyinfo new_page_pos=param->new_file_pos; param->new_file_pos+=keyinfo->block_length; - if (!(buff=(uchar*) my_alloca((uint) keyinfo->block_length))) + if (!(buff= (byte*) my_alloca((uint) keyinfo->block_length))) { _ma_check_print_error(param,"Not enough memory for key block"); DBUG_RETURN(-1); @@ -1907,9 +2400,7 @@ err: */ int maria_change_to_newfile(const char * filename, const char * old_ext, - const char * new_ext, - uint raid_chunks __attribute__((unused)), - myf MyFlags) + const char * new_ext, myf MyFlags) { char old_filename[FN_REFLEN],new_filename[FN_REFLEN]; #ifdef USE_RAID @@ -1981,7 +2472,7 @@ err: */ int maria_repair_by_sort(HA_CHECK *param, register MARIA_HA *info, - const char * name, int rep_quick) + const char * name, int rep_quick) { int got_error; uint i; @@ -2034,7 +2525,8 @@ int maria_repair_by_sort(HA_CHECK *param, register MARIA_HA *info, if (!(sort_param.record=(byte*) my_malloc((uint) share->base.pack_reclength, MYF(0))) || - !_ma_alloc_rec_buff(info, -1, &sort_param.rec_buff)) + _ma_alloc_buffer(&sort_param.rec_buff, &sort_param.rec_buff_size, + info->s->base.default_rec_buff_size)) { _ma_check_print_error(param, "Not enough memory for extra record"); goto err; @@ -2042,14 +2534,11 @@ int maria_repair_by_sort(HA_CHECK *param, register MARIA_HA *info, if (!rep_quick) { /* Get real path for data file */ - if ((new_file=my_raid_create(fn_format(param->temp_filename, - share->data_file_name, "", - DATA_TMP_EXT, 2+4), - 0,param->tmpfile_createflag, - share->base.raid_type, - share->base.raid_chunks, - share->base.raid_chunksize, - MYF(0))) < 0) + if ((new_file=my_create(fn_format(param->temp_filename, + share->data_file_name, "", + DATA_TMP_EXT, 2+4), + 0,param->tmpfile_createflag, + MYF(0))) < 0) { _ma_check_print_error(param,"Can't create new tempfile: '%s'", param->temp_filename); @@ -2059,10 +2548,7 @@ int maria_repair_by_sort(HA_CHECK *param, register MARIA_HA *info, "datafile-header")) goto err; if (param->testflag & T_UNPACK) - { - share->options&= ~HA_OPTION_COMPRESS_RECORD; - mi_int2store(share->state.header.options,share->options); - } + restore_data_file_type(share); share->state.dellink= HA_OFFSET_ERROR; info->rec_cache.file=new_file; } @@ -2072,14 +2558,13 @@ int maria_repair_by_sort(HA_CHECK *param, register MARIA_HA *info, { /* Flush key cache for this file if we are calling this outside - mariachk + maria_chk */ flush_key_blocks(share->key_cache,share->kfile, FLUSH_IGNORE_CHANGED); /* Clear the pointers to the given rows */ for (i=0 ; i < share->base.keys ; i++) share->state.key_root[i]= HA_OFFSET_ERROR; - for (i=0 ; i < share->state.header.max_block_size_index ; i++) - share->state.key_del[i]= HA_OFFSET_ERROR; + share->state.key_del= HA_OFFSET_ERROR; info->state->key_file_length=share->base.keystart; } else @@ -2191,13 +2676,13 @@ int maria_repair_by_sort(HA_CHECK *param, register MARIA_HA *info, 10*param->sort_buffer_length/sort_param.key_length; } - sort_param.key_read=sort_maria_ft_key_read; - sort_param.key_write=sort_maria_ft_key_write; + sort_param.key_read= sort_maria_ft_key_read; + sort_param.key_write= sort_maria_ft_key_write; } else { - sort_param.key_read=sort_key_read; - sort_param.key_write=sort_key_write; + sort_param.key_read= sort_key_read; + sort_param.key_write= sort_key_write; } if (_ma_create_index_by_sort(&sort_param, @@ -2276,7 +2761,7 @@ int maria_repair_by_sort(HA_CHECK *param, register MARIA_HA *info, skr < share->base.reloc*share->base.min_pack_length) skr=share->base.reloc*share->base.min_pack_length; #endif - if (skr != sort_info.filelength && !info->s->base.raid_type) + if (skr != sort_info.filelength) if (my_chsize(info->dfile,skr,0,MYF(0))) _ma_check_print_warning(param, "Can't change size of datafile, error: %d", @@ -2315,9 +2800,9 @@ err: my_close(new_file,MYF(0)); info->dfile=new_file= -1; if (maria_change_to_newfile(share->data_file_name,MARIA_NAME_DEXT, - DATA_TMP_EXT, share->base.raid_chunks, - (param->testflag & T_BACKUP_DATA ? - MYF(MY_REDEL_MAKE_BACKUP): MYF(0))) || + DATA_TMP_EXT, + (param->testflag & T_BACKUP_DATA ? + MYF(MY_REDEL_MAKE_BACKUP): MYF(0))) || _ma_open_datafile(info,share,-1)) got_error=1; } @@ -2329,8 +2814,7 @@ err: if (new_file >= 0) { VOID(my_close(new_file,MYF(0))); - VOID(my_raid_delete(param->temp_filename,share->base.raid_chunks, - MYF(MY_WME))); + VOID(my_delete(param->temp_filename, MYF(MY_WME))); if (info->dfile == new_file) info->dfile= -1; } @@ -2340,8 +2824,7 @@ err: share->state.changed&= ~STATE_NOT_OPTIMIZED_KEYS; share->state.changed|=STATE_NOT_SORTED_PAGES; - my_free(_ma_get_rec_buff_ptr(info, sort_param.rec_buff), - MYF(MY_ALLOW_ZERO_PTR)); + my_free(sort_param.rec_buff, MYF(MY_ALLOW_ZERO_PTR)); my_free(sort_param.record,MYF(MY_ALLOW_ZERO_PTR)); my_free((gptr) sort_info.key_block,MYF(MY_ALLOW_ZERO_PTR)); my_free((gptr) sort_info.ft_buf, MYF(MY_ALLOW_ZERO_PTR)); @@ -2349,10 +2832,7 @@ err: VOID(end_io_cache(¶m->read_cache)); info->opt_flag&= ~(READ_CACHE_USED | WRITE_CACHE_USED); if (!got_error && (param->testflag & T_UNPACK)) - { - share->state.header.options[0]&= (uchar) ~HA_OPTION_COMPRESS_RECORD; - share->pack.header_length=0; - } + restore_data_file_type(share); DBUG_RETURN(got_error); } @@ -2435,15 +2915,12 @@ int maria_repair_parallel(HA_CHECK *param, register MARIA_HA *info, if (!rep_quick) { /* Get real path for data file */ - if ((new_file=my_raid_create(fn_format(param->temp_filename, - share->data_file_name, "", - DATA_TMP_EXT, - 2+4), - 0,param->tmpfile_createflag, - share->base.raid_type, - share->base.raid_chunks, - share->base.raid_chunksize, - MYF(0))) < 0) + if ((new_file= my_create(fn_format(param->temp_filename, + share->data_file_name, "", + DATA_TMP_EXT, + 2+4), + 0,param->tmpfile_createflag, + MYF(0))) < 0) { _ma_check_print_error(param,"Can't create new tempfile: '%s'", param->temp_filename); @@ -2453,10 +2930,7 @@ int maria_repair_parallel(HA_CHECK *param, register MARIA_HA *info, "datafile-header")) goto err; if (param->testflag & T_UNPACK) - { - share->options&= ~HA_OPTION_COMPRESS_RECORD; - mi_int2store(share->state.header.options,share->options); - } + restore_data_file_type(share); share->state.dellink= HA_OFFSET_ERROR; info->rec_cache.file=new_file; } @@ -2466,14 +2940,13 @@ int maria_repair_parallel(HA_CHECK *param, register MARIA_HA *info, { /* Flush key cache for this file if we are calling this outside - mariachk + maria_chk */ flush_key_blocks(share->key_cache,share->kfile, FLUSH_IGNORE_CHANGED); /* Clear the pointers to the given rows */ for (i=0 ; i < share->base.keys ; i++) share->state.key_root[i]= HA_OFFSET_ERROR; - for (i=0 ; i < share->state.header.max_block_size_index ; i++) - share->state.key_del[i]= HA_OFFSET_ERROR; + share->state.key_del= HA_OFFSET_ERROR; info->state->key_file_length=share->base.keystart; } else @@ -2573,12 +3046,12 @@ int maria_repair_parallel(HA_CHECK *param, register MARIA_HA *info, sort_param[i].record= (((char *)(sort_param+share->base.keys))+ (share->base.pack_reclength * i)); - if (!_ma_alloc_rec_buff(info, -1, &sort_param[i].rec_buff)) + if (_ma_alloc_buffer(&sort_param[i].rec_buff, &sort_param[i].rec_buff_size, + share->base.default_rec_buff_size)) { _ma_check_print_error(param,"Not enough memory!"); goto err; } - sort_param[i].key_length=share->rec_reflength; for (keyseg=sort_param[i].seg; keyseg->type != HA_KEYTYPE_END; keyseg++) @@ -2698,7 +3171,7 @@ int maria_repair_parallel(HA_CHECK *param, register MARIA_HA *info, skr < share->base.reloc*share->base.min_pack_length) skr=share->base.reloc*share->base.min_pack_length; #endif - if (skr != sort_info.filelength && !info->s->base.raid_type) + if (skr != sort_info.filelength) if (my_chsize(info->dfile,skr,0,MYF(0))) _ma_check_print_warning(param, "Can't change size of datafile, error: %d", @@ -2736,9 +3209,9 @@ err: my_close(new_file,MYF(0)); info->dfile=new_file= -1; if (maria_change_to_newfile(share->data_file_name,MARIA_NAME_DEXT, - DATA_TMP_EXT, share->base.raid_chunks, - (param->testflag & T_BACKUP_DATA ? - MYF(MY_REDEL_MAKE_BACKUP): MYF(0))) || + DATA_TMP_EXT, + (param->testflag & T_BACKUP_DATA ? + MYF(MY_REDEL_MAKE_BACKUP): MYF(0))) || _ma_open_datafile(info,share,-1)) got_error=1; } @@ -2750,8 +3223,7 @@ err: if (new_file >= 0) { VOID(my_close(new_file,MYF(0))); - VOID(my_raid_delete(param->temp_filename,share->base.raid_chunks, - MYF(MY_WME))); + VOID(my_delete(param->temp_filename, MYF(MY_WME))); if (info->dfile == new_file) info->dfile= -1; } @@ -2771,21 +3243,18 @@ err: VOID(end_io_cache(¶m->read_cache)); info->opt_flag&= ~(READ_CACHE_USED | WRITE_CACHE_USED); if (!got_error && (param->testflag & T_UNPACK)) - { - share->state.header.options[0]&= (uchar) ~HA_OPTION_COMPRESS_RECORD; - share->pack.header_length=0; - } + restore_data_file_type(share); DBUG_RETURN(got_error); #endif /* THREAD */ } /* Read next record and return next key */ -static int sort_key_read(MARIA_SORT_PARAM *sort_param, void *key) +static int sort_key_read(MARIA_SORT_PARAM *sort_param, byte *key) { int error; - MARIA_SORT_INFO *sort_info=sort_param->sort_info; - MARIA_HA *info=sort_info->info; + MARIA_SORT_INFO *sort_info= sort_param->sort_info; + MARIA_HA *info= sort_info->info; DBUG_ENTER("sort_key_read"); if ((error=sort_get_next_record(sort_param))) @@ -2799,7 +3268,7 @@ static int sort_key_read(MARIA_SORT_PARAM *sort_param, void *key) } sort_param->real_key_length= (info->s->rec_reflength+ - _ma_make_key(info, sort_param->key, (uchar*) key, + _ma_make_key(info, sort_param->key, key, sort_param->record, sort_param->filepos)); #ifdef HAVE_purify bzero(key+sort_param->real_key_length, @@ -2808,7 +3277,8 @@ static int sort_key_read(MARIA_SORT_PARAM *sort_param, void *key) DBUG_RETURN(_ma_sort_write_record(sort_param)); } /* sort_key_read */ -static int sort_maria_ft_key_read(MARIA_SORT_PARAM *sort_param, void *key) + +static int sort_maria_ft_key_read(MARIA_SORT_PARAM *sort_param, byte *key) { int error; MARIA_SORT_INFO *sort_info=sort_param->sort_info; @@ -2841,7 +3311,8 @@ static int sort_maria_ft_key_read(MARIA_SORT_PARAM *sort_param, void *key) sort_param->real_key_length=(info->s->rec_reflength+ _ma_ft_make_key(info, sort_param->key, - key, wptr++, sort_param->filepos)); + key, wptr++, + sort_param->filepos)); #ifdef HAVE_purify if (sort_param->key_length > sort_param->real_key_length) bzero(key+sort_param->real_key_length, @@ -2881,6 +3352,9 @@ static int sort_get_next_record(MARIA_SORT_PARAM *sort_param) DBUG_RETURN(1); switch (share->data_file_type) { + case BLOCK_RECORD: + DBUG_ASSERT(0); + break; case STATIC_RECORD: for (;;) { @@ -2904,7 +3378,7 @@ static int sort_get_next_record(MARIA_SORT_PARAM *sort_param) if (*sort_param->record) { if (param->calc_checksum) - param->glob_crc+= (info->checksum= + param->glob_crc+= (info->cur_row.checksum= _ma_static_checksum(info,sort_param->record)); DBUG_RETURN(0); } @@ -3088,8 +3562,11 @@ static int sort_get_next_record(MARIA_SORT_PARAM *sort_param) sort_param->pos=block_info.filepos+block_info.block_len; if (share->base.blobs) { - if (!(to=_ma_alloc_rec_buff(info,block_info.rec_len, - &(sort_param->rec_buff)))) + if (_ma_alloc_buffer(&sort_param->rec_buff, + &sort_param->rec_buff_size, + block_info.rec_len + + info->s->base.extra_rec_buff_size)) + { if (param->max_record_length >= block_info.rec_len) { @@ -3107,8 +3584,7 @@ static int sort_get_next_record(MARIA_SORT_PARAM *sort_param) } } } - else - to= sort_param->rec_buff; + to= sort_param->rec_buff; } if (left_length < block_info.data_len || ! block_info.data_len) { @@ -3158,7 +3634,7 @@ static int sort_get_next_record(MARIA_SORT_PARAM *sort_param) if (sort_param->read_cache.error < 0) DBUG_RETURN(1); if (info->s->calc_checksum) - info->checksum=_ma_checksum(info,sort_param->record); + info->cur_row.checksum= _ma_checksum(info,sort_param->record); if ((param->testflag & (T_EXTEND | T_REP)) || searching) { if (_ma_rec_check(info, sort_param->record, sort_param->rec_buff, @@ -3172,7 +3648,7 @@ static int sort_get_next_record(MARIA_SORT_PARAM *sort_param) } } if (param->calc_checksum) - param->glob_crc+= info->checksum; + param->glob_crc+= info->cur_row.checksum; DBUG_RETURN(0); } if (!searching) @@ -3230,7 +3706,6 @@ static int sort_get_next_record(MARIA_SORT_PARAM *sort_param) llstr(sort_param->pos,llbuff)); continue; } - info->checksum=_ma_checksum(info,sort_param->record); if (!sort_param->fix_datafile) { sort_param->filepos=sort_param->pos; @@ -3240,8 +3715,12 @@ static int sort_get_next_record(MARIA_SORT_PARAM *sort_param) sort_param->max_pos=(sort_param->pos=block_info.filepos+ block_info.rec_len); info->packed_length=block_info.rec_len; - if (param->calc_checksum) - param->glob_crc+= info->checksum; + + { + info->cur_row.checksum= (*info->s->calc_checksum)(info, + sort_param->record); + param->glob_crc+= info->cur_row.checksum; + } DBUG_RETURN(0); } } @@ -3267,6 +3746,9 @@ int _ma_sort_write_record(MARIA_SORT_PARAM *sort_param) if (sort_param->fix_datafile) { switch (sort_info->new_data_file_type) { + case BLOCK_RECORD: + DBUG_ASSERT(0); + break; case STATIC_RECORD: if (my_b_write(&info->rec_cache,sort_param->record, share->base.pack_reclength)) @@ -3276,7 +3758,6 @@ int _ma_sort_write_record(MARIA_SORT_PARAM *sort_param) } sort_param->filepos+=share->base.pack_reclength; info->s->state.split++; - /* sort_info->param->glob_crc+=_ma_static_checksum(info, sort_param->record); */ break; case DYNAMIC_RECORD: if (! info->blobs) @@ -3298,10 +3779,9 @@ int _ma_sort_write_record(MARIA_SORT_PARAM *sort_param) } from=sort_info->buff+ALIGN_SIZE(MARIA_MAX_DYN_BLOCK_HEADER); } - info->checksum=_ma_checksum(info,sort_param->record); + info->cur_row.checksum= _ma_checksum(info,sort_param->record); reclength= _ma_rec_pack(info,from,sort_param->record); flag=0; - /* sort_info->param->glob_crc+=info->checksum; */ do { @@ -3322,7 +3802,6 @@ int _ma_sort_write_record(MARIA_SORT_PARAM *sort_param) sort_param->filepos+=block_length; info->s->state.split++; } while (reclength); - /* sort_info->param->glob_crc+=info->checksum; */ break; case COMPRESSED_RECORD: reclength=info->packed_length; @@ -3337,7 +3816,6 @@ int _ma_sort_write_record(MARIA_SORT_PARAM *sort_param) _ma_check_print_error(param,"%d when writing to datafile",my_errno); DBUG_RETURN(1); } - /* sort_info->param->glob_crc+=info->checksum; */ sort_param->filepos+=reclength+length; info->s->state.split++; break; @@ -3369,7 +3847,7 @@ static int sort_key_cmp(MARIA_SORT_PARAM *sort_param, const void *a, } /* sort_key_cmp */ -static int sort_key_write(MARIA_SORT_PARAM *sort_param, const void *a) +static int sort_key_write(MARIA_SORT_PARAM *sort_param, const byte *a) { uint diff_pos[2]; char llbuff[22],llbuff2[22]; @@ -3379,11 +3857,11 @@ static int sort_key_write(MARIA_SORT_PARAM *sort_param, const void *a) if (sort_info->key_block->inited) { - cmp=ha_key_cmp(sort_param->seg,sort_info->key_block->lastkey, + cmp=ha_key_cmp(sort_param->seg, (uchar*) sort_info->key_block->lastkey, (uchar*) a, USE_WHOLE_KEY,SEARCH_FIND | SEARCH_UPDATE, diff_pos); if (param->stats_method == MI_STATS_METHOD_NULLS_NOT_EQUAL) - ha_key_cmp(sort_param->seg,sort_info->key_block->lastkey, + ha_key_cmp(sort_param->seg, (uchar*) sort_info->key_block->lastkey, (uchar*) a, USE_WHOLE_KEY, SEARCH_FIND | SEARCH_NULL_ARE_NOT_EQUAL, diff_pos); else if (param->stats_method == MI_STATS_METHOD_IGNORE_NULLS) @@ -3391,7 +3869,7 @@ static int sort_key_write(MARIA_SORT_PARAM *sort_param, const void *a) diff_pos[0]= maria_collect_stats_nonulls_next(sort_param->seg, sort_param->notnull, sort_info->key_block->lastkey, - (uchar*)a); + a); } sort_param->unique[diff_pos[0]-1]++; } @@ -3400,17 +3878,17 @@ static int sort_key_write(MARIA_SORT_PARAM *sort_param, const void *a) cmp= -1; if (param->stats_method == MI_STATS_METHOD_IGNORE_NULLS) maria_collect_stats_nonulls_first(sort_param->seg, sort_param->notnull, - (uchar*)a); + a); } if ((sort_param->keyinfo->flag & HA_NOSAME) && cmp == 0) { sort_info->dupp++; - sort_info->info->lastpos=get_record_for_key(sort_info->info, - sort_param->keyinfo, - (uchar*) a); + sort_info->info->cur_row.lastpos= get_record_for_key(sort_info->info, + sort_param->keyinfo, + a); _ma_check_print_warning(param, "Duplicate key for record at %10s against record at %10s", - llstr(sort_info->info->lastpos,llbuff), + llstr(sort_info->info->cur_row.lastpos, llbuff), llstr(get_record_for_key(sort_info->info, sort_param->keyinfo, sort_info->key_block-> @@ -3418,7 +3896,7 @@ static int sort_key_write(MARIA_SORT_PARAM *sort_param, const void *a) llbuff2)); param->testflag|=T_RETRY_WITHOUT_QUICK; if (sort_info->param->testflag & T_VERBOSE) - _ma_print_key(stdout,sort_param->seg,(uchar*) a, USE_WHOLE_KEY); + _ma_print_key(stdout,sort_param->seg, a, USE_WHOLE_KEY); return (sort_delete_record(sort_param)); } #ifndef DBUG_OFF @@ -3429,10 +3907,11 @@ static int sort_key_write(MARIA_SORT_PARAM *sort_param, const void *a) return(1); } #endif - return (sort_insert_key(sort_param,sort_info->key_block, - (uchar*) a, HA_OFFSET_ERROR)); + return (sort_insert_key(sort_param, sort_info->key_block, + a, HA_OFFSET_ERROR)); } /* sort_key_write */ + int _ma_sort_ft_buf_flush(MARIA_SORT_PARAM *sort_param) { MARIA_SORT_INFO *sort_info=sort_param->sort_info; @@ -3441,24 +3920,24 @@ int _ma_sort_ft_buf_flush(MARIA_SORT_PARAM *sort_param) uint val_off, val_len; int error; SORT_FT_BUF *maria_ft_buf=sort_info->ft_buf; - uchar *from, *to; + byte *from, *to; val_len=share->ft2_keyinfo.keylength; get_key_full_length_rdonly(val_off, maria_ft_buf->lastkey); - to=maria_ft_buf->lastkey+val_off; + to= maria_ft_buf->lastkey+val_off; if (maria_ft_buf->buf) { /* flushing first-level tree */ - error=sort_insert_key(sort_param,key_block,maria_ft_buf->lastkey, - HA_OFFSET_ERROR); + error= sort_insert_key(sort_param,key_block,maria_ft_buf->lastkey, + HA_OFFSET_ERROR); for (from=to+val_len; !error && from < maria_ft_buf->buf; from+= val_len) { memcpy(to, from, val_len); - error=sort_insert_key(sort_param,key_block,maria_ft_buf->lastkey, - HA_OFFSET_ERROR); + error= sort_insert_key(sort_param,key_block,maria_ft_buf->lastkey, + HA_OFFSET_ERROR); } return error; } @@ -3478,10 +3957,11 @@ int _ma_sort_ft_buf_flush(MARIA_SORT_PARAM *sort_param) maria_ft_buf->lastkey,HA_OFFSET_ERROR); } -static int sort_maria_ft_key_write(MARIA_SORT_PARAM *sort_param, const void *a) + +static int sort_maria_ft_key_write(MARIA_SORT_PARAM *sort_param, + const byte *a) { uint a_len, val_off, val_len, error; - uchar *p; MARIA_SORT_INFO *sort_info= sort_param->sort_info; SORT_FT_BUF *ft_buf= sort_info->ft_buf; SORT_KEY_BLOCKS *key_block= sort_info->key_block; @@ -3514,13 +3994,14 @@ static int sort_maria_ft_key_write(MARIA_SORT_PARAM *sort_param, const void *a) if (ha_compare_text(sort_param->seg->charset, ((uchar *)a)+1,a_len-1, - ft_buf->lastkey+1,val_off-1, 0, 0)==0) + (uchar*) ft_buf->lastkey+1,val_off-1, 0, 0)==0) { + byte *p; if (!ft_buf->buf) /* store in second-level tree */ { ft_buf->count++; return sort_insert_key(sort_param,key_block, - ((uchar *)a)+a_len, HA_OFFSET_ERROR); + a + a_len, HA_OFFSET_ERROR); } /* storing the key in the buffer. */ @@ -3569,21 +4050,22 @@ word_init_ft_buf: /* get pointer to record from a key */ static my_off_t get_record_for_key(MARIA_HA *info, MARIA_KEYDEF *keyinfo, - uchar *key) + const byte *key) { - return _ma_dpos(info,0,key + _ma_keylength(keyinfo,key)); + return _ma_dpos(info,0, key + _ma_keylength(keyinfo, key)); } /* get_record_for_key */ /* Insert a key in sort-key-blocks */ static int sort_insert_key(MARIA_SORT_PARAM *sort_param, - register SORT_KEY_BLOCKS *key_block, uchar *key, + register SORT_KEY_BLOCKS *key_block, + const byte *key, my_off_t prev_block) { uint a_length,t_length,nod_flag; my_off_t filepos,key_file_length; - uchar *anc_buff,*lastkey; + byte *anc_buff,*lastkey; MARIA_KEY_PARAM s_temp; MARIA_HA *info; MARIA_KEYDEF *keyinfo=sort_param->keyinfo; @@ -3591,7 +4073,7 @@ static int sort_insert_key(MARIA_SORT_PARAM *sort_param, HA_CHECK *param=sort_info->param; DBUG_ENTER("sort_insert_key"); - anc_buff=key_block->buff; + anc_buff= key_block->buff; info=sort_info->info; lastkey=key_block->lastkey; nod_flag= (key_block == sort_info->key_block ? 0 : @@ -3617,7 +4099,7 @@ static int sort_insert_key(MARIA_SORT_PARAM *sort_param, _ma_kpointer(info,key_block->end_pos,prev_block); t_length=(*keyinfo->pack_key)(keyinfo,nod_flag, - (uchar*) 0,lastkey,lastkey,key, + (byte*) 0,lastkey,lastkey,key, &s_temp); (*keyinfo->store_key)(keyinfo, key_block->end_pos+nod_flag,&s_temp); a_length+=t_length; @@ -3625,14 +4107,14 @@ static int sort_insert_key(MARIA_SORT_PARAM *sort_param, key_block->end_pos+=t_length; if (a_length <= keyinfo->block_length) { - VOID(_ma_move_key(keyinfo,key_block->lastkey,key)); + VOID(_ma_move_key(keyinfo, key_block->lastkey, key)); key_block->last_length=a_length-t_length; DBUG_RETURN(0); } /* Fill block with end-zero and write filled block */ maria_putint(anc_buff,key_block->last_length,nod_flag); - bzero((byte*) anc_buff+key_block->last_length, + bzero(anc_buff+key_block->last_length, keyinfo->block_length- key_block->last_length); key_file_length=info->state->key_file_length; if ((filepos= _ma_new(info,keyinfo,DFLT_INIT_HITS)) == HA_OFFSET_ERROR) @@ -3644,10 +4126,10 @@ static int sort_insert_key(MARIA_SORT_PARAM *sort_param, if (_ma_write_keypage(info, keyinfo, filepos, DFLT_INIT_HITS, anc_buff)) DBUG_RETURN(1); } - else if (my_pwrite(info->s->kfile,(byte*) anc_buff, + else if (my_pwrite(info->s->kfile,anc_buff, (uint) keyinfo->block_length,filepos, param->myf_rw)) DBUG_RETURN(1); - DBUG_DUMP("buff",(byte*) anc_buff,maria_getint(anc_buff)); + DBUG_DUMP("buff",anc_buff,maria_getint(anc_buff)); /* Write separator-key to block in next level */ if (sort_insert_key(sort_param,key_block+1,key_block->lastkey,filepos)) @@ -3665,7 +4147,7 @@ static int sort_delete_record(MARIA_SORT_PARAM *sort_param) { uint i; int old_file,error; - uchar *key; + byte *key; MARIA_SORT_INFO *sort_info=sort_param->sort_info; HA_CHECK *param=sort_info->param; MARIA_HA *info=sort_info->info; @@ -3680,7 +4162,7 @@ static int sort_delete_record(MARIA_SORT_PARAM *sort_param) if (info->s->options & HA_OPTION_COMPRESS_RECORD) { _ma_check_print_error(param, - "Recover aborted; Can't run standard recovery on compressed tables with errors in data-file. Use switch 'mariachk --safe-recover' to fix it\n",stderr);; + "Recover aborted; Can't run standard recovery on compressed tables with errors in data-file. Use switch 'maria_chk --safe-recover' to fix it\n",stderr);; DBUG_RETURN(1); } @@ -3688,8 +4170,9 @@ static int sort_delete_record(MARIA_SORT_PARAM *sort_param) info->dfile=info->rec_cache.file; if (sort_info->current_key) { - key=info->lastkey+info->s->base.max_key_length; - if ((error=(*info->s->read_rnd)(info,sort_param->record,info->lastpos,0)) && + key= info->lastkey+info->s->base.max_key_length; + if ((error=(*info->s->read_record)(info,sort_param->record, + info->cur_row.lastpos)) && error != HA_ERR_RECORD_DELETED) { _ma_check_print_error(param,"Can't read record to be removed"); @@ -3699,10 +4182,13 @@ static int sort_delete_record(MARIA_SORT_PARAM *sort_param) for (i=0 ; i < sort_info->current_key ; i++) { - uint key_length= _ma_make_key(info,i,key,sort_param->record,info->lastpos); - if (_ma_ck_delete(info,i,key,key_length)) + uint key_length= _ma_make_key(info, i, key, sort_param->record, + info->cur_row.lastpos); + if (_ma_ck_delete(info, i, key, key_length)) { - _ma_check_print_error(param,"Can't delete key %d from record to be removed",i+1); + _ma_check_print_error(param, + "Can't delete key %d from record to be removed", + i+1); info->dfile=old_file; DBUG_RETURN(1); } @@ -3738,7 +4224,7 @@ int _ma_flush_pending_blocks(MARIA_SORT_PARAM *sort_param) if (nod_flag) _ma_kpointer(info,key_block->end_pos,filepos); key_file_length=info->state->key_file_length; - bzero((byte*) key_block->buff+length, keyinfo->block_length-length); + bzero(key_block->buff+length, keyinfo->block_length-length); if ((filepos= _ma_new(info,keyinfo,DFLT_INIT_HITS)) == HA_OFFSET_ERROR) DBUG_RETURN(1); @@ -3749,10 +4235,10 @@ int _ma_flush_pending_blocks(MARIA_SORT_PARAM *sort_param) DFLT_INIT_HITS, key_block->buff)) DBUG_RETURN(1); } - else if (my_pwrite(info->s->kfile,(byte*) key_block->buff, + else if (my_pwrite(info->s->kfile,key_block->buff, (uint) keyinfo->block_length,filepos, myf_rw)) DBUG_RETURN(1); - DBUG_DUMP("buff",(byte*) key_block->buff,length); + DBUG_DUMP("buff",key_block->buff,length); nod_flag=1; } info->s->state.key_root[sort_param->key]=filepos; /* Last is root for tree */ @@ -3768,9 +4254,9 @@ static SORT_KEY_BLOCKS *alloc_key_blocks(HA_CHECK *param, uint blocks, SORT_KEY_BLOCKS *block; DBUG_ENTER("alloc_key_blocks"); - if (!(block=(SORT_KEY_BLOCKS*) my_malloc((sizeof(SORT_KEY_BLOCKS)+ - buffer_length+IO_SIZE)*blocks, - MYF(0)))) + if (!(block= (SORT_KEY_BLOCKS*) my_malloc((sizeof(SORT_KEY_BLOCKS)+ + buffer_length+IO_SIZE)*blocks, + MYF(0)))) { _ma_check_print_error(param,"Not enough memory for sort-key-blocks"); return(0); @@ -3778,7 +4264,7 @@ static SORT_KEY_BLOCKS *alloc_key_blocks(HA_CHECK *param, uint blocks, for (i=0 ; i < blocks ; i++) { block[i].inited=0; - block[i].buff=(uchar*) (block+blocks)+(buffer_length+IO_SIZE)*i; + block[i].buff= (byte*) (block+blocks)+(buffer_length+IO_SIZE)*i; } DBUG_RETURN(block); } /* alloc_key_blocks */ @@ -3821,7 +4307,8 @@ int maria_recreate_table(HA_CHECK *param, MARIA_HA **org_info, char *filename) share= *(*org_info)->s; unpack= (share.options & HA_OPTION_COMPRESS_RECORD) && (param->testflag & T_UNPACK); - if (!(keyinfo=(MARIA_KEYDEF*) my_alloca(sizeof(MARIA_KEYDEF)*share.base.keys))) + if (!(keyinfo=(MARIA_KEYDEF*) my_alloca(sizeof(MARIA_KEYDEF) * + share.base.keys))) DBUG_RETURN(0); memcpy((byte*) keyinfo,(byte*) share.keyinfo, (size_t) (sizeof(MARIA_KEYDEF)*share.base.keys)); @@ -3877,8 +4364,10 @@ int maria_recreate_table(HA_CHECK *param, MARIA_HA **org_info, char *filename) keyseg++; /* Skip end pointer */ } - /* Copy the unique definitions and change them to point at the new key - segments*/ + /* + Copy the unique definitions and change them to point at the new key + segments + */ memcpy((byte*) uniquedef,(byte*) share.uniqueinfo, (size_t) (sizeof(MARIA_UNIQUEDEF)*(share.state.header.uniques))); for (u_ptr=uniquedef,u_end=uniquedef+share.state.header.uniques; @@ -3894,7 +4383,7 @@ int maria_recreate_table(HA_CHECK *param, MARIA_HA **org_info, char *filename) (ulong) share.base.min_pack_length); else max_records=0; - unpack= (share.options & HA_OPTION_COMPRESS_RECORD) && + unpack= (share.data_file_type == COMPRESSED_RECORD) && (param->testflag & T_UNPACK); share.options&= ~HA_OPTION_TEMP_COMPRESS_RECORD; @@ -3916,21 +4405,29 @@ int maria_recreate_table(HA_CHECK *param, MARIA_HA **org_info, char *filename) create_info.language = (param->language ? param->language : share.state.header.language); create_info.key_file_length= status_info.key_file_length; + create_info.org_data_file_type= ((enum data_file_type) + share.state.header.org_data_file_type); + /* Allow for creating an auto_increment key. This has an effect only if an auto_increment key exists in the original table. */ create_info.with_auto_increment= TRUE; - /* We don't have to handle symlinks here because we are using - HA_DONT_TOUCH_DATA */ - if (maria_create(filename, - share.base.keys - share.state.header.uniques, - keyinfo, share.base.fields, recdef, - share.state.header.uniques, uniquedef, - &create_info, - HA_DONT_TOUCH_DATA)) - { - _ma_check_print_error(param,"Got error %d when trying to recreate indexfile",my_errno); + create_info.null_bytes= share.base.null_bytes; + /* + We don't have to handle symlinks here because we are using + HA_DONT_TOUCH_DATA + */ + if (maria_create(filename, share.data_file_type, + share.base.keys - share.state.header.uniques, + keyinfo, share.base.fields, recdef, + share.state.header.uniques, uniquedef, + &create_info, + HA_DONT_TOUCH_DATA)) + { + _ma_check_print_error(param, + "Got error %d when trying to recreate indexfile", + my_errno); goto end; } *org_info=maria_open(filename,O_RDWR, @@ -3939,8 +4436,9 @@ int maria_recreate_table(HA_CHECK *param, MARIA_HA **org_info, char *filename) HA_OPEN_ABORT_IF_LOCKED); if (!*org_info) { - _ma_check_print_error(param,"Got error %d when trying to open re-created indexfile", - my_errno); + _ma_check_print_error(param, + "Got error %d when trying to open re-created indexfile", + my_errno); goto end; } /* We are modifing */ @@ -3990,7 +4488,8 @@ int maria_write_data_suffix(MARIA_SORT_INFO *sort_info, my_bool fix_datafile) return 0; } - /* Update state and mariachk_time of indexfile */ + +/* Update state and maria_chk time of indexfile */ int maria_update_state_info(HA_CHECK *param, MARIA_HA *info,uint update) { @@ -4303,12 +4802,7 @@ set_data_file_type(MARIA_SORT_INFO *sort_info, MARIA_SHARE *share) COMPRESSED_RECORD && sort_info->param->testflag & T_UNPACK) { MARIA_SHARE tmp; - - if (share->options & HA_OPTION_PACK_RECORD) - sort_info->new_data_file_type = DYNAMIC_RECORD; - else - sort_info->new_data_file_type = STATIC_RECORD; - + sort_info->new_data_file_type= share->state.header.org_data_file_type; /* Set delete_function for sort_delete_record() */ memcpy((char*) &tmp, share, sizeof(*share)); tmp.options= ~HA_OPTION_COMPRESS_RECORD; @@ -4316,3 +4810,13 @@ set_data_file_type(MARIA_SORT_INFO *sort_info, MARIA_SHARE *share) share->delete_record=tmp.delete_record; } } + +static void restore_data_file_type(MARIA_SHARE *share) +{ + share->options&= ~HA_OPTION_COMPRESS_RECORD; + mi_int2store(share->state.header.options,share->options); + share->state.header.data_file_type= + share->state.header.org_data_file_type; + share->data_file_type= share->state.header.data_file_type= + share->pack.header_length= 0; +} diff --git a/storage/maria/ma_checksum.c b/storage/maria/ma_checksum.c index 054873706a4..1b0f683fe63 100644 --- a/storage/maria/ma_checksum.c +++ b/storage/maria/ma_checksum.c @@ -18,23 +18,27 @@ #include "maria_def.h" -ha_checksum _ma_checksum(MARIA_HA *info, const byte *buf) +ha_checksum _ma_checksum(MARIA_HA *info, const byte *record) { uint i; ha_checksum crc=0; MARIA_COLUMNDEF *rec=info->s->rec; - for (i=info->s->base.fields ; i-- ; buf+=(rec++)->length) + if (info->s->base.null_bytes) + crc= my_checksum(crc, record, info->s->base.null_bytes); + + for (i=info->s->base.fields ; i-- ; ) { - const byte *pos; + const byte *pos= record + rec->offset; ulong length; + switch (rec->type) { case FIELD_BLOB: { length= _ma_calc_blob_length(rec->length- maria_portable_sizeof_char_ptr, - buf); - memcpy((char*) &pos, buf+rec->length- maria_portable_sizeof_char_ptr, + pos); + memcpy((char*) &pos, pos+rec->length- maria_portable_sizeof_char_ptr, sizeof(char*)); break; } @@ -42,18 +46,17 @@ ha_checksum _ma_checksum(MARIA_HA *info, const byte *buf) { uint pack_length= HA_VARCHAR_PACKLENGTH(rec->length-1); if (pack_length == 1) - length= (ulong) *(uchar*) buf; + length= (ulong) *(uchar*) pos; else - length= uint2korr(buf); - pos= buf+pack_length; + length= uint2korr(pos); + pos+= pack_length; break; } default: - length=rec->length; - pos=buf; + length= rec->length; break; } - crc=my_checksum(crc, pos ? pos : "", length); + crc= my_checksum(crc, pos ? pos : "", length); } return crc; } diff --git a/storage/maria/ma_close.c b/storage/maria/ma_close.c index 5b940eaf4c3..e5d2985ce47 100644 --- a/storage/maria/ma_close.c +++ b/storage/maria/ma_close.c @@ -28,7 +28,7 @@ int maria_close(register MARIA_HA *info) int error=0,flag; MARIA_SHARE *share=info->s; DBUG_ENTER("maria_close"); - DBUG_PRINT("enter",("base: %lx reopen: %u locks: %u", + DBUG_PRINT("enter",("base: 0x%lx reopen: %u locks: %u", info,(uint) share->reopen, (uint) share->tot_locks)); pthread_mutex_lock(&THR_LOCK_maria); @@ -60,16 +60,22 @@ int maria_close(register MARIA_HA *info) maria_open_list=list_delete(maria_open_list,&info->open_list); pthread_mutex_unlock(&share->intern_lock); - my_free(_ma_get_rec_buff_ptr(info, info->rec_buff), MYF(MY_ALLOW_ZERO_PTR)); + my_free(info->rec_buff, MYF(MY_ALLOW_ZERO_PTR)); + (share->end)(info); + + if (info->s->data_file_type == BLOCK_RECORD) + info->dfile= -1; /* Closed in ma_end_once_block_row */ if (flag) { - if (share->kfile >= 0 && - flush_key_blocks(share->key_cache, share->kfile, - share->temporary ? FLUSH_IGNORE_CHANGED : - FLUSH_RELEASE)) - error=my_errno; if (share->kfile >= 0) { + if ((*share->once_end)(share)) + error= my_errno; + if (flush_key_blocks(share->key_cache, share->kfile, + share->temporary ? FLUSH_IGNORE_CHANGED : + FLUSH_RELEASE)) + error= my_errno; + /* If we are crashed, we can safely flush the current state as it will not change the crashed state. @@ -78,18 +84,13 @@ int maria_close(register MARIA_HA *info) */ if (share->mode != O_RDONLY && maria_is_crashed(info)) _ma_state_info_write(share->kfile, &share->state, 1); - if (my_close(share->kfile,MYF(0))) - error = my_errno; + if (my_close(share->kfile, MYF(0))) + error= my_errno; } #ifdef HAVE_MMAP if (share->file_map) _ma_unmap_file(info); #endif - if (share->decode_trees) - { - my_free((gptr) share->decode_trees,MYF(0)); - my_free((gptr) share->decode_tables,MYF(0)); - } #ifdef THREAD thr_lock_delete(&share->lock); VOID(pthread_mutex_destroy(&share->intern_lock)); diff --git a/storage/maria/ma_create.c b/storage/maria/ma_create.c index b9fb4eb0d5b..82585e78ba7 100644 --- a/storage/maria/ma_create.c +++ b/storage/maria/ma_create.c @@ -18,6 +18,7 @@ #include "ma_ftdefs.h" #include "ma_sp_defs.h" +#include "ma_blockrec.h" #if defined(MSDOS) || defined(__WIN__) #ifdef __WIN__ @@ -28,41 +29,48 @@ #endif #include <m_ctype.h> +static int compare_columns(MARIA_COLUMNDEF **a, MARIA_COLUMNDEF **b); + /* Old options is used when recreating database, from maria_chk */ -int maria_create(const char *name,uint keys,MARIA_KEYDEF *keydefs, - uint columns, MARIA_COLUMNDEF *recinfo, - uint uniques, MARIA_UNIQUEDEF *uniquedefs, - MARIA_CREATE_INFO *ci,uint flags) +int maria_create(const char *name, enum data_file_type record_type, + uint keys,MARIA_KEYDEF *keydefs, + uint columns, MARIA_COLUMNDEF *recinfo, + uint uniques, MARIA_UNIQUEDEF *uniquedefs, + MARIA_CREATE_INFO *ci,uint flags) { register uint i,j; File dfile,file; int errpos,save_errno, create_mode= O_RDWR | O_TRUNC; myf create_flag; - uint fields,length,max_key_length,packed,pointer,real_length_diff, + uint length,max_key_length,packed,pack_bytes,pointer,real_length_diff, key_length,info_length,key_segs,options,min_key_length_skip, base_pos,long_varchar_count,varchar_length, - max_key_block_length,unique_key_parts,fulltext_keys,offset; - uint aligned_key_start, block_length; + unique_key_parts,fulltext_keys,offset; + uint max_field_lengths, extra_header_size; ulong reclength, real_reclength,min_pack_length; char filename[FN_REFLEN],linkname[FN_REFLEN], *linkname_ptr; ulong pack_reclength; ulonglong tot_length,max_rows, tmp; enum en_fieldtype type; + enum data_file_type org_record_type= record_type; MARIA_SHARE share; MARIA_KEYDEF *keydef,tmp_keydef; MARIA_UNIQUEDEF *uniquedef; HA_KEYSEG *keyseg,tmp_keyseg; - MARIA_COLUMNDEF *rec; + MARIA_COLUMNDEF *rec, *rec_end; ulong *rec_per_key_part; - my_off_t key_root[HA_MAX_POSSIBLE_KEY],key_del[MARIA_MAX_KEY_BLOCK_SIZE]; + my_off_t key_root[HA_MAX_POSSIBLE_KEY]; MARIA_CREATE_INFO tmp_create_info; DBUG_ENTER("maria_create"); DBUG_PRINT("enter", ("keys: %u columns: %u uniques: %u flags: %u", keys, columns, uniques, flags)); + LINT_INIT(dfile); + LINT_INIT(file); + if (!ci) { bzero((char*) &tmp_create_info,sizeof(tmp_create_info)); @@ -73,22 +81,24 @@ int maria_create(const char *name,uint keys,MARIA_KEYDEF *keydefs, { DBUG_RETURN(my_errno=HA_WRONG_CREATE_OPTION); } - LINT_INIT(dfile); - LINT_INIT(file); errpos=0; options=0; bzero((byte*) &share,sizeof(share)); if (flags & HA_DONT_TOUCH_DATA) { + org_record_type= ci->org_data_file_type; if (!(ci->old_options & HA_OPTION_TEMP_COMPRESS_RECORD)) options=ci->old_options & (HA_OPTION_COMPRESS_RECORD | HA_OPTION_PACK_RECORD | HA_OPTION_READ_ONLY_DATA | HA_OPTION_CHECKSUM | HA_OPTION_TMP_TABLE | HA_OPTION_DELAY_KEY_WRITE); else + { + /* Uncompressing rows */ options=ci->old_options & (HA_OPTION_CHECKSUM | HA_OPTION_TMP_TABLE | HA_OPTION_DELAY_KEY_WRITE); + } } if (ci->reloc_rows > ci->max_rows) @@ -101,59 +111,90 @@ int maria_create(const char *name,uint keys,MARIA_KEYDEF *keydefs, /* Start by checking fields and field-types used */ - reclength=varchar_length=long_varchar_count=packed= - min_pack_length=pack_reclength=0; - for (rec=recinfo, fields=0 ; - fields != columns ; - rec++,fields++) + varchar_length=long_varchar_count=packed= + pack_reclength= max_field_lengths= 0; + reclength= min_pack_length= ci->null_bytes; + + for (rec= recinfo, rec_end= rec + columns ; rec != rec_end ; rec++) { - reclength+=rec->length; - if ((type=(enum en_fieldtype) rec->type) != FIELD_NORMAL && - type != FIELD_CHECK) + /* Fill in not used struct parts */ + rec->offset= reclength; + rec->empty_pos= 0; + rec->empty_bit= 0; + rec->fill_length= rec->length; + + reclength+= rec->length; + type= rec->type; + if (type == FIELD_SKIP_PRESPACE && record_type == BLOCK_RECORD) + type= FIELD_NORMAL; /* SKIP_PRESPACE not supported */ + + if (type != FIELD_NORMAL && type != FIELD_CHECK) { - packed++; + rec->empty_pos= packed/8; + rec->empty_bit= (1 << (packed & 7)); if (type == FIELD_BLOB) { + packed++; share.base.blobs++; if (pack_reclength != INT_MAX32) { if (rec->length == 4+maria_portable_sizeof_char_ptr) pack_reclength= INT_MAX32; else - pack_reclength+=(1 << ((rec->length-maria_portable_sizeof_char_ptr)*8)); /* Max blob length */ + { + /* Add max possible blob length */ + pack_reclength+= (1 << ((rec->length- + maria_portable_sizeof_char_ptr)*8)); + } } + max_field_lengths+= (rec->length - maria_portable_sizeof_char_ptr); } else if (type == FIELD_SKIP_PRESPACE || type == FIELD_SKIP_ENDSPACE) { - if (pack_reclength != INT_MAX32) - pack_reclength+= rec->length > 255 ? 2 : 1; + max_field_lengths+= rec->length > 255 ? 2 : 1; min_pack_length++; + packed++; } else if (type == FIELD_VARCHAR) { varchar_length+= rec->length-1; /* Used for min_pack_length */ - packed--; pack_reclength++; min_pack_length++; + max_field_lengths++; + packed++; /* We must test for 257 as length includes pack-length */ if (test(rec->length >= 257)) { long_varchar_count++; - pack_reclength+= 2; /* May be packed on 3 bytes */ + max_field_lengths++; } } else if (type != FIELD_SKIP_ZERO) { min_pack_length+=rec->length; - packed--; /* Not a pack record type */ + rec->empty_pos= 0; + rec->empty_bit= 0; } + else + packed++; } else /* FIELD_NORMAL */ + { min_pack_length+=rec->length; + if (!rec->null_bit) + { + share.base.fixed_not_null_fields++; + share.base.fixed_not_null_fields_length+= rec->length; + } + } } if ((packed & 7) == 1) - { /* Bad packing, try to remove a zero-field */ + { + /* + Not optimal packing, try to remove a 1 byte length zero-field as + this will get same record length, but smaller pack overhead + */ while (rec != recinfo) { rec--; @@ -166,14 +207,27 @@ int maria_create(const char *name,uint keys,MARIA_KEYDEF *keydefs, } } } + share.base.null_bytes= ci->null_bytes; + share.base.original_null_bytes= ci->null_bytes; + share.base.transactional= ci->transactional; + share.base.max_field_lengths= max_field_lengths; + share.base.field_offsets= 0; /* for future */ + + if (pack_reclength != INT_MAX32) + pack_reclength+= max_field_lengths + long_varchar_count; - if (packed || (flags & HA_PACK_RECORD)) - options|=HA_OPTION_PACK_RECORD; /* Must use packed records */ - /* We can't use checksum with static length rows */ - if (!(options & HA_OPTION_PACK_RECORD)) + if (packed && record_type == STATIC_RECORD) + record_type= BLOCK_RECORD; + if (record_type == DYNAMIC_RECORD) + options|= HA_OPTION_PACK_RECORD; /* Must use packed records */ + + if (record_type == STATIC_RECORD) + { + /* We can't use checksum with static length rows */ + flags&= ~HA_CREATE_CHECKSUM; options&= ~HA_OPTION_CHECKSUM; - if (!(options & (HA_OPTION_PACK_RECORD | HA_OPTION_COMPRESS_RECORD))) min_pack_length+= varchar_length; + } if (flags & HA_CREATE_TMP_TABLE) { options|= HA_OPTION_TMP_TABLE; @@ -183,18 +237,24 @@ int maria_create(const char *name,uint keys,MARIA_KEYDEF *keydefs, { options|= HA_OPTION_CHECKSUM; min_pack_length++; + pack_reclength++; } if (flags & HA_CREATE_DELAY_KEY_WRITE) options|= HA_OPTION_DELAY_KEY_WRITE; if (flags & HA_CREATE_RELIES_ON_SQL_LAYER) options|= HA_OPTION_RELIES_ON_SQL_LAYER; - packed=(packed+7)/8; + pack_bytes= (packed + 7) / 8; if (pack_reclength != INT_MAX32) - pack_reclength+= reclength+packed + + pack_reclength+= reclength+pack_bytes + test(test_all_bits(options, HA_OPTION_CHECKSUM | HA_PACK_RECORD)); - min_pack_length+=packed; - + min_pack_length+= pack_bytes; + /* Calculate min possible row length for rows-in-block */ + extra_header_size= MAX_FIXED_HEADER_SIZE; + if (ci->transactional) + extra_header_size= TRANS_MAX_FIXED_HEADER_SIZE; + share.base.min_row_length= (extra_header_size + share.base.null_bytes + + pack_bytes); if (!ci->data_file_length && ci->max_rows) { if (pack_reclength == INT_MAX32 || @@ -204,20 +264,57 @@ int maria_create(const char *name,uint keys,MARIA_KEYDEF *keydefs, ci->data_file_length=(ulonglong) ci->max_rows*pack_reclength; } else if (!ci->max_rows) - ci->max_rows=(ha_rows) (ci->data_file_length/(min_pack_length + - ((options & HA_OPTION_PACK_RECORD) ? - 3 : 0))); - - if (options & (HA_OPTION_COMPRESS_RECORD | HA_OPTION_PACK_RECORD)) - pointer=maria_get_pointer_length(ci->data_file_length,maria_data_pointer_size); + { + if (record_type == BLOCK_RECORD) + { + uint rows_per_page= ((maria_block_size - PAGE_OVERHEAD_SIZE) / + (min_pack_length + extra_header_size + + DIR_ENTRY_SIZE)); + ulonglong data_file_length= ci->data_file_length; + if (data_file_length) + data_file_length= ((((ulonglong) 1 << ((BLOCK_RECORD_POINTER_SIZE-1) * + 8)) -1)); + if (rows_per_page > 0) + { + set_if_smaller(rows_per_page, MAX_ROWS_PER_PAGE); + ci->max_rows= ci->data_file_length / maria_block_size * rows_per_page; + } + else + ci->max_rows= ci->data_file_length / (min_pack_length + + extra_header_size + + DIR_ENTRY_SIZE); + } + else + ci->max_rows=(ha_rows) (ci->data_file_length/(min_pack_length + + ((options & + HA_OPTION_PACK_RECORD) ? + 3 : 0))); + } + max_rows= (ulonglong) ci->max_rows; + if (record_type == BLOCK_RECORD) + { + /* The + 1 is for record position withing page */ + pointer= maria_get_pointer_length((ci->data_file_length / + maria_block_size), 3) + 1; + set_if_smaller(pointer, BLOCK_RECORD_POINTER_SIZE); + + if (!max_rows) + max_rows= (((((ulonglong) 1 << ((pointer-1)*8)) -1) * maria_block_size) / + min_pack_length); + } else - pointer=maria_get_pointer_length(ci->max_rows,maria_data_pointer_size); - if (!(max_rows=(ulonglong) ci->max_rows)) - max_rows= ((((ulonglong) 1 << (pointer*8)) -1) / min_pack_length); - + { + if (record_type != STATIC_RECORD) + pointer= maria_get_pointer_length(ci->data_file_length, + maria_data_pointer_size); + else + pointer= maria_get_pointer_length(ci->max_rows, maria_data_pointer_size); + if (!max_rows) + max_rows= ((((ulonglong) 1 << (pointer*8)) -1) / min_pack_length); + } real_reclength=reclength; - if (!(options & (HA_OPTION_COMPRESS_RECORD | HA_OPTION_PACK_RECORD))) + if (record_type == STATIC_RECORD) { if (reclength <= pointer) reclength=pointer+1; /* reserve place for delete link */ @@ -227,19 +324,14 @@ int maria_create(const char *name,uint keys,MARIA_KEYDEF *keydefs, max_key_length=0; tot_length=0 ; key_segs=0; fulltext_keys=0; - max_key_block_length=0; share.state.rec_per_key_part=rec_per_key_part; share.state.key_root=key_root; - share.state.key_del=key_del; + share.state.key_del= HA_OFFSET_ERROR; if (uniques) - { - max_key_block_length= maria_block_size; - max_key_length= MARIA_UNIQUE_HASH_LENGTH + pointer; - } + max_key_length= MARIA_UNIQUE_HASH_LENGTH + pointer; for (i=0, keydef=keydefs ; i < keys ; i++ , keydef++) { - share.state.key_root[i]= HA_OFFSET_ERROR; min_key_length_skip=length=real_length_diff=0; key_length=pointer; @@ -253,11 +345,11 @@ int maria_create(const char *name,uint keys,MARIA_KEYDEF *keydefs, if (flags & HA_DONT_TOUCH_DATA) { /* - called by mariachk - i.e. table structure was taken from - MYI file and SPATIAL key *does have* additional sp_segs keysegs. - keydef->seg here points right at the GEOMETRY segment, - so we only need to decrease keydef->keysegs. - (see maria_recreate_table() in _ma_check.c) + Called by maria_chk - i.e. table structure was taken from + MYI file and SPATIAL key *does have* additional sp_segs keysegs. + keydef->seg here points right at the GEOMETRY segment, + so we only need to decrease keydef->keysegs. + (see maria_recreate_table() in _ma_check.c) */ keydef->keysegs-=sp_segs-1; } @@ -431,35 +523,22 @@ int maria_create(const char *name,uint keys,MARIA_KEYDEF *keydefs, key_segs) share.state.rec_per_key_part[key_segs-1]=1L; length+=key_length; - /* Get block length for key, if defined by user */ - block_length= (keydef->block_length ? - my_round_up_to_next_power(keydef->block_length) : - maria_block_size); - block_length= max(block_length, MARIA_MIN_KEY_BLOCK_LENGTH); - block_length= min(block_length, MARIA_MAX_KEY_BLOCK_LENGTH); - - keydef->block_length= MARIA_BLOCK_SIZE(length-real_length_diff, - pointer,MARIA_MAX_KEYPTR_SIZE, - block_length); - if (keydef->block_length > MARIA_MAX_KEY_BLOCK_LENGTH || - length >= HA_MAX_KEY_BUFF) + if (length >= min(HA_MAX_KEY_BUFF, MARIA_MAX_KEY_LENGTH)) { my_errno=HA_WRONG_CREATE_OPTION; goto err; } - set_if_bigger(max_key_block_length,keydef->block_length); + keydef->block_length= maria_block_size; keydef->keylength= (uint16) key_length; keydef->minlength= (uint16) (length-min_key_length_skip); keydef->maxlength= (uint16) length; if (length > max_key_length) max_key_length= length; - tot_length+= (max_rows/(ulong) (((uint) keydef->block_length-5)/ - (length*2)))* - (ulong) keydef->block_length; + tot_length+= ((max_rows/(ulong) (((uint) maria_block_size-5)/ + (length*2))) * + maria_block_size); } - for (i=max_key_block_length/MARIA_MIN_KEY_BLOCK_LENGTH ; i-- ; ) - key_del[i]=HA_OFFSET_ERROR; unique_key_parts=0; offset=reclength-uniques*MARIA_UNIQUE_HASH_LENGTH; @@ -476,14 +555,12 @@ int maria_create(const char *name,uint keys,MARIA_KEYDEF *keydefs, key_segs+=uniques; /* Each unique has 1 key seg */ base_pos=(MARIA_STATE_INFO_SIZE + keys * MARIA_STATE_KEY_SIZE + - max_key_block_length/MARIA_MIN_KEY_BLOCK_LENGTH* - MARIA_STATE_KEYBLOCK_SIZE+ - key_segs*MARIA_STATE_KEYSEG_SIZE); - info_length=base_pos+(uint) (MARIA_BASE_INFO_SIZE+ - keys * MARIA_KEYDEF_SIZE+ - uniques * MARIA_UNIQUEDEF_SIZE + - (key_segs + unique_key_parts)*HA_KEYSEG_SIZE+ - columns*MARIA_COLUMNDEF_SIZE); + key_segs * MARIA_STATE_KEYSEG_SIZE); + info_length= base_pos+(uint) (MARIA_BASE_INFO_SIZE+ + keys * MARIA_KEYDEF_SIZE+ + uniques * MARIA_UNIQUEDEF_SIZE + + (key_segs + unique_key_parts)*HA_KEYSEG_SIZE+ + columns*MARIA_COLUMNDEF_SIZE); DBUG_PRINT("info", ("info_length: %u", info_length)); /* There are only 16 bits for the total header length. */ @@ -505,11 +582,13 @@ int maria_create(const char *name,uint keys,MARIA_KEYDEF *keydefs, mi_int2store(share.state.header.state_info_length,MARIA_STATE_INFO_SIZE); mi_int2store(share.state.header.base_info_length,MARIA_BASE_INFO_SIZE); mi_int2store(share.state.header.base_pos,base_pos); + share.state.header.data_file_type= record_type; + share.state.header.org_data_file_type= org_record_type; share.state.header.language= (ci->language ? ci->language : default_charset_info->number); - share.state.header.max_block_size_index= max_key_block_length/MARIA_MIN_KEY_BLOCK_LENGTH; share.state.dellink = HA_OFFSET_ERROR; + share.state.first_bitmap_with_space= 0; share.state.process= (ulong) getpid(); share.state.unique= (ulong) 0; share.state.update_count=(ulong) 0; @@ -518,9 +597,11 @@ int maria_create(const char *name,uint keys,MARIA_KEYDEF *keydefs, share.state.auto_increment=ci->auto_increment; share.options=options; share.base.rec_reflength=pointer; + share.base.block_size= maria_block_size; + /* Get estimate for index file length (this may be wrong for FT keys) */ - tmp= (tot_length + max_key_block_length * keys * - MARIA_INDEX_BLOCK_MARGIN) / MARIA_MIN_KEY_BLOCK_LENGTH; + tmp= (tot_length + maria_block_size * keys * + MARIA_INDEX_BLOCK_MARGIN) / maria_block_size; /* use maximum of key_file_length we calculated and key_file_length value we got from MYI file header (see also mariapack.c:save_state) @@ -534,13 +615,10 @@ int maria_create(const char *name,uint keys,MARIA_KEYDEF *keydefs, mi_int2store(share.state.header.unique_key_parts,unique_key_parts); maria_set_all_keys_active(share.state.key_map, keys); - aligned_key_start= my_round_up_to_next_power(max_key_block_length ? - max_key_block_length : - maria_block_size); share.base.keystart = share.state.state.key_file_length= - MY_ALIGN(info_length, aligned_key_start); - share.base.max_key_block_length=max_key_block_length; + MY_ALIGN(info_length, maria_block_size); + share.base.max_key_block_length= maria_block_size; share.base.max_key_length=ALIGN_SIZE(max_key_length+4); share.base.records=ci->max_rows; share.base.reloc= ci->reloc_rows; @@ -548,9 +626,9 @@ int maria_create(const char *name,uint keys,MARIA_KEYDEF *keydefs, share.base.pack_reclength=reclength+ test(options & HA_OPTION_CHECKSUM); share.base.max_pack_length=pack_reclength; share.base.min_pack_length=min_pack_length; - share.base.pack_bits=packed; - share.base.fields=fields; - share.base.pack_fields=packed; + share.base.pack_bytes= pack_bytes; + share.base.fields= columns; + share.base.pack_fields= packed; #ifdef USE_RAID share.base.raid_type=ci->raid_type; share.base.raid_chunks=ci->raid_chunks; @@ -559,7 +637,7 @@ int maria_create(const char *name,uint keys,MARIA_KEYDEF *keydefs, /* max_data_file_length and max_key_file_length are recalculated on open */ if (options & HA_OPTION_TMP_TABLE) - share.base.max_data_file_length=(my_off_t) ci->data_file_length; + share.base.max_data_file_length= (my_off_t) ci->data_file_length; share.base.min_block_length= (share.base.pack_reclength+3 < MARIA_EXTEND_BLOCK_LENGTH && @@ -632,72 +710,63 @@ int maria_create(const char *name,uint keys,MARIA_KEYDEF *keydefs, if (!(flags & HA_DONT_TOUCH_DATA)) { -#ifdef USE_RAID - if (share.base.raid_type) - { - (void) fn_format(filename, name, "", MARIA_NAME_DEXT, - MY_UNPACK_FILENAME | MY_APPEND_EXT); - if ((dfile=my_raid_create(filename, 0, create_mode, - share.base.raid_type, - share.base.raid_chunks, - share.base.raid_chunksize, - MYF(MY_WME | MY_RAID))) < 0) - goto err; - } - else -#endif + if (ci->data_file_name) { - if (ci->data_file_name) - { - char *dext= strrchr(ci->data_file_name, '.'); - int have_dext= dext && !strcmp(dext, MARIA_NAME_DEXT); + char *dext= strrchr(ci->data_file_name, '.'); + int have_dext= dext && !strcmp(dext, MARIA_NAME_DEXT); - if (options & HA_OPTION_TMP_TABLE) - { - char *path; - /* chop off the table name, tempory tables use generated name */ - if ((path= strrchr(ci->data_file_name, FN_LIBCHAR))) - *path= '\0'; - fn_format(filename, name, ci->data_file_name, MARIA_NAME_DEXT, - MY_REPLACE_DIR | MY_UNPACK_FILENAME | MY_APPEND_EXT); - } - else - { - fn_format(filename, ci->data_file_name, "", MARIA_NAME_DEXT, - MY_UNPACK_FILENAME | - (have_dext ? MY_REPLACE_EXT : MY_APPEND_EXT)); - } - fn_format(linkname, name, "",MARIA_NAME_DEXT, - MY_UNPACK_FILENAME | MY_APPEND_EXT); - linkname_ptr=linkname; - create_flag=0; + if (options & HA_OPTION_TMP_TABLE) + { + char *path; + /* chop off the table name, tempory tables use generated name */ + if ((path= strrchr(ci->data_file_name, FN_LIBCHAR))) + *path= '\0'; + fn_format(filename, name, ci->data_file_name, MARIA_NAME_DEXT, + MY_REPLACE_DIR | MY_UNPACK_FILENAME | MY_APPEND_EXT); } else { - fn_format(filename,name,"", MARIA_NAME_DEXT, - MY_UNPACK_FILENAME | MY_APPEND_EXT); - linkname_ptr=0; - create_flag=MY_DELETE_OLD; + fn_format(filename, ci->data_file_name, "", MARIA_NAME_DEXT, + MY_UNPACK_FILENAME | + (have_dext ? MY_REPLACE_EXT : MY_APPEND_EXT)); } - if ((dfile= - my_create_with_symlink(linkname_ptr, filename, 0, create_mode, - MYF(MY_WME | create_flag))) < 0) - goto err; + fn_format(linkname, name, "",MARIA_NAME_DEXT, + MY_UNPACK_FILENAME | MY_APPEND_EXT); + linkname_ptr=linkname; + create_flag=0; + } + else + { + fn_format(filename,name,"", MARIA_NAME_DEXT, + MY_UNPACK_FILENAME | MY_APPEND_EXT); + linkname_ptr=0; + create_flag=MY_DELETE_OLD; } + if ((dfile= + my_create_with_symlink(linkname_ptr, filename, 0, create_mode, + MYF(MY_WME | create_flag))) < 0) + goto err; errpos=3; + + if (record_type == BLOCK_RECORD) + { + /* Write one bitmap page */ + char buff[IO_SIZE]; + uint i; + bzero(buff, sizeof(buff)); + for (i= 0 ; i < maria_block_size ; i+= IO_SIZE) + if (my_write(dfile, (byte*) buff, sizeof(buff), MYF(MY_NABP))) + goto err; + share.state.state.data_file_length= maria_block_size; + } } DBUG_PRINT("info", ("write state info and base info")); if (_ma_state_info_write(file, &share.state, 2) || _ma_base_info_write(file, &share.base)) goto err; -#ifndef DBUG_OFF - if ((uint) my_tell(file,MYF(0)) != base_pos+ MARIA_BASE_INFO_SIZE) - { - uint pos=(uint) my_tell(file,MYF(0)); - DBUG_PRINT("warning",("base_length: %d != used_length: %d", - base_pos+ MARIA_BASE_INFO_SIZE, pos)); - } -#endif + DBUG_PRINT("info", ("base_pos: %d base_info_size: %d", + base_pos, MARIA_BASE_INFO_SIZE)); + DBUG_ASSERT(my_tell(file,MYF(0)) == base_pos+ MARIA_BASE_INFO_SIZE); /* Write key and keyseg definitions */ DBUG_PRINT("info", ("write key and keyseg definitions")); @@ -738,7 +807,7 @@ int maria_create(const char *name,uint keys,MARIA_KEYDEF *keydefs, { tmp_keydef.keysegs=1; tmp_keydef.flag= HA_UNIQUE_CHECK; - tmp_keydef.block_length= (uint16)maria_block_size; + tmp_keydef.block_length= (uint16) maria_block_size; tmp_keydef.keylength= MARIA_UNIQUE_HASH_LENGTH + pointer; tmp_keydef.minlength=tmp_keydef.maxlength=tmp_keydef.keylength; tmp_keyseg.type= MARIA_UNIQUE_HASH_TYPE; @@ -776,6 +845,7 @@ int maria_create(const char *name,uint keys,MARIA_KEYDEF *keydefs, } break; default: + DBUG_ASSERT((keyseg->flag & HA_VAR_LENGTH_PART) == 0); break; } if (_ma_keyseg_write(file, keyseg)) @@ -783,9 +853,27 @@ int maria_create(const char *name,uint keys,MARIA_KEYDEF *keydefs, } } DBUG_PRINT("info", ("write field definitions")); - for (i=0 ; i < share.base.fields ; i++) - if (_ma_recinfo_write(file, &recinfo[i])) + if (record_type == BLOCK_RECORD) + { + /* Store columns in a more efficent order */ + MARIA_COLUMNDEF **tmp, **pos; + if (!(tmp= (MARIA_COLUMNDEF**) my_malloc(share.base.fields * + sizeof(MARIA_COLUMNDEF*), + MYF(MY_WME)))) goto err; + for (rec= recinfo, pos= tmp ; rec != rec_end ; rec++, pos++) + *pos= rec; + qsort(tmp, share.base.fields, sizeof(*tmp), (qsort_cmp) compare_columns); + for (i=0 ; i < share.base.fields ; i++) + if (_ma_recinfo_write(file, tmp[i])) + goto err; + } + else + { + for (i=0 ; i < share.base.fields ; i++) + if (_ma_recinfo_write(file, &recinfo[i])) + goto err; + } #ifndef DBUG_OFF if ((uint) my_tell(file,MYF(0)) != info_length) @@ -797,7 +885,8 @@ int maria_create(const char *name,uint keys,MARIA_KEYDEF *keydefs, #endif /* Enlarge files */ - DBUG_PRINT("info", ("enlarge to keystart: %lu", (ulong) share.base.keystart)); + DBUG_PRINT("info", ("enlarge to keystart: %lu", + (ulong) share.base.keystart)); if (my_chsize(file,(ulong) share.base.keystart,0,MYF(0))) goto err; @@ -826,7 +915,6 @@ err: VOID(my_close(dfile,MYF(0))); /* fall through */ case 2: - /* QQ: Tõnu should add a call to my_raid_delete() here */ if (! (flags & HA_DONT_TOUCH_DATA)) my_delete_with_symlink(fn_format(filename,name,"",MARIA_NAME_DEXT, MY_UNPACK_FILENAME | MY_APPEND_EXT), @@ -868,3 +956,59 @@ uint maria_get_pointer_length(ulonglong file_length, uint def) } return def; } + + +/* + Sort columns for records-in-block + + IMPLEMENTATION + Sort columns in following order: + + Fixed size, not null columns + Fixed length, null fields + Variable length fields (CHAR, VARCHAR) + Blobs + + For same kind of fields, keep fields in original order +*/ + +static inline int sign(longlong a) +{ + return a < 0 ? -1 : (a > 0 ? 1 : 0); +} + + +int compare_columns(MARIA_COLUMNDEF **a_ptr, MARIA_COLUMNDEF **b_ptr) +{ + MARIA_COLUMNDEF *a= *a_ptr, *b= *b_ptr; + enum en_fieldtype a_type, b_type; + + a_type= (a->type == FIELD_NORMAL || a->type == FIELD_CHECK ? + FIELD_NORMAL : a->type); + b_type= (b->type == FIELD_NORMAL || b->type == FIELD_CHECK ? + FIELD_NORMAL : b->type); + + if (a_type == FIELD_NORMAL && !a->null_bit) + { + if (b_type != FIELD_NORMAL || b->null_bit) + return -1; + return sign((long) (a->offset - b->offset)); + } + if (b_type == FIELD_NORMAL && !b->null_bit) + return 1; + if (a_type == b_type) + return sign((long) (a->offset - b->offset)); + if (a_type == FIELD_NORMAL) + return -1; + if (b_type == FIELD_NORMAL) + return 1; + if (a_type == FIELD_BLOB) + return 1; + if (b_type == FIELD_BLOB) + return -1; + return sign((long) (a->offset - b->offset)); +} + + + + diff --git a/storage/maria/ma_dbug.c b/storage/maria/ma_dbug.c index 7f2bff85047..596bf18bfe5 100644 --- a/storage/maria/ma_dbug.c +++ b/storage/maria/ma_dbug.c @@ -21,15 +21,15 @@ /* Print a key in user understandable format */ void _ma_print_key(FILE *stream, register HA_KEYSEG *keyseg, - const uchar *key, uint length) + const byte *key, uint length) { int flag; short int s_1; long int l_1; float f_1; double d_1; - const uchar *end; - const uchar *key_end=key+length; + const byte *end; + const byte *key_end= key + length; VOID(fputs("Key: \"",stream)); flag=0; diff --git a/storage/maria/ma_delete.c b/storage/maria/ma_delete.c index d1ad9edbed5..2669585202a 100644 --- a/storage/maria/ma_delete.c +++ b/storage/maria/ma_delete.c @@ -20,26 +20,25 @@ #include "ma_rt_index.h" static int d_search(MARIA_HA *info,MARIA_KEYDEF *keyinfo,uint comp_flag, - uchar *key,uint key_length,my_off_t page,uchar *anc_buff); -static int del(MARIA_HA *info,MARIA_KEYDEF *keyinfo,uchar *key,uchar *anc_buff, - my_off_t leaf_page,uchar *leaf_buff,uchar *keypos, - my_off_t next_block,uchar *ret_key); -static int underflow(MARIA_HA *info,MARIA_KEYDEF *keyinfo,uchar *anc_buff, - my_off_t leaf_page,uchar *leaf_buff,uchar *keypos); -static uint remove_key(MARIA_KEYDEF *keyinfo,uint nod_flag,uchar *keypos, - uchar *lastkey,uchar *page_end, + byte *key,uint key_length,my_off_t page,byte *anc_buff); +static int del(MARIA_HA *info,MARIA_KEYDEF *keyinfo,byte *key,byte *anc_buff, + my_off_t leaf_page,byte *leaf_buff,byte *keypos, + my_off_t next_block,byte *ret_key); +static int underflow(MARIA_HA *info,MARIA_KEYDEF *keyinfo,byte *anc_buff, + my_off_t leaf_page,byte *leaf_buff,byte *keypos); +static uint remove_key(MARIA_KEYDEF *keyinfo,uint nod_flag,byte *keypos, + byte *lastkey,byte *page_end, my_off_t *next_block); static int _ma_ck_real_delete(register MARIA_HA *info,MARIA_KEYDEF *keyinfo, - uchar *key, uint key_length, my_off_t *root); + byte *key, uint key_length, my_off_t *root); int maria_delete(MARIA_HA *info,const byte *record) { uint i; - uchar *old_key; + byte *old_key; int save_errno; char lastpos[8]; - MARIA_SHARE *share=info->s; DBUG_ENTER("maria_delete"); @@ -61,17 +60,15 @@ int maria_delete(MARIA_HA *info,const byte *record) } if (_ma_readinfo(info,F_WRLCK,1)) DBUG_RETURN(my_errno); - if (info->s->calc_checksum) - info->checksum=(*info->s->calc_checksum)(info,record); if ((*share->compare_record)(info,record)) goto err; /* Error on read-check */ if (_ma_mark_file_changed(info)) goto err; - /* Remove all keys from the .ISAM file */ + /* Remove all keys from the index file */ - old_key=info->lastkey2; + old_key= info->lastkey2; for (i=0 ; i < share->base.keys ; i++ ) { if (maria_is_key_active(info->s->state.key_map, i)) @@ -79,13 +76,13 @@ int maria_delete(MARIA_HA *info,const byte *record) info->s->keyinfo[i].version++; if (info->s->keyinfo[i].flag & HA_FULLTEXT ) { - if (_ma_ft_del(info,i,(char*) old_key,record,info->lastpos)) + if (_ma_ft_del(info,i,(char*) old_key,record,info->cur_row.lastpos)) goto err; } else { if (info->s->keyinfo[i].ck_delete(info,i,old_key, - _ma_make_key(info,i,old_key,record,info->lastpos))) + _ma_make_key(info,i,old_key,record,info->cur_row.lastpos))) goto err; } /* The above changed info->lastkey2. Inform maria_rnext_same(). */ @@ -95,12 +92,21 @@ int maria_delete(MARIA_HA *info,const byte *record) if ((*share->delete_record)(info)) goto err; /* Remove record from database */ - info->state->checksum-=info->checksum; + + /* + We can't use the row based checksum as this doesn't have enough + precision. + */ + if (info->s->calc_checksum) + { + info->cur_row.checksum= (*info->s->calc_checksum)(info,record); + info->state->checksum-= info->cur_row.checksum; + } info->update= HA_STATE_CHANGED+HA_STATE_DELETED+HA_STATE_ROW_CHANGED; info->state->records--; - mi_sizestore(lastpos,info->lastpos); + mi_sizestore(lastpos, info->cur_row.lastpos); VOID(_ma_writeinfo(info,WRITEINFO_UPDATE_KEYFILE)); allow_break(); /* Allow SIGHUP & SIGINT */ if (info->invalidator != 0) @@ -113,7 +119,7 @@ int maria_delete(MARIA_HA *info,const byte *record) err: save_errno=my_errno; - mi_sizestore(lastpos,info->lastpos); + mi_sizestore(lastpos, info->cur_row.lastpos); if (save_errno != HA_ERR_RECORD_CHANGED) { maria_print_error(info->s, HA_ERR_CRASHED); @@ -135,7 +141,7 @@ err: /* Remove a key from the btree index */ -int _ma_ck_delete(register MARIA_HA *info, uint keynr, uchar *key, +int _ma_ck_delete(register MARIA_HA *info, uint keynr, byte *key, uint key_length) { return _ma_ck_real_delete(info, info->s->keyinfo+keynr, key, key_length, @@ -144,12 +150,12 @@ int _ma_ck_delete(register MARIA_HA *info, uint keynr, uchar *key, static int _ma_ck_real_delete(register MARIA_HA *info, MARIA_KEYDEF *keyinfo, - uchar *key, uint key_length, my_off_t *root) + byte *key, uint key_length, my_off_t *root) { int error; uint nod_flag; my_off_t old_root; - uchar *root_buff; + byte *root_buff; DBUG_ENTER("_ma_ck_real_delete"); if ((old_root=*root) == HA_OFFSET_ERROR) @@ -157,7 +163,7 @@ static int _ma_ck_real_delete(register MARIA_HA *info, MARIA_KEYDEF *keyinfo, maria_print_error(info->s, HA_ERR_CRASHED); DBUG_RETURN(my_errno=HA_ERR_CRASHED); } - if (!(root_buff= (uchar*) my_alloca((uint) keyinfo->block_length+ + if (!(root_buff= (byte*) my_alloca((uint) keyinfo->block_length+ HA_MAX_KEY_BUFF*2))) { DBUG_PRINT("error",("Couldn't allocate memory")); @@ -212,17 +218,17 @@ err: */ static int d_search(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo, - uint comp_flag, uchar *key, uint key_length, - my_off_t page, uchar *anc_buff) + uint comp_flag, byte *key, uint key_length, + my_off_t page, byte *anc_buff) { int flag,ret_value,save_flag; uint length,nod_flag,search_key_length; my_bool last_key; - uchar *leaf_buff,*keypos; + byte *leaf_buff,*keypos; my_off_t leaf_page,next_block; - uchar lastkey[HA_MAX_KEY_BUFF]; + byte lastkey[HA_MAX_KEY_BUFF]; DBUG_ENTER("d_search"); - DBUG_DUMP("page",(byte*) anc_buff,maria_getint(anc_buff)); + DBUG_DUMP("page",anc_buff,maria_getint(anc_buff)); search_key_length= (comp_flag & SEARCH_FIND) ? key_length : USE_WHOLE_KEY; flag=(*keyinfo->bin_search)(info,keyinfo,anc_buff,key, search_key_length, @@ -264,7 +270,7 @@ static int d_search(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo, /* popular word. two-level tree. going down */ uint tmp_key_length; my_off_t root; - uchar *kpos=keypos; + byte *kpos=keypos; if (!(tmp_key_length=(*keyinfo->get_key)(keyinfo,nod_flag,&kpos,lastkey))) { @@ -304,8 +310,8 @@ static int d_search(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo, if (nod_flag) { leaf_page= _ma_kpos(nod_flag,keypos); - if (!(leaf_buff= (uchar*) my_alloca((uint) keyinfo->block_length+ - HA_MAX_KEY_BUFF*2))) + if (!(leaf_buff= (byte*) my_alloca((uint) keyinfo->block_length+ + HA_MAX_KEY_BUFF*2))) { DBUG_PRINT("error",("Couldn't allocate memory")); my_errno=ENOMEM; @@ -366,7 +372,7 @@ static int d_search(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo, if (!_ma_get_last_key(info,keyinfo,anc_buff,lastkey,keypos,&length)) goto err; ret_value= _ma_insert(info,keyinfo,key,anc_buff,keypos,lastkey, - (uchar*) 0,(uchar*) 0,(my_off_t) 0,(my_bool) 0); + (byte*) 0,(byte*) 0,(my_off_t) 0,(my_bool) 0); } } if (ret_value == 0 && maria_getint(anc_buff) > keyinfo->block_length) @@ -378,14 +384,14 @@ static int d_search(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo, ret_value|= _ma_write_keypage(info,keyinfo,page,DFLT_INIT_HITS,anc_buff); else { - DBUG_DUMP("page",(byte*) anc_buff,maria_getint(anc_buff)); + DBUG_DUMP("page",anc_buff,maria_getint(anc_buff)); } - my_afree((byte*) leaf_buff); + my_afree(leaf_buff); DBUG_PRINT("exit",("Return: %d",ret_value)); DBUG_RETURN(ret_value); err: - my_afree((byte*) leaf_buff); + my_afree(leaf_buff); DBUG_PRINT("exit",("Error: %d",my_errno)); DBUG_RETURN (-1); } /* d_search */ @@ -393,24 +399,25 @@ err: /* Remove a key that has a page-reference */ -static int del(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo, uchar *key, - uchar *anc_buff, my_off_t leaf_page, uchar *leaf_buff, - uchar *keypos, /* Pos to where deleted key was */ +static int del(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo, + byte *key, byte *anc_buff, my_off_t leaf_page, + byte *leaf_buff, + byte *keypos, /* Pos to where deleted key was */ my_off_t next_block, - uchar *ret_key) /* key before keypos in anc_buff */ + byte *ret_key) /* key before keypos in anc_buff */ { int ret_value,length; uint a_length,nod_flag,tmp; my_off_t next_page; - uchar keybuff[HA_MAX_KEY_BUFF],*endpos,*next_buff,*key_start, *prev_key; + byte keybuff[HA_MAX_KEY_BUFF],*endpos,*next_buff,*key_start, *prev_key; MARIA_SHARE *share=info->s; MARIA_KEY_PARAM s_temp; DBUG_ENTER("del"); DBUG_PRINT("enter",("leaf_page: %ld keypos: 0x%lx", leaf_page, (ulong) keypos)); - DBUG_DUMP("leaf_buff",(byte*) leaf_buff,maria_getint(leaf_buff)); + DBUG_DUMP("leaf_buff",leaf_buff,maria_getint(leaf_buff)); - endpos=leaf_buff+maria_getint(leaf_buff); + endpos= leaf_buff+ maria_getint(leaf_buff); if (!(key_start= _ma_get_last_key(info,keyinfo,leaf_buff,keybuff,endpos, &tmp))) DBUG_RETURN(-1); @@ -418,14 +425,14 @@ static int del(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo, uchar *k if ((nod_flag=_ma_test_if_nod(leaf_buff))) { next_page= _ma_kpos(nod_flag,endpos); - if (!(next_buff= (uchar*) my_alloca((uint) keyinfo->block_length+ + if (!(next_buff= (byte*) my_alloca((uint) keyinfo->block_length+ HA_MAX_KEY_BUFF*2))) DBUG_RETURN(-1); if (!_ma_fetch_keypage(info,keyinfo,next_page,DFLT_INIT_HITS,next_buff,0)) ret_value= -1; else { - DBUG_DUMP("next_page",(byte*) next_buff,maria_getint(next_buff)); + DBUG_DUMP("next_page",next_buff,maria_getint(next_buff)); if ((ret_value=del(info,keyinfo,key,anc_buff,next_page,next_buff, keypos,next_block,ret_key)) >0) { @@ -446,13 +453,13 @@ static int del(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo, uchar *k &tmp)) goto err; ret_value= _ma_insert(info,keyinfo,key,leaf_buff,endpos,keybuff, - (uchar*) 0,(uchar*) 0,(my_off_t) 0,0); + (byte*) 0,(byte*) 0,(my_off_t) 0,0); } } if (_ma_write_keypage(info,keyinfo,leaf_page,DFLT_INIT_HITS,leaf_buff)) goto err; } - my_afree((byte*) next_buff); + my_afree(next_buff); DBUG_RETURN(ret_value); } @@ -472,11 +479,11 @@ static int del(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo, uchar *k prev_key=(keypos == anc_buff+2+share->base.key_reflength ? 0 : ret_key); length=(*keyinfo->pack_key)(keyinfo,share->base.key_reflength, - keypos == endpos ? (uchar*) 0 : keypos, + keypos == endpos ? (byte*) 0 : keypos, prev_key, prev_key, keybuff,&s_temp); if (length > 0) - bmove_upp((byte*) endpos+length,(byte*) endpos,(uint) (endpos-keypos)); + bmove_upp(endpos+length,endpos,(uint) (endpos-keypos)); else bmove(keypos,keypos-length, (int) (endpos-keypos)+length); (*keyinfo->store_key)(keyinfo,keypos,&s_temp); @@ -497,28 +504,28 @@ err: /* Balances adjacent pages if underflow occours */ static int underflow(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo, - uchar *anc_buff, + byte *anc_buff, my_off_t leaf_page,/* Ancestor page and underflow page */ - uchar *leaf_buff, - uchar *keypos) /* Position to pos after key */ + byte *leaf_buff, + byte *keypos) /* Position to pos after key */ { int t_length; uint length,anc_length,buff_length,leaf_length,p_length,s_length,nod_flag, key_reflength,key_length; my_off_t next_page; - uchar anc_key[HA_MAX_KEY_BUFF],leaf_key[HA_MAX_KEY_BUFF], - *buff,*endpos,*next_keypos,*anc_pos,*half_pos,*temp_pos,*prev_key, - *after_key; + byte anc_key[HA_MAX_KEY_BUFF],leaf_key[HA_MAX_KEY_BUFF]; + byte *buff,*endpos,*next_keypos,*anc_pos,*half_pos,*temp_pos,*prev_key; + byte *after_key; MARIA_KEY_PARAM s_temp; MARIA_SHARE *share=info->s; DBUG_ENTER("underflow"); DBUG_PRINT("enter",("leaf_page: %ld keypos: 0x%lx",(long) leaf_page, (ulong) keypos)); - DBUG_DUMP("anc_buff",(byte*) anc_buff,maria_getint(anc_buff)); - DBUG_DUMP("leaf_buff",(byte*) leaf_buff,maria_getint(leaf_buff)); + DBUG_DUMP("anc_buff",anc_buff,maria_getint(anc_buff)); + DBUG_DUMP("leaf_buff",leaf_buff,maria_getint(leaf_buff)); buff=info->buff; - info->buff_used=1; + info->keybuff_used=1; next_keypos=keypos; nod_flag=_ma_test_if_nod(leaf_buff); p_length=nod_flag+2; @@ -551,26 +558,25 @@ static int underflow(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo, if (!_ma_fetch_keypage(info,keyinfo,next_page,DFLT_INIT_HITS,buff,0)) goto err; buff_length=maria_getint(buff); - DBUG_DUMP("next",(byte*) buff,buff_length); + DBUG_DUMP("next",buff,buff_length); /* find keys to make a big key-page */ - bmove((byte*) next_keypos-key_reflength,(byte*) buff+2, - key_reflength); + bmove(next_keypos-key_reflength, buff+2, key_reflength); if (!_ma_get_last_key(info,keyinfo,anc_buff,anc_key,next_keypos,&length) || !_ma_get_last_key(info,keyinfo,leaf_buff,leaf_key, leaf_buff+leaf_length,&length)) goto err; /* merge pages and put parting key from anc_buff between */ - prev_key=(leaf_length == p_length ? (uchar*) 0 : leaf_key); + prev_key=(leaf_length == p_length ? (byte*) 0 : leaf_key); t_length=(*keyinfo->pack_key)(keyinfo,nod_flag,buff+p_length, prev_key, prev_key, anc_key, &s_temp); length=buff_length-p_length; endpos=buff+length+leaf_length+t_length; /* buff will always be larger than before !*/ - bmove_upp((byte*) endpos, (byte*) buff+buff_length,length); - memcpy((byte*) buff, (byte*) leaf_buff,(size_t) leaf_length); + bmove_upp(endpos, buff+buff_length,length); + memcpy(buff, leaf_buff,(size_t) leaf_length); (*keyinfo->store_key)(keyinfo,buff+leaf_length,&s_temp); buff_length=(uint) (endpos-buff); maria_putint(buff,buff_length,nod_flag); @@ -586,14 +592,14 @@ static int underflow(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo, if (buff_length <= keyinfo->block_length) { /* Keys in one page */ - memcpy((byte*) leaf_buff,(byte*) buff,(size_t) buff_length); + memcpy(leaf_buff,buff,(size_t) buff_length); if (_ma_dispose(info,keyinfo,next_page,DFLT_INIT_HITS)) goto err; } else { /* Page is full */ endpos=anc_buff+anc_length; - DBUG_PRINT("test",("anc_buff: %lx endpos: %lx",anc_buff,endpos)); + DBUG_PRINT("test",("anc_buff: 0x%lx endpos: 0x%lx",anc_buff,endpos)); if (keypos != anc_buff+2+key_reflength && !_ma_get_last_key(info,keyinfo,anc_buff,anc_key,keypos,&length)) goto err; @@ -601,22 +607,21 @@ static int underflow(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo, &key_length, &after_key))) goto err; length=(uint) (half_pos-buff); - memcpy((byte*) leaf_buff,(byte*) buff,(size_t) length); + memcpy(leaf_buff,buff,(size_t) length); maria_putint(leaf_buff,length,nod_flag); /* Correct new keypointer to leaf_page */ half_pos=after_key; _ma_kpointer(info,leaf_key+key_length,next_page); /* Save key in anc_buff */ - prev_key=(keypos == anc_buff+2+key_reflength ? (uchar*) 0 : anc_key), + prev_key=(keypos == anc_buff+2+key_reflength ? (byte*) 0 : anc_key), t_length=(*keyinfo->pack_key)(keyinfo,key_reflength, - (keypos == endpos ? (uchar*) 0 : + (keypos == endpos ? (byte*) 0 : keypos), prev_key, prev_key, leaf_key, &s_temp); if (t_length >= 0) - bmove_upp((byte*) endpos+t_length,(byte*) endpos, - (uint) (endpos-keypos)); + bmove_upp(endpos+t_length, endpos, (uint) (endpos-keypos)); else bmove(keypos,keypos-t_length,(uint) (endpos-keypos)+t_length); (*keyinfo->store_key)(keyinfo,keypos,&s_temp); @@ -624,15 +629,15 @@ static int underflow(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo, /* Store key first in new page */ if (nod_flag) - bmove((byte*) buff+2,(byte*) half_pos-nod_flag,(size_t) nod_flag); + bmove(buff+2,half_pos-nod_flag,(size_t) nod_flag); if (!(*keyinfo->get_key)(keyinfo,nod_flag,&half_pos,leaf_key)) goto err; - t_length=(int) (*keyinfo->pack_key)(keyinfo, nod_flag, (uchar*) 0, - (uchar*) 0, (uchar *) 0, + t_length=(int) (*keyinfo->pack_key)(keyinfo, nod_flag, (byte*) 0, + (byte*) 0, (byte*) 0, leaf_key, &s_temp); /* t_length will always be > 0 for a new page !*/ length=(uint) ((buff+maria_getint(buff))-half_pos); - bmove((byte*) buff+p_length+t_length,(byte*) half_pos,(size_t) length); + bmove(buff+p_length+t_length, half_pos, (size_t) length); (*keyinfo->store_key)(keyinfo,buff+p_length,&s_temp); maria_putint(buff,length+t_length+p_length,nod_flag); @@ -655,11 +660,10 @@ static int underflow(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo, goto err; buff_length=maria_getint(buff); endpos=buff+buff_length; - DBUG_DUMP("prev",(byte*) buff,buff_length); + DBUG_DUMP("prev",buff,buff_length); /* find keys to make a big key-page */ - bmove((byte*) next_keypos - key_reflength,(byte*) leaf_buff+2, - key_reflength); + bmove(next_keypos - key_reflength, leaf_buff+2, key_reflength); next_keypos=keypos; if (!(*keyinfo->get_key)(keyinfo,key_reflength,&next_keypos, anc_key)) @@ -668,17 +672,17 @@ static int underflow(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo, goto err; /* merge pages and put parting key from anc_buff between */ - prev_key=(leaf_length == p_length ? (uchar*) 0 : leaf_key); + prev_key=(leaf_length == p_length ? (byte*) 0 : leaf_key); t_length=(*keyinfo->pack_key)(keyinfo,nod_flag, (leaf_length == p_length ? - (uchar*) 0 : leaf_buff+p_length), + (byte*) 0 : leaf_buff+p_length), prev_key, prev_key, anc_key, &s_temp); if (t_length >= 0) - bmove((byte*) endpos+t_length,(byte*) leaf_buff+p_length, - (size_t) (leaf_length-p_length)); + bmove(endpos+t_length, leaf_buff+p_length, + (size_t) (leaf_length-p_length)); else /* We gained space */ - bmove((byte*) endpos,(byte*) leaf_buff+((int) p_length-t_length), + bmove(endpos,leaf_buff+((int) p_length-t_length), (size_t) (leaf_length-p_length+t_length)); (*keyinfo->store_key)(keyinfo,endpos,&s_temp); @@ -711,18 +715,17 @@ static int underflow(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo, goto err; _ma_kpointer(info,leaf_key+key_length,leaf_page); /* Save key in anc_buff */ - DBUG_DUMP("anc_buff",(byte*) anc_buff,anc_length); - DBUG_DUMP("key_to_anc",(byte*) leaf_key,key_length); + DBUG_DUMP("anc_buff",anc_buff,anc_length); + DBUG_DUMP("key_to_anc",leaf_key,key_length); temp_pos=anc_buff+anc_length; t_length=(*keyinfo->pack_key)(keyinfo,key_reflength, - keypos == temp_pos ? (uchar*) 0 + keypos == temp_pos ? (byte*) 0 : keypos, anc_pos, anc_pos, leaf_key,&s_temp); if (t_length > 0) - bmove_upp((byte*) temp_pos+t_length,(byte*) temp_pos, - (uint) (temp_pos-keypos)); + bmove_upp(temp_pos+t_length, temp_pos, (uint) (temp_pos-keypos)); else bmove(keypos,keypos-t_length,(uint) (temp_pos-keypos)+t_length); (*keyinfo->store_key)(keyinfo,keypos,&s_temp); @@ -730,15 +733,15 @@ static int underflow(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo, /* Store first key on new page */ if (nod_flag) - bmove((byte*) leaf_buff+2,(byte*) half_pos-nod_flag,(size_t) nod_flag); + bmove(leaf_buff+2,half_pos-nod_flag,(size_t) nod_flag); if (!(length=(*keyinfo->get_key)(keyinfo,nod_flag,&half_pos,leaf_key))) goto err; - DBUG_DUMP("key_to_leaf",(byte*) leaf_key,length); - t_length=(*keyinfo->pack_key)(keyinfo,nod_flag, (uchar*) 0, - (uchar*) 0, (uchar*) 0, leaf_key, &s_temp); + DBUG_DUMP("key_to_leaf",leaf_key,length); + t_length=(*keyinfo->pack_key)(keyinfo,nod_flag, (byte*) 0, + (byte*) 0, (byte*) 0, leaf_key, &s_temp); length=(uint) ((buff+buff_length)-half_pos); DBUG_PRINT("info",("t_length: %d length: %d",t_length,(int) length)); - bmove((byte*) leaf_buff+p_length+t_length,(byte*) half_pos, + bmove(leaf_buff+p_length+t_length,half_pos, (size_t) length); (*keyinfo->store_key)(keyinfo,leaf_buff+p_length,&s_temp); maria_putint(leaf_buff,length+t_length+p_length,nod_flag); @@ -763,15 +766,15 @@ err: */ static uint remove_key(MARIA_KEYDEF *keyinfo, uint nod_flag, - uchar *keypos, /* Where key starts */ - uchar *lastkey, /* key to be removed */ - uchar *page_end, /* End of page */ + byte *keypos, /* Where key starts */ + byte *lastkey, /* key to be removed */ + byte *page_end, /* End of page */ my_off_t *next_block) /* ptr to next block */ { int s_length; - uchar *start; + byte *start; DBUG_ENTER("remove_key"); - DBUG_PRINT("enter",("keypos: %lx page_end: %lx",keypos,page_end)); + DBUG_PRINT("enter",("keypos: 0x%lx page_end: 0x%lx", keypos, page_end)); start=keypos; if (!(keyinfo->flag & @@ -795,7 +798,7 @@ static uint remove_key(MARIA_KEYDEF *keyinfo, uint nod_flag, { if (keyinfo->flag & HA_BINARY_PACK_KEY) { - uchar *old_key=start; + byte *old_key=start; uint next_length,prev_length,prev_pack_length; get_key_length(next_length,keypos); get_key_pack_length(prev_length,prev_pack_length,old_key); @@ -882,7 +885,6 @@ static uint remove_key(MARIA_KEYDEF *keyinfo, uint nod_flag, } } end: - bmove((byte*) start,(byte*) start+s_length, - (uint) (page_end-start-s_length)); + bmove(start, start+s_length, (uint) (page_end-start-s_length)); DBUG_RETURN((uint) s_length); } /* remove_key */ diff --git a/storage/maria/ma_delete_all.c b/storage/maria/ma_delete_all.c index b16d82ed9f7..3e1448e858a 100644 --- a/storage/maria/ma_delete_all.c +++ b/storage/maria/ma_delete_all.c @@ -43,8 +43,7 @@ int maria_delete_all_rows(MARIA_HA *info) info->state->empty=info->state->key_empty=0; info->state->checksum=0; - for (i=share->base.max_key_block_length/MARIA_MIN_KEY_BLOCK_LENGTH ; i-- ; ) - state->key_del[i]= HA_OFFSET_ERROR; + state->key_del= HA_OFFSET_ERROR; for (i=0 ; i < share->base.keys ; i++) state->key_root[i]= HA_OFFSET_ERROR; diff --git a/storage/maria/ma_dynrec.c b/storage/maria/ma_dynrec.c index 047826408c3..a1d4ee58bf1 100644 --- a/storage/maria/ma_dynrec.c +++ b/storage/maria/ma_dynrec.c @@ -26,19 +26,16 @@ #include "maria_def.h" -/* Enough for comparing if number is zero */ -static char zero_string[]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; - -static int write_dynamic_record(MARIA_HA *info,const byte *record, - ulong reclength); +static my_bool write_dynamic_record(MARIA_HA *info,const byte *record, + ulong reclength); static int _ma_find_writepos(MARIA_HA *info,ulong reclength,my_off_t *filepos, ulong *length); -static int update_dynamic_record(MARIA_HA *info,my_off_t filepos,byte *record, - ulong reclength); -static int delete_dynamic_record(MARIA_HA *info,my_off_t filepos, - uint second_read); -static int _ma_cmp_buffer(File file, const byte *buff, my_off_t filepos, - uint length); +static my_bool update_dynamic_record(MARIA_HA *info, MARIA_RECORD_POS filepos, + byte *record, ulong reclength); +static my_bool delete_dynamic_record(MARIA_HA *info,MARIA_RECORD_POS filepos, + uint second_read); +static my_bool _ma_cmp_buffer(File file, const byte *buff, my_off_t filepos, + uint length); #ifdef THREAD /* Play it safe; We have a small stack when using threads */ @@ -224,19 +221,26 @@ uint _ma_nommap_pwrite(MARIA_HA *info, byte *Buffer, } -int _ma_write_dynamic_record(MARIA_HA *info, const byte *record) +my_bool _ma_write_dynamic_record(MARIA_HA *info, const byte *record) { - ulong reclength= _ma_rec_pack(info,info->rec_buff,record); - return (write_dynamic_record(info,info->rec_buff,reclength)); + ulong reclength= _ma_rec_pack(info,info->rec_buff + MARIA_REC_BUFF_OFFSET, + record); + return (write_dynamic_record(info,info->rec_buff + MARIA_REC_BUFF_OFFSET, + reclength)); } -int _ma_update_dynamic_record(MARIA_HA *info, my_off_t pos, const byte *record) +my_bool _ma_update_dynamic_record(MARIA_HA *info, MARIA_RECORD_POS pos, + const byte *record) { - uint length= _ma_rec_pack(info,info->rec_buff,record); - return (update_dynamic_record(info,pos,info->rec_buff,length)); + uint length= _ma_rec_pack(info, info->rec_buff + MARIA_REC_BUFF_OFFSET, + record); + return (update_dynamic_record(info, pos, + info->rec_buff + MARIA_REC_BUFF_OFFSET, + length)); } -int _ma_write_blob_record(MARIA_HA *info, const byte *record) + +my_bool _ma_write_blob_record(MARIA_HA *info, const byte *record) { byte *rec_buff; int error; @@ -246,31 +250,27 @@ int _ma_write_blob_record(MARIA_HA *info, const byte *record) MARIA_DYN_DELETE_BLOCK_HEADER+1); reclength= (info->s->base.pack_reclength + _ma_calc_total_blob_length(info,record)+ extra); -#ifdef NOT_USED /* We now support big rows */ - if (reclength > MARIA_DYN_MAX_ROW_LENGTH) - { - my_errno=HA_ERR_TO_BIG_ROW; - return -1; - } -#endif if (!(rec_buff=(byte*) my_alloca(reclength))) { my_errno=ENOMEM; - return(-1); + return(1); } - reclength2= _ma_rec_pack(info,rec_buff+ALIGN_SIZE(MARIA_MAX_DYN_BLOCK_HEADER), + reclength2= _ma_rec_pack(info, + rec_buff+ALIGN_SIZE(MARIA_MAX_DYN_BLOCK_HEADER), record); DBUG_PRINT("info",("reclength: %lu reclength2: %lu", reclength, reclength2)); DBUG_ASSERT(reclength2 <= reclength); - error=write_dynamic_record(info,rec_buff+ALIGN_SIZE(MARIA_MAX_DYN_BLOCK_HEADER), - reclength2); + error= write_dynamic_record(info, + rec_buff+ALIGN_SIZE(MARIA_MAX_DYN_BLOCK_HEADER), + reclength2); my_afree(rec_buff); - return(error); + return(error != 0); } -int _ma_update_blob_record(MARIA_HA *info, my_off_t pos, const byte *record) +my_bool _ma_update_blob_record(MARIA_HA *info, MARIA_RECORD_POS pos, + const byte *record) { byte *rec_buff; int error; @@ -284,13 +284,13 @@ int _ma_update_blob_record(MARIA_HA *info, my_off_t pos, const byte *record) if (reclength > MARIA_DYN_MAX_ROW_LENGTH) { my_errno=HA_ERR_TO_BIG_ROW; - return -1; + return 1; } #endif if (!(rec_buff=(byte*) my_alloca(reclength))) { my_errno=ENOMEM; - return(-1); + return(1); } reclength= _ma_rec_pack(info,rec_buff+ALIGN_SIZE(MARIA_MAX_DYN_BLOCK_HEADER), record); @@ -298,20 +298,20 @@ int _ma_update_blob_record(MARIA_HA *info, my_off_t pos, const byte *record) rec_buff+ALIGN_SIZE(MARIA_MAX_DYN_BLOCK_HEADER), reclength); my_afree(rec_buff); - return(error); + return(error != 0); } -int _ma_delete_dynamic_record(MARIA_HA *info) +my_bool _ma_delete_dynamic_record(MARIA_HA *info) { - return delete_dynamic_record(info,info->lastpos,0); + return delete_dynamic_record(info, info->cur_row.lastpos, 0); } /* Write record to data-file */ -static int write_dynamic_record(MARIA_HA *info, const byte *record, - ulong reclength) +static my_bool write_dynamic_record(MARIA_HA *info, const byte *record, + ulong reclength) { int flag; ulong length; @@ -443,8 +443,8 @@ static bool unlink_deleted_block(MARIA_HA *info, MARIA_BLOCK_INFO *block_info) (maria_rrnd() or maria_scan(), then ensure that we skip over this block when doing next maria_rrnd() or maria_scan(). */ - if (info->nextpos == block_info->filepos) - info->nextpos+=block_info->block_len; + if (info->cur_row.nextpos == block_info->filepos) + info->cur_row.nextpos+= block_info->block_len; DBUG_RETURN(0); } @@ -464,8 +464,9 @@ static bool unlink_deleted_block(MARIA_HA *info, MARIA_BLOCK_INFO *block_info) 1 error. In this case my_error is set. */ -static int update_backward_delete_link(MARIA_HA *info, my_off_t delete_block, - my_off_t filepos) +static my_bool update_backward_delete_link(MARIA_HA *info, + my_off_t delete_block, + MARIA_RECORD_POS filepos) { MARIA_BLOCK_INFO block_info; DBUG_ENTER("update_backward_delete_link"); @@ -490,11 +491,11 @@ static int update_backward_delete_link(MARIA_HA *info, my_off_t delete_block, DBUG_RETURN(0); } - /* Delete datarecord from database */ - /* info->rec_cache.seek_not_done is updated in cmp_record */ +/* Delete datarecord from database */ +/* info->rec_cache.seek_not_done is updated in cmp_record */ -static int delete_dynamic_record(MARIA_HA *info, my_off_t filepos, - uint second_read) +static my_bool delete_dynamic_record(MARIA_HA *info, MARIA_RECORD_POS filepos, + uint second_read) { uint length,b_type; MARIA_BLOCK_INFO block_info,del_block; @@ -522,7 +523,8 @@ static int delete_dynamic_record(MARIA_HA *info, my_off_t filepos, del_block.second_read=0; remove_next_block=0; if (_ma_get_block_info(&del_block,info->dfile,filepos+length) & - BLOCK_DELETED && del_block.block_len+length < MARIA_DYN_MAX_BLOCK_LENGTH) + BLOCK_DELETED && del_block.block_len+length < + MARIA_DYN_MAX_BLOCK_LENGTH) { /* We can't remove this yet as this block may be the head block */ remove_next_block=1; @@ -719,8 +721,9 @@ int _ma_write_part_record(MARIA_HA *info, else { info->rec_cache.seek_not_done=1; - if (info->s->file_write(info,(byte*) *record-head_length,length+extra_length+ - del_length,filepos,info->s->write_flag)) + if (info->s->file_write(info,(byte*) *record-head_length, + length+extra_length+ + del_length,filepos,info->s->write_flag)) goto err; } memcpy(record_end,temp,(size_t) (extra_length+del_length)); @@ -745,8 +748,8 @@ err: /* update record from datafile */ -static int update_dynamic_record(MARIA_HA *info, my_off_t filepos, byte *record, - ulong reclength) +static my_bool update_dynamic_record(MARIA_HA *info, MARIA_RECORD_POS filepos, + byte *record, ulong reclength) { int flag; uint error; @@ -784,8 +787,8 @@ static int update_dynamic_record(MARIA_HA *info, my_off_t filepos, byte *record, { /* extend file */ DBUG_PRINT("info",("Extending file with %d bytes",tmp)); - if (info->nextpos == info->state->data_file_length) - info->nextpos+= tmp; + if (info->cur_row.nextpos == info->state->data_file_length) + info->cur_row.nextpos+= tmp; info->state->data_file_length+= tmp; info->update|= HA_STATE_WRITE_AT_END | HA_STATE_EXTEND_BLOCK; length+=tmp; @@ -829,8 +832,8 @@ static int update_dynamic_record(MARIA_HA *info, my_off_t filepos, byte *record, mi_int3store(del_block.header+1, rest_length); mi_sizestore(del_block.header+4,info->s->state.dellink); bfill(del_block.header+12,8,255); - if (info->s->file_write(info,(byte*) del_block.header,20, next_pos, - MYF(MY_NABP))) + if (info->s->file_write(info,(byte*) del_block.header, 20, + next_pos, MYF(MY_NABP))) DBUG_RETURN(1); info->s->state.dellink= next_pos; info->s->state.split++; @@ -877,9 +880,18 @@ uint _ma_rec_pack(MARIA_HA *info, register byte *to, register const byte *from) MARIA_BLOB *blob; DBUG_ENTER("_ma_rec_pack"); - flag=0 ; bit=1; - startpos=packpos=to; to+= info->s->base.pack_bits; blob=info->blobs; - rec=info->s->rec; + flag= 0; + bit= 1; + startpos= packpos=to; + to+= info->s->base.pack_bytes; + blob= info->blobs; + rec= info->s->rec; + if (info->s->base.null_bytes) + { + memcpy(to, from, info->s->base.null_bytes); + from+= info->s->base.null_bytes; + to+= info->s->base.null_bytes; + } for (i=info->s->base.fields ; i-- > 0; from+= length,rec++) { @@ -903,7 +915,7 @@ uint _ma_rec_pack(MARIA_HA *info, register byte *to, register const byte *from) } else if (type == FIELD_SKIP_ZERO) { - if (memcmp((byte*) from,zero_string,length) == 0) + if (memcmp((byte*) from, maria_zero_string, length) == 0) flag|=bit; else { @@ -981,7 +993,7 @@ uint _ma_rec_pack(MARIA_HA *info, register byte *to, register const byte *from) if (bit != 1) *packpos= (char) (uchar) flag; if (info->s->calc_checksum) - *to++=(char) info->checksum; + *to++= (byte) info->cur_row.checksum; DBUG_PRINT("exit",("packed length: %d",(int) (to-startpos))); DBUG_RETURN((uint) (to-startpos)); } /* _ma_rec_pack */ @@ -989,7 +1001,7 @@ uint _ma_rec_pack(MARIA_HA *info, register byte *to, register const byte *from) /* - Check if a record was correctly packed. Used only by mariachk + Check if a record was correctly packed. Used only by maria_chk Returns 0 if record is ok. */ @@ -1002,9 +1014,11 @@ my_bool _ma_rec_check(MARIA_HA *info,const char *record, byte *rec_buff, reg3 MARIA_COLUMNDEF *rec; DBUG_ENTER("_ma_rec_check"); - packpos=rec_buff; to= rec_buff+info->s->base.pack_bits; + packpos=rec_buff; to= rec_buff+info->s->base.pack_bytes; rec=info->s->rec; flag= *packpos; bit=1; + record+= info->s->base.null_bytes; + to+= info->s->base.null_bytes; for (i=info->s->base.fields ; i-- > 0; record+= length, rec++) { @@ -1022,7 +1036,7 @@ my_bool _ma_rec_check(MARIA_HA *info,const char *record, byte *rec_buff, } else if (type == FIELD_SKIP_ZERO) { - if (memcmp((byte*) record,zero_string,length) == 0) + if (memcmp((byte*) record, maria_zero_string, length) == 0) { if (!(flag & bit)) goto err; @@ -1098,7 +1112,7 @@ my_bool _ma_rec_check(MARIA_HA *info,const char *record, byte *rec_buff, if (packed_length != (uint) (to - rec_buff) + test(info->s->calc_checksum) || (bit != 1 && (flag & ~(bit - 1)))) goto err; - if (with_checksum && ((uchar) info->checksum != (uchar) *to)) + if (with_checksum && ((uchar) info->cur_row.checksum != (uchar) *to)) { DBUG_PRINT("error",("wrong checksum for row")); goto err; @@ -1129,8 +1143,16 @@ ulong _ma_rec_unpack(register MARIA_HA *info, register byte *to, byte *from, flag= (uchar) *from; bit=1; packpos=from; if (found_length < info->s->base.min_pack_length) goto err; - from+= info->s->base.pack_bits; - min_pack_length=info->s->base.min_pack_length - info->s->base.pack_bits; + from+= info->s->base.pack_bytes; + min_pack_length= info->s->base.min_pack_length - info->s->base.pack_bytes; + + if ((length= info->s->base.null_bytes)) + { + memcpy(to, from, length); + from+= length; + to+= length; + min_pack_length-= length; + } for (rec=info->s->rec , end_field=rec+info->s->base.fields ; rec < end_field ; to+= rec_length, rec++) @@ -1234,13 +1256,13 @@ ulong _ma_rec_unpack(register MARIA_HA *info, register byte *to, byte *from, } } if (info->s->calc_checksum) - from++; + info->cur_row.checksum= (uint) (uchar) *from++; if (to == to_end && from == from_end && (bit == 1 || !(flag & ~(bit-1)))) DBUG_RETURN(found_length); err: my_errno= HA_ERR_WRONG_IN_RECORD; - DBUG_PRINT("error",("to_end: %lx -> %lx from_end: %lx -> %lx", + DBUG_PRINT("error",("to_end: 0x%lx -> 0x%lx from_end: 0x%lx -> 0x%lx", to,to_end,from,from_end)); DBUG_DUMP("from",(byte*) info->rec_buff,info->s->base.min_pack_length); DBUG_RETURN(MY_FILE_ERROR); @@ -1305,16 +1327,17 @@ void _ma_store_blob_length(byte *pos,uint pack_length,uint length) /* Read record from datafile */ - /* Returns 0 if ok, -1 if error */ + /* Returns 0 if ok, 1 if error */ -int _ma_read_dynamic_record(MARIA_HA *info, my_off_t filepos, byte *buf) +int _ma_read_dynamic_record(MARIA_HA *info, byte *buf, + MARIA_RECORD_POS filepos) { int flag; uint b_type,left_length; byte *to; MARIA_BLOCK_INFO block_info; File file; - DBUG_ENTER("maria_read_dynamic_record"); + DBUG_ENTER("_ma_read_dynamic_record"); if (filepos != HA_OFFSET_ERROR) { @@ -1349,17 +1372,18 @@ int _ma_read_dynamic_record(MARIA_HA *info, my_off_t filepos, byte *buf) goto panic; if (info->s->base.blobs) { - if (!(to=_ma_alloc_rec_buff(info, block_info.rec_len, - &info->rec_buff))) + if (_ma_alloc_buffer(&info->rec_buff, &info->rec_buff_size, + block_info.rec_len + + info->s->base.extra_rec_buff_size)) goto err; } - else - to= info->rec_buff; + to= info->rec_buff; left_length=block_info.rec_len; } if (left_length < block_info.data_len || ! block_info.data_len) goto panic; /* Wrong linked record */ - if (info->s->file_read(info,(byte*) to,block_info.data_len,block_info.filepos, + if (info->s->file_read(info,(byte*) to,block_info.data_len, + block_info.filepos, MYF(MY_NABP))) goto panic; left_length-=block_info.data_len; @@ -1369,55 +1393,61 @@ int _ma_read_dynamic_record(MARIA_HA *info, my_off_t filepos, byte *buf) info->update|= HA_STATE_AKTIV; /* We have a aktive record */ fast_ma_writeinfo(info); DBUG_RETURN(_ma_rec_unpack(info,buf,info->rec_buff,block_info.rec_len) != - MY_FILE_ERROR ? 0 : -1); + MY_FILE_ERROR ? 0 : 1); } fast_ma_writeinfo(info); - DBUG_RETURN(-1); /* Wrong data to read */ + DBUG_RETURN(1); /* Wrong data to read */ panic: my_errno=HA_ERR_WRONG_IN_RECORD; err: VOID(_ma_writeinfo(info,0)); - DBUG_RETURN(-1); + DBUG_RETURN(1); } /* compare unique constraint between stored rows */ -int _ma_cmp_dynamic_unique(MARIA_HA *info, MARIA_UNIQUEDEF *def, - const byte *record, my_off_t pos) +my_bool _ma_cmp_dynamic_unique(MARIA_HA *info, MARIA_UNIQUEDEF *def, + const byte *record, MARIA_RECORD_POS pos) { - byte *rec_buff,*old_record; - int error; + byte *old_rec_buff,*old_record; + my_off_t old_rec_buff_size; + my_bool error; DBUG_ENTER("_ma_cmp_dynamic_unique"); if (!(old_record=my_alloca(info->s->base.reclength))) DBUG_RETURN(1); /* Don't let the compare destroy blobs that may be in use */ - rec_buff=info->rec_buff; + old_rec_buff= info->rec_buff; + old_rec_buff_size= info->rec_buff_size; + if (info->s->base.blobs) - info->rec_buff=0; - error= _ma_read_dynamic_record(info,pos,old_record); + info->rec_buff= 0; + error= _ma_read_dynamic_record(info, old_record, pos) != 0; if (!error) - error=_ma_unique_comp(def, record, old_record, def->null_are_equal); + error=_ma_unique_comp(def, record, old_record, def->null_are_equal) != 0; if (info->s->base.blobs) { - my_free(_ma_get_rec_buff_ptr(info, info->rec_buff), MYF(MY_ALLOW_ZERO_PTR)); - info->rec_buff=rec_buff; + my_free(info->rec_buff, MYF(MY_ALLOW_ZERO_PTR)); + info->rec_buff= old_rec_buff; + info->rec_buff_size= old_rec_buff_size; } my_afree(old_record); DBUG_RETURN(error); } - /* Compare of record one disk with packed record in memory */ + /* Compare of record on disk with packed record in memory */ -int _ma_cmp_dynamic_record(register MARIA_HA *info, register const byte *record) +my_bool _ma_cmp_dynamic_record(register MARIA_HA *info, + register const byte *record) { - uint flag,reclength,b_type; + uint flag, reclength, b_type,cmp_length; my_off_t filepos; byte *buffer; MARIA_BLOCK_INFO block_info; + my_bool error= 1; DBUG_ENTER("_ma_cmp_dynamic_record"); /* We are going to do changes; dont let anybody disturb */ @@ -1427,7 +1457,7 @@ int _ma_cmp_dynamic_record(register MARIA_HA *info, register const byte *record) { info->update&= ~(HA_STATE_WRITE_AT_END | HA_STATE_EXTEND_BLOCK); if (flush_io_cache(&info->rec_cache)) - DBUG_RETURN(-1); + DBUG_RETURN(1); } info->rec_cache.seek_not_done=1; @@ -1440,12 +1470,12 @@ int _ma_cmp_dynamic_record(register MARIA_HA *info, register const byte *record) { if (!(buffer=(byte*) my_alloca(info->s->base.pack_reclength+ _ma_calc_total_blob_length(info,record)))) - DBUG_RETURN(-1); + DBUG_RETURN(1); } reclength= _ma_rec_pack(info,buffer,record); record= buffer; - filepos=info->lastpos; + filepos= info->cur_row.lastpos; flag=block_info.second_read=0; block_info.next_filepos=filepos; while (reclength > 0) @@ -1472,9 +1502,13 @@ int _ma_cmp_dynamic_record(register MARIA_HA *info, register const byte *record) my_errno=HA_ERR_WRONG_IN_RECORD; goto err; } - reclength-=block_info.data_len; + reclength-= block_info.data_len; + cmp_length= block_info.data_len; + if (!reclength && info->s->calc_checksum) + cmp_length--; /* 'record' may not contain checksum */ + if (_ma_cmp_buffer(info->dfile,record,block_info.filepos, - block_info.data_len)) + cmp_length)) { my_errno=HA_ERR_RECORD_CHANGED; goto err; @@ -1484,17 +1518,19 @@ int _ma_cmp_dynamic_record(register MARIA_HA *info, register const byte *record) } } my_errno=0; + error= 0; err: if (buffer != info->rec_buff) my_afree((gptr) buffer); - DBUG_RETURN(my_errno); + DBUG_PRINT("exit", ("result: %d", error)); + DBUG_RETURN(error); } /* Compare file to buffert */ -static int _ma_cmp_buffer(File file, const byte *buff, my_off_t filepos, - uint length) +static my_bool _ma_cmp_buffer(File file, const byte *buff, my_off_t filepos, + uint length) { uint next_length; char temp_buff[IO_SIZE*2]; @@ -1514,14 +1550,15 @@ static int _ma_cmp_buffer(File file, const byte *buff, my_off_t filepos, } if (my_pread(file,temp_buff,length,filepos,MYF(MY_NABP))) goto err; - DBUG_RETURN(memcmp((byte*) buff,temp_buff,length)); + DBUG_RETURN(memcmp((byte*) buff,temp_buff,length) != 0); err: DBUG_RETURN(1); } -int _ma_read_rnd_dynamic_record(MARIA_HA *info, byte *buf, - register my_off_t filepos, +int _ma_read_rnd_dynamic_record(MARIA_HA *info, + byte *buf, + register MARIA_RECORD_POS filepos, my_bool skip_deleted_blocks) { int flag,info_read,save_errno; @@ -1594,9 +1631,9 @@ int _ma_read_rnd_dynamic_record(MARIA_HA *info, byte *buf, } if (b_type & (BLOCK_DELETED | BLOCK_SYNC_ERROR)) { - my_errno=HA_ERR_RECORD_DELETED; - info->lastpos=block_info.filepos; - info->nextpos=block_info.filepos+block_info.block_len; + my_errno= HA_ERR_RECORD_DELETED; + info->cur_row.lastpos= block_info.filepos; + info->cur_row.nextpos= block_info.filepos+block_info.block_len; } goto err; } @@ -1604,15 +1641,15 @@ int _ma_read_rnd_dynamic_record(MARIA_HA *info, byte *buf, { if (block_info.rec_len > (uint) share->base.max_pack_length) goto panic; - info->lastpos=filepos; + info->cur_row.lastpos= filepos; if (share->base.blobs) { - if (!(to= _ma_alloc_rec_buff(info, block_info.rec_len, - &info->rec_buff))) + if (_ma_alloc_buffer(&info->rec_buff, &info->rec_buff_size, + block_info.rec_len + + info->s->base.extra_rec_buff_size)) goto err; } - else - to= info->rec_buff; + to= info->rec_buff; left_len=block_info.rec_len; } if (left_len < block_info.data_len) @@ -1658,7 +1695,7 @@ int _ma_read_rnd_dynamic_record(MARIA_HA *info, byte *buf, } if (flag++ == 0) { - info->nextpos=block_info.filepos+block_info.block_len; + info->cur_row.nextpos= block_info.filepos+block_info.block_len; skip_deleted_blocks=0; } left_len-=block_info.data_len; diff --git a/storage/maria/ma_extra.c b/storage/maria/ma_extra.c index d600fedb99b..a75b8084214 100644 --- a/storage/maria/ma_extra.c +++ b/storage/maria/ma_extra.c @@ -19,7 +19,8 @@ #include <sys/mman.h> #endif -static void maria_extra_keyflag(MARIA_HA *info, enum ha_extra_function function); +static void maria_extra_keyflag(MARIA_HA *info, + enum ha_extra_function function); /* @@ -38,7 +39,8 @@ static void maria_extra_keyflag(MARIA_HA *info, enum ha_extra_function function) # error */ -int maria_extra(MARIA_HA *info, enum ha_extra_function function, void *extra_arg) +int maria_extra(MARIA_HA *info, enum ha_extra_function function, + void *extra_arg) { int error=0; ulong cache_size; @@ -49,7 +51,7 @@ int maria_extra(MARIA_HA *info, enum ha_extra_function function, void *extra_arg switch (function) { case HA_EXTRA_RESET_STATE: /* Reset state (don't free buffers) */ info->lastinx= 0; /* Use first index as def */ - info->last_search_keypage=info->lastpos= HA_OFFSET_ERROR; + info->last_search_keypage= info->cur_row.lastpos= HA_OFFSET_ERROR; info->page_changed=1; /* Next/prev gives first/last */ if (info->opt_flag & READ_CACHE_USED) @@ -115,7 +117,7 @@ int maria_extra(MARIA_HA *info, enum ha_extra_function function, void *extra_arg case HA_EXTRA_REINIT_CACHE: if (info->opt_flag & READ_CACHE_USED) { - reinit_io_cache(&info->rec_cache,READ_CACHE,info->nextpos, + reinit_io_cache(&info->rec_cache, READ_CACHE, info->cur_row.nextpos, (pbool) (info->lock_type != F_UNLCK), (pbool) test(info->update & HA_STATE_ROW_CHANGED)); info->update&= ~HA_STATE_ROW_CHANGED; @@ -185,7 +187,7 @@ int maria_extra(MARIA_HA *info, enum ha_extra_function function, void *extra_arg (byte*) info->lastkey,info->lastkey_length); info->save_update= info->update; info->save_lastinx= info->lastinx; - info->save_lastpos= info->lastpos; + info->save_lastpos= info->cur_row.lastpos; info->save_lastkey_length=info->lastkey_length; if (function == HA_EXTRA_REMEMBER_POS) break; @@ -203,7 +205,7 @@ int maria_extra(MARIA_HA *info, enum ha_extra_function function, void *extra_arg info->save_lastkey_length); info->update= info->save_update | HA_STATE_WRITTEN; info->lastinx= info->save_lastinx; - info->lastpos= info->save_lastpos; + info->cur_row.lastpos= info->save_lastpos; info->lastkey_length=info->save_lastkey_length; } info->read_record= share->read_record; @@ -327,8 +329,13 @@ int maria_extra(MARIA_HA *info, enum ha_extra_function function, void *extra_arg maria_mark_crashed(info); /* Fatal error found */ } } - if (share->base.blobs) - _ma_alloc_rec_buff(info, -1, &info->rec_buff); + if (share->base.blobs && info->rec_buff_size > + share->base.default_rec_buff_size) + { + info->rec_buff_size= 1; /* Force realloc */ + _ma_alloc_buffer(&info->rec_buff, &info->rec_buff_size, + share->base.default_rec_buff_size); + } break; case HA_EXTRA_NORMAL: /* Theese isn't in use */ info->quick_mode=0; @@ -419,8 +426,13 @@ int maria_reset(MARIA_HA *info) info->opt_flag&= ~(READ_CACHE_USED | WRITE_CACHE_USED); error= end_io_cache(&info->rec_cache); } - if (share->base.blobs) - _ma_alloc_rec_buff(info, -1, &info->rec_buff); + if (share->base.blobs && info->rec_buff_size > + share->base.default_rec_buff_size) + { + info->rec_buff_size= 1; /* Force realloc */ + _ma_alloc_buffer(&info->rec_buff, &info->rec_buff_size, + share->base.default_rec_buff_size); + } #if defined(HAVE_MMAP) && defined(HAVE_MADVISE) if (info->opt_flag & MEMMAP_USED) madvise(share->file_map,share->state.state.data_file_length,MADV_RANDOM); @@ -428,7 +440,7 @@ int maria_reset(MARIA_HA *info) info->opt_flag&= ~(KEY_READ_USED | REMEMBER_OLD_POS); info->quick_mode=0; info->lastinx= 0; /* Use first index as def */ - info->last_search_keypage= info->lastpos= HA_OFFSET_ERROR; + info->last_search_keypage= info->cur_row.lastpos= HA_OFFSET_ERROR; info->page_changed= 1; info->update= ((info->update & HA_STATE_CHANGED) | HA_STATE_NEXT_FOUND | HA_STATE_PREV_FOUND); diff --git a/storage/maria/ma_ft_boolean_search.c b/storage/maria/ma_ft_boolean_search.c index 83901cb5e47..40ac88bfcbf 100644 --- a/storage/maria/ma_ft_boolean_search.c +++ b/storage/maria/ma_ft_boolean_search.c @@ -332,7 +332,7 @@ static int _ft2_search(FTB *ftb, FTB_WORD *ftbw, my_bool init_search) my_bool can_go_down; MARIA_HA *info=ftb->info; uint off, extra=HA_FT_WLEN+info->s->base.rec_reflength; - byte *lastkey_buf=ftbw->word+ftbw->off; + byte *lastkey_buf= ftbw->word+ftbw->off; LINT_INIT(off); if (ftbw->flags & FTB_FLAG_TRUNC) @@ -343,7 +343,7 @@ static int _ft2_search(FTB *ftb, FTB_WORD *ftbw, my_bool init_search) ftbw->key_root=info->s->state.key_root[ftb->keynr]; ftbw->keyinfo=info->s->keyinfo+ftb->keynr; - r= _ma_search(info, ftbw->keyinfo, (uchar*) ftbw->word, ftbw->len, + r= _ma_search(info, ftbw->keyinfo, ftbw->word, ftbw->len, SEARCH_FIND | SEARCH_BIGGER, ftbw->key_root); } else @@ -352,10 +352,10 @@ static int _ft2_search(FTB *ftb, FTB_WORD *ftbw, my_bool init_search) if (ftbw->docid[0] < *ftbw->max_docid) { sflag|= SEARCH_SAME; - _ma_dpointer(info, (uchar *)(ftbw->word + ftbw->len + HA_FT_WLEN), + _ma_dpointer(info, (ftbw->word + ftbw->len + HA_FT_WLEN), *ftbw->max_docid); } - r= _ma_search(info, ftbw->keyinfo, (uchar*) lastkey_buf, + r= _ma_search(info, ftbw->keyinfo, lastkey_buf, USE_WHOLE_KEY, sflag, ftbw->key_root); } @@ -369,7 +369,7 @@ static int _ft2_search(FTB *ftb, FTB_WORD *ftbw, my_bool init_search) off=info->lastkey_length-extra; subkeys=ft_sintXkorr(info->lastkey+off); } - if (subkeys<0 || info->lastpos < info->state->data_file_length) + if (subkeys<0 || info->cur_row.lastpos < info->state->data_file_length) break; r= _ma_search_next(info, ftbw->keyinfo, info->lastkey, info->lastkey_length, @@ -379,11 +379,11 @@ static int _ft2_search(FTB *ftb, FTB_WORD *ftbw, my_bool init_search) if (!r && !ftbw->off) { r= ha_compare_text(ftb->charset, - info->lastkey+1, + (uchar*) info->lastkey+1, info->lastkey_length-extra-1, - (uchar*) ftbw->word+1, + (uchar*) ftbw->word+1, ftbw->len-1, - (my_bool) (ftbw->flags & FTB_FLAG_TRUNC),0); + (my_bool) (ftbw->flags & FTB_FLAG_TRUNC), 0); } if (r) /* not found */ @@ -405,7 +405,7 @@ static int _ft2_search(FTB *ftb, FTB_WORD *ftbw, my_bool init_search) } /* going up to the first-level tree to continue search there */ - _ma_dpointer(info, (uchar*) (lastkey_buf+HA_FT_WLEN), ftbw->key_root); + _ma_dpointer(info, (lastkey_buf+HA_FT_WLEN), ftbw->key_root); ftbw->key_root=info->s->state.key_root[ftb->keynr]; ftbw->keyinfo=info->s->keyinfo+ftb->keynr; ftbw->off=0; @@ -425,15 +425,15 @@ static int _ft2_search(FTB *ftb, FTB_WORD *ftbw, my_bool init_search) TODO here: subkey-based optimization */ ftbw->off=off; - ftbw->key_root=info->lastpos; + ftbw->key_root= info->cur_row.lastpos; ftbw->keyinfo=& info->s->ft2_keyinfo; r= _ma_search_first(info, ftbw->keyinfo, ftbw->key_root); DBUG_ASSERT(r==0); /* found something */ memcpy(lastkey_buf+off, info->lastkey, info->lastkey_length); } - ftbw->docid[0]=info->lastpos; + ftbw->docid[0]= info->cur_row.lastpos; if (ftbw->flags & FTB_FLAG_YES) - *ftbw->max_docid= info->lastpos; + *ftbw->max_docid= info->cur_row.lastpos; return 0; } @@ -796,11 +796,11 @@ int maria_ft_boolean_read_next(FT_INFO *ftb, char *record) /* but it managed already to get past this line once */ continue; - info->lastpos=curdoc; + info->cur_row.lastpos= curdoc; /* Clear all states, except that the table was updated */ info->update&= (HA_STATE_CHANGED | HA_STATE_ROW_CHANGED); - if (!(*info->read_record)(info,curdoc,record)) + if (!(*info->read_record)(info, record, curdoc)) { info->update|= HA_STATE_AKTIV; /* Record is read */ if (ftb->with_scan && maria_ft_boolean_find_relevance(ftb,record,0)==0) @@ -851,9 +851,9 @@ static int ftb_find_relevance_add_word(MYSQL_FTPARSER_PARAM *param, (uchar*)ftbw->word + 1,ftbw->len - 1, (my_bool)(ftbw->flags & FTB_FLAG_TRUNC), 0)) break; - if (ftbw->docid[1] == ftb->info->lastpos) + if (ftbw->docid[1] == ftb->info->cur_row.lastpos) continue; - ftbw->docid[1]= ftb->info->lastpos; + ftbw->docid[1]= ftb->info->cur_row.lastpos; _ftb_climb_the_tree(ftb, ftbw, ftb_param->ftsi); } return(0); @@ -877,7 +877,7 @@ float maria_ft_boolean_find_relevance(FT_INFO *ftb, byte *record, uint length) { FTB_EXPR *ftbe; FT_SEG_ITERATOR ftsi, ftsi2; - my_off_t docid=ftb->info->lastpos; + MARIA_RECORD_POS docid= ftb->info->cur_row.lastpos; MY_FTB_FIND_PARAM ftb_param; MYSQL_FTPARSER_PARAM *param; struct st_mysql_ftparser *parser= ftb->keynr == NO_SUCH_KEY ? diff --git a/storage/maria/ma_ft_nlq_search.c b/storage/maria/ma_ft_nlq_search.c index 993857aecbb..4c922516455 100644 --- a/storage/maria/ma_ft_nlq_search.c +++ b/storage/maria/ma_ft_nlq_search.c @@ -69,8 +69,8 @@ static int walk_and_match(FT_WORD *word, uint32 count, ALL_IN_ONE *aio) FT_SUPERDOC sdoc, *sptr; TREE_ELEMENT *selem; double gweight=1; - MARIA_HA *info=aio->info; - uchar *keybuff=aio->keybuff; + MARIA_HA *info= aio->info; + byte *keybuff= (byte*) aio->keybuff; MARIA_KEYDEF *keyinfo=info->s->keyinfo+aio->keynr; my_off_t key_root=info->s->state.key_root[aio->keynr]; uint extra=HA_FT_WLEN+info->s->base.rec_reflength; @@ -92,7 +92,7 @@ static int walk_and_match(FT_WORD *word, uint32 count, ALL_IN_ONE *aio) for (r= _ma_search(info, keyinfo, keybuff, keylen, SEARCH_FIND, key_root) ; !r && (subkeys=ft_sintXkorr(info->lastkey+info->lastkey_length-extra)) > 0 && - info->lastpos >= info->state->data_file_length ; + info->cur_row.lastpos >= info->state->data_file_length ; r= _ma_search_next(info, keyinfo, info->lastkey, info->lastkey_length, SEARCH_BIGGER, key_root)) ; @@ -104,8 +104,9 @@ static int walk_and_match(FT_WORD *word, uint32 count, ALL_IN_ONE *aio) { if (keylen && - ha_compare_text(aio->charset,info->lastkey+1, - info->lastkey_length-extra-1, keybuff+1,keylen-1,0,0)) + ha_compare_text(aio->charset, + (uchar*) info->lastkey+1, info->lastkey_length-extra-1, + (uchar*) keybuff+1, keylen-1, 0, 0)) break; if (subkeys<0) @@ -118,7 +119,7 @@ static int walk_and_match(FT_WORD *word, uint32 count, ALL_IN_ONE *aio) */ keybuff+=keylen; keyinfo=& info->s->ft2_keyinfo; - key_root=info->lastpos; + key_root= info->cur_row.lastpos; keylen=0; r= _ma_search_first(info, keyinfo, key_root); goto do_skip; @@ -132,7 +133,7 @@ static int walk_and_match(FT_WORD *word, uint32 count, ALL_IN_ONE *aio) if (tmp_weight==0) DBUG_RETURN(doc_cnt); /* stopword, doc_cnt should be 0 */ - sdoc.doc.dpos=info->lastpos; + sdoc.doc.dpos= info->cur_row.lastpos; /* saving document matched into dtree */ if (!(selem=tree_insert(&aio->dtree, &sdoc, 0, aio->dtree.custom_arg))) @@ -162,7 +163,7 @@ static int walk_and_match(FT_WORD *word, uint32 count, ALL_IN_ONE *aio) SEARCH_BIGGER, key_root); do_skip: while ((subkeys=ft_sintXkorr(info->lastkey+info->lastkey_length-extra)) > 0 && - !r && info->lastpos >= info->state->data_file_length) + !r && info->cur_row.lastpos >= info->state->data_file_length) r= _ma_search_next(info, keyinfo, info->lastkey, info->lastkey_length, SEARCH_BIGGER, key_root); @@ -209,22 +210,22 @@ FT_INFO *maria_ft_init_nlq_search(MARIA_HA *info, uint keynr, byte *query, ALL_IN_ONE aio; FT_DOC *dptr; FT_INFO *dlist=NULL; - my_off_t saved_lastpos=info->lastpos; + MARIA_RECORD_POS saved_lastpos= info->cur_row.lastpos; struct st_mysql_ftparser *parser; MYSQL_FTPARSER_PARAM *ftparser_param; DBUG_ENTER("maria_ft_init_nlq_search"); -/* black magic ON */ + /* black magic ON */ if ((int) (keynr = _ma_check_index(info,keynr)) < 0) DBUG_RETURN(NULL); if (_ma_readinfo(info,F_RDLCK,1)) DBUG_RETURN(NULL); -/* black magic OFF */ + /* black magic OFF */ aio.info=info; aio.keynr=keynr; aio.charset=info->s->keyinfo[keynr].seg->charset; - aio.keybuff=info->lastkey+info->s->base.max_key_length; + aio.keybuff= (uchar*) info->lastkey+info->s->base.max_key_length; parser= info->s->keyinfo[keynr].parser; if (! (ftparser_param= maria_ftparser_call_initializer(info, keynr, 0))) goto err; @@ -254,7 +255,7 @@ FT_INFO *maria_ft_init_nlq_search(MARIA_HA *info, uint keynr, byte *query, while (best.elements) { my_off_t docid=((FT_DOC *)queue_remove(& best, 0))->dpos; - if (!(*info->read_record)(info,docid,record)) + if (!(*info->read_record)(info, record, docid)) { info->update|= HA_STATE_AKTIV; ftparser_param->flags= MYSQL_FTFLAGS_NEED_COPY; @@ -296,7 +297,7 @@ FT_INFO *maria_ft_init_nlq_search(MARIA_HA *info, uint keynr, byte *query, err: delete_tree(&aio.dtree); delete_tree(&wtree); - info->lastpos=saved_lastpos; + info->cur_row.lastpos= saved_lastpos; DBUG_RETURN(dlist); } @@ -313,8 +314,8 @@ int maria_ft_nlq_read_next(FT_INFO *handler, char *record) info->update&= (HA_STATE_CHANGED | HA_STATE_ROW_CHANGED); - info->lastpos=handler->doc[handler->curdoc].dpos; - if (!(*info->read_record)(info,info->lastpos,record)) + info->cur_row.lastpos= handler->doc[handler->curdoc].dpos; + if (!(*info->read_record)(info, record, info->cur_row.lastpos)) { info->update|= HA_STATE_AKTIV; /* Record is read */ return 0; @@ -329,7 +330,7 @@ float maria_ft_nlq_find_relevance(FT_INFO *handler, { int a,b,c; FT_DOC *docs=handler->doc; - my_off_t docid=handler->info->lastpos; + MARIA_RECORD_POS docid= handler->info->cur_row.lastpos; if (docid == HA_POS_ERROR) return -5.0; diff --git a/storage/maria/ma_ft_update.c b/storage/maria/ma_ft_update.c index 965f9afc91d..25f4d5a67a0 100644 --- a/storage/maria/ma_ft_update.c +++ b/storage/maria/ma_ft_update.c @@ -141,7 +141,7 @@ static int _ma_ft_store(MARIA_HA *info, uint keynr, byte *keybuf, for (; wlist->pos; wlist++) { key_length= _ma_ft_make_key(info,keynr,keybuf,wlist,filepos); - if (_ma_ck_write(info,keynr,(uchar*) keybuf,key_length)) + if (_ma_ck_write(info, keynr, keybuf, key_length)) DBUG_RETURN(1); } DBUG_RETURN(0); @@ -156,7 +156,7 @@ static int _ma_ft_erase(MARIA_HA *info, uint keynr, byte *keybuf, for (; wlist->pos; wlist++) { key_length= _ma_ft_make_key(info,keynr,keybuf,wlist,filepos); - if (_ma_ck_delete(info,keynr,(uchar*) keybuf,key_length)) + if (_ma_ck_delete(info, keynr, keybuf, key_length)) err=1; } DBUG_RETURN(err); @@ -219,13 +219,13 @@ int _ma_ft_update(MARIA_HA *info, uint keynr, byte *keybuf, if (cmp < 0 || cmp2) { key_length= _ma_ft_make_key(info,keynr,keybuf,old_word,pos); - if ((error= _ma_ck_delete(info,keynr,(uchar*) keybuf,key_length))) + if ((error= _ma_ck_delete(info,keynr, keybuf,key_length))) goto err; } if (cmp > 0 || cmp2) { - key_length= _ma_ft_make_key(info,keynr,keybuf,new_word,pos); - if ((error= _ma_ck_write(info,keynr,(uchar*) keybuf,key_length))) + key_length= _ma_ft_make_key(info, keynr, keybuf, new_word,pos); + if ((error= _ma_ck_write(info, keynr, keybuf,key_length))) goto err; } if (cmp<=0) old_word++; @@ -277,8 +277,9 @@ int _ma_ft_del(MARIA_HA *info, uint keynr, byte *keybuf, const byte *record, DBUG_RETURN(error); } + uint _ma_ft_make_key(MARIA_HA *info, uint keynr, byte *keybuf, FT_WORD *wptr, - my_off_t filepos) + my_off_t filepos) { byte buf[HA_FT_MAXBYTELEN+16]; DBUG_ENTER("_ma_ft_make_key"); @@ -294,7 +295,7 @@ uint _ma_ft_make_key(MARIA_HA *info, uint keynr, byte *keybuf, FT_WORD *wptr, int2store(buf+HA_FT_WLEN,wptr->len); memcpy(buf+HA_FT_WLEN+2,wptr->pos,wptr->len); - DBUG_RETURN(_ma_make_key(info,keynr,(uchar*) keybuf,buf,filepos)); + DBUG_RETURN(_ma_make_key(info, keynr, keybuf, buf, filepos)); } @@ -302,12 +303,12 @@ uint _ma_ft_make_key(MARIA_HA *info, uint keynr, byte *keybuf, FT_WORD *wptr, convert key value to ft2 */ -uint _ma_ft_convert_to_ft2(MARIA_HA *info, uint keynr, uchar *key) +uint _ma_ft_convert_to_ft2(MARIA_HA *info, uint keynr, byte *key) { my_off_t root; DYNAMIC_ARRAY *da=info->ft1_to_ft2; MARIA_KEYDEF *keyinfo=&info->s->ft2_keyinfo; - uchar *key_ptr= (uchar*) dynamic_array_ptr(da, 0), *end; + byte *key_ptr= (byte*) dynamic_array_ptr(da, 0), *end; uint length, key_length; DBUG_ENTER("_ma_ft_convert_to_ft2"); @@ -329,13 +330,13 @@ uint _ma_ft_convert_to_ft2(MARIA_HA *info, uint keynr, uchar *key) /* creating pageful of keys */ maria_putint(info->buff,length+2,0); memcpy(info->buff+2, key_ptr, length); - info->buff_used=info->page_changed=1; /* info->buff is used */ + info->keybuff_used=info->page_changed=1; /* info->buff is used */ if ((root= _ma_new(info,keyinfo,DFLT_INIT_HITS)) == HA_OFFSET_ERROR || _ma_write_keypage(info,keyinfo,root,DFLT_INIT_HITS,info->buff)) DBUG_RETURN(-1); /* inserting the rest of key values */ - end= (uchar*) dynamic_array_ptr(da, da->elements); + end= (byte*) dynamic_array_ptr(da, da->elements); for (key_ptr+=length; key_ptr < end; key_ptr+=keyinfo->keylength) if(_ma_ck_real_write_btree(info, keyinfo, key_ptr, 0, &root, SEARCH_SAME)) DBUG_RETURN(-1); diff --git a/storage/maria/ma_fulltext.h b/storage/maria/ma_fulltext.h index 946a5628175..cf21471b316 100644 --- a/storage/maria/ma_fulltext.h +++ b/storage/maria/ma_fulltext.h @@ -25,4 +25,4 @@ int _ma_ft_cmp(MARIA_HA *, uint, const byte *, const byte *); int _ma_ft_add(MARIA_HA *, uint, byte *, const byte *, my_off_t); int _ma_ft_del(MARIA_HA *, uint, byte *, const byte *, my_off_t); -uint _ma_ft_convert_to_ft2(MARIA_HA *, uint, uchar *); +uint _ma_ft_convert_to_ft2(MARIA_HA *, uint, byte *); diff --git a/storage/maria/ma_info.c b/storage/maria/ma_info.c index b22ffa41833..397cd2465d4 100644 --- a/storage/maria/ma_info.c +++ b/storage/maria/ma_info.c @@ -23,9 +23,9 @@ /* Get position to last record */ -my_off_t maria_position(MARIA_HA *info) +MARIA_RECORD_POS maria_position(MARIA_HA *info) { - return info->lastpos; + return info->cur_row.lastpos; } @@ -38,7 +38,7 @@ int maria_status(MARIA_HA *info, register MARIA_INFO *x, uint flag) MARIA_SHARE *share=info->s; DBUG_ENTER("maria_status"); - x->recpos = info->lastpos; + x->recpos= info->cur_row.lastpos; if (flag == HA_STATUS_POS) DBUG_RETURN(0); /* Compatible with ISAM */ if (!(flag & HA_STATUS_NO_LOCK)) @@ -64,8 +64,8 @@ int maria_status(MARIA_HA *info, register MARIA_INFO *x, uint flag) } if (flag & HA_STATUS_ERRKEY) { - x->errkey = info->errkey; - x->dupp_key_pos= info->dupp_key_pos; + x->errkey= info->errkey; + x->dup_key_pos= info->dup_key_pos; } if (flag & HA_STATUS_CONST) { @@ -121,13 +121,17 @@ int maria_status(MARIA_HA *info, register MARIA_INFO *x, uint flag) void _ma_report_error(int errcode, const char *file_name) { - size_t lgt; + uint length; DBUG_ENTER("_ma_report_error"); DBUG_PRINT("enter",("errcode %d, table '%s'", errcode, file_name)); - if ((lgt= strlen(file_name)) > 64) - file_name+= lgt - 64; + if ((length= strlen(file_name)) > 64) + { + uint dir_length= dirname_length(file_name); + file_name+= dir_length; + if ((length-= dir_length) > 64) + file_name+= length - 64; + } my_error(errcode, MYF(ME_NOREFRESH), file_name); DBUG_VOID_RETURN; } - diff --git a/storage/maria/ma_init.c b/storage/maria/ma_init.c index 318bbe341e4..b1d119732e2 100644 --- a/storage/maria/ma_init.c +++ b/storage/maria/ma_init.c @@ -18,6 +18,7 @@ #include "maria_def.h" #include <ft_global.h> +#include "ma_blockrec.h" static int maria_inited= 0; pthread_mutex_t THR_LOCK_maria; @@ -42,6 +43,7 @@ int maria_init(void) { maria_inited= 1; pthread_mutex_init(&THR_LOCK_maria,MY_MUTEX_INIT_SLOW); + _ma_init_block_record_data(); } return 0; } diff --git a/storage/maria/ma_key.c b/storage/maria/ma_key.c index ecd51f5dc92..d366c9461d6 100644 --- a/storage/maria/ma_key.c +++ b/storage/maria/ma_key.c @@ -49,11 +49,11 @@ static int _ma_put_key_in_record(MARIA_HA *info,uint keynr,byte *record); Length of key */ -uint _ma_make_key(register MARIA_HA *info, uint keynr, uchar *key, - const byte *record, my_off_t filepos) +uint _ma_make_key(register MARIA_HA *info, uint keynr, byte *key, + const byte *record, MARIA_RECORD_POS filepos) { - byte *pos,*end; - uchar *start; + const byte *pos,*end; + byte *start; reg1 HA_KEYSEG *keyseg; my_bool is_ft= info->s->keyinfo[keynr].flag & HA_FULLTEXT; DBUG_ENTER("_ma_make_key"); @@ -64,7 +64,7 @@ uint _ma_make_key(register MARIA_HA *info, uint keynr, uchar *key, TODO: nulls processing */ #ifdef HAVE_SPATIAL - DBUG_RETURN(sp_make_key(info,keynr,key,record,filepos)); + DBUG_RETURN(sp_make_key(info,keynr, key,record,filepos)); #else DBUG_ASSERT(0); /* maria_open should check that this never happens*/ #endif @@ -91,17 +91,17 @@ uint _ma_make_key(register MARIA_HA *info, uint keynr, uchar *key, char_length= ((!is_ft && cs && cs->mbmaxlen > 1) ? length/cs->mbmaxlen : length); - pos= (byte*) record+keyseg->start; + pos= record+keyseg->start; if (type == HA_KEYTYPE_BIT) { if (keyseg->bit_length) { uchar bits= get_rec_bits((uchar*) record + keyseg->bit_pos, keyseg->bit_start, keyseg->bit_length); - *key++= bits; + *key++= (char) bits; length--; } - memcpy((byte*) key, pos, length); + memcpy(key, pos, length); key+= length; continue; } @@ -121,7 +121,7 @@ uint _ma_make_key(register MARIA_HA *info, uint keynr, uchar *key, length=(uint) (end-pos); FIX_LENGTH(cs, pos, length, char_length); store_key_length_inc(key,char_length); - memcpy((byte*) key,(byte*) pos,(size_t) char_length); + memcpy(key, pos, (size_t) char_length); key+=char_length; continue; } @@ -134,18 +134,18 @@ uint _ma_make_key(register MARIA_HA *info, uint keynr, uchar *key, set_if_smaller(length,tmp_length); FIX_LENGTH(cs, pos, length, char_length); store_key_length_inc(key,char_length); - memcpy((byte*) key,(byte*) pos,(size_t) char_length); + memcpy(key,pos,(size_t) char_length); key+= char_length; continue; } else if (keyseg->flag & HA_BLOB_PART) { uint tmp_length= _ma_calc_blob_length(keyseg->bit_start,pos); - memcpy_fixed((byte*) &pos,pos+keyseg->bit_start,sizeof(char*)); + memcpy_fixed(&pos,pos+keyseg->bit_start,sizeof(char*)); set_if_smaller(length,tmp_length); FIX_LENGTH(cs, pos, length, char_length); store_key_length_inc(key,char_length); - memcpy((byte*) key,(byte*) pos,(size_t) char_length); + memcpy(key,pos,(size_t) char_length); key+= char_length; continue; } @@ -184,14 +184,14 @@ uint _ma_make_key(register MARIA_HA *info, uint keynr, uchar *key, continue; } FIX_LENGTH(cs, pos, length, char_length); - memcpy((byte*) key, pos, char_length); + memcpy(key, pos, char_length); if (length > char_length) cs->cset->fill(cs, (char*) key+char_length, length-char_length, ' '); key+= length; } _ma_dpointer(info,key,filepos); DBUG_PRINT("exit",("keynr: %d",keynr)); - DBUG_DUMP("key",(byte*) start,(uint) (key-start)+keyseg->length); + DBUG_DUMP("key",start,(uint) (key-start)+keyseg->length); DBUG_EXECUTE("key", _ma_print_key(DBUG_FILE,info->s->keyinfo[keynr].seg,start, (uint) (key-start));); @@ -217,10 +217,10 @@ uint _ma_make_key(register MARIA_HA *info, uint keynr, uchar *key, last_use_keyseg Store pointer to the keyseg after the last used one */ -uint _ma_pack_key(register MARIA_HA *info, uint keynr, uchar *key, uchar *old, - uint k_length, HA_KEYSEG **last_used_keyseg) +uint _ma_pack_key(register MARIA_HA *info, uint keynr, byte *key, + const byte *old, uint k_length, HA_KEYSEG **last_used_keyseg) { - uchar *start_key=key; + byte *start_key=key; HA_KEYSEG *keyseg; my_bool is_ft= info->s->keyinfo[keynr].flag & HA_FULLTEXT; DBUG_ENTER("_ma_pack_key"); @@ -232,7 +232,7 @@ uint _ma_pack_key(register MARIA_HA *info, uint keynr, uchar *key, uchar *old, enum ha_base_keytype type=(enum ha_base_keytype) keyseg->type; uint length=min((uint) keyseg->length,(uint) k_length); uint char_length; - uchar *pos; + const byte *pos; CHARSET_INFO *cs=keyseg->charset; if (keyseg->null_bit) @@ -249,11 +249,12 @@ uint _ma_pack_key(register MARIA_HA *info, uint keynr, uchar *key, uchar *old, continue; /* Found NULL */ } } - char_length= (!is_ft && cs && cs->mbmaxlen > 1) ? length/cs->mbmaxlen : length; - pos=old; + char_length= ((!is_ft && cs && cs->mbmaxlen > 1) ? length/cs->mbmaxlen : + length); + pos= old; if (keyseg->flag & HA_SPACE_PACK) { - uchar *end=pos+length; + const byte *end= pos + length; if (type != HA_KEYTYPE_NUM) { while (end > pos && end[-1] == ' ') @@ -268,7 +269,7 @@ uint _ma_pack_key(register MARIA_HA *info, uint keynr, uchar *key, uchar *old, length=(uint) (end-pos); FIX_LENGTH(cs, pos, length, char_length); store_key_length_inc(key,char_length); - memcpy((byte*) key,pos,(size_t) char_length); + memcpy(key,pos,(size_t) char_length); key+= char_length; continue; } @@ -282,7 +283,7 @@ uint _ma_pack_key(register MARIA_HA *info, uint keynr, uchar *key, uchar *old, FIX_LENGTH(cs, pos, length, char_length); store_key_length_inc(key,char_length); old+=2; /* Skip length */ - memcpy((byte*) key, pos,(size_t) char_length); + memcpy(key, pos,(size_t) char_length); key+= char_length; continue; } @@ -297,7 +298,7 @@ uint _ma_pack_key(register MARIA_HA *info, uint keynr, uchar *key, uchar *old, continue; } FIX_LENGTH(cs, pos, length, char_length); - memcpy((byte*) key, pos, char_length); + memcpy(key, pos, char_length); if (length > char_length) cs->cset->fill(cs, (char*) key+char_length, length-char_length, ' '); key+= length; @@ -321,7 +322,7 @@ uint _ma_pack_key(register MARIA_HA *info, uint keynr, uchar *key, uchar *old, length+= keyseg->length; keyseg++; } while (keyseg->type); - bzero((byte*) key,length); + bzero(key,length); key+=length; } #endif @@ -358,8 +359,8 @@ static int _ma_put_key_in_record(register MARIA_HA *info, uint keynr, byte *blob_ptr; DBUG_ENTER("_ma_put_key_in_record"); - blob_ptr= (byte*) info->lastkey2; /* Place to put blob parts */ - key=(byte*) info->lastkey; /* KEy that was read */ + blob_ptr= info->lastkey2; /* Place to put blob parts */ + key=info->lastkey; /* KEy that was read */ key_end=key+info->lastkey_length; for (keyseg=info->s->keyinfo[keynr].seg ; keyseg->type ;keyseg++) { @@ -378,7 +379,7 @@ static int _ma_put_key_in_record(register MARIA_HA *info, uint keynr, if (keyseg->bit_length) { - uchar bits= *key++; + byte bits= *key++; set_rec_bits(bits, record + keyseg->bit_pos, keyseg->bit_start, keyseg->bit_length); length--; @@ -388,7 +389,7 @@ static int _ma_put_key_in_record(register MARIA_HA *info, uint keynr, clr_rec_bits(record + keyseg->bit_pos, keyseg->bit_start, keyseg->bit_length); } - memcpy(record + keyseg->start, (byte*) key, length); + memcpy(record + keyseg->start, key, length); key+= length; continue; } @@ -429,7 +430,7 @@ static int _ma_put_key_in_record(register MARIA_HA *info, uint keynr, else int2store(record+keyseg->start, length); /* And key data */ - memcpy(record+keyseg->start + keyseg->bit_start, (byte*) key, length); + memcpy(record+keyseg->start + keyseg->bit_start, key, length); key+= length; } else if (keyseg->flag & HA_BLOB_PART) @@ -472,8 +473,7 @@ static int _ma_put_key_in_record(register MARIA_HA *info, uint keynr, if (key+keyseg->length > key_end) goto err; #endif - memcpy(record+keyseg->start,(byte*) key, - (size_t) keyseg->length); + memcpy(record+keyseg->start, key, (size_t) keyseg->length); key+= keyseg->length; } } @@ -486,7 +486,7 @@ err: /* Here when key reads are used */ -int _ma_read_key_record(MARIA_HA *info, my_off_t filepos, byte *buf) +int _ma_read_key_record(MARIA_HA *info, byte *buf, MARIA_RECORD_POS filepos) { fast_ma_writeinfo(info); if (filepos != HA_OFFSET_ERROR) @@ -526,7 +526,7 @@ ulonglong ma_retrieve_auto_increment(MARIA_HA *info,const byte *record) ulonglong value= 0; /* Store unsigned values here */ longlong s_value= 0; /* Store signed values here */ HA_KEYSEG *keyseg= info->s->keyinfo[info->s->base.auto_key-1].seg; - const uchar *key= (uchar*) record + keyseg->start; + const byte *key= record + keyseg->start; switch (keyseg->type) { case HA_KEYTYPE_INT8: diff --git a/storage/maria/ma_keycache.c b/storage/maria/ma_keycache.c index 837b0fbac66..a2ea4349338 100644 --- a/storage/maria/ma_keycache.c +++ b/storage/maria/ma_keycache.c @@ -54,8 +54,9 @@ int maria_assign_to_key_cache(MARIA_HA *info, int error= 0; MARIA_SHARE* share= info->s; DBUG_ENTER("maria_assign_to_key_cache"); - DBUG_PRINT("enter",("old_key_cache_handle: %lx new_key_cache_handle: %lx", - share->key_cache, key_cache)); + DBUG_PRINT("enter", + ("old_key_cache_handle: 0x%lx new_key_cache_handle: 0x%lx", + share->key_cache, key_cache)); /* Skip operation if we didn't change key cache. This can happen if we diff --git a/storage/maria/ma_locking.c b/storage/maria/ma_locking.c index adb4b03bebe..62746eba875 100644 --- a/storage/maria/ma_locking.c +++ b/storage/maria/ma_locking.c @@ -60,13 +60,25 @@ int maria_lock_database(MARIA_HA *info, int lock_type) else count= --share->w_locks; --share->tot_locks; - if (info->lock_type == F_WRLCK && !share->w_locks && - !share->delay_key_write && flush_key_blocks(share->key_cache, - share->kfile,FLUSH_KEEP)) + if (info->lock_type == F_WRLCK && !share->w_locks) { - error=my_errno; - maria_print_error(info->s, HA_ERR_CRASHED); - maria_mark_crashed(info); /* Mark that table must be checked */ + if (!share->delay_key_write && flush_key_blocks(share->key_cache, + share->kfile, + FLUSH_KEEP)) + { + error= my_errno; + maria_print_error(info->s, HA_ERR_CRASHED); + /* Mark that table must be checked */ + maria_mark_crashed(info); + } + if (share->data_file_type == BLOCK_RECORD && + flush_key_blocks(share->key_cache, info->dfile, FLUSH_KEEP)) + { + error= my_errno; + maria_print_error(info->s, HA_ERR_CRASHED); + /* Mark that table must be checked */ + maria_mark_crashed(info); + } } if (info->opt_flag & (READ_CACHE_USED | WRITE_CACHE_USED)) { @@ -84,16 +96,17 @@ int maria_lock_database(MARIA_HA *info, int lock_type) if (share->changed && !share->w_locks) { #ifdef HAVE_MMAP - if ((info->s->mmaped_length != info->s->state.state.data_file_length) && - (info->s->nonmmaped_inserts > MAX_NONMAPPED_INSERTS)) - { - if (info->s->concurrent_insert) - rw_wrlock(&info->s->mmap_lock); - _ma_remap_file(info, info->s->state.state.data_file_length); - info->s->nonmmaped_inserts= 0; - if (info->s->concurrent_insert) - rw_unlock(&info->s->mmap_lock); - } + if ((info->s->mmaped_length != + info->s->state.state.data_file_length) && + (info->s->nonmmaped_inserts > MAX_NONMAPPED_INSERTS)) + { + if (info->s->concurrent_insert) + rw_wrlock(&info->s->mmap_lock); + _ma_remap_file(info, info->s->state.state.data_file_length); + info->s->nonmmaped_inserts= 0; + if (info->s->concurrent_insert) + rw_unlock(&info->s->mmap_lock); + } #endif share->state.process= share->last_process=share->this_process; share->state.unique= info->last_unique= info->this_unique; @@ -350,7 +363,7 @@ int _ma_readinfo(register MARIA_HA *info, int lock_type, int check_keybuffer) int _ma_writeinfo(register MARIA_HA *info, uint operation) { int error,olderror; - MARIA_SHARE *share=info->s; + MARIA_SHARE *share= info->s; DBUG_ENTER("_ma_writeinfo"); DBUG_PRINT("info",("operation: %u tot_locks: %u", operation, share->tot_locks)); @@ -358,13 +371,13 @@ int _ma_writeinfo(register MARIA_HA *info, uint operation) error=0; if (share->tot_locks == 0) { - olderror=my_errno; /* Remember last error */ if (operation) { /* Two threads can't be here */ + olderror= my_errno; /* Remember last error */ share->state.process= share->last_process= share->this_process; share->state.unique= info->last_unique= info->this_unique; share->state.update_count= info->last_loop= ++info->this_loop; - if ((error=_ma_state_info_write(share->kfile, &share->state, 1))) + if ((error= _ma_state_info_write(share->kfile, &share->state, 1))) olderror=my_errno; #ifdef __WIN__ if (maria_flush) @@ -373,8 +386,8 @@ int _ma_writeinfo(register MARIA_HA *info, uint operation) _commit(info->dfile); } #endif + my_errno=olderror; } - my_errno=olderror; } else if (operation) share->changed= 1; /* Mark keyfile changed */ diff --git a/storage/maria/ma_open.c b/storage/maria/ma_open.c index 38e71a44f8b..cbc781c589e 100644 --- a/storage/maria/ma_open.c +++ b/storage/maria/ma_open.c @@ -19,6 +19,7 @@ #include "ma_fulltext.h" #include "ma_sp_defs.h" #include "ma_rt_index.h" +#include "ma_blockrec.h" #include <m_ctype.h> #if defined(MSDOS) || defined(__WIN__) @@ -33,6 +34,12 @@ #endif static void setup_key_functions(MARIA_KEYDEF *keyinfo); +static my_bool maria_scan_init_dummy(MARIA_HA *info); +static void maria_scan_end_dummy(MARIA_HA *info); +static my_bool maria_once_init_dummy(MARIA_SHARE *, File); +static my_bool maria_once_end_dummy(MARIA_SHARE *); +static byte *_ma_base_info_read(byte *ptr, MARIA_BASE_INFO *base); + #define get_next_element(to,pos,size) { memcpy((char*) to,pos,(size_t) size); \ pos+=size;} @@ -76,7 +83,7 @@ MARIA_HA *_ma_test_if_reopen(char *filename) MARIA_HA *maria_open(const char *name, int mode, uint open_flags) { int kfile,open_mode,save_errno,have_rtree=0; - uint i,j,len,errpos,head_length,base_pos,offset,info_length,keys, + uint i,j,len,errpos,head_length,base_pos,info_length,keys, key_parts,unique_key_parts,fulltext_keys,uniques; char name_buff[FN_REFLEN], org_name[FN_REFLEN], index_name[FN_REFLEN], data_name[FN_REFLEN]; @@ -84,13 +91,13 @@ MARIA_HA *maria_open(const char *name, int mode, uint open_flags) MARIA_HA info,*m_info,*old_info; MARIA_SHARE share_buff,*share; ulong rec_per_key_part[HA_MAX_POSSIBLE_KEY*HA_MAX_KEY_SEG]; - my_off_t key_root[HA_MAX_POSSIBLE_KEY],key_del[MARIA_MAX_KEY_BLOCK_SIZE]; + my_off_t key_root[HA_MAX_POSSIBLE_KEY]; ulonglong max_key_file_length, max_data_file_length; DBUG_ENTER("maria_open"); LINT_INIT(m_info); kfile= -1; - errpos=0; + errpos= 0; head_length=sizeof(share_buff.state.header); bzero((byte*) &info,sizeof(info)); @@ -103,7 +110,6 @@ MARIA_HA *maria_open(const char *name, int mode, uint open_flags) bzero((gptr) &share_buff,sizeof(share_buff)); share_buff.state.rec_per_key_part=rec_per_key_part; share_buff.state.key_root=key_root; - share_buff.state.key_del=key_del; share_buff.key_cache= multi_key_cache_search(name_buff, strlen(name_buff), maria_key_cache); @@ -121,7 +127,7 @@ MARIA_HA *maria_open(const char *name, int mode, uint open_flags) goto err; } share->mode=open_mode; - errpos=1; + errpos= 1; if (my_read(kfile,(char*) share->state.header.file_version,head_length, MYF(MY_NABP))) { @@ -165,17 +171,17 @@ MARIA_HA *maria_open(const char *name, int mode, uint open_flags) MY_APPEND_EXT|MY_UNPACK_FILENAME|MY_RESOLVE_SYMLINKS); info_length=mi_uint2korr(share->state.header.header_length); - base_pos=mi_uint2korr(share->state.header.base_pos); + base_pos= mi_uint2korr(share->state.header.base_pos); if (!(disk_cache=(char*) my_alloca(info_length+128))) { my_errno=ENOMEM; goto err; } end_pos=disk_cache+info_length; - errpos=2; + errpos= 2; VOID(my_seek(kfile,0L,MY_SEEK_SET,MYF(0))); - errpos=3; + errpos= 3; if (my_read(kfile,disk_cache,info_length,MYF(MY_NABP))) { my_errno=HA_ERR_CRASHED; @@ -195,15 +201,14 @@ MARIA_HA *maria_open(const char *name, int mode, uint open_flags) } share->state_diff_length=len-MARIA_STATE_INFO_SIZE; - _ma_state_info_read((uchar*) disk_cache, &share->state); + _ma_state_info_read(disk_cache, &share->state); len= mi_uint2korr(share->state.header.base_info_length); if (len != MARIA_BASE_INFO_SIZE) { DBUG_PRINT("warning",("saved_base_info_length: %d base_info_length: %d", len,MARIA_BASE_INFO_SIZE)); } - disk_pos= (char*) - _ma_n_base_info_read((uchar*) disk_cache + base_pos, &share->base); + disk_pos= _ma_base_info_read(disk_cache + base_pos, &share->base); share->state.state_length=base_pos; if (!(open_flags & HA_OPEN_FOR_REPAIR) && @@ -239,6 +244,7 @@ MARIA_HA *maria_open(const char *name, int mode, uint open_flags) (((ulonglong) 1 << (share->base.rec_reflength*8))-1) : (_ma_safe_mul(share->base.pack_reclength, (ulonglong) 1 << (share->base.rec_reflength*8))-1); + max_key_file_length= _ma_safe_mul(MARIA_MIN_KEY_BLOCK_LENGTH, ((ulonglong) 1 << (share->base.key_reflength*8))-1); @@ -246,25 +252,6 @@ MARIA_HA *maria_open(const char *name, int mode, uint open_flags) set_if_smaller(max_data_file_length, INT_MAX32); set_if_smaller(max_key_file_length, INT_MAX32); #endif -#if USE_RAID && SYSTEM_SIZEOF_OFF_T == 4 - set_if_smaller(max_key_file_length, INT_MAX32); - if (!share->base.raid_type) - { - set_if_smaller(max_data_file_length, INT_MAX32); - } - else - { - set_if_smaller(max_data_file_length, - (ulonglong) share->base.raid_chunks << 31); - } -#elif !defined(USE_RAID) - if (share->base.raid_type) - { - DBUG_PRINT("error",("Table uses RAID but we don't have RAID support")); - my_errno=HA_ERR_UNSUPPORTED; - goto err; - } -#endif share->base.max_data_file_length=(my_off_t) max_data_file_length; share->base.max_key_file_length=(my_off_t) max_key_file_length; @@ -286,29 +273,25 @@ MARIA_HA *maria_open(const char *name, int mode, uint open_flags) &share->index_file_name,strlen(index_name)+1, &share->data_file_name,strlen(data_name)+1, &share->state.key_root,keys*sizeof(my_off_t), - &share->state.key_del, - (share->state.header.max_block_size_index*sizeof(my_off_t)), #ifdef THREAD &share->key_root_lock,sizeof(rw_lock_t)*keys, #endif &share->mmap_lock,sizeof(rw_lock_t), NullS)) goto err; - errpos=4; + errpos= 4; + *share=share_buff; memcpy((char*) share->state.rec_per_key_part, (char*) rec_per_key_part, sizeof(long)*key_parts); memcpy((char*) share->state.key_root, (char*) key_root, sizeof(my_off_t)*keys); - memcpy((char*) share->state.key_del, - (char*) key_del, (sizeof(my_off_t) * - share->state.header.max_block_size_index)); strmov(share->unique_file_name, name_buff); share->unique_name_length= strlen(name_buff); strmov(share->index_file_name, index_name); strmov(share->data_file_name, data_name); - share->blocksize=min(IO_SIZE,maria_block_size); + share->block_size= maria_block_size; { HA_KEYSEG *pos=share->keyparts; for (i=0 ; i < keys ; i++) @@ -319,7 +302,7 @@ MARIA_HA *maria_open(const char *name, int mode, uint open_flags) end_pos); if (share->keyinfo[i].key_alg == HA_KEY_ALG_RTREE) have_rtree=1; - set_if_smaller(share->blocksize,share->keyinfo[i].block_length); + set_if_smaller(share->block_size,share->keyinfo[i].block_length); share->keyinfo[i].seg=pos; for (j=0 ; j < share->keyinfo[i].keysegs; j++,pos++) { @@ -423,28 +406,43 @@ MARIA_HA *maria_open(const char *name, int mode, uint open_flags) } share->ftparsers= 0; } - - disk_pos_assert(disk_pos + share->base.fields *MARIA_COLUMNDEF_SIZE, end_pos); - for (i=j=offset=0 ; i < share->base.fields ; i++) + share->data_file_type= share->state.header.data_file_type; + share->base_length= (BASE_ROW_HEADER_SIZE + + share->base.is_nulls_extended + + share->base.null_bytes + + share->base.pack_bytes + + test(share->options & HA_OPTION_CHECKSUM)); + if (share->base.transactional) + share->base_length+= TRANS_ROW_EXTRA_HEADER_SIZE; + share->base.default_rec_buff_size= max(share->base.pack_reclength, + share->base.max_key_length); + if (share->data_file_type == DYNAMIC_RECORD) + { + share->base.extra_rec_buff_size= + (ALIGN_SIZE(MARIA_MAX_DYN_BLOCK_HEADER) + MARIA_SPLIT_LENGTH + + MARIA_REC_BUFF_OFFSET); + share->base.default_rec_buff_size+= share->base.extra_rec_buff_size; + } + disk_pos_assert(disk_pos + share->base.fields *MARIA_COLUMNDEF_SIZE, + end_pos); + for (i= j= 0 ; i < share->base.fields ; i++) { disk_pos=_ma_recinfo_read(disk_pos,&share->rec[i]); share->rec[i].pack_type=0; share->rec[i].huff_tree=0; - share->rec[i].offset=offset; if (share->rec[i].type == (int) FIELD_BLOB) { share->blobs[j].pack_length= share->rec[i].length-maria_portable_sizeof_char_ptr;; - share->blobs[j].offset=offset; + share->blobs[j].offset= share->rec[i].offset; j++; } - offset+=share->rec[i].length; } share->rec[i].type=(int) FIELD_LAST; /* End marker */ if (_ma_open_datafile(&info, share, -1)) goto err; - errpos=5; + errpos= 5; share->kfile=kfile; share->this_process=(ulong) getpid(); @@ -456,25 +454,12 @@ MARIA_HA *maria_open(const char *name, int mode, uint open_flags) share->rec_reflength=share->base.rec_reflength; /* May be changed */ share->base.margin_key_file_length=(share->base.max_key_file_length - (keys ? MARIA_INDEX_BLOCK_MARGIN * - share->blocksize * keys : 0)); - share->blocksize=min(IO_SIZE,maria_block_size); - share->data_file_type=STATIC_RECORD; - if (share->options & HA_OPTION_COMPRESS_RECORD) - { - share->data_file_type = COMPRESSED_RECORD; - share->options|= HA_OPTION_READ_ONLY_DATA; - info.s=share; - if (_ma_read_pack_info(&info, - (pbool) - test(!(share->options & - (HA_OPTION_PACK_RECORD | - HA_OPTION_TEMP_COMPRESS_RECORD))))) - goto err; - } - else if (share->options & HA_OPTION_PACK_RECORD) - share->data_file_type = DYNAMIC_RECORD; + share->block_size * keys : 0)); + share->block_size= share->base.block_size; my_afree((gptr) disk_cache); _ma_setup_functions(share); + if ((*share->once_init)(share, info.dfile)) + goto err; #ifdef THREAD thr_lock_init(&share->lock); VOID(pthread_mutex_init(&share->intern_lock,MY_MUTEX_INIT_FAST)); @@ -493,6 +478,7 @@ MARIA_HA *maria_open(const char *name, int mode, uint open_flags) HA_OPTION_COMPRESS_RECORD | HA_OPTION_TEMP_COMPRESS_RECORD)) || (open_flags & HA_OPEN_TMP_TABLE) || + share->data_file_type == BLOCK_RECORD || have_rtree) ? 0 : 1; if (share->concurrent_insert) { @@ -512,9 +498,11 @@ MARIA_HA *maria_open(const char *name, int mode, uint open_flags) my_errno=EACCES; /* Can't open in write mode */ goto err; } - if (_ma_open_datafile(&info, share, old_info->dfile)) + if (share->data_file_type == BLOCK_RECORD) + info.dfile= share->bitmap.file; + else if (_ma_open_datafile(&info, share, old_info->dfile)) goto err; - errpos=5; + errpos= 5; have_rtree= old_info->maria_rtree_recursion_state != NULL; } @@ -530,7 +518,7 @@ MARIA_HA *maria_open(const char *name, int mode, uint open_flags) &info.maria_rtree_recursion_state,have_rtree ? 1024 : 0, NullS)) goto err; - errpos=6; + errpos= 6; if (!have_rtree) info.maria_rtree_recursion_state= NULL; @@ -540,7 +528,7 @@ MARIA_HA *maria_open(const char *name, int mode, uint open_flags) info.lastkey2=info.lastkey+share->base.max_key_length; info.s=share; - info.lastpos= HA_OFFSET_ERROR; + info.cur_row.lastpos= HA_OFFSET_ERROR; info.update= (short) (HA_STATE_NEXT_FOUND+HA_STATE_PREV_FOUND); info.opt_flag=READ_CHECK_USED; info.this_unique= (ulong) info.dfile; /* Uniq number in process */ @@ -557,8 +545,12 @@ MARIA_HA *maria_open(const char *name, int mode, uint open_flags) info.ft1_to_ft2=0; info.errkey= -1; info.page_changed=1; + info.keyread_buff= info.buff + share->base.max_key_block_length; + if ((*share->init)(&info)) + goto err; + pthread_mutex_lock(&share->intern_lock); - info.read_record=share->read_record; + info.read_record= share->read_record; share->reopen++; share->write_flag=MYF(MY_NABP | MY_WAIT_IF_FULL); if (share->options & HA_OPTION_READ_ONLY_DATA) @@ -570,7 +562,8 @@ MARIA_HA *maria_open(const char *name, int mode, uint open_flags) if ((open_flags & HA_OPEN_TMP_TABLE) || (share->options & HA_OPTION_TMP_TABLE)) { - share->temporary=share->delay_key_write=1; + share->temporary= share->delay_key_write= 1; + share->write_flag=MYF(MY_NABP); share->w_locks++; /* We don't have to update status */ share->tot_locks++; @@ -580,15 +573,17 @@ MARIA_HA *maria_open(const char *name, int mode, uint open_flags) (share->options & HA_OPTION_DELAY_KEY_WRITE)) && maria_delay_key_write) share->delay_key_write=1; + info.state= &share->state.state; /* Change global values by default */ pthread_mutex_unlock(&share->intern_lock); /* Allocate buffer for one record */ - - /* prerequisites: bzero(info) && info->s=share; are met. */ - if (!_ma_alloc_rec_buff(&info, -1, &info.rec_buff)) + /* prerequisites: info->rec_buffer == 0 && info->rec_buff_size == 0 */ + if (_ma_alloc_buffer(&info.rec_buff, &info.rec_buff_size, + share->base.default_rec_buff_size)) goto err; - bzero(info.rec_buff, _ma_get_rec_buff_len(&info, info.rec_buff)); + + bzero(info.rec_buff, share->base.default_rec_buff_size); *m_info=info; #ifdef THREAD @@ -608,12 +603,15 @@ err: _ma_report_error(save_errno, name); switch (errpos) { case 6: + (*share->end)(&info); my_free((gptr) m_info,MYF(0)); /* fall through */ case 5: - VOID(my_close(info.dfile,MYF(0))); + if (share->data_file_type != BLOCK_RECORD) + VOID(my_close(info.dfile,MYF(0))); if (old_info) break; /* Don't remove open table */ + (*share->once_end)(share); /* fall through */ case 4: my_free((gptr) share,MYF(0)); @@ -636,38 +634,23 @@ err: } /* maria_open */ -byte *_ma_alloc_rec_buff(MARIA_HA *info, ulong length, byte **buf) -{ - uint extra; - uint32 old_length; - LINT_INIT(old_length); +/* + Reallocate a buffer, if the current buffer is not large enough +*/ - if (! *buf || length > (old_length=_ma_get_rec_buff_len(info, *buf))) +my_bool _ma_alloc_buffer(byte **old_addr, my_size_t *old_size, + my_size_t new_size) +{ + if (*old_size < new_size) { - byte *newptr = *buf; - - /* to simplify initial init of info->rec_buf in maria_open and maria_extra */ - if (length == (ulong) -1) - { - length= max(info->s->base.pack_reclength, - info->s->base.max_key_length); - /* Avoid unnecessary realloc */ - if (newptr && length == old_length) - return newptr; - } - - extra= ((info->s->options & HA_OPTION_PACK_RECORD) ? - ALIGN_SIZE(MARIA_MAX_DYN_BLOCK_HEADER)+MARIA_SPLIT_LENGTH+ - MARIA_REC_BUFF_OFFSET : 0); - if (extra && newptr) - newptr-= MARIA_REC_BUFF_OFFSET; - if (!(newptr=(byte*) my_realloc((gptr)newptr, length+extra+8, - MYF(MY_ALLOW_ZERO_PTR)))) - return newptr; - *((uint32 *) newptr)= (uint32) length; - *buf= newptr+(extra ? MARIA_REC_BUFF_OFFSET : 0); + byte *addr; + if (!(addr= (byte*) my_realloc((gptr) *old_addr, new_size, + MYF(MY_ALLOW_ZERO_PTR)))) + return 1; + *old_addr= addr; + *old_size= new_size; } - return *buf; + return 0; } @@ -684,28 +667,37 @@ ulonglong _ma_safe_mul(ulonglong a, ulonglong b) void _ma_setup_functions(register MARIA_SHARE *share) { - if (share->options & HA_OPTION_COMPRESS_RECORD) - { + share->once_init= maria_once_init_dummy; + share->once_end= maria_once_end_dummy; + share->init= maria_scan_init_dummy; + share->end= maria_scan_end_dummy; + share->scan_init= maria_scan_init_dummy; + share->scan_end= maria_scan_end_dummy; + share->write_record_init= _ma_write_init_default; + share->write_record_abort= _ma_write_abort_default; + + switch (share->data_file_type) { + case COMPRESSED_RECORD: share->read_record= _ma_read_pack_record; - share->read_rnd= _ma_read_rnd_pack_record; - if (!(share->options & HA_OPTION_TEMP_COMPRESS_RECORD)) - share->calc_checksum=0; /* No checksum */ - else if (share->options & HA_OPTION_PACK_RECORD) - share->calc_checksum= _ma_checksum; - else + share->scan= _ma_read_rnd_pack_record; + share->once_init= _ma_once_init_pack_row; + share->once_end= _ma_once_end_pack_row; + /* Calculate checksum according how the original row was stored */ + if (share->state.header.org_data_file_type == STATIC_RECORD) share->calc_checksum= _ma_static_checksum; - } - else if (share->options & HA_OPTION_PACK_RECORD) - { + else + share->calc_checksum= _ma_checksum; + share->calc_write_checksum= share->calc_checksum; + break; + case DYNAMIC_RECORD: share->read_record= _ma_read_dynamic_record; - share->read_rnd= _ma_read_rnd_dynamic_record; + share->scan= _ma_read_rnd_dynamic_record; share->delete_record= _ma_delete_dynamic_record; share->compare_record= _ma_cmp_dynamic_record; share->compare_unique= _ma_cmp_dynamic_unique; - share->calc_checksum= _ma_checksum; - + share->calc_checksum= share->calc_write_checksum= _ma_checksum; /* add bits used to pack data to pack_reclength for faster allocation */ - share->base.pack_reclength+= share->base.pack_bits; + share->base.pack_reclength+= share->base.pack_bytes; if (share->base.blobs) { share->update_record= _ma_update_blob_record; @@ -716,22 +708,42 @@ void _ma_setup_functions(register MARIA_SHARE *share) share->write_record= _ma_write_dynamic_record; share->update_record= _ma_update_dynamic_record; } - } - else - { + break; + case STATIC_RECORD: share->read_record= _ma_read_static_record; - share->read_rnd= _ma_read_rnd_static_record; + share->scan= _ma_read_rnd_static_record; share->delete_record= _ma_delete_static_record; share->compare_record= _ma_cmp_static_record; share->update_record= _ma_update_static_record; share->write_record= _ma_write_static_record; share->compare_unique= _ma_cmp_static_unique; - share->calc_checksum= _ma_static_checksum; + share->calc_checksum= share->calc_write_checksum= _ma_static_checksum; + break; + case BLOCK_RECORD: + share->once_init= _ma_once_init_block_row; + share->once_end= _ma_once_end_block_row; + share->init= _ma_init_block_row; + share->end= _ma_end_block_row; + share->write_record_init= _ma_write_init_block_record; + share->write_record_abort= _ma_write_abort_block_record; + share->scan_init= _ma_scan_init_block_record; + share->scan_end= _ma_scan_end_block_record; + share->read_record= _ma_read_block_record; + share->scan= _ma_scan_block_record; + share->delete_record= _ma_delete_block_record; + share->compare_record= _ma_compare_block_record; + share->update_record= _ma_update_block_record; + share->write_record= _ma_write_block_record; + share->compare_unique= _ma_cmp_block_unique; + share->calc_checksum= _ma_checksum; + share->calc_write_checksum= 0; + break; } share->file_read= _ma_nommap_pread; share->file_write= _ma_nommap_pwrite; - if (!(share->options & HA_OPTION_CHECKSUM)) - share->calc_checksum=0; + if (!(share->options & HA_OPTION_CHECKSUM) && + share->data_file_type != COMPRESSED_RECORD) + share->calc_checksum= share->calc_write_checksum= 0; return; } @@ -798,55 +810,53 @@ uint _ma_state_info_write(File file, MARIA_STATE_INFO *state, uint pWrite) { uchar buff[MARIA_STATE_INFO_SIZE + MARIA_STATE_EXTRA_SIZE]; uchar *ptr=buff; - uint i, keys= (uint) state->header.keys, - key_blocks=state->header.max_block_size_index; + uint i, keys= (uint) state->header.keys; DBUG_ENTER("_ma_state_info_write"); memcpy_fixed(ptr,&state->header,sizeof(state->header)); ptr+=sizeof(state->header); /* open_count must be first because of _ma_mark_file_changed ! */ - mi_int2store(ptr,state->open_count); ptr +=2; - *ptr++= (uchar)state->changed; *ptr++= state->sortkey; - mi_rowstore(ptr,state->state.records); ptr +=8; - mi_rowstore(ptr,state->state.del); ptr +=8; - mi_rowstore(ptr,state->split); ptr +=8; - mi_sizestore(ptr,state->dellink); ptr +=8; - mi_sizestore(ptr,state->state.key_file_length); ptr +=8; - mi_sizestore(ptr,state->state.data_file_length); ptr +=8; - mi_sizestore(ptr,state->state.empty); ptr +=8; - mi_sizestore(ptr,state->state.key_empty); ptr +=8; - mi_int8store(ptr,state->auto_increment); ptr +=8; - mi_int8store(ptr,(ulonglong) state->state.checksum);ptr +=8; - mi_int4store(ptr,state->process); ptr +=4; - mi_int4store(ptr,state->unique); ptr +=4; - mi_int4store(ptr,state->status); ptr +=4; - mi_int4store(ptr,state->update_count); ptr +=4; - - ptr+=state->state_diff_length; + mi_int2store(ptr,state->open_count); ptr+= 2; + *ptr++= (uchar)state->changed; + *ptr++= state->sortkey; + mi_rowstore(ptr,state->state.records); ptr+= 8; + mi_rowstore(ptr,state->state.del); ptr+= 8; + mi_rowstore(ptr,state->split); ptr+= 8; + mi_sizestore(ptr,state->dellink); ptr+= 8; + mi_sizestore(ptr,state->first_bitmap_with_space); ptr+= 8; + mi_sizestore(ptr,state->state.key_file_length); ptr+= 8; + mi_sizestore(ptr,state->state.data_file_length); ptr+= 8; + mi_sizestore(ptr,state->state.empty); ptr+= 8; + mi_sizestore(ptr,state->state.key_empty); ptr+= 8; + mi_int8store(ptr,state->auto_increment); ptr+= 8; + mi_int8store(ptr,(ulonglong) state->state.checksum); ptr+= 8; + mi_int4store(ptr,state->process); ptr+= 4; + mi_int4store(ptr,state->unique); ptr+= 4; + mi_int4store(ptr,state->status); ptr+= 4; + mi_int4store(ptr,state->update_count); ptr+= 4; + + ptr+= state->state_diff_length; for (i=0; i < keys; i++) { - mi_sizestore(ptr,state->key_root[i]); ptr +=8; - } - for (i=0; i < key_blocks; i++) - { - mi_sizestore(ptr,state->key_del[i]); ptr +=8; + mi_sizestore(ptr,state->key_root[i]); ptr+= 8; } - if (pWrite & 2) /* From isamchk */ + mi_sizestore(ptr,state->key_del); ptr+= 8; + if (pWrite & 2) /* From maria_chk */ { uint key_parts= mi_uint2korr(state->header.key_parts); - mi_int4store(ptr,state->sec_index_changed); ptr +=4; - mi_int4store(ptr,state->sec_index_used); ptr +=4; - mi_int4store(ptr,state->version); ptr +=4; - mi_int8store(ptr,state->key_map); ptr +=8; - mi_int8store(ptr,(ulonglong) state->create_time); ptr +=8; - mi_int8store(ptr,(ulonglong) state->recover_time); ptr +=8; - mi_int8store(ptr,(ulonglong) state->check_time); ptr +=8; - mi_sizestore(ptr,state->rec_per_key_rows); ptr+=8; + mi_int4store(ptr,state->sec_index_changed); ptr+= 4; + mi_int4store(ptr,state->sec_index_used); ptr+= 4; + mi_int4store(ptr,state->version); ptr+= 4; + mi_int8store(ptr,state->key_map); ptr+= 8; + mi_int8store(ptr,(ulonglong) state->create_time); ptr+= 8; + mi_int8store(ptr,(ulonglong) state->recover_time); ptr+= 8; + mi_int8store(ptr,(ulonglong) state->check_time); ptr+= 8; + mi_sizestore(ptr,state->rec_per_key_rows); ptr+= 8; for (i=0 ; i < key_parts ; i++) { - mi_int4store(ptr,state->rec_per_key_part[i]); ptr+=4; + mi_int4store(ptr,state->rec_per_key_part[i]); ptr+=4; } } @@ -858,54 +868,51 @@ uint _ma_state_info_write(File file, MARIA_STATE_INFO *state, uint pWrite) } -uchar *_ma_state_info_read(uchar *ptr, MARIA_STATE_INFO *state) +byte *_ma_state_info_read(byte *ptr, MARIA_STATE_INFO *state) { - uint i,keys,key_parts,key_blocks; + uint i,keys,key_parts; memcpy_fixed(&state->header,ptr, sizeof(state->header)); - ptr +=sizeof(state->header); - keys=(uint) state->header.keys; - key_parts=mi_uint2korr(state->header.key_parts); - key_blocks=state->header.max_block_size_index; - - state->open_count = mi_uint2korr(ptr); ptr +=2; - state->changed= (bool) *ptr++; - state->sortkey = (uint) *ptr++; - state->state.records= mi_rowkorr(ptr); ptr +=8; - state->state.del = mi_rowkorr(ptr); ptr +=8; - state->split = mi_rowkorr(ptr); ptr +=8; - state->dellink= mi_sizekorr(ptr); ptr +=8; - state->state.key_file_length = mi_sizekorr(ptr); ptr +=8; - state->state.data_file_length= mi_sizekorr(ptr); ptr +=8; - state->state.empty = mi_sizekorr(ptr); ptr +=8; - state->state.key_empty= mi_sizekorr(ptr); ptr +=8; - state->auto_increment=mi_uint8korr(ptr); ptr +=8; - state->state.checksum=(ha_checksum) mi_uint8korr(ptr); ptr +=8; - state->process= mi_uint4korr(ptr); ptr +=4; - state->unique = mi_uint4korr(ptr); ptr +=4; - state->status = mi_uint4korr(ptr); ptr +=4; - state->update_count=mi_uint4korr(ptr); ptr +=4; + ptr+= sizeof(state->header); + keys= (uint) state->header.keys; + key_parts= mi_uint2korr(state->header.key_parts); + + state->open_count = mi_uint2korr(ptr); ptr+= 2; + state->changed= (my_bool) *ptr++; + state->sortkey= (uint) *ptr++; + state->state.records= mi_rowkorr(ptr); ptr+= 8; + state->state.del = mi_rowkorr(ptr); ptr+= 8; + state->split = mi_rowkorr(ptr); ptr+= 8; + state->dellink= mi_sizekorr(ptr); ptr+= 8; + state->first_bitmap_with_space= mi_sizekorr(ptr); ptr+= 8; + state->state.key_file_length = mi_sizekorr(ptr); ptr+= 8; + state->state.data_file_length= mi_sizekorr(ptr); ptr+= 8; + state->state.empty = mi_sizekorr(ptr); ptr+= 8; + state->state.key_empty= mi_sizekorr(ptr); ptr+= 8; + state->auto_increment=mi_uint8korr(ptr); ptr+= 8; + state->state.checksum=(ha_checksum) mi_uint8korr(ptr);ptr+= 8; + state->process= mi_uint4korr(ptr); ptr+= 4; + state->unique = mi_uint4korr(ptr); ptr+= 4; + state->status = mi_uint4korr(ptr); ptr+= 4; + state->update_count=mi_uint4korr(ptr); ptr+= 4; ptr+= state->state_diff_length; for (i=0; i < keys; i++) { - state->key_root[i]= mi_sizekorr(ptr); ptr +=8; - } - for (i=0; i < key_blocks; i++) - { - state->key_del[i] = mi_sizekorr(ptr); ptr +=8; + state->key_root[i]= mi_sizekorr(ptr); ptr+= 8; } - state->sec_index_changed = mi_uint4korr(ptr); ptr +=4; - state->sec_index_used = mi_uint4korr(ptr); ptr +=4; - state->version = mi_uint4korr(ptr); ptr +=4; - state->key_map = mi_uint8korr(ptr); ptr +=8; - state->create_time = (time_t) mi_sizekorr(ptr); ptr +=8; - state->recover_time =(time_t) mi_sizekorr(ptr); ptr +=8; - state->check_time = (time_t) mi_sizekorr(ptr); ptr +=8; - state->rec_per_key_rows=mi_sizekorr(ptr); ptr +=8; + state->key_del= mi_sizekorr(ptr); ptr+= 8; + state->sec_index_changed = mi_uint4korr(ptr); ptr+= 4; + state->sec_index_used = mi_uint4korr(ptr); ptr+= 4; + state->version = mi_uint4korr(ptr); ptr+= 4; + state->key_map = mi_uint8korr(ptr); ptr+= 8; + state->create_time = (time_t) mi_sizekorr(ptr); ptr+= 8; + state->recover_time =(time_t) mi_sizekorr(ptr); ptr+= 8; + state->check_time = (time_t) mi_sizekorr(ptr); ptr+= 8; + state->rec_per_key_rows=mi_sizekorr(ptr); ptr+= 8; for (i=0 ; i < key_parts ; i++) { - state->rec_per_key_part[i]= mi_uint4korr(ptr); ptr+=4; + state->rec_per_key_part[i]= mi_uint4korr(ptr); ptr+=4; } return ptr; } @@ -924,7 +931,7 @@ uint _ma_state_info_read_dsk(File file, MARIA_STATE_INFO *state, my_bool pRead) } else if (my_read(file, buff, state->state_length,MYF(MY_NABP))) return (MY_FILE_ERROR); - _ma_state_info_read((uchar*) buff, state); + _ma_state_info_read(buff, state); } return 0; } @@ -938,74 +945,84 @@ uint _ma_base_info_write(File file, MARIA_BASE_INFO *base) { uchar buff[MARIA_BASE_INFO_SIZE], *ptr=buff; - mi_sizestore(ptr,base->keystart); ptr +=8; - mi_sizestore(ptr,base->max_data_file_length); ptr +=8; - mi_sizestore(ptr,base->max_key_file_length); ptr +=8; - mi_rowstore(ptr,base->records); ptr +=8; - mi_rowstore(ptr,base->reloc); ptr +=8; - mi_int4store(ptr,base->mean_row_length); ptr +=4; - mi_int4store(ptr,base->reclength); ptr +=4; - mi_int4store(ptr,base->pack_reclength); ptr +=4; - mi_int4store(ptr,base->min_pack_length); ptr +=4; - mi_int4store(ptr,base->max_pack_length); ptr +=4; - mi_int4store(ptr,base->min_block_length); ptr +=4; - mi_int4store(ptr,base->fields); ptr +=4; - mi_int4store(ptr,base->pack_fields); ptr +=4; - *ptr++=base->rec_reflength; - *ptr++=base->key_reflength; - *ptr++=base->keys; - *ptr++=base->auto_key; - mi_int2store(ptr,base->pack_bits); ptr +=2; - mi_int2store(ptr,base->blobs); ptr +=2; - mi_int2store(ptr,base->max_key_block_length); ptr +=2; - mi_int2store(ptr,base->max_key_length); ptr +=2; - mi_int2store(ptr,base->extra_alloc_bytes); ptr +=2; + mi_sizestore(ptr,base->keystart); ptr+= 8; + mi_sizestore(ptr,base->max_data_file_length); ptr+= 8; + mi_sizestore(ptr,base->max_key_file_length); ptr+= 8; + mi_rowstore(ptr,base->records); ptr+= 8; + mi_rowstore(ptr,base->reloc); ptr+= 8; + mi_int4store(ptr,base->mean_row_length); ptr+= 4; + mi_int4store(ptr,base->reclength); ptr+= 4; + mi_int4store(ptr,base->pack_reclength); ptr+= 4; + mi_int4store(ptr,base->min_pack_length); ptr+= 4; + mi_int4store(ptr,base->max_pack_length); ptr+= 4; + mi_int4store(ptr,base->min_block_length); ptr+= 4; + mi_int2store(ptr,base->fields); ptr+= 2; + mi_int2store(ptr,base->fixed_not_null_fields); ptr+= 2; + mi_int2store(ptr,base->fixed_not_null_fields_length); ptr+= 2; + mi_int2store(ptr,base->max_field_lengths); ptr+= 2; + mi_int2store(ptr,base->pack_fields); ptr+= 2; + mi_int2store(ptr,0); ptr+= 2; + mi_int2store(ptr,base->null_bytes); ptr+= 2; + mi_int2store(ptr,base->original_null_bytes); ptr+= 2; + mi_int2store(ptr,base->field_offsets); ptr+= 2; + mi_int2store(ptr,base->min_row_length); ptr+= 2; + mi_int2store(ptr,base->block_size); ptr+= 2; + *ptr++= base->rec_reflength; + *ptr++= base->key_reflength; + *ptr++= base->keys; + *ptr++= base->auto_key; + *ptr++= base->transactional; + *ptr++= 0; /* Reserved */ + mi_int2store(ptr,base->pack_bytes); ptr+= 2; + mi_int2store(ptr,base->blobs); ptr+= 2; + mi_int2store(ptr,base->max_key_block_length); ptr+= 2; + mi_int2store(ptr,base->max_key_length); ptr+= 2; + mi_int2store(ptr,base->extra_alloc_bytes); ptr+= 2; *ptr++= base->extra_alloc_procent; - *ptr++= base->raid_type; - mi_int2store(ptr,base->raid_chunks); ptr +=2; - mi_int4store(ptr,base->raid_chunksize); ptr +=4; - bzero(ptr,6); ptr +=6; /* extra */ + bzero(ptr,16); ptr+= 16; /* extra */ + DBUG_ASSERT((ptr - buff) == MARIA_BASE_INFO_SIZE); return my_write(file,(char*) buff, (uint) (ptr-buff), MYF(MY_NABP)); } -uchar *_ma_n_base_info_read(uchar *ptr, MARIA_BASE_INFO *base) +static byte *_ma_base_info_read(byte *ptr, MARIA_BASE_INFO *base) { - base->keystart = mi_sizekorr(ptr); ptr +=8; - base->max_data_file_length = mi_sizekorr(ptr); ptr +=8; - base->max_key_file_length = mi_sizekorr(ptr); ptr +=8; - base->records = (ha_rows) mi_sizekorr(ptr); ptr +=8; - base->reloc = (ha_rows) mi_sizekorr(ptr); ptr +=8; - base->mean_row_length = mi_uint4korr(ptr); ptr +=4; - base->reclength = mi_uint4korr(ptr); ptr +=4; - base->pack_reclength = mi_uint4korr(ptr); ptr +=4; - base->min_pack_length = mi_uint4korr(ptr); ptr +=4; - base->max_pack_length = mi_uint4korr(ptr); ptr +=4; - base->min_block_length = mi_uint4korr(ptr); ptr +=4; - base->fields = mi_uint4korr(ptr); ptr +=4; - base->pack_fields = mi_uint4korr(ptr); ptr +=4; - - base->rec_reflength = *ptr++; - base->key_reflength = *ptr++; - base->keys= *ptr++; - base->auto_key= *ptr++; - base->pack_bits = mi_uint2korr(ptr); ptr +=2; - base->blobs = mi_uint2korr(ptr); ptr +=2; - base->max_key_block_length= mi_uint2korr(ptr); ptr +=2; - base->max_key_length = mi_uint2korr(ptr); ptr +=2; - base->extra_alloc_bytes = mi_uint2korr(ptr); ptr +=2; - base->extra_alloc_procent = *ptr++; - base->raid_type= *ptr++; - base->raid_chunks= mi_uint2korr(ptr); ptr +=2; - base->raid_chunksize= mi_uint4korr(ptr); ptr +=4; - /* TO BE REMOVED: Fix for old RAID files */ - if (base->raid_type == 0) - { - base->raid_chunks=0; - base->raid_chunksize=0; - } - - ptr+=6; + base->keystart= mi_sizekorr(ptr); ptr+= 8; + base->max_data_file_length= mi_sizekorr(ptr); ptr+= 8; + base->max_key_file_length= mi_sizekorr(ptr); ptr+= 8; + base->records= (ha_rows) mi_sizekorr(ptr); ptr+= 8; + base->reloc= (ha_rows) mi_sizekorr(ptr); ptr+= 8; + base->mean_row_length= mi_uint4korr(ptr); ptr+= 4; + base->reclength= mi_uint4korr(ptr); ptr+= 4; + base->pack_reclength= mi_uint4korr(ptr); ptr+= 4; + base->min_pack_length= mi_uint4korr(ptr); ptr+= 4; + base->max_pack_length= mi_uint4korr(ptr); ptr+= 4; + base->min_block_length= mi_uint4korr(ptr); ptr+= 4; + base->fields= mi_uint2korr(ptr); ptr+= 2; + base->fixed_not_null_fields= mi_uint2korr(ptr); ptr+= 2; + base->fixed_not_null_fields_length= mi_uint2korr(ptr);ptr+= 2; + base->max_field_lengths= mi_uint2korr(ptr); ptr+= 2; + base->pack_fields= mi_uint2korr(ptr); ptr+= 2; + ptr+= 2; + base->null_bytes= mi_uint2korr(ptr); ptr+= 2; + base->original_null_bytes= mi_uint2korr(ptr); ptr+= 2; + base->field_offsets= mi_uint2korr(ptr); ptr+= 2; + base->min_row_length= mi_uint2korr(ptr); ptr+= 2; + base->block_size= mi_uint2korr(ptr); ptr+= 2; + + base->rec_reflength= *ptr++; + base->key_reflength= *ptr++; + base->keys= *ptr++; + base->auto_key= *ptr++; + base->transactional= *ptr++; + ptr++; + base->pack_bytes= mi_uint2korr(ptr); ptr+= 2; + base->blobs= mi_uint2korr(ptr); ptr+= 2; + base->max_key_block_length= mi_uint2korr(ptr); ptr+= 2; + base->max_key_length= mi_uint2korr(ptr); ptr+= 2; + base->extra_alloc_bytes= mi_uint2korr(ptr); ptr+= 2; + base->extra_alloc_procent= *ptr++; + ptr+= 16; return ptr; } @@ -1018,13 +1035,13 @@ uint _ma_keydef_write(File file, MARIA_KEYDEF *keydef) uchar buff[MARIA_KEYDEF_SIZE]; uchar *ptr=buff; - *ptr++ = (uchar) keydef->keysegs; - *ptr++ = keydef->key_alg; /* Rtree or Btree */ - mi_int2store(ptr,keydef->flag); ptr +=2; - mi_int2store(ptr,keydef->block_length); ptr +=2; - mi_int2store(ptr,keydef->keylength); ptr +=2; - mi_int2store(ptr,keydef->minlength); ptr +=2; - mi_int2store(ptr,keydef->maxlength); ptr +=2; + *ptr++= (uchar) keydef->keysegs; + *ptr++= keydef->key_alg; /* Rtree or Btree */ + mi_int2store(ptr,keydef->flag); ptr+= 2; + mi_int2store(ptr,keydef->block_length); ptr+= 2; + mi_int2store(ptr,keydef->keylength); ptr+= 2; + mi_int2store(ptr,keydef->minlength); ptr+= 2; + mi_int2store(ptr,keydef->maxlength); ptr+= 2; return my_write(file,(char*) buff, (uint) (ptr-buff), MYF(MY_NABP)); } @@ -1033,12 +1050,11 @@ char *_ma_keydef_read(char *ptr, MARIA_KEYDEF *keydef) keydef->keysegs = (uint) *ptr++; keydef->key_alg = *ptr++; /* Rtree or Btree */ - keydef->flag = mi_uint2korr(ptr); ptr +=2; - keydef->block_length = mi_uint2korr(ptr); ptr +=2; - keydef->keylength = mi_uint2korr(ptr); ptr +=2; - keydef->minlength = mi_uint2korr(ptr); ptr +=2; - keydef->maxlength = mi_uint2korr(ptr); ptr +=2; - keydef->block_size_index = keydef->block_length/MARIA_MIN_KEY_BLOCK_LENGTH-1; + keydef->flag = mi_uint2korr(ptr); ptr+= 2; + keydef->block_length = mi_uint2korr(ptr); ptr+= 2; + keydef->keylength = mi_uint2korr(ptr); ptr+= 2; + keydef->minlength = mi_uint2korr(ptr); ptr+= 2; + keydef->maxlength = mi_uint2korr(ptr); ptr+= 2; keydef->underflow_block_length=keydef->block_length/3; keydef->version = 0; /* Not saved */ keydef->parser = &ft_default_parser; @@ -1062,9 +1078,9 @@ int _ma_keyseg_write(File file, const HA_KEYSEG *keyseg) *ptr++= keyseg->bit_start; *ptr++= keyseg->bit_end; *ptr++= keyseg->bit_length; - mi_int2store(ptr,keyseg->flag); ptr+=2; - mi_int2store(ptr,keyseg->length); ptr+=2; - mi_int4store(ptr,keyseg->start); ptr+=4; + mi_int2store(ptr,keyseg->flag); ptr+= 2; + mi_int2store(ptr,keyseg->length); ptr+= 2; + mi_int4store(ptr,keyseg->start); ptr+= 4; pos= keyseg->null_bit ? keyseg->null_pos : keyseg->bit_pos; mi_int4store(ptr, pos); ptr+=4; @@ -1081,10 +1097,10 @@ char *_ma_keyseg_read(char *ptr, HA_KEYSEG *keyseg) keyseg->bit_start = *ptr++; keyseg->bit_end = *ptr++; keyseg->bit_length = *ptr++; - keyseg->flag = mi_uint2korr(ptr); ptr +=2; - keyseg->length = mi_uint2korr(ptr); ptr +=2; - keyseg->start = mi_uint4korr(ptr); ptr +=4; - keyseg->null_pos = mi_uint4korr(ptr); ptr +=4; + keyseg->flag = mi_uint2korr(ptr); ptr+= 2; + keyseg->length = mi_uint2korr(ptr); ptr+= 2; + keyseg->start = mi_uint4korr(ptr); ptr+= 4; + keyseg->null_pos = mi_uint4korr(ptr); ptr+= 4; keyseg->charset=0; /* Will be filled in later */ if (keyseg->null_bit) keyseg->bit_pos= (uint16)(keyseg->null_pos + (keyseg->null_bit == 7)); @@ -1129,47 +1145,44 @@ uint _ma_recinfo_write(File file, MARIA_COLUMNDEF *recinfo) uchar buff[MARIA_COLUMNDEF_SIZE]; uchar *ptr=buff; - mi_int2store(ptr,recinfo->type); ptr +=2; - mi_int2store(ptr,recinfo->length); ptr +=2; - *ptr++ = recinfo->null_bit; - mi_int2store(ptr,recinfo->null_pos); ptr+= 2; + mi_int6store(ptr,recinfo->offset); ptr+= 6; + mi_int2store(ptr,recinfo->type); ptr+= 2; + mi_int2store(ptr,recinfo->length); ptr+= 2; + mi_int2store(ptr,recinfo->fill_length); ptr+= 2; + mi_int2store(ptr,recinfo->null_pos); ptr+= 2; + mi_int2store(ptr,recinfo->empty_pos); ptr+= 2; + (*ptr++)= recinfo->null_bit; + (*ptr++)= recinfo->empty_bit; return my_write(file,(char*) buff, (uint) (ptr-buff), MYF(MY_NABP)); } char *_ma_recinfo_read(char *ptr, MARIA_COLUMNDEF *recinfo) { - recinfo->type= mi_sint2korr(ptr); ptr +=2; - recinfo->length=mi_uint2korr(ptr); ptr +=2; - recinfo->null_bit= (uint8) *ptr++; - recinfo->null_pos=mi_uint2korr(ptr); ptr +=2; - return ptr; + recinfo->offset= mi_uint6korr(ptr); ptr+= 6; + recinfo->type= mi_sint2korr(ptr); ptr+= 2; + recinfo->length= mi_uint2korr(ptr); ptr+= 2; + recinfo->fill_length= mi_uint2korr(ptr); ptr+= 2; + recinfo->null_pos= mi_uint2korr(ptr); ptr+= 2; + recinfo->empty_pos= mi_uint2korr(ptr); ptr+= 2; + recinfo->null_bit= (uint8) *ptr++; + recinfo->empty_bit= (uint8) *ptr++; + return ptr; } /************************************************************************** -Open data file with or without RAID -We can't use dup() here as the data file descriptors need to have different -active seek-positions. + Open data file + We can't use dup() here as the data file descriptors need to have different + active seek-positions. -The argument file_to_dup is here for the future if there would on some OS -exist a dup()-like call that would give us two different file descriptors. + The argument file_to_dup is here for the future if there would on some OS + exist a dup()-like call that would give us two different file descriptors. *************************************************************************/ -int _ma_open_datafile(MARIA_HA *info, MARIA_SHARE *share, File file_to_dup __attribute__((unused))) +int _ma_open_datafile(MARIA_HA *info, MARIA_SHARE *share, + File file_to_dup __attribute__((unused))) { -#ifdef USE_RAID - if (share->base.raid_type) - { - info->dfile=my_raid_open(share->data_file_name, - share->mode | O_SHARE, - share->base.raid_type, - share->base.raid_chunks, - share->base.raid_chunksize, - MYF(MY_WME | MY_RAID)); - } - else -#endif - info->dfile=my_open(share->data_file_name, share->mode | O_SHARE, - MYF(MY_WME)); + info->dfile= my_open(share->data_file_name, share->mode | O_SHARE, + MYF(MY_WME)); return info->dfile >= 0 ? 0 : 1; } @@ -1264,3 +1277,25 @@ int maria_indexes_are_disabled(MARIA_HA *info) return (! maria_is_any_key_active(share->state.key_map) && share->base.keys); } + + +static my_bool maria_scan_init_dummy(MARIA_HA *info __attribute__((unused))) +{ + return 0; +} + +static void maria_scan_end_dummy(MARIA_HA *info __attribute__((unused))) +{ +} + +static my_bool maria_once_init_dummy(MARIA_SHARE *share + __attribute__((unused)), + File dfile __attribute__((unused))) +{ + return 0; +} + +static my_bool maria_once_end_dummy(MARIA_SHARE *share __attribute__((unused))) +{ + return 0; +} diff --git a/storage/maria/ma_packrec.c b/storage/maria/ma_packrec.c index eb99e299f9a..69d2f15ca16 100644 --- a/storage/maria/ma_packrec.c +++ b/storage/maria/ma_packrec.c @@ -44,7 +44,10 @@ #define OFFSET_TABLE_SIZE 512 -static uint read_huff_table(MARIA_BIT_BUFF *bit_buff,MARIA_DECODE_TREE *decode_tree, +static my_bool _ma_read_pack_info(MARIA_SHARE *share, File file, + pbool fix_keys); +static uint read_huff_table(MARIA_BIT_BUFF *bit_buff, + MARIA_DECODE_TREE *decode_tree, uint16 **decode_table,byte **intervall_buff, uint16 *tmp_buff); static void make_quick_table(uint16 *to_table,uint16 *decode_table, @@ -56,55 +59,61 @@ static uint copy_decode_table(uint16 *to_pos,uint offset, uint16 *decode_table); static uint find_longest_bitstream(uint16 *table, uint16 *end); static void (*get_unpack_function(MARIA_COLUMNDEF *rec))(MARIA_COLUMNDEF *field, - MARIA_BIT_BUFF *buff, - uchar *to, - uchar *end); -static void uf_zerofill_skip_zero(MARIA_COLUMNDEF *rec,MARIA_BIT_BUFF *bit_buff, - uchar *to,uchar *end); + MARIA_BIT_BUFF *buff, + byte *to, + byte *end); +static void uf_zerofill_skip_zero(MARIA_COLUMNDEF *rec, + MARIA_BIT_BUFF *bit_buff, + byte *to,byte *end); static void uf_skip_zero(MARIA_COLUMNDEF *rec,MARIA_BIT_BUFF *bit_buff, - uchar *to,uchar *end); + byte *to,byte *end); static void uf_space_normal(MARIA_COLUMNDEF *rec,MARIA_BIT_BUFF *bit_buff, - uchar *to,uchar *end); -static void uf_space_endspace_selected(MARIA_COLUMNDEF *rec,MARIA_BIT_BUFF *bit_buff, - uchar *to, uchar *end); + byte *to,byte *end); +static void uf_space_endspace_selected(MARIA_COLUMNDEF *rec, + MARIA_BIT_BUFF *bit_buff, + byte *to, byte *end); static void uf_endspace_selected(MARIA_COLUMNDEF *rec,MARIA_BIT_BUFF *bit_buff, - uchar *to,uchar *end); + byte *to,byte *end); static void uf_space_endspace(MARIA_COLUMNDEF *rec,MARIA_BIT_BUFF *bit_buff, - uchar *to,uchar *end); + byte *to,byte *end); static void uf_endspace(MARIA_COLUMNDEF *rec,MARIA_BIT_BUFF *bit_buff, - uchar *to,uchar *end); -static void uf_space_prespace_selected(MARIA_COLUMNDEF *rec,MARIA_BIT_BUFF *bit_buff, - uchar *to, uchar *end); + byte *to,byte *end); +static void uf_space_prespace_selected(MARIA_COLUMNDEF *rec, + MARIA_BIT_BUFF *bit_buff, + byte *to, byte *end); static void uf_prespace_selected(MARIA_COLUMNDEF *rec,MARIA_BIT_BUFF *bit_buff, - uchar *to,uchar *end); + byte *to,byte *end); static void uf_space_prespace(MARIA_COLUMNDEF *rec,MARIA_BIT_BUFF *bit_buff, - uchar *to,uchar *end); + byte *to,byte *end); static void uf_prespace(MARIA_COLUMNDEF *rec,MARIA_BIT_BUFF *bit_buff, - uchar *to,uchar *end); + byte *to,byte *end); static void uf_zerofill_normal(MARIA_COLUMNDEF *rec,MARIA_BIT_BUFF *bit_buff, - uchar *to,uchar *end); + byte *to,byte *end); static void uf_constant(MARIA_COLUMNDEF *rec,MARIA_BIT_BUFF *bit_buff, - uchar *to,uchar *end); + byte *to,byte *end); static void uf_intervall(MARIA_COLUMNDEF *rec,MARIA_BIT_BUFF *bit_buff, - uchar *to,uchar *end); + byte *to,byte *end); static void uf_zero(MARIA_COLUMNDEF *rec,MARIA_BIT_BUFF *bit_buff, - uchar *to,uchar *end); + byte *to,byte *end); static void uf_blob(MARIA_COLUMNDEF *rec, MARIA_BIT_BUFF *bit_buff, - uchar *to, uchar *end); + byte *to, byte *end); static void uf_varchar1(MARIA_COLUMNDEF *rec, MARIA_BIT_BUFF *bit_buff, - uchar *to, uchar *end); + byte *to, byte *end); static void uf_varchar2(MARIA_COLUMNDEF *rec, MARIA_BIT_BUFF *bit_buff, - uchar *to, uchar *end); + byte *to, byte *end); static void decode_bytes(MARIA_COLUMNDEF *rec,MARIA_BIT_BUFF *bit_buff, - uchar *to,uchar *end); -static uint decode_pos(MARIA_BIT_BUFF *bit_buff,MARIA_DECODE_TREE *decode_tree); -static void init_bit_buffer(MARIA_BIT_BUFF *bit_buff,uchar *buffer,uint length); + byte *to,byte *end); +static uint decode_pos(MARIA_BIT_BUFF *bit_buff, + MARIA_DECODE_TREE *decode_tree); +static void init_bit_buffer(MARIA_BIT_BUFF *bit_buff,uchar *buffer, + uint length); static uint fill_and_get_bits(MARIA_BIT_BUFF *bit_buff,uint count); static void fill_buffer(MARIA_BIT_BUFF *bit_buff); static uint max_bit(uint value); static uint read_pack_length(uint version, const uchar *buf, ulong *length); #ifdef HAVE_MMAP -static uchar *_ma_mempack_get_block_info(MARIA_HA *maria,MARIA_BLOCK_INFO *info, +static uchar *_ma_mempack_get_block_info(MARIA_HA *maria, + MARIA_BLOCK_INFO *info, uchar *header); #endif @@ -121,21 +130,43 @@ static maria_bit_type mask[]= 0x01ffffff, 0x03ffffff, 0x07ffffff, 0x0fffffff, 0x1fffffff, 0x3fffffff, 0x7fffffff, 0xffffffff, #endif - }; +}; - /* Read all packed info, allocate memory and fix field structs */ +my_bool _ma_once_init_pack_row(MARIA_SHARE *share, File dfile) +{ + share->options|= HA_OPTION_READ_ONLY_DATA; + if (_ma_read_pack_info(share, dfile, + (pbool) + test(!(share->options & + (HA_OPTION_PACK_RECORD | + HA_OPTION_TEMP_COMPRESS_RECORD))))) + return 1; + return 0; +} -my_bool _ma_read_pack_info(MARIA_HA *info, pbool fix_keys) +my_bool _ma_once_end_pack_row(MARIA_SHARE *share) +{ + if (share->decode_trees) + { + my_free((gptr) share->decode_trees,MYF(0)); + my_free((gptr) share->decode_tables,MYF(0)); + } + return 0; +} + + +/* Read all packed info, allocate memory and fix field structs */ + +static my_bool _ma_read_pack_info(MARIA_SHARE *share, File file, + pbool fix_keys) { - File file; int diff_length; uint i,trees,huff_tree_bits,rec_reflength,length; uint16 *decode_table,*tmp_buff; ulong elements,intervall_length; char *disk_cache,*intervall_buff; uchar header[32]; - MARIA_SHARE *share=info->s; MARIA_BIT_BUFF bit_buff; DBUG_ENTER("_ma_read_pack_info"); @@ -144,7 +175,6 @@ my_bool _ma_read_pack_info(MARIA_HA *info, pbool fix_keys) else if (maria_quick_table_bits > MAX_QUICK_TABLE_BITS) maria_quick_table_bits=MAX_QUICK_TABLE_BITS; - file=info->dfile; my_errno=0; if (my_read(file,(byte*) header,sizeof(header),MYF(MY_NABP))) { @@ -206,7 +236,7 @@ my_bool _ma_read_pack_info(MARIA_HA *info, pbool fix_keys) share->rec[i].space_length_bits=get_bits(&bit_buff,5); share->rec[i].huff_tree=share->decode_trees+(uint) get_bits(&bit_buff, huff_tree_bits); - share->rec[i].unpack=get_unpack_function(share->rec+i); + share->rec[i].unpack= get_unpack_function(share->rec+i); } skip_to_next_byte(&bit_buff); decode_table=share->decode_tables; @@ -257,7 +287,8 @@ err0: /* Read on huff-code-table from datafile */ -static uint read_huff_table(MARIA_BIT_BUFF *bit_buff, MARIA_DECODE_TREE *decode_tree, +static uint read_huff_table(MARIA_BIT_BUFF *bit_buff, + MARIA_DECODE_TREE *decode_tree, uint16 **decode_table, byte **intervall_buff, uint16 *tmp_buff) { @@ -432,7 +463,7 @@ static uint find_longest_bitstream(uint16 *table, uint16 *end) HA_ERR_WRONG_IN_RECORD or -1 on error */ -int _ma_read_pack_record(MARIA_HA *info, my_off_t filepos, byte *buf) +int _ma_read_pack_record(MARIA_HA *info, byte *buf, MARIA_RECORD_POS filepos) { MARIA_BLOCK_INFO block_info; File file; @@ -466,15 +497,20 @@ int _ma_pack_rec_unpack(register MARIA_HA *info, register byte *to, byte *from, MARIA_SHARE *share=info->s; DBUG_ENTER("_ma_pack_rec_unpack"); - init_bit_buffer(&info->bit_buff, (uchar*) from,reclength); - + if (info->s->base.null_bytes) + { + memcpy(to, from, info->s->base.null_bytes); + to+= info->s->base.null_bytes; + from+= info->s->base.null_bytes; + reclength-= info->s->base.null_bytes; + } + init_bit_buffer(&info->bit_buff, (uchar*) from, reclength); for (current_field=share->rec, end=current_field+share->base.fields ; current_field < end ; current_field++,to=end_field) { end_field=to+current_field->length; - (*current_field->unpack)(current_field,&info->bit_buff,(uchar*) to, - (uchar*) end_field); + (*current_field->unpack)(current_field,&info->bit_buff, to, end_field); } if (! info->bit_buff.error && info->bit_buff.pos - info->bit_buff.bits/8 == info->bit_buff.end) @@ -487,7 +523,7 @@ int _ma_pack_rec_unpack(register MARIA_HA *info, register byte *to, byte *from, /* Return function to unpack field */ static void (*get_unpack_function(MARIA_COLUMNDEF *rec)) -(MARIA_COLUMNDEF *, MARIA_BIT_BUFF *, uchar *, uchar *) + (MARIA_COLUMNDEF *, MARIA_BIT_BUFF *, byte *, byte *) { switch (rec->base_type) { case FIELD_SKIP_ZERO: @@ -541,8 +577,9 @@ static void (*get_unpack_function(MARIA_COLUMNDEF *rec)) /* The different functions to unpack a field */ -static void uf_zerofill_skip_zero(MARIA_COLUMNDEF *rec, MARIA_BIT_BUFF *bit_buff, - uchar *to, uchar *end) +static void uf_zerofill_skip_zero(MARIA_COLUMNDEF *rec, + MARIA_BIT_BUFF *bit_buff, + byte *to, byte *end) { if (get_bit(bit_buff)) bzero((char*) to,(uint) (end-to)); @@ -554,8 +591,8 @@ static void uf_zerofill_skip_zero(MARIA_COLUMNDEF *rec, MARIA_BIT_BUFF *bit_buff } } -static void uf_skip_zero(MARIA_COLUMNDEF *rec, MARIA_BIT_BUFF *bit_buff, uchar *to, - uchar *end) +static void uf_skip_zero(MARIA_COLUMNDEF *rec, MARIA_BIT_BUFF *bit_buff, + byte *to, byte *end) { if (get_bit(bit_buff)) bzero((char*) to,(uint) (end-to)); @@ -563,8 +600,8 @@ static void uf_skip_zero(MARIA_COLUMNDEF *rec, MARIA_BIT_BUFF *bit_buff, uchar * decode_bytes(rec,bit_buff,to,end); } -static void uf_space_normal(MARIA_COLUMNDEF *rec, MARIA_BIT_BUFF *bit_buff, uchar *to, - uchar *end) +static void uf_space_normal(MARIA_COLUMNDEF *rec, MARIA_BIT_BUFF *bit_buff, + byte *to, byte *end) { if (get_bit(bit_buff)) bfill((byte*) to,(end-to),' '); @@ -572,8 +609,9 @@ static void uf_space_normal(MARIA_COLUMNDEF *rec, MARIA_BIT_BUFF *bit_buff, ucha decode_bytes(rec,bit_buff,to,end); } -static void uf_space_endspace_selected(MARIA_COLUMNDEF *rec, MARIA_BIT_BUFF *bit_buff, - uchar *to, uchar *end) +static void uf_space_endspace_selected(MARIA_COLUMNDEF *rec, + MARIA_BIT_BUFF *bit_buff, + byte *to, byte *end) { uint spaces; if (get_bit(bit_buff)) @@ -596,8 +634,9 @@ static void uf_space_endspace_selected(MARIA_COLUMNDEF *rec, MARIA_BIT_BUFF *bit } } -static void uf_endspace_selected(MARIA_COLUMNDEF *rec, MARIA_BIT_BUFF *bit_buff, - uchar *to, uchar *end) +static void uf_endspace_selected(MARIA_COLUMNDEF *rec, + MARIA_BIT_BUFF *bit_buff, + byte *to, byte *end) { uint spaces; if (get_bit(bit_buff)) @@ -615,8 +654,8 @@ static void uf_endspace_selected(MARIA_COLUMNDEF *rec, MARIA_BIT_BUFF *bit_buff, decode_bytes(rec,bit_buff,to,end); } -static void uf_space_endspace(MARIA_COLUMNDEF *rec, MARIA_BIT_BUFF *bit_buff, uchar *to, - uchar *end) +static void uf_space_endspace(MARIA_COLUMNDEF *rec, MARIA_BIT_BUFF *bit_buff, + byte *to, byte *end) { uint spaces; if (get_bit(bit_buff)) @@ -634,8 +673,8 @@ static void uf_space_endspace(MARIA_COLUMNDEF *rec, MARIA_BIT_BUFF *bit_buff, uc } } -static void uf_endspace(MARIA_COLUMNDEF *rec, MARIA_BIT_BUFF *bit_buff, uchar *to, - uchar *end) +static void uf_endspace(MARIA_COLUMNDEF *rec, MARIA_BIT_BUFF *bit_buff, + byte *to, byte *end) { uint spaces; if ((spaces=get_bits(bit_buff,rec->space_length_bits))+to > end) @@ -648,8 +687,9 @@ static void uf_endspace(MARIA_COLUMNDEF *rec, MARIA_BIT_BUFF *bit_buff, uchar *t bfill((byte*) end-spaces,spaces,' '); } -static void uf_space_prespace_selected(MARIA_COLUMNDEF *rec, MARIA_BIT_BUFF *bit_buff, - uchar *to, uchar *end) +static void uf_space_prespace_selected(MARIA_COLUMNDEF *rec, + MARIA_BIT_BUFF *bit_buff, + byte *to, byte *end) { uint spaces; if (get_bit(bit_buff)) @@ -673,8 +713,9 @@ static void uf_space_prespace_selected(MARIA_COLUMNDEF *rec, MARIA_BIT_BUFF *bit } -static void uf_prespace_selected(MARIA_COLUMNDEF *rec, MARIA_BIT_BUFF *bit_buff, - uchar *to, uchar *end) +static void uf_prespace_selected(MARIA_COLUMNDEF *rec, + MARIA_BIT_BUFF *bit_buff, + byte *to, byte *end) { uint spaces; if (get_bit(bit_buff)) @@ -693,8 +734,8 @@ static void uf_prespace_selected(MARIA_COLUMNDEF *rec, MARIA_BIT_BUFF *bit_buff, } -static void uf_space_prespace(MARIA_COLUMNDEF *rec, MARIA_BIT_BUFF *bit_buff, uchar *to, - uchar *end) +static void uf_space_prespace(MARIA_COLUMNDEF *rec, MARIA_BIT_BUFF *bit_buff, + byte *to, byte *end) { uint spaces; if (get_bit(bit_buff)) @@ -712,8 +753,8 @@ static void uf_space_prespace(MARIA_COLUMNDEF *rec, MARIA_BIT_BUFF *bit_buff, uc } } -static void uf_prespace(MARIA_COLUMNDEF *rec, MARIA_BIT_BUFF *bit_buff, uchar *to, - uchar *end) +static void uf_prespace(MARIA_COLUMNDEF *rec, MARIA_BIT_BUFF *bit_buff, + byte *to, byte *end) { uint spaces; if ((spaces=get_bits(bit_buff,rec->space_length_bits))+to > end) @@ -726,24 +767,24 @@ static void uf_prespace(MARIA_COLUMNDEF *rec, MARIA_BIT_BUFF *bit_buff, uchar *t decode_bytes(rec,bit_buff,to+spaces,end); } -static void uf_zerofill_normal(MARIA_COLUMNDEF *rec, MARIA_BIT_BUFF *bit_buff, uchar *to, - uchar *end) +static void uf_zerofill_normal(MARIA_COLUMNDEF *rec, MARIA_BIT_BUFF *bit_buff, + byte *to, byte *end) { end-=rec->space_length_bits; - decode_bytes(rec,bit_buff,(uchar*) to,end); + decode_bytes(rec,bit_buff, to, end); bzero((char*) end,rec->space_length_bits); } static void uf_constant(MARIA_COLUMNDEF *rec, MARIA_BIT_BUFF *bit_buff __attribute__((unused)), - uchar *to, - uchar *end) + byte *to, byte *end) { memcpy(to,rec->huff_tree->intervalls,(size_t) (end-to)); } -static void uf_intervall(MARIA_COLUMNDEF *rec, MARIA_BIT_BUFF *bit_buff, uchar *to, - uchar *end) +static void uf_intervall(MARIA_COLUMNDEF *rec, MARIA_BIT_BUFF *bit_buff, + byte *to, + byte *end) { reg1 uint field_length=(uint) (end-to); memcpy(to,rec->huff_tree->intervalls+field_length*decode_pos(bit_buff, @@ -755,16 +796,16 @@ static void uf_intervall(MARIA_COLUMNDEF *rec, MARIA_BIT_BUFF *bit_buff, uchar * /*ARGSUSED*/ static void uf_zero(MARIA_COLUMNDEF *rec __attribute__((unused)), MARIA_BIT_BUFF *bit_buff __attribute__((unused)), - uchar *to, uchar *end) + byte *to, byte *end) { - bzero((char*) to,(uint) (end-to)); + bzero(to, (uint) (end-to)); } static void uf_blob(MARIA_COLUMNDEF *rec, MARIA_BIT_BUFF *bit_buff, - uchar *to, uchar *end) + byte *to, byte *end) { if (get_bit(bit_buff)) - bzero((byte*) to,(end-to)); + bzero(to, (uint) (end-to)); else { ulong length=get_bits(bit_buff,rec->space_length_bits); @@ -775,7 +816,8 @@ static void uf_blob(MARIA_COLUMNDEF *rec, MARIA_BIT_BUFF *bit_buff, bzero((byte*) to,(end-to)); return; } - decode_bytes(rec,bit_buff,bit_buff->blob_pos,bit_buff->blob_pos+length); + decode_bytes(rec,bit_buff,(byte*) bit_buff->blob_pos, + (byte*) bit_buff->blob_pos+length); _ma_store_blob_length((byte*) to,pack_length,length); memcpy_fixed((char*) to+pack_length,(char*) &bit_buff->blob_pos, sizeof(char*)); @@ -785,21 +827,21 @@ static void uf_blob(MARIA_COLUMNDEF *rec, MARIA_BIT_BUFF *bit_buff, static void uf_varchar1(MARIA_COLUMNDEF *rec, MARIA_BIT_BUFF *bit_buff, - uchar *to, uchar *end __attribute__((unused))) + byte *to, byte *end __attribute__((unused))) { if (get_bit(bit_buff)) to[0]= 0; /* Zero lengths */ else { ulong length=get_bits(bit_buff,rec->space_length_bits); - *to= (uchar) length; + *to= (char) length; decode_bytes(rec,bit_buff,to+1,to+1+length); } } static void uf_varchar2(MARIA_COLUMNDEF *rec, MARIA_BIT_BUFF *bit_buff, - uchar *to, uchar *end __attribute__((unused))) + byte *to, byte *end __attribute__((unused))) { if (get_bit(bit_buff)) to[0]=to[1]=0; /* Zero lengths */ @@ -815,8 +857,8 @@ static void uf_varchar2(MARIA_COLUMNDEF *rec, MARIA_BIT_BUFF *bit_buff, #if BITS_SAVED == 64 -static void decode_bytes(MARIA_COLUMNDEF *rec,MARIA_BIT_BUFF *bit_buff,uchar *to, - uchar *end) +static void decode_bytes(MARIA_COLUMNDEF *rec,MARIA_BIT_BUFF *bit_buff, + byte *to, byte *end) { reg1 uint bits,low_byte; reg3 uint16 *pos; @@ -850,7 +892,7 @@ static void decode_bytes(MARIA_COLUMNDEF *rec,MARIA_BIT_BUFF *bit_buff,uchar *to low_byte=decode_tree->table[low_byte]; if (low_byte & IS_CHAR) { - *to++ = (low_byte & 255); /* Found char in quick table */ + *to++ = (char) (low_byte & 255); /* Found char in quick table */ bits-= ((low_byte >> 8) & 31); /* Remove bits used */ } else @@ -870,7 +912,7 @@ static void decode_bytes(MARIA_COLUMNDEF *rec,MARIA_BIT_BUFF *bit_buff,uchar *to decode_bytes_test_bit(7); bits-=8; } - *to++ = *pos; + *to++ = (char) *pos; } } while (to != end); @@ -880,8 +922,8 @@ static void decode_bytes(MARIA_COLUMNDEF *rec,MARIA_BIT_BUFF *bit_buff,uchar *to #else -static void decode_bytes(MARIA_COLUMNDEF *rec, MARIA_BIT_BUFF *bit_buff, uchar *to, - uchar *end) +static void decode_bytes(MARIA_COLUMNDEF *rec, MARIA_BIT_BUFF *bit_buff, + byte *to, byte *end) { reg1 uint bits,low_byte; reg3 uint16 *pos; @@ -967,7 +1009,7 @@ static void decode_bytes(MARIA_COLUMNDEF *rec, MARIA_BIT_BUFF *bit_buff, uchar * decode_bytes_test_bit(7); bits-=8; } - *to++ = (uchar) *pos; + *to++ = (char) *pos; } } while (to != end); @@ -977,7 +1019,8 @@ static void decode_bytes(MARIA_COLUMNDEF *rec, MARIA_BIT_BUFF *bit_buff, uchar * #endif /* BIT_SAVED == 64 */ -static uint decode_pos(MARIA_BIT_BUFF *bit_buff, MARIA_DECODE_TREE *decode_tree) +static uint decode_pos(MARIA_BIT_BUFF *bit_buff, + MARIA_DECODE_TREE *decode_tree) { uint16 *pos=decode_tree->table; for (;;) @@ -991,8 +1034,9 @@ static uint decode_pos(MARIA_BIT_BUFF *bit_buff, MARIA_DECODE_TREE *decode_tree) } -int _ma_read_rnd_pack_record(MARIA_HA *info, byte *buf, - register my_off_t filepos, +int _ma_read_rnd_pack_record(MARIA_HA *info, + byte *buf, + register MARIA_RECORD_POS filepos, my_bool skip_deleted_blocks) { uint b_type; @@ -1039,9 +1083,9 @@ int _ma_read_rnd_pack_record(MARIA_HA *info, byte *buf, MYF(MY_NABP))) goto err; } - info->packed_length=block_info.rec_len; - info->lastpos=filepos; - info->nextpos=block_info.filepos+block_info.rec_len; + info->packed_length= block_info.rec_len; + info->cur_row.lastpos= filepos; + info->cur_row.nextpos= block_info.filepos+block_info.rec_len; info->update|= HA_STATE_AKTIV | HA_STATE_KEY_CHANGED; DBUG_RETURN (_ma_pack_rec_unpack(info,buf,info->rec_buff, @@ -1053,10 +1097,10 @@ int _ma_read_rnd_pack_record(MARIA_HA *info, byte *buf, /* Read and process header from a huff-record-file */ -uint _ma_pack_get_block_info(MARIA_HA *maria, MARIA_BLOCK_INFO *info, File file, - my_off_t filepos) +uint _ma_pack_get_block_info(MARIA_HA *maria, MARIA_BLOCK_INFO *info, + File file, my_off_t filepos) { - uchar *header=info->header; + uchar *header= info->header; uint head_length,ref_length; LINT_INIT(ref_length); @@ -1078,8 +1122,9 @@ uint _ma_pack_get_block_info(MARIA_HA *maria, MARIA_BLOCK_INFO *info, File file, { head_length+= read_pack_length((uint) maria->s->pack.version, header + head_length, &info->blob_len); - if (!(_ma_alloc_rec_buff(maria,info->rec_len + info->blob_len, - &maria->rec_buff))) + if (_ma_alloc_buffer(&maria->rec_buff, &maria->rec_buff_size, + info->rec_len + info->blob_len + + maria->s->base.extra_rec_buff_size)) return BLOCK_FATAL_ERROR; /* not enough memory */ maria->bit_buff.blob_pos=(uchar*) maria->rec_buff+info->rec_len; maria->bit_buff.blob_end= maria->bit_buff.blob_pos+info->blob_len; @@ -1098,7 +1143,8 @@ uint _ma_pack_get_block_info(MARIA_HA *maria, MARIA_BLOCK_INFO *info, File file, /* rutines for bit buffer */ /* Note buffer must be 6 byte bigger than longest row */ -static void init_bit_buffer(MARIA_BIT_BUFF *bit_buff, uchar *buffer, uint length) +static void init_bit_buffer(MARIA_BIT_BUFF *bit_buff, uchar *buffer, + uint length) { bit_buff->pos=buffer; bit_buff->end=buffer+length; @@ -1174,8 +1220,10 @@ static uint max_bit(register uint value) #ifdef HAVE_MMAP -static int _ma_read_mempack_record(MARIA_HA *info,my_off_t filepos,byte *buf); -static int _ma_read_rnd_mempack_record(MARIA_HA*, byte *,my_off_t, my_bool); +static int _ma_read_mempack_record(MARIA_HA *info, byte *buf, + MARIA_RECORD_POS filepos); +static int _ma_read_rnd_mempack_record(MARIA_HA*, byte *, MARIA_RECORD_POS, + my_bool); my_bool _ma_memmap_file(MARIA_HA *info) { @@ -1195,7 +1243,7 @@ my_bool _ma_memmap_file(MARIA_HA *info) } info->opt_flag|= MEMMAP_USED; info->read_record= share->read_record= _ma_read_mempack_record; - share->read_rnd= _ma_read_rnd_mempack_record; + share->scan= _ma_read_rnd_mempack_record; DBUG_RETURN(1); } @@ -1207,7 +1255,8 @@ void _ma_unmap_file(MARIA_HA *info) } -static uchar *_ma_mempack_get_block_info(MARIA_HA *maria,MARIA_BLOCK_INFO *info, +static uchar *_ma_mempack_get_block_info(MARIA_HA *maria, + MARIA_BLOCK_INFO *info, uchar *header) { header+= read_pack_length((uint) maria->s->pack.version, header, @@ -1217,8 +1266,8 @@ static uchar *_ma_mempack_get_block_info(MARIA_HA *maria,MARIA_BLOCK_INFO *info, header+= read_pack_length((uint) maria->s->pack.version, header, &info->blob_len); /* _ma_alloc_rec_buff sets my_errno on error */ - if (!(_ma_alloc_rec_buff(maria, info->blob_len, - &maria->rec_buff))) + if (_ma_alloc_buffer(&maria->rec_buff, &maria->rec_buff_size, + info->blob_len + maria->s->base.extra_rec_buff_size)) return 0; /* not enough memory */ maria->bit_buff.blob_pos=(uchar*) maria->rec_buff; maria->bit_buff.blob_end= (uchar*) maria->rec_buff + info->blob_len; @@ -1227,7 +1276,8 @@ static uchar *_ma_mempack_get_block_info(MARIA_HA *maria,MARIA_BLOCK_INFO *info, } -static int _ma_read_mempack_record(MARIA_HA *info, my_off_t filepos, byte *buf) +static int _ma_read_mempack_record(MARIA_HA *info, byte *buf, + MARIA_RECORD_POS filepos) { MARIA_BLOCK_INFO block_info; MARIA_SHARE *share=info->s; @@ -1246,8 +1296,9 @@ static int _ma_read_mempack_record(MARIA_HA *info, my_off_t filepos, byte *buf) /*ARGSUSED*/ -static int _ma_read_rnd_mempack_record(MARIA_HA *info, byte *buf, - register my_off_t filepos, +static int _ma_read_rnd_mempack_record(MARIA_HA *info, + byte *buf, + register MARIA_RECORD_POS filepos, my_bool skip_deleted_blocks __attribute__((unused))) { @@ -1274,8 +1325,8 @@ static int _ma_read_rnd_mempack_record(MARIA_HA *info, byte *buf, } #endif info->packed_length=block_info.rec_len; - info->lastpos=filepos; - info->nextpos=filepos+(uint) (pos-start)+block_info.rec_len; + info->cur_row.lastpos= filepos; + info->cur_row.nextpos= filepos+(uint) (pos-start)+block_info.rec_len; info->update|= HA_STATE_AKTIV | HA_STATE_KEY_CHANGED; DBUG_RETURN (_ma_pack_rec_unpack(info,buf,pos, block_info.rec_len)); diff --git a/storage/maria/ma_page.c b/storage/maria/ma_page.c index 054b8e16468..e7ca329c3e2 100644 --- a/storage/maria/ma_page.c +++ b/storage/maria/ma_page.c @@ -20,22 +20,20 @@ /* Fetch a key-page in memory */ -uchar *_ma_fetch_keypage(register MARIA_HA *info, MARIA_KEYDEF *keyinfo, - my_off_t page, int level, - uchar *buff, int return_buffer) +byte *_ma_fetch_keypage(register MARIA_HA *info, MARIA_KEYDEF *keyinfo, + my_off_t page, int level, + byte *buff, int return_buffer) { - uchar *tmp; + byte *tmp; uint page_size; DBUG_ENTER("_ma_fetch_keypage"); DBUG_PRINT("enter",("page: %ld",page)); - tmp=(uchar*) key_cache_read(info->s->key_cache, - info->s->kfile, page, level, (byte*) buff, - (uint) keyinfo->block_length, - (uint) keyinfo->block_length, - return_buffer); + tmp= key_cache_read(info->s->key_cache, info->s->kfile, page, level, buff, + info->s->block_size, info->s->block_size, + return_buffer); if (tmp == info->buff) - info->buff_used=1; + info->keybuff_used=1; else if (!tmp) { DBUG_PRINT("error",("Got errno: %d from key_cache_read",my_errno)); @@ -53,8 +51,8 @@ uchar *_ma_fetch_keypage(register MARIA_HA *info, MARIA_KEYDEF *keyinfo, DBUG_DUMP("page", (char*) tmp, keyinfo->block_length); info->last_keypage = HA_OFFSET_ERROR; maria_print_error(info->s, HA_ERR_CRASHED); - my_errno = HA_ERR_CRASHED; - tmp = 0; + my_errno= HA_ERR_CRASHED; + tmp= 0; } DBUG_RETURN(tmp); } /* _ma_fetch_keypage */ @@ -63,7 +61,7 @@ uchar *_ma_fetch_keypage(register MARIA_HA *info, MARIA_KEYDEF *keyinfo, /* Write a key-page on disk */ int _ma_write_keypage(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo, - my_off_t page, int level, uchar *buff) + my_off_t page, int level, byte *buff) { reg3 uint length; DBUG_ENTER("_ma_write_keypage"); @@ -112,8 +110,8 @@ int _ma_dispose(register MARIA_HA *info, MARIA_KEYDEF *keyinfo, my_off_t pos, DBUG_ENTER("_ma_dispose"); DBUG_PRINT("enter",("pos: %ld", (long) pos)); - old_link= info->s->state.key_del[keyinfo->block_size_index]; - info->s->state.key_del[keyinfo->block_size_index]= pos; + old_link= info->s->state.key_del; + info->s->state.key_del= pos; mi_sizestore(buff,old_link); info->s->state.changed|= STATE_NOT_SORTED_PAGES; DBUG_RETURN(key_cache_write(info->s->key_cache, @@ -129,11 +127,10 @@ int _ma_dispose(register MARIA_HA *info, MARIA_KEYDEF *keyinfo, my_off_t pos, my_off_t _ma_new(register MARIA_HA *info, MARIA_KEYDEF *keyinfo, int level) { my_off_t pos; - char buff[8]; + byte buff[8]; DBUG_ENTER("_ma_new"); - if ((pos= info->s->state.key_del[keyinfo->block_size_index]) == - HA_OFFSET_ERROR) + if ((pos= info->s->state.key_del) == HA_OFFSET_ERROR) { if (info->state->key_file_length >= info->s->base.max_key_file_length - keyinfo->block_length) @@ -153,7 +150,7 @@ my_off_t _ma_new(register MARIA_HA *info, MARIA_KEYDEF *keyinfo, int level) (uint) keyinfo->block_length,0)) pos= HA_OFFSET_ERROR; else - info->s->state.key_del[keyinfo->block_size_index]= mi_sizekorr(buff); + info->s->state.key_del= mi_sizekorr(buff); } info->s->state.changed|= STATE_NOT_SORTED_PAGES; DBUG_PRINT("exit",("Pos: %ld",(long) pos)); diff --git a/storage/maria/ma_range.c b/storage/maria/ma_range.c index 0f6883f4c9d..243e8e1b9c3 100644 --- a/storage/maria/ma_range.c +++ b/storage/maria/ma_range.c @@ -24,10 +24,10 @@ static ha_rows _ma_record_pos(MARIA_HA *info,const byte *key,uint key_len, enum ha_rkey_function search_flag); -static double _ma_search_pos(MARIA_HA *info,MARIA_KEYDEF *keyinfo,uchar *key, - uint key_len,uint nextflag,my_off_t pos); -static uint _ma_keynr(MARIA_HA *info,MARIA_KEYDEF *keyinfo,uchar *page, - uchar *keypos,uint *ret_max_key); +static double _ma_search_pos(MARIA_HA *info,MARIA_KEYDEF *keyinfo, byte *key, + uint key_len,uint nextflag, my_off_t pos); +static uint _ma_keynr(MARIA_HA *info, MARIA_KEYDEF *keyinfo, byte *page, + byte *keypos, uint *ret_max_key); /* @@ -68,12 +68,12 @@ ha_rows maria_records_in_range(MARIA_HA *info, int inx, key_range *min_key, #ifdef HAVE_RTREE_KEYS case HA_KEY_ALG_RTREE: { - uchar * key_buff; + byte *key_buff; uint start_key_len; key_buff= info->lastkey+info->s->base.max_key_length; start_key_len= _ma_pack_key(info,inx, key_buff, - (uchar*) min_key->key, min_key->length, + min_key->key, min_key->length, (HA_KEYSEG**) 0); res= maria_rtree_estimate(info, inx, key_buff, start_key_len, maria_read_vec[min_key->flag]); @@ -113,24 +113,23 @@ static ha_rows _ma_record_pos(MARIA_HA *info, const byte *key, uint key_len, { uint inx=(uint) info->lastinx, nextflag; MARIA_KEYDEF *keyinfo=info->s->keyinfo+inx; - uchar *key_buff; + byte *key_buff; double pos; - DBUG_ENTER("_ma_record_pos"); DBUG_PRINT("enter",("search_flag: %d",search_flag)); if (key_len == 0) - key_len=USE_WHOLE_KEY; + key_len= USE_WHOLE_KEY; key_buff=info->lastkey+info->s->base.max_key_length; - key_len= _ma_pack_key(info,inx,key_buff,(uchar*) key,key_len, + key_len= _ma_pack_key(info, inx, key_buff, key, key_len, (HA_KEYSEG**) 0); - DBUG_EXECUTE("key", _ma_print_key(DBUG_FILE,keyinfo->seg, - (uchar*) key_buff,key_len);); + DBUG_EXECUTE("key", _ma_print_key(DBUG_FILE, keyinfo->seg, + key_buff, key_len);); nextflag=maria_read_vec[search_flag]; if (!(nextflag & (SEARCH_FIND | SEARCH_NO_FIND | SEARCH_LAST))) key_len=USE_WHOLE_KEY; - pos= _ma_search_pos(info,keyinfo,key_buff,key_len, + pos= _ma_search_pos(info,keyinfo, key_buff, key_len, nextflag | SEARCH_SAVE_BUFF, info->s->state.key_root[inx]); if (pos >= 0.0) @@ -147,13 +146,13 @@ static ha_rows _ma_record_pos(MARIA_HA *info, const byte *key, uint key_len, static double _ma_search_pos(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo, - uchar *key, uint key_len, uint nextflag, + byte *key, uint key_len, uint nextflag, register my_off_t pos) { int flag; uint nod_flag,keynr,max_keynr; my_bool after_key; - uchar *keypos,*buff; + byte *keypos, *buff; double offset; DBUG_ENTER("_ma_search_pos"); @@ -162,7 +161,7 @@ static double _ma_search_pos(register MARIA_HA *info, if (!(buff= _ma_fetch_keypage(info,keyinfo,pos,DFLT_INIT_HITS,info->buff,1))) goto err; - flag=(*keyinfo->bin_search)(info,keyinfo,buff,key,key_len,nextflag, + flag=(*keyinfo->bin_search)(info, keyinfo, buff, key, key_len, nextflag, &keypos,info->lastkey, &after_key); nod_flag=_ma_test_if_nod(buff); keynr= _ma_keynr(info,keyinfo,buff,keypos,&max_keynr); @@ -213,11 +212,11 @@ err: /* Get keynummer of current key and max number of keys in nod */ -static uint _ma_keynr(MARIA_HA *info, register MARIA_KEYDEF *keyinfo, uchar *page, - uchar *keypos, uint *ret_max_key) +static uint _ma_keynr(MARIA_HA *info, register MARIA_KEYDEF *keyinfo, + byte *page, byte *keypos, uint *ret_max_key) { uint nod_flag,keynr,max_key; - uchar t_buff[HA_MAX_KEY_BUFF],*end; + byte t_buff[HA_MAX_KEY_BUFF],*end; end= page+maria_getint(page); nod_flag=_ma_test_if_nod(page); diff --git a/storage/maria/ma_rfirst.c b/storage/maria/ma_rfirst.c index 503e8989936..6fa8af75c40 100644 --- a/storage/maria/ma_rfirst.c +++ b/storage/maria/ma_rfirst.c @@ -21,7 +21,7 @@ int maria_rfirst(MARIA_HA *info, byte *buf, int inx) { DBUG_ENTER("maria_rfirst"); - info->lastpos= HA_OFFSET_ERROR; + info->cur_row.lastpos= HA_OFFSET_ERROR; info->update|= HA_STATE_PREV_FOUND; DBUG_RETURN(maria_rnext(info,buf,inx)); } /* maria_rfirst */ diff --git a/storage/maria/ma_rkey.c b/storage/maria/ma_rkey.c index 2cb54a73b15..bd92ebd4e4c 100644 --- a/storage/maria/ma_rkey.c +++ b/storage/maria/ma_rkey.c @@ -22,16 +22,16 @@ /* Read a record using key */ /* Ordinary search_flag is 0 ; Give error if no record with key */ -int maria_rkey(MARIA_HA *info, byte *buf, int inx, const byte *key, uint key_len, - enum ha_rkey_function search_flag) +int maria_rkey(MARIA_HA *info, byte *buf, int inx, const byte *key, + uint key_len, enum ha_rkey_function search_flag) { - uchar *key_buff; + byte *key_buff; MARIA_SHARE *share=info->s; MARIA_KEYDEF *keyinfo; HA_KEYSEG *last_used_keyseg; uint pack_key_length, use_key_length, nextflag; DBUG_ENTER("maria_rkey"); - DBUG_PRINT("enter", ("base: %lx buf: %lx inx: %d search_flag: %d", + DBUG_PRINT("enter", ("base: 0x%lx buf: 0x%lx inx: %d search_flag: %d", (long) info, (long) buf, inx, search_flag)); if ((inx = _ma_check_index(info,inx)) < 0) @@ -47,7 +47,7 @@ int maria_rkey(MARIA_HA *info, byte *buf, int inx, const byte *key, uint key_len /* key is already packed!; This happens when we are using a MERGE TABLE */ - key_buff=info->lastkey+info->s->base.max_key_length; + key_buff= info->lastkey+info->s->base.max_key_length; pack_key_length= key_len; bmove(key_buff,key,key_len); last_used_keyseg= 0; @@ -58,7 +58,7 @@ int maria_rkey(MARIA_HA *info, byte *buf, int inx, const byte *key, uint key_len key_len=USE_WHOLE_KEY; /* Save the packed key for later use in the second buffer of lastkey. */ key_buff=info->lastkey+info->s->base.max_key_length; - pack_key_length= _ma_pack_key(info,(uint) inx, key_buff, (uchar*) key, + pack_key_length= _ma_pack_key(info,(uint) inx, key_buff, key, key_len, &last_used_keyseg); /* Save packed_key_length for use by the MERGE engine. */ info->pack_key_length= pack_key_length; @@ -82,15 +82,17 @@ int maria_rkey(MARIA_HA *info, byte *buf, int inx, const byte *key, uint key_len if (maria_rtree_find_first(info,inx,key_buff,use_key_length,nextflag) < 0) { maria_print_error(info->s, HA_ERR_CRASHED); - my_errno=HA_ERR_CRASHED; - goto err; + my_errno= HA_ERR_CRASHED; + info->cur_row.lastpos= HA_OFFSET_ERROR; } break; #endif case HA_KEY_ALG_BTREE: default: if (!_ma_search(info, keyinfo, key_buff, use_key_length, - maria_read_vec[search_flag], info->s->state.key_root[inx])) + maria_read_vec[search_flag], + info->s->state.key_root[inx]) && + share->concurrent_insert) { /* If we are searching for an exact key (including the data pointer) @@ -98,50 +100,65 @@ int maria_rkey(MARIA_HA *info, byte *buf, int inx, const byte *key, uint key_len then the result is "key not found". */ if ((search_flag == HA_READ_KEY_EXACT) && - (info->lastpos >= info->state->data_file_length)) + (info->cur_row.lastpos >= info->state->data_file_length)) { my_errno= HA_ERR_KEY_NOT_FOUND; - info->lastpos= HA_OFFSET_ERROR; + info->cur_row.lastpos= HA_OFFSET_ERROR; } - else while (info->lastpos >= info->state->data_file_length) + else { - /* - Skip rows that are inserted by other threads since we got a lock - Note that this can only happen if we are not searching after an - exact key, because the keys are sorted according to position - */ - - if (_ma_search_next(info, keyinfo, info->lastkey, - info->lastkey_length, - maria_readnext_vec[search_flag], - info->s->state.key_root[inx])) - break; + while (info->cur_row.lastpos >= info->state->data_file_length) + { + /* + Skip rows that are inserted by other threads since we got a lock + Note that this can only happen if we are not searching after an + exact key, because the keys are sorted according to position + */ + + if (_ma_search_next(info, keyinfo, info->lastkey, + info->lastkey_length, + maria_readnext_vec[search_flag], + info->s->state.key_root[inx])) + { + info->cur_row.lastpos= HA_OFFSET_ERROR; + break; + } + } } } } if (share->concurrent_insert) rw_unlock(&share->key_root_lock[inx]); + if (info->cur_row.lastpos == HA_OFFSET_ERROR) + { + fast_ma_writeinfo(info); + goto err; + } + /* Calculate length of the found key; Used by maria_rnext_same */ - if ((keyinfo->flag & HA_VAR_LENGTH_KEY) && last_used_keyseg && - info->lastpos != HA_OFFSET_ERROR) + if ((keyinfo->flag & HA_VAR_LENGTH_KEY) && last_used_keyseg) info->last_rkey_length= _ma_keylength_part(keyinfo, info->lastkey, last_used_keyseg); else info->last_rkey_length= pack_key_length; + /* Check if we don't want to have record back, only error message */ if (!buf) - DBUG_RETURN(info->lastpos == HA_OFFSET_ERROR ? my_errno : 0); - - if (!(*info->read_record)(info,info->lastpos,buf)) + { + fast_ma_writeinfo(info); + DBUG_RETURN(0); + } + if (!(*info->read_record)(info, buf, info->cur_row.lastpos)) { info->update|= HA_STATE_AKTIV; /* Record is read */ DBUG_RETURN(0); } - info->lastpos = HA_OFFSET_ERROR; /* Didn't find key */ + info->cur_row.lastpos= HA_OFFSET_ERROR; /* Didn't find row */ +err: /* Store last used key as a base for read next */ memcpy(info->lastkey,key_buff,pack_key_length); info->last_rkey_length= pack_key_length; @@ -150,6 +167,5 @@ int maria_rkey(MARIA_HA *info, byte *buf, int inx, const byte *key, uint key_len if (search_flag == HA_READ_AFTER_KEY) info->update|=HA_STATE_NEXT_FOUND; /* Previous gives last row */ -err: DBUG_RETURN(my_errno); } /* _ma_rkey */ diff --git a/storage/maria/ma_rlast.c b/storage/maria/ma_rlast.c index 8ce26afa78d..504cc89aed3 100644 --- a/storage/maria/ma_rlast.c +++ b/storage/maria/ma_rlast.c @@ -21,7 +21,7 @@ int maria_rlast(MARIA_HA *info, byte *buf, int inx) { DBUG_ENTER("maria_rlast"); - info->lastpos= HA_OFFSET_ERROR; + info->cur_row.lastpos= HA_OFFSET_ERROR; info->update|= HA_STATE_NEXT_FOUND; DBUG_RETURN(maria_rprev(info,buf,inx)); } /* maria_rlast */ diff --git a/storage/maria/ma_rnext.c b/storage/maria/ma_rnext.c index 8f342c6a8d2..c7feded933e 100644 --- a/storage/maria/ma_rnext.c +++ b/storage/maria/ma_rnext.c @@ -34,7 +34,8 @@ int maria_rnext(MARIA_HA *info, byte *buf, int inx) if ((inx = _ma_check_index(info,inx)) < 0) DBUG_RETURN(my_errno); flag=SEARCH_BIGGER; /* Read next */ - if (info->lastpos == HA_OFFSET_ERROR && info->update & HA_STATE_PREV_FOUND) + if (info->cur_row.lastpos == HA_OFFSET_ERROR && + info->update & HA_STATE_PREV_FOUND) flag=0; /* Read first */ if (fast_ma_readinfo(info)) @@ -86,7 +87,7 @@ int maria_rnext(MARIA_HA *info, byte *buf, int inx) { if (!error) { - while (info->lastpos >= info->state->data_file_length) + while (info->cur_row.lastpos >= info->state->data_file_length) { /* Skip rows inserted by other threads since we got a lock */ if ((error= _ma_search_next(info,info->s->keyinfo+inx, @@ -110,9 +111,9 @@ int maria_rnext(MARIA_HA *info, byte *buf, int inx) } else if (!buf) { - DBUG_RETURN(info->lastpos==HA_OFFSET_ERROR ? my_errno : 0); + DBUG_RETURN(info->cur_row.lastpos == HA_OFFSET_ERROR ? my_errno : 0); } - else if (!(*info->read_record)(info,info->lastpos,buf)) + else if (!(*info->read_record)(info, buf, info->cur_row.lastpos)) { info->update|= HA_STATE_AKTIV; /* Record is read */ DBUG_RETURN(0); diff --git a/storage/maria/ma_rnext_same.c b/storage/maria/ma_rnext_same.c index b53639073e3..a5ce0cfe15c 100644 --- a/storage/maria/ma_rnext_same.c +++ b/storage/maria/ma_rnext_same.c @@ -17,13 +17,14 @@ #include "maria_def.h" #include "ma_rt_index.h" - /* - Read next row with the same key as previous read, but abort if - the key changes. - One may have done a write, update or delete of the previous row. - NOTE! Even if one changes the previous row, the next read is done - based on the position of the last used key! - */ +/* + Read next row with the same key as previous read, but abort if + the key changes. + One may have done a write, update or delete of the previous row. + + NOTE! Even if one changes the previous row, the next read is done + based on the position of the last used key! +*/ int maria_rnext_same(MARIA_HA *info, byte *buf) { @@ -32,9 +33,10 @@ int maria_rnext_same(MARIA_HA *info, byte *buf) MARIA_KEYDEF *keyinfo; DBUG_ENTER("maria_rnext_same"); - if ((int) (inx=info->lastinx) < 0 || info->lastpos == HA_OFFSET_ERROR) + if ((int) (inx= info->lastinx) < 0 || + info->cur_row.lastpos == HA_OFFSET_ERROR) DBUG_RETURN(my_errno=HA_ERR_WRONG_INDEX); - keyinfo=info->s->keyinfo+inx; + keyinfo= info->s->keyinfo+inx; if (fast_ma_readinfo(info)) DBUG_RETURN(my_errno); @@ -50,7 +52,7 @@ int maria_rnext_same(MARIA_HA *info, byte *buf) { error=1; my_errno=HA_ERR_END_OF_FILE; - info->lastpos= HA_OFFSET_ERROR; + info->cur_row.lastpos= HA_OFFSET_ERROR; break; } break; @@ -68,16 +70,17 @@ int maria_rnext_same(MARIA_HA *info, byte *buf) info->lastkey_length,SEARCH_BIGGER, info->s->state.key_root[inx]))) break; - if (ha_key_cmp(keyinfo->seg, info->lastkey, info->lastkey2, + if (ha_key_cmp(keyinfo->seg, (uchar*) info->lastkey, + (uchar*) info->lastkey2, info->last_rkey_length, SEARCH_FIND, not_used)) { error=1; my_errno=HA_ERR_END_OF_FILE; - info->lastpos= HA_OFFSET_ERROR; + info->cur_row.lastpos= HA_OFFSET_ERROR; break; } /* Skip rows that are inserted by other threads since we got a lock */ - if (info->lastpos < info->state->data_file_length) + if (info->cur_row.lastpos < info->state->data_file_length) break; } } @@ -94,9 +97,9 @@ int maria_rnext_same(MARIA_HA *info, byte *buf) } else if (!buf) { - DBUG_RETURN(info->lastpos==HA_OFFSET_ERROR ? my_errno : 0); + DBUG_RETURN(info->cur_row.lastpos == HA_OFFSET_ERROR ? my_errno : 0); } - else if (!(*info->read_record)(info,info->lastpos,buf)) + else if (!(*info->read_record)(info, buf, info->cur_row.lastpos)) { info->update|= HA_STATE_AKTIV; /* Record is read */ DBUG_RETURN(0); diff --git a/storage/maria/ma_rprev.c b/storage/maria/ma_rprev.c index 8dd4498cf8b..ea562359ded 100644 --- a/storage/maria/ma_rprev.c +++ b/storage/maria/ma_rprev.c @@ -33,7 +33,8 @@ int maria_rprev(MARIA_HA *info, byte *buf, int inx) if ((inx = _ma_check_index(info,inx)) < 0) DBUG_RETURN(my_errno); flag=SEARCH_SMALLER; /* Read previous */ - if (info->lastpos == HA_OFFSET_ERROR && info->update & HA_STATE_NEXT_FOUND) + if (info->cur_row.lastpos == HA_OFFSET_ERROR && + info->update & HA_STATE_NEXT_FOUND) flag=0; /* Read last */ if (fast_ma_readinfo(info)) @@ -56,7 +57,7 @@ int maria_rprev(MARIA_HA *info, byte *buf, int inx) { if (!error) { - while (info->lastpos >= info->state->data_file_length) + while (info->cur_row.lastpos >= info->state->data_file_length) { /* Skip rows that are inserted by other threads since we got a lock */ if ((error= _ma_search_next(info,share->keyinfo+inx,info->lastkey, @@ -77,9 +78,9 @@ int maria_rprev(MARIA_HA *info, byte *buf, int inx) } else if (!buf) { - DBUG_RETURN(info->lastpos==HA_OFFSET_ERROR ? my_errno : 0); + DBUG_RETURN(info->cur_row.lastpos == HA_OFFSET_ERROR ? my_errno : 0); } - else if (!(*info->read_record)(info,info->lastpos,buf)) + else if (!(*info->read_record)(info, buf, info->cur_row.lastpos)) { info->update|= HA_STATE_AKTIV; /* Record is read */ DBUG_RETURN(0); diff --git a/storage/maria/ma_rrnd.c b/storage/maria/ma_rrnd.c index 2f01c0e92c5..33940d5f23f 100644 --- a/storage/maria/ma_rrnd.c +++ b/storage/maria/ma_rrnd.c @@ -21,40 +21,34 @@ #include "maria_def.h" /* - Read a row based on position. - If filepos= HA_OFFSET_ERROR then read next row - Return values - Returns one of following values: - 0 = Ok. - HA_ERR_RECORD_DELETED = Record is deleted. - HA_ERR_END_OF_FILE = EOF. + Read a row based on position. + + RETURN + 0 Ok. + HA_ERR_RECORD_DELETED Record is deleted. + HA_ERR_END_OF_FILE EOF. */ -int maria_rrnd(MARIA_HA *info, byte *buf, register my_off_t filepos) +int maria_rrnd(MARIA_HA *info, byte *buf, MARIA_RECORD_POS filepos) { - my_bool skip_deleted_blocks; DBUG_ENTER("maria_rrnd"); - skip_deleted_blocks=0; - + DBUG_ASSERT(filepos != HA_OFFSET_ERROR); +#ifdef NOT_USED if (filepos == HA_OFFSET_ERROR) { skip_deleted_blocks=1; - if (info->lastpos == HA_OFFSET_ERROR) /* First read ? */ - filepos= info->s->pack.header_length; /* Read first record */ + if (info->cur_row.lastpos == HA_OFFSET_ERROR) /* First read ? */ + filepos= info->s->pack.header_length; /* Read first record */ else - filepos= info->nextpos; + filepos= info->cur_row.nextpos; } +#endif - if (info->once_flags & RRND_PRESERVE_LASTINX) - info->once_flags&= ~RRND_PRESERVE_LASTINX; - else - info->lastinx= -1; /* Can't forward or backward */ /* Init all but update-flag */ info->update&= (HA_STATE_CHANGED | HA_STATE_ROW_CHANGED); - if (info->opt_flag & WRITE_CACHE_USED && flush_io_cache(&info->rec_cache)) DBUG_RETURN(my_errno); - DBUG_RETURN ((*info->s->read_rnd)(info,buf,filepos,skip_deleted_blocks)); + DBUG_RETURN((*info->s->read_record)(info, buf, filepos)); } diff --git a/storage/maria/ma_rsame.c b/storage/maria/ma_rsame.c index 913ae3b4370..7556c1e7332 100644 --- a/storage/maria/ma_rsame.c +++ b/storage/maria/ma_rsame.c @@ -16,14 +16,17 @@ #include "maria_def.h" - /* - ** Find current row with read on position or read on key - ** If inx >= 0 find record using key - ** Return values: - ** 0 = Ok. - ** HA_ERR_KEY_NOT_FOUND = Row is deleted - ** HA_ERR_END_OF_FILE = End of file - */ +/* + Find current row with read on position or read on key + + NOTES + If inx >= 0 find record using key + + RETURN + 0 Ok + HA_ERR_KEY_NOT_FOUND Row is deleted + HA_ERR_END_OF_FILE End of file +*/ int maria_rsame(MARIA_HA *info, byte *record, int inx) @@ -34,7 +37,8 @@ int maria_rsame(MARIA_HA *info, byte *record, int inx) { DBUG_RETURN(my_errno=HA_ERR_WRONG_INDEX); } - if (info->lastpos == HA_OFFSET_ERROR || info->update & HA_STATE_DELETED) + if (info->cur_row.lastpos == HA_OFFSET_ERROR || + info->update & HA_STATE_DELETED) { DBUG_RETURN(my_errno=HA_ERR_KEY_NOT_FOUND); /* No current record */ } @@ -48,7 +52,7 @@ int maria_rsame(MARIA_HA *info, byte *record, int inx) { info->lastinx=inx; info->lastkey_length= _ma_make_key(info,(uint) inx,info->lastkey,record, - info->lastpos); + info->cur_row.lastpos); if (info->s->concurrent_insert) rw_rdlock(&info->s->key_root_lock[inx]); VOID(_ma_search(info,info->s->keyinfo+inx,info->lastkey, USE_WHOLE_KEY, @@ -58,7 +62,7 @@ int maria_rsame(MARIA_HA *info, byte *record, int inx) rw_unlock(&info->s->key_root_lock[inx]); } - if (!(*info->read_record)(info,info->lastpos,record)) + if (!(*info->read_record)(info, record, info->cur_row.lastpos)) DBUG_RETURN(0); if (my_errno == HA_ERR_RECORD_DELETED) my_errno=HA_ERR_KEY_NOT_FOUND; diff --git a/storage/maria/ma_rsamepos.c b/storage/maria/ma_rsamepos.c index 09861c03c32..859f0da9b51 100644 --- a/storage/maria/ma_rsamepos.c +++ b/storage/maria/ma_rsamepos.c @@ -28,29 +28,31 @@ ** HA_ERR_END_OF_FILE = End of file */ -int maria_rsame_with_pos(MARIA_HA *info, byte *record, int inx, my_off_t filepos) +int maria_rsame_with_pos(MARIA_HA *info, byte *record, int inx, + MARIA_RECORD_POS filepos) { DBUG_ENTER("maria_rsame_with_pos"); DBUG_PRINT("enter",("index: %d filepos: %ld", inx, (long) filepos)); - if (inx < -1 || (inx >= 0 && !maria_is_key_active(info->s->state.key_map, inx))) + if (inx < -1 || + (inx >= 0 && !maria_is_key_active(info->s->state.key_map, inx))) { DBUG_RETURN(my_errno=HA_ERR_WRONG_INDEX); } info->update&= (HA_STATE_CHANGED | HA_STATE_ROW_CHANGED); - if ((*info->s->read_rnd)(info,record,filepos,0)) + if ((*info->s->read_record)(info, record, filepos)) { if (my_errno == HA_ERR_RECORD_DELETED) my_errno=HA_ERR_KEY_NOT_FOUND; DBUG_RETURN(my_errno); } - info->lastpos=filepos; - info->lastinx=inx; + info->cur_row.lastpos= filepos; + info->lastinx= inx; if (inx >= 0) { info->lastkey_length= _ma_make_key(info,(uint) inx,info->lastkey,record, - info->lastpos); + info->cur_row.lastpos); info->update|=HA_STATE_KEY_CHANGED; /* Don't use indexposition */ } DBUG_RETURN(0); diff --git a/storage/maria/ma_rt_index.c b/storage/maria/ma_rt_index.c index 83ced5b8167..8e8ec6c991b 100644 --- a/storage/maria/ma_rt_index.c +++ b/storage/maria/ma_rt_index.c @@ -53,18 +53,17 @@ typedef struct st_page_list 1 Not found */ -static int maria_rtree_find_req(MARIA_HA *info, MARIA_KEYDEF *keyinfo, uint search_flag, - uint nod_cmp_flag, my_off_t page, int level) +static int maria_rtree_find_req(MARIA_HA *info, MARIA_KEYDEF *keyinfo, + uint search_flag, + uint nod_cmp_flag, my_off_t page, int level) { - uchar *k; - uchar *last; uint nod_flag; int res; - uchar *page_buf; + byte *page_buf, *k, *last; int k_len; uint *saved_key = (uint*) (info->maria_rtree_recursion_state) + level; - if (!(page_buf = (uchar*)my_alloca((uint)keyinfo->block_length))) + if (!(page_buf = (byte*) my_alloca((uint)keyinfo->block_length))) { my_errno = HA_ERR_OUT_OF_MEM; return -1; @@ -77,24 +76,27 @@ static int maria_rtree_find_req(MARIA_HA *info, MARIA_KEYDEF *keyinfo, uint sear if(info->maria_rtree_recursion_depth >= level) { - k = page_buf + *saved_key; + k= page_buf + *saved_key; } else { k = rt_PAGE_FIRST_KEY(page_buf, nod_flag); } - last = rt_PAGE_END(page_buf); + last= rt_PAGE_END(page_buf); for (; k < last; k = rt_PAGE_NEXT_KEY(k, k_len, nod_flag)) { if (nod_flag) { /* this is an internal node in the tree */ - if (!(res = maria_rtree_key_cmp(keyinfo->seg, info->first_mbr_key, k, - info->last_rkey_length, nod_cmp_flag))) + if (!(res = maria_rtree_key_cmp(keyinfo->seg, + info->first_mbr_key, k, + info->last_rkey_length, nod_cmp_flag))) { - switch ((res = maria_rtree_find_req(info, keyinfo, search_flag, nod_cmp_flag, - _ma_kpos(nod_flag, k), level + 1))) + switch ((res = maria_rtree_find_req(info, keyinfo, search_flag, + nod_cmp_flag, + _ma_kpos(nod_flag, k), + level + 1))) { case 0: /* found - exit from recursion */ *saved_key = k - page_buf; @@ -111,11 +113,11 @@ static int maria_rtree_find_req(MARIA_HA *info, MARIA_KEYDEF *keyinfo, uint sear else { /* this is a leaf */ - if (!maria_rtree_key_cmp(keyinfo->seg, info->first_mbr_key, k, - info->last_rkey_length, search_flag)) + if (!maria_rtree_key_cmp(keyinfo->seg, info->first_mbr_key, + k, info->last_rkey_length, search_flag)) { - uchar *after_key = rt_PAGE_NEXT_KEY(k, k_len, nod_flag); - info->lastpos = _ma_dpos(info, 0, after_key); + byte *after_key = (byte*) rt_PAGE_NEXT_KEY(k, k_len, nod_flag); + info->cur_row.lastpos = _ma_dpos(info, 0, after_key); info->lastkey_length = k_len + info->s->base.rec_reflength; memcpy(info->lastkey, k, info->lastkey_length); info->maria_rtree_recursion_depth = level; @@ -126,11 +128,11 @@ static int maria_rtree_find_req(MARIA_HA *info, MARIA_KEYDEF *keyinfo, uint sear info->int_keypos = info->buff; info->int_maxpos = info->buff + (last - after_key); memcpy(info->buff, after_key, last - after_key); - info->buff_used = 0; + info->keybuff_used = 0; } else { - info->buff_used = 1; + info->keybuff_used = 1; } res = 0; @@ -138,7 +140,7 @@ static int maria_rtree_find_req(MARIA_HA *info, MARIA_KEYDEF *keyinfo, uint sear } } } - info->lastpos = HA_OFFSET_ERROR; + info->cur_row.lastpos = HA_OFFSET_ERROR; my_errno = HA_ERR_KEY_NOT_FOUND; res = 1; @@ -148,7 +150,7 @@ ok: err1: my_afree((byte*)page_buf); - info->lastpos = HA_OFFSET_ERROR; + info->cur_row.lastpos = HA_OFFSET_ERROR; return -1; } @@ -170,8 +172,8 @@ err1: 1 Not found */ -int maria_rtree_find_first(MARIA_HA *info, uint keynr, uchar *key, uint key_length, - uint search_flag) +int maria_rtree_find_first(MARIA_HA *info, uint keynr, byte *key, + uint key_length, uint search_flag) { my_off_t root; uint nod_cmp_flag; @@ -191,11 +193,12 @@ int maria_rtree_find_first(MARIA_HA *info, uint keynr, uchar *key, uint key_leng info->last_rkey_length = key_length; info->maria_rtree_recursion_depth = -1; - info->buff_used = 1; + info->keybuff_used = 1; - nod_cmp_flag = ((search_flag & (MBR_EQUAL | MBR_WITHIN)) ? - MBR_WITHIN : MBR_INTERSECT); - return maria_rtree_find_req(info, keyinfo, search_flag, nod_cmp_flag, root, 0); + nod_cmp_flag= ((search_flag & (MBR_EQUAL | MBR_WITHIN)) ? + MBR_WITHIN : MBR_INTERSECT); + return maria_rtree_find_req(info, keyinfo, search_flag, nod_cmp_flag, root, + 0); } @@ -221,27 +224,29 @@ int maria_rtree_find_next(MARIA_HA *info, uint keynr, uint search_flag) MARIA_KEYDEF *keyinfo = info->s->keyinfo + keynr; if (info->update & HA_STATE_DELETED) - return maria_rtree_find_first(info, keynr, info->lastkey, info->lastkey_length, - search_flag); + return maria_rtree_find_first(info, keynr, info->lastkey, + info->lastkey_length, + search_flag); - if (!info->buff_used) + if (!info->keybuff_used) { - uchar *key= info->int_keypos; + byte *key= info->int_keypos; while (key < info->int_maxpos) { - if (!maria_rtree_key_cmp(keyinfo->seg, info->first_mbr_key, key, - info->last_rkey_length, search_flag)) + if (!maria_rtree_key_cmp(keyinfo->seg, + info->first_mbr_key, key, + info->last_rkey_length, search_flag)) { - uchar *after_key = key + keyinfo->keylength; + byte *after_key= key + keyinfo->keylength; - info->lastpos= _ma_dpos(info, 0, after_key); + info->cur_row.lastpos= _ma_dpos(info, 0, after_key); memcpy(info->lastkey, key, info->lastkey_length); if (after_key < info->int_maxpos) info->int_keypos= after_key; else - info->buff_used= 1; + info->keybuff_used= 1; return 0; } key+= keyinfo->keylength; @@ -274,15 +279,12 @@ int maria_rtree_find_next(MARIA_HA *info, uint keynr, uint search_flag) static int maria_rtree_get_req(MARIA_HA *info, MARIA_KEYDEF *keyinfo, uint key_length, my_off_t page, int level) { - uchar *k; - uchar *last; - uint nod_flag; + byte *page_buf, *last, *k; + uint nod_flag, k_len; int res; - uchar *page_buf; - uint k_len; - uint *saved_key = (uint*) (info->maria_rtree_recursion_state) + level; + uint *saved_key= (uint*) (info->maria_rtree_recursion_state) + level; - if (!(page_buf = (uchar*)my_alloca((uint)keyinfo->block_length))) + if (!(page_buf= (byte*) my_alloca((uint)keyinfo->block_length))) return -1; if (!_ma_fetch_keypage(info, keyinfo, page, DFLT_INIT_HITS, page_buf, 0)) goto err1; @@ -312,7 +314,7 @@ static int maria_rtree_get_req(MARIA_HA *info, MARIA_KEYDEF *keyinfo, uint key_l { /* this is an internal node in the tree */ switch ((res = maria_rtree_get_req(info, keyinfo, key_length, - _ma_kpos(nod_flag, k), level + 1))) + _ma_kpos(nod_flag, k), level + 1))) { case 0: /* found - exit from recursion */ *saved_key = k - page_buf; @@ -328,8 +330,8 @@ static int maria_rtree_get_req(MARIA_HA *info, MARIA_KEYDEF *keyinfo, uint key_l else { /* this is a leaf */ - uchar *after_key = rt_PAGE_NEXT_KEY(k, k_len, nod_flag); - info->lastpos = _ma_dpos(info, 0, after_key); + byte *after_key = rt_PAGE_NEXT_KEY(k, k_len, nod_flag); + info->cur_row.lastpos = _ma_dpos(info, 0, after_key); info->lastkey_length = k_len + info->s->base.rec_reflength; memcpy(info->lastkey, k, info->lastkey_length); @@ -338,21 +340,21 @@ static int maria_rtree_get_req(MARIA_HA *info, MARIA_KEYDEF *keyinfo, uint key_l if (after_key < last) { - info->int_keypos = (uchar*)saved_key; + info->int_keypos = (byte*) saved_key; memcpy(info->buff, page_buf, keyinfo->block_length); info->int_maxpos = rt_PAGE_END(info->buff); - info->buff_used = 0; + info->keybuff_used = 0; } else { - info->buff_used = 1; + info->keybuff_used = 1; } res = 0; goto ok; } } - info->lastpos = HA_OFFSET_ERROR; + info->cur_row.lastpos = HA_OFFSET_ERROR; my_errno = HA_ERR_KEY_NOT_FOUND; res = 1; @@ -362,7 +364,7 @@ ok: err1: my_afree((byte*)page_buf); - info->lastpos = HA_OFFSET_ERROR; + info->cur_row.lastpos = HA_OFFSET_ERROR; return -1; } @@ -388,7 +390,7 @@ int maria_rtree_get_first(MARIA_HA *info, uint keynr, uint key_length) } info->maria_rtree_recursion_depth = -1; - info->buff_used = 1; + info->keybuff_used = 1; return maria_rtree_get_req(info, &keyinfo[keynr], key_length, root, 0); } @@ -408,23 +410,23 @@ int maria_rtree_get_next(MARIA_HA *info, uint keynr, uint key_length) my_off_t root; MARIA_KEYDEF *keyinfo = info->s->keyinfo + keynr; - if (!info->buff_used) + if (!info->keybuff_used) { uint k_len = keyinfo->keylength - info->s->base.rec_reflength; /* rt_PAGE_NEXT_KEY(info->int_keypos) */ - uchar *key = info->buff + *(int*)info->int_keypos + k_len + + byte *key = info->buff + *(int*)info->int_keypos + k_len + info->s->base.rec_reflength; /* rt_PAGE_NEXT_KEY(key) */ - uchar *after_key = key + k_len + info->s->base.rec_reflength; + byte *after_key = key + k_len + info->s->base.rec_reflength; - info->lastpos = _ma_dpos(info, 0, after_key); + info->cur_row.lastpos = _ma_dpos(info, 0, after_key); info->lastkey_length = k_len + info->s->base.rec_reflength; memcpy(info->lastkey, key, k_len + info->s->base.rec_reflength); *(int*)info->int_keypos = key - info->buff; if (after_key >= info->int_maxpos) { - info->buff_used = 1; + info->keybuff_used = 1; } return 0; @@ -447,8 +449,10 @@ int maria_rtree_get_next(MARIA_HA *info, uint keynr, uint key_length) */ #ifdef PICK_BY_PERIMETER -static uchar *maria_rtree_pick_key(MARIA_HA *info, MARIA_KEYDEF *keyinfo, uchar *key, - uint key_length, uchar *page_buf, uint nod_flag) +static uchar *maria_rtree_pick_key(MARIA_HA *info, MARIA_KEYDEF *keyinfo, + uchar *key, + uint key_length, byte *page_buf, + uint nod_flag) { double increase; double best_incr = DBL_MAX; @@ -480,16 +484,18 @@ static uchar *maria_rtree_pick_key(MARIA_HA *info, MARIA_KEYDEF *keyinfo, uchar #endif /*PICK_BY_PERIMETER*/ #ifdef PICK_BY_AREA -static uchar *maria_rtree_pick_key(MARIA_HA *info, MARIA_KEYDEF *keyinfo, uchar *key, - uint key_length, uchar *page_buf, uint nod_flag) +static byte *maria_rtree_pick_key(MARIA_HA *info, MARIA_KEYDEF *keyinfo, + byte *key, + uint key_length, byte *page_buf, + uint nod_flag) { double increase; double best_incr = DBL_MAX; double area; double best_area; - uchar *best_key; - uchar *k = rt_PAGE_FIRST_KEY(page_buf, nod_flag); - uchar *last = rt_PAGE_END(page_buf); + byte *best_key; + byte *k = rt_PAGE_FIRST_KEY(page_buf, nod_flag); + byte *last = rt_PAGE_END(page_buf); LINT_INIT(best_area); LINT_INIT(best_key); @@ -498,7 +504,7 @@ static uchar *maria_rtree_pick_key(MARIA_HA *info, MARIA_KEYDEF *keyinfo, uchar { /* The following is safe as -1.0 is an exact number */ if ((increase = maria_rtree_area_increase(keyinfo->seg, k, key, key_length, - &area)) == -1.0) + &area)) == -1.0) return NULL; /* The following should be safe, even if we compare doubles */ if (increase < best_incr) @@ -532,16 +538,17 @@ static uchar *maria_rtree_pick_key(MARIA_HA *info, MARIA_KEYDEF *keyinfo, uchar 1 Child was split */ -static int maria_rtree_insert_req(MARIA_HA *info, MARIA_KEYDEF *keyinfo, uchar *key, - uint key_length, my_off_t page, my_off_t *new_page, - int ins_level, int level) +static int maria_rtree_insert_req(MARIA_HA *info, MARIA_KEYDEF *keyinfo, + byte *key, + uint key_length, my_off_t page, + my_off_t *new_page, + int ins_level, int level) { - uchar *k; uint nod_flag; - uchar *page_buf; int res; + byte *page_buf, *k; - if (!(page_buf = (uchar*)my_alloca((uint)keyinfo->block_length + + if (!(page_buf= (byte*) my_alloca((uint)keyinfo->block_length + HA_MAX_KEY_BUFF))) { my_errno = HA_ERR_OUT_OF_MEM; @@ -555,10 +562,11 @@ static int maria_rtree_insert_req(MARIA_HA *info, MARIA_KEYDEF *keyinfo, uchar * (ins_level > -1 && ins_level > level)) /* branch: go down to ins_level */ { if ((k = maria_rtree_pick_key(info, keyinfo, key, key_length, page_buf, - nod_flag)) == NULL) + nod_flag)) == NULL) goto err1; switch ((res = maria_rtree_insert_req(info, keyinfo, key, key_length, - _ma_kpos(nod_flag, k), new_page, ins_level, level + 1))) + _ma_kpos(nod_flag, k), new_page, + ins_level, level + 1))) { case 0: /* child was not split */ { @@ -569,14 +577,15 @@ static int maria_rtree_insert_req(MARIA_HA *info, MARIA_KEYDEF *keyinfo, uchar * } case 1: /* child was split */ { - uchar *new_key = page_buf + keyinfo->block_length + nod_flag; + byte *new_key = page_buf + keyinfo->block_length + nod_flag; /* set proper MBR for key */ if (maria_rtree_set_key_mbr(info, keyinfo, k, key_length, - _ma_kpos(nod_flag, k))) + _ma_kpos(nod_flag, k))) goto err1; /* add new key for new page */ _ma_kpointer(info, new_key - nod_flag, *new_page); - if (maria_rtree_set_key_mbr(info, keyinfo, new_key, key_length, *new_page)) + if (maria_rtree_set_key_mbr(info, keyinfo, new_key, key_length, + *new_page)) goto err1; res = maria_rtree_add_key(info, keyinfo, new_key, key_length, page_buf, new_page); @@ -593,18 +602,18 @@ static int maria_rtree_insert_req(MARIA_HA *info, MARIA_KEYDEF *keyinfo, uchar * } else { - res = maria_rtree_add_key(info, keyinfo, key, key_length, page_buf, new_page); + res = maria_rtree_add_key(info, keyinfo, key, key_length, page_buf, + new_page); if (_ma_write_keypage(info, keyinfo, page, DFLT_INIT_HITS, page_buf)) goto err1; - goto ok; } ok: - my_afree((byte*)page_buf); + my_afree(page_buf); return res; err1: - my_afree((byte*)page_buf); + my_afree(page_buf); return -1; } @@ -618,8 +627,8 @@ err1: 1 Root was split */ -static int maria_rtree_insert_level(MARIA_HA *info, uint keynr, uchar *key, - uint key_length, int ins_level) +static int maria_rtree_insert_level(MARIA_HA *info, uint keynr, byte *key, + uint key_length, int ins_level) { my_off_t old_root; MARIA_KEYDEF *keyinfo = info->s->keyinfo + keynr; @@ -632,7 +641,7 @@ static int maria_rtree_insert_level(MARIA_HA *info, uint keynr, uchar *key, if ((old_root = _ma_new(info, keyinfo, DFLT_INIT_HITS)) == HA_OFFSET_ERROR) return -1; - info->buff_used = 1; + info->keybuff_used = 1; maria_putint(info->buff, 2, 0); res = maria_rtree_add_key(info, keyinfo, key, key_length, info->buff, NULL); if (_ma_write_keypage(info, keyinfo, old_root, DFLT_INIT_HITS, info->buff)) @@ -650,13 +659,12 @@ static int maria_rtree_insert_level(MARIA_HA *info, uint keynr, uchar *key, } case 1: /* root was split, grow a new root */ { - uchar *new_root_buf; + byte *new_root_buf, *new_key; my_off_t new_root; - uchar *new_key; uint nod_flag = info->s->base.key_reflength; - if (!(new_root_buf = (uchar*)my_alloca((uint)keyinfo->block_length + - HA_MAX_KEY_BUFF))) + if (!(new_root_buf= (byte*) my_alloca((uint)keyinfo->block_length + + HA_MAX_KEY_BUFF))) { my_errno = HA_ERR_OUT_OF_MEM; return -1; @@ -670,15 +678,19 @@ static int maria_rtree_insert_level(MARIA_HA *info, uint keynr, uchar *key, new_key = new_root_buf + keyinfo->block_length + nod_flag; _ma_kpointer(info, new_key - nod_flag, old_root); - if (maria_rtree_set_key_mbr(info, keyinfo, new_key, key_length, old_root)) + if (maria_rtree_set_key_mbr(info, keyinfo, new_key, key_length, + old_root)) goto err1; - if (maria_rtree_add_key(info, keyinfo, new_key, key_length, new_root_buf, NULL) + if (maria_rtree_add_key(info, keyinfo, new_key, key_length, new_root_buf, + NULL) == -1) goto err1; _ma_kpointer(info, new_key - nod_flag, new_page); - if (maria_rtree_set_key_mbr(info, keyinfo, new_key, key_length, new_page)) + if (maria_rtree_set_key_mbr(info, keyinfo, new_key, key_length, + new_page)) goto err1; - if (maria_rtree_add_key(info, keyinfo, new_key, key_length, new_root_buf, NULL) + if (maria_rtree_add_key(info, keyinfo, new_key, key_length, new_root_buf, + NULL) == -1) goto err1; if (_ma_write_keypage(info, keyinfo, new_root, @@ -710,10 +722,11 @@ err1: 0 OK */ -int maria_rtree_insert(MARIA_HA *info, uint keynr, uchar *key, uint key_length) +int maria_rtree_insert(MARIA_HA *info, uint keynr, byte *key, uint key_length) { return (!key_length || - (maria_rtree_insert_level(info, keynr, key, key_length, -1) == -1)) ? -1 : 0; + (maria_rtree_insert_level(info, keynr, key, key_length, -1) == -1)) ? + -1 : 0; } @@ -756,18 +769,18 @@ err1: 2 Empty leaf */ -static int maria_rtree_delete_req(MARIA_HA *info, MARIA_KEYDEF *keyinfo, uchar *key, - uint key_length, my_off_t page, uint *page_size, - stPageList *ReinsertList, int level) +static int maria_rtree_delete_req(MARIA_HA *info, MARIA_KEYDEF *keyinfo, + byte *key, + uint key_length, my_off_t page, + uint *page_size, + stPageList *ReinsertList, int level) { - uchar *k; - uchar *last; ulong i; uint nod_flag; - uchar *page_buf; int res; + byte *page_buf, *last, *k; - if (!(page_buf = (uchar*)my_alloca((uint)keyinfo->block_length))) + if (!(page_buf = (byte*) my_alloca((uint)keyinfo->block_length))) { my_errno = HA_ERR_OUT_OF_MEM; return -1; @@ -779,7 +792,7 @@ static int maria_rtree_delete_req(MARIA_HA *info, MARIA_KEYDEF *keyinfo, uchar * k = rt_PAGE_FIRST_KEY(page_buf, nod_flag); last = rt_PAGE_END(page_buf); - for (i = 0; k < last; k = rt_PAGE_NEXT_KEY(k, key_length, nod_flag), ++i) + for (i = 0; k < last; k = rt_PAGE_NEXT_KEY(k, key_length, nod_flag), i++) { if (nod_flag) { @@ -792,7 +805,8 @@ static int maria_rtree_delete_req(MARIA_HA *info, MARIA_KEYDEF *keyinfo, uchar * case 0: /* deleted */ { /* test page filling */ - if (*page_size + key_length >= rt_PAGE_MIN_SIZE(keyinfo->block_length)) + if (*page_size + key_length >= + rt_PAGE_MIN_SIZE(keyinfo->block_length)) { /* OK */ if (maria_rtree_set_key_mbr(info, keyinfo, k, key_length, @@ -805,7 +819,8 @@ static int maria_rtree_delete_req(MARIA_HA *info, MARIA_KEYDEF *keyinfo, uchar * else { /* too small: delete key & add it descendant to reinsert list */ - if (maria_rtree_fill_reinsert_list(ReinsertList, _ma_kpos(nod_flag, k), + if (maria_rtree_fill_reinsert_list(ReinsertList, + _ma_kpos(nod_flag, k), level + 1)) goto err1; maria_rtree_delete_key(info, page_buf, k, key_length, nod_flag); @@ -883,7 +898,7 @@ err1: 0 Deleted */ -int maria_rtree_delete(MARIA_HA *info, uint keynr, uchar *key, uint key_length) +int maria_rtree_delete(MARIA_HA *info, uint keynr, byte *key, uint key_length) { uint page_size; stPageList ReinsertList; @@ -914,12 +929,10 @@ int maria_rtree_delete(MARIA_HA *info, uint keynr, uchar *key, uint key_length) ulong i; for (i = 0; i < ReinsertList.n_pages; ++i) { - uchar *page_buf; uint nod_flag; - uchar *k; - uchar *last; + byte *page_buf, *k, *last; - if (!(page_buf = (uchar*)my_alloca((uint)keyinfo->block_length))) + if (!(page_buf = (byte*) my_alloca((uint)keyinfo->block_length))) { my_errno = HA_ERR_OUT_OF_MEM; goto err1; @@ -935,11 +948,11 @@ int maria_rtree_delete(MARIA_HA *info, uint keynr, uchar *key, uint key_length) if (maria_rtree_insert_level(info, keynr, k, key_length, ReinsertList.pages[i].level) == -1) { - my_afree((byte*)page_buf); + my_afree(page_buf); goto err1; } } - my_afree((byte*)page_buf); + my_afree(page_buf); if (_ma_dispose(info, keyinfo, ReinsertList.pages[i].offs, DFLT_INIT_HITS)) goto err1; @@ -969,16 +982,14 @@ int maria_rtree_delete(MARIA_HA *info, uint keynr, uchar *key, uint key_length) err1: return -1; } - case 1: /* not found */ + case 1: /* not found */ { my_errno = HA_ERR_KEY_NOT_FOUND; return -1; } default: - case -1: /* error */ - { + case -1: /* error */ return -1; - } } } @@ -990,17 +1001,14 @@ err1: estimated value */ -ha_rows maria_rtree_estimate(MARIA_HA *info, uint keynr, uchar *key, +ha_rows maria_rtree_estimate(MARIA_HA *info, uint keynr, byte *key, uint key_length, uint flag) { MARIA_KEYDEF *keyinfo = info->s->keyinfo + keynr; my_off_t root; uint i = 0; - uchar *k; - uchar *last; - uint nod_flag; - uchar *page_buf; - uint k_len; + uint nod_flag, k_len; + byte *page_buf, *k, *last; double area = 0; ha_rows res = 0; @@ -1009,7 +1017,7 @@ ha_rows maria_rtree_estimate(MARIA_HA *info, uint keynr, uchar *key, if ((root = info->s->state.key_root[keynr]) == HA_OFFSET_ERROR) return HA_POS_ERROR; - if (!(page_buf = (uchar*)my_alloca((uint)keyinfo->block_length))) + if (!(page_buf= (byte*) my_alloca((uint)keyinfo->block_length))) return HA_POS_ERROR; if (!_ma_fetch_keypage(info, keyinfo, root, DFLT_INIT_HITS, page_buf, 0)) goto err1; @@ -1020,7 +1028,7 @@ ha_rows maria_rtree_estimate(MARIA_HA *info, uint keynr, uchar *key, k = rt_PAGE_FIRST_KEY(page_buf, nod_flag); last = rt_PAGE_END(page_buf); - for (; k < last; k = rt_PAGE_NEXT_KEY(k, k_len, nod_flag), ++i) + for (; k < last; k = rt_PAGE_NEXT_KEY(k, k_len, nod_flag), i++) { if (nod_flag) { @@ -1035,7 +1043,8 @@ ha_rows maria_rtree_estimate(MARIA_HA *info, uint keynr, uchar *key, } else if (flag & (MBR_WITHIN | MBR_EQUAL)) { - if (!maria_rtree_key_cmp(keyinfo->seg, key, k, key_length, MBR_WITHIN)) + if (!maria_rtree_key_cmp(keyinfo->seg, key, k, key_length, + MBR_WITHIN)) area += 1; } else @@ -1045,14 +1054,15 @@ ha_rows maria_rtree_estimate(MARIA_HA *info, uint keynr, uchar *key, { if (flag & (MBR_CONTAIN | MBR_INTERSECT)) { - area += maria_rtree_overlapping_area(keyinfo->seg, key, k, key_length) / - k_area; + area+= maria_rtree_overlapping_area(keyinfo->seg, key, k, + key_length) / k_area; } else if (flag & (MBR_WITHIN | MBR_EQUAL)) { - if (!maria_rtree_key_cmp(keyinfo->seg, key, k, key_length, MBR_WITHIN)) - area += maria_rtree_rect_volume(keyinfo->seg, key, key_length) / - k_area; + if (!maria_rtree_key_cmp(keyinfo->seg, key, k, key_length, + MBR_WITHIN)) + area+= (maria_rtree_rect_volume(keyinfo->seg, key, key_length) / + k_area); } else goto err1; @@ -1076,7 +1086,7 @@ ha_rows maria_rtree_estimate(MARIA_HA *info, uint keynr, uchar *key, return res; err1: - my_afree((byte*)page_buf); + my_afree(page_buf); return HA_POS_ERROR; } diff --git a/storage/maria/ma_rt_index.h b/storage/maria/ma_rt_index.h index ff431d81372..76b6c6e230c 100644 --- a/storage/maria/ma_rt_index.h +++ b/storage/maria/ma_rt_index.h @@ -27,21 +27,22 @@ #define rt_PAGE_MIN_SIZE(block_length) ((uint)(block_length) / 3) -int maria_rtree_insert(MARIA_HA *info, uint keynr, uchar *key, uint key_length); -int maria_rtree_delete(MARIA_HA *info, uint keynr, uchar *key, uint key_length); +int maria_rtree_insert(MARIA_HA *info, uint keynr, byte *key, uint key_length); +int maria_rtree_delete(MARIA_HA *info, uint keynr, byte *key, uint key_length); -int maria_rtree_find_first(MARIA_HA *info, uint keynr, uchar *key, uint key_length, - uint search_flag); +int maria_rtree_find_first(MARIA_HA *info, uint keynr, byte *key, + uint key_length, uint search_flag); int maria_rtree_find_next(MARIA_HA *info, uint keynr, uint search_flag); int maria_rtree_get_first(MARIA_HA *info, uint keynr, uint key_length); int maria_rtree_get_next(MARIA_HA *info, uint keynr, uint key_length); -ha_rows maria_rtree_estimate(MARIA_HA *info, uint keynr, uchar *key, - uint key_length, uint flag); +ha_rows maria_rtree_estimate(MARIA_HA *info, uint keynr, byte *key, + uint key_length, uint flag); -int maria_rtree_split_page(MARIA_HA *info, MARIA_KEYDEF *keyinfo, uchar *page, - uchar *key, uint key_length, my_off_t *new_page_offs); +int maria_rtree_split_page(MARIA_HA *info, MARIA_KEYDEF *keyinfo, byte *page, + byte *key, uint key_length, + my_off_t *new_page_offs); #endif /*HAVE_RTREE_KEYS*/ #endif /* _rt_index_h */ diff --git a/storage/maria/ma_rt_key.c b/storage/maria/ma_rt_key.c index 2732fefffbe..1453195d263 100644 --- a/storage/maria/ma_rt_key.c +++ b/storage/maria/ma_rt_key.c @@ -30,8 +30,8 @@ 1 Split */ -int maria_rtree_add_key(MARIA_HA *info, MARIA_KEYDEF *keyinfo, uchar *key, - uint key_length, uchar *page_buf, my_off_t *new_page) +int maria_rtree_add_key(MARIA_HA *info, MARIA_KEYDEF *keyinfo, byte *key, + uint key_length, byte *page_buf, my_off_t *new_page) { uint page_size = maria_getint(page_buf); uint nod_flag = _ma_test_if_nod(page_buf); @@ -61,14 +61,16 @@ int maria_rtree_add_key(MARIA_HA *info, MARIA_KEYDEF *keyinfo, uchar *key, new_page) ? -1 : 1); } + /* Delete key from the page */ -int maria_rtree_delete_key(MARIA_HA *info, uchar *page_buf, uchar *key, + +int maria_rtree_delete_key(MARIA_HA *info, byte *page_buf, byte *key, uint key_length, uint nod_flag) { uint16 page_size = maria_getint(page_buf); - uchar *key_start; + byte *key_start; key_start= key - nod_flag; if (!nod_flag) @@ -87,7 +89,7 @@ int maria_rtree_delete_key(MARIA_HA *info, uchar *page_buf, uchar *key, Calculate and store key MBR */ -int maria_rtree_set_key_mbr(MARIA_HA *info, MARIA_KEYDEF *keyinfo, uchar *key, +int maria_rtree_set_key_mbr(MARIA_HA *info, MARIA_KEYDEF *keyinfo, byte *key, uint key_length, my_off_t child_page) { if (!_ma_fetch_keypage(info, keyinfo, child_page, diff --git a/storage/maria/ma_rt_key.h b/storage/maria/ma_rt_key.h index 448024ed8c5..f44251782c1 100644 --- a/storage/maria/ma_rt_key.h +++ b/storage/maria/ma_rt_key.h @@ -22,12 +22,12 @@ #ifdef HAVE_RTREE_KEYS -int maria_rtree_add_key(MARIA_HA *info, MARIA_KEYDEF *keyinfo, uchar *key, - uint key_length, uchar *page_buf, my_off_t *new_page); -int maria_rtree_delete_key(MARIA_HA *info, uchar *page, uchar *key, - uint key_length, uint nod_flag); -int maria_rtree_set_key_mbr(MARIA_HA *info, MARIA_KEYDEF *keyinfo, uchar *key, - uint key_length, my_off_t child_page); +int maria_rtree_add_key(MARIA_HA *info, MARIA_KEYDEF *keyinfo, byte *key, + uint key_length, byte *page_buf, my_off_t *new_page); +int maria_rtree_delete_key(MARIA_HA *info, byte *page, byte *key, + uint key_length, uint nod_flag); +int maria_rtree_set_key_mbr(MARIA_HA *info, MARIA_KEYDEF *keyinfo, byte *key, + uint key_length, my_off_t child_page); #endif /*HAVE_RTREE_KEYS*/ #endif /* _rt_key_h */ diff --git a/storage/maria/ma_rt_mbr.c b/storage/maria/ma_rt_mbr.c index 67b1d59f505..851618a4300 100644 --- a/storage/maria/ma_rt_mbr.c +++ b/storage/maria/ma_rt_mbr.c @@ -93,8 +93,9 @@ MBR_DATA(a,b) Data reference is the same Returns 0 on success. */ -int maria_rtree_key_cmp(HA_KEYSEG *keyseg, uchar *b, uchar *a, uint key_length, - uint nextflag) + +int maria_rtree_key_cmp(HA_KEYSEG *keyseg, byte *b, byte *a, uint key_length, + uint nextflag) { for (; (int) key_length > 0; keyseg += 2 ) { @@ -153,7 +154,7 @@ int maria_rtree_key_cmp(HA_KEYSEG *keyseg, uchar *b, uchar *a, uint key_length, end: if (nextflag & MBR_DATA) { - uchar *end = a + keyseg->length; + byte *end = a + keyseg->length; do { if (*a++ != *b++) @@ -182,7 +183,7 @@ end: /* Calculates rectangle volume */ -double maria_rtree_rect_volume(HA_KEYSEG *keyseg, uchar *a, uint key_length) +double maria_rtree_rect_volume(HA_KEYSEG *keyseg, byte *a, uint key_length) { double res = 1; for (; (int)key_length > 0; keyseg += 2) @@ -263,7 +264,7 @@ double maria_rtree_rect_volume(HA_KEYSEG *keyseg, uchar *a, uint key_length) Creates an MBR as an array of doubles. */ -int maria_rtree_d_mbr(HA_KEYSEG *keyseg, uchar *a, uint key_length, double *res) +int maria_rtree_d_mbr(HA_KEYSEG *keyseg, byte *a, uint key_length, double *res) { for (; (int)key_length > 0; keyseg += 2) { @@ -352,7 +353,7 @@ int maria_rtree_d_mbr(HA_KEYSEG *keyseg, uchar *a, uint key_length, double *res) Result is written to c */ -int maria_rtree_combine_rect(HA_KEYSEG *keyseg, uchar* a, uchar* b, uchar* c, +int maria_rtree_combine_rect(HA_KEYSEG *keyseg, byte* a, byte* b, byte* c, uint key_length) { for ( ; (int) key_length > 0 ; keyseg += 2) @@ -443,7 +444,7 @@ int maria_rtree_combine_rect(HA_KEYSEG *keyseg, uchar* a, uchar* b, uchar* c, /* Calculates overlapping area of two MBRs a & b */ -double maria_rtree_overlapping_area(HA_KEYSEG *keyseg, uchar* a, uchar* b, +double maria_rtree_overlapping_area(HA_KEYSEG *keyseg, byte* a, byte* b, uint key_length) { double res = 1; @@ -525,10 +526,11 @@ double maria_rtree_overlapping_area(HA_KEYSEG *keyseg, uchar* a, uchar* b, } /* -Calculates MBR_AREA(a+b) - MBR_AREA(a) + Calculates MBR_AREA(a+b) - MBR_AREA(a) */ -double maria_rtree_area_increase(HA_KEYSEG *keyseg, uchar* a, uchar* b, - uint key_length, double *ab_area) + +double maria_rtree_area_increase(HA_KEYSEG *keyseg, byte *a, byte *b, + uint key_length, double *ab_area) { double a_area= 1.0; double loc_ab_area= 1.0; @@ -620,7 +622,7 @@ safe_end: /* Calculates MBR_PERIMETER(a+b) - MBR_PERIMETER(a) */ -double maria_rtree_perimeter_increase(HA_KEYSEG *keyseg, uchar* a, uchar* b, +double maria_rtree_perimeter_increase(HA_KEYSEG *keyseg, byte* a, byte* b, uint key_length, double *ab_perim) { double a_perim = 0.0; @@ -731,16 +733,16 @@ double maria_rtree_perimeter_increase(HA_KEYSEG *keyseg, uchar* a, uchar* b, } /* -Calculates key page total MBR = MBR(key1) + MBR(key2) + ... + Calculates key page total MBR = MBR(key1) + MBR(key2) + ... */ -int maria_rtree_page_mbr(MARIA_HA *info, HA_KEYSEG *keyseg, uchar *page_buf, - uchar *c, uint key_length) +int maria_rtree_page_mbr(MARIA_HA *info, HA_KEYSEG *keyseg, byte *page_buf, + byte *c, uint key_length) { uint inc = 0; uint k_len = key_length; uint nod_flag = _ma_test_if_nod(page_buf); - uchar *k; - uchar *last = rt_PAGE_END(page_buf); + byte *k; + byte *last = rt_PAGE_END(page_buf); for (; (int)key_length > 0; keyseg += 2) { diff --git a/storage/maria/ma_rt_mbr.h b/storage/maria/ma_rt_mbr.h index 81e2a6851d4..3282ee0d7a3 100644 --- a/storage/maria/ma_rt_mbr.h +++ b/storage/maria/ma_rt_mbr.h @@ -20,19 +20,20 @@ #ifdef HAVE_RTREE_KEYS -int maria_rtree_key_cmp(HA_KEYSEG *keyseg, uchar *a, uchar *b, uint key_length, - uint nextflag); -int maria_rtree_combine_rect(HA_KEYSEG *keyseg,uchar *, uchar *, uchar*, - uint key_length); -double maria_rtree_rect_volume(HA_KEYSEG *keyseg, uchar*, uint key_length); -int maria_rtree_d_mbr(HA_KEYSEG *keyseg, uchar *a, uint key_length, double *res); -double maria_rtree_overlapping_area(HA_KEYSEG *keyseg, uchar *a, uchar *b, - uint key_length); -double maria_rtree_area_increase(HA_KEYSEG *keyseg, uchar *a, uchar *b, - uint key_length, double *ab_area); -double maria_rtree_perimeter_increase(HA_KEYSEG *keyseg, uchar* a, uchar* b, - uint key_length, double *ab_perim); -int maria_rtree_page_mbr(MARIA_HA *info, HA_KEYSEG *keyseg, uchar *page_buf, - uchar* c, uint key_length); +int maria_rtree_key_cmp(HA_KEYSEG *keyseg, byte *a, byte *b, uint key_length, + uint nextflag); +int maria_rtree_combine_rect(HA_KEYSEG *keyseg,byte *, byte *, byte*, + uint key_length); +double maria_rtree_rect_volume(HA_KEYSEG *keyseg, byte*, uint key_length); +int maria_rtree_d_mbr(HA_KEYSEG *keyseg, byte *a, uint key_length, + double *res); +double maria_rtree_overlapping_area(HA_KEYSEG *keyseg, byte *a, byte *b, + uint key_length); +double maria_rtree_area_increase(HA_KEYSEG *keyseg, byte *a, byte *b, + uint key_length, double *ab_area); +double maria_rtree_perimeter_increase(HA_KEYSEG *keyseg, byte* a, byte* b, + uint key_length, double *ab_perim); +int maria_rtree_page_mbr(MARIA_HA *info, HA_KEYSEG *keyseg, byte *page_buf, + byte* c, uint key_length); #endif /*HAVE_RTREE_KEYS*/ #endif /* _rt_mbr_h */ diff --git a/storage/maria/ma_rt_split.c b/storage/maria/ma_rt_split.c index 034799efd89..00c8d18f5e5 100644 --- a/storage/maria/ma_rt_split.c +++ b/storage/maria/ma_rt_split.c @@ -27,7 +27,7 @@ typedef struct { double square; int n_node; - uchar *key; + byte *key; double *coords; } SplitStruct; @@ -243,8 +243,9 @@ static int split_maria_rtree_node(SplitStruct *node, int n_entries, return 0; } -int maria_rtree_split_page(MARIA_HA *info, MARIA_KEYDEF *keyinfo, uchar *page, uchar *key, - uint key_length, my_off_t *new_page_offs) +int maria_rtree_split_page(MARIA_HA *info, MARIA_KEYDEF *keyinfo, + byte *page, byte *key, + uint key_length, my_off_t *new_page_offs) { int n1, n2; /* Number of items in groups */ @@ -255,8 +256,8 @@ int maria_rtree_split_page(MARIA_HA *info, MARIA_KEYDEF *keyinfo, uchar *page, u double *next_coord; double *old_coord; int n_dim; - uchar *source_cur, *cur1, *cur2; - uchar *new_page; + byte *source_cur, *cur1, *cur2; + byte *new_page; int err_code= 0; uint nod_flag= _ma_test_if_nod(page); uint full_length= key_length + (nod_flag ? nod_flag : @@ -300,7 +301,7 @@ int maria_rtree_split_page(MARIA_HA *info, MARIA_KEYDEF *keyinfo, uchar *page, u goto split_err; } - if (!(new_page = (uchar*)my_alloca((uint)keyinfo->block_length))) + if (!(new_page = (byte*) my_alloca((uint)keyinfo->block_length))) { err_code= -1; goto split_err; @@ -313,7 +314,7 @@ int maria_rtree_split_page(MARIA_HA *info, MARIA_KEYDEF *keyinfo, uchar *page, u n1= n2 = 0; for (cur = task; cur < stop; ++cur) { - uchar *to; + byte *to; if (cur->n_node == 1) { to = cur1; diff --git a/storage/maria/ma_rt_test.c b/storage/maria/ma_rt_test.c index ca4825c2ce2..04b0c88c222 100644 --- a/storage/maria/ma_rt_test.c +++ b/storage/maria/ma_rt_test.c @@ -153,10 +153,11 @@ static int run_test(const char *filename) create_info.max_rows=10000000; if (maria_create(filename, - 1, /* keys */ - keyinfo, - 1+2*ndims+opt_unique, /* columns */ - recinfo,uniques,&uniquedef,&create_info,create_flag)) + DYNAMIC_RECORD, + 1, /* keys */ + keyinfo, + 1+2*ndims+opt_unique, /* columns */ + recinfo,uniques,&uniquedef,&create_info,create_flag)) goto err; if (!silent) diff --git a/storage/maria/ma_scan.c b/storage/maria/ma_scan.c index c9c988722b7..4538c87e2be 100644 --- a/storage/maria/ma_scan.c +++ b/storage/maria/ma_scan.c @@ -21,26 +21,41 @@ int maria_scan_init(register MARIA_HA *info) { DBUG_ENTER("maria_scan_init"); - info->nextpos=info->s->pack.header_length; /* Read first record */ + + info->cur_row.nextpos= info->s->pack.header_length; /* Read first record */ info->lastinx= -1; /* Can't forward or backward */ if (info->opt_flag & WRITE_CACHE_USED && flush_io_cache(&info->rec_cache)) DBUG_RETURN(my_errno); + + if ((*info->s->scan_init)(info)) + DBUG_RETURN(my_errno); DBUG_RETURN(0); } /* - Read a row based on position. - If filepos= HA_OFFSET_ERROR then read next row - Return values - Returns one of following values: - 0 = Ok. - HA_ERR_END_OF_FILE = EOF. + Read a row based on position. + + SYNOPSIS + maria_scan() + info Maria handler + record Read data here + + RETURN + 0 ok + HA_ERR_END_OF_FILE End of file + # Error code */ -int maria_scan(MARIA_HA *info, byte *buf) +int maria_scan(MARIA_HA *info, byte *record) { DBUG_ENTER("maria_scan"); /* Init all but update-flag */ info->update&= (HA_STATE_CHANGED | HA_STATE_ROW_CHANGED); - DBUG_RETURN ((*info->s->read_rnd)(info,buf,info->nextpos,1)); + DBUG_RETURN((*info->s->scan)(info, record, info->cur_row.nextpos, 1)); +} + + +void maria_scan_end(MARIA_HA *info) +{ + (*info->s->scan_end)(info); } diff --git a/storage/maria/ma_search.c b/storage/maria/ma_search.c index af25be06a09..d8738ae4639 100644 --- a/storage/maria/ma_search.c +++ b/storage/maria/ma_search.c @@ -19,8 +19,9 @@ #include "ma_fulltext.h" #include "m_ctype.h" -static my_bool _ma_get_prev_key(MARIA_HA *info, MARIA_KEYDEF *keyinfo, uchar *page, - uchar *key, uchar *keypos, +static my_bool _ma_get_prev_key(MARIA_HA *info, MARIA_KEYDEF *keyinfo, + byte *page, + byte *key, byte *keypos, uint *return_key_length); /* Check index */ @@ -55,31 +56,32 @@ int _ma_check_index(MARIA_HA *info, int inx) */ int _ma_search(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo, - uchar *key, uint key_len, uint nextflag, register my_off_t pos) + byte *key, uint key_len, uint nextflag, register my_off_t pos) { my_bool last_key; int error,flag; uint nod_flag; - uchar *keypos,*maxpos; - uchar lastkey[HA_MAX_KEY_BUFF],*buff; + byte *keypos,*maxpos; + byte lastkey[HA_MAX_KEY_BUFF],*buff; DBUG_ENTER("_ma_search"); DBUG_PRINT("enter",("pos: %lu nextflag: %u lastpos: %lu", - (ulong) pos, nextflag, (ulong) info->lastpos)); + (ulong) pos, nextflag, (ulong) info->cur_row.lastpos)); DBUG_EXECUTE("key", _ma_print_key(DBUG_FILE,keyinfo->seg,key,key_len);); if (pos == HA_OFFSET_ERROR) { my_errno=HA_ERR_KEY_NOT_FOUND; /* Didn't find key */ - info->lastpos= HA_OFFSET_ERROR; + info->cur_row.lastpos= HA_OFFSET_ERROR; if (!(nextflag & (SEARCH_SMALLER | SEARCH_BIGGER | SEARCH_LAST))) DBUG_RETURN(-1); /* Not found ; return error */ DBUG_RETURN(1); /* Search at upper levels */ } - if (!(buff= _ma_fetch_keypage(info,keyinfo,pos,DFLT_INIT_HITS,info->buff, + if (!(buff= _ma_fetch_keypage(info,keyinfo,pos,DFLT_INIT_HITS, + info->keyread_buff, test(!(nextflag & SEARCH_SAVE_BUFF))))) goto err; - DBUG_DUMP("page",(byte*) buff,maria_getint(buff)); + DBUG_DUMP("page", buff, maria_getint(buff)); flag=(*keyinfo->bin_search)(info,keyinfo,buff,key,key_len,nextflag, &keypos,lastkey, &last_key); @@ -118,9 +120,10 @@ int _ma_search(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo, } if (pos != info->last_keypage) { - uchar *old_buff=buff; - if (!(buff= _ma_fetch_keypage(info,keyinfo,pos,DFLT_INIT_HITS,info->buff, - test(!(nextflag & SEARCH_SAVE_BUFF))))) + byte *old_buff=buff; + if (!(buff= _ma_fetch_keypage(info,keyinfo,pos,DFLT_INIT_HITS, + info->keyread_buff, + test(!(nextflag & SEARCH_SAVE_BUFF))))) goto err; keypos=buff+(keypos-old_buff); maxpos=buff+(maxpos-old_buff); @@ -133,8 +136,8 @@ int _ma_search(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo, &info->lastkey_length)) goto err; if (!(nextflag & SEARCH_SMALLER) && - ha_key_cmp(keyinfo->seg, info->lastkey, key, key_len, SEARCH_FIND, - not_used)) + ha_key_cmp(keyinfo->seg, (uchar*) info->lastkey, (uchar*) key, key_len, + SEARCH_FIND, not_used)) { my_errno=HA_ERR_KEY_NOT_FOUND; /* Didn't find key */ goto err; @@ -147,22 +150,22 @@ int _ma_search(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo, goto err; memcpy(info->lastkey,lastkey,info->lastkey_length); } - info->lastpos= _ma_dpos(info,0,info->lastkey+info->lastkey_length); + info->cur_row.lastpos= _ma_dpos(info,0,info->lastkey+info->lastkey_length); /* Save position for a possible read next / previous */ - info->int_keypos=info->buff+ (keypos-buff); - info->int_maxpos=info->buff+ (maxpos-buff); + info->int_keypos= info->keyread_buff+ (keypos-buff); + info->int_maxpos= info->keyread_buff+ (maxpos-buff); info->int_nod_flag=nod_flag; info->int_keytree_version=keyinfo->version; info->last_search_keypage=info->last_keypage; info->page_changed=0; - info->buff_used= (info->buff != buff); /* If we have to reread buff */ + info->keybuff_used= (info->keyread_buff != buff); /* If we have to reread */ - DBUG_PRINT("exit",("found key at %lu",(ulong) info->lastpos)); + DBUG_PRINT("exit",("found key at %lu",(ulong) info->cur_row.lastpos)); DBUG_RETURN(0); err: DBUG_PRINT("exit",("Error: %d",my_errno)); - info->lastpos= HA_OFFSET_ERROR; + info->cur_row.lastpos= HA_OFFSET_ERROR; info->page_changed=1; DBUG_RETURN (-1); } /* _ma_search */ @@ -173,9 +176,9 @@ err: /* ret_pos point to where find or bigger key starts */ /* ARGSUSED */ -int _ma_bin_search(MARIA_HA *info, register MARIA_KEYDEF *keyinfo, uchar *page, - uchar *key, uint key_len, uint comp_flag, uchar **ret_pos, - uchar *buff __attribute__((unused)), my_bool *last_key) +int _ma_bin_search(MARIA_HA *info, register MARIA_KEYDEF *keyinfo, byte *page, + byte *key, uint key_len, uint comp_flag, byte **ret_pos, + byte *buff __attribute__((unused)), my_bool *last_key) { reg4 int start,mid,end,save_end; int flag; @@ -192,16 +195,16 @@ int _ma_bin_search(MARIA_HA *info, register MARIA_KEYDEF *keyinfo, uchar *page, while (start != end) { mid= (start+end)/2; - if ((flag=ha_key_cmp(keyinfo->seg,page+(uint) mid*totlength,key,key_len, - comp_flag, not_used)) + if ((flag=ha_key_cmp(keyinfo->seg,(uchar*) page+(uint) mid*totlength, + (uchar*) key, key_len, comp_flag, not_used)) >= 0) end=mid; else start=mid+1; } if (mid != start) - flag=ha_key_cmp(keyinfo->seg,page+(uint) start*totlength,key,key_len, - comp_flag, not_used); + flag=ha_key_cmp(keyinfo->seg, (uchar*) page+(uint) start*totlength, + (uchar*) key, key_len, comp_flag, not_used); if (flag < 0) start++; /* point at next, bigger key */ *ret_pos=page+(uint) start*totlength; @@ -237,13 +240,13 @@ int _ma_bin_search(MARIA_HA *info, register MARIA_KEYDEF *keyinfo, uchar *page, < 0 Not found. */ -int _ma_seq_search(MARIA_HA *info, register MARIA_KEYDEF *keyinfo, uchar *page, - uchar *key, uint key_len, uint comp_flag, uchar **ret_pos, - uchar *buff, my_bool *last_key) +int _ma_seq_search(MARIA_HA *info, register MARIA_KEYDEF *keyinfo, byte *page, + byte *key, uint key_len, uint comp_flag, byte **ret_pos, + byte *buff, my_bool *last_key) { int flag; uint nod_flag,length,not_used[2]; - uchar t_buff[HA_MAX_KEY_BUFF],*end; + byte t_buff[HA_MAX_KEY_BUFF],*end; DBUG_ENTER("_ma_seq_search"); LINT_INIT(flag); LINT_INIT(length); @@ -264,8 +267,8 @@ int _ma_seq_search(MARIA_HA *info, register MARIA_KEYDEF *keyinfo, uchar *page, length, (long) page, (long) end)); DBUG_RETURN(MARIA_FOUND_WRONG_KEY); } - if ((flag=ha_key_cmp(keyinfo->seg,t_buff,key,key_len,comp_flag, - not_used)) >= 0) + if ((flag= ha_key_cmp(keyinfo->seg, (uchar*) t_buff,(uchar*) key, + key_len,comp_flag, not_used)) >= 0) break; #ifdef EXTRA_DEBUG DBUG_PRINT("loop",("page: 0x%lx key: '%s' flag: %d", (long) page, t_buff, @@ -282,9 +285,9 @@ int _ma_seq_search(MARIA_HA *info, register MARIA_KEYDEF *keyinfo, uchar *page, } /* _ma_seq_search */ -int _ma_prefix_search(MARIA_HA *info, register MARIA_KEYDEF *keyinfo, uchar *page, - uchar *key, uint key_len, uint nextflag, uchar **ret_pos, - uchar *buff, my_bool *last_key) +int _ma_prefix_search(MARIA_HA *info, register MARIA_KEYDEF *keyinfo, + byte *page, byte *key, uint key_len, uint nextflag, + byte **ret_pos, byte *buff, my_bool *last_key) { /* my_flag is raw comparison result to be changed according to @@ -295,10 +298,11 @@ int _ma_prefix_search(MARIA_HA *info, register MARIA_KEYDEF *keyinfo, uchar *pag uint nod_flag, length, len, matched, cmplen, kseg_len; uint prefix_len,suffix_len; int key_len_skip, seg_len_pack, key_len_left; - uchar *end, *kseg, *vseg; - uchar *sort_order=keyinfo->seg->charset->sort_order; - uchar tt_buff[HA_MAX_KEY_BUFF+2], *t_buff=tt_buff+2; - uchar *saved_from, *saved_to, *saved_vseg; + byte *end; + uchar *kseg, *vseg, *saved_vseg, *saved_from; + uchar *sort_order= keyinfo->seg->charset->sort_order; + byte tt_buff[HA_MAX_KEY_BUFF+2], *t_buff=tt_buff+2; + byte *saved_to; uint saved_length=0, saved_prefix_len=0; uint length_pack; DBUG_ENTER("_ma_prefix_search"); @@ -315,9 +319,9 @@ int _ma_prefix_search(MARIA_HA *info, register MARIA_KEYDEF *keyinfo, uchar *pag nod_flag=_ma_test_if_nod(page); page+=2+nod_flag; *ret_pos=page; - kseg=key; + kseg= (uchar*) key; - get_key_pack_length(kseg_len,length_pack,kseg); + get_key_pack_length(kseg_len, length_pack, kseg); key_len_skip=length_pack+kseg_len; key_len_left=(int) key_len- (int) key_len_skip; /* If key_len is 0, then lenght_pack is 1, then key_len_left is -1. */ @@ -344,7 +348,7 @@ int _ma_prefix_search(MARIA_HA *info, register MARIA_KEYDEF *keyinfo, uchar *pag { uint packed= *page & 128; - vseg=page; + vseg= (uchar*) page; if (keyinfo->seg->length >= 127) { suffix_len=mi_uint2korr(vseg) & 32767; @@ -387,7 +391,7 @@ int _ma_prefix_search(MARIA_HA *info, register MARIA_KEYDEF *keyinfo, uchar *pag DBUG_PRINT("loop",("page: '%.*s%.*s'",prefix_len,t_buff+seg_len_pack, suffix_len,vseg)); { - uchar *from=vseg+suffix_len; + uchar *from= vseg+suffix_len; HA_KEYSEG *keyseg; uint l; @@ -408,9 +412,9 @@ int _ma_prefix_search(MARIA_HA *info, register MARIA_KEYDEF *keyinfo, uchar *pag from+=l; } - from+=keyseg->length; - page=from+nod_flag; - length=from-vseg; + from+= keyseg->length; + page= (byte*) from+nod_flag; + length= (uint) (from-vseg); } if (page > end) @@ -427,7 +431,7 @@ int _ma_prefix_search(MARIA_HA *info, register MARIA_KEYDEF *keyinfo, uchar *pag { /* We have to compare. But we can still skip part of the key */ uint left; - uchar *k=kseg+prefix_len; + uchar *k= kseg+prefix_len; /* If prefix_len > cmplen then we are in the end-space comparison @@ -477,7 +481,7 @@ int _ma_prefix_search(MARIA_HA *info, register MARIA_KEYDEF *keyinfo, uchar *pag for ( ; k < end && *k == ' '; k++) ; if (k == end) goto cmp_rest; /* should never happen */ - if (*k < (uchar) ' ') + if ((uchar) *k < (uchar) ' ') { my_flag= 1; /* Compared string is smaller */ break; @@ -493,11 +497,11 @@ int _ma_prefix_search(MARIA_HA *info, register MARIA_KEYDEF *keyinfo, uchar *pag /* We have to compare k and vseg as if they were space extended */ for (end=vseg + (len-cmplen) ; - vseg < end && *vseg == (uchar) ' '; + vseg < end && *vseg == (byte) ' '; vseg++, matched++) ; DBUG_ASSERT(vseg < end); - if (*vseg > (uchar) ' ') + if ((uchar) *vseg > (uchar) ' ') { my_flag= 1; /* Compared string is smaller */ break; @@ -534,8 +538,8 @@ int _ma_prefix_search(MARIA_HA *info, register MARIA_KEYDEF *keyinfo, uchar *pag /* else (matched < prefix_len) ---> do nothing. */ memcpy(buff,t_buff,saved_length=seg_len_pack+prefix_len); - saved_to=buff+saved_length; - saved_from=saved_vseg; + saved_to= buff+saved_length; + saved_from= saved_vseg; saved_length=length; *ret_pos=page; } @@ -544,12 +548,12 @@ int _ma_prefix_search(MARIA_HA *info, register MARIA_KEYDEF *keyinfo, uchar *pag if (flag == 0) { memcpy(buff,t_buff,saved_length=seg_len_pack+prefix_len); - saved_to=buff+saved_length; - saved_from=saved_vseg; + saved_to= buff+saved_length; + saved_from= saved_vseg; saved_length=length; } if (saved_length) - memcpy(saved_to,saved_from,saved_length); + memcpy(saved_to, (byte*) saved_from, saved_length); *last_key= page == end; @@ -560,7 +564,7 @@ int _ma_prefix_search(MARIA_HA *info, register MARIA_KEYDEF *keyinfo, uchar *pag /* Get pos to a key_block */ -my_off_t _ma_kpos(uint nod_flag, uchar *after_key) +my_off_t _ma_kpos(uint nod_flag, byte *after_key) { after_key-=nod_flag; switch (nod_flag) { @@ -596,7 +600,7 @@ my_off_t _ma_kpos(uint nod_flag, uchar *after_key) /* Save pos to a key_block */ -void _ma_kpointer(register MARIA_HA *info, register uchar *buff, my_off_t pos) +void _ma_kpointer(register MARIA_HA *info, register byte *buff, my_off_t pos) { pos/=MARIA_MIN_KEY_BLOCK_LENGTH; switch (info->s->base.key_reflength) { @@ -615,7 +619,7 @@ void _ma_kpointer(register MARIA_HA *info, register uchar *buff, my_off_t pos) case 4: mi_int4store(buff,pos); break; case 3: mi_int3store(buff,pos); break; case 2: mi_int2store(buff,(uint) pos); break; - case 1: buff[0]= (uchar) pos; break; + case 1: buff[0]= (char) (uchar) pos; break; default: abort(); /* impossible */ } } /* _ma_kpointer */ @@ -624,7 +628,7 @@ void _ma_kpointer(register MARIA_HA *info, register uchar *buff, my_off_t pos) /* Calc pos to a data-record from a key */ -my_off_t _ma_dpos(MARIA_HA *info, uint nod_flag, uchar *after_key) +my_off_t _ma_dpos(MARIA_HA *info, uint nod_flag, const byte *after_key) { my_off_t pos; after_key-=(nod_flag + info->s->rec_reflength); @@ -646,15 +650,14 @@ my_off_t _ma_dpos(MARIA_HA *info, uint nod_flag, uchar *after_key) default: pos=0L; /* Shut compiler up */ } - return (info->s->options & - (HA_OPTION_PACK_RECORD | HA_OPTION_COMPRESS_RECORD)) ? pos : - pos*info->s->base.pack_reclength; + return ((info->s->data_file_type == STATIC_RECORD) ? + pos * info->s->base.pack_reclength : pos); } /* Calc position from a record pointer ( in delete link chain ) */ -my_off_t _ma_rec_pos(MARIA_SHARE *s, uchar *ptr) +my_off_t _ma_rec_pos(MARIA_SHARE *s, byte *ptr) { my_off_t pos; switch (s->rec_reflength) { @@ -704,20 +707,18 @@ my_off_t _ma_rec_pos(MARIA_SHARE *s, uchar *ptr) break; default: abort(); /* Impossible */ } - return ((s->options & - (HA_OPTION_PACK_RECORD | HA_OPTION_COMPRESS_RECORD)) ? pos : - pos*s->base.pack_reclength); + return ((s->data_file_type == STATIC_RECORD) ? + pos * s->base.pack_reclength : pos); } /* save position to record */ -void _ma_dpointer(MARIA_HA *info, uchar *buff, my_off_t pos) +void _ma_dpointer(MARIA_HA *info, byte *buff, my_off_t pos) { - if (!(info->s->options & - (HA_OPTION_PACK_RECORD | HA_OPTION_COMPRESS_RECORD)) && + if (info->s->data_file_type == STATIC_RECORD && pos != HA_OFFSET_ERROR) - pos/=info->s->base.pack_reclength; + pos/= info->s->base.pack_reclength; switch (info->s->rec_reflength) { #if SIZEOF_OFF_T > 4 @@ -752,7 +753,7 @@ void _ma_dpointer(MARIA_HA *info, uchar *buff, my_off_t pos) /* same as _ma_get_key but used with fixed length keys */ uint _ma_get_static_key(register MARIA_KEYDEF *keyinfo, uint nod_flag, - register uchar **page, register uchar *key) + register byte **page, register byte *key) { memcpy((byte*) key,(byte*) *page, (size_t) (keyinfo->keylength+nod_flag)); @@ -776,10 +777,10 @@ uint _ma_get_static_key(register MARIA_KEYDEF *keyinfo, uint nod_flag, */ uint _ma_get_pack_key(register MARIA_KEYDEF *keyinfo, uint nod_flag, - register uchar **page_pos, register uchar *key) + register byte **page_pos, register byte *key) { reg1 HA_KEYSEG *keyseg; - uchar *start_key,*page=*page_pos; + byte *start_key,*page=*page_pos; uint length; start_key=key; @@ -788,7 +789,7 @@ uint _ma_get_pack_key(register MARIA_KEYDEF *keyinfo, uint nod_flag, if (keyseg->flag & HA_PACK_KEY) { /* key with length, packed to previous key */ - uchar *start=key; + byte *start= key; uint packed= *page & 128,tot_length,rest_length; if (keyseg->length >= 127) { @@ -834,7 +835,7 @@ uint _ma_get_pack_key(register MARIA_KEYDEF *keyinfo, uint nod_flag, tot_length=rest_length+length; /* If the stored length has changed, we must move the key */ - if (tot_length >= 255 && *start != 255) + if (tot_length >= 255 && *start != (char) 255) { /* length prefix changed from a length of one to a length of 3 */ bmove_upp((char*) key+length+3,(char*) key+length+1,length); @@ -842,7 +843,7 @@ uint _ma_get_pack_key(register MARIA_KEYDEF *keyinfo, uint nod_flag, mi_int2store(key+1,tot_length); key+=3+length; } - else if (tot_length < 255 && *start == 255) + else if (tot_length < 255 && *start == (char) 255) { bmove(key+1,key+3,length); *key=tot_length; @@ -891,7 +892,7 @@ uint _ma_get_pack_key(register MARIA_KEYDEF *keyinfo, uint nod_flag, if (keyseg->flag & (HA_VAR_LENGTH_PART | HA_BLOB_PART | HA_SPACE_PACK)) { - uchar *tmp=page; + byte *tmp=page; get_key_length(length,tmp); length+=(uint) (tmp-page); } @@ -913,10 +914,10 @@ uint _ma_get_pack_key(register MARIA_KEYDEF *keyinfo, uint nod_flag, /* key that is packed relatively to previous */ uint _ma_get_binary_pack_key(register MARIA_KEYDEF *keyinfo, uint nod_flag, - register uchar **page_pos, register uchar *key) + register byte **page_pos, register byte *key) { reg1 HA_KEYSEG *keyseg; - uchar *start_key,*page,*page_end,*from,*from_end; + byte *start_key,*page,*page_end,*from,*from_end; uint length,tmp; DBUG_ENTER("_ma_get_binary_pack_key"); @@ -1018,8 +1019,8 @@ uint _ma_get_binary_pack_key(register MARIA_KEYDEF *keyinfo, uint nod_flag, /* Get key at position without knowledge of previous key */ /* Returns pointer to next key */ -uchar *_ma_get_key(MARIA_HA *info, MARIA_KEYDEF *keyinfo, uchar *page, - uchar *key, uchar *keypos, uint *return_key_length) +byte *_ma_get_key(MARIA_HA *info, MARIA_KEYDEF *keyinfo, byte *page, + byte *key, byte *keypos, uint *return_key_length) { uint nod_flag; DBUG_ENTER("_ma_get_key"); @@ -1054,8 +1055,8 @@ uchar *_ma_get_key(MARIA_HA *info, MARIA_KEYDEF *keyinfo, uchar *page, /* Get key at position without knowledge of previous key */ /* Returns 0 if ok */ -static my_bool _ma_get_prev_key(MARIA_HA *info, MARIA_KEYDEF *keyinfo, uchar *page, - uchar *key, uchar *keypos, +static my_bool _ma_get_prev_key(MARIA_HA *info, MARIA_KEYDEF *keyinfo, + byte *page, byte *key, byte *keypos, uint *return_key_length) { uint nod_flag; @@ -1092,11 +1093,11 @@ static my_bool _ma_get_prev_key(MARIA_HA *info, MARIA_KEYDEF *keyinfo, uchar *pa /* Get last key from key-page */ /* Return pointer to where key starts */ -uchar *_ma_get_last_key(MARIA_HA *info, MARIA_KEYDEF *keyinfo, uchar *page, - uchar *lastkey, uchar *endpos, uint *return_key_length) +byte *_ma_get_last_key(MARIA_HA *info, MARIA_KEYDEF *keyinfo, byte *page, + byte *lastkey, byte *endpos, uint *return_key_length) { uint nod_flag; - uchar *lastpos; + byte *lastpos; DBUG_ENTER("_ma_get_last_key"); DBUG_PRINT("enter",("page: 0x%lx endpos: 0x%lx", (long) page, (long) endpos)); @@ -1135,15 +1136,15 @@ uchar *_ma_get_last_key(MARIA_HA *info, MARIA_KEYDEF *keyinfo, uchar *page, /* Calculate length of key */ -uint _ma_keylength(MARIA_KEYDEF *keyinfo, register uchar *key) +uint _ma_keylength(MARIA_KEYDEF *keyinfo, register const byte *key) { reg1 HA_KEYSEG *keyseg; - uchar *start; + const byte *start; if (! (keyinfo->flag & (HA_VAR_LENGTH_KEY | HA_BINARY_PACK_KEY))) return (keyinfo->keylength); - start=key; + start= key; for (keyseg=keyinfo->seg ; keyseg->type ; keyseg++) { if (keyseg->flag & HA_NULL_PART) @@ -1170,11 +1171,11 @@ uint _ma_keylength(MARIA_KEYDEF *keyinfo, register uchar *key) after '0xDF' but find 'ss' */ -uint _ma_keylength_part(MARIA_KEYDEF *keyinfo, register uchar *key, +uint _ma_keylength_part(MARIA_KEYDEF *keyinfo, register const byte *key, HA_KEYSEG *end) { reg1 HA_KEYSEG *keyseg; - uchar *start= key; + const byte *start= key; for (keyseg=keyinfo->seg ; keyseg != end ; keyseg++) { @@ -1193,29 +1194,35 @@ uint _ma_keylength_part(MARIA_KEYDEF *keyinfo, register uchar *key, return (uint) (key-start); } - /* Move a key */ -uchar *_ma_move_key(MARIA_KEYDEF *keyinfo, uchar *to, uchar *from) +/* Move a key */ + +byte *_ma_move_key(MARIA_KEYDEF *keyinfo, byte *to, const byte *from) { reg1 uint length; - memcpy((byte*) to, (byte*) from, - (size_t) (length= _ma_keylength(keyinfo,from))); + memcpy(to, from, (size_t) (length= _ma_keylength(keyinfo, from))); return to+length; } - /* Find next/previous record with same key */ - /* This can't be used when database is touched after last read */ + +/* + Find next/previous record with same key + + WARNING + This can't be used when database is touched after last read +*/ int _ma_search_next(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo, - uchar *key, uint key_length, uint nextflag, my_off_t pos) + byte *key, uint key_length, uint nextflag, my_off_t pos) { int error; uint nod_flag; - uchar lastkey[HA_MAX_KEY_BUFF]; + byte lastkey[HA_MAX_KEY_BUFF]; DBUG_ENTER("_ma_search_next"); - DBUG_PRINT("enter",("nextflag: %u lastpos: %lu int_keypos: %lu", - nextflag, (ulong) info->lastpos, - (ulong) info->int_keypos)); + DBUG_PRINT("enter",("nextflag: %u lastpos: %lu int_keypos: %lu page_changed %d keybuff_used: %d", + nextflag, (ulong) info->cur_row.lastpos, + (ulong) info->int_keypos, + info->page_changed, info->keybuff_used)); DBUG_EXECUTE("key", _ma_print_key(DBUG_FILE,keyinfo->seg,key,key_length);); /* Force full read if we are at last key or if we are not on a leaf @@ -1228,20 +1235,20 @@ int _ma_search_next(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo, if (((nextflag & SEARCH_BIGGER) && info->int_keypos >= info->int_maxpos) || info->page_changed || (info->int_keytree_version != keyinfo->version && - (info->int_nod_flag || info->buff_used))) + (info->int_nod_flag || info->keybuff_used))) DBUG_RETURN(_ma_search(info,keyinfo,key, USE_WHOLE_KEY, nextflag | SEARCH_SAVE_BUFF, pos)); - if (info->buff_used) + if (info->keybuff_used) { if (!_ma_fetch_keypage(info,keyinfo,info->last_search_keypage, - DFLT_INIT_HITS,info->buff,0)) + DFLT_INIT_HITS,info->keyread_buff,0)) DBUG_RETURN(-1); - info->buff_used=0; + info->keybuff_used=0; } - /* Last used buffer is in info->buff */ - nod_flag=_ma_test_if_nod(info->buff); + /* Last used buffer is in info->keyread_buff */ + nod_flag=_ma_test_if_nod(info->keyread_buff); if (nextflag & SEARCH_BIGGER) /* Next key */ { @@ -1261,11 +1268,11 @@ int _ma_search_next(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo, { uint length; /* Find start of previous key */ - info->int_keypos= _ma_get_last_key(info,keyinfo,info->buff,lastkey, + info->int_keypos= _ma_get_last_key(info,keyinfo,info->keyread_buff,lastkey, info->int_keypos, &length); if (!info->int_keypos) DBUG_RETURN(-1); - if (info->int_keypos == info->buff+2) + if (info->int_keypos == info->keyread_buff+2) DBUG_RETURN(_ma_search(info,keyinfo,key, USE_WHOLE_KEY, nextflag | SEARCH_SAVE_BUFF, pos)); if ((error= _ma_search(info,keyinfo,key, USE_WHOLE_KEY, @@ -1274,84 +1281,84 @@ int _ma_search_next(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo, DBUG_RETURN(error); /* QQ: We should be able to optimize away the following call */ - if (! _ma_get_last_key(info,keyinfo,info->buff,lastkey, + if (! _ma_get_last_key(info,keyinfo,info->keyread_buff,lastkey, info->int_keypos,&info->lastkey_length)) DBUG_RETURN(-1); } memcpy(info->lastkey,lastkey,info->lastkey_length); - info->lastpos= _ma_dpos(info,0,info->lastkey+info->lastkey_length); - DBUG_PRINT("exit",("found key at %lu",(ulong) info->lastpos)); + info->cur_row.lastpos= _ma_dpos(info,0,info->lastkey+info->lastkey_length); + DBUG_PRINT("exit",("found key at %lu",(ulong) info->cur_row.lastpos)); DBUG_RETURN(0); } /* _ma_search_next */ /* Search after position for the first row in an index */ - /* This is stored in info->lastpos */ + /* This is stored in info->cur_row.lastpos */ int _ma_search_first(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo, register my_off_t pos) { uint nod_flag; - uchar *page; + byte *page; DBUG_ENTER("_ma_search_first"); if (pos == HA_OFFSET_ERROR) { my_errno=HA_ERR_KEY_NOT_FOUND; - info->lastpos= HA_OFFSET_ERROR; + info->cur_row.lastpos= HA_OFFSET_ERROR; DBUG_RETURN(-1); } do { - if (!_ma_fetch_keypage(info,keyinfo,pos,DFLT_INIT_HITS,info->buff,0)) + if (!_ma_fetch_keypage(info,keyinfo,pos,DFLT_INIT_HITS,info->keyread_buff,0)) { - info->lastpos= HA_OFFSET_ERROR; + info->cur_row.lastpos= HA_OFFSET_ERROR; DBUG_RETURN(-1); } - nod_flag=_ma_test_if_nod(info->buff); - page=info->buff+2+nod_flag; + nod_flag=_ma_test_if_nod(info->keyread_buff); + page=info->keyread_buff+2+nod_flag; } while ((pos= _ma_kpos(nod_flag,page)) != HA_OFFSET_ERROR); if (!(info->lastkey_length=(*keyinfo->get_key)(keyinfo,nod_flag,&page, info->lastkey))) DBUG_RETURN(-1); /* Crashed */ - info->int_keypos=page; info->int_maxpos=info->buff+maria_getint(info->buff)-1; + info->int_keypos=page; info->int_maxpos=info->keyread_buff+maria_getint(info->keyread_buff)-1; info->int_nod_flag=nod_flag; info->int_keytree_version=keyinfo->version; info->last_search_keypage=info->last_keypage; - info->page_changed=info->buff_used=0; - info->lastpos= _ma_dpos(info,0,info->lastkey+info->lastkey_length); + info->page_changed=info->keybuff_used=0; + info->cur_row.lastpos= _ma_dpos(info,0,info->lastkey+info->lastkey_length); - DBUG_PRINT("exit",("found key at %lu", (ulong) info->lastpos)); + DBUG_PRINT("exit",("found key at %lu", (ulong) info->cur_row.lastpos)); DBUG_RETURN(0); } /* _ma_search_first */ /* Search after position for the last row in an index */ - /* This is stored in info->lastpos */ + /* This is stored in info->cur_row.lastpos */ int _ma_search_last(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo, register my_off_t pos) { uint nod_flag; - uchar *buff,*page; + byte *buff,*page; DBUG_ENTER("_ma_search_last"); if (pos == HA_OFFSET_ERROR) { my_errno=HA_ERR_KEY_NOT_FOUND; /* Didn't find key */ - info->lastpos= HA_OFFSET_ERROR; + info->cur_row.lastpos= HA_OFFSET_ERROR; DBUG_RETURN(-1); } - buff=info->buff; + buff=info->keyread_buff; do { if (!_ma_fetch_keypage(info,keyinfo,pos,DFLT_INIT_HITS,buff,0)) { - info->lastpos= HA_OFFSET_ERROR; + info->cur_row.lastpos= HA_OFFSET_ERROR; DBUG_RETURN(-1); } page= buff+maria_getint(buff); @@ -1361,14 +1368,14 @@ int _ma_search_last(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo, if (!_ma_get_last_key(info,keyinfo,buff,info->lastkey,page, &info->lastkey_length)) DBUG_RETURN(-1); - info->lastpos= _ma_dpos(info,0,info->lastkey+info->lastkey_length); + info->cur_row.lastpos= _ma_dpos(info,0,info->lastkey+info->lastkey_length); info->int_keypos=info->int_maxpos=page; info->int_nod_flag=nod_flag; info->int_keytree_version=keyinfo->version; info->last_search_keypage=info->last_keypage; - info->page_changed=info->buff_used=0; + info->page_changed=info->keybuff_used=0; - DBUG_PRINT("exit",("found key at %lu",(ulong) info->lastpos)); + DBUG_PRINT("exit",("found key at %lu",(ulong) info->cur_row.lastpos)); DBUG_RETURN(0); } /* _ma_search_last */ @@ -1391,12 +1398,12 @@ int _ma_search_last(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo, int _ma_calc_static_key_length(MARIA_KEYDEF *keyinfo,uint nod_flag, - uchar *next_pos __attribute__((unused)), - uchar *org_key __attribute__((unused)), - uchar *prev_key __attribute__((unused)), - uchar *key, MARIA_KEY_PARAM *s_temp) + byte *next_pos __attribute__((unused)), + byte *org_key __attribute__((unused)), + byte *prev_key __attribute__((unused)), + const byte *key, MARIA_KEY_PARAM *s_temp) { - s_temp->key=key; + s_temp->key= key; return (int) (s_temp->totlength=keyinfo->keylength+nod_flag); } @@ -1404,18 +1411,18 @@ _ma_calc_static_key_length(MARIA_KEYDEF *keyinfo,uint nod_flag, int _ma_calc_var_key_length(MARIA_KEYDEF *keyinfo,uint nod_flag, - uchar *next_pos __attribute__((unused)), - uchar *org_key __attribute__((unused)), - uchar *prev_key __attribute__((unused)), - uchar *key, MARIA_KEY_PARAM *s_temp) + byte *next_pos __attribute__((unused)), + byte *org_key __attribute__((unused)), + byte *prev_key __attribute__((unused)), + const byte *key, MARIA_KEY_PARAM *s_temp) { - s_temp->key=key; + s_temp->key= key; return (int) (s_temp->totlength= _ma_keylength(keyinfo,key)+nod_flag); } /* length of key with a variable length first segment which is prefix - compressed (mariachk reports 'packed + stripped') + compressed (maria_chk reports 'packed + stripped') Keys are compressed the following way: @@ -1434,15 +1441,16 @@ _ma_calc_var_key_length(MARIA_KEYDEF *keyinfo,uint nod_flag, int _ma_calc_var_pack_key_length(MARIA_KEYDEF *keyinfo, uint nod_flag, - uchar *next_key, - uchar *org_key, uchar *prev_key, uchar *key, + byte *next_key, + byte *org_key, byte *prev_key, const byte *key, MARIA_KEY_PARAM *s_temp) { reg1 HA_KEYSEG *keyseg; int length; uint key_length,ref_length,org_key_length=0, length_pack,new_key_length,diff_flag,pack_marker; - uchar *start,*end,*key_end,*sort_order; + const byte *start,*end,*key_end; + uchar *sort_order; bool same_length; length_pack=s_temp->ref_length=s_temp->n_ref_length=s_temp->n_length=0; @@ -1455,7 +1463,7 @@ _ma_calc_var_pack_key_length(MARIA_KEYDEF *keyinfo, uint nod_flag, (keyseg->type == HA_KEYTYPE_VARTEXT1) || (keyseg->type == HA_KEYTYPE_VARTEXT2)) && !use_strnxfrm(keyseg->charset)) - sort_order=keyseg->charset->sort_order; + sort_order= keyseg->charset->sort_order; /* diff flag contains how many bytes is needed to pack key */ if (keyseg->length >= 127) @@ -1475,10 +1483,10 @@ _ma_calc_var_pack_key_length(MARIA_KEYDEF *keyinfo, uint nod_flag, { if (!*key++) { - s_temp->key=key; - s_temp->key_length=0; - s_temp->totlength=key_length-1+diff_flag; - s_temp->next_key_pos=0; /* No next key */ + s_temp->key= key; + s_temp->key_length= 0; + s_temp->totlength= key_length-1+diff_flag; + s_temp->next_key_pos= 0; /* No next key */ return (s_temp->totlength); } s_temp->store_not_null=1; @@ -1490,13 +1498,13 @@ _ma_calc_var_pack_key_length(MARIA_KEYDEF *keyinfo, uint nod_flag, } else s_temp->store_not_null=0; - s_temp->prev_key=org_key; + s_temp->prev_key= org_key; /* The key part will start with a packed length */ get_key_pack_length(new_key_length,length_pack,key); - end=key_end= key+ new_key_length; - start=key; + end= key_end= key+ new_key_length; + start= key; /* Calc how many characters are identical between this and the prev. key */ if (prev_key) @@ -1507,11 +1515,12 @@ _ma_calc_var_pack_key_length(MARIA_KEYDEF *keyinfo, uint nod_flag, if (new_key_length && new_key_length == org_key_length) same_length=1; else if (new_key_length > org_key_length) - end=key + org_key_length; + end= key + org_key_length; if (sort_order) /* SerG */ { - while (key < end && sort_order[*key] == sort_order[*prev_key]) + while (key < end && + sort_order[* (uchar*) key] == sort_order[* (uchar*) prev_key]) { key++; prev_key++; } @@ -1592,7 +1601,8 @@ _ma_calc_var_pack_key_length(MARIA_KEYDEF *keyinfo, uint nod_flag, key=start; if (sort_order) /* SerG */ { - while (key < end && sort_order[*key] == sort_order[*org_key]) + while (key < end && + sort_order[*(uchar*) key] == sort_order[*(uchar*) org_key]) { key++; org_key++; } @@ -1672,11 +1682,11 @@ _ma_calc_var_pack_key_length(MARIA_KEYDEF *keyinfo, uint nod_flag, uint tmp_length; key=(start+=ref_length); if (key+n_length < key_end) /* Normalize length based */ - key_end=key+n_length; + key_end= key+n_length; if (sort_order) /* SerG */ { - while (key < key_end && sort_order[*key] == - sort_order[*next_key]) + while (key < key_end && + sort_order[*(uchar*) key] == sort_order[*(uchar*) next_key]) { key++; next_key++; } @@ -1716,8 +1726,9 @@ _ma_calc_var_pack_key_length(MARIA_KEYDEF *keyinfo, uint nod_flag, /* Length of key which is prefix compressed */ int _ma_calc_bin_pack_key_length(MARIA_KEYDEF *keyinfo, uint nod_flag, - uchar *next_key, - uchar *org_key, uchar *prev_key, uchar *key, + byte *next_key, + byte *org_key, byte *prev_key, + const byte *key, MARIA_KEY_PARAM *s_temp) { uint length,key_length,ref_length; @@ -1732,10 +1743,10 @@ int _ma_calc_bin_pack_key_length(MARIA_KEYDEF *keyinfo, uint nod_flag, { /* pack key against previous key */ /* - As keys may be identical when running a sort in mariachk, we + As keys may be identical when running a sort in maria_chk, we have to guard against the case where keys may be identical */ - uchar *end; + const byte *end; end=key+key_length; for ( ; *key == *prev_key && key < end; key++,prev_key++) ; s_temp->ref_length= ref_length=(uint) (key-s_temp->key); @@ -1756,7 +1767,7 @@ int _ma_calc_bin_pack_key_length(MARIA_KEYDEF *keyinfo, uint nod_flag, /* If first key and next key is packed (only on delete) */ if (!prev_key && org_key && next_length) { - uchar *end; + const byte *end; for (key= s_temp->key, end=key+next_length ; *key == *org_key && key < end; key++,org_key++) ; @@ -1798,7 +1809,7 @@ int _ma_calc_bin_pack_key_length(MARIA_KEYDEF *keyinfo, uint nod_flag, /* store key without compression */ void _ma_store_static_key(MARIA_KEYDEF *keyinfo __attribute__((unused)), - register uchar *key_pos, + register byte *key_pos, register MARIA_KEY_PARAM *s_temp) { memcpy((byte*) key_pos,(byte*) s_temp->key,(size_t) s_temp->totlength); @@ -1813,11 +1824,11 @@ void _ma_store_static_key(MARIA_KEYDEF *keyinfo __attribute__((unused)), void _ma_store_var_pack_key(MARIA_KEYDEF *keyinfo __attribute__((unused)), - register uchar *key_pos, + register byte *key_pos, register MARIA_KEY_PARAM *s_temp) { uint length; - uchar *start; + byte *start; start=key_pos; @@ -1876,7 +1887,7 @@ void _ma_store_var_pack_key(MARIA_KEYDEF *keyinfo __attribute__((unused)), /* variable length key with prefix compression */ void _ma_store_bin_pack_key(MARIA_KEYDEF *keyinfo __attribute__((unused)), - register uchar *key_pos, + register byte *key_pos, register MARIA_KEY_PARAM *s_temp) { store_key_length_inc(key_pos,s_temp->ref_length); diff --git a/storage/maria/ma_sort.c b/storage/maria/ma_sort.c index 5ae23c37261..3859bd96149 100644 --- a/storage/maria/ma_sort.c +++ b/storage/maria/ma_sort.c @@ -44,31 +44,31 @@ extern void print_error _VARARGS((const char *fmt,...)); /* Functions defined in this file */ static ha_rows NEAR_F find_all_keys(MARIA_SORT_PARAM *info,uint keys, - uchar **sort_keys, + byte **sort_keys, DYNAMIC_ARRAY *buffpek,int *maxbuffer, IO_CACHE *tempfile, IO_CACHE *tempfile_for_exceptions); -static int NEAR_F write_keys(MARIA_SORT_PARAM *info,uchar **sort_keys, +static int NEAR_F write_keys(MARIA_SORT_PARAM *info, byte **sort_keys, uint count, BUFFPEK *buffpek,IO_CACHE *tempfile); -static int NEAR_F write_key(MARIA_SORT_PARAM *info, uchar *key, +static int NEAR_F write_key(MARIA_SORT_PARAM *info, byte *key, IO_CACHE *tempfile); -static int NEAR_F write_index(MARIA_SORT_PARAM *info,uchar * *sort_keys, +static int NEAR_F write_index(MARIA_SORT_PARAM *info, byte **sort_keys, uint count); static int NEAR_F merge_many_buff(MARIA_SORT_PARAM *info,uint keys, - uchar * *sort_keys, + byte **sort_keys, BUFFPEK *buffpek,int *maxbuffer, IO_CACHE *t_file); static uint NEAR_F read_to_buffer(IO_CACHE *fromfile,BUFFPEK *buffpek, uint sort_length); static int NEAR_F merge_buffers(MARIA_SORT_PARAM *info,uint keys, IO_CACHE *from_file, IO_CACHE *to_file, - uchar * *sort_keys, BUFFPEK *lastbuff, + byte **sort_keys, BUFFPEK *lastbuff, BUFFPEK *Fb, BUFFPEK *Tb); -static int NEAR_F merge_index(MARIA_SORT_PARAM *,uint,uchar **,BUFFPEK *, int, +static int NEAR_F merge_index(MARIA_SORT_PARAM *,uint, byte **,BUFFPEK *, int, IO_CACHE *); static int flush_maria_ft_buf(MARIA_SORT_PARAM *info); -static int NEAR_F write_keys_varlen(MARIA_SORT_PARAM *info,uchar **sort_keys, +static int NEAR_F write_keys_varlen(MARIA_SORT_PARAM *info, byte **sort_keys, uint count, BUFFPEK *buffpek, IO_CACHE *tempfile); static uint NEAR_F read_to_buffer_varlen(IO_CACHE *fromfile,BUFFPEK *buffpek, @@ -96,27 +96,27 @@ my_var_write(MARIA_SORT_PARAM *info, IO_CACHE *to_file, byte *bufs); <> 0 Error */ -int _ma_create_index_by_sort(MARIA_SORT_PARAM *info,my_bool no_messages, - ulong sortbuff_size) +int _ma_create_index_by_sort(MARIA_SORT_PARAM *info, my_bool no_messages, + ulong sortbuff_size) { int error,maxbuffer,skr; uint memavl,old_memavl,keys,sort_length; DYNAMIC_ARRAY buffpek; ha_rows records; - uchar **sort_keys; + byte **sort_keys; IO_CACHE tempfile, tempfile_for_exceptions; DBUG_ENTER("_ma_create_index_by_sort"); DBUG_PRINT("enter",("sort_length: %d", info->key_length)); if (info->keyinfo->flag & HA_VAR_LENGTH_KEY) { - info->write_keys=write_keys_varlen; + info->write_keys= write_keys_varlen; info->read_to_buffer=read_to_buffer_varlen; info->write_key=write_merge_key_varlen; } else { - info->write_keys=write_keys; + info->write_keys= write_keys; info->read_to_buffer=read_to_buffer; info->write_key=write_merge_key; } @@ -124,7 +124,7 @@ int _ma_create_index_by_sort(MARIA_SORT_PARAM *info,my_bool no_messages, my_b_clear(&tempfile); my_b_clear(&tempfile_for_exceptions); bzero((char*) &buffpek,sizeof(buffpek)); - sort_keys= (uchar **) NULL; error= 1; + sort_keys= (byte **) NULL; error= 1; maxbuffer=1; memavl=max(sortbuff_size,MIN_SORT_MEMORY); @@ -152,8 +152,8 @@ int _ma_create_index_by_sort(MARIA_SORT_PARAM *info,my_bool no_messages, } while ((maxbuffer= (int) (records/(keys-1)+1)) != skr); - if ((sort_keys=(uchar **)my_malloc(keys*(sort_length+sizeof(char*))+ - HA_FT_MAXBYTELEN, MYF(0)))) + if ((sort_keys=(byte**) my_malloc(keys*(sort_length+sizeof(char*))+ + HA_FT_MAXBYTELEN, MYF(0)))) { if (my_init_dynamic_array(&buffpek, sizeof(BUFFPEK), maxbuffer, maxbuffer/2)) @@ -230,7 +230,7 @@ int _ma_create_index_by_sort(MARIA_SORT_PARAM *info,my_bool no_messages, && !my_b_read(&tempfile_for_exceptions,(byte*)sort_keys, (uint) key_length)) { - if (_ma_ck_write(index,keyno,(uchar*) sort_keys,key_length-ref_length)) + if (_ma_ck_write(index,keyno,(byte*) sort_keys,key_length-ref_length)) goto err; } } @@ -251,7 +251,7 @@ err: /* Search after all keys and place them in a temp. file */ static ha_rows NEAR_F find_all_keys(MARIA_SORT_PARAM *info, uint keys, - uchar **sort_keys, DYNAMIC_ARRAY *buffpek, + byte **sort_keys, DYNAMIC_ARRAY *buffpek, int *maxbuffer, IO_CACHE *tempfile, IO_CACHE *tempfile_for_exceptions) { @@ -260,7 +260,7 @@ static ha_rows NEAR_F find_all_keys(MARIA_SORT_PARAM *info, uint keys, DBUG_ENTER("find_all_keys"); idx=error=0; - sort_keys[0]=(uchar*) (sort_keys+keys); + sort_keys[0]= (byte*) (sort_keys+keys); while (!(error=(*info->key_read)(info,sort_keys[idx]))) { @@ -277,7 +277,7 @@ static ha_rows NEAR_F find_all_keys(MARIA_SORT_PARAM *info, uint keys, tempfile)) DBUG_RETURN(HA_POS_ERROR); /* purecov: inspected */ - sort_keys[0]=(uchar*) (sort_keys+keys); + sort_keys[0]=(byte*) (sort_keys+keys); memcpy(sort_keys[0],sort_keys[idx-1],(size_t) info->key_length); idx=1; } @@ -308,7 +308,7 @@ pthread_handler_t _ma_thr_find_all_keys(void *arg) int error; uint memavl,old_memavl,keys,sort_length; uint idx, maxbuffer; - uchar **sort_keys=0; + byte **sort_keys= 0; LINT_INIT(keys); @@ -336,7 +336,6 @@ pthread_handler_t _ma_thr_find_all_keys(void *arg) my_b_clear(&info->tempfile_for_exceptions); bzero((char*) &info->buffpek,sizeof(info->buffpek)); bzero((char*) &info->unique, sizeof(info->unique)); - sort_keys= (uchar **) NULL; memavl=max(info->sortbuff_size, MIN_SORT_MEMORY); idx= info->sort_info->max_records; @@ -365,15 +364,15 @@ pthread_handler_t _ma_thr_find_all_keys(void *arg) } while ((maxbuffer= (int) (idx/(keys-1)+1)) != skr); } - if ((sort_keys=(uchar **)my_malloc(keys*(sort_length+sizeof(char*))+ - ((info->keyinfo->flag & HA_FULLTEXT) ? - HA_FT_MAXBYTELEN : 0), MYF(0)))) + if ((sort_keys=(byte**) my_malloc(keys*(sort_length+sizeof(char*))+ + ((info->keyinfo->flag & HA_FULLTEXT) ? + HA_FT_MAXBYTELEN : 0), MYF(0)))) { if (my_init_dynamic_array(&info->buffpek, sizeof(BUFFPEK), maxbuffer, maxbuffer/2)) { my_free((gptr) sort_keys,MYF(0)); - sort_keys= (uchar **) NULL; /* for err: label */ + sort_keys= (byte**) NULL; /* for err: label */ } else break; @@ -393,7 +392,7 @@ pthread_handler_t _ma_thr_find_all_keys(void *arg) info->sort_keys=sort_keys; idx=error=0; - sort_keys[0]=(uchar*) (sort_keys+keys); + sort_keys[0]=(byte*) (sort_keys+keys); while (!(error=info->sort_info->got_error) && !(error=(*info->key_read)(info,sort_keys[idx]))) @@ -411,7 +410,7 @@ pthread_handler_t _ma_thr_find_all_keys(void *arg) (BUFFPEK *)alloc_dynamic(&info->buffpek), &info->tempfile)) goto err; - sort_keys[0]=(uchar*) (sort_keys+keys); + sort_keys[0]=(byte*) (sort_keys+keys); memcpy(sort_keys[0],sort_keys[idx-1],(size_t) info->key_length); idx=1; } @@ -422,7 +421,8 @@ pthread_handler_t _ma_thr_find_all_keys(void *arg) if (info->buffpek.elements) { if (info->write_keys(info,sort_keys, idx, - (BUFFPEK *) alloc_dynamic(&info->buffpek), &info->tempfile)) + (BUFFPEK *) alloc_dynamic(&info->buffpek), + &info->tempfile)) goto err; info->keys=(info->buffpek.elements-1)*(keys-1)+idx; } @@ -434,8 +434,7 @@ pthread_handler_t _ma_thr_find_all_keys(void *arg) err: info->sort_info->got_error=1; /* no need to protect this with a mutex */ - if (sort_keys) - my_free((gptr) sort_keys,MYF(0)); + my_free((gptr) sort_keys, MYF(MY_ALLOW_ZERO_PTR)); info->sort_keys=0; delete_dynamic(& info->buffpek); close_cached_file(&info->tempfile); @@ -499,8 +498,7 @@ int _ma_thr_write_keys(MARIA_SORT_PARAM *sort_param) } } my_free((gptr) sinfo->sort_keys,MYF(0)); - my_free(_ma_get_rec_buff_ptr(info, sinfo->rec_buff), - MYF(MY_ALLOW_ZERO_PTR)); + my_free(sinfo->rec_buff, MYF(MY_ALLOW_ZERO_PTR)); sinfo->sort_keys=0; } @@ -548,7 +546,7 @@ int _ma_thr_write_keys(MARIA_SORT_PARAM *sort_param) { if (param->testflag & T_VERBOSE) printf("Key %d - Merging %u keys\n",sinfo->key+1, sinfo->keys); - if (merge_many_buff(sinfo, keys, (uchar **)mergebuf, + if (merge_many_buff(sinfo, keys, (byte **) mergebuf, dynamic_element(&sinfo->buffpek, 0, BUFFPEK *), (int*) &maxbuffer, &sinfo->tempfile)) { @@ -564,7 +562,7 @@ int _ma_thr_write_keys(MARIA_SORT_PARAM *sort_param) } if (param->testflag & T_VERBOSE) printf("Key %d - Last merge and dumping keys\n", sinfo->key+1); - if (merge_index(sinfo, keys, (uchar **)mergebuf, + if (merge_index(sinfo, keys, (byte**) mergebuf, dynamic_element(&sinfo->buffpek,0,BUFFPEK *), maxbuffer,&sinfo->tempfile) || flush_maria_ft_buf(sinfo) || @@ -596,7 +594,7 @@ int _ma_thr_write_keys(MARIA_SORT_PARAM *sort_param) if (key_length > sizeof(maria_ft_buf) || my_b_read(&sinfo->tempfile_for_exceptions, (byte*)maria_ft_buf, (uint)key_length) || - _ma_ck_write(info, sinfo->key, (uchar*)maria_ft_buf, + _ma_ck_write(info, sinfo->key, maria_ft_buf, key_length - info->s->rec_reflength)) got_error=1; } @@ -607,12 +605,14 @@ int _ma_thr_write_keys(MARIA_SORT_PARAM *sort_param) } #endif /* THREAD */ - /* Write all keys in memory to file for later merge */ -static int NEAR_F write_keys(MARIA_SORT_PARAM *info, register uchar **sort_keys, +/* Write all keys in memory to file for later merge */ + +static int NEAR_F write_keys(MARIA_SORT_PARAM *info, + register byte **sort_keys, uint count, BUFFPEK *buffpek, IO_CACHE *tempfile) { - uchar **end; + byte **end; uint sort_length=info->key_length; DBUG_ENTER("write_keys"); @@ -628,7 +628,7 @@ static int NEAR_F write_keys(MARIA_SORT_PARAM *info, register uchar **sort_keys, for (end=sort_keys+count ; sort_keys != end ; sort_keys++) { - if (my_b_write(tempfile,(byte*) *sort_keys,(uint) sort_length)) + if (my_b_write(tempfile, *sort_keys, (uint) sort_length)) DBUG_RETURN(1); /* purecov: inspected */ } DBUG_RETURN(0); @@ -639,7 +639,7 @@ static inline int my_var_write(MARIA_SORT_PARAM *info, IO_CACHE *to_file, byte *bufs) { int err; - uint16 len = _ma_keylength(info->keyinfo, (uchar*) bufs); + uint16 len= _ma_keylength(info->keyinfo, bufs); /* The following is safe as this is a local file */ if ((err= my_b_write(to_file, (byte*)&len, sizeof(len)))) @@ -651,11 +651,11 @@ my_var_write(MARIA_SORT_PARAM *info, IO_CACHE *to_file, byte *bufs) static int NEAR_F write_keys_varlen(MARIA_SORT_PARAM *info, - register uchar **sort_keys, + register byte **sort_keys, uint count, BUFFPEK *buffpek, IO_CACHE *tempfile) { - uchar **end; + byte **end; int err; DBUG_ENTER("write_keys_varlen"); @@ -670,14 +670,14 @@ static int NEAR_F write_keys_varlen(MARIA_SORT_PARAM *info, buffpek->count=count; for (end=sort_keys+count ; sort_keys != end ; sort_keys++) { - if ((err= my_var_write(info,tempfile, (byte*) *sort_keys))) + if ((err= my_var_write(info,tempfile, *sort_keys))) DBUG_RETURN(err); } DBUG_RETURN(0); } /* write_keys_varlen */ -static int NEAR_F write_key(MARIA_SORT_PARAM *info, uchar *key, +static int NEAR_F write_key(MARIA_SORT_PARAM *info, byte *key, IO_CACHE *tempfile) { uint key_length=info->real_key_length; @@ -688,8 +688,8 @@ static int NEAR_F write_key(MARIA_SORT_PARAM *info, uchar *key, DISK_BUFFER_SIZE, info->sort_info->param->myf_rw)) DBUG_RETURN(1); - if (my_b_write(tempfile,(byte*)&key_length,sizeof(key_length)) || - my_b_write(tempfile,(byte*)key,(uint) key_length)) + if (my_b_write(tempfile, (byte*)&key_length,sizeof(key_length)) || + my_b_write(tempfile, key, (uint) key_length)) DBUG_RETURN(1); DBUG_RETURN(0); } /* write_key */ @@ -697,7 +697,8 @@ static int NEAR_F write_key(MARIA_SORT_PARAM *info, uchar *key, /* Write index */ -static int NEAR_F write_index(MARIA_SORT_PARAM *info, register uchar **sort_keys, +static int NEAR_F write_index(MARIA_SORT_PARAM *info, + register byte **sort_keys, register uint count) { DBUG_ENTER("write_index"); @@ -706,7 +707,7 @@ static int NEAR_F write_index(MARIA_SORT_PARAM *info, register uchar **sort_keys (qsort2_cmp) info->key_cmp,info); while (count--) { - if ((*info->key_write)(info,*sort_keys++)) + if ((*info->key_write)(info, *sort_keys++)) DBUG_RETURN(-1); /* purecov: inspected */ } DBUG_RETURN(0); @@ -716,7 +717,7 @@ static int NEAR_F write_index(MARIA_SORT_PARAM *info, register uchar **sort_keys /* Merge buffers to make < MERGEBUFF2 buffers */ static int NEAR_F merge_many_buff(MARIA_SORT_PARAM *info, uint keys, - uchar **sort_keys, BUFFPEK *buffpek, + byte **sort_keys, BUFFPEK *buffpek, int *maxbuffer, IO_CACHE *t_file) { register int i; @@ -797,11 +798,11 @@ static uint NEAR_F read_to_buffer_varlen(IO_CACHE *fromfile, BUFFPEK *buffpek, register uint count; uint16 length_of_key = 0; uint idx; - uchar *buffp; + byte *buffp; if ((count=(uint) min((ha_rows) buffpek->max_keys,buffpek->count))) { - buffp = buffpek->base; + buffp= buffpek->base; for (idx=1;idx<=count;idx++) { @@ -855,18 +856,17 @@ static int NEAR_F write_merge_key(MARIA_SORT_PARAM *info __attribute__((unused)) static int NEAR_F merge_buffers(MARIA_SORT_PARAM *info, uint keys, IO_CACHE *from_file, - IO_CACHE *to_file, uchar **sort_keys, BUFFPEK *lastbuff, + IO_CACHE *to_file, byte **sort_keys, BUFFPEK *lastbuff, BUFFPEK *Fb, BUFFPEK *Tb) { int error; uint sort_length,maxcount; ha_rows count; my_off_t to_start_filepos; - uchar *strpos; + byte *strpos; BUFFPEK *buffpek,**refpek; QUEUE queue; volatile int *killed= _ma_killed_ptr(info->sort_info->param); - DBUG_ENTER("merge_buffers"); count=error=0; @@ -874,7 +874,7 @@ merge_buffers(MARIA_SORT_PARAM *info, uint keys, IO_CACHE *from_file, LINT_INIT(to_start_filepos); if (to_file) to_start_filepos=my_b_tell(to_file); - strpos=(uchar*) sort_keys; + strpos= (byte*) sort_keys; sort_length=info->key_length; if (init_queue(&queue,(uint) (Tb-Fb)+1,offsetof(BUFFPEK,key),0, @@ -923,7 +923,7 @@ merge_buffers(MARIA_SORT_PARAM *info, uint keys, IO_CACHE *from_file, { if (!(error=(int) info->read_to_buffer(from_file,buffpek,sort_length))) { - uchar *base=buffpek->base; + byte *base= buffpek->base; uint max_keys=buffpek->max_keys; VOID(queue_remove(&queue,0)); @@ -955,7 +955,7 @@ merge_buffers(MARIA_SORT_PARAM *info, uint keys, IO_CACHE *from_file, } } buffpek=(BUFFPEK*) queue_top(&queue); - buffpek->base=(uchar *) sort_keys; + buffpek->base= (byte*) sort_keys; buffpek->max_keys=keys; do { @@ -969,21 +969,21 @@ merge_buffers(MARIA_SORT_PARAM *info, uint keys, IO_CACHE *from_file, } else { - register uchar *end; + register byte *end; strpos= buffpek->key; - for (end=strpos+buffpek->mem_count*sort_length; + for (end= strpos+buffpek->mem_count*sort_length; strpos != end ; strpos+=sort_length) { - if ((*info->key_write)(info,(void*) strpos)) + if ((*info->key_write)(info, (byte*) strpos)) { error=1; goto err; /* purecov: inspected */ } } } } - while ((error=(int) info->read_to_buffer(from_file,buffpek,sort_length)) != -1 && - error != 0); + while ((error=(int) info->read_to_buffer(from_file,buffpek,sort_length)) != + -1 && error != 0); lastbuff->count=count; if (to_file) @@ -997,7 +997,7 @@ err: /* Do a merge to output-file (save only positions) */ static int NEAR_F -merge_index(MARIA_SORT_PARAM *info, uint keys, uchar **sort_keys, +merge_index(MARIA_SORT_PARAM *info, uint keys, byte **sort_keys, BUFFPEK *buffpek, int maxbuffer, IO_CACHE *tempfile) { DBUG_ENTER("merge_index"); @@ -1007,8 +1007,8 @@ merge_index(MARIA_SORT_PARAM *info, uint keys, uchar **sort_keys, DBUG_RETURN(0); } /* merge_index */ -static int -flush_maria_ft_buf(MARIA_SORT_PARAM *info) + +static int flush_maria_ft_buf(MARIA_SORT_PARAM *info) { int err=0; if (info->sort_info->ft_buf) diff --git a/storage/maria/ma_sp_defs.h b/storage/maria/ma_sp_defs.h index a7e282f0ddc..8b9dd204ded 100644 --- a/storage/maria/ma_sp_defs.h +++ b/storage/maria/ma_sp_defs.h @@ -41,7 +41,7 @@ enum wkbByteOrder wkbNDR = 1 /* Little Endian */ }; -uint sp_make_key(register MARIA_HA *info, uint keynr, uchar *key, +uint sp_make_key(register MARIA_HA *info, uint keynr, byte *key, const byte *record, my_off_t filepos); #endif /*HAVE_SPATIAL*/ diff --git a/storage/maria/ma_sp_key.c b/storage/maria/ma_sp_key.c index b9841fed1e7..79345550dd9 100644 --- a/storage/maria/ma_sp_key.c +++ b/storage/maria/ma_sp_key.c @@ -37,7 +37,7 @@ static void get_double(double *d, const byte *pos) float8get(*d, pos); } -uint sp_make_key(register MARIA_HA *info, uint keynr, uchar *key, +uint sp_make_key(register MARIA_HA *info, uint keynr, byte *key, const byte *record, my_off_t filepos) { HA_KEYSEG *keyseg; diff --git a/storage/maria/ma_sp_test.c b/storage/maria/ma_sp_test.c index ea812974c8c..1ac1a74d7d7 100644 --- a/storage/maria/ma_sp_test.c +++ b/storage/maria/ma_sp_test.c @@ -109,10 +109,11 @@ int run_test(const char *filename) create_info.max_rows=10000000; if (maria_create(filename, - 1, /* keys */ - keyinfo, - 2, /* columns */ - recinfo,uniques,&uniquedef,&create_info,create_flag)) + DYNAMIC_RECORD, + 1, /* keys */ + keyinfo, + 2, /* columns */ + recinfo,uniques,&uniquedef,&create_info,create_flag)) goto err; if (!silent) diff --git a/storage/maria/ma_static.c b/storage/maria/ma_static.c index 511c5507aaf..c5580e1e981 100644 --- a/storage/maria/ma_static.c +++ b/storage/maria/ma_static.c @@ -25,12 +25,13 @@ LIST *maria_open_list=0; uchar NEAR maria_file_magic[]= -{ (uchar) 254, (uchar) 254,'\007', '\001', }; +{ (uchar) 254, (uchar) 254, (uchar) 9, '\001', }; uchar NEAR maria_pack_file_magic[]= -{ (uchar) 254, (uchar) 254,'\010', '\002', }; +{ (uchar) 254, (uchar) 254, (uchar) 10, '\001', }; uint maria_quick_table_bits=9; ulong maria_block_size= MARIA_KEY_BLOCK_LENGTH; -my_bool maria_flush=0, maria_delay_key_write=0, maria_single_user=0; +my_bool maria_flush= 0, maria_single_user= 0; +my_bool maria_delay_key_write= 0; #if defined(THREAD) && !defined(DONT_USE_RW_LOCKS) ulong maria_concurrent_insert= 2; #else @@ -38,11 +39,14 @@ ulong maria_concurrent_insert= 0; #endif my_off_t maria_max_temp_length= MAX_FILE_SIZE; ulong maria_bulk_insert_tree_size=8192*1024; -ulong maria_data_pointer_size=4; +ulong maria_data_pointer_size= 4; KEY_CACHE maria_key_cache_var; KEY_CACHE *maria_key_cache= &maria_key_cache_var; +/* Enough for comparing if number is zero */ +byte maria_zero_string[]= {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; + /* read_vec[] is used for converting between P_READ_KEY.. and SEARCH_ Position is , == , >= , <= , > , < diff --git a/storage/maria/ma_statrec.c b/storage/maria/ma_statrec.c index 0aef24f40a9..11049d6f279 100644 --- a/storage/maria/ma_statrec.c +++ b/storage/maria/ma_statrec.c @@ -19,9 +19,9 @@ #include "maria_def.h" -int _ma_write_static_record(MARIA_HA *info, const byte *record) +my_bool _ma_write_static_record(MARIA_HA *info, const byte *record) { - uchar temp[8]; /* max pointer length */ + byte temp[8]; /* max pointer length */ if (info->s->state.dellink != HA_OFFSET_ERROR && !info->append_insert_at_end) { @@ -86,7 +86,8 @@ int _ma_write_static_record(MARIA_HA *info, const byte *record) return 1; } -int _ma_update_static_record(MARIA_HA *info, my_off_t pos, const byte *record) +my_bool _ma_update_static_record(MARIA_HA *info, MARIA_RECORD_POS pos, + const byte *record) { info->rec_cache.seek_not_done=1; /* We have done a seek */ return (info->s->file_write(info, @@ -96,22 +97,22 @@ int _ma_update_static_record(MARIA_HA *info, my_off_t pos, const byte *record) } -int _ma_delete_static_record(MARIA_HA *info) +my_bool _ma_delete_static_record(MARIA_HA *info) { - uchar temp[9]; /* 1+sizeof(uint32) */ - + byte temp[9]; /* 1+sizeof(uint32) */ info->state->del++; info->state->empty+=info->s->base.pack_reclength; temp[0]= '\0'; /* Mark that record is deleted */ _ma_dpointer(info,temp+1,info->s->state.dellink); - info->s->state.dellink = info->lastpos; + info->s->state.dellink= info->cur_row.lastpos; info->rec_cache.seek_not_done=1; - return (info->s->file_write(info,(byte*) temp, 1+info->s->rec_reflength, - info->lastpos, MYF(MY_NABP)) != 0); + return (info->s->file_write(info, temp, 1+info->s->rec_reflength, + info->cur_row.lastpos, MYF(MY_NABP)) != 0); } -int _ma_cmp_static_record(register MARIA_HA *info, register const byte *old) +my_bool _ma_cmp_static_record(register MARIA_HA *info, + register const byte *old) { DBUG_ENTER("_ma_cmp_static_record"); @@ -122,7 +123,7 @@ int _ma_cmp_static_record(register MARIA_HA *info, register const byte *old) { if (flush_io_cache(&info->rec_cache)) { - DBUG_RETURN(-1); + DBUG_RETURN(1); } info->rec_cache.seek_not_done=1; /* We have done a seek */ } @@ -130,10 +131,11 @@ int _ma_cmp_static_record(register MARIA_HA *info, register const byte *old) if ((info->opt_flag & READ_CHECK_USED)) { /* If check isn't disabled */ info->rec_cache.seek_not_done=1; /* We have done a seek */ - if (info->s->file_read(info, (char*) info->rec_buff, info->s->base.reclength, - info->lastpos, - MYF(MY_NABP))) - DBUG_RETURN(-1); + if (info->s->file_read(info, (char*) info->rec_buff, + info->s->base.reclength, + info->cur_row.lastpos, + MYF(MY_NABP))) + DBUG_RETURN(1); if (memcmp((byte*) info->rec_buff, (byte*) old, (uint) info->s->base.reclength)) { @@ -147,27 +149,31 @@ int _ma_cmp_static_record(register MARIA_HA *info, register const byte *old) } -int _ma_cmp_static_unique(MARIA_HA *info, MARIA_UNIQUEDEF *def, - const byte *record, my_off_t pos) +my_bool _ma_cmp_static_unique(MARIA_HA *info, MARIA_UNIQUEDEF *def, + const byte *record, MARIA_RECORD_POS pos) { DBUG_ENTER("_ma_cmp_static_unique"); info->rec_cache.seek_not_done=1; /* We have done a seek */ if (info->s->file_read(info, (char*) info->rec_buff, info->s->base.reclength, pos, MYF(MY_NABP))) - DBUG_RETURN(-1); - DBUG_RETURN(_ma_unique_comp(def, record, info->rec_buff, - def->null_are_equal)); + DBUG_RETURN(1); + DBUG_RETURN(_ma_unique_comp(def, record, (byte*) info->rec_buff, + def->null_are_equal)); } - /* Read a fixed-length-record */ - /* Returns 0 if Ok. */ - /* 1 if record is deleted */ - /* MY_FILE_ERROR on read-error or locking-error */ +/* + Read a fixed-length-record + + RETURN + 0 Ok + 1 record delete + -1 on read-error or locking-error +*/ -int _ma_read_static_record(register MARIA_HA *info, register my_off_t pos, - register byte *record) +int _ma_read_static_record(register MARIA_HA *info, register byte *record, + MARIA_RECORD_POS pos) { int error; @@ -180,7 +186,7 @@ int _ma_read_static_record(register MARIA_HA *info, register my_off_t pos, info->rec_cache.seek_not_done=1; /* We have done a seek */ error=info->s->file_read(info,(char*) record,info->s->base.reclength, - pos,MYF(MY_NABP)) != 0; + pos, MYF(MY_NABP)) != 0; fast_ma_writeinfo(info); if (! error) { @@ -201,8 +207,8 @@ int _ma_read_static_record(register MARIA_HA *info, register my_off_t pos, int _ma_read_rnd_static_record(MARIA_HA *info, byte *buf, - register my_off_t filepos, - my_bool skip_deleted_blocks) + MARIA_RECORD_POS filepos, + my_bool skip_deleted_blocks) { int locked,error,cache_read; uint cache_length; @@ -211,10 +217,6 @@ int _ma_read_rnd_static_record(MARIA_HA *info, byte *buf, cache_read=0; cache_length=0; - if (info->opt_flag & WRITE_CACHE_USED && - (info->rec_cache.pos_in_file <= filepos || skip_deleted_blocks) && - flush_io_cache(&info->rec_cache)) - DBUG_RETURN(my_errno); if (info->opt_flag & READ_CACHE_USED) { /* Cache in use */ if (filepos == my_b_tell(&info->rec_cache) && @@ -256,12 +258,12 @@ int _ma_read_rnd_static_record(MARIA_HA *info, byte *buf, fast_ma_writeinfo(info); DBUG_RETURN(my_errno=HA_ERR_END_OF_FILE); } - info->lastpos= filepos; - info->nextpos= filepos+share->base.pack_reclength; + info->cur_row.lastpos= filepos; + info->cur_row.nextpos= filepos+share->base.pack_reclength; if (! cache_read) /* No cacheing */ { - if ((error= _ma_read_static_record(info,filepos,buf))) + if ((error= _ma_read_static_record(info, buf, filepos))) { if (error > 0) error=my_errno=HA_ERR_RECORD_DELETED; diff --git a/storage/maria/ma_test1.c b/storage/maria/ma_test1.c index 69d432a5d95..0f37391c1d4 100644 --- a/storage/maria/ma_test1.c +++ b/storage/maria/ma_test1.c @@ -28,12 +28,13 @@ static int rec_pointer_size=0, flags[50]; static int key_field=FIELD_SKIP_PRESPACE,extra_field=FIELD_SKIP_ENDSPACE; static int key_type=HA_KEYTYPE_NUM; static int create_flag=0; +static enum data_file_type record_type= DYNAMIC_RECORD; static uint insert_count, update_count, remove_count; static uint pack_keys=0, pack_seg=0, key_length; static uint unique_key=HA_NOSAME; static my_bool key_cacheing, null_fields, silent, skip_update, opt_unique, - verbose; + verbose, skip_delete; static MARIA_COLUMNDEF recinfo[4]; static MARIA_KEYDEF keyinfo[10]; static HA_KEYSEG keyseg[10]; @@ -63,31 +64,30 @@ static int run_test(const char *filename) MARIA_HA *file; int i,j,error,deleted,rec_length,uniques=0; ha_rows found,row_count; - my_off_t pos; char record[MAX_REC_LENGTH],key[MAX_REC_LENGTH],read_record[MAX_REC_LENGTH]; MARIA_UNIQUEDEF uniquedef; MARIA_CREATE_INFO create_info; bzero((char*) recinfo,sizeof(recinfo)); + bzero((char*) &create_info,sizeof(create_info)); /* First define 2 columns */ - recinfo[0].type=FIELD_NORMAL; recinfo[0].length=1; /* For NULL bits */ - recinfo[1].type=key_field; - recinfo[1].length= (key_field == FIELD_BLOB ? 4+maria_portable_sizeof_char_ptr : + create_info.null_bytes= 1; + recinfo[0].type= key_field; + recinfo[0].length= (key_field == FIELD_BLOB ? 4+maria_portable_sizeof_char_ptr : key_length); if (key_field == FIELD_VARCHAR) - recinfo[1].length+= HA_VARCHAR_PACKLENGTH(key_length);; - recinfo[2].type=extra_field; - recinfo[2].length= (extra_field == FIELD_BLOB ? 4 + maria_portable_sizeof_char_ptr : 24); + recinfo[0].length+= HA_VARCHAR_PACKLENGTH(key_length); + recinfo[1].type=extra_field; + recinfo[1].length= (extra_field == FIELD_BLOB ? 4 + maria_portable_sizeof_char_ptr : 24); if (extra_field == FIELD_VARCHAR) - recinfo[2].length+= HA_VARCHAR_PACKLENGTH(recinfo[2].length); + recinfo[1].length+= HA_VARCHAR_PACKLENGTH(recinfo[1].length); if (opt_unique) { - recinfo[3].type=FIELD_CHECK; - recinfo[3].length=MARIA_UNIQUE_HASH_LENGTH; + recinfo[2].type=FIELD_CHECK; + recinfo[2].length=MARIA_UNIQUE_HASH_LENGTH; } - rec_length=recinfo[0].length+recinfo[1].length+recinfo[2].length+ - recinfo[3].length; + rec_length= recinfo[0].length+recinfo[1].length+recinfo[2].length; if (key_type == HA_KEYTYPE_VARTEXT1 && key_length > 255) @@ -125,8 +125,8 @@ static int run_test(const char *filename) for (i=0, start=1 ; i < 2 ; i++) { uniqueseg[i].start=start; - start+=recinfo[i+1].length; - uniqueseg[i].length=recinfo[i+1].length; + start+=recinfo[i].length; + uniqueseg[i].length=recinfo[i].length; uniqueseg[i].language= default_charset_info->number; } uniqueseg[0].type= key_type; @@ -139,18 +139,21 @@ static int run_test(const char *filename) uniqueseg[1].flag|= HA_BLOB_PART; } else if (extra_field == FIELD_VARCHAR) + { uniqueseg[1].flag|= HA_VAR_LENGTH_PART; + uniqueseg[1].type= (HA_VARCHAR_PACKLENGTH(recinfo[1].length-1) == 1 ? + HA_KEYTYPE_VARTEXT1 : HA_KEYTYPE_VARTEXT2); + } } else uniques=0; if (!silent) - printf("- Creating isam-file\n"); - bzero((char*) &create_info,sizeof(create_info)); + printf("- Creating maria file\n"); create_info.max_rows=(ulong) (rec_pointer_size ? (1L << (rec_pointer_size*8))/40 : 0); - if (maria_create(filename,1,keyinfo,3+opt_unique,recinfo, + if (maria_create(filename, record_type, 1, keyinfo,2+opt_unique,recinfo, uniques, &uniquedef, &create_info, create_flag)) goto err; @@ -223,9 +226,10 @@ static int run_test(const char *filename) } /* Read through all rows and update them */ - pos=(my_off_t) 0; + assert(maria_scan_init(file) == 0); + found=0; - while ((error=maria_rrnd(file,read_record,pos)) == 0) + while ((error= maria_scan(file,read_record)) == 0) { if (update_count-- == 0) { VOID(maria_close(file)) ; exit(0) ; } memcpy(record,read_record,rec_length); @@ -236,17 +240,17 @@ static int run_test(const char *filename) keyinfo[0].seg[0].length,record+1,my_errno); } found++; - pos=HA_OFFSET_ERROR; } if (found != row_count) printf("Found %ld of %ld rows\n", (ulong) found, (ulong) row_count); + maria_scan_end(file); } if (!silent) printf("- Reopening file\n"); if (maria_close(file)) goto err; if (!(file=maria_open(filename,2,HA_OPEN_ABORT_IF_LOCKED))) goto err; - if (!skip_update) + if (!skip_delete) { if (!silent) printf("- Removing keys\n"); @@ -254,7 +258,13 @@ static int run_test(const char *filename) for (i=0 ; i <= 10 ; i++) { /* testing */ - if (remove_count-- == 0) { VOID(maria_close(file)) ; exit(0) ; } + if (remove_count-- == 0) + { + fprintf(stderr, + "delete-rows number of rows deleted; Going down hard!\n"); + VOID(maria_close(file)); + exit(0) ; + } j=i*2; if (!flags[j]) continue; @@ -283,6 +293,7 @@ static int run_test(const char *filename) } if (!silent) printf("- Reading rows with key\n"); + record[1]= 0; /* For nicer printf */ for (i=0 ; i <= 25 ; i++) { create_key(key,i); @@ -299,10 +310,16 @@ static int run_test(const char *filename) if (!silent) printf("- Reading rows with position\n"); + if (maria_scan_init(file)) + { + fprintf(stderr, "maria_scan_init failed\n"); + goto err; + } + for (i=1,found=0 ; i <= 30 ; i++) { my_errno=0; - if ((error=maria_rrnd(file,read_record,i == 1 ? 0L : HA_OFFSET_ERROR)) == -1) + if ((error= maria_scan(file, read_record)) == HA_ERR_END_OF_FILE) { if (found != row_count-deleted) printf("Found only %ld of %ld rows\n", (ulong) found, @@ -318,7 +335,8 @@ static int run_test(const char *filename) i-1,error,my_errno,read_record+1); } } - if (maria_close(file)) goto err; + if (maria_close(file)) + goto err; maria_end(); my_end(MY_CHECK_ERROR); @@ -346,7 +364,7 @@ static void create_key_part(char *key,uint rownr) if ((rownr & 7) == 0) { /* Change the key to force a unpack of the next key */ - bfill(key+3,keyinfo[0].seg[0].length-4,rownr < 10 ? 'a' : 'b'); + bfill(key+3,keyinfo[0].seg[0].length-5,rownr < 10 ? 'a' : 'b'); } } else @@ -375,7 +393,7 @@ static void create_key(char *key,uint rownr) if (rownr == 0) { key[0]=1; /* null key */ - key[1]=0; /* Fore easy print of key */ + key[1]=0; /* For easy print of key */ return; } *key++=0; @@ -405,7 +423,7 @@ static void create_record(char *record,uint rownr) record[0]|=keyinfo[0].seg[0].null_bit; /* Null key */ pos=record+1; - if (recinfo[1].type == FIELD_BLOB) + if (recinfo[0].type == FIELD_BLOB) { uint tmp; char *ptr; @@ -414,25 +432,25 @@ static void create_record(char *record,uint rownr) int4store(pos,tmp); ptr=blob_key; memcpy_fixed(pos+4,&ptr,sizeof(char*)); - pos+=recinfo[1].length; + pos+=recinfo[0].length; } - else if (recinfo[1].type == FIELD_VARCHAR) + else if (recinfo[0].type == FIELD_VARCHAR) { - uint tmp, pack_length= HA_VARCHAR_PACKLENGTH(recinfo[1].length-1); + uint tmp, pack_length= HA_VARCHAR_PACKLENGTH(recinfo[0].length-1); create_key_part(pos+pack_length,rownr); tmp= strlen(pos+pack_length); if (pack_length == 1) *(uchar*) pos= (uchar) tmp; else int2store(pos,tmp); - pos+= recinfo[1].length; + pos+= recinfo[0].length; } else { create_key_part(pos,rownr); - pos+=recinfo[1].length; + pos+=recinfo[0].length; } - if (recinfo[2].type == FIELD_BLOB) + if (recinfo[1].type == FIELD_BLOB) { uint tmp; char *ptr;; @@ -443,7 +461,7 @@ static void create_record(char *record,uint rownr) ptr=blob_record; memcpy_fixed(pos+4,&ptr,sizeof(char*)); } - else if (recinfo[2].type == FIELD_VARCHAR) + else if (recinfo[1].type == FIELD_VARCHAR) { uint tmp, pack_length= HA_VARCHAR_PACKLENGTH(recinfo[1].length-1); sprintf(pos+pack_length, "... row: %d", rownr); @@ -456,7 +474,7 @@ static void create_record(char *record,uint rownr) else { sprintf(pos,"... row: %d", rownr); - strappend(pos,recinfo[2].length,' '); + strappend(pos,recinfo[1].length,' '); } } @@ -465,7 +483,7 @@ static void create_record(char *record,uint rownr) static void update_record(char *record) { char *pos=record+1; - if (recinfo[1].type == FIELD_BLOB) + if (recinfo[0].type == FIELD_BLOB) { char *column,*ptr; int length; @@ -477,16 +495,16 @@ static void update_record(char *record) if (keyinfo[0].seg[0].type != HA_KEYTYPE_NUM) default_charset_info->cset->casedn(default_charset_info, blob_key, length, blob_key, length); - pos+=recinfo[1].length; + pos+=recinfo[0].length; } - else if (recinfo[1].type == FIELD_VARCHAR) + else if (recinfo[0].type == FIELD_VARCHAR) { - uint pack_length= HA_VARCHAR_PACKLENGTH(recinfo[1].length-1); + uint pack_length= HA_VARCHAR_PACKLENGTH(recinfo[0].length-1); uint length= pack_length == 1 ? (uint) *(uchar*) pos : uint2korr(pos); default_charset_info->cset->casedn(default_charset_info, pos + pack_length, length, pos + pack_length, length); - pos+=recinfo[1].length; + pos+=recinfo[0].length; } else { @@ -494,10 +512,10 @@ static void update_record(char *record) default_charset_info->cset->casedn(default_charset_info, pos, keyinfo[0].seg[0].length, pos, keyinfo[0].seg[0].length); - pos+=recinfo[1].length; + pos+=recinfo[0].length; } - if (recinfo[2].type == FIELD_BLOB) + if (recinfo[1].type == FIELD_BLOB) { char *column; int length; @@ -510,13 +528,14 @@ static void update_record(char *record) column=blob_record; memcpy_fixed(pos+4,&column,sizeof(char*)); } - else if (recinfo[2].type == FIELD_VARCHAR) + else if (recinfo[1].type == FIELD_VARCHAR) { /* Second field is longer than 10 characters */ uint pack_length= HA_VARCHAR_PACKLENGTH(recinfo[1].length-1); uint length= pack_length == 1 ? (uint) *(uchar*) pos : uint2korr(pos); - bfill(pos+pack_length+length,recinfo[2].length-length-pack_length,'.'); - length=recinfo[2].length-pack_length; + pos= record+ recinfo[1].offset; + bfill(pos+pack_length+length,recinfo[1].length-length-pack_length,'.'); + length=recinfo[1].length-pack_length; if (pack_length == 1) *(uchar*) pos= (uchar) length; else @@ -524,7 +543,7 @@ static void update_record(char *record) } else { - bfill(pos+recinfo[2].length-10,10,'.'); + bfill(pos+recinfo[1].length-10,10,'.'); } } @@ -537,44 +556,49 @@ static struct my_option my_long_options[] = {"debug", '#', "Undocumented", 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, #endif - {"delete_rows", 'd', "Undocumented", (gptr*) &remove_count, - (gptr*) &remove_count, 0, GET_UINT, REQUIRED_ARG, 1000, 0, 0, 0, 0, 0}, + {"delete-rows", 'd', "Abort after this many rows has been deleted", + (gptr*) &remove_count, (gptr*) &remove_count, 0, GET_UINT, REQUIRED_ARG, + 1000, 0, 0, 0, 0, 0}, {"help", '?', "Display help and exit", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, - {"insert_rows", 'i', "Undocumented", (gptr*) &insert_count, + {"insert-rows", 'i', "Undocumented", (gptr*) &insert_count, (gptr*) &insert_count, 0, GET_UINT, REQUIRED_ARG, 1000, 0, 0, 0, 0, 0}, - {"key_alpha", 'a', "Use a key of type HA_KEYTYPE_TEXT", + {"key-alpha", 'a', "Use a key of type HA_KEYTYPE_TEXT", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, - {"key_binary_pack", 'B', "Undocumented", + {"key-binary-pack", 'B', "Undocumented", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, - {"key_blob", 'b', "Undocumented", + {"key-blob", 'b', "Undocumented", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, - {"key_cache", 'K', "Undocumented", (gptr*) &key_cacheing, + {"key-cache", 'K', "Undocumented", (gptr*) &key_cacheing, (gptr*) &key_cacheing, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, - {"key_length", 'k', "Undocumented", (gptr*) &key_length, (gptr*) &key_length, + {"key-length", 'k', "Undocumented", (gptr*) &key_length, (gptr*) &key_length, 0, GET_UINT, REQUIRED_ARG, 6, 0, 0, 0, 0, 0}, - {"key_multiple", 'm', "Undocumented", + {"key-multiple", 'm', "Undocumented", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, - {"key_prefix_pack", 'P', "Undocumented", + {"key-prefix_pack", 'P', "Undocumented", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, - {"key_space_pack", 'p', "Undocumented", + {"key-space_pack", 'p', "Undocumented", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, - {"key_varchar", 'w', "Test VARCHAR keys", + {"key-varchar", 'w', "Test VARCHAR keys", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, - {"null_fields", 'N', "Define fields with NULL", + {"null-fields", 'N', "Define fields with NULL", (gptr*) &null_fields, (gptr*) &null_fields, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, - {"row_fixed_size", 'S', "Undocumented", + {"row-fixed-size", 'S', "Fixed size records", + 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, + {"rows-in-block", 'M', "Store rows in block format", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, - {"row_pointer_size", 'R', "Undocumented", (gptr*) &rec_pointer_size, + {"row-pointer-size", 'R', "Undocumented", (gptr*) &rec_pointer_size, (gptr*) &rec_pointer_size, 0, GET_INT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"silent", 's', "Undocumented", (gptr*) &silent, (gptr*) &silent, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, - {"skip_update", 'U', "Undocumented", (gptr*) &skip_update, + {"skip-delete", 'U', "Don't test deletes", (gptr*) &skip_delete, + (gptr*) &skip_delete, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, + {"skip-update", 'D', "Don't test updates", (gptr*) &skip_update, (gptr*) &skip_update, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"unique", 'C', "Undocumented", (gptr*) &opt_unique, (gptr*) &opt_unique, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, - {"update_rows", 'u', "Undocumented", (gptr*) &update_count, + {"update-rows", 'u', "Undocumented", (gptr*) &update_count, (gptr*) &update_count, 0, GET_UINT, REQUIRED_ARG, 1000, 0, 0, 0, 0, 0}, {"verbose", 'v', "Be more verbose", (gptr*) &verbose, (gptr*) &verbose, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, @@ -605,15 +629,20 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)), case 'B': pack_keys= HA_BINARY_PACK_KEY; /* Use binary compression */ break; + case 'M': + record_type= BLOCK_RECORD; + break; case 'S': if (key_field == FIELD_VARCHAR) { create_flag=0; /* Static sized varchar */ + record_type= STATIC_RECORD; } else if (key_field != FIELD_BLOB) { key_field=FIELD_NORMAL; /* static-size record */ extra_field=FIELD_NORMAL; + record_type= STATIC_RECORD; } break; case 'p': @@ -629,6 +658,8 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)), extra_field= FIELD_BLOB; pack_seg|= HA_BLOB_PART; key_type= HA_KEYTYPE_VARTEXT1; + if (record_type == STATIC_RECORD) + record_type= DYNAMIC_RECORD; break; case 'k': if (key_length < 4 || key_length > HA_MAX_KEY_LENGTH) @@ -642,7 +673,8 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)), extra_field= FIELD_VARCHAR; key_type= HA_KEYTYPE_VARTEXT1; pack_seg|= HA_VAR_LENGTH_PART; - create_flag|= HA_PACK_RECORD; + if (record_type == STATIC_RECORD) + record_type= DYNAMIC_RECORD; break; case 'K': /* Use key cacheing */ key_cacheing=1; diff --git a/storage/maria/ma_test2.c b/storage/maria/ma_test2.c index 840ecb2eeb7..6d54a078f25 100644 --- a/storage/maria/ma_test2.c +++ b/storage/maria/ma_test2.c @@ -38,7 +38,8 @@ static void get_options(int argc, char *argv[]); static uint rnd(uint max_value); static void fix_length(byte *record,uint length); -static void put_blob_in_record(char *blob_pos,char **blob_buffer); +static void put_blob_in_record(char *blob_pos,char **blob_buffer, + ulong *length); static void copy_key(struct st_maria_info *info,uint inx, uchar *record,uchar *key); @@ -46,10 +47,11 @@ static int verbose=0,testflag=0, first_key=0,async_io=0,key_cacheing=0,write_cacheing=0,locking=0, rec_pointer_size=0,pack_fields=1,silent=0, opt_quick_mode=0; -static int pack_seg=HA_SPACE_PACK,pack_type=HA_PACK_KEY,remove_count=-1, - create_flag=0; +static int pack_seg=HA_SPACE_PACK,pack_type=HA_PACK_KEY,remove_count=-1; +static int create_flag= 0, srand_arg= 0; static ulong key_cache_size=IO_SIZE*16; static uint key_cache_block_size= KEY_CACHE_BLOCK_SIZE; +static enum data_file_type record_type= DYNAMIC_RECORD; static uint keys=MARIA_KEYS,recant=1000; static uint use_blob=0; @@ -201,16 +203,14 @@ int main(int argc, char *argv[]) for (i=4999 ; i>0 ; i--) key3[i]=0; if (!silent) - printf("- Creating isam-file\n"); - /* DBUG_PUSH(""); */ - /* my_delete(filename,MYF(0)); */ /* Remove old locks under gdb */ + printf("- Creating maria-file\n"); file= 0; bzero((char*) &create_info,sizeof(create_info)); create_info.max_rows=(ha_rows) (rec_pointer_size ? (1L << (rec_pointer_size*8))/ reclength : 0); create_info.reloc_rows=(ha_rows) 100; - if (maria_create(filename,keys,&keyinfo[first_key], + if (maria_create(filename, record_type, keys,&keyinfo[first_key], use_blob ? 7 : 6, &recinfo[0], 0,(MARIA_UNIQUEDEF*) 0, &create_info,create_flag)) @@ -230,12 +230,13 @@ int main(int argc, char *argv[]) for (i=0 ; i < recant ; i++) { + ulong blob_length; n1=rnd(1000); n2=rnd(100); n3=rnd(5000); sprintf(record,"%6d:%4d:%8d:Pos: %4d ",n1,n2,n3,write_count); int4store(record+STANDARD_LENGTH-4,(long) i); fix_length(record,(uint) STANDARD_LENGTH+rnd(60)); - put_blob_in_record(record+blob_pos,&blob_buffer); - DBUG_PRINT("test",("record: %d",i)); + put_blob_in_record(record+blob_pos,&blob_buffer, &blob_length); + DBUG_PRINT("test",("record: %d blob_length: %lu", i, blob_length)); if (maria_write(file,record)) { @@ -257,7 +258,7 @@ int main(int argc, char *argv[]) } /* Check if we can find key without flushing database */ - if (i == recant/2) + if (i % 10 == 0) { for (j=rnd(1000)+1 ; j>0 && key1[j] == 0 ; j--) ; if (!j) @@ -270,7 +271,8 @@ int main(int argc, char *argv[]) } } } - if (testflag==1) goto end; + if (testflag == 1) + goto end; if (write_cacheing) { @@ -285,6 +287,8 @@ int main(int argc, char *argv[]) if (!silent) printf("- Delete\n"); + if (srand_arg) + srand(srand_arg); for (i=0 ; i<recant/10 ; i++) { for (j=rnd(1000)+1 ; j>0 && key1[j] == 0 ; j--) ; @@ -296,6 +300,12 @@ int main(int argc, char *argv[]) printf("can't find key1: \"%s\"\n",key); goto err; } + if (bcmp(read_record+keyinfo[0].seg[0].start, + key, keyinfo[0].seg[0].length)) + { + printf("Found wrong record when searching for key: \"%s\"\n",key); + goto err; + } if (opt_delete == (uint) remove_count) /* While testing */ goto end; if (maria_delete(file,read_record)) @@ -310,10 +320,13 @@ int main(int argc, char *argv[]) else puts("Warning: Skipping delete test because no dupplicate keys"); } - if (testflag==2) goto end; + if (testflag == 2) + goto end; if (!silent) printf("- Update\n"); + if (srand_arg) + srand(srand_arg); for (i=0 ; i<recant/10 ; i++) { n1=rnd(1000); n2=rnd(100); n3=rnd(5000); @@ -330,10 +343,19 @@ int main(int argc, char *argv[]) printf("can't find key1: \"%s\"\n",key); goto err; } + if (bcmp(read_record+keyinfo[0].seg[0].start, + key, keyinfo[0].seg[0].length)) + { + printf("Found wrong record when searching for key: \"%s\"; Found \"%.*s\"\n", + key, keyinfo[0].seg[0].length, + read_record+keyinfo[0].seg[0].start); + goto err; + } if (use_blob) { + ulong blob_length; if (i & 1) - put_blob_in_record(record+blob_pos,&blob_buffer); + put_blob_in_record(record+blob_pos,&blob_buffer, &blob_length); else bmove(record+blob_pos,read_record+blob_pos,8); } @@ -395,10 +417,12 @@ int main(int argc, char *argv[]) goto end; } { + info.recpos= maria_position(file); int skr=maria_rnext(file,read_record2,0); if ((skr && my_errno != HA_ERR_END_OF_FILE) || maria_rprev(file,read_record2,-1) || - memcmp(read_record,read_record2,reclength) != 0) + memcmp(read_record,read_record2,reclength) != 0 || + info.recpos != maria_position(file)) { printf("maria_rsame_with_pos lost position\n"); goto end; @@ -588,13 +612,24 @@ int main(int argc, char *argv[]) if (!silent) puts("- Test if: Read rrnd - same"); DBUG_PRINT("progpos",("Read rrnd - same")); + assert(maria_scan_init(file) == 0); for (i=0 ; i < write_count ; i++) { - if (maria_rrnd(file,read_record,i == 0 ? 0L : HA_OFFSET_ERROR) == 0) + int tmp; + if ((tmp= maria_scan(file,read_record)) && + tmp != HA_ERR_END_OF_FILE && + tmp != HA_ERR_RECORD_DELETED) + { + printf("Got error %d when scanning table\n", tmp); break; + } } - if (i == write_count) + maria_scan_end(file); + if (i != write_count && i != write_count - opt_delete) + { + printf("Found wrong number of rows while scanning table\n"); goto err; + } bmove(read_record2,read_record,reclength); for (i=min(2,keys) ; i-- > 0 ;) @@ -602,7 +637,7 @@ int main(int argc, char *argv[]) if (maria_rsame(file,read_record2,(int) i)) goto err; if (bcmp(read_record,read_record2,reclength) != 0) { - printf("is_rsame didn't find same record\n"); + printf("maria_rsame didn't find same record\n"); goto end; } } @@ -716,12 +751,14 @@ int main(int argc, char *argv[]) } } ant=0; - while ((error=maria_rrnd(file,record,HA_OFFSET_ERROR)) != HA_ERR_END_OF_FILE && + assert(maria_scan_init(file) == 0); + while ((error= maria_scan(file,record)) != HA_ERR_END_OF_FILE && ant < write_count + 10) - ant+= error ? 0 : 1; + ant+= error ? 0 : 1; + maria_scan_end(file); if (ant != write_count-opt_delete) { - printf("rrnd with cache: I can only find: %d records of %d\n", + printf("scan with cache: I can only find: %d records of %d\n", ant,write_count-opt_delete); goto end; } @@ -743,7 +780,8 @@ int main(int argc, char *argv[]) goto end; } - if (testflag == 4) goto end; + if (testflag == 4) + goto end; if (!silent) printf("- Removing keys\n"); @@ -752,8 +790,8 @@ int main(int argc, char *argv[]) /* DBUG_POP(); */ maria_reset(file); found_parts=0; - while ((error=maria_rrnd(file,read_record,HA_OFFSET_ERROR)) != - HA_ERR_END_OF_FILE) + maria_scan_init(file); + while ((error= maria_scan(file,read_record)) != HA_ERR_END_OF_FILE) { info.recpos=maria_position(file); if (lastpos >= info.recpos && lastpos != HA_OFFSET_ERROR) @@ -767,7 +805,7 @@ int main(int argc, char *argv[]) { if (opt_delete == (uint) remove_count) /* While testing */ goto end; - if (maria_rsame(file,read_record,-1)) + if (rnd(2) == 1 && maria_rsame(file,read_record,-1)) { printf("can't find record %lx\n",(long) info.recpos); goto err; @@ -783,9 +821,10 @@ int main(int argc, char *argv[]) { if (ptr[pos] != (uchar) (blob_length+pos)) { - printf("found blob with wrong info at %ld\n",(long) lastpos); - use_blob=0; - break; + printf("Found blob with wrong info at %ld\n",(long) lastpos); + maria_scan_end(file); + my_errno= 0; + goto err; } } } @@ -793,6 +832,7 @@ int main(int argc, char *argv[]) { printf("can't delete record: %6.6s, delete_count: %d\n", read_record, opt_delete); + maria_scan_end(file); goto err; } opt_delete++; @@ -800,6 +840,7 @@ int main(int argc, char *argv[]) else found_parts++; } + maria_scan_end(file); if (my_errno != HA_ERR_END_OF_FILE && my_errno != HA_ERR_RECORD_DELETED) printf("error: %d from maria_rrnd\n",my_errno); if (write_count != opt_delete) @@ -851,8 +892,7 @@ reads: %10lu\n", (ulong) maria_key_cache->global_cache_read); } end_key_cache(maria_key_cache,1); - if (blob_buffer) - my_free(blob_buffer,MYF(0)); + my_free(blob_buffer, MYF(MY_ALLOW_ZERO_PTR)); my_end(silent ? MY_CHECK_ERROR : MY_CHECK_ERROR | MY_GIVE_INFO); return(0); err: @@ -864,8 +904,7 @@ err: } /* main */ - /* l{ser optioner */ - /* OBS! intierar endast DEBUG - ingen debuggning h{r ! */ +/* Read options */ static void get_options(int argc, char **argv) { @@ -879,7 +918,9 @@ static void get_options(int argc, char **argv) pack_type= HA_BINARY_PACK_KEY; break; case 'b': - use_blob=1; + use_blob= 1; + if (*++pos) + use_blob= atol(pos); break; case 'K': /* Use key cacheing */ key_cacheing=1; @@ -896,7 +937,7 @@ static void get_options(int argc, char **argv) break; case 'i': if (*++pos) - srand(atoi(pos)); + srand(srand_arg= atoi(pos)); break; case 'L': locking=1; @@ -910,9 +951,9 @@ static void get_options(int argc, char **argv) verbose=1; break; case 'm': /* records */ - if ((recant=atoi(++pos)) < 10) + if ((recant=atoi(++pos)) < 10 && testflag > 1) { - fprintf(stderr,"record count must be >= 10\n"); + fprintf(stderr,"record count must be >= 10 (if testflag != 1)\n"); exit(1); } break; @@ -943,6 +984,9 @@ static void get_options(int argc, char **argv) keys > (uint) (MARIA_KEYS-first_key)) keys=MARIA_KEYS-first_key; break; + case 'M': + record_type= BLOCK_RECORD; + break; case 'P': pack_type=0; /* Don't use DIFF_LENGTH */ pack_seg=0; @@ -954,6 +998,7 @@ static void get_options(int argc, char **argv) break; case 'S': pack_fields=0; /* Static-length-records */ + record_type= STATIC_RECORD; break; case 's': silent=1; @@ -973,7 +1018,7 @@ static void get_options(int argc, char **argv) case '?': case 'I': case 'V': - printf("%s Ver 1.2 for %s at %s\n",progname,SYSTEM_TYPE,MACHINE_TYPE); + printf("%s Ver 1.0 for %s at %s\n",progname,SYSTEM_TYPE,MACHINE_TYPE); puts("By Monty, for your professional use\n"); printf("Usage: %s [-?AbBcDIKLPRqSsVWltv] [-k#] [-f#] [-m#] [-e#] [-E#] [-t#]\n", progname); @@ -1010,7 +1055,8 @@ static void fix_length(byte *rec, uint length) /* Put maybe a blob in record */ -static void put_blob_in_record(char *blob_pos, char **blob_buffer) +static void put_blob_in_record(char *blob_pos, char **blob_buffer, + ulong *blob_length) { ulong i,length; if (use_blob) @@ -1028,10 +1074,12 @@ static void put_blob_in_record(char *blob_pos, char **blob_buffer) (*blob_buffer)[i]=(char) (length+i); int4store(blob_pos,length); memcpy_fixed(blob_pos+4,(char*) blob_buffer,sizeof(char*)); + *blob_length= length; } else { int4store(blob_pos,0); + *blob_length= 0; } } return; diff --git a/storage/maria/ma_test3.c b/storage/maria/ma_test3.c index 96b896b03c6..4911d13f2f1 100644 --- a/storage/maria/ma_test3.c +++ b/storage/maria/ma_test3.c @@ -97,8 +97,8 @@ int main(int argc,char **argv) puts("- Creating maria-file"); my_delete(filename,MYF(0)); /* Remove old locks under gdb */ - if (maria_create(filename,2,&keyinfo[0],2,&recinfo[0],0,(MARIA_UNIQUEDEF*) 0, - (MARIA_CREATE_INFO*) 0,0)) + if (maria_create(filename,BLOCK_RECORD, 2, &keyinfo[0],2,&recinfo[0],0, + (MARIA_UNIQUEDEF*) 0, (MARIA_CREATE_INFO*) 0,0)) exit(1); rnd_init(0); diff --git a/storage/maria/ma_test_all.sh b/storage/maria/ma_test_all.sh index f857127dca9..17e654ac51f 100755 --- a/storage/maria/ma_test_all.sh +++ b/storage/maria/ma_test_all.sh @@ -5,143 +5,188 @@ valgrind="valgrind --alignment=8 --leak-check=yes" silent="-s" +suffix="" +#set -x -v -e -if test -f ma_test1$MACH ; then suffix=$MACH ; else suffix=""; fi -./ma_test1$suffix $silent -./maria_chk$suffix -se test1 -./ma_test1$suffix $silent -N -S -./maria_chk$suffix -se test1 -./ma_test1$suffix $silent -P --checksum -./maria_chk$suffix -se test1 -./ma_test1$suffix $silent -P -N -S -./maria_chk$suffix -se test1 -./ma_test1$suffix $silent -B -N -R2 -./maria_chk$suffix -sm test1 -./ma_test1$suffix $silent -a -k 480 --unique -./maria_chk$suffix -sm test1 -./ma_test1$suffix $silent -a -N -S -R1 -./maria_chk$suffix -sm test1 -./ma_test1$suffix $silent -p -S -./maria_chk$suffix -sm test1 -./ma_test1$suffix $silent -p -S -N --unique -./maria_chk$suffix -sm test1 -./ma_test1$suffix $silent -p -S -N --key_length=127 --checksum -./maria_chk$suffix -sm test1 -./ma_test1$suffix $silent -p -S -N --key_length=128 -./maria_chk$suffix -sm test1 -./ma_test1$suffix $silent -p -S --key_length=480 -./maria_chk$suffix -sm test1 -./ma_test1$suffix $silent -a -B -./maria_chk$suffix -sm test1 -./ma_test1$suffix $silent -a -B --key_length=64 --unique -./maria_chk$suffix -sm test1 -./ma_test1$suffix $silent -a -B -k 480 --checksum -./maria_chk$suffix -sm test1 -./ma_test1$suffix $silent -a -B -k 480 -N --unique --checksum -./maria_chk$suffix -sm test1 -./ma_test1$suffix $silent -a -m -./maria_chk$suffix -sm test1 -./ma_test1$suffix $silent -a -m -P --unique --checksum -./maria_chk$suffix -sm test1 -./ma_test1$suffix $silent -a -m -P --key_length=480 --key_cache -./maria_chk$suffix -sm test1 -./ma_test1$suffix $silent -m -p -./maria_chk$suffix -sm test1 -./ma_test1$suffix $silent -w -S --unique -./maria_chk$suffix -sm test1 -./ma_test1$suffix $silent -a -w --key_length=64 --checksum -./maria_chk$suffix -sm test1 -./ma_test1$suffix $silent -a -w -N --key_length=480 -./maria_chk$suffix -sm test1 -./ma_test1$suffix $silent -a -w -S --key_length=480 --checksum -./maria_chk$suffix -sm test1 -./ma_test1$suffix $silent -a -b -N -./maria_chk$suffix -sm test1 -./ma_test1$suffix $silent -a -b --key_length=480 -./maria_chk$suffix -sm test1 -./ma_test1$suffix $silent -p -B --key_length=480 -./maria_chk$suffix -sm test1 +run_tests() +{ + row_type=$1 + # + # First some simple tests + # + ./ma_test1$suffix $silent $row_type + ./maria_chk$suffix -se test1 + ./ma_test1$suffix $silent -N $row_type + ./maria_chk$suffix -se test1 + ./ma_test1$suffix $silent -P --checksum $row_type + ./maria_chk$suffix -se test1 + ./ma_test1$suffix $silent -P -N $row_type + ./maria_chk$suffix -se test1 + ./ma_test1$suffix $silent -B -N -R2 $row_type + ./maria_chk$suffix -sm test1 + ./ma_test1$suffix $silent -a -k 480 --unique $row_type + ./maria_chk$suffix -sm test1 + ./ma_test1$suffix $silent -a -N -R1 $row_type + ./maria_chk$suffix -sm test1 + ./ma_test1$suffix $silent -p $row_type + ./maria_chk$suffix -sm test1 + ./ma_test1$suffix $silent -p -N --unique $row_type + ./maria_chk$suffix -sm test1 + ./ma_test1$suffix $silent -p -N --key_length=127 --checksum $row_type + ./maria_chk$suffix -sm test1 + ./ma_test1$suffix $silent -p -N --key_length=128 $row_type + ./maria_chk$suffix -sm test1 + ./ma_test1$suffix $silent -p --key_length=480 $row_type + ./maria_chk$suffix -sm test1 + ./ma_test1$suffix $silent -a -B $row_type + ./maria_chk$suffix -sm test1 + ./ma_test1$suffix $silent -a -B --key_length=64 --unique $row_type + ./maria_chk$suffix -sm test1 + ./ma_test1$suffix $silent -a -B -k 480 --checksum $row_type + ./maria_chk$suffix -sm test1 + ./ma_test1$suffix $silent -a -B -k 480 -N --unique --checksum $row_type + ./maria_chk$suffix -sm test1 + ./ma_test1$suffix $silent -a -m $row_type + ./maria_chk$suffix -sm test1 + ./ma_test1$suffix $silent -a -m -P --unique --checksum $row_type + ./maria_chk$suffix -sm test1 + ./ma_test1$suffix $silent -a -m -P --key_length=480 --key_cache $row_type + ./maria_chk$suffix -sm test1 + ./ma_test1$suffix $silent -m -p $row_type + ./maria_chk$suffix -sm test1 + ./ma_test1$suffix $silent -w --unique $row_type + ./maria_chk$suffix -sm test1 + ./ma_test1$suffix $silent -a -w --key_length=64 --checksum $row_type + ./maria_chk$suffix -sm test1 + ./ma_test1$suffix $silent -a -w -N --key_length=480 $row_type + ./maria_chk$suffix -sm test1 + ./ma_test1$suffix $silent -a -w --key_length=480 --checksum $row_type + ./maria_chk$suffix -sm test1 + ./ma_test1$suffix $silent -a -b -N $row_type + ./maria_chk$suffix -sm test1 + ./ma_test1$suffix $silent -a -b --key_length=480 $row_type + ./maria_chk$suffix -sm test1 + ./ma_test1$suffix $silent -p -B --key_length=480 $row_type + ./maria_chk$suffix -sm test1 + ./ma_test1$suffix $silent --checksum --unique $row_type + ./maria_chk$suffix -se test1 + ./ma_test1$suffix $silent --unique $row_type + ./maria_chk$suffix -se test1 + + ./ma_test1$suffix $silent --key_multiple -N -S $row_type + ./maria_chk$suffix -sm test1 + ./ma_test1$suffix $silent --key_multiple -a -p --key_length=480 $row_type + ./maria_chk$suffix -sm test1 + ./ma_test1$suffix $silent --key_multiple -a -B --key_length=480 $row_type + ./maria_chk$suffix -sm test1 + ./ma_test1$suffix $silent --key_multiple -P -S $row_type + ./maria_chk$suffix -sm test1 + + ./maria_pack$suffix --force -s test1 + ./maria_chk$suffix -ess test1 + + ./ma_test2$suffix $silent -L -K -W -P $row_type + ./maria_chk$suffix -sm test2 + ./ma_test2$suffix $silent -L -K -W -P -A $row_type + ./maria_chk$suffix -sm test2 + ./ma_test2$suffix $silent -L -K -P -R3 -m50 -b1000000 $row_type + ./maria_chk$suffix -sm test2 + ./ma_test2$suffix $silent -L -B $row_type + ./maria_chk$suffix -sm test2 + ./ma_test2$suffix $silent -D -B -c $row_type + ./maria_chk$suffix -sm test2 + ./ma_test2$suffix $silent -m10000 -e4096 -K $row_type + ./maria_chk$suffix -sm test2 + ./ma_test2$suffix $silent -m10000 -e8192 -K $row_type + ./maria_chk$suffix -sm test2 + ./ma_test2$suffix $silent -m10000 -e16384 -E16384 -K -L $row_type + ./maria_chk$suffix -sm test2 +} -./ma_test1$suffix $silent --checksum -./maria_chk$suffix -se test1 -./maria_chk$suffix -rs test1 -./maria_chk$suffix -se test1 -./maria_chk$suffix -rqs test1 -./maria_chk$suffix -se test1 -./maria_chk$suffix -rs --correct-checksum test1 -./maria_chk$suffix -se test1 -./maria_chk$suffix -rqs --correct-checksum test1 -./maria_chk$suffix -se test1 -./maria_chk$suffix -ros --correct-checksum test1 -./maria_chk$suffix -se test1 -./maria_chk$suffix -rqos --correct-checksum test1 -./maria_chk$suffix -se test1 +run_repair_tests() +{ + row_type=$1 + ./ma_test1$suffix $silent --checksum $row_type + ./maria_chk$suffix -se test1 + ./maria_chk$suffix -rs test1 + ./maria_chk$suffix -se test1 + ./maria_chk$suffix -rqs test1 + ./maria_chk$suffix -se test1 + ./maria_chk$suffix -rs --correct-checksum test1 + ./maria_chk$suffix -se test1 + ./maria_chk$suffix -rqs --correct-checksum test1 + ./maria_chk$suffix -se test1 + ./maria_chk$suffix -ros --correct-checksum test1 + ./maria_chk$suffix -se test1 + ./maria_chk$suffix -rqos --correct-checksum test1 + ./maria_chk$suffix -se test1 +} -# check of maria_pack / maria_chk -./maria_pack$suffix --force -s test1 -./maria_chk$suffix -es test1 -./maria_chk$suffix -rqs test1 -./maria_chk$suffix -es test1 -./maria_chk$suffix -rs test1 -./maria_chk$suffix -es test1 -./maria_chk$suffix -rus test1 -./maria_chk$suffix -es test1 +run_pack_tests() +{ + row_type=$1 + # check of maria_pack / maria_chk + ./ma_test1$suffix $silent --checksum $row_type + ./maria_pack$suffix --force -s test1 + ./maria_chk$suffix -ess test1 + ./maria_chk$suffix -rqs test1 + ./maria_chk$suffix -es test1 + ./maria_chk$suffix -rs test1 + ./maria_chk$suffix -es test1 + ./maria_chk$suffix -rus test1 + ./maria_chk$suffix -es test1 + + ./ma_test1$suffix $silent --checksum -S $row_type + ./maria_chk$suffix -se test1 + ./maria_chk$suffix -ros test1 + ./maria_chk$suffix -rqs test1 + ./maria_chk$suffix -se test1 + + ./maria_pack$suffix --force -s test1 + ./maria_chk$suffix -rqs test1 + ./maria_chk$suffix -es test1 + ./maria_chk$suffix -rus test1 + ./maria_chk$suffix -es test1 +} -./ma_test1$suffix $silent --checksum -S -./maria_chk$suffix -se test1 -./maria_chk$suffix -ros test1 -./maria_chk$suffix -rqs test1 -./maria_chk$suffix -se test1 +echo "Running tests with dynamic row format" +run_tests "" +run_repair_tests "" +run_pack_tests "" -./maria_pack$suffix --force -s test1 -./maria_chk$suffix -rqs test1 -./maria_chk$suffix -es test1 -./maria_chk$suffix -rus test1 -./maria_chk$suffix -es test1 +echo "Running tests with static row format" +run_tests -S +run_repair_tests -S +run_pack_tests -S -./ma_test1$suffix $silent --checksum --unique -./maria_chk$suffix -se test1 -./ma_test1$suffix $silent --unique -S -./maria_chk$suffix -se test1 +echo "Running tests with block row format" +run_tests -M +# +# Tests that gives warnings +# -./ma_test1$suffix $silent --key_multiple -N -S -./maria_chk$suffix -sm test1 -./ma_test1$suffix $silent --key_multiple -a -p --key_length=480 -./maria_chk$suffix -sm test1 -./ma_test1$suffix $silent --key_multiple -a -B --key_length=480 -./maria_chk$suffix -sm test1 -./ma_test1$suffix $silent --key_multiple -P -S -./maria_chk$suffix -sm test1 - -./ma_test2$suffix $silent -L -K -W -P -./maria_chk$suffix -sm test2 -./ma_test2$suffix $silent -L -K -W -P -A -./maria_chk$suffix -sm test2 ./ma_test2$suffix $silent -L -K -W -P -S -R1 -m500 -echo "ma_test2$suffix $silent -L -K -R1 -m2000 ; Should give error 135" ./maria_chk$suffix -sm test2 +echo "ma_test2$suffix $silent -L -K -R1 -m2000 ; Should give error 135" ./ma_test2$suffix $silent -L -K -R1 -m2000 +echo "./maria_chk$suffix -sm test2 will warn that 'Datafile is almost full'" ./maria_chk$suffix -sm test2 -./ma_test2$suffix $silent -L -K -P -S -R3 -m50 -b1000000 -./maria_chk$suffix -sm test2 -./ma_test2$suffix $silent -L -B -./maria_chk$suffix -sm test2 -./ma_test2$suffix $silent -D -B -c -./maria_chk$suffix -sm test2 -./ma_test2$suffix $silent -m10000 -e8192 -K -./maria_chk$suffix -sm test2 -./ma_test2$suffix $silent -m10000 -e16384 -E16384 -K -L -./maria_chk$suffix -sm test2 +./maria_chk$suffix -ssm test2 -./ma_test2$suffix $silent -L -K -W -P -m50 -l -./maria_log$suffix -./ma_test2$suffix $silent -L -K -W -P -m50 -l -b100 -./maria_log$suffix +# +# Some timing tests +# time ./ma_test2$suffix $silent +time ./ma_test2$suffix $silent -S +time ./ma_test2$suffix $silent -M +time ./ma_test2$suffix $silent -B +time ./ma_test2$suffix $silent -L +time ./ma_test2$suffix $silent -K time ./ma_test2$suffix $silent -K -B time ./ma_test2$suffix $silent -L -B time ./ma_test2$suffix $silent -L -K -B time ./ma_test2$suffix $silent -L -K -W -B -time ./ma_test2$suffix $silent -L -K -W -S -B -time ./ma_test2$suffix $silent -D -K -W -S -B +time ./ma_test2$suffix $silent -L -K -W -B -S +time ./ma_test2$suffix $silent -L -K -W -B -M +time ./ma_test2$suffix $silent -D -K -W -B -S diff --git a/storage/maria/ma_unique.c b/storage/maria/ma_unique.c index bc1aa71966b..8348bfbd84b 100644 --- a/storage/maria/ma_unique.c +++ b/storage/maria/ma_unique.c @@ -22,10 +22,11 @@ my_bool _ma_check_unique(MARIA_HA *info, MARIA_UNIQUEDEF *def, byte *record, ha_checksum unique_hash, my_off_t disk_pos) { - my_off_t lastpos=info->lastpos; + my_off_t lastpos=info->cur_row.lastpos; MARIA_KEYDEF *key= &info->s->keyinfo[def->key]; - uchar *key_buff=info->lastkey2; + byte *key_buff= info->lastkey2; DBUG_ENTER("_ma_check_unique"); + DBUG_PRINT("enter",("unique_hash: %lu", unique_hash)); maria_unique_store(record+key->seg->start, unique_hash); _ma_make_key(info,def->key,key_buff,record,0); @@ -33,24 +34,25 @@ my_bool _ma_check_unique(MARIA_HA *info, MARIA_UNIQUEDEF *def, byte *record, /* The above changed info->lastkey2. Inform maria_rnext_same(). */ info->update&= ~HA_STATE_RNEXT_SAME; - if (_ma_search(info,info->s->keyinfo+def->key,key_buff,MARIA_UNIQUE_HASH_LENGTH, + if (_ma_search(info,info->s->keyinfo+def->key,key_buff, + MARIA_UNIQUE_HASH_LENGTH, SEARCH_FIND,info->s->state.key_root[def->key])) { info->page_changed=1; /* Can't optimize read next */ - info->lastpos= lastpos; + info->cur_row.lastpos= lastpos; DBUG_RETURN(0); /* No matching rows */ } for (;;) { - if (info->lastpos != disk_pos && - !(*info->s->compare_unique)(info,def,record,info->lastpos)) + if (info->cur_row.lastpos != disk_pos && + !(*info->s->compare_unique)(info,def,record,info->cur_row.lastpos)) { my_errno=HA_ERR_FOUND_DUPP_UNIQUE; info->errkey= (int) def->key; - info->dupp_key_pos= info->lastpos; - info->page_changed=1; /* Can't optimize read next */ - info->lastpos=lastpos; + info->dup_key_pos= info->cur_row.lastpos; + info->page_changed= 1; /* Can't optimize read next */ + info->cur_row.lastpos= lastpos; DBUG_PRINT("info",("Found duplicate")); DBUG_RETURN(1); /* Found identical */ } @@ -60,8 +62,8 @@ my_bool _ma_check_unique(MARIA_HA *info, MARIA_UNIQUEDEF *def, byte *record, memcmp((char*) info->lastkey, (char*) key_buff, MARIA_UNIQUE_HASH_LENGTH)) { - info->page_changed=1; /* Can't optimize read next */ - info->lastpos=lastpos; + info->page_changed= 1; /* Can't optimize read next */ + info->cur_row.lastpos= lastpos; DBUG_RETURN(0); /* end of tree */ } } @@ -144,11 +146,11 @@ ha_checksum _ma_unique_hash(MARIA_UNIQUEDEF *def, const byte *record) RETURN 0 if both rows have equal unique value - # Rows are different + 1 Rows are different */ -int _ma_unique_comp(MARIA_UNIQUEDEF *def, const byte *a, const byte *b, - my_bool null_are_equal) +my_bool _ma_unique_comp(MARIA_UNIQUEDEF *def, const byte *a, const byte *b, + my_bool null_are_equal) { const byte *pos_a, *pos_b, *end; HA_KEYSEG *keyseg; diff --git a/storage/maria/ma_update.c b/storage/maria/ma_update.c index 248b17ce2c9..c86ebd16c6f 100644 --- a/storage/maria/ma_update.c +++ b/storage/maria/ma_update.c @@ -24,7 +24,7 @@ int maria_update(register MARIA_HA *info, const byte *oldrec, byte *newrec) int flag,key_changed,save_errno; reg3 my_off_t pos; uint i; - uchar old_key[HA_MAX_KEY_BUFF],*new_key; + byte old_key[HA_MAX_KEY_BUFF],*new_key; bool auto_key_changed=0; ulonglong changed; MARIA_SHARE *share=info->s; @@ -49,18 +49,26 @@ int maria_update(register MARIA_HA *info, const byte *oldrec, byte *newrec) { DBUG_RETURN(my_errno=HA_ERR_INDEX_FILE_FULL); } - pos=info->lastpos; + pos= info->cur_row.lastpos; if (_ma_readinfo(info,F_WRLCK,1)) DBUG_RETURN(my_errno); - if (share->calc_checksum) - old_checksum=info->checksum=(*share->calc_checksum)(info,oldrec); if ((*share->compare_record)(info,oldrec)) { - save_errno=my_errno; + save_errno= my_errno; + DBUG_PRINT("warning", ("Got error from compare record")); goto err_end; /* Record has changed */ } + if (share->calc_checksum) + { + /* + We can't use the row based checksum as this doesn't have enough + precision. + */ + if (info->s->calc_checksum) + old_checksum= (*info->s->calc_checksum)(info, oldrec); + } /* Calculate and check all unique constraints */ key_changed=0; @@ -69,7 +77,7 @@ int maria_update(register MARIA_HA *info, const byte *oldrec, byte *newrec) MARIA_UNIQUEDEF *def=share->uniqueinfo+i; if (_ma_unique_comp(def, newrec, oldrec,1) && _ma_check_unique(info, def, newrec, _ma_unique_hash(def, newrec), - info->lastpos)) + pos)) { save_errno=my_errno; goto err_end; @@ -83,7 +91,7 @@ int maria_update(register MARIA_HA *info, const byte *oldrec, byte *newrec) /* Check which keys changed from the original row */ - new_key=info->lastkey2; + new_key= info->lastkey2; changed=0; for (i=0 ; i < share->base.keys ; i++) { @@ -116,7 +124,7 @@ int maria_update(register MARIA_HA *info, const byte *oldrec, byte *newrec) info->update&= ~HA_STATE_RNEXT_SAME; if (new_length != old_length || - memcmp((byte*) old_key,(byte*) new_key,new_length)) + memcmp(old_key, new_key, new_length)) { if ((int) i == info->lastinx) key_changed|=HA_STATE_WRITTEN; /* Mark that keyfile changed */ @@ -139,7 +147,7 @@ int maria_update(register MARIA_HA *info, const byte *oldrec, byte *newrec) if (share->calc_checksum) { - info->checksum=(*share->calc_checksum)(info,newrec); + info->cur_row.checksum= (*share->calc_checksum)(info,newrec); /* Store new checksum in index file header */ key_changed|= HA_STATE_CHANGED; } @@ -167,10 +175,13 @@ int maria_update(register MARIA_HA *info, const byte *oldrec, byte *newrec) set_if_bigger(info->s->state.auto_increment, ma_retrieve_auto_increment(info, newrec)); if (share->calc_checksum) - info->state->checksum+=(info->checksum - old_checksum); + info->state->checksum+= (info->cur_row.checksum - old_checksum); - info->update= (HA_STATE_CHANGED | HA_STATE_ROW_CHANGED | HA_STATE_AKTIV | - key_changed); + /* + We can't yet have HA_STATE_ACTIVE here, as block_record dosn't support + it + */ + info->update= (HA_STATE_CHANGED | HA_STATE_ROW_CHANGED | key_changed); VOID(_ma_writeinfo(info,key_changed ? WRITEINFO_UPDATE_KEYFILE : 0)); allow_break(); /* Allow SIGHUP & SIGINT */ if (info->invalidator != 0) @@ -184,8 +195,6 @@ int maria_update(register MARIA_HA *info, const byte *oldrec, byte *newrec) err: DBUG_PRINT("error",("key: %d errno: %d",i,my_errno)); save_errno=my_errno; - if (changed) - key_changed|= HA_STATE_CHANGED; if (my_errno == HA_ERR_FOUND_DUPP_KEY || my_errno == HA_ERR_RECORD_FILE_FULL) { info->errkey= (int) i; diff --git a/storage/maria/ma_write.c b/storage/maria/ma_write.c index 24768b36c89..a4fe5506c8e 100644 --- a/storage/maria/ma_write.c +++ b/storage/maria/ma_write.c @@ -24,33 +24,52 @@ /* Functions declared in this file */ static int w_search(MARIA_HA *info,MARIA_KEYDEF *keyinfo, - uint comp_flag, uchar *key, - uint key_length, my_off_t pos, uchar *father_buff, - uchar *father_keypos, my_off_t father_page, + uint comp_flag, byte *key, + uint key_length, my_off_t pos, byte *father_buff, + byte *father_keypos, my_off_t father_page, my_bool insert_last); -static int _ma_balance_page(MARIA_HA *info,MARIA_KEYDEF *keyinfo,uchar *key, - uchar *curr_buff,uchar *father_buff, - uchar *father_keypos,my_off_t father_page); -static uchar *_ma_find_last_pos(MARIA_KEYDEF *keyinfo, uchar *page, - uchar *key, uint *return_key_length, - uchar **after_key); -int _ma_ck_write_tree(register MARIA_HA *info, uint keynr,uchar *key, +static int _ma_balance_page(MARIA_HA *info,MARIA_KEYDEF *keyinfo,byte *key, + byte *curr_buff,byte *father_buff, + byte *father_keypos,my_off_t father_page); +static byte *_ma_find_last_pos(MARIA_KEYDEF *keyinfo, byte *page, + byte *key, uint *return_key_length, + byte **after_key); +int _ma_ck_write_tree(register MARIA_HA *info, uint keynr,byte *key, uint key_length); -int _ma_ck_write_btree(register MARIA_HA *info, uint keynr,uchar *key, +int _ma_ck_write_btree(register MARIA_HA *info, uint keynr,byte *key, uint key_length); - /* Write new record to database */ + +MARIA_RECORD_POS _ma_write_init_default(MARIA_HA *info, + const byte *record + __attribute__((unused))) +{ + return ((info->s->state.dellink != HA_OFFSET_ERROR && + !info->append_insert_at_end) ? + info->s->state.dellink : + info->state->data_file_length); +} + +my_bool _ma_write_abort_default(MARIA_HA *info __attribute__((unused))) +{ + return 0; +} + + +/* Write new record to a table */ int maria_write(MARIA_HA *info, byte *record) { MARIA_SHARE *share=info->s; uint i; int save_errno; - my_off_t filepos; - uchar *buff; + MARIA_RECORD_POS filepos; + byte *buff; my_bool lock_tree= share->concurrent_insert; + my_bool fatal_error; DBUG_ENTER("maria_write"); - DBUG_PRINT("enter",("isam: %d data: %d",info->s->kfile,info->dfile)); + DBUG_PRINT("enter",("index_file: %d data_file: %d", + info->s->kfile,info->dfile)); DBUG_EXECUTE_IF("maria_pretend_crashed_table_on_usage", maria_print_error(info->s, HA_ERR_CRASHED); @@ -62,10 +81,6 @@ int maria_write(MARIA_HA *info, byte *record) if (_ma_readinfo(info,F_WRLCK,1)) DBUG_RETURN(my_errno); dont_break(); /* Dont allow SIGHUP or SIGINT */ - filepos= ((share->state.dellink != HA_OFFSET_ERROR && - !info->append_insert_at_end) ? - share->state.dellink : - info->state->data_file_length); if (share->base.reloc == (ha_rows) 1 && share->base.records == (ha_rows) 1 && @@ -86,14 +101,26 @@ int maria_write(MARIA_HA *info, byte *record) for (i=0 ; i < share->state.header.uniques ; i++) { if (_ma_check_unique(info,share->uniqueinfo+i,record, - _ma_unique_hash(share->uniqueinfo+i,record), - HA_OFFSET_ERROR)) + _ma_unique_hash(share->uniqueinfo+i,record), + HA_OFFSET_ERROR)) goto err2; } - /* Write all keys to indextree */ + if ((info->opt_flag & OPT_NO_ROWS)) + filepos= HA_OFFSET_ERROR; + else + { + /* + This may either calculate a record or, or write the record and return + the record id + */ + if ((filepos= (*share->write_record_init)(info, record)) == + HA_OFFSET_ERROR) + goto err2; + } - buff=info->lastkey2; + /* Write all keys to indextree */ + buff= info->lastkey2; for (i=0 ; i < share->base.keys ; i++) { if (maria_is_key_active(share->state.key_map, i)) @@ -136,13 +163,13 @@ int maria_write(MARIA_HA *info, byte *record) rw_unlock(&share->key_root_lock[i]); } } - if (share->calc_checksum) - info->checksum=(*share->calc_checksum)(info,record); - if (!(info->opt_flag & OPT_NO_ROWS)) + if (share->calc_write_checksum) + info->cur_row.checksum= (*share->calc_write_checksum)(info,record); + if (filepos != HA_OFFSET_ERROR) { if ((*share->write_record)(info,record)) goto err; - info->state->checksum+=info->checksum; + info->state->checksum+= info->cur_row.checksum; } if (share->base.auto_key) set_if_bigger(info->s->state.auto_increment, @@ -150,7 +177,7 @@ int maria_write(MARIA_HA *info, byte *record) info->update= (HA_STATE_CHANGED | HA_STATE_AKTIV | HA_STATE_WRITTEN | HA_STATE_ROW_CHANGED); info->state->records++; - info->lastpos=filepos; + info->cur_row.lastpos= filepos; VOID(_ma_writeinfo(info, WRITEINFO_UPDATE_KEYFILE)); if (info->invalidator != 0) { @@ -162,8 +189,10 @@ int maria_write(MARIA_HA *info, byte *record) DBUG_RETURN(0); err: - save_errno=my_errno; - if (my_errno == HA_ERR_FOUND_DUPP_KEY || my_errno == HA_ERR_RECORD_FILE_FULL || + save_errno= my_errno; + fatal_error= 0; + if (my_errno == HA_ERR_FOUND_DUPP_KEY || + my_errno == HA_ERR_RECORD_FILE_FULL || my_errno == HA_ERR_NULL_IN_SPATIAL) { if (info->bulk_insert) @@ -207,14 +236,21 @@ err: } } else + fatal_error= 1; + + if ((*share->write_record_abort)(info)) + fatal_error= 1; + if (fatal_error) { maria_print_error(info->s, HA_ERR_CRASHED); maria_mark_crashed(info); } + info->update= (HA_STATE_CHANGED | HA_STATE_WRITTEN | HA_STATE_ROW_CHANGED); my_errno=save_errno; err2: save_errno=my_errno; + DBUG_PRINT("error", ("got error: %d", save_errno)); VOID(_ma_writeinfo(info,WRITEINFO_UPDATE_KEYFILE)); allow_break(); /* Allow SIGHUP & SIGINT */ DBUG_RETURN(my_errno=save_errno); @@ -223,7 +259,7 @@ err2: /* Write one key to btree */ -int _ma_ck_write(MARIA_HA *info, uint keynr, uchar *key, uint key_length) +int _ma_ck_write(MARIA_HA *info, uint keynr, byte *key, uint key_length) { DBUG_ENTER("_ma_ck_write"); @@ -242,7 +278,7 @@ int _ma_ck_write(MARIA_HA *info, uint keynr, uchar *key, uint key_length) * Normal insert code * **********************************************************************/ -int _ma_ck_write_btree(register MARIA_HA *info, uint keynr, uchar *key, +int _ma_ck_write_btree(register MARIA_HA *info, uint keynr, byte *key, uint key_length) { int error; @@ -275,15 +311,17 @@ int _ma_ck_write_btree(register MARIA_HA *info, uint keynr, uchar *key, DBUG_RETURN(error); } /* _ma_ck_write_btree */ + int _ma_ck_real_write_btree(MARIA_HA *info, MARIA_KEYDEF *keyinfo, - uchar *key, uint key_length, my_off_t *root, uint comp_flag) + byte *key, uint key_length, my_off_t *root, + uint comp_flag) { int error; DBUG_ENTER("_ma_ck_real_write_btree"); /* key_length parameter is used only if comp_flag is SEARCH_FIND */ if (*root == HA_OFFSET_ERROR || (error=w_search(info, keyinfo, comp_flag, key, key_length, - *root, (uchar *) 0, (uchar*) 0, + *root, (byte*) 0, (byte*) 0, (my_off_t) 0, 1)) > 0) error= _ma_enlarge_root(info,keyinfo,key,root); DBUG_RETURN(error); @@ -292,7 +330,7 @@ int _ma_ck_real_write_btree(MARIA_HA *info, MARIA_KEYDEF *keyinfo, /* Make a new root with key as only pointer */ -int _ma_enlarge_root(MARIA_HA *info, MARIA_KEYDEF *keyinfo, uchar *key, +int _ma_enlarge_root(MARIA_HA *info, MARIA_KEYDEF *keyinfo, byte *key, my_off_t *root) { uint t_length,nod_flag; @@ -302,11 +340,11 @@ int _ma_enlarge_root(MARIA_HA *info, MARIA_KEYDEF *keyinfo, uchar *key, nod_flag= (*root != HA_OFFSET_ERROR) ? share->base.key_reflength : 0; _ma_kpointer(info,info->buff+2,*root); /* if nod */ - t_length=(*keyinfo->pack_key)(keyinfo,nod_flag,(uchar*) 0, - (uchar*) 0, (uchar*) 0, key,&s_temp); + t_length=(*keyinfo->pack_key)(keyinfo,nod_flag,(byte*) 0, + (byte*) 0, (byte*) 0, key,&s_temp); maria_putint(info->buff,t_length+2+nod_flag,nod_flag); (*keyinfo->store_key)(keyinfo,info->buff+2+nod_flag,&s_temp); - info->buff_used=info->page_changed=1; /* info->buff is used */ + info->keybuff_used=info->page_changed=1; /* info->buff is used */ if ((*root= _ma_new(info,keyinfo,DFLT_INIT_HITS)) == HA_OFFSET_ERROR || _ma_write_keypage(info,keyinfo,*root,DFLT_INIT_HITS,info->buff)) DBUG_RETURN(-1); @@ -322,21 +360,21 @@ int _ma_enlarge_root(MARIA_HA *info, MARIA_KEYDEF *keyinfo, uchar *key, */ static int w_search(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo, - uint comp_flag, uchar *key, uint key_length, my_off_t page, - uchar *father_buff, uchar *father_keypos, + uint comp_flag, byte *key, uint key_length, my_off_t page, + byte *father_buff, byte *father_keypos, my_off_t father_page, my_bool insert_last) { int error,flag; uint nod_flag, search_key_length; - uchar *temp_buff,*keypos; - uchar keybuff[HA_MAX_KEY_BUFF]; + byte *temp_buff,*keypos; + byte keybuff[HA_MAX_KEY_BUFF]; my_bool was_last_key; - my_off_t next_page, dupp_key_pos; + my_off_t next_page, dup_key_pos; DBUG_ENTER("w_search"); DBUG_PRINT("enter",("page: %ld",page)); search_key_length= (comp_flag & SEARCH_FIND) ? key_length : USE_WHOLE_KEY; - if (!(temp_buff= (uchar*) my_alloca((uint) keyinfo->block_length+ + if (!(temp_buff= (byte*) my_alloca((uint) keyinfo->block_length+ HA_MAX_KEY_BUFF*2))) DBUG_RETURN(-1); if (!_ma_fetch_keypage(info,keyinfo,page,DFLT_INIT_HITS,temp_buff,0)) @@ -351,9 +389,9 @@ static int w_search(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo, /* get position to record with duplicated key */ tmp_key_length=(*keyinfo->get_key)(keyinfo,nod_flag,&keypos,keybuff); if (tmp_key_length) - dupp_key_pos= _ma_dpos(info,0,keybuff+tmp_key_length); + dup_key_pos= _ma_dpos(info,0,keybuff+tmp_key_length); else - dupp_key_pos= HA_OFFSET_ERROR; + dup_key_pos= HA_OFFSET_ERROR; if (keyinfo->flag & HA_FULLTEXT) { @@ -373,7 +411,7 @@ static int w_search(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo, else { /* popular word. two-level tree. going down */ - my_off_t root=dupp_key_pos; + my_off_t root=dup_key_pos; keyinfo=&info->s->ft2_keyinfo; get_key_full_length_rdonly(off, key); key+=off; @@ -392,7 +430,7 @@ static int w_search(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo, } else /* not HA_FULLTEXT, normal HA_NOSAME key */ { - info->dupp_key_pos= dupp_key_pos; + info->dup_key_pos= dup_key_pos; my_afree((byte*) temp_buff); my_errno=HA_ERR_FOUND_DUPP_KEY; DBUG_RETURN(-1); @@ -447,25 +485,25 @@ err: */ int _ma_insert(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo, - uchar *key, uchar *anc_buff, uchar *key_pos, uchar *key_buff, - uchar *father_buff, uchar *father_key_pos, my_off_t father_page, + byte *key, byte *anc_buff, byte *key_pos, byte *key_buff, + byte *father_buff, byte *father_key_pos, my_off_t father_page, my_bool insert_last) { uint a_length,nod_flag; int t_length; - uchar *endpos, *prev_key; + byte *endpos, *prev_key; MARIA_KEY_PARAM s_temp; DBUG_ENTER("_ma_insert"); - DBUG_PRINT("enter",("key_pos: %lx",key_pos)); + DBUG_PRINT("enter",("key_pos: 0x%lx", (ulong) key_pos)); DBUG_EXECUTE("key", _ma_print_key(DBUG_FILE,keyinfo->seg,key, USE_WHOLE_KEY);); nod_flag=_ma_test_if_nod(anc_buff); a_length=maria_getint(anc_buff); endpos= anc_buff+ a_length; - prev_key=(key_pos == anc_buff+2+nod_flag ? (uchar*) 0 : key_buff); + prev_key=(key_pos == anc_buff+2+nod_flag ? (byte*) 0 : key_buff); t_length=(*keyinfo->pack_key)(keyinfo,nod_flag, - (key_pos == endpos ? (uchar*) 0 : key_pos), + (key_pos == endpos ? (byte*) 0 : key_pos), prev_key, prev_key, key,&s_temp); #ifndef DBUG_OFF @@ -478,7 +516,7 @@ int _ma_insert(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo, { DBUG_PRINT("test",("t_length: %d ref_len: %d", t_length,s_temp.ref_length)); - DBUG_PRINT("test",("n_ref_len: %d n_length: %d key_pos: %lx", + DBUG_PRINT("test",("n_ref_len: %d n_length: %d key_pos: 0x%lx", s_temp.n_ref_length,s_temp.n_length,s_temp.key)); } #endif @@ -517,19 +555,20 @@ int _ma_insert(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo, Let's consider converting. We'll compare 'key' and the first key at anc_buff */ - uchar *a=key, *b=anc_buff+2+nod_flag; + byte *a=key, *b=anc_buff+2+nod_flag; uint alen, blen, ft2len=info->s->ft2_keyinfo.keylength; /* the very first key on the page is always unpacked */ DBUG_ASSERT((*b & 128) == 0); #if HA_FT_MAXLEN >= 127 blen= mi_uint2korr(b); b+=2; #else - blen= *b++; + blen= *(uchar*) b++; #endif get_key_length(alen,a); DBUG_ASSERT(info->ft1_to_ft2==0); if (alen == blen && - ha_compare_text(keyinfo->seg->charset, a, alen, b, blen, 0, 0)==0) + ha_compare_text(keyinfo->seg->charset, (uchar*) a, alen, + (uchar*) b, blen, 0, 0) == 0) { /* yup. converting */ info->ft1_to_ft2=(DYNAMIC_ARRAY *) @@ -570,11 +609,11 @@ int _ma_insert(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo, /* split a full page in two and assign emerging item to key */ int _ma_split_page(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo, - uchar *key, uchar *buff, uchar *key_buff, + byte *key, byte *buff, byte *key_buff, my_bool insert_last_key) { uint length,a_length,key_ref_length,t_length,nod_flag,key_length; - uchar *key_pos,*pos, *after_key; + byte *key_pos,*pos, *after_key; my_off_t new_pos; MARIA_KEY_PARAM s_temp; DBUG_ENTER("maria_split_page"); @@ -582,7 +621,7 @@ int _ma_split_page(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo, if (info->s->keyinfo+info->lastinx == keyinfo) info->page_changed=1; /* Info->buff is used */ - info->buff_used=1; + info->keybuff_used=1; nod_flag=_ma_test_if_nod(buff); key_ref_length=2+nod_flag; if (insert_last_key) @@ -614,8 +653,8 @@ int _ma_split_page(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo, if (!(*keyinfo->get_key)(keyinfo,nod_flag,&key_pos,key_buff)) DBUG_RETURN(-1); - t_length=(*keyinfo->pack_key)(keyinfo,nod_flag,(uchar *) 0, - (uchar*) 0, (uchar*) 0, + t_length=(*keyinfo->pack_key)(keyinfo,nod_flag,(byte *) 0, + (byte*) 0, (byte*) 0, key_buff, &s_temp); length=(uint) ((buff+a_length)-key_pos); memcpy((byte*) info->buff+key_ref_length+t_length,(byte*) key_pos, @@ -638,12 +677,12 @@ int _ma_split_page(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo, after_key will contain the position to where the next key starts */ -uchar *_ma_find_half_pos(uint nod_flag, MARIA_KEYDEF *keyinfo, uchar *page, - uchar *key, uint *return_key_length, - uchar **after_key) +byte *_ma_find_half_pos(uint nod_flag, MARIA_KEYDEF *keyinfo, byte *page, + byte *key, uint *return_key_length, + byte **after_key) { uint keys,length,key_ref_length; - uchar *end,*lastpos; + byte *end,*lastpos; DBUG_ENTER("_ma_find_half_pos"); key_ref_length=2+nod_flag; @@ -672,24 +711,25 @@ uchar *_ma_find_half_pos(uint nod_flag, MARIA_KEYDEF *keyinfo, uchar *page, } while (page < end); *return_key_length=length; *after_key=page; - DBUG_PRINT("exit",("returns: %lx page: %lx half: %lx",lastpos,page,end)); + DBUG_PRINT("exit",("returns: 0x%lx page: 0x%lx half: 0x%lx", + lastpos, page, end)); DBUG_RETURN(lastpos); } /* _ma_find_half_pos */ - /* - Split buffer at last key - Returns pointer to the start of the key before the last key - key will contain the last key - */ +/* + Split buffer at last key + Returns pointer to the start of the key before the last key + key will contain the last key +*/ -static uchar *_ma_find_last_pos(MARIA_KEYDEF *keyinfo, uchar *page, - uchar *key, uint *return_key_length, - uchar **after_key) +static byte *_ma_find_last_pos(MARIA_KEYDEF *keyinfo, byte *page, + byte *key, uint *return_key_length, + byte **after_key) { uint keys,length,last_length,key_ref_length; - uchar *end,*lastpos,*prevpos; - uchar key_buff[HA_MAX_KEY_BUFF]; + byte *end,*lastpos,*prevpos; + byte key_buff[HA_MAX_KEY_BUFF]; DBUG_ENTER("_ma_find_last_pos"); key_ref_length=2; @@ -727,7 +767,8 @@ static uchar *_ma_find_last_pos(MARIA_KEYDEF *keyinfo, uchar *page, } *return_key_length=last_length; *after_key=lastpos; - DBUG_PRINT("exit",("returns: %lx page: %lx end: %lx",prevpos,page,end)); + DBUG_PRINT("exit",("returns: 0x%lx page: 0x%lx end: 0x%lx", + prevpos, page, end)); DBUG_RETURN(prevpos); } /* _ma_find_last_pos */ @@ -736,14 +777,14 @@ static uchar *_ma_find_last_pos(MARIA_KEYDEF *keyinfo, uchar *page, /* returns 0 if balance was done */ static int _ma_balance_page(register MARIA_HA *info, MARIA_KEYDEF *keyinfo, - uchar *key, uchar *curr_buff, uchar *father_buff, - uchar *father_key_pos, my_off_t father_page) + byte *key, byte *curr_buff, byte *father_buff, + byte *father_key_pos, my_off_t father_page) { my_bool right; uint k_length,father_length,father_keylength,nod_flag,curr_keylength, right_length,left_length,new_right_length,new_left_length,extra_length, length,keys; - uchar *pos,*buff,*extra_buff; + byte *pos,*buff,*extra_buff; my_off_t next_page,new_pos; byte tmp_part_key[HA_MAX_KEY_BUFF]; DBUG_ENTER("_ma_balance_page"); @@ -880,7 +921,8 @@ typedef struct { uint keynr; } bulk_insert_param; -int _ma_ck_write_tree(register MARIA_HA *info, uint keynr, uchar *key, + +int _ma_ck_write_tree(register MARIA_HA *info, uint keynr, byte *key, uint key_length) { int error; @@ -896,22 +938,22 @@ int _ma_ck_write_tree(register MARIA_HA *info, uint keynr, uchar *key, /* typeof(_ma_keys_compare)=qsort_cmp2 */ -static int keys_compare(bulk_insert_param *param, uchar *key1, uchar *key2) +static int keys_compare(bulk_insert_param *param, byte *key1, byte *key2) { uint not_used[2]; return ha_key_cmp(param->info->s->keyinfo[param->keynr].seg, - key1, key2, USE_WHOLE_KEY, SEARCH_SAME, + (uchar*) key1, (uchar*) key2, USE_WHOLE_KEY, SEARCH_SAME, not_used); } -static int keys_free(uchar *key, TREE_FREE mode, bulk_insert_param *param) +static int keys_free(byte *key, TREE_FREE mode, bulk_insert_param *param) { /* Probably I can use info->lastkey here, but I'm not sure, and to be safe I'd better use local lastkey. */ - uchar lastkey[HA_MAX_KEY_BUFF]; + byte lastkey[HA_MAX_KEY_BUFF]; uint keylen; MARIA_KEYDEF *keyinfo; diff --git a/storage/maria/maria_chk.c b/storage/maria/maria_chk.c index e423a3f5c36..8ea00fa9776 100644 --- a/storage/maria/maria_chk.c +++ b/storage/maria/maria_chk.c @@ -36,21 +36,23 @@ SET_STACK_SIZE(9000) /* Minimum stack size for program */ static uint decode_bits; static char **default_argv; -static const char *load_default_groups[]= { "mariachk", 0 }; +static const char *load_default_groups[]= { "maria_chk", 0 }; static const char *set_collation_name, *opt_tmpdir; static CHARSET_INFO *set_collation; static long opt_maria_block_size; static long opt_key_cache_block_size; static const char *my_progname_short; static int stopwords_inited= 0; -static MY_TMPDIR mariachk_tmpdir; +static MY_TMPDIR maria_chk_tmpdir; static const char *type_names[]= -{ "impossible","char","binary", "short", "long", "float", +{ + "impossible","char","binary", "short", "long", "float", "double","number","unsigned short", "unsigned long","longlong","ulonglong","int24", "uint24","int8","varchar", "varbin","?", - "?"}; + "?" +}; static const char *prefix_packed_txt="packed ", *bin_packed_txt="prefix ", @@ -59,23 +61,30 @@ static const char *prefix_packed_txt="packed ", *blob_txt="BLOB "; static const char *field_pack[]= -{"","no endspace", "no prespace", +{ + "","no endspace", "no prespace", "no zeros", "blob", "constant", "table-lockup", - "always zero","varchar","unique-hash","?","?"}; + "always zero","varchar","unique-hash","?","?" +}; + +static const char *record_formats[]= +{ + "Fixed length", "Packed", "Compressed", "Block", "?" +}; static const char *maria_stats_method_str="nulls_unequal"; static void get_options(int *argc,char * * *argv); static void print_version(void); static void usage(void); -static int mariachk(HA_CHECK *param, char *filename); +static int maria_chk(HA_CHECK *param, char *filename); static void descript(HA_CHECK *param, register MARIA_HA *info, my_string name); static int maria_sort_records(HA_CHECK *param, register MARIA_HA *info, - my_string name, uint sort_key, - my_bool write_info, my_bool update_index); + my_string name, uint sort_key, + my_bool write_info, my_bool update_index); static int sort_record_index(MARIA_SORT_PARAM *sort_param, MARIA_HA *info, MARIA_KEYDEF *keyinfo, - my_off_t page,uchar *buff,uint sortkey, + my_off_t page, byte *buff,uint sortkey, File new_file, my_bool update_index); HA_CHECK check_param; @@ -88,7 +97,7 @@ int main(int argc, char **argv) MY_INIT(argv[0]); my_progname_short= my_progname+dirname_length(my_progname); - mariachk_init(&check_param); + maria_chk_init(&check_param); check_param.opt_lock_memory= 1; /* Lock memory if possible */ check_param.using_global_keycache = 0; get_options(&argc,(char***) &argv); @@ -98,7 +107,7 @@ int main(int argc, char **argv) while (--argc >= 0) { - int new_error=mariachk(&check_param, *(argv++)); + int new_error=maria_chk(&check_param, *(argv++)); if ((check_param.testflag & T_REP_ANY) != T_REP) check_param.testflag&= ~T_REP; VOID(fflush(stdout)); @@ -112,7 +121,7 @@ int main(int argc, char **argv) if (!(check_param.testflag & T_REP)) check_param.testflag|= T_REP_BY_SORT; check_param.testflag&= ~T_EXTEND; /* Don't needed */ - error|=mariachk(&check_param, argv[-1]); + error|=maria_chk(&check_param, argv[-1]); check_param.testflag= old_testflag; VOID(fflush(stdout)); VOID(fflush(stderr)); @@ -134,7 +143,7 @@ int main(int argc, char **argv) llstr(check_param.total_deleted,buff2)); } free_defaults(default_argv); - free_tmpdir(&mariachk_tmpdir); + free_tmpdir(&maria_chk_tmpdir); maria_end(); my_end(check_param.testflag & T_INFO ? MY_CHECK_ERROR | MY_GIVE_INFO : MY_CHECK_ERROR); @@ -218,7 +227,7 @@ static struct my_option my_long_options[] = (gptr*) &check_param.keys_in_use, 0, GET_ULL, REQUIRED_ARG, -1, 0, 0, 0, 0, 0}, {"max-record-length", OPT_MAX_RECORD_LENGTH, - "Skip rows bigger than this if mariachk can't allocate memory to hold it", + "Skip rows bigger than this if maria_chk can't allocate memory to hold it", (gptr*) &check_param.max_record_length, (gptr*) &check_param.max_record_length, 0, GET_ULL, REQUIRED_ARG, LONGLONG_MAX, 0, LONGLONG_MAX, 0, 0, 0}, @@ -259,7 +268,7 @@ static struct my_option my_long_options[] = "Change the value of a variable. Please note that this option is deprecated; you can set variables directly with --variable-name=value.", 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"silent", 's', - "Only print errors. One can use two -s to make mariachk very silent.", + "Only print errors. One can use two -s to make maria_chk very silent.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, {"sort-index", 'S', "Sort index blocks. This speeds up 'read-next' in applications.", @@ -346,7 +355,7 @@ static struct my_option my_long_options[] = static void print_version(void) { - printf("%s Ver 2.7 for %s at %s\n", my_progname, SYSTEM_TYPE, + printf("%s Ver 1.0 for %s at %s\n", my_progname, SYSTEM_TYPE, MACHINE_TYPE); NETWARE_SET_SCREEN_MODE(1); } @@ -381,7 +390,7 @@ static void usage(void) printf(", they will be used\n\ in a round-robin fashion.\n\ -s, --silent Only print errors. One can use two -s to make\n\ - mariachk very silent.\n\ + maria_chk very silent.\n\ -v, --verbose Print more information. This can be used with\n\ --description and --check. Use many -v for more verbosity.\n\ -V, --version Print version and exit.\n\ @@ -390,10 +399,10 @@ static void usage(void) puts(" --start-check-pos=# Start reading file at given offset.\n"); #endif - puts("Check options (check is the default action for mariachk):\n\ + puts("Check options (check is the default action for maria_chk):\n\ -c, --check Check table for errors.\n\ -e, --extend-check Check the table VERY throughly. Only use this in\n\ - extreme cases as mariachk should normally be able to\n\ + extreme cases as maria_chk should normally be able to\n\ find out if the table is ok even without this switch.\n\ -F, --fast Check only tables that haven't been closed properly.\n\ -C, --check-only-changed\n\ @@ -419,7 +428,7 @@ static void usage(void) bit mask of which keys to use. This can be used to\n\ get faster inserts.\n\ --max-record-length=#\n\ - Skip rows bigger than this if mariachk can't allocate\n\ + Skip rows bigger than this if maria_chk can't allocate\n\ memory to hold it.\n\ -r, --recover Can fix almost anything except unique keys that aren't\n\ unique.\n\ @@ -436,7 +445,7 @@ static void usage(void) --set-collation=name\n\ Change the collation used by the index.\n\ -q, --quick Faster repair by not modifying the data file.\n\ - One can give a second '-q' to force mariachk to\n\ + One can give a second '-q' to force maria_chk to\n\ modify the original datafile in case of duplicate keys.\n\ NOTE: Tables where the data file is currupted can't be\n\ fixed with this option.\n\ @@ -684,7 +693,7 @@ get_one_option(int optid, } else { - DBUG_PUSH(argument ? argument : "d:t:o,/tmp/mariachk.trace"); + DBUG_PUSH(argument ? argument : "d:t:o,/tmp/maria_chk.trace"); } break; case 'V': @@ -700,6 +709,7 @@ get_one_option(int optid, { int method; enum_handler_stats_method method_conv; + LINT_INIT(method_conv); maria_stats_method_str= argument; if ((method=find_type(argument, &maria_stats_method_typelib, 2)) <= 0) { @@ -778,10 +788,10 @@ static void get_options(register int *argc,register char ***argv) exit(1); } - if (init_tmpdir(&mariachk_tmpdir, opt_tmpdir)) + if (init_tmpdir(&maria_chk_tmpdir, opt_tmpdir)) exit(1); - check_param.tmpdir=&mariachk_tmpdir; + check_param.tmpdir=&maria_chk_tmpdir; check_param.key_cache_block_size= opt_key_cache_block_size; if (set_collation_name) @@ -796,17 +806,16 @@ static void get_options(register int *argc,register char ***argv) /* Check table */ -static int mariachk(HA_CHECK *param, my_string filename) +static int maria_chk(HA_CHECK *param, my_string filename) { int error,lock_type,recreate; int rep_quick= param->testflag & (T_QUICK | T_FORCE_UNIQUENESS); - uint raid_chunks; MARIA_HA *info; File datafile; char llbuff[22],llbuff2[22]; my_bool state_updated=0; MARIA_SHARE *share; - DBUG_ENTER("mariachk"); + DBUG_ENTER("maria_chk"); param->out_flag=error=param->warning_printed=param->error_printed= recreate=0; @@ -849,7 +858,8 @@ static int mariachk(HA_CHECK *param, my_string filename) _ma_check_print_error(param,"File '%s' doesn't exist",filename); break; case EACCES: - _ma_check_print_error(param,"You don't have permission to use '%s'",filename); + _ma_check_print_error(param,"You don't have permission to use '%s'", + filename); break; default: _ma_check_print_error(param,"%d when opening MARIA-table '%s'", @@ -862,7 +872,18 @@ static int mariachk(HA_CHECK *param, my_string filename) share->options&= ~HA_OPTION_READ_ONLY_DATA; /* We are modifing it */ share->tot_locks-= share->r_locks; share->r_locks=0; - raid_chunks=share->base.raid_chunks; + + if (share->data_file_type == BLOCK_RECORD && + (param->testflag & (T_REP_ANY | T_SORT_RECORDS | T_FAST | T_STATISTICS | + T_CHECK | T_CHECK_ONLY_CHANGED))) + { + _ma_check_print_error(param, + "Record format used by '%s' is is not yet supported with repair/check", + filename); + param->error_printed= 0; + error= 1; + goto end2; + } /* Skip the checking of the file if: @@ -871,7 +892,8 @@ static int mariachk(HA_CHECK *param, my_string filename) */ if (param->testflag & (T_FAST | T_CHECK_ONLY_CHANGED)) { - my_bool need_to_check= maria_is_crashed(info) || share->state.open_count != 0; + my_bool need_to_check= (maria_is_crashed(info) || + share->state.open_count != 0); if ((param->testflag & (T_REP_ANY | T_SORT_RECORDS)) && ((share->state.changed & (STATE_CHANGED | STATE_CRASHED | @@ -969,6 +991,7 @@ static int mariachk(HA_CHECK *param, my_string filename) _ma_check_print_error(param,"Can't lock indexfile of '%s', error: %d", filename,my_errno); param->error_printed=0; + error= 1; goto end2; } /* @@ -989,7 +1012,8 @@ static int mariachk(HA_CHECK *param, my_string filename) if (tmp != share->state.key_map) info->update|=HA_STATE_CHANGED; } - if (rep_quick && maria_chk_del(param, info, param->testflag & ~T_VERBOSE)) + if (rep_quick && + maria_chk_del(param, info, param->testflag & ~T_VERBOSE)) { if (param->testflag & T_FORCE_CREATE) { @@ -1032,8 +1056,7 @@ static int mariachk(HA_CHECK *param, my_string filename) { /* Change temp file to org file */ VOID(my_close(info->dfile,MYF(MY_WME))); /* Close new file */ error|=maria_change_to_newfile(filename,MARIA_NAME_DEXT,DATA_TMP_EXT, - raid_chunks, - MYF(0)); + MYF(0)); if (_ma_open_datafile(info,info->s, -1)) error=1; param->out_flag&= ~O_NEW_DATA; /* We are using new datafile */ @@ -1112,8 +1135,7 @@ static int mariachk(HA_CHECK *param, my_string filename) 1, MYF(MY_WME))); maria_lock_memory(param); - if ((info->s->options & (HA_OPTION_PACK_RECORD | - HA_OPTION_COMPRESS_RECORD)) || + if ((info->s->data_file_type != STATIC_RECORD) || (param->testflag & (T_EXTEND | T_MEDIUM))) error|=maria_chk_data_link(param, info, param->testflag & T_EXTEND); error|=_ma_flush_blocks(param, share->key_cache, share->kfile); @@ -1163,12 +1185,11 @@ end2: { if (param->out_flag & O_NEW_DATA) error|=maria_change_to_newfile(filename,MARIA_NAME_DEXT,DATA_TMP_EXT, - raid_chunks, - ((param->testflag & T_BACKUP_DATA) ? - MYF(MY_REDEL_MAKE_BACKUP) : MYF(0))); + ((param->testflag & T_BACKUP_DATA) ? + MYF(MY_REDEL_MAKE_BACKUP) : MYF(0))); if (param->out_flag & O_NEW_INDEX) - error|=maria_change_to_newfile(filename,MARIA_NAME_IEXT,INDEX_TMP_EXT,0, - MYF(0)); + error|=maria_change_to_newfile(filename,MARIA_NAME_IEXT,INDEX_TMP_EXT, + MYF(0)); } VOID(fflush(stdout)); VOID(fflush(stderr)); if (param->error_printed) @@ -1195,10 +1216,10 @@ end2: filename)); VOID(fflush(stderr)); DBUG_RETURN(error); -} /* mariachk */ +} /* maria_chk */ - /* Write info about table */ +/* Write info about table */ static void descript(HA_CHECK *param, register MARIA_HA *info, my_string name) { @@ -1212,14 +1233,8 @@ static void descript(HA_CHECK *param, register MARIA_HA *info, my_string name) char llbuff[22],llbuff2[22]; DBUG_ENTER("describe"); - printf("\nMARIA file: %s\n",name); - fputs("Record format: ",stdout); - if (share->options & HA_OPTION_COMPRESS_RECORD) - puts("Compressed"); - else if (share->options & HA_OPTION_PACK_RECORD) - puts("Packed"); - else - puts("Fixed length"); + printf("\nMARIA file: %s\n",name); + printf("Record format: %s\n", record_formats[share->data_file_type]); printf("Character set: %s (%d)\n", get_charset_name(share->state.header.language), share->state.header.language); @@ -1260,25 +1275,18 @@ static void descript(HA_CHECK *param, register MARIA_HA *info, my_string name) printf("Status: %s\n",buff); if (share->base.auto_key) { - printf("Auto increment key: %13d Last value: %13s\n", + printf("Auto increment key: %16d Last value: %18s\n", share->base.auto_key, llstr(share->state.auto_increment,llbuff)); } - if (share->base.raid_type) - { - printf("RAID: Type: %u Chunks: %u Chunksize: %lu\n", - share->base.raid_type, - share->base.raid_chunks, - share->base.raid_chunksize); - } if (share->options & (HA_OPTION_CHECKSUM | HA_OPTION_COMPRESS_RECORD)) - printf("Checksum: %23s\n",llstr(info->state->checksum,llbuff)); + printf("Checksum: %26s\n",llstr(info->state->checksum,llbuff)); ; if (share->options & HA_OPTION_DELAY_KEY_WRITE) printf("Keys are only flushed at close\n"); } - printf("Data records: %13s Deleted blocks: %13s\n", + printf("Data records: %16s Deleted blocks: %18s\n", llstr(info->state->records,llbuff),llstr(info->state->del,llbuff2)); if (param->testflag & T_SILENT) DBUG_VOID_RETURN; /* This is enough */ @@ -1286,14 +1294,14 @@ static void descript(HA_CHECK *param, register MARIA_HA *info, my_string name) if (param->testflag & T_VERBOSE) { #ifdef USE_RELOC - printf("Init-relocation: %13s\n",llstr(share->base.reloc,llbuff)); + printf("Init-relocation: %16s\n",llstr(share->base.reloc,llbuff)); #endif - printf("Datafile parts: %13s Deleted data: %13s\n", + printf("Datafile parts: %16s Deleted data: %18s\n", llstr(share->state.split,llbuff), llstr(info->state->empty,llbuff2)); - printf("Datafile pointer (bytes):%9d Keyfile pointer (bytes):%9d\n", + printf("Datafile pointer (bytes): %11d Keyfile pointer (bytes): %13d\n", share->rec_reflength,share->base.key_reflength); - printf("Datafile length: %13s Keyfile length: %13s\n", + printf("Datafile length: %16s Keyfile length: %18s\n", llstr(info->state->data_file_length,llbuff), llstr(info->state->key_file_length,llbuff2)); @@ -1303,13 +1311,13 @@ static void descript(HA_CHECK *param, register MARIA_HA *info, my_string name) { if (share->base.max_data_file_length != HA_OFFSET_ERROR || share->base.max_key_file_length != HA_OFFSET_ERROR) - printf("Max datafile length: %13s Max keyfile length: %13s\n", + printf("Max datafile length: %16s Max keyfile length: %18s\n", llstr(share->base.max_data_file_length-1,llbuff), llstr(share->base.max_key_file_length-1,llbuff2)); } } - - printf("Recordlength: %13d\n",(int) share->base.pack_reclength); + printf("Block_size: %16d\n",(int) share->block_size); + printf("Recordlength: %16d\n",(int) share->base.pack_reclength); if (! maria_is_all_keys_active(share->state.key_map, share->base.keys)) { longlong2str(share->state.key_map,buff,2); @@ -1417,7 +1425,7 @@ static void descript(HA_CHECK *param, register MARIA_HA *info, my_string name) if (share->options & HA_OPTION_COMPRESS_RECORD) printf(" Huff tree Bits"); VOID(putchar('\n')); - start=1; + for (field=0 ; field < share->base.fields ; field++) { if (share->options & HA_OPTION_COMPRESS_RECORD) @@ -1446,8 +1454,9 @@ static void descript(HA_CHECK *param, register MARIA_HA *info, my_string name) sprintf(null_bit,"%d",share->rec[field].null_bit); sprintf(null_pos,"%d",share->rec[field].null_pos+1); } - printf("%-6d%-6d%-7s%-8s%-8s%-35s",field+1,start,length, - null_pos, null_bit, buff); + printf("%-6d%-6u%-7s%-8s%-8s%-35s",field+1, + (uint) share->rec[field].offset+1, + length, null_pos, null_bit, buff); if (share->options & HA_OPTION_COMPRESS_RECORD) { if (share->rec[field].huff_tree) @@ -1475,7 +1484,7 @@ static int maria_sort_records(HA_CHECK *param, uint key; MARIA_KEYDEF *keyinfo; File new_file; - uchar *temp_buff; + byte *temp_buff; ha_rows old_record_count; MARIA_SHARE *share=info->s; char llbuff[22],llbuff2[22]; @@ -1532,7 +1541,7 @@ static int maria_sort_records(HA_CHECK *param, goto err; info->opt_flag|=WRITE_CACHE_USED; - if (!(temp_buff=(uchar*) my_alloca((uint) keyinfo->block_length))) + if (!(temp_buff=(byte*) my_alloca((uint) keyinfo->block_length))) { _ma_check_print_error(param,"Not enough memory for key block"); goto err; @@ -1544,14 +1553,11 @@ static int maria_sort_records(HA_CHECK *param, goto err; } fn_format(param->temp_filename,name,"", MARIA_NAME_DEXT,2+4+32); - new_file=my_raid_create(fn_format(param->temp_filename, - param->temp_filename,"", - DATA_TMP_EXT,2+4), - 0,param->tmpfile_createflag, - share->base.raid_type, - share->base.raid_chunks, - share->base.raid_chunksize, - MYF(0)); + new_file= my_create(fn_format(param->temp_filename, + param->temp_filename,"", + DATA_TMP_EXT,2+4), + 0,param->tmpfile_createflag, + MYF(0)); if (new_file < 0) { _ma_check_print_error(param,"Can't create new tempfile: '%s'", @@ -1568,7 +1574,7 @@ static int maria_sort_records(HA_CHECK *param, for (key=0 ; key < share->base.keys ; key++) share->keyinfo[key].flag|= HA_SORT_ALLOWS_SAME; - if (my_pread(share->kfile,(byte*) temp_buff, + if (my_pread(share->kfile, temp_buff, (uint) keyinfo->block_length, share->state.key_root[sort_key], MYF(MY_NABP+MY_WME))) @@ -1589,7 +1595,8 @@ static int maria_sort_records(HA_CHECK *param, if (sort_info.new_data_file_type != COMPRESSED_RECORD) info->state->checksum=0; - if (sort_record_index(&sort_param,info,keyinfo,share->state.key_root[sort_key], + if (sort_record_index(&sort_param,info,keyinfo, + share->state.key_root[sort_key], temp_buff, sort_key,new_file,update_index) || maria_write_data_suffix(&sort_info,1) || flush_io_cache(&info->rec_cache)) @@ -1626,8 +1633,7 @@ err: { VOID(end_io_cache(&info->rec_cache)); (void) my_close(new_file,MYF(MY_WME)); - (void) my_raid_delete(param->temp_filename, share->base.raid_chunks, - MYF(MY_WME)); + (void) my_delete(param->temp_filename, MYF(MY_WME)); } if (temp_buff) { @@ -1644,17 +1650,17 @@ err: } /* sort_records */ - /* Sort records recursive using one index */ +/* Sort records recursive using one index */ static int sort_record_index(MARIA_SORT_PARAM *sort_param,MARIA_HA *info, MARIA_KEYDEF *keyinfo, - my_off_t page, uchar *buff, uint sort_key, + my_off_t page, byte *buff, uint sort_key, File new_file,my_bool update_index) { uint nod_flag,used_length,key_length; - uchar *temp_buff,*keypos,*endpos; + byte *temp_buff,*keypos,*endpos; my_off_t next_page,rec_pos; - uchar lastkey[HA_MAX_KEY_BUFF]; + byte lastkey[HA_MAX_KEY_BUFF]; char llbuff[22]; MARIA_SORT_INFO *sort_info= sort_param->sort_info; HA_CHECK *param=sort_info->param; @@ -1665,7 +1671,7 @@ static int sort_record_index(MARIA_SORT_PARAM *sort_param,MARIA_HA *info, if (nod_flag) { - if (!(temp_buff=(uchar*) my_alloca((uint) keyinfo->block_length))) + if (!(temp_buff= (byte*) my_alloca((uint) keyinfo->block_length))) { _ma_check_print_error(param,"Not Enough memory"); DBUG_RETURN(-1); @@ -1679,7 +1685,7 @@ static int sort_record_index(MARIA_SORT_PARAM *sort_param,MARIA_HA *info, _sanity(__FILE__,__LINE__); if (nod_flag) { - next_page= _ma_kpos(nod_flag,keypos); + next_page= _ma_kpos(nod_flag, keypos); if (my_pread(info->s->kfile,(byte*) temp_buff, (uint) keyinfo->block_length, next_page, MYF(MY_NABP+MY_WME))) @@ -1688,7 +1694,8 @@ static int sort_record_index(MARIA_SORT_PARAM *sort_param,MARIA_HA *info, llstr(next_page,llbuff)); goto err; } - if (sort_record_index(sort_param, info,keyinfo,next_page,temp_buff,sort_key, + if (sort_record_index(sort_param, info,keyinfo,next_page,temp_buff, + sort_key, new_file, update_index)) goto err; } @@ -1699,7 +1706,7 @@ static int sort_record_index(MARIA_SORT_PARAM *sort_param,MARIA_HA *info, break; rec_pos= _ma_dpos(info,0,lastkey+key_length); - if ((*info->s->read_rnd)(info,sort_param->record,rec_pos,0)) + if ((*info->s->read_record)(info,sort_param->record,rec_pos)) { _ma_check_print_error(param,"%d when reading datafile",my_errno); goto err; @@ -1738,7 +1745,7 @@ err: /* - Check if mariachk was killed by a signal + Check if maria_chk was killed by a signal This is overloaded by other programs that want to be able to abort sorting */ diff --git a/storage/maria/maria_def.h b/storage/maria/maria_def.h index ecd93807a06..778c5817e4f 100644 --- a/storage/maria/maria_def.h +++ b/storage/maria/maria_def.h @@ -55,14 +55,15 @@ typedef struct st_maria_state_info uchar keys; /* number of keys in file */ uchar uniques; /* number of UNIQUE definitions */ uchar language; /* Language for indexes */ - uchar max_block_size_index; /* max keyblock size */ uchar fulltext_keys; - uchar not_used; /* To align to 8 */ + uchar data_file_type; + uchar org_data_file_type; /* Used by mariapack to store dft */ } header; MARIA_STATUS_INFO state; ha_rows split; /* number of split blocks */ my_off_t dellink; /* Link to next removed block */ + ulonglong first_bitmap_with_space; ulonglong auto_increment; ulong process; /* process that updated table last */ ulong unique; /* Unique number for this process */ @@ -70,7 +71,7 @@ typedef struct st_maria_state_info ulong status; ulong *rec_per_key_part; my_off_t *key_root; /* Start of key trees */ - my_off_t *key_del; /* delete links for trees */ + my_off_t key_del; /* delete links for trees */ my_off_t rec_per_key_rows; /* Rows when calculating rec_per_key */ ulong sec_index_changed; /* Updated when new sec_index */ @@ -91,60 +92,73 @@ typedef struct st_maria_state_info } MARIA_STATE_INFO; -#define MARIA_STATE_INFO_SIZE (24+14*8+7*4+2*2+8) +#define MARIA_STATE_INFO_SIZE (24 + 4 + 11*8 + 4*4 + 8 + 3*4 + 5*8) #define MARIA_STATE_KEY_SIZE 8 #define MARIA_STATE_KEYBLOCK_SIZE 8 #define MARIA_STATE_KEYSEG_SIZE 4 -#define MARIA_STATE_EXTRA_SIZE ((MARIA_MAX_KEY+MARIA_MAX_KEY_BLOCK_SIZE)*MARIA_STATE_KEY_SIZE + MARIA_MAX_KEY*HA_MAX_KEY_SEG*MARIA_STATE_KEYSEG_SIZE) +#define MARIA_STATE_EXTRA_SIZE (MARIA_MAX_KEY*MARIA_STATE_KEY_SIZE + MARIA_MAX_KEY*HA_MAX_KEY_SEG*MARIA_STATE_KEYSEG_SIZE) #define MARIA_KEYDEF_SIZE (2+ 5*2) #define MARIA_UNIQUEDEF_SIZE (2+1+1) #define HA_KEYSEG_SIZE (6+ 2*2 + 4*2) -#define MARIA_COLUMNDEF_SIZE (2*3+1) -#define MARIA_BASE_INFO_SIZE (5*8 + 8*4 + 4 + 4*2 + 16) +#define MARIA_COLUMNDEF_SIZE (6+2+2+2+2+2+1+1) +#define MARIA_BASE_INFO_SIZE (5*8 + 6*4 + 11*2 + 6 + 5*2 + 1 + 16) #define MARIA_INDEX_BLOCK_MARGIN 16 /* Safety margin for .MYI tables */ -typedef struct st__ma_base_info +typedef struct st_ma_base_info { - my_off_t keystart; /* Start of keys */ + my_off_t keystart; /* Start of keys */ my_off_t max_data_file_length; my_off_t max_key_file_length; my_off_t margin_key_file_length; - ha_rows records, reloc; /* Create information */ - ulong mean_row_length; /* Create information */ - ulong reclength; /* length of unpacked record */ - ulong pack_reclength; /* Length of full packed rec */ + ha_rows records, reloc; /* Create information */ + ulong mean_row_length; /* Create information */ + ulong reclength; /* length of unpacked record */ + ulong pack_reclength; /* Length of full packed rec */ ulong min_pack_length; - ulong max_pack_length; /* Max possibly length of - packed rec. */ + ulong max_pack_length; /* Max possibly length of packed rec */ ulong min_block_length; - ulong fields, /* fields in table */ - pack_fields; /* packed fields in table */ - uint rec_reflength; /* = 2-8 */ - uint key_reflength; /* = 2-8 */ - uint keys; /* same as in state.header */ - uint auto_key; /* Which key-1 is a auto key */ - uint blobs; /* Number of blobs */ - uint pack_bits; /* Length of packed bits */ - uint max_key_block_length; /* Max block length */ - uint max_key_length; /* Max key length */ + uint fields; /* fields in table */ + uint fixed_not_null_fields; + uint fixed_not_null_fields_length; + uint max_field_lengths; + uint pack_fields; /* packed fields in table */ + uint varlength_fields; /* char/varchar/blobs */ + uint rec_reflength; /* = 2-8 */ + uint key_reflength; /* = 2-8 */ + uint keys; /* same as in state.header */ + uint auto_key; /* Which key-1 is a auto key */ + uint blobs; /* Number of blobs */ + /* Length of packed bits (when table was created first time) */ + uint pack_bytes; + /* Length of null bits (when table was created first time) */ + uint original_null_bytes; + uint null_bytes; /* Null bytes in record */ + uint field_offsets; /* Number of field offsets */ + uint max_key_block_length; /* Max block length */ + uint max_key_length; /* Max key length */ /* Extra allocation when using dynamic record format */ uint extra_alloc_bytes; uint extra_alloc_procent; - /* Info about raid */ - uint raid_type, raid_chunks; - ulong raid_chunksize; + uint is_nulls_extended; /* 1 if new null bytes */ + uint min_row_length; + uint default_row_flag; /* 0 or ROW_FLAG_NULLS_EXTENDED */ + uint block_size; + uint default_rec_buff_size; + uint extra_rec_buff_size; + /* The following are from the header */ uint key_parts, all_key_parts; + my_bool transactional; } MARIA_BASE_INFO; - /* Structs used intern in database */ +/* Structs used intern in database */ -typedef struct st_maria_blob /* Info of record */ +typedef struct st_maria_blob /* Info of record */ { - ulong offset; /* Offset to blob in record */ - uint pack_length; /* Type of packed length */ - ulong length; /* Calc:ed for each record */ + ulong offset; /* Offset to blob in record */ + uint pack_length; /* Type of packed length */ + ulong length; /* Calc:ed for each record */ } MARIA_BLOB; @@ -155,6 +169,26 @@ typedef struct st_maria_pack uchar version; } MARIA_PACK; +typedef struct st_maria_file_bitmap +{ + uchar *map; + ulonglong page; /* Page number for current bitmap */ + uint used_size; /* Size of bitmap that is not 0 */ + File file; + + my_bool changed; + +#ifdef THREAD + pthread_mutex_t bitmap_lock; +#endif + /* Constants, allocated when initiating bitmaps */ + uint sizes[8]; /* Size per bit combination */ + uint total_size; /* Total usable size of bitmap page */ + uint block_size; /* Block size of file */ + ulong pages_covered; /* Pages covered by bitmap + 1 */ +} MARIA_FILE_BITMAP; + + #define MAX_NONMAPPED_INSERTS 1000 typedef struct st_maria_share @@ -175,28 +209,36 @@ typedef struct st_maria_share symlinks */ *index_file_name; byte *file_map; /* mem-map of file if possible */ - KEY_CACHE *key_cache; /* ref to the current key cache - */ + KEY_CACHE *key_cache; /* ref to the current key cache */ MARIA_DECODE_TREE *decode_trees; uint16 *decode_tables; - int(*read_record) (struct st_maria_info *, my_off_t, byte *); - int(*write_record) (struct st_maria_info *, const byte *); - int(*update_record) (struct st_maria_info *, my_off_t, const byte *); - int(*delete_record) (struct st_maria_info *); - int(*read_rnd) (struct st_maria_info *, byte *, my_off_t, my_bool); - int(*compare_record) (struct st_maria_info *, const byte *); - ha_checksum(*calc_checksum) (struct st_maria_info *, const byte *); - int(*compare_unique) (struct st_maria_info *, MARIA_UNIQUEDEF *, - const byte *record, my_off_t pos); - uint(*file_read) (MARIA_HA *, byte *, uint, my_off_t, myf); - uint(*file_write) (MARIA_HA *, byte *, uint, my_off_t, myf); + my_bool (*once_init)(struct st_maria_share *, File); + my_bool (*once_end)(struct st_maria_share *); + my_bool (*init)(struct st_maria_info *); + void (*end)(struct st_maria_info *); + int (*read_record)(struct st_maria_info *, byte *, MARIA_RECORD_POS); + my_bool (*scan_init)(struct st_maria_info *); + int (*scan)(struct st_maria_info *, byte *, MARIA_RECORD_POS, my_bool); + void (*scan_end)(struct st_maria_info *); + MARIA_RECORD_POS (*write_record_init)(struct st_maria_info *, const byte *); + my_bool (*write_record)(struct st_maria_info *, const byte *); + my_bool (*write_record_abort)(struct st_maria_info *); + my_bool (*update_record)(struct st_maria_info *, MARIA_RECORD_POS, + const byte *); + my_bool (*delete_record)(struct st_maria_info *); + my_bool (*compare_record)(struct st_maria_info *, const byte *); + ha_checksum(*calc_checksum) (struct st_maria_info *, const byte *); + ha_checksum(*calc_write_checksum) (struct st_maria_info *, const byte *); + my_bool (*compare_unique) (struct st_maria_info *, MARIA_UNIQUEDEF *, + const byte *record, MARIA_RECORD_POS pos); + uint(*file_read) (MARIA_HA *, byte *, uint, my_off_t, myf); + uint(*file_write) (MARIA_HA *, byte *, uint, my_off_t, myf); invalidator_by_filename invalidator; /* query cache invalidator */ ulong this_process; /* processid */ ulong last_process; /* For table-change-check */ ulong last_version; /* Version on start */ ulong options; /* Options used */ - ulong min_pack_length; /* Theese are used by packed - data */ + ulong min_pack_length; /* These are used by packed data */ ulong max_pack_length; ulong state_diff_length; uint rec_reflength; /* rec_reflength in use now */ @@ -208,21 +250,24 @@ typedef struct st_maria_share int mode; /* mode of file on open */ uint reopen; /* How many times reopened */ uint w_locks, r_locks, tot_locks; /* Number of read/write locks */ - uint blocksize; /* blocksize of keyfile */ + uint block_size; /* block_size of keyfile & data file*/ + uint base_length; myf write_flag; enum data_file_type data_file_type; + my_bool temporary; my_bool changed, /* If changed since lock */ global_changed, /* If changed since open */ - not_flushed, temporary, delay_key_write, concurrent_insert; + not_flushed, concurrent_insert; + my_bool delay_key_write; #ifdef THREAD THR_LOCK lock; - pthread_mutex_t intern_lock; /* Locking for use with - _locking */ + pthread_mutex_t intern_lock; /* Locking for use with _locking */ rw_lock_t *key_root_lock; #endif my_off_t mmaped_length; uint nonmmaped_inserts; /* counter of writing in non-mmaped area */ + MARIA_FILE_BITMAP bitmap; rw_lock_t mmap_lock; } MARIA_SHARE; @@ -237,45 +282,106 @@ typedef struct st_maria_bit_buff uint error; } MARIA_BIT_BUFF; +typedef byte MARIA_BITMAP_BUFFER; + +typedef struct st_maria_bitmap_block +{ + ulonglong page; /* Page number */ + /* Number of continuous pages. TAIL_BIT is set if this is a tail page */ + uint page_count; + uint empty_space; /* Set for head and tail pages */ + /* + Number of BLOCKS for block-region (holds all non-blob-fields or one blob) + */ + uint sub_blocks; + /* set to <> 0 in write_record() if this block was actually used */ + uint8 used; + uint8 org_bitmap_value; +} MARIA_BITMAP_BLOCK; + + +typedef struct st_maria_bitmap_blocks +{ + MARIA_BITMAP_BLOCK *block; + uint count; + my_bool tail_page_skipped; /* If some tail pages was not used */ + my_bool page_skipped; /* If some full pages was not used */ +} MARIA_BITMAP_BLOCKS; + + +/* Data about the currently read row */ +typedef struct st_maria_row +{ + MARIA_BITMAP_BLOCKS insert_blocks; + MARIA_BITMAP_BUFFER *extents; + MARIA_RECORD_POS lastpos, nextpos; + MARIA_RECORD_POS *tail_positions; + ha_checksum checksum; + byte *empty_bits, *field_lengths; + byte *empty_bits_buffer; /* For storing cur_row.empty_bits */ + uint *null_field_lengths; /* All null field lengths */ + ulong *blob_lengths; /* Length for each blob */ + ulong base_length, normal_length, char_length, varchar_length, blob_length; + ulong head_length, total_length; + my_size_t extents_buffer_length; /* Size of 'extents' buffer */ + uint field_lengths_length; /* Length of data in field_lengths */ + uint extents_count; /* number of extents in 'extents' */ + uint full_page_count, tail_count; /* For maria_chk */ +} MARIA_ROW; + +/* Data to scan row in blocked format */ +typedef struct st_maria_block_scan +{ + byte *bitmap_buff, *bitmap_pos, *bitmap_end, *page_buff; + byte *dir, *dir_end; + ulong bitmap_page; + ulonglong bits; + uint number_of_rows, bit_pos; + MARIA_RECORD_POS row_base_page; +} MARIA_BLOCK_SCAN; + + struct st_maria_info { MARIA_SHARE *s; /* Shared between open:s */ MARIA_STATUS_INFO *state, save_state; + MARIA_ROW cur_row, new_row; + MARIA_BLOCK_SCAN scan; MARIA_BLOB *blobs; /* Pointer to blobs */ MARIA_BIT_BUFF bit_buff; + DYNAMIC_ARRAY bitmap_blocks; /* accumulate indexfile changes between write's */ TREE *bulk_insert; DYNAMIC_ARRAY *ft1_to_ft2; /* used only in ft1->ft2 conversion */ MEM_ROOT ft_memroot; /* used by the parser */ MYSQL_FTPARSER_PARAM *ftparser_param; /* share info between init/deinit */ char *filename; /* parameter to open filename */ - uchar *buff, /* Temp area for key */ - *lastkey, *lastkey2; /* Last used search key */ - uchar *first_mbr_key; /* Searhed spatial key */ - byte *rec_buff; /* Tempbuff for recordpack */ - uchar *int_keypos, /* Save position for next/previous */ + byte *buff; /* page buffer */ + byte *keyread_buff; /* Buffer for last key read */ + byte *lastkey, *lastkey2; /* Last used search key */ + byte *first_mbr_key; /* Searhed spatial key */ + byte *rec_buff; /* Temp buffer for recordpack */ + byte *int_keypos, /* Save position for next/previous */ *int_maxpos; /* -""- */ uint int_nod_flag; /* -""- */ uint32 int_keytree_version; /* -""- */ - int(*read_record) (struct st_maria_info *, my_off_t, byte *); + int (*read_record) (struct st_maria_info *, byte*, MARIA_RECORD_POS); invalidator_by_filename invalidator; /* query cache invalidator */ ulong this_unique; /* uniq filenumber or thread */ ulong last_unique; /* last unique number */ ulong this_loop; /* counter for this open */ ulong last_loop; /* last used counter */ - my_off_t lastpos, /* Last record position */ - nextpos; /* Position to next record */ - my_off_t save_lastpos; + MARIA_RECORD_POS save_lastpos; + MARIA_RECORD_POS dup_key_pos; my_off_t pos; /* Intern variable */ my_off_t last_keypage; /* Last key page read */ my_off_t last_search_keypage; /* Last keypage when searching */ - my_off_t dupp_key_pos; - ha_checksum checksum; /* QQ: the folloing two xxx_length fields should be removed, as they are not compatible with parallel repair */ ulong packed_length, blob_length; /* Length of found, packed record */ + my_size_t rec_buff_size; int dfile; /* The datafile */ uint opt_flag; /* Optim. for space/speed */ uint update; /* If file changed since open */ @@ -298,19 +404,19 @@ struct st_maria_info my_bool was_locked; /* Was locked in panic */ my_bool append_insert_at_end; /* Set if concurrent insert */ my_bool quick_mode; - /* If info->buff can't be used for rnext */ + /* If info->keyread_buff can't be used for rnext */ my_bool page_changed; - /* If info->buff has to be reread for rnext */ - my_bool buff_used; - my_bool once_flags; /* For MARIAMRG */ + /* If info->keyread_buff has to be reread for rnext */ + my_bool keybuff_used; + my_bool once_flags; /* For MARIA_MRG */ #ifdef THREAD THR_LOCK_DATA lock; #endif - uchar *maria_rtree_recursion_state; /* For RTREE */ + uchar *maria_rtree_recursion_state; /* For RTREE */ int maria_rtree_recursion_depth; }; -/* Some defines used by isam-funktions */ +/* Some defines used by maria-functions */ #define USE_WHOLE_KEY HA_MAX_KEY_BUFF*2 /* Use whole key in _search() */ #define F_EXTRA_LCK -1 @@ -361,15 +467,15 @@ struct st_maria_info } #define get_key_full_length(length,key) \ -{ if ((uchar) *(key) != 255) \ - length= ((uint) (uchar) *((key)++))+1; \ + { if (*(uchar*) (key) != 255) \ + length= ((uint) *(uchar*) ((key)++))+1; \ else \ { length=mi_uint2korr((key)+1)+3; (key)+=3; } \ } #define get_key_full_length_rdonly(length,key) \ -{ if ((uchar) *(key) != 255) \ - length= ((uint) (uchar) *((key)))+1; \ +{ if (*(uchar*) (key) != 255) \ + length= ((uint) *(uchar*) ((key)))+1; \ else \ { length=mi_uint2korr((key)+1)+3; } \ } @@ -398,7 +504,6 @@ struct st_maria_info #define PACK_TYPE_ZERO_FILL 4 #define MARIA_FOUND_WRONG_KEY 32738 /* Impossible value from ha_key_cmp */ -#define MARIA_MAX_KEY_BLOCK_SIZE (MARIA_MAX_KEY_BLOCK_LENGTH/MARIA_MIN_KEY_BLOCK_LENGTH) #define MARIA_BLOCK_SIZE(key_length,data_pointer,key_pointer,block_size) (((((key_length)+(data_pointer)+(key_pointer))*4+(key_pointer)+2)/(block_size)+1)*(block_size)) #define MARIA_MAX_KEYPTR_SIZE 5 /* For calculating block lengths */ #define MARIA_MIN_KEYBLOCK_LENGTH 50 /* When to split delete blocks */ @@ -428,85 +533,88 @@ extern LIST *maria_open_list; extern uchar NEAR maria_file_magic[], NEAR maria_pack_file_magic[]; extern uint NEAR maria_read_vec[], NEAR maria_readnext_vec[]; extern uint maria_quick_table_bits; +extern byte maria_zero_string[]; /* This is used by _ma_calc_xxx_key_length och _ma_store_key */ typedef struct st_maria_s_param { - uint ref_length, key_length, - n_ref_length, - n_length, totlength, part_of_prev_key, prev_length, pack_marker; - uchar *key, *prev_key, *next_key_pos; + uint ref_length, key_length, n_ref_length; + uint n_length, totlength, part_of_prev_key, prev_length, pack_marker; + const byte *key; + byte *prev_key, *next_key_pos; bool store_not_null; } MARIA_KEY_PARAM; /* Prototypes for intern functions */ -extern int _ma_read_dynamic_record(MARIA_HA *info, my_off_t filepos, - byte *buf); -extern int _ma_write_dynamic_record(MARIA_HA *, const byte *); -extern int _ma_update_dynamic_record(MARIA_HA *, my_off_t, const byte *); -extern int _ma_delete_dynamic_record(MARIA_HA *info); -extern int _ma_cmp_dynamic_record(MARIA_HA *info, const byte *record); -extern int _ma_read_rnd_dynamic_record(MARIA_HA *, byte *, my_off_t, +extern int _ma_read_dynamic_record(MARIA_HA *, byte *, MARIA_RECORD_POS); +extern int _ma_read_rnd_dynamic_record(MARIA_HA *, byte *, MARIA_RECORD_POS, my_bool); -extern int _ma_write_blob_record(MARIA_HA *, const byte *); -extern int _ma_update_blob_record(MARIA_HA *, my_off_t, const byte *); -extern int _ma_read_static_record(MARIA_HA *info, my_off_t filepos, - byte *buf); -extern int _ma_write_static_record(MARIA_HA *, const byte *); -extern int _ma_update_static_record(MARIA_HA *, my_off_t, const byte *); -extern int _ma_delete_static_record(MARIA_HA *info); -extern int _ma_cmp_static_record(MARIA_HA *info, const byte *record); -extern int _ma_read_rnd_static_record(MARIA_HA *, byte *, my_off_t, my_bool); -extern int _ma_ck_write(MARIA_HA *info, uint keynr, uchar *key, +extern my_bool _ma_write_dynamic_record(MARIA_HA *, const byte *); +extern my_bool _ma_update_dynamic_record(MARIA_HA *, MARIA_RECORD_POS, + const byte *); +extern my_bool _ma_delete_dynamic_record(MARIA_HA *info); +extern my_bool _ma_cmp_dynamic_record(MARIA_HA *info, const byte *record); +extern my_bool _ma_write_blob_record(MARIA_HA *, const byte *); +extern my_bool _ma_update_blob_record(MARIA_HA *, MARIA_RECORD_POS, + const byte *); +extern int _ma_read_static_record(MARIA_HA *info, byte *, MARIA_RECORD_POS); +extern int _ma_read_rnd_static_record(MARIA_HA *, byte *, MARIA_RECORD_POS, + my_bool); +extern my_bool _ma_write_static_record(MARIA_HA *, const byte *); +extern my_bool _ma_update_static_record(MARIA_HA *, MARIA_RECORD_POS, + const byte *); +extern my_bool _ma_delete_static_record(MARIA_HA *info); +extern my_bool _ma_cmp_static_record(MARIA_HA *info, const byte *record); +extern int _ma_ck_write(MARIA_HA *info, uint keynr, byte *key, uint length); extern int _ma_ck_real_write_btree(MARIA_HA *info, MARIA_KEYDEF *keyinfo, - uchar *key, uint key_length, - my_off_t *root, uint comp_flag); + byte *key, uint key_length, + MARIA_RECORD_POS *root, uint comp_flag); extern int _ma_enlarge_root(MARIA_HA *info, MARIA_KEYDEF *keyinfo, - uchar *key, my_off_t *root); -extern int _ma_insert(MARIA_HA *info, MARIA_KEYDEF *keyinfo, uchar *key, - uchar *anc_buff, uchar *key_pos, uchar *key_buff, - uchar *father_buff, uchar *father_keypos, + byte *key, MARIA_RECORD_POS *root); +extern int _ma_insert(MARIA_HA *info, MARIA_KEYDEF *keyinfo, byte *key, + byte *anc_buff, byte *key_pos, byte *key_buff, + byte *father_buff, byte *father_keypos, my_off_t father_page, my_bool insert_last); extern int _ma_split_page(MARIA_HA *info, MARIA_KEYDEF *keyinfo, - uchar *key, uchar *buff, uchar *key_buff, + byte *key, byte *buff, byte *key_buff, my_bool insert_last); -extern uchar *_ma_find_half_pos(uint nod_flag, MARIA_KEYDEF *keyinfo, - uchar *page, uchar *key, +extern byte *_ma_find_half_pos(uint nod_flag, MARIA_KEYDEF *keyinfo, + byte *page, byte *key, uint *return_key_length, - uchar ** after_key); + byte ** after_key); extern int _ma_calc_static_key_length(MARIA_KEYDEF *keyinfo, uint nod_flag, - uchar *key_pos, uchar *org_key, - uchar *key_buff, uchar *key, + byte *key_pos, byte *org_key, + byte *key_buff, const byte *key, MARIA_KEY_PARAM *s_temp); extern int _ma_calc_var_key_length(MARIA_KEYDEF *keyinfo, uint nod_flag, - uchar *key_pos, uchar *org_key, - uchar *key_buff, uchar *key, + byte *key_pos, byte *org_key, + byte *key_buff, const byte *key, MARIA_KEY_PARAM *s_temp); extern int _ma_calc_var_pack_key_length(MARIA_KEYDEF *keyinfo, - uint nod_flag, uchar *key_pos, - uchar *org_key, uchar *prev_key, - uchar *key, + uint nod_flag, byte *key_pos, + byte *org_key, byte *prev_key, + const byte *key, MARIA_KEY_PARAM *s_temp); extern int _ma_calc_bin_pack_key_length(MARIA_KEYDEF *keyinfo, - uint nod_flag, uchar *key_pos, - uchar *org_key, uchar *prev_key, - uchar *key, + uint nod_flag, byte *key_pos, + byte *org_key, byte *prev_key, + const byte *key, MARIA_KEY_PARAM *s_temp); -void _ma_store_static_key(MARIA_KEYDEF *keyinfo, uchar *key_pos, +void _ma_store_static_key(MARIA_KEYDEF *keyinfo, byte *key_pos, MARIA_KEY_PARAM *s_temp); -void _ma_store_var_pack_key(MARIA_KEYDEF *keyinfo, uchar *key_pos, +void _ma_store_var_pack_key(MARIA_KEYDEF *keyinfo, byte *key_pos, MARIA_KEY_PARAM *s_temp); #ifdef NOT_USED -void _ma_store_pack_key(MARIA_KEYDEF *keyinfo, uchar *key_pos, +void _ma_store_pack_key(MARIA_KEYDEF *keyinfo, byte *key_pos, MARIA_KEY_PARAM *s_temp); #endif -void _ma_store_bin_pack_key(MARIA_KEYDEF *keyinfo, uchar *key_pos, +void _ma_store_bin_pack_key(MARIA_KEYDEF *keyinfo, byte *key_pos, MARIA_KEY_PARAM *s_temp); -extern int _ma_ck_delete(MARIA_HA *info, uint keynr, uchar *key, +extern int _ma_ck_delete(MARIA_HA *info, uint keynr, byte *key, uint key_length); extern int _ma_readinfo(MARIA_HA *info, int lock_flag, int check_keybuffer); extern int _ma_writeinfo(MARIA_HA *info, uint options); @@ -514,74 +622,69 @@ extern int _ma_test_if_changed(MARIA_HA *info); extern int _ma_mark_file_changed(MARIA_HA *info); extern int _ma_decrement_open_count(MARIA_HA *info); extern int _ma_check_index(MARIA_HA *info, int inx); -extern int _ma_search(MARIA_HA *info, MARIA_KEYDEF *keyinfo, uchar *key, +extern int _ma_search(MARIA_HA *info, MARIA_KEYDEF *keyinfo, byte *key, uint key_len, uint nextflag, my_off_t pos); extern int _ma_bin_search(struct st_maria_info *info, MARIA_KEYDEF *keyinfo, - uchar *page, uchar *key, uint key_len, - uint comp_flag, uchar **ret_pos, uchar *buff, + byte *page, byte *key, uint key_len, + uint comp_flag, byte **ret_pos, byte *buff, my_bool *was_last_key); extern int _ma_seq_search(MARIA_HA *info, MARIA_KEYDEF *keyinfo, - uchar *page, uchar *key, uint key_len, - uint comp_flag, uchar ** ret_pos, uchar *buff, + byte *page, byte *key, uint key_len, + uint comp_flag, byte ** ret_pos, byte *buff, my_bool *was_last_key); extern int _ma_prefix_search(MARIA_HA *info, MARIA_KEYDEF *keyinfo, - uchar *page, uchar *key, uint key_len, - uint comp_flag, uchar ** ret_pos, uchar *buff, + byte *page, byte *key, uint key_len, + uint comp_flag, byte ** ret_pos, byte *buff, my_bool *was_last_key); -extern my_off_t _ma_kpos(uint nod_flag, uchar *after_key); -extern void _ma_kpointer(MARIA_HA *info, uchar *buff, my_off_t pos); -extern my_off_t _ma_dpos(MARIA_HA *info, uint nod_flag, uchar *after_key); -extern my_off_t _ma_rec_pos(MARIA_SHARE *info, uchar *ptr); -extern void _ma_dpointer(MARIA_HA *info, uchar *buff, my_off_t pos); +extern my_off_t _ma_kpos(uint nod_flag, byte *after_key); +extern void _ma_kpointer(MARIA_HA *info, byte *buff, my_off_t pos); +extern MARIA_RECORD_POS _ma_dpos(MARIA_HA *info, uint nod_flag, + const byte *after_key); +extern MARIA_RECORD_POS _ma_rec_pos(MARIA_SHARE *info, byte *ptr); +extern void _ma_dpointer(MARIA_HA *info, byte *buff, MARIA_RECORD_POS pos); extern uint _ma_get_static_key(MARIA_KEYDEF *keyinfo, uint nod_flag, - uchar **page, uchar *key); + byte **page, byte *key); extern uint _ma_get_pack_key(MARIA_KEYDEF *keyinfo, uint nod_flag, - uchar **page, uchar *key); + byte **page, byte *key); extern uint _ma_get_binary_pack_key(MARIA_KEYDEF *keyinfo, uint nod_flag, - uchar ** page_pos, uchar *key); -extern uchar *_ma_get_last_key(MARIA_HA *info, MARIA_KEYDEF *keyinfo, - uchar *keypos, uchar *lastkey, - uchar *endpos, uint *return_key_length); -extern uchar *_ma_get_key(MARIA_HA *info, MARIA_KEYDEF *keyinfo, - uchar *page, uchar *key, uchar *keypos, + byte ** page_pos, byte *key); +extern byte *_ma_get_last_key(MARIA_HA *info, MARIA_KEYDEF *keyinfo, + byte *keypos, byte *lastkey, + byte *endpos, uint *return_key_length); +extern byte *_ma_get_key(MARIA_HA *info, MARIA_KEYDEF *keyinfo, + byte *page, byte *key, byte *keypos, uint *return_key_length); -extern uint _ma_keylength(MARIA_KEYDEF *keyinfo, uchar *key); -extern uint _ma_keylength_part(MARIA_KEYDEF *keyinfo, register uchar *key, +extern uint _ma_keylength(MARIA_KEYDEF *keyinfo, const byte *key); +extern uint _ma_keylength_part(MARIA_KEYDEF *keyinfo, register const byte *key, HA_KEYSEG *end); -extern uchar *_ma_move_key(MARIA_KEYDEF *keyinfo, uchar *to, uchar *from); +extern byte *_ma_move_key(MARIA_KEYDEF *keyinfo, byte *to, const byte *from); extern int _ma_search_next(MARIA_HA *info, MARIA_KEYDEF *keyinfo, - uchar *key, uint key_length, uint nextflag, + byte *key, uint key_length, uint nextflag, my_off_t pos); extern int _ma_search_first(MARIA_HA *info, MARIA_KEYDEF *keyinfo, my_off_t pos); extern int _ma_search_last(MARIA_HA *info, MARIA_KEYDEF *keyinfo, my_off_t pos); -extern uchar *_ma_fetch_keypage(MARIA_HA *info, MARIA_KEYDEF *keyinfo, - my_off_t page, int level, uchar *buff, +extern byte *_ma_fetch_keypage(MARIA_HA *info, MARIA_KEYDEF *keyinfo, + my_off_t page, int level, byte *buff, int return_buffer); extern int _ma_write_keypage(MARIA_HA *info, MARIA_KEYDEF *keyinfo, - my_off_t page, int level, uchar *buff); + my_off_t page, int level, byte *buff); extern int _ma_dispose(MARIA_HA *info, MARIA_KEYDEF *keyinfo, my_off_t pos, int level); extern my_off_t _ma_new(MARIA_HA *info, MARIA_KEYDEF *keyinfo, int level); -extern uint _ma_make_key(MARIA_HA *info, uint keynr, uchar *key, - const byte *record, my_off_t filepos); -extern uint _ma_pack_key(MARIA_HA *info, uint keynr, uchar *key, - uchar *old, uint key_length, +extern uint _ma_make_key(MARIA_HA *info, uint keynr, byte *key, + const byte *record, MARIA_RECORD_POS filepos); +extern uint _ma_pack_key(MARIA_HA *info, uint keynr, byte *key, + const byte *old, uint key_length, HA_KEYSEG ** last_used_keyseg); -extern int _ma_read_key_record(MARIA_HA *info, my_off_t filepos, - byte *buf); -extern int _ma_read_cache(IO_CACHE *info, byte *buff, my_off_t pos, +extern int _ma_read_key_record(MARIA_HA *info, byte *buf, MARIA_RECORD_POS); +extern int _ma_read_cache(IO_CACHE *info, byte *buff, MARIA_RECORD_POS pos, uint length, int re_read_if_possibly); extern ulonglong ma_retrieve_auto_increment(MARIA_HA *info, const byte *record); -extern byte *_ma_alloc_rec_buff(MARIA_HA *, ulong, byte **); -#define _ma_get_rec_buff_ptr(info,buf) \ - ((((info)->s->options & HA_OPTION_PACK_RECORD) && (buf)) ? \ - (buf) - MARIA_REC_BUFF_OFFSET : (buf)) -#define _ma_get_rec_buff_len(info,buf) \ - (*((uint32 *)(_ma_get_rec_buff_ptr(info,buf)))) - +extern my_bool _ma_alloc_buffer(byte **old_addr, my_size_t *old_size, + my_size_t new_size); extern ulong _ma_rec_unpack(MARIA_HA *info, byte *to, byte *from, ulong reclength); extern my_bool _ma_rec_check(MARIA_HA *info, const char *record, @@ -592,11 +695,13 @@ extern int _ma_write_part_record(MARIA_HA *info, my_off_t filepos, byte ** record, ulong *reclength, int *flag); extern void _ma_print_key(FILE *stream, HA_KEYSEG *keyseg, - const uchar *key, uint length); -extern my_bool _ma_read_pack_info(MARIA_HA *info, pbool fix_keys); -extern int _ma_read_pack_record(MARIA_HA *info, my_off_t filepos, - byte *buf); -extern int _ma_read_rnd_pack_record(MARIA_HA *, byte *, my_off_t, my_bool); + const byte *key, uint length); +extern my_bool _ma_once_init_pack_row(MARIA_SHARE *share, File dfile); +extern my_bool _ma_once_end_pack_row(MARIA_SHARE *share); +extern int _ma_read_pack_record(MARIA_HA *info, byte *buf, + MARIA_RECORD_POS filepos); +extern int _ma_read_rnd_pack_record(MARIA_HA *, byte *, MARIA_RECORD_POS, + my_bool); extern int _ma_pack_rec_unpack(MARIA_HA *info, byte *to, byte *from, ulong reclength); extern ulonglong _ma_safe_mul(ulonglong a, ulonglong b); @@ -613,9 +718,9 @@ typedef struct st_maria_block_info ulong data_len; ulong block_len; ulong blob_len; - my_off_t filepos; - my_off_t next_filepos; - my_off_t prev_filepos; + MARIA_RECORD_POS filepos; + MARIA_RECORD_POS next_filepos; + MARIA_RECORD_POS prev_filepos; uint second_read; uint offset; } MARIA_BLOCK_INFO; @@ -672,11 +777,10 @@ extern uint _ma_nommap_pwrite(MARIA_HA *info, byte *Buffer, uint Count, my_off_t offset, myf MyFlags); uint _ma_state_info_write(File file, MARIA_STATE_INFO *state, uint pWrite); -uchar *_ma_state_info_read(uchar *ptr, MARIA_STATE_INFO *state); +byte *_ma_state_info_read(byte *ptr, MARIA_STATE_INFO *state); uint _ma_state_info_read_dsk(File file, MARIA_STATE_INFO *state, my_bool pRead); uint _ma_base_info_write(File file, MARIA_BASE_INFO *base); -uchar *_ma_n_base_info_read(uchar *ptr, MARIA_BASE_INFO *base); int _ma_keyseg_write(File file, const HA_KEYSEG *keyseg); char *_ma_keyseg_read(char *ptr, HA_KEYSEG *keyseg); uint _ma_keydef_write(File file, MARIA_KEYDEF *keydef); @@ -690,14 +794,14 @@ ha_checksum _ma_checksum(MARIA_HA *info, const byte *buf); ha_checksum _ma_static_checksum(MARIA_HA *info, const byte *buf); my_bool _ma_check_unique(MARIA_HA *info, MARIA_UNIQUEDEF *def, byte *record, ha_checksum unique_hash, - my_off_t pos); + MARIA_RECORD_POS pos); ha_checksum _ma_unique_hash(MARIA_UNIQUEDEF *def, const byte *buf); -int _ma_cmp_static_unique(MARIA_HA *info, MARIA_UNIQUEDEF *def, - const byte *record, my_off_t pos); -int _ma_cmp_dynamic_unique(MARIA_HA *info, MARIA_UNIQUEDEF *def, - const byte *record, my_off_t pos); -int _ma_unique_comp(MARIA_UNIQUEDEF *def, const byte *a, const byte *b, - my_bool null_are_equal); +my_bool _ma_cmp_static_unique(MARIA_HA *info, MARIA_UNIQUEDEF *def, + const byte *record, MARIA_RECORD_POS pos); +my_bool _ma_cmp_dynamic_unique(MARIA_HA *info, MARIA_UNIQUEDEF *def, + const byte *record, MARIA_RECORD_POS pos); +my_bool _ma_unique_comp(MARIA_UNIQUEDEF *def, const byte *a, const byte *b, + my_bool null_are_equal); void _ma_get_status(void *param, int concurrent_insert); void _ma_update_status(void *param); void _ma_copy_status(void *to, void *from); @@ -711,6 +815,9 @@ void _ma_setup_functions(register MARIA_SHARE *share); my_bool _ma_dynmap_file(MARIA_HA *info, my_off_t size); void _ma_remap_file(MARIA_HA *info, my_off_t size); +MARIA_RECORD_POS _ma_write_init_default(MARIA_HA *info, const byte *record); +my_bool _ma_write_abort_default(MARIA_HA *info); + /* Functions needed by _ma_check (are overrided in MySQL) */ C_MODE_START volatile int *_ma_killed_ptr(HA_CHECK *param); diff --git a/storage/maria/maria_ftdump.c b/storage/maria/maria_ftdump.c index b840072aed0..0faa64327eb 100644 --- a/storage/maria/maria_ftdump.c +++ b/storage/maria/maria_ftdump.c @@ -106,7 +106,7 @@ int main(int argc,char *argv[]) maria_lock_database(info, F_EXTRA_LCK); - info->lastpos= HA_OFFSET_ERROR; + info->cur_row.lastpos= HA_OFFSET_ERROR; info->update|= HA_STATE_PREV_FOUND; while (!(error=maria_rnext(info,NULL,inx))) @@ -157,9 +157,9 @@ int main(int argc,char *argv[]) if (dump) { if (subkeys>=0) - printf("%9lx %20.7f %s\n", (long) info->lastpos,weight,buf); + printf("%9lx %20.7f %s\n", (long) info->cur_row.lastpos,weight,buf); else - printf("%9lx => %17d %s\n",(long) info->lastpos,-subkeys,buf); + printf("%9lx => %17d %s\n",(long) info->cur_row.lastpos,-subkeys,buf); } if (verbose && (total%HOW_OFTEN_TO_WRITE)==0) printf("%10ld\r",total); diff --git a/storage/maria/maria_pack.c b/storage/maria/maria_pack.c index c5a53b1ffac..e4e38cb6e9d 100644 --- a/storage/maria/maria_pack.c +++ b/storage/maria/maria_pack.c @@ -239,7 +239,7 @@ int main(int argc, char **argv) } } if (ok && isamchk_neaded && !silent) - puts("Remember to run mariachk -rq on compressed tables"); + puts("Remember to run maria_chk -rq on compressed tables"); VOID(fflush(stdout)); VOID(fflush(stderr)); free_defaults(default_argv); @@ -294,7 +294,7 @@ static struct my_option my_long_options[] = static void print_version(void) { - VOID(printf("%s Ver 1.23 for %s on %s\n", + VOID(printf("%s Ver 1.0 for %s on %s\n", my_progname, SYSTEM_TYPE, MACHINE_TYPE)); NETWARE_SET_SCREEN_MODE(1); } @@ -308,7 +308,7 @@ static void usage(void) puts("and you are welcome to modify and redistribute it under the GPL license\n"); puts("Pack a MARIA-table to take much less space."); - puts("Keys are not updated, you must run mariachk -rq on the datafile"); + puts("Keys are not updated, you must run maria_chk -rq on the datafile"); puts("afterwards to update the keys."); puts("You should give the .MYI file as the filename argument."); @@ -359,7 +359,7 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)), silent= 0; break; case '#': - DBUG_PUSH(argument ? argument : "d:t:o"); + DBUG_PUSH(argument ? argument : "d:t:o,/tmp/maria_pack.trace"); break; case 'V': print_version(); @@ -665,7 +665,7 @@ static int compress(PACK_MRG_INFO *mrg,char *result_table) /* Display statistics. */ DBUG_PRINT("info", ("Min record length: %6d Max length: %6d " - "Mean total length: %6ld\n", + "Mean total length: %6ld", mrg->min_pack_length, mrg->max_pack_length, (ulong) (mrg->records ? (new_length/mrg->records) : 0))); if (verbose && mrg->records) @@ -681,6 +681,7 @@ static int compress(PACK_MRG_INFO *mrg,char *result_table) { error|=my_close(isam_file->dfile,MYF(MY_WME)); isam_file->dfile= -1; /* Tell maria_close file is closed */ + isam_file->s->bitmap.file= -1; } } @@ -841,32 +842,27 @@ static void free_counts_and_tree_and_queue(HUFF_TREE *huff_trees, uint trees, static int get_statistic(PACK_MRG_INFO *mrg,HUFF_COUNTS *huff_counts) { int error; - uint length; + uint length, null_bytes; ulong reclength,max_blob_length; byte *record,*pos,*next_pos,*end_pos,*start_pos; ha_rows record_count; - my_bool static_row_size; HUFF_COUNTS *count,*end_count; TREE_ELEMENT *element; + ha_checksum(*calc_checksum) (struct st_maria_info *, const byte *); DBUG_ENTER("get_statistic"); - reclength=mrg->file[0]->s->base.reclength; + reclength= mrg->file[0]->s->base.reclength; + null_bytes= mrg->file[0]->s->base.null_bytes; record=(byte*) my_alloca(reclength); end_count=huff_counts+mrg->file[0]->s->base.fields; record_count=0; glob_crc=0; max_blob_length=0; /* Check how to calculate checksum */ - static_row_size=1; - for (count=huff_counts ; count < end_count ; count++) - { - if (count->field_type == FIELD_BLOB || - count->field_type == FIELD_VARCHAR) - { - static_row_size=0; - break; - } - } + if (mrg->file[0]->s->data_file_type == STATIC_RECORD) + calc_checksum= _ma_static_checksum; + else + calc_checksum= _ma_checksum; mrg_reset(mrg); while ((error=mrg_rrnd(mrg,record)) != HA_ERR_END_OF_FILE) @@ -875,13 +871,10 @@ static int get_statistic(PACK_MRG_INFO *mrg,HUFF_COUNTS *huff_counts) if (! error) { /* glob_crc is a checksum over all bytes of all records. */ - if (static_row_size) - glob_crc+=_ma_static_checksum(mrg->file[0],record); - else - glob_crc+=_ma_checksum(mrg->file[0],record); + glob_crc+= (*calc_checksum)(mrg->file[0],record); /* Count the incidence of values separately for every column. */ - for (pos=record,count=huff_counts ; + for (pos=record + null_bytes, count=huff_counts ; count < end_count ; count++, pos=next_pos) @@ -1109,14 +1102,14 @@ static int get_statistic(PACK_MRG_INFO *mrg,HUFF_COUNTS *huff_counts) DBUG_PRINT("info", ("column: %3lu", count - huff_counts + 1)); if (verbose >= 2) - VOID(printf("column: %3lu\n", count - huff_counts + 1)); + VOID(printf("column: %3u\n", count - huff_counts + 1)); if (count->tree_buff) { DBUG_PRINT("info", ("number of distinct values: %lu", (count->tree_pos - count->tree_buff) / count->field_length)); if (verbose >= 2) - VOID(printf("number of distinct values: %lu\n", + VOID(printf("number of distinct values: %u\n", (count->tree_pos - count->tree_buff) / count->field_length)); } @@ -1368,7 +1361,8 @@ static void check_counts(HUFF_COUNTS *huff_counts, uint trees, DBUG_VOID_RETURN; } - /* Test if we can use space-compression and empty-field-compression */ + +/* Test if we can use space-compression and empty-field-compression */ static int test_space_compress(HUFF_COUNTS *huff_counts, my_off_t records, @@ -2281,7 +2275,7 @@ static my_off_t write_huff_tree(HUFF_TREE *huff_tree, uint trees) if (bits > 8 * sizeof(code)) { VOID(fflush(stdout)); - VOID(fprintf(stderr, "error: Huffman code too long: %u/%lu\n", + VOID(fprintf(stderr, "error: Huffman code too long: %u/%u\n", bits, 8 * sizeof(code))); errors++; break; @@ -2410,8 +2404,8 @@ static uint max_bit(register uint value) static int compress_isam_file(PACK_MRG_INFO *mrg, HUFF_COUNTS *huff_counts) { int error; - uint i,max_calc_length,pack_ref_length,min_record_length,max_record_length, - intervall,field_length,max_pack_length,pack_blob_length; + uint i,max_calc_length,pack_ref_length,min_record_length,max_record_length; + uint intervall,field_length,max_pack_length,pack_blob_length, null_bytes; my_off_t record_count; char llbuf[32]; ulong length,pack_length; @@ -2429,6 +2423,7 @@ static int compress_isam_file(PACK_MRG_INFO *mrg, HUFF_COUNTS *huff_counts) end_count=huff_counts+isam_file->s->base.fields; min_record_length= (uint) ~0; max_record_length=0; + null_bytes= isam_file->s->base.null_bytes; /* Calculate the maximum number of bits required to pack the records. @@ -2439,7 +2434,8 @@ static int compress_isam_file(PACK_MRG_INFO *mrg, HUFF_COUNTS *huff_counts) Empty blobs and varchar are encoded with a single 1 bit. Other blobs and varchar get a leading 0 bit. */ - for (i=max_calc_length=0 ; i < isam_file->s->base.fields ; i++) + max_calc_length= null_bytes; + for (i= 0 ; i < isam_file->s->base.fields ; i++) { if (!(huff_counts[i].pack_type & PACK_TYPE_ZERO_FILL)) huff_counts[i].max_zero_fill=0; @@ -2475,8 +2471,16 @@ static int compress_isam_file(PACK_MRG_INFO *mrg, HUFF_COUNTS *huff_counts) if (flush_buffer((ulong) max_calc_length + (ulong) max_pack_length)) break; record_pos= (byte*) file_buffer.pos; - file_buffer.pos+=max_pack_length; - for (start_pos=record, count= huff_counts; count < end_count ; count++) + file_buffer.pos+= max_pack_length; + if (null_bytes) + { + /* Copy null bits 'as is' */ + memcpy(file_buffer.pos, record, null_bytes); + file_buffer.pos+= null_bytes; + } + for (start_pos=record+null_bytes, count= huff_counts; + count < end_count ; + count++) { end_pos=start_pos+(field_length=count->field_length); tree=count->tree; @@ -2738,8 +2742,9 @@ static int compress_isam_file(PACK_MRG_INFO *mrg, HUFF_COUNTS *huff_counts) length=(ulong) ((byte*) file_buffer.pos - record_pos) - max_pack_length; pack_length= _ma_save_pack_length(pack_version, record_pos, length); if (pack_blob_length) - pack_length+= _ma_save_pack_length(pack_version, record_pos + pack_length, - tot_blob_length); + pack_length+= _ma_save_pack_length(pack_version, + record_pos + pack_length, + tot_blob_length); DBUG_PRINT("fields", ("record: %lu length: %lu blob-length: %lu " "length-bytes: %lu", (ulong) record_count, length, tot_blob_length, pack_length)); @@ -2934,7 +2939,8 @@ static void flush_bits(void) ** functions to handle the joined files ****************************************************************************/ -static int save_state(MARIA_HA *isam_file,PACK_MRG_INFO *mrg,my_off_t new_length, +static int save_state(MARIA_HA *isam_file,PACK_MRG_INFO *mrg, + my_off_t new_length, ha_checksum crc) { MARIA_SHARE *share=isam_file->s; @@ -2944,6 +2950,8 @@ static int save_state(MARIA_HA *isam_file,PACK_MRG_INFO *mrg,my_off_t new_length options|= HA_OPTION_COMPRESS_RECORD | HA_OPTION_READ_ONLY_DATA; mi_int2store(share->state.header.options,options); + share->state.header.org_data_file_type= share->state.header.data_file_type; + share->state.header.data_file_type= COMPRESSED_RECORD; share->state.state.data_file_length=new_length; share->state.state.del=0; @@ -2962,14 +2970,13 @@ static int save_state(MARIA_HA *isam_file,PACK_MRG_INFO *mrg,my_off_t new_length } /* If there are no disabled indexes, keep key_file_length value from - original file so "mariachk -rq" can use this value (this is necessary + original file so "maria_chk -rq" can use this value (this is necessary because index size cannot be easily calculated for fulltext keys) */ maria_clear_all_keys_active(share->state.key_map); for (key=0 ; key < share->base.keys ; key++) share->state.key_root[key]= HA_OFFSET_ERROR; - for (key=0 ; key < share->state.header.max_block_size_index ; key++) - share->state.key_del[key]= HA_OFFSET_ERROR; + share->state.key_del= HA_OFFSET_ERROR; isam_file->state->checksum=crc; /* Save crc here */ share->changed=1; /* Force write of header */ share->state.open_count=0; @@ -3037,21 +3044,18 @@ static int mrg_rrnd(PACK_MRG_INFO *info,byte *buf) info->end=info->current+info->count; maria_reset(isam_info); maria_extra(isam_info, HA_EXTRA_CACHE, 0); - filepos=isam_info->s->pack.header_length; + if ((error= maria_scan_init(isam_info))) + return(error); } else - { isam_info= *info->current; - filepos= isam_info->nextpos; - } for (;;) { - isam_info->update&= HA_STATE_CHANGED; - if (!(error=(*isam_info->s->read_rnd)(isam_info,(byte*) buf, - filepos, 1)) || + if (!(error= maria_scan(isam_info, buf)) || error != HA_ERR_END_OF_FILE) return (error); + maria_scan_end(isam_info); maria_extra(isam_info,HA_EXTRA_NO_CACHE, 0); if (info->current+1 == info->end) return(HA_ERR_END_OF_FILE); @@ -3060,6 +3064,8 @@ static int mrg_rrnd(PACK_MRG_INFO *info,byte *buf) filepos=isam_info->s->pack.header_length; maria_reset(isam_info); maria_extra(isam_info,HA_EXTRA_CACHE, 0); + if ((error= maria_scan_init(isam_info))) + return(error); } } @@ -3068,11 +3074,13 @@ static int mrg_close(PACK_MRG_INFO *mrg) { uint i; int error=0; + DBUG_ENTER("mrg_close"); + for (i=0 ; i < mrg->count ; i++) error|=maria_close(mrg->file[i]); if (mrg->free_file) my_free((gptr) mrg->file,MYF(0)); - return error; + DBUG_RETURN(error); } |