diff --git a/storage/maria/ma_control_file.c b/storage/maria/ma_control_file.c index 84fae2a9f7b..1e1fc34c77e 100644 --- a/storage/maria/ma_control_file.c +++ b/storage/maria/ma_control_file.c @@ -185,8 +185,12 @@ static CONTROL_FILE_ERROR create_control_file(const char *name, files around (indeed it could be that the control file alone was deleted or not restored, and we should not go on with life at this point). - TODO: For now we trust (this is alpha version), but for beta if would - be great to verify. + Things should still be relatively safe as if someone tries to use + an old table with a new control file the different uuid:s between + the files will cause ma_open() to generate an HA_ERR_OLD_FILE + error. When used from mysqld this will cause the table to be open + in repair mode which will remove all dependencies between the + table and the old control file. We could have a tool which can rebuild the control file, by reading the directory of logs, finding the newest log, reading it to find last diff --git a/storage/maria/ma_key.c b/storage/maria/ma_key.c index 1fdb3d15f55..729d3cbc6de 100644 --- a/storage/maria/ma_key.c +++ b/storage/maria/ma_key.c @@ -61,7 +61,7 @@ static int _ma_put_key_in_record(MARIA_HA *info,uint keynr,uchar *record); if trid < 256-12 one byte else - one byte prefix (256-length_of_trid_in_bytes) followed by data + one byte prefix length_of_trid_in_bytes + 249 followed by data in high-byte-first order Prefix bytes 244 to 249 are reserved for negative transid, that can be used @@ -69,6 +69,25 @@ static int _ma_put_key_in_record(MARIA_HA *info,uint keynr,uchar *record); We have to store transid in high-byte-first order to be able to do a fast byte-per-byte comparision of them without packing them up. + + For example, assuming we the following data: + + key_data: 1 (4 byte integer) + pointer_to_row: 2 << 8 + 3 = 515 (page 2, row 3) + table_create_transid 1000 Defined at create table time + transid 1010 Transaction that created row + delete_transid 2011 Transaction that deleted row + + In addition we assume the table is created with a data pointer length + of 4 bytes (this is automatically calculated based on the medium + length of rows and the given max number of rows) + + The binary data for the key would then look like this in hex: + + 00 00 00 01 Key data (1 stored high byte first) + 00 00 00 47 (515 << 1) + 1 ; The last 1 is marker that key cont. + 15 ((1000-1010) << 1) + 1 ; The last 1 is marker that key cont. + FB 07 E6 length byte and ((2011 - 1000) << 1) = 07 E6 */ uint transid_store_packed(MARIA_HA *info, uchar *to, ulonglong trid) @@ -76,7 +95,7 @@ uint transid_store_packed(MARIA_HA *info, uchar *to, ulonglong trid) uchar *start; uint length; uchar buff[8]; - DBUG_ASSERT(trid < (LL(1) << (MAX_PACK_TRANSID_SIZE*8))); + DBUG_ASSERT(trid < (LL(1) << (MARIA_MAX_PACK_TRANSID_SIZE*8))); DBUG_ASSERT(trid >= info->s->state.create_trid); trid= (trid - info->s->state.create_trid) << 1; @@ -84,7 +103,7 @@ uint transid_store_packed(MARIA_HA *info, uchar *to, ulonglong trid) /* Mark that key contains transid */ to[-1]|= 1; - if (trid < MIN_TRANSID_PACK_PREFIX) + if (trid < MARIA_MIN_TRANSID_PACK_OFFSET) { to[0]= (uchar) trid; return 1; @@ -100,7 +119,8 @@ uint transid_store_packed(MARIA_HA *info, uchar *to, ulonglong trid) } while (trid); length= (uint) (to - buff); - start[0]= (uchar) (256 - length); /* Store length prefix */ + /* Store length prefix */ + start[0]= (uchar) (length + MARIA_TRANSID_PACK_OFFSET); start++; /* Copy things in high-byte-first order to output buffer */ do @@ -127,12 +147,13 @@ ulonglong transid_get_packed(MARIA_SHARE *share, const uchar *from) ulonglong value; uint length; - if (from[0] < MIN_TRANSID_PACK_PREFIX) + if (from[0] < MARIA_MIN_TRANSID_PACK_OFFSET) value= (ulonglong) from[0]; else { value= 0; - for (length= (uint) (256 - from[0]), value= (ulonglong) from[1], from+=2; + for (length= (uint) (from[0] - MARIA_TRANSID_PACK_OFFSET), + value= (ulonglong) from[1], from+=2; --length ; from++) value= (value << 8) + ((ulonglong) *from); diff --git a/storage/maria/ma_open.c b/storage/maria/ma_open.c index 14f7b656517..992061fcda2 100644 --- a/storage/maria/ma_open.c +++ b/storage/maria/ma_open.c @@ -449,7 +449,7 @@ MARIA_HA *maria_open(const char *name, int mode, uint open_flags) /* Ensure we have space in the key buffer for transaction id's */ if (share->base.born_transactional) share->base.max_key_length= ALIGN_SIZE(share->base.max_key_length + - MAX_PACK_TRANSID_SIZE); + MARIA_MAX_PACK_TRANSID_SIZE); /* If page cache is not initialized, then assume we will create the diff --git a/storage/maria/maria_def.h b/storage/maria/maria_def.h index ace22dd99c2..3d96aea8694 100644 --- a/storage/maria/maria_def.h +++ b/storage/maria/maria_def.h @@ -146,14 +146,15 @@ typedef struct st_maria_state_info #define MARIA_KEYDEF_SIZE (2+ 5*2) #define MARIA_UNIQUEDEF_SIZE (2+1+1) #define HA_KEYSEG_SIZE (6+ 2*2 + 4*2) -#define MARIA_MAX_KEY_BUFF (HA_MAX_KEY_BUFF + MAX_PACK_TRANSID_SIZE) +#define MARIA_MAX_KEY_BUFF (HA_MAX_KEY_BUFF + MARIA_MAX_PACK_TRANSID_SIZE) #define MARIA_COLUMNDEF_SIZE (2*7+1+1+4) #define MARIA_BASE_INFO_SIZE (MY_UUID_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 MAX_PACK_TRANSID_SIZE (TRANSID_SIZE+1) -#define MIN_TRANSID_PACK_PREFIX (256-TRANSID_SIZE*2) -#define MARIA_INDEX_OVERHEAD_SIZE (MAX_PACK_TRANSID_SIZE * 2) +/* Internal management bytes needed to store 2 transid/key on an index page */ +#define MARIA_MAX_PACK_TRANSID_SIZE (TRANSID_SIZE+1) +#define MARIA_TRANSID_PACK_OFFSET (256- TRANSID_SIZE - 1) +#define MARIA_MIN_TRANSID_PACK_OFFSET (MARIA_TRANSID_PACK_OFFSET-TRANSID_SIZE) +#define MARIA_INDEX_OVERHEAD_SIZE (MARIA_MAX_PACK_TRANSID_SIZE * 2) #define MARIA_DELETE_KEY_NR 255 /* keynr for deleted blocks */ /* @@ -941,8 +942,8 @@ extern my_bool _ma_compact_keypage(MARIA_HA *info, MARIA_KEYDEF *keyinfo, extern uint transid_store_packed(MARIA_HA *info, uchar *to, ulonglong trid); extern ulonglong transid_get_packed(MARIA_SHARE *share, const uchar *from); #define transid_packed_length(data) \ - ((data)[0] < MIN_TRANSID_PACK_PREFIX ? 1 : \ - (uint) (257 - (uchar) (data)[0])) + ((data)[0] < MARIA_MIN_TRANSID_PACK_OFFSET ? 1 : \ + (uint) ((uchar) (data)[0]) - (MARIA_TRANSID_PACK_OFFSET - 1)) #define key_has_transid(key) (*(key) & 1) extern MARIA_KEY *_ma_make_key(MARIA_HA *info, MARIA_KEY *int_key, uint keynr,