Fixes after review of guilhem of block record patch

Short overview:
Changed a lot of variable, functions, defines and struct elements to use more readable names
More comments (mostly function and structure slot comments)

Other things:
Changed 'USE_WHOLE_KEY' to a big number to not interfer with long keys
Ensure that tail block are at least of size 'MIN_TAIL_SIZE'
Allow longer keys and key parts than before (don't limit Maria interface by HA_MAX_KEY_LENGTH)
Use ma_chsize() to write initial bitmap page
Added checking if using file with wrong block_size
Added issing types to type_names[] (for maria_chk -d)
Added maria_max_key_length()


include/maria.h:
  Changed maria_portable_size_char_ptr to portable_size_char_ptr and moved it to my_handler.h
  Removed not used variable maria_delay_rec_write.
  More comments
include/my_handler.h:
  Added portable_sizeof_char_ptr
include/myisam.h:
  Changed mi_portable_size_char_ptr to portable_size_char_ptr and moved it to my_handler.h
mysql-test/r/maria.result:
  Fix results when we now have a longer key length
mysql-test/t/maria.test:
  More tests
mysys/my_pread.c:
  Code cleanup
sql/net_serv.cc:
  Changed warning to note (as in main 5.1 tree) to avoid not critical failing tests
sql/sql_select.cc:
  Use portable_sizeof_char_ptr
storage/maria/ha_maria.cc:
  Added max_supported_key_length(), as this is not a trival function anymore
storage/maria/ha_maria.h:
  Moved max_supported_key_length(), as this is not a trival function anymore
storage/maria/ma_bitmap.c:
  Lots of new comments
  Added maria_bitmap_marker[] to mark 2 last bytes of each bitmap (for corruption detection)
  Trivial code changes (based on review comments)
storage/maria/ma_blockrec.c:
  More code comments
  Renamed _block_row() functions to _block_record()
  Trivial code changes, based on review comments
  Moved Code from maria_close() to _ma_end_block_record()
  Some function renames to make things more understandable
  DIR_ENTRY_OFFSET -> DIR_COUNT_OFFSET
  keybuff_used -> keyread_buff_used
  ma_recordpos_to_offset -> ma_recordpos_to_dir_entry
  Changed some 'rec' named variables to 'column'.
  Ensure that tail block are at least of size 'MIN_TAIL_SIZE'
storage/maria/ma_blockrec.h:
  More comments
  DIRCOUNT_SIZE -> DIR_COUNT_SIZE
  Added define for maira_bitmap_marker[]
  ma_recordpos_to_offset -> ma_recordpos_to_dir_entry
  xxx_block_row() -> xxx_block_record()
  Made _ma_read_bitmap_page() static
storage/maria/ma_check.c:
  More comments
  ma_recordpos_to_offset() -> ma_recordpos_to_dir_entry()
  DIR_ENTRY_OFFSET -> DIR_COUNT_OFFSET
  rec variables -> column variables
  recdef -> columndef
storage/maria/ma_checksum.c:
  rec -> column
  Avoid an 'if' in _ma_checksum() for the common case
storage/maria/ma_close.c:
  Moved resetting of info->dfile to ma_end_once_block_record()
storage/maria/ma_create.c:
  Some variable changes to make things more readable:
  recinfo -> columndef
  rec -> column
  rec_end -> end_column
  record_type -> datafile_type
  ma_recinfo_write() -> ma_columndef_write()
  Fixed wrong setting of 'data_file_length'; Now max_rows should be calculated correctly
  New check if too long key.
  Use ma_chsize() to write bitmap page.
storage/maria/ma_delete.c:
  keybuff_used -> keyread_buff_used
storage/maria/ma_dynrec.c:
  rec -> columndef
  rec_length -> column_length
  maria_portable_sizeof_char_ptr -> portable_sizeof_char_ptr
  Better comment for _ma_read_rnd_dynamic_record()
storage/maria/ma_ft_eval.c:
  maria_portable_sizeof_char_ptr -> portable_sizeof_char_ptr
storage/maria/ma_ft_test1.c:
  maria_portable_sizeof_char_ptr -> portable_sizeof_char_ptr
storage/maria/ma_ft_update.c:
  keybuff_used -> keyread_buff_used
storage/maria/ma_info.c:
  More comments
storage/maria/ma_open.c:
  Added checking if using file with wrong block_size
  New checking of max_key_length
  rec -> columndef
  _ma_recinfo_write -> _ma_columndef_write
  Don't change block_size (as this is checked in ma_create())
  More comments
storage/maria/ma_packrec.c:
  Trivial code changes
  rec -> columndef
  maria_portable_sizeof_char_ptr -> portable_sizeof_char_ptr
storage/maria/ma_page.c:
  keybuff_used -> keyread_buff_used
storage/maria/ma_rkey.c:
  Removed not needded empty line
storage/maria/ma_rrnd.c:
  Removed not used variable
storage/maria/ma_rt_index.c:
  keybuff_used -> keyread_buff_used
storage/maria/ma_search.c:
  keybuff_used -> keyread_buff_used
  Trivial code changes
storage/maria/ma_sp_test.c:
  maria_portable_sizeof_char_ptr -> portable_sizeof_char_ptr
storage/maria/ma_test1.c:
  maria_portable_sizeof_char_ptr -> portable_sizeof_char_ptr
storage/maria/ma_test2.c:
  maria_portable_sizeof_char_ptr -> portable_sizeof_char_ptr
storage/maria/ma_update.c:
  Updated comment
storage/maria/ma_write.c:
  keybuff_used -> keyread_buff_used
storage/maria/maria_chk.c:
  Added missing types to type_names[]
  Removed not used variable
  rec -> columndef
  Replaced some numbers with define flags
storage/maria/maria_def.h:
  More comments
  Added 'MARIA_INDEX_MIN_OVERHEAD_SIZE'
  rec -> columndef
  keybuff_used -> keyread_buff_used
  _ma_recinfo_write -> _ma_culumndef_write
  _ma_recinfo_read -> _ma_columndef_read
  Changed 'USE_WHOLE_KEY' to a big number to not interfer with long keys
  Added maria_max_key_length()
storage/maria/maria_pack.c:
  Updated message strings
  rec -> columndef
  maria_portable_sizeof_char_ptr -> portable_sizeof_char_ptr
  More comments
storage/myisam/ft_eval.c:
  mi_portable_sizeof_char_ptr -> portable_sizeof_char_ptr
storage/myisam/ft_test1.c:
  mi_portable_sizeof_char_ptr -> portable_sizeof_char_ptr
storage/myisam/mi_checksum.c:
  mi_portable_sizeof_char_ptr -> portable_sizeof_char_ptr
storage/myisam/mi_create.c:
  mi_portable_sizeof_char_ptr -> portable_sizeof_char_ptr
storage/myisam/mi_dynrec.c:
  mi_portable_sizeof_char_ptr -> portable_sizeof_char_ptr
storage/myisam/mi_open.c:
  mi_portable_sizeof_char_ptr -> portable_sizeof_char_ptr
storage/myisam/mi_packrec.c:
  mi_portable_sizeof_char_ptr -> portable_sizeof_char_ptr
storage/myisam/mi_rkey.c:
  Unlock mutex also in case of error
storage/myisam/mi_test1.c:
  mi_portable_sizeof_char_ptr -> portable_sizeof_char_ptr
storage/myisam/mi_test2.c:
  mi_portable_sizeof_char_ptr -> portable_sizeof_char_ptr
storage/myisam/myisampack.c:
  mi_portable_sizeof_char_ptr -> portable_sizeof_char_ptr
storage/myisam/sp_test.c:
  mi_portable_sizeof_char_ptr -> portable_sizeof_char_ptr
support-files/magic:
  Fixed typo
This commit is contained in:
unknown 2007-04-19 13:18:56 +03:00
parent 1bf0ed7754
commit eb7d9500a9
51 changed files with 997 additions and 555 deletions

View file

@ -54,8 +54,6 @@ extern "C" {
#define MARIA_KEY_BLOCK_LENGTH 8192 /* default key block length */
#define MARIA_MIN_KEY_BLOCK_LENGTH 1024 /* Min key block length */
#define MARIA_MAX_KEY_BLOCK_LENGTH 32768
#define maria_portable_sizeof_char_ptr 8
#define MARIA_MAX_KEY_LENGTH 1000 /* Max length in bytes */
/*
In the following macros '_keyno_' is 0 .. keys-1.
@ -150,6 +148,7 @@ typedef struct st_maria_create_info
ulonglong auto_increment;
ulonglong data_file_length;
ulonglong key_file_length;
/* Size of null bitmap at start of row */
uint null_bytes;
uint old_options;
enum data_file_type org_data_file_type;
@ -226,11 +225,13 @@ typedef struct st_maria_columndef /* column information */
uint64 offset; /* Offset to position in row */
enum en_fieldtype type;
uint16 length; /* length of field */
/* Intern variable (size of total storage area for the row) */
uint16 fill_length;
uint16 null_pos; /* Position for null marker */
uint16 empty_pos; /* Position for empty marker */
uint8 null_bit; /* If column may be NULL */
uint8 empty_bit; /* If column may be empty */
/* Intern. Set if column should be zero packed (part of empty_bits) */
uint8 empty_bit;
#ifndef NOT_PACKED_DATABASES
void(*unpack)(struct st_maria_columndef *rec,
@ -246,7 +247,7 @@ typedef struct st_maria_columndef /* column information */
extern ulong maria_block_size;
extern ulong maria_concurrent_insert;
extern my_bool maria_flush, maria_single_user;
extern my_bool maria_delay_key_write, maria_delay_rec_write;
extern my_bool maria_delay_key_write;
extern my_off_t maria_max_temp_length;
extern ulong maria_bulk_insert_tree_size, maria_data_pointer_size;
extern KEY_CACHE maria_key_cache_var, *maria_key_cache;

View file

@ -111,4 +111,11 @@ extern int ha_key_cmp(register HA_KEYSEG *keyseg, register uchar *a,
extern HA_KEYSEG *ha_find_null(HA_KEYSEG *keyseg, uchar *a);
/*
Inside an in-memory data record, memory pointers to pieces of the
record (like BLOBs) are stored in their native byte order and in
this amount of bytes.
*/
#define portable_sizeof_char_ptr 8
#endif /* _my_handler_h */

View file

@ -55,8 +55,6 @@ extern "C" {
#define MI_MIN_KEY_BLOCK_LENGTH 1024 /* Min key block length */
#define MI_MAX_KEY_BLOCK_LENGTH 16384
#define mi_portable_sizeof_char_ptr 8
/*
In the following macros '_keyno_' is 0 .. keys-1.
If there can be more keys than bits in the key_map, the highest bit

View file

@ -325,10 +325,14 @@ Table Op Msg_type Msg_text
test.t1 check status OK
drop table t1;
CREATE TABLE t1 (a varchar(255), b varchar(255), c varchar(255), d varchar(255), e varchar(255), KEY t1 (a, b, c, d, e));
ERROR 42000: Specified key was too long; max key length is 1000 bytes
ERROR 42000: Specified key was too long; max key length is 1112 bytes
CREATE TABLE t1 (a varchar(32000), unique key(a));
ERROR 42000: Specified key was too long; max key length is 1112 bytes
CREATE TABLE t1 (a varchar(1), b varchar(1), key (a,b,a,b,a,b,a,b,a,b,a,b,a,b,a,b,a,b,a,b,a,b,a,b,a,b,a,b,a,b,a,b,a,b,a,b));
ERROR 42000: Too many key parts specified; max 16 parts allowed
CREATE TABLE t1 (a varchar(255), b varchar(255), c varchar(255), d varchar(255), e varchar(255));
ALTER TABLE t1 ADD INDEX t1 (a, b, c, d, e);
ERROR 42000: Specified key was too long; max key length is 1000 bytes
ERROR 42000: Specified key was too long; max key length is 1112 bytes
DROP TABLE t1;
CREATE TABLE t1 (a int not null, b int, c int, key(b), key(c), key(a,b), key(c,a));
INSERT into t1 values (0, null, 0), (0, null, 1), (0, null, 2), (0, null,3), (1,1,4);
@ -1476,7 +1480,7 @@ a b
drop table t1;
create table t1 (v varchar(65530), key(v));
Warnings:
Warning 1071 Specified key was too long; max key length is 1000 bytes
Warning 1071 Specified key was too long; max key length is 1112 bytes
drop table if exists t1;
create table t1 (v varchar(65536));
Warnings:
@ -1607,34 +1611,34 @@ t1 CREATE TABLE `t1` (
drop table t1;
create table t1 (a varchar(2048), key `a` (a));
Warnings:
Warning 1071 Specified key was too long; max key length is 1000 bytes
Warning 1071 Specified key was too long; max key length is 1112 bytes
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
`a` varchar(2048) DEFAULT NULL,
KEY `a` (`a`(1000))
KEY `a` (`a`(1112))
) ENGINE=MARIA DEFAULT CHARSET=latin1
drop table t1;
create table t1 (a varchar(2048), key `a` (a) key_block_size=1024);
Warnings:
Warning 1071 Specified key was too long; max key length is 1000 bytes
Warning 1071 Specified key was too long; max key length is 1112 bytes
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
`a` varchar(2048) DEFAULT NULL,
KEY `a` (`a`(1000)) KEY_BLOCK_SIZE=8192
KEY `a` (`a`(1112)) KEY_BLOCK_SIZE=8192
) ENGINE=MARIA DEFAULT CHARSET=latin1
drop table t1;
create table t1 (a int not null, b varchar(2048), key (a), key(b)) key_block_size=1024;
Warnings:
Warning 1071 Specified key was too long; max key length is 1000 bytes
Warning 1071 Specified key was too long; max key length is 1112 bytes
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
`a` int(11) NOT NULL,
`b` varchar(2048) DEFAULT NULL,
KEY `a` (`a`) KEY_BLOCK_SIZE=8192,
KEY `b` (`b`(1000)) KEY_BLOCK_SIZE=8192
KEY `b` (`b`(1112)) KEY_BLOCK_SIZE=8192
) ENGINE=MARIA DEFAULT CHARSET=latin1 KEY_BLOCK_SIZE=1024
alter table t1 key_block_size=2048;
show create table t1;
@ -1643,7 +1647,7 @@ t1 CREATE TABLE `t1` (
`a` int(11) NOT NULL,
`b` varchar(2048) DEFAULT NULL,
KEY `a` (`a`) KEY_BLOCK_SIZE=8192,
KEY `b` (`b`(1000)) KEY_BLOCK_SIZE=8192
KEY `b` (`b`(1112)) KEY_BLOCK_SIZE=8192
) ENGINE=MARIA DEFAULT CHARSET=latin1 KEY_BLOCK_SIZE=2048
alter table t1 add c int, add key (c);
show create table t1;
@ -1653,7 +1657,7 @@ t1 CREATE TABLE `t1` (
`b` varchar(2048) DEFAULT NULL,
`c` int(11) DEFAULT NULL,
KEY `a` (`a`) KEY_BLOCK_SIZE=8192,
KEY `b` (`b`(1000)) KEY_BLOCK_SIZE=8192,
KEY `b` (`b`(1112)) KEY_BLOCK_SIZE=8192,
KEY `c` (`c`) KEY_BLOCK_SIZE=8192
) ENGINE=MARIA DEFAULT CHARSET=latin1 KEY_BLOCK_SIZE=2048
alter table t1 key_block_size=0;
@ -1666,33 +1670,33 @@ t1 CREATE TABLE `t1` (
`c` int(11) DEFAULT NULL,
`d` int(11) DEFAULT NULL,
KEY `a` (`a`) KEY_BLOCK_SIZE=8192,
KEY `b` (`b`(1000)) KEY_BLOCK_SIZE=8192,
KEY `b` (`b`(1112)) KEY_BLOCK_SIZE=8192,
KEY `c` (`c`) KEY_BLOCK_SIZE=8192,
KEY `d` (`d`)
) ENGINE=MARIA DEFAULT CHARSET=latin1
drop table t1;
create table t1 (a int not null, b varchar(2048), key (a), key(b)) key_block_size=8192;
Warnings:
Warning 1071 Specified key was too long; max key length is 1000 bytes
Warning 1071 Specified key was too long; max key length is 1112 bytes
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
`a` int(11) NOT NULL,
`b` varchar(2048) DEFAULT NULL,
KEY `a` (`a`),
KEY `b` (`b`(1000))
KEY `b` (`b`(1112))
) ENGINE=MARIA DEFAULT CHARSET=latin1 KEY_BLOCK_SIZE=8192
drop table t1;
create table t1 (a int not null, b varchar(2048), key (a) key_block_size=1024, key(b)) key_block_size=8192;
Warnings:
Warning 1071 Specified key was too long; max key length is 1000 bytes
Warning 1071 Specified key was too long; max key length is 1112 bytes
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
`a` int(11) NOT NULL,
`b` varchar(2048) DEFAULT NULL,
KEY `a` (`a`),
KEY `b` (`b`(1000))
KEY `b` (`b`(1112))
) ENGINE=MARIA DEFAULT CHARSET=latin1 KEY_BLOCK_SIZE=8192
drop table t1;
create table t1 (a int not null, b int, key (a) key_block_size=1024, key(b) key_block_size=8192) key_block_size=16384;
@ -1715,12 +1719,12 @@ t1 CREATE TABLE `t1` (
drop table t1;
create table t1 (a varchar(2048), key `a` (a) key_block_size=1000000000000000000);
Warnings:
Warning 1071 Specified key was too long; max key length is 1000 bytes
Warning 1071 Specified key was too long; max key length is 1112 bytes
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
`a` varchar(2048) DEFAULT NULL,
KEY `a` (`a`(1000)) KEY_BLOCK_SIZE=8192
KEY `a` (`a`(1112)) KEY_BLOCK_SIZE=8192
) ENGINE=MARIA DEFAULT CHARSET=latin1
drop table t1;
create table t1 (a int not null, key `a` (a) key_block_size=1025);

View file

@ -345,6 +345,10 @@ drop table t1;
--error 1071
CREATE TABLE t1 (a varchar(255), b varchar(255), c varchar(255), d varchar(255), e varchar(255), KEY t1 (a, b, c, d, e));
--error 1071
CREATE TABLE t1 (a varchar(32000), unique key(a));
--error 1070
CREATE TABLE t1 (a varchar(1), b varchar(1), key (a,b,a,b,a,b,a,b,a,b,a,b,a,b,a,b,a,b,a,b,a,b,a,b,a,b,a,b,a,b,a,b,a,b,a,b));
CREATE TABLE t1 (a varchar(255), b varchar(255), c varchar(255), d varchar(255), e varchar(255));
--error 1071
ALTER TABLE t1 ADD INDEX t1 (a, b, c, d, e);

View file

@ -87,10 +87,8 @@ uint my_pread(File Filedes, byte *Buffer, uint Count, my_off_t offset,
my_error(EE_READ, MYF(ME_BELL+ME_WAITTANG),
my_filename(Filedes),my_errno);
else if (MyFlags & (MY_NABP | MY_FNABP))
{
my_error(EE_EOFERR, MYF(ME_BELL+ME_WAITTANG),
my_filename(Filedes),my_errno);
}
}
if ((int) readbytes == -1 || (MyFlags & (MY_FNABP | MY_NABP)))
DBUG_RETURN(MY_FILE_ERROR); /* Return with error */

View file

@ -298,8 +298,8 @@ void net_clear(NET *net, my_bool clear_buffer)
{
DBUG_PRINT("info",("skipped %d bytes from file: %s",
count, vio_description(net->vio)));
#if defined(EXTRA_DEBUG) && (MYSQL_VERSION_ID < 51000)
fprintf(stderr,"Error: net_clear() skipped %d bytes from file: %s\n",
#if defined(EXTRA_DEBUG) && (MYSQL_VERSION_ID < 50100)
fprintf(stderr,"Note: net_clear() skipped %d bytes from file: %s\n",
count, vio_description(net->vio));
#endif
}

View file

@ -9301,7 +9301,7 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
table->s= share;
init_tmp_table_share(share, "", 0, tmpname, tmpname);
share->blob_field= blob_field;
share->blob_ptr_size= mi_portable_sizeof_char_ptr;
share->blob_ptr_size= portable_sizeof_char_ptr;
share->db_low_byte_first=1; // True for HEAP and MyISAM
share->table_charset= param->table_charset;
share->primary_key= MAX_KEY; // Indicate no primary key
@ -9856,7 +9856,7 @@ TABLE *create_virtual_tmp_table(THD *thd, List<create_field> &field_list)
table->s= share;
share->blob_field= blob_field;
share->fields= field_count;
share->blob_ptr_size= mi_portable_sizeof_char_ptr;
share->blob_ptr_size= portable_sizeof_char_ptr;
setup_tmp_table_column_bitmaps(table, bitmaps);
/* Create all fields and calculate the total length of record */

View file

@ -28,6 +28,7 @@
#include "maria_def.h"
#include "ma_rt_index.h"
#include "ma_blockrec.h"
ulong maria_recover_options= HA_RECOVER_NONE;
@ -108,7 +109,6 @@ static void _ma_check_print_msg(HA_CHECK *param, const char *msg_type,
}
/*
Convert TABLE object to Maria key and column definition
@ -512,6 +512,26 @@ double ha_maria::scan_time()
return handler::scan_time();
}
/*
We need to be able to store at least two keys on an index page as the
splitting algorithms depends on this. (With only one key on a page
we also can't use any compression, which may make the index file much
larger)
We use HA_MAX_KEY_BUFF as this is a stack restriction imposed by the
handler interface.
We also need to reserve place for a record pointer (8) and 3 bytes
per key segment to store the length of the segment + possible null bytes.
These extra bytes are required here so that maria_create() will surely
accept any keys created which the returned key data storage length.
*/
uint ha_maria::max_supported_key_length() const
{
uint tmp= (maria_max_key_length() - 8 - HA_MAX_KEY_SEG*3);
return min(HA_MAX_KEY_BUFF, tmp);
}
#ifdef HAVE_REPLICATION
int ha_maria::net_read_dump(NET * net)

View file

@ -59,10 +59,9 @@ public:
}
uint max_supported_keys() const
{ return MARIA_MAX_KEY; }
uint max_supported_key_length() const
{ return HA_MAX_KEY_LENGTH; }
uint max_supported_key_length() const;
uint max_supported_key_part_length() const
{ return HA_MAX_KEY_LENGTH; }
{ return max_supported_key_length(); }
enum row_type get_row_type() const;
uint checksum() const;
virtual double scan_time();

View file

@ -30,7 +30,7 @@
2 bits are used to indicate:
0 Empty
1 50-75 % full (at least room for 2 records)
1 0-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)
@ -89,9 +89,9 @@
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.
fill this one.
- First bitmap which is not completely full. This is updated when we
free data with an update or delete.
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
@ -106,7 +106,6 @@
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"
@ -118,6 +117,15 @@
#define FULL_HEAD_PAGE 4
#define FULL_TAIL_PAGE 7
uchar maria_bitmap_marker[2]= {(uchar) 'b',(uchar) 'm'};
static my_bool _ma_read_bitmap_page(MARIA_SHARE *share,
MARIA_FILE_BITMAP *bitmap,
ulonglong page);
/* Write bitmap page to key cache */
static inline my_bool write_changed_bitmap(MARIA_SHARE *share,
MARIA_FILE_BITMAP *bitmap)
{
@ -128,7 +136,19 @@ static inline my_bool write_changed_bitmap(MARIA_SHARE *share,
}
/*
Initialize bitmap. This is called the first time a file is opened
Initialize bitmap variables in share
SYNOPSIS
_ma_bitmap_init()
share Share handler
file data file handler
NOTES
This is called the first time a file is opened.
RETURN
0 ok
1 error
*/
my_bool _ma_bitmap_init(MARIA_SHARE *share, File file)
@ -175,20 +195,21 @@ my_bool _ma_bitmap_init(MARIA_SHARE *share, File file)
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;
return _ma_read_bitmap_page(share, bitmap, (ulonglong) 0);
}
/*
Free data allocated by _ma_bitmap_init
SYNOPSIS
_ma_bitmap_end()
share Share handler
*/
my_bool _ma_bitmap_end(MARIA_SHARE *share)
{
my_bool res= 0;
_ma_flush_bitmap(share);
my_bool res= _ma_flush_bitmap(share);
pthread_mutex_destroy(&share->bitmap.bitmap_lock);
my_free((byte*) share->bitmap.map, MYF(MY_ALLOW_ZERO_PTR));
share->bitmap.map= 0;
@ -198,6 +219,20 @@ my_bool _ma_bitmap_end(MARIA_SHARE *share)
/*
Flush bitmap to disk
SYNOPSIS
_ma_flush_bitmap()
share Share handler
NOTES
In the future, _ma_flush_bitmap() will be called to flush changes don't
by this thread (ie, checking the changed flag is ok). The reason we
check it again in the mutex is that if someone else did a flush at the
same time, we don't have to do the write.
RETURN
0 ok
1 error
*/
my_bool _ma_flush_bitmap(MARIA_SHARE *share)
@ -217,12 +252,24 @@ my_bool _ma_flush_bitmap(MARIA_SHARE *share)
}
/*
Intialize bitmap in memory to a zero bitmap
SYNOPSIS
_ma_bitmap_delete_all()
share Share handler
NOTES
This is called on ma_delete_all (truncate data file).
*/
void _ma_bitmap_delete_all(MARIA_SHARE *share)
{
MARIA_FILE_BITMAP *bitmap= &share->bitmap;
if (bitmap->map) /* Not in create */
{
bzero(bitmap->map, share->block_size);
memcpy(bitmap->map + share->block_size - 2, maria_bitmap_marker, 2);
bitmap->changed= 0;
bitmap->page= 0;
bitmap->used_size= bitmap->total_size;
@ -256,7 +303,15 @@ static uint size_to_head_pattern(MARIA_FILE_BITMAP *bitmap, uint size)
/*
Return bitmap pattern for block where there is size bytes free
Return bitmap pattern for head block where there is size bytes free
SYNOPSIS
_ma_free_size_to_head_pattern()
bitmap Bitmap
size Requested size
RETURN
0-4 (Possible bitmap patterns for head block)
*/
uint _ma_free_size_to_head_pattern(MARIA_FILE_BITMAP *bitmap, uint size)
@ -294,6 +349,18 @@ static uint size_to_tail_pattern(MARIA_FILE_BITMAP *bitmap, uint size)
}
/*
Return bitmap pattern for tail block where there is size bytes free
SYNOPSIS
free_size_to_tail_pattern()
bitmap Bitmap
size Requested size
RETURN
0, 5, 6, 7 For a description of the bitmap sizes, see the header
*/
static uint free_size_to_tail_pattern(MARIA_FILE_BITMAP *bitmap, uint size)
{
if (size >= bitmap->sizes[0])
@ -310,7 +377,7 @@ static uint free_size_to_tail_pattern(MARIA_FILE_BITMAP *bitmap, uint size)
Return size guranteed to be available on a page
SYNOPSIS
pattern_to_head_size
pattern_to_head_size()
bitmap Bitmap
pattern Pattern (0-7)
@ -327,6 +394,15 @@ static inline uint pattern_to_size(MARIA_FILE_BITMAP *bitmap, uint pattern)
/*
Print bitmap for debugging
SYNOPSIS
_ma_print_bitmap()
bitmap Bitmap to print
IMPLEMENTATION
Prints all changed bits since last call to _ma_print_bitmap().
This is done by having a copy of the last bitmap in
bitmap->map+bitmap->block_size.
*/
#ifndef DBUG_OFF
@ -342,18 +418,24 @@ static void _ma_print_bitmap(MARIA_FILE_BITMAP *bitmap)
uchar *pos, *end, *org_pos;
ulong page;
end= bitmap->map+ bitmap->used_size;
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 ;
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;
/*
Test if there is any changes in the next 16 bitmaps (to not have to
loop through all bits if we know they are the same)
*/
if (bits != org_bits)
{
for (i= 0; i < 16 ; i++, bits>>= 3, org_bits>>= 3)
@ -367,7 +449,7 @@ static void _ma_print_bitmap(MARIA_FILE_BITMAP *bitmap)
}
fputc('\n', DBUG_FILE);
DBUG_UNLOCK_FILE;
memcpy(bitmap->map+ bitmap->block_size, bitmap->map, bitmap->block_size);
memcpy(bitmap->map + bitmap->block_size, bitmap->map, bitmap->block_size);
}
#endif /* DBUG_OFF */
@ -394,8 +476,9 @@ static void _ma_print_bitmap(MARIA_FILE_BITMAP *bitmap)
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)
static 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;
@ -407,6 +490,7 @@ my_bool _ma_read_bitmap_page(MARIA_SHARE *share, MARIA_FILE_BITMAP *bitmap,
{
share->state.state.data_file_length= position + bitmap->block_size;
bzero(bitmap->map, bitmap->block_size);
memcpy(bitmap->map + share->block_size - 2, maria_bitmap_marker, 2);
bitmap->used_size= 0;
DBUG_RETURN(0);
}
@ -417,7 +501,7 @@ my_bool _ma_read_bitmap_page(MARIA_SHARE *share, MARIA_FILE_BITMAP *bitmap,
bitmap->block_size, bitmap->block_size, 0) == 0;
#ifndef DBUG_OFF
if (!res)
memcpy(bitmap->map+ bitmap->block_size, bitmap->map, bitmap->block_size);
memcpy(bitmap->map + bitmap->block_size, bitmap->map, bitmap->block_size);
#endif
DBUG_RETURN(res);
}
@ -465,6 +549,10 @@ static my_bool _ma_change_bitmap_page(MARIA_HA *info,
move_to_next_bitmap()
bitmap Bitmap handle
NOTES
The found bitmap may be full, so calling function may need to call this
repeatedly until it finds enough space.
TODO
Add cache of bitmaps to not read something that is not usable
@ -505,7 +593,12 @@ static my_bool move_to_next_bitmap(MARIA_HA *info, MARIA_FILE_BITMAP *bitmap)
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
best_bits The original value of the bits at best_pos
fill_pattern Bitmap pattern to store in best_data[best_pos]
NOTES
We mark all pages to be 'TAIL's, which means that
block->page_count is really a row position inside the page.
*/
static void fill_block(MARIA_FILE_BITMAP *bitmap,
@ -523,7 +616,7 @@ static void fill_block(MARIA_FILE_BITMAP *bitmap,
block->empty_space= pattern_to_size(bitmap, best_bits);
block->sub_blocks= 1;
block->org_bitmap_value= best_bits;
block->used= BLOCKUSED_TAIL;
block->used= BLOCKUSED_TAIL; /* See _ma_bitmap_release_unused() */
/*
Mark place used by reading/writing 2 bytes at a time to handle
@ -533,6 +626,8 @@ static void fill_block(MARIA_FILE_BITMAP *bitmap,
data= best_data+ best_pos / 8;
offset= best_pos & 7;
tmp= uint2korr(data);
/* we turn off the 3 bits and replace them with fill_pattern */
tmp= (tmp & ~(7 << offset)) | (fill_pattern << offset);
int2store(data, tmp);
bitmap->changed= 1;
@ -546,9 +641,14 @@ static void fill_block(MARIA_FILE_BITMAP *bitmap,
SYNOPSIS
allocate_head()
bitmap bitmap
size Size of block we need to find
size Size of data region we need to store
block Store found information here
IMPLEMENTATION
Find the best-fit page to put a region of 'size'
This is defined as the first page of the set of pages
with the smallest free space that can hold 'size'.
RETURN
0 ok (block is updated)
1 error (no space in bitmap; block is not touched)
@ -586,9 +686,10 @@ static my_bool allocate_head(MARIA_FILE_BITMAP *bitmap, uint size,
uint pattern= bits & 7;
if (pattern <= min_bits)
{
/* There is enough space here */
if (pattern == min_bits)
{
/* Found perfect match */
/* There is exactly enough space here, return this page */
best_bits= min_bits;
best_data= data;
best_pos= i;
@ -596,6 +697,11 @@ static my_bool allocate_head(MARIA_FILE_BITMAP *bitmap, uint size,
}
if ((int) pattern > (int) best_bits)
{
/*
There is more than enough space here and it's better than what
we have found so far. Remember it, as we will choose it if we
don't find anything in this bitmap page.
*/
best_bits= pattern;
best_data= data;
best_pos= i;
@ -603,10 +709,10 @@ static my_bool allocate_head(MARIA_FILE_BITMAP *bitmap, uint size,
}
}
}
if (!best_data)
if (!best_data) /* Found no place */
{
if (bitmap->used_size == bitmap->total_size)
DBUG_RETURN(1);
DBUG_RETURN(1); /* No space in bitmap */
/* Allocate data at end of bitmap */
bitmap->used_size+= 6;
best_data= data;
@ -655,7 +761,12 @@ static my_bool allocate_tail(MARIA_FILE_BITMAP *bitmap, uint size,
/*
Skip common patterns
We can skip empty pages (if we already found a match) or
the following patterns: 1-4 or 7
the following patterns: 1-4 (head pages, not suitable for tail) or
7 (full tail page). See 'Dynamic size records' comment at start of file.
At the moment we only skip full tail pages (ie, all bits are
set) as this is easy to detect with one simple test and is a
quite common case if we have blobs.
*/
if ((!bits && best_data) || bits == LL(0xffffffffffff))
@ -888,6 +999,13 @@ static ulong allocate_full_pages(MARIA_FILE_BITMAP *bitmap,
/*
Find right bitmap and position for head block
SYNOPSIS
find_head()
info Maria handler
length Size of data region we need store
position Position in bitmap_blocks where to store the
information for the head block.
RETURN
0 ok
1 error
@ -897,7 +1015,10 @@ 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 */
/*
There is always place for the head block in bitmap_blocks as these are
preallocated at _ma_init_block_record().
*/
block= dynamic_element(&info->bitmap_blocks, position, MARIA_BITMAP_BLOCK *);
while (allocate_head(bitmap, length, block))
@ -910,6 +1031,13 @@ static my_bool find_head(MARIA_HA *info, uint length, uint position)
/*
Find right bitmap and position for tail
SYNOPSIS
find_tail()
info Maria handler
length Size of data region we need store
position Position in bitmap_blocks where to store the
information for the head block.
RETURN
0 ok
1 error
@ -936,8 +1064,15 @@ static my_bool find_tail(MARIA_HA *info, uint length, uint position)
/*
Find right bitmap and position for full blocks in one extent
SYNOPSIS
find_mid()
info Maria handler.
pages How many pages to allocate.
position Position in bitmap_blocks where to store the
information for the head block.
NOTES
This is used to allocate the main extent after the 'head' block
(Ie, the middle part of the head-middle-tail entry)
RETURN
0 ok
@ -962,6 +1097,11 @@ static my_bool find_mid(MARIA_HA *info, ulong pages, uint position)
/*
Find right bitmap and position for putting a blob
SYNOPSIS
find_blob()
info Maria handler.
length Length of the blob
NOTES
The extents are stored last in info->bitmap_blocks
@ -1023,6 +1163,19 @@ static my_bool find_blob(MARIA_HA *info, ulong length)
}
/*
Find pages to put ALL blobs
SYNOPSIS
allocate_blobs()
info Maria handler
row Information of what is in the row (from calc_record_size())
RETURN
0 ok
1 error
*/
static my_bool allocate_blobs(MARIA_HA *info, MARIA_ROW *row)
{
ulong *length, *end;
@ -1045,6 +1198,23 @@ static my_bool allocate_blobs(MARIA_HA *info, MARIA_ROW *row)
}
/*
Store in the bitmap the new size for a head page
SYNOPSIS
use_head()
info Maria handler
page Page number to update
(Note that caller guarantees this is in the active
bitmap)
size How much free space is left on the page
block_position In which info->bitmap_block we have the
information about the head block.
NOTES
This is used on update where we are updating an existing head page
*/
static void use_head(MARIA_HA *info, ulonglong page, uint size,
uint block_position)
{
@ -1078,7 +1248,18 @@ static void use_head(MARIA_HA *info, ulonglong page, uint size,
/*
Find out where to split the row;
Find out where to split the row (ie, what goes in head, middle, tail etc)
SYNOPSIS
find_where_to_split_row()
share Maria share
row Information of what is in the row (from calc_record_size())
extents_length Number of bytes needed to store all extents
split_size Free size on the page (The head length must be less
than this)
RETURN
row_length for the head block.
*/
static uint find_where_to_split_row(MARIA_SHARE *share, MARIA_ROW *row,
@ -1108,6 +1289,21 @@ static uint find_where_to_split_row(MARIA_SHARE *share, MARIA_ROW *row,
}
/*
Find where to write the middle parts of the row and the tail
SYNOPSIS
write_rest_of_head()
info Maria handler
position Position in bitmap_blocks. Is 0 for rows that needs
full blocks (ie, has a head, middle part and optional tail)
rest_length How much left of the head block to write.
RETURN
0 ok
1 error
*/
static my_bool write_rest_of_head(MARIA_HA *info, uint position,
ulong rest_length)
{
@ -1349,6 +1545,23 @@ abort:
Clear and reset bits
****************************************************************************/
/*
Set fill pattern for a page
set_page_bits()
info Maria handler
bitmap Bitmap handler
page Adress to page
fill_pattern Pattern (not size) for page
NOTES
Page may not be part of active bitmap
RETURN
0 ok
1 error
*/
static my_bool set_page_bits(MARIA_HA *info, MARIA_FILE_BITMAP *bitmap,
ulonglong page, uint fill_pattern)
{
@ -1390,11 +1603,10 @@ static my_bool set_page_bits(MARIA_HA *info, MARIA_FILE_BITMAP *bitmap,
Get bitmap pattern for a given page
SYNOPSIS
get_page_bits()
info Maria handler
bitmap Bitmap handler
page Page number
get_page_bits()
info Maria handler
bitmap Bitmap handler
page Page number
RETURN
0-7 Bitmap pattern
@ -1432,7 +1644,7 @@ static uint get_page_bits(MARIA_HA *info, MARIA_FILE_BITMAP *bitmap,
Mark all pages in a region as free
SYNOPSIS
reset_full_page_bits()
_ma_reset_full_page_bits()
info Maria handler
bitmap Bitmap handler
page Start page
@ -1579,6 +1791,11 @@ my_bool _ma_bitmap_release_unused(MARIA_HA *info, MARIA_BITMAP_BLOCKS *blocks)
}
else
bits= block->org_bitmap_value;
/*
The page has all bits set; The following test is an optimization
to not set the bits to the same value as before.
*/
if (bits != FULL_TAIL_PAGE &&
set_page_bits(info, bitmap, block->page, bits))
goto err;
@ -1638,8 +1855,22 @@ my_bool _ma_bitmap_free_full_pages(MARIA_HA *info, const byte *extents,
}
/*
Mark in the bitmap how much free space there is on a page
my_bool _ma_bitmap_set(MARIA_HA *info, ulonglong pos, my_bool head,
SYNOPSIS
_ma_bitmap_set()
info Mari handler
page Adress to page
head 1 if page is a head page, 0 if tail page
empty_space How much empty space there is on page
RETURN
0 ok
1 error
*/
my_bool _ma_bitmap_set(MARIA_HA *info, ulonglong page, my_bool head,
uint empty_space)
{
MARIA_FILE_BITMAP *bitmap= &info->s->bitmap;
@ -1651,7 +1882,7 @@ my_bool _ma_bitmap_set(MARIA_HA *info, ulonglong pos, my_bool head,
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);
res= set_page_bits(info, bitmap, page, bits);
pthread_mutex_unlock(&info->s->bitmap.bitmap_lock);
DBUG_RETURN(res);
}
@ -1663,6 +1894,15 @@ my_bool _ma_bitmap_set(MARIA_HA *info, ulonglong pos, my_bool head,
NOTES
Used in maria_chk
SYNOPSIS
_ma_check_bitmap_data()
info Maria handler
page_type What kind of page this is
page Adress to page
empty_space Empty space on page
bitmap_pattern Store here the pattern that was in the bitmap for the
page. This is always updated.
RETURN
0 ok
1 error
@ -1694,7 +1934,15 @@ my_bool _ma_check_bitmap_data(MARIA_HA *info,
/*
Check that bitmap pattern is correct for a page
Check if the page type matches the one that we have in the bitmap
SYNOPSIS
_ma_check_if_right_bitmap_type()
info Maria handler
page_type What kind of page this is
page Adress to page
bitmap_pattern Store here the pattern that was in the bitmap for the
page. This is always updated.
NOTES
Used in maria_chk

View file

@ -16,16 +16,19 @@
/*
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:
Some clarifactions about the abbrev used:
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)
NULL fields -> Fields that may have contain a NULL value.
Not null fields -> Fields that may not contain a NULL value.
Critical fields -> Fields that can't be null and can't be dropped without
causing a table reorganization.
Maria will have a LSN at start of each page (excluding the bitmap pages)
The different page types that are in a data file are:
Bitmap pages Map of free pages in the next extent (8129 page size
Bitmap pages Map of free pages in the next extent (8192 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
@ -43,9 +46,9 @@
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
without having to reorganize the page. It also allows us to later store
some more bytes after each row to allow them to grow without having to move
around other rows.
Page header:
@ -59,7 +62,7 @@
Row data
Row directory of NO entires, that consist of the following for each row
Row directory of NO entries, 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
@ -69,7 +72,8 @@
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
eof flag 1 byte Reserved for full page read testing. (Ie, did the
previous write get the whole block on disk.
----------------
@ -105,19 +109,27 @@
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.
Null_bits .. One bit for each NULL field (a field that may
have the value NULL)
Empty_bits .. One bit for each field that may be 'empty'.
(Both for null and not null fields).
This bit is 1 if the value for the field 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.
For each 32'th 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.
TODO: Implement this.
Things marked above as 'optional' will only be present if the corresponding
bit is set in 'Flag' field.
Things marked above as 'optional' will only be present if the
corresponding bit is set in 'Flag' field. Flag gives us 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.
Data in the following order:
(Field order is precalculated when table is created)
@ -176,11 +188,6 @@
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,
@ -198,8 +205,10 @@
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.
TODO: Add code for handling dropped fields.
One ROW_EXTENT is coded as:
A ROW EXTENT is range of pages. One ROW_EXTENT is coded as:
START_PAGE 5 bytes
PAGE_COUNT 2 bytes. High bit is used to indicate tail page/
@ -248,14 +257,36 @@
#include "maria_def.h"
#include "ma_blockrec.h"
/*
Struct for having a cursor over a set of extent.
This is used to loop over all extents for a row when reading
the row data. It's also used to store the tail positions for
a read row to be used by a later update/delete command.
*/
typedef struct st_maria_extent_cursor
{
/*
Pointer to packed byte array of extents for the row.
Format is described above in the header
*/
byte *extent;
byte *data_start; /* For error checking */
/* Where data starts on page; Only for debugging */
byte *data_start;
/* Position to all tails in the row. Updated when reading a row */
MARIA_RECORD_POS *tail_positions;
/* Current page */
my_off_t page;
uint extent_count, page_count;
uint tail; /* <> 0 if current extent is a tail page */
/* How many pages in the page region */
uint page_count;
/* Total number of extents (ie, entries in the 'extent' slot) */
uint extent_count;
/* <> 0 if current extent is a tail page; Set while using cursor */
uint tail;
/*
<> 1 if we are working on the first extent (ie, the one that is store in
the row header, not an extent that is stored as part of the row data).
*/
my_bool first_extent;
} MARIA_EXTENT_CURSOR;
@ -327,38 +358,47 @@ void _ma_init_block_record_data(void)
}
my_bool _ma_once_init_block_row(MARIA_SHARE *share, File data_file)
my_bool _ma_once_init_block_record(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);
set_if_smaller(share->base.max_data_file_length, INT_MAX32);
#endif
return _ma_bitmap_init(share, data_file);
}
my_bool _ma_once_end_block_row(MARIA_SHARE *share)
my_bool _ma_once_end_block_record(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;
if (share->bitmap.file >= 0)
{
if (flush_key_blocks(share->key_cache, share->bitmap.file,
share->temporary ? FLUSH_IGNORE_CHANGED :
FLUSH_RELEASE))
res= 1;
if (my_close(share->bitmap.file, MYF(MY_WME)))
res= 1;
/*
Trivial assignment to guard against multiple invocations
(May happen if file are closed but we want to keep the maria object
around a bit longer)
*/
share->bitmap.file= -1;
}
return res;
}
/* Init info->cur_row structure */
my_bool _ma_init_block_row(MARIA_HA *info)
my_bool _ma_init_block_record(MARIA_HA *info)
{
MARIA_ROW *row= &info->cur_row, *new_row= &info->new_row;
DBUG_ENTER("_ma_init_block_row");
DBUG_ENTER("_ma_init_block_record");
if (!my_multi_malloc(MY_WME,
&row->empty_bits_buffer, info->s->base.pack_bytes,
@ -398,12 +438,18 @@ my_bool _ma_init_block_row(MARIA_HA *info)
}
void _ma_end_block_row(MARIA_HA *info)
void _ma_end_block_record(MARIA_HA *info)
{
DBUG_ENTER("_ma_end_block_row");
DBUG_ENTER("_ma_end_block_record");
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));
/*
The data file is closed, when needed, in ma_once_end_block_record().
The following protects us from doing an extra, not allowed, close
in maria_close()
*/
info->dfile= -1;
DBUG_VOID_RETURN;
}
@ -412,7 +458,19 @@ void _ma_end_block_row(MARIA_HA *info)
Helper functions
****************************************************************************/
static inline uint empty_pos_after_row(byte *dir)
/*
Return the next used byte on the page after a directory entry.
SYNOPSIS
start_of_next_entry()
dir Directory entry to be used
RETURN
# Position in page where next entry starts.
Everything between the '*dir' and this are free to be used.
*/
static inline uint start_of_next_entry(byte *dir)
{
byte *prev;
/*
@ -427,6 +485,18 @@ static inline uint empty_pos_after_row(byte *dir)
}
/*
Check that a region is all zero
SYNOPSIS
check_if_zero()
pos Start of memory to check
length length of memory region
NOTES
Used mainly to detect rows with wrong extent information
*/
static my_bool check_if_zero(byte *pos, uint length)
{
byte *end;
@ -438,7 +508,7 @@ static my_bool check_if_zero(byte *pos, uint length)
/*
Find free postion in directory
Find free position in directory
SYNOPSIS
find_free_position()
@ -450,7 +520,7 @@ static my_bool check_if_zero(byte *pos, uint length)
all empty space, including the found block.
NOTES
If there is a free directory entry (entry with postion == 0),
If there is a free directory entry (entry with position == 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
@ -473,7 +543,7 @@ static my_bool check_if_zero(byte *pos, uint length)
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 max_entry= (uint) ((uchar*) buff)[DIR_COUNT_OFFSET];
uint entry, length, first_pos;
byte *dir, *end;
DBUG_ENTER("find_free_position");
@ -482,22 +552,23 @@ static byte *find_free_position(byte *buff, uint block_size, uint *res_rownr,
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 */
first_pos= PAGE_HEADER_SIZE;
for (entry= 0 ; dir <= end ; end-= DIR_ENTRY_SIZE, entry++)
{
if (end[0] == 0 && end[1] == 0) /* Found not used entry */
uint tmp= uint2korr(end);
if (!tmp) /* Found not used entry */
{
length= empty_pos_after_row(end) - first_pos;
length= start_of_next_entry(end) - first_pos;
int2store(end, first_pos); /* Update dir entry */
int2store(end + 2, length);
*res_rownr= entry;
*res_length= length;
DBUG_RETURN(end);
}
first_pos= uint2korr(end) + uint2korr(end + 2);
first_pos= tmp + uint2korr(end + 2);
}
/* No empty places in dir; create a new one */
dir= end;
@ -513,7 +584,7 @@ static byte *find_free_position(byte *buff, uint block_size, uint *res_rownr,
uint2korr(end + DIR_ENTRY_SIZE+ 2));
*empty_space= uint2korr(buff + EMPTY_SPACE_OFFSET);
}
buff[DIR_ENTRY_OFFSET]= (byte) (uchar) max_entry+1;
buff[DIR_COUNT_OFFSET]= (byte) (uchar) max_entry+1;
length= (uint) (dir - buff - first_pos);
DBUG_ASSERT(length <= *empty_space - DIR_ENTRY_SIZE);
int2store(dir, first_pos);
@ -551,7 +622,7 @@ static void calc_record_size(MARIA_HA *info, const byte *record,
{
MARIA_SHARE *share= info->s;
byte *field_length_data;
MARIA_COLUMNDEF *rec, *end_field;
MARIA_COLUMNDEF *column, *end_column;
uint *null_field_lengths= row->null_field_lengths;
ulong *blob_lengths= row->blob_lengths;
@ -562,56 +633,56 @@ static void calc_record_size(MARIA_HA *info, const byte *record,
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++)
for (column= share->columndef + share->base.fixed_not_null_fields,
end_column= share->columndef + share->base.fields;
column < end_column; column++, null_field_lengths++)
{
if ((record[rec->null_pos] & rec->null_bit))
if ((record[column->null_pos] & column->null_bit))
{
if (rec->type != FIELD_BLOB)
if (column->type != FIELD_BLOB)
*null_field_lengths= 0;
else
*blob_lengths++= 0;
continue;
}
switch ((enum en_fieldtype) rec->type) {
switch ((enum en_fieldtype) column->type) {
case FIELD_CHECK:
case FIELD_NORMAL: /* Fixed length field */
case FIELD_ZERO:
DBUG_ASSERT(rec->empty_bit == 0);
DBUG_ASSERT(column->empty_bit == 0);
/* fall through */
case FIELD_SKIP_PRESPACE: /* Not packed */
row->normal_length+= rec->length;
*null_field_lengths= rec->length;
row->normal_length+= column->length;
*null_field_lengths= column->length;
break;
case FIELD_SKIP_ZERO: /* Fixed length field */
if (memcmp(record+ rec->offset, maria_zero_string,
rec->length) == 0)
if (memcmp(record+ column->offset, maria_zero_string,
column->length) == 0)
{
row->empty_bits[rec->empty_pos] |= rec->empty_bit;
row->empty_bits[column->empty_pos] |= column->empty_bit;
*null_field_lengths= 0;
}
else
{
row->normal_length+= rec->length;
*null_field_lengths= rec->length;
row->normal_length+= column->length;
*null_field_lengths= column->length;
}
break;
case FIELD_SKIP_ENDSPACE: /* CHAR */
{
const char *pos, *end;
for (pos= record + rec->offset, end= pos + rec->length;
for (pos= record + column->offset, end= pos + column->length;
end > pos && end[-1] == ' '; end--)
;
if (pos == end) /* If empty string */
{
row->empty_bits[rec->empty_pos]|= rec->empty_bit;
row->empty_bits[column->empty_pos]|= column->empty_bit;
*null_field_lengths= 0;
}
else
{
uint length= (end - pos);
if (rec->length <= 255)
if (column->length <= 255)
*field_length_data++= (byte) (uchar) length;
else
{
@ -626,11 +697,11 @@ static void calc_record_size(MARIA_HA *info, const byte *record,
case FIELD_VARCHAR:
{
uint length, field_length_data_length;
const byte *field_pos= record + rec->offset;
const byte *field_pos= record + column->offset;
/* 256 is correct as this includes the length byte */
field_length_data[0]= field_pos[0];
if (rec->length <= 256)
if (column->length <= 256)
{
length= (uint) (uchar) *field_pos;
field_length_data_length= 1;
@ -644,7 +715,7 @@ static void calc_record_size(MARIA_HA *info, const byte *record,
*null_field_lengths= length;
if (!length)
{
row->empty_bits[rec->empty_pos]|= rec->empty_bit;
row->empty_bits[column->empty_pos]|= column->empty_bit;
break;
}
row->varchar_length+= length;
@ -654,13 +725,13 @@ static void calc_record_size(MARIA_HA *info, const byte *record,
}
case FIELD_BLOB:
{
const byte *field_pos= record + rec->offset;
uint size_length= rec->length - maria_portable_sizeof_char_ptr;
const byte *field_pos= record + column->offset;
uint size_length= column->length - portable_sizeof_char_ptr;
ulong blob_length= _ma_calc_blob_length(size_length, field_pos);
*blob_lengths++= blob_length;
if (!blob_length)
row->empty_bits[rec->empty_pos]|= rec->empty_bit;
row->empty_bits[column->empty_pos]|= column->empty_bit;
else
{
row->blob_length+= blob_length;
@ -709,7 +780,7 @@ static void calc_record_size(MARIA_HA *info, const byte *record,
static void compact_page(byte *buff, uint block_size, uint rownr,
my_bool extend_block)
{
uint max_entry= (uint) ((uchar *) buff)[DIR_ENTRY_OFFSET];
uint max_entry= (uint) ((uchar *) buff)[DIR_COUNT_OFFSET];
uint page_pos, next_free_pos, start_of_found_block, diff, end_of_found_block;
byte *dir, *end;
DBUG_ENTER("compact_page");
@ -875,7 +946,7 @@ static my_bool get_head_or_tail_page(MARIA_HA *info,
bzero(buff+ PAGE_HEADER_SIZE, block_size - PAGE_HEADER_SIZE);
buff[PAGE_TYPE_OFFSET]= (byte) page_type;
buff[DIR_ENTRY_OFFSET]= 1;
buff[DIR_COUNT_OFFSET]= 1;
res->buff= buff;
res->empty_space= res->length= (block_size - PAGE_OVERHEAD_SIZE);
res->data= (buff + PAGE_HEADER_SIZE);
@ -956,12 +1027,18 @@ static my_bool write_tail(MARIA_HA *info,
DBUG_PRINT("enter", ("page: %lu length: %u",
(ulong) block->page, length));
info->keybuff_used= 1;
info->keyread_buff_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);
/*
Don't allocate smaller block than MIN_TAIL_SIZE (we want to give rows
some place to grow in the future)
*/
if (length < MIN_TAIL_SIZE)
length= MIN_TAIL_SIZE;
int2store(row_pos.dir + 2, length);
empty_space= row_pos.empty_space - length;
int2store(row_pos.buff + EMPTY_SPACE_OFFSET, empty_space);
@ -969,10 +1046,10 @@ static my_bool write_tail(MARIA_HA *info,
/*
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
during _ma_bitmap_find_place() allocate more entries on the tail page
than it can hold
*/
block->empty_space= ((uint) ((uchar*) row_pos.buff)[DIR_ENTRY_OFFSET] <=
block->empty_space= ((uint) ((uchar*) row_pos.buff)[DIR_COUNT_OFFSET] <=
MAX_ROWS_PER_PAGE - 1 - info->s->base.blobs ?
empty_space : 0);
block->used= BLOCKUSED_USED | BLOCKUSED_TAIL;
@ -1015,7 +1092,7 @@ static my_bool write_full_pages(MARIA_HA *info,
(ulong) length, (ulong) block->page,
(ulong) block->page_count));
info->keybuff_used= 1;
info->keyread_buff_used= 1;
page= block->page;
page_count= block->page_count;
@ -1134,7 +1211,7 @@ static my_bool write_block_record(MARIA_HA *info, const byte *record,
byte *page_buff;
MARIA_BITMAP_BLOCK *block, *head_block;
MARIA_SHARE *share;
MARIA_COLUMNDEF *rec, *end_field;
MARIA_COLUMNDEF *column, *end_column;
uint block_size, flag;
ulong *blob_lengths;
my_off_t position;
@ -1219,16 +1296,17 @@ static my_bool write_block_record(MARIA_HA *info, const byte *record,
}
/* 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++)
for (column= share->columndef,
end_column= column + share->base.fixed_not_null_fields;
column < end_column; column++)
{
if (!tmp_data_used && tmp_data + rec->length > end_of_data)
if (!tmp_data_used && tmp_data + column->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;
memcpy(tmp_data, record + column->offset, column->length);
tmp_data+= column->length;
}
/* Copy length of data for variable length fields */
@ -1242,26 +1320,26 @@ static my_bool write_block_record(MARIA_HA *info, const byte *record,
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++)
for (end_column= share->columndef + share->base.fields - share->base.blobs;
column < end_column ;
column++)
{
const byte *field_pos;
ulong length;
if ((record[rec->null_pos] & rec->null_bit) ||
(row->empty_bits[rec->empty_pos] & rec->empty_bit))
if ((record[column->null_pos] & column->null_bit) ||
(row->empty_bits[column->empty_pos] & column->empty_bit))
continue;
field_pos= record + rec->offset;
switch ((enum en_fieldtype) rec->type) {
field_pos= record + column->offset;
switch ((enum en_fieldtype) column->type) {
case FIELD_NORMAL: /* Fixed length field */
case FIELD_SKIP_PRESPACE:
case FIELD_SKIP_ZERO: /* Fixed length field */
length= rec->length;
length= column->length;
break;
case FIELD_SKIP_ENDSPACE: /* CHAR */
/* Char that is space filled */
if (rec->length <= 255)
if (column->length <= 255)
length= (uint) (uchar) *field_length_data++;
else
{
@ -1270,7 +1348,7 @@ static my_bool write_block_record(MARIA_HA *info, const byte *record,
}
break;
case FIELD_VARCHAR:
if (rec->length <= 256)
if (column->length <= 256)
{
length= (uint) (uchar) *field_length_data++;
field_pos++; /* Skip length byte */
@ -1298,21 +1376,21 @@ static my_bool write_block_record(MARIA_HA *info, const byte *record,
block= head_block + head_block->sub_blocks; /* Point to first blob data */
end_field= rec + share->base.blobs;
end_column= column + 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++)
for (; column < end_column && *blob_lengths < (ulong) (end_of_data - data);
column++, 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,
length= column->length - portable_sizeof_char_ptr;
memcpy_fixed((byte*) &tmp_pos, record + column->offset + length,
sizeof(char*));
memcpy(data, tmp_pos, *blob_lengths);
data+= *blob_lengths;
@ -1342,7 +1420,7 @@ static my_bool write_block_record(MARIA_HA *info, const byte *record,
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)
if (page_buff[DIR_COUNT_OFFSET] == (char) MAX_ROWS_PER_PAGE)
head_block->empty_space= 0; /* Page is full */
head_block->used= BLOCKUSED_USED;
}
@ -1362,14 +1440,14 @@ static my_bool write_block_record(MARIA_HA *info, const byte *record,
if (row_extents_in_use)
{
if (rec != end_field) /* If blob fields */
if (column != end_column) /* If blob fields */
{
MARIA_COLUMNDEF *save_rec= rec;
MARIA_COLUMNDEF *save_column= column;
MARIA_BITMAP_BLOCK *save_block= block;
MARIA_BITMAP_BLOCK *end_block;
ulong *save_blob_lengths= blob_lengths;
for (; rec < end_field; rec++, blob_lengths++)
for (; column < end_column; column++, blob_lengths++)
{
byte *blob_pos;
if (!*blob_lengths) /* Null or "" */
@ -1377,8 +1455,8 @@ static my_bool write_block_record(MARIA_HA *info, const byte *record,
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,
length= column->length - portable_sizeof_char_ptr;
memcpy_fixed((byte *) &blob_pos, record + column->offset + length,
sizeof(char*));
length= *blob_lengths % FULL_PAGE_SIZE(block_size); /* tail size */
if (write_tail(info, block + block->sub_blocks-1,
@ -1395,7 +1473,7 @@ static my_bool write_block_record(MARIA_HA *info, const byte *record,
block->used|= BLOCKUSED_USED;
}
}
rec= save_rec;
column= save_column;
block= save_block;
blob_lengths= save_blob_lengths;
}
@ -1593,15 +1671,15 @@ static my_bool write_block_record(MARIA_HA *info, const byte *record,
}
/* Write rest of blobs (data, but no tails as they are already written) */
for (; rec < end_field; rec++, blob_lengths++)
for (; column < end_column; column++, 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,
length= column->length - portable_sizeof_char_ptr;
memcpy_fixed((byte*) &blob_pos, record + column->offset + length,
sizeof(char*));
/* remove tail part */
blob_length= *blob_lengths;
@ -1705,7 +1783,7 @@ my_bool _ma_write_abort_block_record(MARIA_HA *info)
if (delete_head_or_tail(info,
ma_recordpos_to_page(info->cur_row.lastpos),
ma_recordpos_to_offset(info->cur_row.lastpos), 1))
ma_recordpos_to_dir_entry(info->cur_row.lastpos), 1))
res= 1;
for (block= blocks->block + 1, end= block + blocks->count - 1; block < end;
block++)
@ -1764,7 +1842,7 @@ my_bool _ma_update_block_record(MARIA_HA *info, MARIA_RECORD_POS record_pos,
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);
rownr= ma_recordpos_to_dir_entry(record_pos);
dir= (buff + block_size - DIR_ENTRY_SIZE * rownr -
DIR_ENTRY_SIZE - PAGE_SUFFIX_SIZE);
@ -1785,8 +1863,8 @@ my_bool _ma_update_block_record(MARIA_HA *info, MARIA_RECORD_POS record_pos,
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 (rownr != (uint) ((uchar *) buff)[DIR_COUNT_OFFSET] - 1)
empty= start_of_next_entry(dir) - (offset + length);
if (new_row->total_length > length + empty)
{
compact_page(buff, info->s->block_size, rownr, 1);
@ -1876,14 +1954,14 @@ static my_bool delete_head_or_tail(MARIA_HA *info,
my_off_t position;
DBUG_ENTER("delete_head_or_tail");
info->keybuff_used= 1;
info->keyread_buff_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];
number_of_records= (uint) ((uchar *) buff)[DIR_COUNT_OFFSET];
#ifdef SANITY_CHECKS
if (record_number >= number_of_records ||
record_number > ((block_size - LSN_SIZE - PAGE_TYPE_SIZE - 1 -
@ -1911,7 +1989,7 @@ static my_bool delete_head_or_tail(MARIA_HA *info,
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;
buff[DIR_COUNT_OFFSET]= (byte) (uchar) number_of_records;
}
empty_space+= length;
if (number_of_records != 0)
@ -1957,7 +2035,7 @@ static my_bool delete_tails(MARIA_HA *info, MARIA_RECORD_POS *tails)
{
if (delete_head_or_tail(info,
ma_recordpos_to_page(*tails),
ma_recordpos_to_offset(*tails), 0))
ma_recordpos_to_dir_entry(*tails), 0))
res= 1;
}
DBUG_RETURN(res);
@ -1978,7 +2056,7 @@ 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),
ma_recordpos_to_dir_entry(info->cur_row.lastpos),
1) ||
delete_tails(info, info->cur_row.tail_positions))
DBUG_RETURN(1);
@ -2011,7 +2089,7 @@ my_bool _ma_delete_block_record(MARIA_HA *info)
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];
uint number_of_records= (uint) ((uchar *) buff)[DIR_COUNT_OFFSET];
byte *dir;
byte *data;
uint offset, length;
@ -2254,7 +2332,7 @@ int _ma_read_block_record2(MARIA_HA *info, byte *record,
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;
MARIA_COLUMNDEF *column, *end_column;
DBUG_ENTER("_ma_read_block_record2");
LINT_INIT(field_lengths);
@ -2347,15 +2425,16 @@ int _ma_read_block_record2(MARIA_HA *info, byte *record,
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++)
for (column= share->columndef,
end_column= column + share->base.fixed_not_null_fields;
column < end_column; column++)
{
uint rec_length= rec->length;
uint column_length= column->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;
memcpy(record + column->offset, data, column_length);
data+= column_length;
}
/* Read array of field lengths. This may be stored in several extents */
@ -2368,18 +2447,19 @@ int _ma_read_block_record2(MARIA_HA *info, byte *record,
}
/* 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++)
for (end_column= share->columndef + share->base.fields;
column < end_column; column++)
{
enum en_fieldtype type= (enum en_fieldtype) rec->type;
byte *field_pos= record + rec->offset;
enum en_fieldtype type= (enum en_fieldtype) column->type;
byte *field_pos= record + column->offset;
/* First check if field is present in record */
if ((record[rec->null_pos] & rec->null_bit) ||
(info->cur_row.empty_bits[rec->empty_pos] & rec->empty_bit))
if ((record[column->null_pos] & column->null_bit) ||
(info->cur_row.empty_bits[column->empty_pos] & column->empty_bit))
{
if (type == FIELD_SKIP_ENDSPACE)
bfill(record + rec->offset, rec->length, ' ');
bfill(record + column->offset, column->length, ' ');
else
bzero(record + rec->offset, rec->fill_length);
bzero(record + column->offset, column->fill_length);
continue;
}
switch (type) {
@ -2389,14 +2469,14 @@ int _ma_read_block_record2(MARIA_HA *info, byte *record,
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;
memcpy(field_pos, data, column->length);
data+= column->length;
break;
case FIELD_SKIP_ENDSPACE: /* CHAR */
{
/* Char that is space filled */
uint length;
if (rec->length <= 255)
if (column->length <= 255)
length= (uint) (uchar) *field_length_data++;
else
{
@ -2404,19 +2484,19 @@ int _ma_read_block_record2(MARIA_HA *info, byte *record,
field_length_data+= 2;
}
#ifdef SANITY_CHECKS
if (length > rec->length)
if (length > column->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, ' ');
bfill(field_pos + length, column->length - length, ' ');
break;
}
case FIELD_VARCHAR:
{
ulong length;
if (rec->length <= 256)
if (column->length <= 256)
{
length= (uint) (uchar) (*field_pos++= *field_length_data++);
}
@ -2435,7 +2515,7 @@ int _ma_read_block_record2(MARIA_HA *info, byte *record,
}
case FIELD_BLOB:
{
uint size_length= rec->length - maria_portable_sizeof_char_ptr;
uint size_length= column->length - portable_sizeof_char_ptr;
ulong blob_length= _ma_calc_blob_length(size_length, field_length_data);
if (!found_blob)
@ -2443,17 +2523,17 @@ int _ma_read_block_record2(MARIA_HA *info, byte *record,
/* Calculate total length for all blobs */
ulong blob_lengths= 0;
byte *length_data= field_length_data;
MARIA_COLUMNDEF *blob_field= rec;
MARIA_COLUMNDEF *blob_field= column;
found_blob= 1;
for (; blob_field < end_field; blob_field++)
for (; blob_field < end_column; 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;
size_length= blob_field->length - portable_sizeof_char_ptr;
blob_lengths+= _ma_calc_blob_length(size_length, length_data);
length_data+= size_length;
}
@ -2547,7 +2627,7 @@ int _ma_read_block_record(MARIA_HA *info, byte *record,
info->cur_row.lastpos= record_pos;
page= ma_recordpos_to_page(record_pos) * block_size;
offset= ma_recordpos_to_offset(record_pos);
offset= ma_recordpos_to_dir_entry(record_pos);
if (!(buff= key_cache_read(info->s->key_cache,
info->dfile, page, 0, info->buff,
@ -2754,7 +2834,7 @@ restart_bitmap_scan:
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)
(uint) (uchar) info->scan.page_buff[DIR_COUNT_OFFSET]) == 0)
{
DBUG_PRINT("error", ("Wrong page header"));
DBUG_RETURN((my_errno= HA_ERR_WRONG_IN_RECORD));
@ -2818,7 +2898,7 @@ my_bool _ma_compare_block_record(MARIA_HA *info __attribute__ ((unused)),
static void _ma_print_directory(byte *buff, uint block_size)
{
uint max_entry= (uint) ((uchar *) buff)[DIR_ENTRY_OFFSET], row= 0;
uint max_entry= (uint) ((uchar *) buff)[DIR_COUNT_OFFSET], row= 0;
uint end_of_prev_row= PAGE_HEADER_SIZE;
byte *dir, *end;

View file

@ -18,11 +18,11 @@
*/
#define LSN_SIZE 7
#define DIRCOUNT_SIZE 1 /* Stores number of rows on page */
#define DIR_COUNT_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 +\
#define PAGE_HEADER_SIZE (LSN_SIZE + DIR_COUNT_SIZE + EMPTY_SPACE_SIZE +\
PAGE_TYPE_SIZE)
#define PAGE_OVERHEAD_SIZE (PAGE_HEADER_SIZE + DIR_ENTRY_SIZE + \
PAGE_SUFFIX_SIZE)
@ -34,14 +34,18 @@
#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 */
/* Number of extents reserved MARIA_BITMAP_BLOCKS to store head part */
#define ELEMENTS_RESERVED_FOR_MAIN_PART 4
/* Fields before 'row->null_field_lengths' used by find_where_to_split_row */
#define EXTRA_LENGTH_FIELDS 3
/* Size for the different parts in the row header (and head page) */
#define FLAG_SIZE 1
#define TRANSID_SIZE 6
#define VERPTR_SIZE 7
#define DIR_ENTRY_SIZE 4
#define FIELD_OFFSET_SIZE 2
#define FIELD_OFFSET_SIZE 2 /* size of pointers to field starts */
/* Minimum header size needed for a new row */
#define BASE_ROW_HEADER_SIZE FLAG_SIZE
@ -51,8 +55,8 @@
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 DIR_COUNT_OFFSET LSN_SIZE+PAGE_TYPE_SIZE
#define EMPTY_SPACE_OFFSET (DIR_COUNT_OFFSET + DIR_COUNT_SIZE)
#define PAGE_CAN_BE_COMPACTED 128 /* Bit in PAGE_TYPE */
@ -64,10 +68,15 @@ enum en_page_type { UNALLOCATED_PAGE, HEAD_PAGE, TAIL_PAGE, BLOB_PAGE, MAX_PAGE_
#define ROW_FLAG_EXTENTS 128
#define ROW_FLAG_ALL (1+2+4+8+128)
/* Variables that affects how data pages are utilized */
/******** Variables that affects how data pages are utilized ********/
/* Minium size of tail segment */
#define MIN_TAIL_SIZE 32
/* Fixed part of Max possible header size; See table in ma_blockrec.c */
/*
Fixed length part of Max possible header size; See row data structure
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 + \
TRANSID_SIZE + VERPTR_SIZE + \
@ -77,21 +86,30 @@ enum en_page_type { UNALLOCATED_PAGE, HEAD_PAGE, TAIL_PAGE, BLOB_PAGE, MAX_PAGE_
#define MAX_ROWS_PER_PAGE 255
/* Bits for MARIA_BITMAP_BLOCKS->used */
/* We stored data on disk in the block */
#define BLOCKUSED_USED 1
/* Bitmap on disk is block->org_bitmap_value ; Happens only on update */
#define BLOCKUSED_USE_ORG_BITMAP 2
/* We stored tail data on disk for the block */
#define BLOCKUSED_TAIL 4
/* defines that affects allocation (density) of data */
/******* defines that affects allocation (density) of data *******/
/* If we fill up a block to 75 %, don't create a new tail page for it */
/*
If the tail part (from the main block or a blob) uses more than 75 % of
the size of page, store the tail on a full page instead of a shared
tail page.
*/
#define MAX_TAIL_SIZE(block_size) ((block_size) *3 / 4)
extern uchar maria_bitmap_marker[2];
/* Functions to convert MARIA_RECORD_POS to/from page:offset */
static inline MARIA_RECORD_POS ma_recordpos(ulonglong page, uint offset)
static inline MARIA_RECORD_POS ma_recordpos(ulonglong page, uint dir_entry)
{
DBUG_ASSERT(offset <= 255);
return (MARIA_RECORD_POS) ((page << 8) | offset);
DBUG_ASSERT(dir_entry <= 255);
return (MARIA_RECORD_POS) ((page << 8) | dir_entry);
}
static inline my_off_t ma_recordpos_to_page(MARIA_RECORD_POS record_pos)
@ -99,17 +117,17 @@ 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)
static inline my_off_t ma_recordpos_to_dir_entry(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_once_init_block_record(MARIA_SHARE *share, File dfile);
my_bool _ma_once_end_block_record(MARIA_SHARE *share);
my_bool _ma_init_block_record(MARIA_HA *info);
void _ma_end_block_record(MARIA_HA *info);
my_bool _ma_update_block_record(MARIA_HA *info, MARIA_RECORD_POS pos,
const byte *record);
@ -136,8 +154,6 @@ my_bool _ma_compare_block_record(register MARIA_HA *info,
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);

View file

@ -941,7 +941,7 @@ static void record_pos_to_txt(MARIA_HA *info, my_off_t recpos,
else
{
my_off_t page= ma_recordpos_to_page(recpos);
uint row= ma_recordpos_to_offset(recpos);
uint row= ma_recordpos_to_dir_entry(recpos);
char *end= longlong10_to_str(page, buff, 10);
*(end++)= ':';
longlong10_to_str(row, end, 10);
@ -1370,6 +1370,9 @@ end:
/*
Check if layout on a page is ok
NOTES
This is for rows-in-block format.
*/
static int check_page_layout(HA_CHECK *param, MARIA_HA *info,
@ -1442,6 +1445,8 @@ static int check_page_layout(HA_CHECK *param, MARIA_HA *info,
Check all rows on head page
NOTES
This is for rows-in-block format.
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)
@ -1548,6 +1553,9 @@ static my_bool check_head_page(HA_CHECK *param, MARIA_HA *info, byte *record,
}
/*
Check if rows-in-block data file is consistent
*/
static int check_block_record(HA_CHECK *param, MARIA_HA *info, int extend,
byte *record)
@ -1638,7 +1646,7 @@ static int check_block_record(HA_CHECK *param, MARIA_HA *info, int extend,
DBUG_ASSERT(0);
break;
case HEAD_PAGE:
row_count= ((uchar*) page_buff)[DIR_ENTRY_OFFSET];
row_count= ((uchar*) page_buff)[DIR_COUNT_OFFSET];
empty_space= uint2korr(page_buff + EMPTY_SPACE_OFFSET);
param->used+= (PAGE_HEADER_SIZE + PAGE_SUFFIX_SIZE +
row_count * DIR_ENTRY_SIZE);
@ -1647,7 +1655,7 @@ static int check_block_record(HA_CHECK *param, MARIA_HA *info, int extend,
full_dir= row_count == MAX_ROWS_PER_PAGE;
break;
case TAIL_PAGE:
row_count= ((uchar*) page_buff)[DIR_ENTRY_OFFSET];
row_count= ((uchar*) page_buff)[DIR_COUNT_OFFSET];
empty_space= uint2korr(page_buff + EMPTY_SPACE_OFFSET);
param->used+= (PAGE_HEADER_SIZE + PAGE_SUFFIX_SIZE +
row_count * DIR_ENTRY_SIZE);
@ -1712,7 +1720,7 @@ err:
}
/* Check that record-link is ok */
/* Check that record-link is ok */
int maria_chk_data_link(HA_CHECK *param, MARIA_HA *info,int extend)
{
@ -4581,7 +4589,7 @@ int maria_recreate_table(HA_CHECK *param, MARIA_HA **org_info, char *filename)
MARIA_SHARE share;
MARIA_KEYDEF *keyinfo,*key,*key_end;
HA_KEYSEG *keysegs,*keyseg;
MARIA_COLUMNDEF *recdef,*rec,*end;
MARIA_COLUMNDEF *columndef,*column,*end;
MARIA_UNIQUEDEF *uniquedef,*u_ptr,*u_end;
MARIA_STATUS_INFO status_info;
uint unpack,key_parts;
@ -4610,7 +4618,7 @@ int maria_recreate_table(HA_CHECK *param, MARIA_HA **org_info, char *filename)
my_afree((gptr) keyinfo);
DBUG_RETURN(1);
}
if (!(recdef=(MARIA_COLUMNDEF*)
if (!(columndef=(MARIA_COLUMNDEF*)
my_alloca(sizeof(MARIA_COLUMNDEF)*(share.base.fields+1))))
{
my_afree((gptr) keyinfo);
@ -4620,22 +4628,24 @@ int maria_recreate_table(HA_CHECK *param, MARIA_HA **org_info, char *filename)
if (!(uniquedef=(MARIA_UNIQUEDEF*)
my_alloca(sizeof(MARIA_UNIQUEDEF)*(share.state.header.uniques+1))))
{
my_afree((gptr) recdef);
my_afree((gptr) columndef);
my_afree((gptr) keyinfo);
my_afree((gptr) keysegs);
DBUG_RETURN(1);
}
/* Copy the column definitions */
memcpy((byte*) recdef,(byte*) share.rec,
memcpy((byte*) columndef,(byte*) share.columndef,
(size_t) (sizeof(MARIA_COLUMNDEF)*(share.base.fields+1)));
for (rec=recdef,end=recdef+share.base.fields; rec != end ; rec++)
for (column=columndef, end= columndef+share.base.fields;
column != end ;
column++)
{
if (unpack && !(share.options & HA_OPTION_PACK_RECORD) &&
rec->type != FIELD_BLOB &&
rec->type != FIELD_VARCHAR &&
rec->type != FIELD_CHECK)
rec->type=(int) FIELD_NORMAL;
column->type != FIELD_BLOB &&
column->type != FIELD_VARCHAR &&
column->type != FIELD_CHECK)
column->type=(int) FIELD_NORMAL;
}
/* Change the new key to point at the saved key segments */
@ -4710,7 +4720,7 @@ int maria_recreate_table(HA_CHECK *param, MARIA_HA **org_info, char *filename)
*/
if (maria_create(filename, share.data_file_type,
share.base.keys - share.state.header.uniques,
keyinfo, share.base.fields, recdef,
keyinfo, share.base.fields, columndef,
share.state.header.uniques, uniquedef,
&create_info,
HA_DONT_TOUCH_DATA))
@ -4751,7 +4761,7 @@ int maria_recreate_table(HA_CHECK *param, MARIA_HA **org_info, char *filename)
end:
my_afree((gptr) uniquedef);
my_afree((gptr) keyinfo);
my_afree((gptr) recdef);
my_afree((gptr) columndef);
my_afree((gptr) keysegs);
DBUG_RETURN(error);
}

View file

@ -20,29 +20,32 @@
ha_checksum _ma_checksum(MARIA_HA *info, const byte *record)
{
ha_checksum crc=0;
MARIA_COLUMNDEF *rec= info->s->rec, *rec_end= rec+ info->s->base.fields;
MARIA_COLUMNDEF *column= info->s->columndef;
MARIA_COLUMNDEF *column_end= column+ info->s->base.fields;
if (info->s->base.null_bytes)
crc= my_checksum(crc, record, info->s->base.null_bytes);
for ( ; rec != rec_end ; rec++)
for ( ; column != column_end ; column++)
{
const byte *pos= record + rec->offset;
const byte *pos= record + column->offset;
ulong length;
switch (rec->type) {
switch (column->type) {
case FIELD_BLOB:
{
length= _ma_calc_blob_length(rec->length-
maria_portable_sizeof_char_ptr,
pos);
memcpy((char*) &pos, pos+rec->length- maria_portable_sizeof_char_ptr,
sizeof(char*));
break;
uint blob_size_length= column->length- portable_sizeof_char_ptr;
length= _ma_calc_blob_length(blob_size_length, pos);
if (length)
{
memcpy((char*) &pos, pos + blob_size_length, sizeof(char*));
crc= my_checksum(crc, pos, length);
}
continue;
}
case FIELD_VARCHAR:
{
uint pack_length= HA_VARCHAR_PACKLENGTH(rec->length-1);
uint pack_length= HA_VARCHAR_PACKLENGTH(column->length-1);
if (pack_length == 1)
length= (ulong) *(uchar*) pos;
else
@ -51,10 +54,10 @@ ha_checksum _ma_checksum(MARIA_HA *info, const byte *record)
break;
}
default:
length= rec->length;
length= column->length;
break;
}
crc= my_checksum(crc, pos ? pos : "", length);
crc= my_checksum(crc, pos, length);
}
return crc;
}

View file

@ -69,10 +69,8 @@ int maria_close(register MARIA_HA *info)
pthread_mutex_unlock(&share->intern_lock);
my_free(info->rec_buff, MYF(MY_ALLOW_ZERO_PTR));
(share->end)(info);
(*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)

View file

@ -35,9 +35,9 @@ 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, enum data_file_type record_type,
int maria_create(const char *name, enum data_file_type datafile_type,
uint keys,MARIA_KEYDEF *keydefs,
uint columns, MARIA_COLUMNDEF *recinfo,
uint columns, MARIA_COLUMNDEF *columndef,
uint uniques, MARIA_UNIQUEDEF *uniquedefs,
MARIA_CREATE_INFO *ci,uint flags)
{
@ -55,12 +55,12 @@ int maria_create(const char *name, enum data_file_type record_type,
ulong pack_reclength;
ulonglong tot_length,max_rows, tmp;
enum en_fieldtype type;
enum data_file_type org_record_type= record_type;
enum data_file_type org_datafile_type= datafile_type;
MARIA_SHARE share;
MARIA_KEYDEF *keydef,tmp_keydef;
MARIA_UNIQUEDEF *uniquedef;
HA_KEYSEG *keyseg,tmp_keyseg;
MARIA_COLUMNDEF *rec, *rec_end;
MARIA_COLUMNDEF *column, *end_column;
ulong *rec_per_key_part;
my_off_t key_root[HA_MAX_POSSIBLE_KEY];
MARIA_CREATE_INFO tmp_create_info;
@ -70,6 +70,7 @@ int maria_create(const char *name, enum data_file_type record_type,
DBUG_PRINT("enter", ("keys: %u columns: %u uniques: %u flags: %u",
keys, columns, uniques, flags));
DBUG_ASSERT(maria_block_size && maria_block_size % IO_SIZE == 0);
LINT_INIT(dfile);
LINT_INIT(file);
@ -89,7 +90,7 @@ int maria_create(const char *name, enum data_file_type record_type,
if (flags & HA_DONT_TOUCH_DATA)
{
org_record_type= ci->org_data_file_type;
org_datafile_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 |
@ -117,83 +118,85 @@ int maria_create(const char *name, enum data_file_type record_type,
pack_reclength= max_field_lengths= 0;
reclength= min_pack_length= ci->null_bytes;
for (rec= recinfo, rec_end= rec + columns ; rec != rec_end ; rec++)
for (column= columndef, end_column= column + columns ;
column != end_column ;
column++)
{
/* Fill in not used struct parts */
rec->offset= reclength;
rec->empty_pos= 0;
rec->empty_bit= 0;
rec->fill_length= rec->length;
column->offset= reclength;
column->empty_pos= 0;
column->empty_bit= 0;
column->fill_length= column->length;
reclength+= rec->length;
type= rec->type;
if (type == FIELD_SKIP_PRESPACE && record_type == BLOCK_RECORD)
reclength+= column->length;
type= column->type;
if (type == FIELD_SKIP_PRESPACE && datafile_type == BLOCK_RECORD)
type= FIELD_NORMAL; /* SKIP_PRESPACE not supported */
if (type != FIELD_NORMAL && type != FIELD_CHECK)
{
rec->empty_pos= packed/8;
rec->empty_bit= (1 << (packed & 7));
column->empty_pos= packed/8;
column->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)
if (column->length == 4+portable_sizeof_char_ptr)
pack_reclength= INT_MAX32;
else
{
/* Add max possible blob length */
pack_reclength+= (1 << ((rec->length-
maria_portable_sizeof_char_ptr)*8));
pack_reclength+= (1 << ((column->length-
portable_sizeof_char_ptr)*8));
}
}
max_field_lengths+= (rec->length - maria_portable_sizeof_char_ptr);
max_field_lengths+= (column->length - portable_sizeof_char_ptr);
}
else if (type == FIELD_SKIP_PRESPACE ||
type == FIELD_SKIP_ENDSPACE)
{
max_field_lengths+= rec->length > 255 ? 2 : 1;
if (record_type != BLOCK_RECORD)
max_field_lengths+= column->length > 255 ? 2 : 1;
if (datafile_type != BLOCK_RECORD)
min_pack_length++;
packed++;
}
else if (type == FIELD_VARCHAR)
{
varchar_length+= rec->length-1; /* Used for min_pack_length */
varchar_length+= column->length-1; /* Used for min_pack_length */
pack_reclength++;
if (record_type != BLOCK_RECORD)
if (datafile_type != BLOCK_RECORD)
min_pack_length++;
max_field_lengths++;
packed++;
rec->fill_length= 1;
column->fill_length= 1;
/* We must test for 257 as length includes pack-length */
if (test(rec->length >= 257))
if (test(column->length >= 257))
{
long_varchar_count++;
max_field_lengths++;
rec->fill_length= 2;
column->fill_length= 2;
}
}
else if (type == FIELD_SKIP_ZERO)
packed++;
else
{
if (record_type != BLOCK_RECORD || !rec->null_bit)
min_pack_length+= rec->length;
rec->empty_pos= 0;
rec->empty_bit= 0;
if (datafile_type != BLOCK_RECORD || !column->null_bit)
min_pack_length+= column->length;
column->empty_pos= 0;
column->empty_bit= 0;
}
}
else /* FIELD_NORMAL */
{
if (record_type != BLOCK_RECORD || !rec->null_bit)
min_pack_length+= rec->length;
if (!rec->null_bit)
if (datafile_type != BLOCK_RECORD || !column->null_bit)
min_pack_length+= column->length;
if (!column->null_bit)
{
share.base.fixed_not_null_fields++;
share.base.fixed_not_null_fields_length+= rec->length;
share.base.fixed_not_null_fields_length+= column->length;
}
}
}
@ -203,14 +206,14 @@ int maria_create(const char *name, enum data_file_type record_type,
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)
while (column != columndef)
{
rec--;
if (rec->type == (int) FIELD_SKIP_ZERO && rec->length == 1)
column--;
if (column->type == (int) FIELD_SKIP_ZERO && column->length == 1)
{
rec->type=(int) FIELD_NORMAL;
rec->empty_pos= 0;
rec->empty_bit= 0;
column->type=(int) FIELD_NORMAL;
column->empty_pos= 0;
column->empty_bit= 0;
packed--;
min_pack_length++;
break;
@ -226,12 +229,12 @@ int maria_create(const char *name, enum data_file_type record_type,
if (pack_reclength != INT_MAX32)
pack_reclength+= max_field_lengths + long_varchar_count;
if (packed && record_type == STATIC_RECORD)
record_type= BLOCK_RECORD;
if (record_type == DYNAMIC_RECORD)
if (packed && datafile_type == STATIC_RECORD)
datafile_type= BLOCK_RECORD;
if (datafile_type == DYNAMIC_RECORD)
options|= HA_OPTION_PACK_RECORD; /* Must use packed records */
if (record_type == STATIC_RECORD)
if (datafile_type == STATIC_RECORD)
{
/* We can't use checksum with static length rows */
flags&= ~HA_CREATE_CHECKSUM;
@ -275,24 +278,24 @@ int maria_create(const char *name, enum data_file_type record_type,
}
else if (!ci->max_rows)
{
if (record_type == BLOCK_RECORD)
if (datafile_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)
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;
ci->max_rows= 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);
ci->max_rows= 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 +
@ -301,7 +304,7 @@ int maria_create(const char *name, enum data_file_type record_type,
3 : 0)));
}
max_rows= (ulonglong) ci->max_rows;
if (record_type == BLOCK_RECORD)
if (datafile_type == BLOCK_RECORD)
{
/* The + 1 is for record position withing page */
pointer= maria_get_pointer_length((ci->data_file_length /
@ -314,7 +317,7 @@ int maria_create(const char *name, enum data_file_type record_type,
}
else
{
if (record_type != STATIC_RECORD)
if (datafile_type != STATIC_RECORD)
pointer= maria_get_pointer_length(ci->data_file_length,
maria_data_pointer_size);
else
@ -324,7 +327,7 @@ int maria_create(const char *name, enum data_file_type record_type,
}
real_reclength=reclength;
if (record_type == STATIC_RECORD)
if (datafile_type == STATIC_RECORD)
{
if (reclength <= pointer)
reclength=pointer+1; /* reserve place for delete link */
@ -533,7 +536,12 @@ int maria_create(const char *name, enum data_file_type record_type,
key_segs)
share.state.rec_per_key_part[key_segs-1]=1L;
length+=key_length;
if (length >= HA_MAX_KEY_BUFF)
/*
A key can't be longer than than half a index block (as we have
to be able to put at least 2 keys on an index block for the key
algorithms to work).
*/
if (length > maria_max_key_length())
{
my_errno=HA_WRONG_CREATE_OPTION;
goto err_no_lock;
@ -592,8 +600,8 @@ int maria_create(const char *name, enum data_file_type record_type,
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.data_file_type= datafile_type;
share.state.header.org_data_file_type= org_datafile_type;
share.state.header.language= (ci->language ?
ci->language : default_charset_info->number);
@ -653,7 +661,7 @@ int maria_create(const char *name, enum data_file_type record_type,
share.base.max_data_file_length= (my_off_t) ci->data_file_length;
}
if (record_type == BLOCK_RECORD)
if (datafile_type == BLOCK_RECORD)
share.base.min_block_length= share.base.min_row_length;
else
{
@ -869,21 +877,23 @@ int maria_create(const char *name, enum data_file_type record_type,
}
}
DBUG_PRINT("info", ("write field definitions"));
if (record_type == BLOCK_RECORD)
if (datafile_type == BLOCK_RECORD)
{
/* Store columns in a more efficent order */
MARIA_COLUMNDEF **col_order, **pos;
if (!(col_order= (MARIA_COLUMNDEF**) my_malloc(share.base.fields *
sizeof(MARIA_COLUMNDEF*),
MYF(MY_WME))))
sizeof(MARIA_COLUMNDEF*),
MYF(MY_WME))))
goto err;
for (rec= recinfo, pos= col_order ; rec != rec_end ; rec++, pos++)
*pos= rec;
for (column= columndef, pos= col_order ;
column != end_column ;
column++, pos++)
*pos= column;
qsort(col_order, share.base.fields, sizeof(*col_order),
(qsort_cmp) compare_columns);
for (i=0 ; i < share.base.fields ; i++)
{
if (_ma_recinfo_write(file, col_order[i]))
if (_ma_columndef_write(file, col_order[i]))
{
my_free((gptr) col_order, MYF(0));
goto err;
@ -894,7 +904,7 @@ int maria_create(const char *name, enum data_file_type record_type,
else
{
for (i=0 ; i < share.base.fields ; i++)
if (_ma_recinfo_write(file, &recinfo[i]))
if (_ma_columndef_write(file, &columndef[i]))
goto err;
}
@ -1026,9 +1036,9 @@ static 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 ?
a_type= ((a->type == FIELD_NORMAL || a->type == FIELD_CHECK) ?
FIELD_NORMAL : a->type);
b_type= (b->type == FIELD_NORMAL || b->type == FIELD_CHECK ?
b_type= ((b->type == FIELD_NORMAL || b->type == FIELD_CHECK) ?
FIELD_NORMAL : b->type);
if (a_type == FIELD_NORMAL && !a->null_bit)
@ -1059,15 +1069,8 @@ int _ma_initialize_data_file(File dfile, MARIA_SHARE *share)
{
if (share->data_file_type == BLOCK_RECORD)
{
/* Write one bitmap page */
byte buff[IO_SIZE];
uint i;
bzero((char*) buff, sizeof(buff));
if (my_seek(dfile, 0, SEEK_SET, 0))
if (my_chsize(dfile, maria_block_size, 0, MYF(MY_WME)))
return 1;
for (i= 0 ; i < maria_block_size ; i+= IO_SIZE)
if (my_write(dfile, buff, sizeof(buff), MYF(MY_NABP)))
return 1;
share->state.state.data_file_length= maria_block_size;
_ma_bitmap_delete_all(share);
}

View file

@ -525,7 +525,7 @@ static int underflow(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo,
DBUG_DUMP("leaf_buff",leaf_buff,maria_getint(leaf_buff));
buff=info->buff;
info->keybuff_used=1;
info->keyread_buff_used=1;
next_keypos=keypos;
nod_flag=_ma_test_if_nod(leaf_buff);
p_length=nod_flag+2;

View file

@ -883,7 +883,7 @@ uint _ma_rec_pack(MARIA_HA *info, register byte *to, register const byte *from)
uint length,new_length,flag,bit,i;
char *pos,*end,*startpos,*packpos;
enum en_fieldtype type;
reg3 MARIA_COLUMNDEF *rec;
reg3 MARIA_COLUMNDEF *column;
MARIA_BLOB *blob;
DBUG_ENTER("_ma_rec_pack");
@ -892,7 +892,7 @@ uint _ma_rec_pack(MARIA_HA *info, register byte *to, register const byte *from)
startpos= packpos=to;
to+= info->s->base.pack_bytes;
blob= info->blobs;
rec= info->s->rec;
column= info->s->columndef;
if (info->s->base.null_bytes)
{
memcpy(to, from, info->s->base.null_bytes);
@ -900,10 +900,10 @@ uint _ma_rec_pack(MARIA_HA *info, register byte *to, register const byte *from)
to+= info->s->base.null_bytes;
}
for (i=info->s->base.fields ; i-- > 0; from+= length,rec++)
for (i=info->s->base.fields ; i-- > 0; from+= length, column++)
{
length=(uint) rec->length;
if ((type = (enum en_fieldtype) rec->type) != FIELD_NORMAL)
length=(uint) column->length;
if ((type = (enum en_fieldtype) column->type) != FIELD_NORMAL)
{
if (type == FIELD_BLOB)
{
@ -912,7 +912,7 @@ uint _ma_rec_pack(MARIA_HA *info, register byte *to, register const byte *from)
else
{
char *temp_pos;
size_t tmp_length=length-maria_portable_sizeof_char_ptr;
size_t tmp_length=length-portable_sizeof_char_ptr;
memcpy((byte*) to,from,tmp_length);
memcpy_fixed(&temp_pos,from+tmp_length,sizeof(char*));
memcpy(to+tmp_length,temp_pos,(size_t) blob->length);
@ -944,10 +944,10 @@ uint _ma_rec_pack(MARIA_HA *info, register byte *to, register const byte *from)
pos++;
}
new_length=(uint) (end-pos);
if (new_length +1 + test(rec->length > 255 && new_length > 127)
if (new_length +1 + test(column->length > 255 && new_length > 127)
< length)
{
if (rec->length > 255 && new_length > 127)
if (column->length > 255 && new_length > 127)
{
to[0]=(char) ((new_length & 127)+128);
to[1]=(char) (new_length >> 7);
@ -965,7 +965,7 @@ uint _ma_rec_pack(MARIA_HA *info, register byte *to, register const byte *from)
}
else if (type == FIELD_VARCHAR)
{
uint pack_length= HA_VARCHAR_PACKLENGTH(rec->length -1);
uint pack_length= HA_VARCHAR_PACKLENGTH(column->length -1);
uint tmp_length;
if (pack_length == 1)
{
@ -1018,28 +1018,28 @@ my_bool _ma_rec_check(MARIA_HA *info,const char *record, byte *rec_buff,
uint length,new_length,flag,bit,i;
char *pos,*end,*packpos,*to;
enum en_fieldtype type;
reg3 MARIA_COLUMNDEF *rec;
reg3 MARIA_COLUMNDEF *column;
DBUG_ENTER("_ma_rec_check");
packpos=rec_buff; to= rec_buff+info->s->base.pack_bytes;
rec=info->s->rec;
column= info->s->columndef;
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++)
for (i=info->s->base.fields ; i-- > 0; record+= length, column++)
{
length=(uint) rec->length;
if ((type = (enum en_fieldtype) rec->type) != FIELD_NORMAL)
length=(uint) column->length;
if ((type = (enum en_fieldtype) column->type) != FIELD_NORMAL)
{
if (type == FIELD_BLOB)
{
uint blob_length=
_ma_calc_blob_length(length-maria_portable_sizeof_char_ptr,record);
_ma_calc_blob_length(length-portable_sizeof_char_ptr,record);
if (!blob_length && !(flag & bit))
goto err;
if (blob_length)
to+=length - maria_portable_sizeof_char_ptr+ blob_length;
to+=length - portable_sizeof_char_ptr+ blob_length;
}
else if (type == FIELD_SKIP_ZERO)
{
@ -1066,12 +1066,12 @@ my_bool _ma_rec_check(MARIA_HA *info,const char *record, byte *rec_buff,
pos++;
}
new_length=(uint) (end-pos);
if (new_length +1 + test(rec->length > 255 && new_length > 127)
if (new_length +1 + test(column->length > 255 && new_length > 127)
< length)
{
if (!(flag & bit))
goto err;
if (rec->length > 255 && new_length > 127)
if (column->length > 255 && new_length > 127)
{
if (to[0] != (char) ((new_length & 127)+128) ||
to[1] != (char) (new_length >> 7))
@ -1087,7 +1087,7 @@ my_bool _ma_rec_check(MARIA_HA *info,const char *record, byte *rec_buff,
}
else if (type == FIELD_VARCHAR)
{
uint pack_length= HA_VARCHAR_PACKLENGTH(rec->length -1);
uint pack_length= HA_VARCHAR_PACKLENGTH(column->length -1);
uint tmp_length;
if (pack_length == 1)
{
@ -1139,10 +1139,10 @@ err:
ulong _ma_rec_unpack(register MARIA_HA *info, register byte *to, byte *from,
ulong found_length)
{
uint flag,bit,length,rec_length,min_pack_length;
uint flag,bit,length,min_pack_length, column_length;
enum en_fieldtype type;
byte *from_end,*to_end,*packpos;
reg3 MARIA_COLUMNDEF *rec,*end_field;
reg3 MARIA_COLUMNDEF *column, *end_column;
DBUG_ENTER("_ma_rec_unpack");
to_end=to + info->s->base.reclength;
@ -1161,27 +1161,27 @@ ulong _ma_rec_unpack(register MARIA_HA *info, register byte *to, byte *from,
min_pack_length-= length;
}
for (rec=info->s->rec , end_field=rec+info->s->base.fields ;
rec < end_field ; to+= rec_length, rec++)
for (column= info->s->columndef, end_column= column + info->s->base.fields;
column < end_column ; to+= column_length, column++)
{
rec_length=rec->length;
if ((type = (enum en_fieldtype) rec->type) != FIELD_NORMAL &&
column_length= column->length;
if ((type = (enum en_fieldtype) column->type) != FIELD_NORMAL &&
(type != FIELD_CHECK))
{
if (type == FIELD_VARCHAR)
{
uint pack_length= HA_VARCHAR_PACKLENGTH(rec_length-1);
uint pack_length= HA_VARCHAR_PACKLENGTH(column_length-1);
if (pack_length == 1)
{
length= (uint) *(uchar*) from;
if (length > rec_length-1)
if (length > column_length-1)
goto err;
*to= *from++;
}
else
{
get_key_length(length, from);
if (length > rec_length-2)
if (length > column_length-2)
goto err;
int2store(to,length);
}
@ -1195,11 +1195,11 @@ ulong _ma_rec_unpack(register MARIA_HA *info, register byte *to, byte *from,
if (flag & bit)
{
if (type == FIELD_BLOB || type == FIELD_SKIP_ZERO)
bzero((byte*) to,rec_length);
bzero((byte*) to,column_length);
else if (type == FIELD_SKIP_ENDSPACE ||
type == FIELD_SKIP_PRESPACE)
{
if (rec->length > 255 && *from & 128)
if (column->length > 255 && *from & 128)
{
if (from + 1 >= from_end)
goto err;
@ -1212,25 +1212,25 @@ ulong _ma_rec_unpack(register MARIA_HA *info, register byte *to, byte *from,
length= (uchar) *from++;
}
min_pack_length--;
if (length >= rec_length ||
if (length >= column_length ||
min_pack_length + length > (uint) (from_end - from))
goto err;
if (type == FIELD_SKIP_ENDSPACE)
{
memcpy(to,(byte*) from,(size_t) length);
bfill((byte*) to+length,rec_length-length,' ');
bfill((byte*) to+length,column_length-length,' ');
}
else
{
bfill((byte*) to,rec_length-length,' ');
memcpy(to+rec_length-length,(byte*) from,(size_t) length);
bfill((byte*) to,column_length-length,' ');
memcpy(to+column_length-length,(byte*) from,(size_t) length);
}
from+=length;
}
}
else if (type == FIELD_BLOB)
{
uint size_length=rec_length- maria_portable_sizeof_char_ptr;
uint size_length=column_length- portable_sizeof_char_ptr;
ulong blob_length= _ma_calc_blob_length(size_length,from);
ulong from_left= (ulong) (from_end - from);
if (from_left < size_length ||
@ -1246,9 +1246,9 @@ ulong _ma_rec_unpack(register MARIA_HA *info, register byte *to, byte *from,
{
if (type == FIELD_SKIP_ENDSPACE || type == FIELD_SKIP_PRESPACE)
min_pack_length--;
if (min_pack_length + rec_length > (uint) (from_end - from))
if (min_pack_length + column_length > (uint) (from_end - from))
goto err;
memcpy(to,(byte*) from,(size_t) rec_length); from+=rec_length;
memcpy(to,(byte*) from,(size_t) column_length); from+=column_length;
}
if ((bit= bit << 1) >= 256)
{
@ -1259,9 +1259,9 @@ ulong _ma_rec_unpack(register MARIA_HA *info, register byte *to, byte *from,
{
if (min_pack_length > (uint) (from_end - from))
goto err;
min_pack_length-=rec_length;
memcpy(to, (byte*) from, (size_t) rec_length);
from+=rec_length;
min_pack_length-=column_length;
memcpy(to, (byte*) from, (size_t) column_length);
from+=column_length;
}
}
if (info->s->calc_checksum)
@ -1620,7 +1620,7 @@ err:
/*
Read record from datafile.
Read next record from datafile during table scan.
SYNOPSIS
_ma_read_rnd_dynamic_record()
@ -1631,22 +1631,17 @@ err:
record is found.
NOTE
This is identical to _ma_read_dynamic_record(), except the following
cases:
If a write buffer is active, it needs to be flushed if its contents
intersects with the record to read. We always check if the position
of the first byte of the write buffer is lower than the position
past the last byte to read. In theory this is also true if the write
buffer is completely below the read segment. That is, if there is no
intersection. But this case is unusual. We flush anyway. Only if the
first byte in the write buffer is above the last byte to read, we do
not flush.
- If there is no active row at 'filepos', continue scanning for
an active row. (This is becasue the previous
_ma_read_rnd_dynamic_record() call stored the next block position
in filepos, but this position may not be a start block for a row
- We may have READ_CACHING enabled, in which case we use the cache
to read rows.
A dynamic record may need several reads. So this check must be done
before every read. Reading a dynamic record starts with reading the
block header. If the record does not fit into the free space of the
header, the block may be longer than the header. In this case a
second read is necessary. These one or two reads repeat for every
part of the record.
For other comments, check _ma_read_dynamic_record()
RETURN
0 OK

View file

@ -49,7 +49,7 @@ int main(int argc, char *argv[])
recinfo[0].type=FIELD_SKIP_ENDSPACE;
recinfo[0].length=docid_length;
recinfo[1].type=FIELD_BLOB;
recinfo[1].length= 4+maria_portable_sizeof_char_ptr;
recinfo[1].length= 4+portable_sizeof_char_ptr;
/* Define a key over the first column */
keyinfo[0].seg=keyseg;

View file

@ -76,12 +76,12 @@ static int run_test(const char *filename)
/* First define 2 columns */
recinfo[0].type=extra_field;
recinfo[0].length= (extra_field == FIELD_BLOB ? 4 + maria_portable_sizeof_char_ptr :
recinfo[0].length= (extra_field == FIELD_BLOB ? 4 + portable_sizeof_char_ptr :
extra_length);
if (extra_field == FIELD_VARCHAR)
recinfo[0].length+= HA_VARCHAR_PACKLENGTH(extra_length);
recinfo[1].type=key_field;
recinfo[1].length= (key_field == FIELD_BLOB ? 4+maria_portable_sizeof_char_ptr :
recinfo[1].length= (key_field == FIELD_BLOB ? 4+portable_sizeof_char_ptr :
key_length);
if (key_field == FIELD_VARCHAR)
recinfo[1].length+= HA_VARCHAR_PACKLENGTH(key_length);

View file

@ -329,7 +329,7 @@ uint _ma_ft_convert_to_ft2(MARIA_HA *info, uint keynr, byte *key)
/* creating pageful of keys */
maria_putint(info->buff,length+2,0);
memcpy(info->buff+2, key_ptr, length);
info->keybuff_used=info->page_changed=1; /* info->buff is used */
info->keyread_buff_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);

View file

@ -126,10 +126,14 @@ void _ma_report_error(int errcode, const char *file_name)
if ((length= strlen(file_name)) > 64)
{
/* we first remove the directory */
uint dir_length= dirname_length(file_name);
file_name+= dir_length;
if ((length-= dir_length) > 64)
{
/* still too long, chop start of table name */
file_name+= length - 64;
}
}
my_error(errcode, MYF(ME_NOREFRESH), file_name);
DBUG_VOID_RETURN;

View file

@ -232,13 +232,21 @@ MARIA_HA *maria_open(const char *name, int mode, uint open_flags)
}
key_parts+=fulltext_keys*FT_SEGS;
if (share->base.max_key_length > HA_MAX_KEY_BUFF || keys > MARIA_MAX_KEY ||
key_parts >= MARIA_MAX_KEY * HA_MAX_KEY_SEG)
if (share->base.max_key_length > maria_max_key_length() ||
keys > MARIA_MAX_KEY || key_parts >= MARIA_MAX_KEY * HA_MAX_KEY_SEG)
{
DBUG_PRINT("error",("Wrong key info: Max_key_length: %d keys: %d key_parts: %d", share->base.max_key_length, keys, key_parts));
my_errno=HA_ERR_UNSUPPORTED;
goto err;
}
if (share->base.block_size != maria_block_size)
{
DBUG_PRINT("error", ("Wrong block size %u; Expected %u",
(uint) share->base.block_size,
(uint) maria_block_size));
my_errno=HA_ERR_UNSUPPORTED;
goto err;
}
/* Correct max_file_length based on length of sizeof(off_t) */
max_data_file_length=
@ -268,7 +276,7 @@ MARIA_HA *maria_open(const char *name, int mode, uint open_flags)
&share->keyparts,
(key_parts+unique_key_parts+keys+uniques) *
sizeof(HA_KEYSEG),
&share->rec,
&share->columndef,
(share->base.fields+1)*sizeof(MARIA_COLUMNDEF),
&share->blobs,sizeof(MARIA_BLOB)*share->base.blobs,
&share->unique_file_name,strlen(name_buff)+1,
@ -304,7 +312,6 @@ 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->block_size,share->keyinfo[i].block_length);
share->keyinfo[i].seg=pos;
for (j=0 ; j < share->keyinfo[i].keysegs; j++,pos++)
{
@ -418,7 +425,7 @@ MARIA_HA *maria_open(const char *name, int mode, uint open_flags)
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);
share->base.max_key_length);
if (share->data_file_type == DYNAMIC_RECORD)
{
share->base.extra_rec_buff_size=
@ -430,18 +437,18 @@ MARIA_HA *maria_open(const char *name, int mode, uint open_flags)
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;
if (share->rec[i].type == (int) FIELD_BLOB)
disk_pos=_ma_columndef_read(disk_pos,&share->columndef[i]);
share->columndef[i].pack_type=0;
share->columndef[i].huff_tree=0;
if (share->columndef[i].type == (int) FIELD_BLOB)
{
share->blobs[j].pack_length=
share->rec[i].length-maria_portable_sizeof_char_ptr;;
share->blobs[j].offset= share->rec[i].offset;
share->columndef[i].length-portable_sizeof_char_ptr;;
share->blobs[j].offset= share->columndef[i].offset;
j++;
}
}
share->rec[i].type=(int) FIELD_LAST; /* End marker */
share->columndef[i].type=(int) FIELD_LAST; /* End marker */
#ifdef ASKMONTY
/*
This code was added to mi_open.c in this cset:
@ -718,8 +725,8 @@ void _ma_setup_functions(register MARIA_SHARE *share)
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->scan_init= maria_scan_init_dummy;/* Compat. dummy function */
share->scan_end= maria_scan_end_dummy;/* Compat. dummy function */
share->write_record_init= _ma_write_init_default;
share->write_record_abort= _ma_write_abort_default;
@ -729,7 +736,10 @@ void _ma_setup_functions(register MARIA_SHARE *share)
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 */
/*
Calculate checksum according to data in the original, not compressed,
row.
*/
if (share->state.header.org_data_file_type == STATIC_RECORD)
share->calc_checksum= _ma_static_checksum;
else
@ -767,10 +777,10 @@ void _ma_setup_functions(register MARIA_SHARE *share)
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->once_init= _ma_once_init_block_record;
share->once_end= _ma_once_end_block_record;
share->init= _ma_init_block_record;
share->end= _ma_end_block_record;
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;
@ -783,6 +793,10 @@ void _ma_setup_functions(register MARIA_SHARE *share)
share->write_record= _ma_write_block_record;
share->compare_unique= _ma_cmp_block_unique;
share->calc_checksum= _ma_checksum;
/*
write_block_record() will calculate the checksum; Tell maria_write()
that it doesn't have to do this.
*/
share->calc_write_checksum= 0;
break;
}
@ -1187,32 +1201,32 @@ char *_ma_uniquedef_read(char *ptr, MARIA_UNIQUEDEF *def)
** MARIA_COLUMNDEF
***************************************************************************/
uint _ma_recinfo_write(File file, MARIA_COLUMNDEF *recinfo)
uint _ma_columndef_write(File file, MARIA_COLUMNDEF *columndef)
{
uchar buff[MARIA_COLUMNDEF_SIZE];
uchar *ptr=buff;
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;
mi_int6store(ptr,columndef->offset); ptr+= 6;
mi_int2store(ptr,columndef->type); ptr+= 2;
mi_int2store(ptr,columndef->length); ptr+= 2;
mi_int2store(ptr,columndef->fill_length); ptr+= 2;
mi_int2store(ptr,columndef->null_pos); ptr+= 2;
mi_int2store(ptr,columndef->empty_pos); ptr+= 2;
(*ptr++)= columndef->null_bit;
(*ptr++)= columndef->empty_bit;
return my_write(file,(char*) buff, (uint) (ptr-buff), MYF(MY_NABP));
}
char *_ma_recinfo_read(char *ptr, MARIA_COLUMNDEF *recinfo)
char *_ma_columndef_read(char *ptr, MARIA_COLUMNDEF *columndef)
{
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++;
columndef->offset= mi_uint6korr(ptr); ptr+= 6;
columndef->type= mi_sint2korr(ptr); ptr+= 2;
columndef->length= mi_uint2korr(ptr); ptr+= 2;
columndef->fill_length= mi_uint2korr(ptr); ptr+= 2;
columndef->null_pos= mi_uint2korr(ptr); ptr+= 2;
columndef->empty_pos= mi_uint2korr(ptr); ptr+= 2;
columndef->null_bit= (uint8) *ptr++;
columndef->empty_bit= (uint8) *ptr++;
return ptr;
}

View file

@ -142,15 +142,14 @@ static maria_bit_type mask[]=
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;
return (_ma_read_pack_info(share, dfile,
(pbool)
test(!(share->options &
(HA_OPTION_PACK_RECORD |
HA_OPTION_TEMP_COMPRESS_RECORD)))));
}
my_bool _ma_once_end_pack_row(MARIA_SHARE *share)
{
if (share->decode_trees)
@ -262,15 +261,16 @@ static my_bool _ma_read_pack_info(MARIA_SHARE *share, File file,
/* Read new info for each field */
for (i=0 ; i < share->base.fields ; i++)
{
share->rec[i].base_type=(enum en_fieldtype) get_bits(&bit_buff,5);
share->rec[i].pack_type=(uint) get_bits(&bit_buff,6);
share->rec[i].space_length_bits=get_bits(&bit_buff,5);
share->rec[i].huff_tree=share->decode_trees+(uint) get_bits(&bit_buff,
share->columndef[i].base_type=(enum en_fieldtype) get_bits(&bit_buff,5);
share->columndef[i].pack_type=(uint) get_bits(&bit_buff,6);
share->columndef[i].space_length_bits=get_bits(&bit_buff,5);
share->columndef[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->columndef[i].unpack= get_unpack_function(share->columndef + i);
DBUG_PRINT("info", ("col: %2u type: %2u pack: %u slbits: %2u",
i, share->rec[i].base_type, share->rec[i].pack_type,
share->rec[i].space_length_bits));
i, share->columndef[i].base_type,
share->columndef[i].pack_type,
share->columndef[i].space_length_bits));
}
skip_to_next_byte(&bit_buff);
/*
@ -776,7 +776,7 @@ int _ma_pack_rec_unpack(register MARIA_HA *info, MARIA_BIT_BUFF *bit_buff,
reclength-= info->s->base.null_bytes;
}
init_bit_buffer(bit_buff, (uchar*) from, reclength);
for (current_field=share->rec, end=current_field+share->base.fields ;
for (current_field=share->columndef, end=current_field+share->base.fields ;
current_field < end ;
current_field++,to=end_field)
{
@ -1080,7 +1080,7 @@ static void uf_blob(MARIA_COLUMNDEF *rec, MARIA_BIT_BUFF *bit_buff,
else
{
ulong length=get_bits(bit_buff,rec->space_length_bits);
uint pack_length=(uint) (end-to)-maria_portable_sizeof_char_ptr;
uint pack_length=(uint) (end-to)-portable_sizeof_char_ptr;
if (bit_buff->blob_pos+length > bit_buff->blob_end)
{
bit_buff->error=1;

View file

@ -32,7 +32,7 @@ byte *_ma_fetch_keypage(register MARIA_HA *info, MARIA_KEYDEF *keyinfo,
info->s->block_size, info->s->block_size,
return_buffer);
if (tmp == info->buff)
info->keybuff_used=1;
info->keyread_buff_used=1;
else if (!tmp)
{
DBUG_PRINT("error",("Got errno: %d from key_cache_read",my_errno));

View file

@ -150,7 +150,6 @@ int maria_rkey(MARIA_HA *info, byte *buf, int inx, const byte *key,
else
info->last_rkey_length= pack_key_length;
/* Check if we don't want to have record back, only error message */
if (!buf)
{

View file

@ -36,7 +36,6 @@ int maria_rrnd(MARIA_HA *info, byte *buf, MARIA_RECORD_POS filepos)
#ifdef NOT_USED
if (filepos == HA_OFFSET_ERROR)
{
skip_deleted_blocks=1;
if (info->cur_row.lastpos == HA_OFFSET_ERROR) /* First read ? */
filepos= info->s->pack.header_length; /* Read first record */
else

View file

@ -127,11 +127,11 @@ static int maria_rtree_find_req(MARIA_HA *info, MARIA_KEYDEF *keyinfo,
info->int_keypos = info->buff;
info->int_maxpos = info->buff + (last - after_key);
memcpy(info->buff, after_key, last - after_key);
info->keybuff_used = 0;
info->keyread_buff_used = 0;
}
else
{
info->keybuff_used = 1;
info->keyread_buff_used = 1;
}
res = 0;
@ -192,7 +192,7 @@ int maria_rtree_find_first(MARIA_HA *info, uint keynr, byte *key,
info->last_rkey_length = key_length;
info->maria_rtree_recursion_depth = -1;
info->keybuff_used = 1;
info->keyread_buff_used = 1;
nod_cmp_flag= ((search_flag & (MBR_EQUAL | MBR_WITHIN)) ?
MBR_WITHIN : MBR_INTERSECT);
@ -227,7 +227,7 @@ int maria_rtree_find_next(MARIA_HA *info, uint keynr, uint search_flag)
info->lastkey_length,
search_flag);
if (!info->keybuff_used)
if (!info->keyread_buff_used)
{
byte *key= info->int_keypos;
@ -245,7 +245,7 @@ int maria_rtree_find_next(MARIA_HA *info, uint keynr, uint search_flag)
if (after_key < info->int_maxpos)
info->int_keypos= after_key;
else
info->keybuff_used= 1;
info->keyread_buff_used= 1;
return 0;
}
key+= keyinfo->keylength;
@ -342,11 +342,11 @@ static int maria_rtree_get_req(MARIA_HA *info, MARIA_KEYDEF *keyinfo, uint key_l
info->int_keypos = (byte*) saved_key;
memcpy(info->buff, page_buf, keyinfo->block_length);
info->int_maxpos = rt_PAGE_END(info->buff);
info->keybuff_used = 0;
info->keyread_buff_used = 0;
}
else
{
info->keybuff_used = 1;
info->keyread_buff_used = 1;
}
res = 0;
@ -389,7 +389,7 @@ int maria_rtree_get_first(MARIA_HA *info, uint keynr, uint key_length)
}
info->maria_rtree_recursion_depth = -1;
info->keybuff_used = 1;
info->keyread_buff_used = 1;
return maria_rtree_get_req(info, &keyinfo[keynr], key_length, root, 0);
}
@ -409,7 +409,7 @@ 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->keybuff_used)
if (!info->keyread_buff_used)
{
uint k_len = keyinfo->keylength - info->s->base.rec_reflength;
/* rt_PAGE_NEXT_KEY(info->int_keypos) */
@ -425,7 +425,7 @@ int maria_rtree_get_next(MARIA_HA *info, uint keynr, uint key_length)
*(int*)info->int_keypos = key - info->buff;
if (after_key >= info->int_maxpos)
{
info->keybuff_used = 1;
info->keyread_buff_used = 1;
}
return 0;
@ -638,7 +638,7 @@ static int maria_rtree_insert_level(MARIA_HA *info, uint keynr, byte *key,
{
if ((old_root = _ma_new(info, keyinfo, DFLT_INIT_HITS)) == HA_OFFSET_ERROR)
return -1;
info->keybuff_used = 1;
info->keyread_buff_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))

View file

@ -157,7 +157,7 @@ int _ma_search(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo,
info->int_keytree_version=keyinfo->version;
info->last_search_keypage=info->last_keypage;
info->page_changed=0;
info->keybuff_used= (info->keyread_buff != buff); /* If we have to reread */
info->keyread_buff_used= (info->keyread_buff != buff); /* If we have to reread */
DBUG_PRINT("exit",("found key at %lu",(ulong) info->cur_row.lastpos));
DBUG_RETURN(0);
@ -618,7 +618,7 @@ void _ma_kpointer(register MARIA_HA *info, register byte *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]= (char) (uchar) pos; break;
case 1: buff[0]= (byte) pos; break;
default: abort(); /* impossible */
}
} /* _ma_kpointer */
@ -1219,10 +1219,10 @@ int _ma_search_next(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo,
uint nod_flag;
byte lastkey[HA_MAX_KEY_BUFF];
DBUG_ENTER("_ma_search_next");
DBUG_PRINT("enter",("nextflag: %u lastpos: %lu int_keypos: %lu page_changed %d keybuff_used: %d",
DBUG_PRINT("enter",("nextflag: %u lastpos: %lu int_keypos: %lu page_changed %d keyread_buff_used: %d",
nextflag, (ulong) info->cur_row.lastpos,
(ulong) info->int_keypos,
info->page_changed, info->keybuff_used));
info->page_changed, info->keyread_buff_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
@ -1235,16 +1235,16 @@ 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->keybuff_used)))
(info->int_nod_flag || info->keyread_buff_used)))
DBUG_RETURN(_ma_search(info,keyinfo,key, USE_WHOLE_KEY,
nextflag | SEARCH_SAVE_BUFF, pos));
if (info->keybuff_used)
if (info->keyread_buff_used)
{
if (!_ma_fetch_keypage(info,keyinfo,info->last_search_keypage,
DFLT_INIT_HITS,info->keyread_buff,0))
DBUG_RETURN(-1);
info->keybuff_used=0;
info->keyread_buff_used=0;
}
/* Last used buffer is in info->keyread_buff */
@ -1328,7 +1328,7 @@ int _ma_search_first(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo,
info->int_nod_flag=nod_flag;
info->int_keytree_version=keyinfo->version;
info->last_search_keypage=info->last_keypage;
info->page_changed=info->keybuff_used=0;
info->page_changed=info->keyread_buff_used=0;
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));
@ -1373,7 +1373,7 @@ int _ma_search_last(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo,
info->int_nod_flag=nod_flag;
info->int_keytree_version=keyinfo->version;
info->last_search_keypage=info->last_keypage;
info->page_changed=info->keybuff_used=0;
info->page_changed=info->keyread_buff_used=0;
DBUG_PRINT("exit",("found key at %lu",(ulong) info->cur_row.lastpos));
DBUG_RETURN(0);

View file

@ -80,7 +80,7 @@ int run_test(const char *filename)
/* Define spatial column */
recinfo[1].type=FIELD_BLOB;
recinfo[1].length=4 + maria_portable_sizeof_char_ptr;
recinfo[1].length=4 + portable_sizeof_char_ptr;

View file

@ -73,12 +73,12 @@ static int run_test(const char *filename)
/* First define 2 columns */
create_info.null_bytes= 1;
recinfo[0].type= key_field;
recinfo[0].length= (key_field == FIELD_BLOB ? 4+maria_portable_sizeof_char_ptr :
recinfo[0].length= (key_field == FIELD_BLOB ? 4+portable_sizeof_char_ptr :
key_length);
if (key_field == FIELD_VARCHAR)
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);
recinfo[1].length= (extra_field == FIELD_BLOB ? 4 + portable_sizeof_char_ptr : 24);
if (extra_field == FIELD_VARCHAR)
recinfo[1].length+= HA_VARCHAR_PACKLENGTH(recinfo[1].length);
if (opt_unique)

View file

@ -191,7 +191,7 @@ int main(int argc, char *argv[])
if (use_blob)
{
recinfo[6].type=FIELD_BLOB;
recinfo[6].length=4+maria_portable_sizeof_char_ptr;
recinfo[6].length=4+portable_sizeof_char_ptr;
recinfo[6].null_bit=0;
recinfo[6].null_pos=0;
}

View file

@ -177,7 +177,7 @@ int maria_update(register MARIA_HA *info, const byte *oldrec, byte *newrec)
info->state->checksum+= (info->cur_row.checksum - old_checksum);
/*
We can't yet have HA_STATE_ACTIVE here, as block_record dosn't support
We can't yet have HA_STATE_AKTIV here, as block_record dosn't support
it
*/
info->update= (HA_STATE_CHANGED | HA_STATE_ROW_CHANGED | key_changed);

View file

@ -356,7 +356,7 @@ int _ma_enlarge_root(MARIA_HA *info, MARIA_KEYDEF *keyinfo, byte *key,
(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->keybuff_used=info->page_changed=1; /* info->buff is used */
info->keyread_buff_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);
@ -634,7 +634,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->keybuff_used=1;
info->keyread_buff_used=1;
nod_flag=_ma_test_if_nod(buff);
key_ref_length=2+nod_flag;
if (insert_last_key)

View file

@ -50,8 +50,8 @@ static const char *type_names[]=
"impossible","char","binary", "short", "long", "float",
"double","number","unsigned short",
"unsigned long","longlong","ulonglong","int24",
"uint24","int8","varchar", "varbin","?",
"?"
"uint24","int8","varchar", "varbin", "varchar2", "varbin2", "bit",
"?","?"
};
static const char *prefix_packed_txt="packed ",
@ -1224,7 +1224,7 @@ end2:
static void descript(HA_CHECK *param, register MARIA_HA *info, my_string name)
{
uint key,keyseg_nr,field,start;
uint key,keyseg_nr,field;
reg3 MARIA_KEYDEF *keyinfo;
reg2 HA_KEYSEG *keyseg;
reg4 const char *text;
@ -1430,43 +1430,42 @@ static void descript(HA_CHECK *param, register MARIA_HA *info, my_string name)
for (field=0 ; field < share->base.fields ; field++)
{
if (share->options & HA_OPTION_COMPRESS_RECORD)
type=share->rec[field].base_type;
type=share->columndef[field].base_type;
else
type=(enum en_fieldtype) share->rec[field].type;
type=(enum en_fieldtype) share->columndef[field].type;
end=strmov(buff,field_pack[type]);
if (share->options & HA_OPTION_COMPRESS_RECORD)
{
if (share->rec[field].pack_type & PACK_TYPE_SELECTED)
if (share->columndef[field].pack_type & PACK_TYPE_SELECTED)
end=strmov(end,", not_always");
if (share->rec[field].pack_type & PACK_TYPE_SPACE_FIELDS)
if (share->columndef[field].pack_type & PACK_TYPE_SPACE_FIELDS)
end=strmov(end,", no empty");
if (share->rec[field].pack_type & PACK_TYPE_ZERO_FILL)
if (share->columndef[field].pack_type & PACK_TYPE_ZERO_FILL)
{
sprintf(end,", zerofill(%d)",share->rec[field].space_length_bits);
sprintf(end,", zerofill(%d)",share->columndef[field].space_length_bits);
end=strend(end);
}
}
if (buff[0] == ',')
strmov(buff,buff+2);
int10_to_str((long) share->rec[field].length,length,10);
int10_to_str((long) share->columndef[field].length,length,10);
null_bit[0]=null_pos[0]=0;
if (share->rec[field].null_bit)
if (share->columndef[field].null_bit)
{
sprintf(null_bit,"%d",share->rec[field].null_bit);
sprintf(null_pos,"%d",share->rec[field].null_pos+1);
sprintf(null_bit,"%d",share->columndef[field].null_bit);
sprintf(null_pos,"%d",share->columndef[field].null_pos+1);
}
printf("%-6d%-6u%-7s%-8s%-8s%-35s",field+1,
(uint) share->rec[field].offset+1,
(uint) share->columndef[field].offset+1,
length, null_pos, null_bit, buff);
if (share->options & HA_OPTION_COMPRESS_RECORD)
{
if (share->rec[field].huff_tree)
if (share->columndef[field].huff_tree)
printf("%3d %2d",
(uint) (share->rec[field].huff_tree-share->decode_trees)+1,
share->rec[field].huff_tree->quick_table_bits);
(uint) (share->columndef[field].huff_tree-share->decode_trees)+1,
share->columndef[field].huff_tree->quick_table_bits);
}
VOID(putchar('\n'));
start+=share->rec[field].length;
}
}
DBUG_VOID_RETURN;
@ -1556,8 +1555,9 @@ static int maria_sort_records(HA_CHECK *param,
fn_format(param->temp_filename,name,"", MARIA_NAME_DEXT,2+4+32);
new_file= my_create(fn_format(param->temp_filename,
param->temp_filename,"",
DATA_TMP_EXT,2+4),
0,param->tmpfile_createflag,
DATA_TMP_EXT,
MY_REPLACE_EXT | MY_UNPACK_FILENAME),
0, param->tmpfile_createflag,
MYF(0));
if (new_file < 0)
{

View file

@ -60,7 +60,8 @@ typedef struct st_maria_state_info
uchar language; /* Language for indexes */
uchar fulltext_keys;
uchar data_file_type;
uchar org_data_file_type; /* Used by mariapack to store dft */
/* Used by mariapack to store the original data_file_type */
uchar org_data_file_type;
} header;
MARIA_STATUS_INFO state;
@ -75,7 +76,7 @@ typedef struct st_maria_state_info
ulong *rec_per_key_part;
ha_checksum checksum; /* Table checksum */
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 index pages */
my_off_t rec_per_key_rows; /* Rows when calculating rec_per_key */
ulong sec_index_changed; /* Updated when new sec_index */
@ -107,6 +108,13 @@ typedef struct st_maria_state_info
#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 */
/* Internal management bytes needed to store 2 keys on an index page */
#define MARIA_INDEX_MIN_OVERHEAD_SIZE (4 + (TRANSID_SIZE+1) * 2)
/*
Basic information of the Maria table. This is stored on disk
and not changed (unless we do DLL changes).
*/
typedef struct st_ma_base_info
{
@ -127,7 +135,9 @@ typedef struct st_ma_base_info
uint max_field_lengths;
uint pack_fields; /* packed fields in table */
uint varlength_fields; /* char/varchar/blobs */
uint rec_reflength; /* = 2-8 */
/* Number of bytes in the index used to refer to a row (2-8) */
uint rec_reflength;
/* Number of bytes in the index used to refer to another index page (2-8) */
uint key_reflength; /* = 2-8 */
uint keys; /* same as in state.header */
uint auto_key; /* Which key-1 is a auto key */
@ -144,14 +154,17 @@ typedef struct st_ma_base_info
uint extra_alloc_bytes;
uint extra_alloc_procent;
uint is_nulls_extended; /* 1 if new null bytes */
uint min_row_length;
uint min_row_length; /* Min possible length of a row */
uint default_row_flag; /* 0 or ROW_FLAG_NULLS_EXTENDED */
uint block_size;
/* Size of initial record buffer */
uint default_rec_buff_size;
/* Extra number of bytes the row format require in the record buffer */
uint extra_rec_buff_size;
/* The following are from the header */
uint key_parts, all_key_parts;
/* If false, we disable logging, versioning etc */
my_bool transactional;
} MARIA_BASE_INFO;
@ -177,8 +190,8 @@ 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;
uint used_size; /* Size of bitmap head that is not 0 */
File file; /* Datafile, where bitmap is stored */
my_bool changed;
@ -204,8 +217,7 @@ typedef struct st_maria_share
MARIA_KEYDEF *keyinfo; /* Key definitions */
MARIA_UNIQUEDEF *uniqueinfo; /* unique definitions */
HA_KEYSEG *keyparts; /* key part info */
MARIA_COLUMNDEF *rec; /* Pointer to field information
*/
MARIA_COLUMNDEF *columndef; /* Pointer to column information */
MARIA_PACK pack; /* Data about packed records */
MARIA_BLOB *blobs; /* Pointer to blobs */
char *unique_file_name; /* realpath() of index file */
@ -216,25 +228,43 @@ typedef struct st_maria_share
KEY_CACHE *key_cache; /* ref to the current key cache */
MARIA_DECODE_TREE *decode_trees;
uint16 *decode_tables;
/* Called the first time the table instance is opened */
my_bool (*once_init)(struct st_maria_share *, File);
/* Called when the last instance of the table is closed */
my_bool (*once_end)(struct st_maria_share *);
/* Is called for every open of the table */
my_bool (*init)(struct st_maria_info *);
/* Is called for every close of the table */
void (*end)(struct st_maria_info *);
/* Called when we want to read a record from a specific position */
int (*read_record)(struct st_maria_info *, byte *, MARIA_RECORD_POS);
/* Initialize a scan */
my_bool (*scan_init)(struct st_maria_info *);
/* Read next record while scanning */
int (*scan)(struct st_maria_info *, byte *, MARIA_RECORD_POS, my_bool);
/* End scan */
void (*scan_end)(struct st_maria_info *);
/* Pre-write of row (some handlers may do the actual write here) */
MARIA_RECORD_POS (*write_record_init)(struct st_maria_info *, const byte *);
/* Write record (or accept write_record_init) */
my_bool (*write_record)(struct st_maria_info *, const byte *);
/* Called when write failed */
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 *);
/* calculate checksum for a row */
ha_checksum(*calc_checksum)(struct st_maria_info *, const byte *);
/*
Calculate checksum for a row during write. May be 0 if we calculate
the checksum in write_record_init()
*/
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);
/* Compare a row in memory with a row on disk */
my_bool (*compare_unique)(struct st_maria_info *, MARIA_UNIQUEDEF *,
const byte *record, MARIA_RECORD_POS pos);
/* Mapings to read/write the data file */
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 */
@ -255,6 +285,7 @@ typedef struct st_maria_share
uint reopen; /* How many times reopened */
uint w_locks, r_locks, tot_locks; /* Number of read/write locks */
uint block_size; /* block_size of keyfile & data file*/
/* Fixed length part of a packed row in BLOCK_RECORD format */
uint base_length;
myf write_flag;
enum data_file_type data_file_type;
@ -342,7 +373,8 @@ struct st_maria_info
{
MARIA_SHARE *s; /* Shared between open:s */
MARIA_STATUS_INFO *state, save_state;
MARIA_ROW cur_row, new_row;
MARIA_ROW cur_row; /* The active row that we just read */
MARIA_ROW new_row; /* Storage for a row during update */
MARIA_BLOCK_SCAN scan;
MARIA_BLOB *blobs; /* Pointer to blobs */
MARIA_BIT_BUFF bit_buff;
@ -404,8 +436,8 @@ struct st_maria_info
my_bool quick_mode;
/* If info->keyread_buff can't be used for rnext */
my_bool page_changed;
/* If info->keyread_buff has to be reread for rnext */
my_bool keybuff_used;
/* If info->keyread_buff has to be re-read for rnext */
my_bool keyread_buff_used;
my_bool once_flags; /* For MARIA_MRG */
#ifdef __WIN__
my_bool owned_by_merge; /* This Maria table is part of a merge union */
@ -419,7 +451,7 @@ struct st_maria_info
/* Some defines used by maria-functions */
#define USE_WHOLE_KEY HA_MAX_KEY_BUFF*2 /* Use whole key in _search() */
#define USE_WHOLE_KEY 65535 /* Use whole key in _search() */
#define F_EXTRA_LCK -1
/* bits in opt_flag */
@ -489,6 +521,7 @@ struct st_maria_info
{ length=mi_uint2korr((key)+1)+3; } \
}
#define maria_max_key_length() ((maria_block_size - MARIA_INDEX_MIN_OVERHEAD_SIZE)/2)
#define get_pack_length(length) ((length) >= 255 ? 3 : 1)
#define MARIA_MIN_BLOCK_LENGTH 20 /* Because of delete-link */
@ -720,7 +753,11 @@ extern int _ma_ft_update(MARIA_HA *info, uint keynr, byte *keybuf,
const byte *oldrec, const byte *newrec,
my_off_t pos);
/* Parameter to _ma_get_block_info */
/*
Parameter to _ma_get_block_info
The dynamic row header is read into this struct. For an explanation of
the fields, look at the function _ma_get_block_info().
*/
typedef struct st_maria_block_info
{
@ -736,6 +773,7 @@ typedef struct st_maria_block_info
uint offset;
} MARIA_BLOCK_INFO;
/* bits in return from _ma_get_block_info */
#define BLOCK_FIRST 1
@ -800,8 +838,8 @@ uint _ma_keydef_write(File file, MARIA_KEYDEF *keydef);
char *_ma_keydef_read(char *ptr, MARIA_KEYDEF *keydef);
uint _ma_uniquedef_write(File file, MARIA_UNIQUEDEF *keydef);
char *_ma_uniquedef_read(char *ptr, MARIA_UNIQUEDEF *keydef);
uint _ma_recinfo_write(File file, MARIA_COLUMNDEF *recinfo);
char *_ma_recinfo_read(char *ptr, MARIA_COLUMNDEF *recinfo);
uint _ma_columndef_write(File file, MARIA_COLUMNDEF *columndef);
char *_ma_columndef_read(char *ptr, MARIA_COLUMNDEF *columndef);
ulong _ma_calc_total_blob_length(MARIA_HA *info, const byte *record);
ha_checksum _ma_checksum(MARIA_HA *info, const byte *buf);
ha_checksum _ma_static_checksum(MARIA_HA *info, const byte *buf);

View file

@ -307,9 +307,10 @@ 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 maria_chk -rq on the datafile");
puts("Keys are not updated, you must run maria_chk -rq on the index (.MAI) file");
puts("afterwards to update the keys.");
puts("You should give the .MYI file as the filename argument.");
puts("You should give the .MAI file as the filename argument.");
puts("To unpack a packed table, run maria_chk -u on the table");
VOID(printf("\nUsage: %s [OPTIONS] filename...\n", my_progname));
my_print_help(my_long_options);
@ -462,9 +463,9 @@ static bool open_isam_files(PACK_MRG_INFO *mrg,char **names,uint count)
if (mrg->file[j]->s->base.reclength != mrg->file[j+1]->s->base.reclength ||
mrg->file[j]->s->base.fields != mrg->file[j+1]->s->base.fields)
goto diff_file;
m1=mrg->file[j]->s->rec;
m1=mrg->file[j]->s->columndef;
end=m1+mrg->file[j]->s->base.fields;
m2=mrg->file[j+1]->s->rec;
m2=mrg->file[j+1]->s->columndef;
for ( ; m1 != end ; m1++,m2++)
{
if (m1->type != m2->type || m1->length != m2->length)
@ -773,8 +774,8 @@ static HUFF_COUNTS *init_huff_count(MARIA_HA *info,my_off_t records)
for (i=0 ; i < info->s->base.fields ; i++)
{
enum en_fieldtype type;
count[i].field_length=info->s->rec[i].length;
type= count[i].field_type= (enum en_fieldtype) info->s->rec[i].type;
count[i].field_length=info->s->columndef[i].length;
type= count[i].field_type= (enum en_fieldtype) info->s->columndef[i].type;
if (type == FIELD_INTERVALL ||
type == FIELD_CONSTANT ||
type == FIELD_ZERO)
@ -1003,7 +1004,7 @@ static int get_statistic(PACK_MRG_INFO *mrg,HUFF_COUNTS *huff_counts)
/* Calculate pos, end_pos, and max_length for variable length fields. */
if (count->field_type == FIELD_BLOB)
{
uint field_length=count->field_length -maria_portable_sizeof_char_ptr;
uint field_length=count->field_length -portable_sizeof_char_ptr;
ulong blob_length= _ma_calc_blob_length(field_length, start_pos);
memcpy_fixed((char*) &pos, start_pos+field_length,sizeof(char*));
end_pos=pos+blob_length;
@ -2656,7 +2657,7 @@ static int compress_isam_file(PACK_MRG_INFO *mrg, HUFF_COUNTS *huff_counts)
case FIELD_BLOB:
{
ulong blob_length= _ma_calc_blob_length(field_length-
maria_portable_sizeof_char_ptr,
portable_sizeof_char_ptr,
start_pos);
/* Empty blobs are encoded with a single 1 bit. */
if (!blob_length)
@ -2673,7 +2674,7 @@ static int compress_isam_file(PACK_MRG_INFO *mrg, HUFF_COUNTS *huff_counts)
DBUG_PRINT("fields", ("FIELD_BLOB %lu bytes, bits: %2u",
blob_length, count->length_bits));
write_bits(blob_length,count->length_bits);
memcpy_fixed(&blob,end_pos-maria_portable_sizeof_char_ptr,
memcpy_fixed(&blob,end_pos-portable_sizeof_char_ptr,
sizeof(char*));
blob_end=blob+blob_length;
/* Encode the blob bytes. */
@ -2952,6 +2953,7 @@ static int save_state(MARIA_HA *isam_file,PACK_MRG_INFO *mrg,
options|= HA_OPTION_COMPRESS_RECORD | HA_OPTION_READ_ONLY_DATA;
mi_int2store(share->state.header.options,options);
/* Save the original file type of we have to undo the packing later */
share->state.header.org_data_file_type= share->state.header.data_file_type;
share->state.header.data_file_type= COMPRESSED_RECORD;

View file

@ -48,7 +48,7 @@ int main(int argc, char *argv[])
recinfo[0].type=FIELD_SKIP_ENDSPACE;
recinfo[0].length=docid_length;
recinfo[1].type=FIELD_BLOB;
recinfo[1].length= 4+mi_portable_sizeof_char_ptr;
recinfo[1].length= 4+portable_sizeof_char_ptr;
/* Define a key over the first column */
keyinfo[0].seg=keyseg;

View file

@ -75,12 +75,12 @@ static int run_test(const char *filename)
/* First define 2 columns */
recinfo[0].type=extra_field;
recinfo[0].length= (extra_field == FIELD_BLOB ? 4 + mi_portable_sizeof_char_ptr :
recinfo[0].length= (extra_field == FIELD_BLOB ? 4 + portable_sizeof_char_ptr :
extra_length);
if (extra_field == FIELD_VARCHAR)
recinfo[0].length+= HA_VARCHAR_PACKLENGTH(extra_length);
recinfo[1].type=key_field;
recinfo[1].length= (key_field == FIELD_BLOB ? 4+mi_portable_sizeof_char_ptr :
recinfo[1].length= (key_field == FIELD_BLOB ? 4+portable_sizeof_char_ptr :
key_length);
if (key_field == FIELD_VARCHAR)
recinfo[1].length+= HA_VARCHAR_PACKLENGTH(key_length);

View file

@ -31,9 +31,9 @@ ha_checksum mi_checksum(MI_INFO *info, const byte *buf)
case FIELD_BLOB:
{
length=_mi_calc_blob_length(rec->length-
mi_portable_sizeof_char_ptr,
portable_sizeof_char_ptr,
buf);
memcpy((char*) &pos, buf+rec->length- mi_portable_sizeof_char_ptr,
memcpy((char*) &pos, buf+rec->length- portable_sizeof_char_ptr,
sizeof(char*));
break;
}

View file

@ -117,10 +117,10 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs,
share.base.blobs++;
if (pack_reclength != INT_MAX32)
{
if (rec->length == 4+mi_portable_sizeof_char_ptr)
if (rec->length == 4+portable_sizeof_char_ptr)
pack_reclength= INT_MAX32;
else
pack_reclength+=(1 << ((rec->length-mi_portable_sizeof_char_ptr)*8)); /* Max blob length */
pack_reclength+=(1 << ((rec->length-portable_sizeof_char_ptr)*8)); /* Max blob length */
}
}
else if (type == FIELD_SKIP_PRESPACE ||

View file

@ -900,7 +900,7 @@ uint _mi_rec_pack(MI_INFO *info, register byte *to, register const byte *from)
else
{
char *temp_pos;
size_t tmp_length=length-mi_portable_sizeof_char_ptr;
size_t tmp_length=length-portable_sizeof_char_ptr;
memcpy((byte*) to,from,tmp_length);
memcpy_fixed(&temp_pos,from+tmp_length,sizeof(char*));
memcpy(to+tmp_length,temp_pos,(size_t) blob->length);
@ -1021,11 +1021,11 @@ my_bool _mi_rec_check(MI_INFO *info,const char *record, byte *rec_buff,
if (type == FIELD_BLOB)
{
uint blob_length=
_mi_calc_blob_length(length-mi_portable_sizeof_char_ptr,record);
_mi_calc_blob_length(length-portable_sizeof_char_ptr,record);
if (!blob_length && !(flag & bit))
goto err;
if (blob_length)
to+=length - mi_portable_sizeof_char_ptr+ blob_length;
to+=length - portable_sizeof_char_ptr+ blob_length;
}
else if (type == FIELD_SKIP_ZERO)
{
@ -1208,7 +1208,7 @@ ulong _mi_rec_unpack(register MI_INFO *info, register byte *to, byte *from,
}
else if (type == FIELD_BLOB)
{
uint size_length=rec_length- mi_portable_sizeof_char_ptr;
uint size_length=rec_length- portable_sizeof_char_ptr;
ulong blob_length=_mi_calc_blob_length(size_length,from);
ulong from_left= (ulong) (from_end - from);
if (from_left < size_length ||

View file

@ -453,7 +453,7 @@ MI_INFO *mi_open(const char *name, int mode, uint open_flags)
if (share->rec[i].type == (int) FIELD_BLOB)
{
share->blobs[j].pack_length=
share->rec[i].length-mi_portable_sizeof_char_ptr;;
share->rec[i].length-portable_sizeof_char_ptr;;
share->blobs[j].offset=offset;
j++;
}

View file

@ -1036,7 +1036,7 @@ static void uf_blob(MI_COLUMNDEF *rec, MI_BIT_BUFF *bit_buff,
else
{
ulong length=get_bits(bit_buff,rec->space_length_bits);
uint pack_length=(uint) (end-to)-mi_portable_sizeof_char_ptr;
uint pack_length=(uint) (end-to)-portable_sizeof_char_ptr;
if (bit_buff->blob_pos+length > bit_buff->blob_end)
{
bit_buff->error=1;

View file

@ -83,6 +83,8 @@ int mi_rkey(MI_INFO *info, byte *buf, int inx, const byte *key, uint key_len,
{
mi_print_error(info->s, HA_ERR_CRASHED);
my_errno=HA_ERR_CRASHED;
if (share->concurrent_insert)
rw_unlock(&share->key_root_lock[inx]);
goto err;
}
break;

View file

@ -71,12 +71,12 @@ static int run_test(const char *filename)
/* 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+mi_portable_sizeof_char_ptr :
recinfo[1].length= (key_field == FIELD_BLOB ? 4+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 + mi_portable_sizeof_char_ptr : 24);
recinfo[2].length= (extra_field == FIELD_BLOB ? 4 + portable_sizeof_char_ptr : 24);
if (extra_field == FIELD_VARCHAR)
recinfo[2].length+= HA_VARCHAR_PACKLENGTH(recinfo[2].length);
if (opt_unique)

View file

@ -188,7 +188,7 @@ int main(int argc, char *argv[])
if (use_blob)
{
recinfo[6].type=FIELD_BLOB;
recinfo[6].length=4+mi_portable_sizeof_char_ptr;
recinfo[6].length=4+portable_sizeof_char_ptr;
recinfo[6].null_bit=0;
recinfo[6].null_pos=0;
}

View file

@ -305,7 +305,7 @@ static void usage(void)
puts("and you are welcome to modify and redistribute it under the GPL license\n");
puts("Pack a MyISAM-table to take much less space.");
puts("Keys are not updated, you must run myisamchk -rq on the datafile");
puts("Keys are not updated, you must run myisamchk -rq on the index (.MYI) file");
puts("afterwards to update the keys.");
puts("You should give the .MYI file as the filename argument.");
@ -1008,7 +1008,7 @@ static int get_statistic(PACK_MRG_INFO *mrg,HUFF_COUNTS *huff_counts)
/* Calculate pos, end_pos, and max_length for variable length fields. */
if (count->field_type == FIELD_BLOB)
{
uint field_length=count->field_length -mi_portable_sizeof_char_ptr;
uint field_length=count->field_length -portable_sizeof_char_ptr;
ulong blob_length= _mi_calc_blob_length(field_length, start_pos);
memcpy_fixed((char*) &pos, start_pos+field_length,sizeof(char*));
end_pos=pos+blob_length;
@ -2650,7 +2650,7 @@ static int compress_isam_file(PACK_MRG_INFO *mrg, HUFF_COUNTS *huff_counts)
case FIELD_BLOB:
{
ulong blob_length=_mi_calc_blob_length(field_length-
mi_portable_sizeof_char_ptr,
portable_sizeof_char_ptr,
start_pos);
/* Empty blobs are encoded with a single 1 bit. */
if (!blob_length)
@ -2667,7 +2667,7 @@ static int compress_isam_file(PACK_MRG_INFO *mrg, HUFF_COUNTS *huff_counts)
DBUG_PRINT("fields", ("FIELD_BLOB %lu bytes, bits: %2u",
blob_length, count->length_bits));
write_bits(blob_length,count->length_bits);
memcpy_fixed(&blob,end_pos-mi_portable_sizeof_char_ptr,
memcpy_fixed(&blob,end_pos-portable_sizeof_char_ptr,
sizeof(char*));
blob_end=blob+blob_length;
/* Encode the blob bytes. */

View file

@ -79,7 +79,7 @@ int run_test(const char *filename)
/* Define spatial column */
recinfo[1].type=FIELD_BLOB;
recinfo[1].length=4 + mi_portable_sizeof_char_ptr;
recinfo[1].length=4 + portable_sizeof_char_ptr;

View file

@ -4,9 +4,9 @@
#
0 beshort 0xfe01 MySQL table definition file
>2 byte x Version %d
0 belong&0xffffff00 0xfefe0700 MySQL MISAM index file
0 belong&0xffffff00 0xfefe0700 MySQL MyISAM index file
>3 byte x Version %d
0 belong&0xffffff00 0xfefe0800 MySQL MISAM compressed data file
0 belong&0xffffff00 0xfefe0800 MySQL MyISAM compressed data file
>3 byte x Version %d
0 belong&0xffffff00 0xfefe0900 MySQL Maria index file
>3 byte x Version %d