merge
This commit is contained in:
commit
89ad11ae8f
@ -2314,7 +2314,8 @@ int ha_maria::external_lock(THD *thd, int lock_type)
|
||||
trnman_new_statement(trn);
|
||||
}
|
||||
|
||||
if (file->s->lock.get_status)
|
||||
/* If handler uses versioning */
|
||||
if (file->s->lock_key_trees)
|
||||
{
|
||||
if (_ma_setup_live_state(file))
|
||||
DBUG_RETURN(HA_ERR_OUT_OF_MEM);
|
||||
@ -2513,7 +2514,8 @@ int ha_maria::implicit_commit(THD *thd, bool new_trn)
|
||||
if (handler->s->base.born_transactional)
|
||||
{
|
||||
_ma_set_trn_for_table(handler, trn);
|
||||
if (handler->s->lock.get_status)
|
||||
/* If handler uses versioning */
|
||||
if (handler->s->lock_key_trees)
|
||||
{
|
||||
if (_ma_setup_live_state(handler))
|
||||
error= HA_ERR_OUT_OF_MEM;
|
||||
@ -3074,6 +3076,16 @@ static int mark_recovery_success(void)
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Return 1 if table has changed during the current transaction
|
||||
*/
|
||||
|
||||
bool ha_maria::is_changed() const
|
||||
{
|
||||
return file->state->changed;
|
||||
}
|
||||
|
||||
|
||||
static int ha_maria_init(void *p)
|
||||
{
|
||||
int res;
|
||||
|
@ -139,6 +139,7 @@ public:
|
||||
int repair(THD * thd, HA_CHECK_OPT * check_opt);
|
||||
bool check_and_repair(THD * thd);
|
||||
bool is_crashed() const;
|
||||
bool is_changed() const;
|
||||
bool auto_repair() const { return 1; }
|
||||
int optimize(THD * thd, HA_CHECK_OPT * check_opt);
|
||||
int restore(THD * thd, HA_CHECK_OPT * check_opt);
|
||||
|
@ -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
|
||||
|
@ -116,6 +116,7 @@ int maria_delete(MARIA_HA *info,const uchar *record)
|
||||
info->update= HA_STATE_CHANGED+HA_STATE_DELETED+HA_STATE_ROW_CHANGED;
|
||||
share->state.changed|= (STATE_NOT_OPTIMIZED_ROWS | STATE_NOT_MOVABLE |
|
||||
STATE_NOT_ZEROFILLED);
|
||||
info->state->changed=1;
|
||||
|
||||
mi_sizestore(lastpos, info->cur_row.lastpos);
|
||||
VOID(_ma_writeinfo(info,WRITEINFO_UPDATE_KEYFILE));
|
||||
|
@ -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);
|
||||
|
@ -121,6 +121,8 @@ struct st_translog_buffer
|
||||
in case of flush by LSN it can be offset + size - TRANSLOG_PAGE_SIZE)
|
||||
*/
|
||||
TRANSLOG_ADDRESS next_buffer_offset;
|
||||
/* Previous buffer offset to detect it flush finish */
|
||||
TRANSLOG_ADDRESS prev_buffer_offset;
|
||||
/*
|
||||
How much is written (or will be written when copy_to_buffer_in_progress
|
||||
become 0) to this buffer
|
||||
@ -135,12 +137,12 @@ struct st_translog_buffer
|
||||
/* list of waiting buffer ready threads */
|
||||
struct st_my_thread_var *waiting_flush;
|
||||
/*
|
||||
Pointer on the buffer which overlap with this one (due to flush of
|
||||
If true then previous buffer overlap with this one (due to flush of
|
||||
loghandler, the last page of that buffer is the same as the first page
|
||||
of this buffer) and have to be written first (because contain old
|
||||
content of page which present in both buffers)
|
||||
*/
|
||||
struct st_translog_buffer *overlay;
|
||||
my_bool overlay;
|
||||
uint buffer_no;
|
||||
/*
|
||||
Lock for the buffer.
|
||||
@ -175,6 +177,14 @@ struct st_translog_buffer
|
||||
With file and offset it allow detect buffer changes
|
||||
*/
|
||||
uint8 ver;
|
||||
|
||||
/*
|
||||
When previous buffer sent to disk it set its address here to allow
|
||||
to detect when it is done
|
||||
(we have to keep it in this buffer to lock buffers only in one direction).
|
||||
*/
|
||||
TRANSLOG_ADDRESS prev_sent_to_disk;
|
||||
pthread_cond_t prev_sent_to_disk_cond;
|
||||
};
|
||||
|
||||
|
||||
@ -1421,9 +1431,12 @@ static my_bool translog_buffer_init(struct st_translog_buffer *buffer)
|
||||
/* list of waiting buffer ready threads */
|
||||
buffer->waiting_flush= 0;
|
||||
/* lock for the buffer. Current buffer also lock the handler */
|
||||
if (pthread_mutex_init(&buffer->mutex, MY_MUTEX_INIT_FAST))
|
||||
if (pthread_mutex_init(&buffer->mutex, MY_MUTEX_INIT_FAST) ||
|
||||
pthread_cond_init(&buffer->prev_sent_to_disk_cond, 0))
|
||||
DBUG_RETURN(1);
|
||||
buffer->is_closing_buffer= 0;
|
||||
buffer->prev_sent_to_disk= LSN_IMPOSSIBLE;
|
||||
buffer->prev_buffer_offset= LSN_IMPOSSIBLE;
|
||||
buffer->ver= 0;
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
@ -2100,10 +2113,12 @@ static my_bool translog_buffer_next(TRANSLOG_ADDRESS *horizon,
|
||||
{
|
||||
translog_lock_assert_owner();
|
||||
translog_start_buffer(new_buffer, cursor, new_buffer_no);
|
||||
new_buffer->prev_buffer_offset=
|
||||
log_descriptor.buffers[old_buffer_no].offset;
|
||||
new_buffer->prev_last_lsn=
|
||||
BUFFER_MAX_LSN(log_descriptor.buffers + old_buffer_no);
|
||||
}
|
||||
log_descriptor.buffers[old_buffer_no].next_buffer_offset= new_buffer->offset;
|
||||
new_buffer->prev_last_lsn=
|
||||
BUFFER_MAX_LSN(log_descriptor.buffers + old_buffer_no);
|
||||
DBUG_PRINT("info", ("prev_last_lsn set to (%lu,0x%lx) buffer: 0x%lx",
|
||||
LSN_IN_PARTS(new_buffer->prev_last_lsn),
|
||||
(ulong) new_buffer));
|
||||
@ -2117,14 +2132,16 @@ static my_bool translog_buffer_next(TRANSLOG_ADDRESS *horizon,
|
||||
|
||||
SYNOPSIS
|
||||
translog_set_sent_to_disk()
|
||||
lsn LSN to assign
|
||||
in_buffers to assign to in_buffers_only
|
||||
buffer buffer which we have sent to disk
|
||||
|
||||
TODO: use atomic operations if possible (64bit architectures?)
|
||||
*/
|
||||
|
||||
static void translog_set_sent_to_disk(LSN lsn, TRANSLOG_ADDRESS in_buffers)
|
||||
static void translog_set_sent_to_disk(struct st_translog_buffer *buffer)
|
||||
{
|
||||
LSN lsn= buffer->last_lsn;
|
||||
TRANSLOG_ADDRESS in_buffers= buffer->next_buffer_offset;
|
||||
|
||||
DBUG_ENTER("translog_set_sent_to_disk");
|
||||
pthread_mutex_lock(&log_descriptor.sent_to_disk_lock);
|
||||
DBUG_PRINT("enter", ("lsn: (%lu,0x%lx) in_buffers: (%lu,0x%lx) "
|
||||
@ -2415,6 +2432,51 @@ static uint16 translog_get_total_chunk_length(uchar *page, uint16 offset)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@brief Waits previous buffer flush finish
|
||||
|
||||
@param buffer buffer for check
|
||||
|
||||
@retval 0 previous buffer flushed and this thread have to flush this one
|
||||
@retval 1 previous buffer flushed and this buffer flushed by other thread too
|
||||
*/
|
||||
|
||||
my_bool translog_prev_buffer_flush_wait(struct st_translog_buffer *buffer)
|
||||
{
|
||||
TRANSLOG_ADDRESS offset= buffer->offset;
|
||||
TRANSLOG_FILE *file= buffer->file;
|
||||
uint8 ver= buffer->ver;
|
||||
DBUG_ENTER("translog_prev_buffer_flush_wait");
|
||||
DBUG_PRINT("enter", ("buffer: 0x%lx #%u offset: (%lu,0x%lx) "
|
||||
"prev sent: (%lu,0x%lx) prev offset: (%lu,0x%lx)",
|
||||
(ulong) buffer, (uint) buffer->buffer_no,
|
||||
LSN_IN_PARTS(buffer->offset),
|
||||
LSN_IN_PARTS(buffer->prev_sent_to_disk),
|
||||
LSN_IN_PARTS(buffer->prev_buffer_offset)));
|
||||
translog_buffer_lock_assert_owner(buffer);
|
||||
/*
|
||||
if prev_sent_to_disk == LSN_IMPOSSIBLE then
|
||||
prev_buffer_offset should be LSN_IMPOSSIBLE
|
||||
because it means that this buffer was never used
|
||||
*/
|
||||
DBUG_ASSERT((buffer->prev_sent_to_disk == LSN_IMPOSSIBLE &&
|
||||
buffer->prev_buffer_offset == LSN_IMPOSSIBLE) ||
|
||||
buffer->prev_sent_to_disk != LSN_IMPOSSIBLE);
|
||||
if (buffer->prev_buffer_offset != buffer->prev_sent_to_disk)
|
||||
{
|
||||
do {
|
||||
pthread_cond_wait(&buffer->prev_sent_to_disk_cond, &buffer->mutex);
|
||||
if (buffer->file != file || buffer->offset != offset ||
|
||||
buffer->ver != ver)
|
||||
{
|
||||
translog_buffer_unlock(buffer);
|
||||
DBUG_RETURN(1); /* some the thread flushed the buffer already */
|
||||
}
|
||||
} while(buffer->prev_buffer_offset != buffer->prev_sent_to_disk);
|
||||
}
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Flush given buffer
|
||||
@ -2460,39 +2522,8 @@ static my_bool translog_buffer_flush(struct st_translog_buffer *buffer)
|
||||
if (buffer->file != file || buffer->offset != offset || buffer->ver != ver)
|
||||
DBUG_RETURN(0); /* some the thread flushed the buffer already */
|
||||
|
||||
if (buffer->overlay && buffer->overlay->file == buffer->file &&
|
||||
cmp_translog_addr(buffer->overlay->offset + buffer->overlay->size,
|
||||
buffer->offset) > 0)
|
||||
{
|
||||
/*
|
||||
This can't happen for normal translog_flush,
|
||||
only during destroying the loghandler
|
||||
*/
|
||||
struct st_translog_buffer *overlay= buffer->overlay;
|
||||
TRANSLOG_ADDRESS buffer_offset= buffer->offset;
|
||||
TRANSLOG_FILE *fl= buffer->file;
|
||||
uint8 ver= buffer->ver;
|
||||
translog_buffer_unlock(buffer);
|
||||
translog_buffer_lock(overlay);
|
||||
/* rechecks under mutex protection that overlay is still our overlay */
|
||||
if (buffer->overlay->file == fl &&
|
||||
cmp_translog_addr(buffer->overlay->offset + buffer->overlay->size,
|
||||
buffer_offset) > 0)
|
||||
{
|
||||
translog_wait_for_buffer_free(overlay);
|
||||
}
|
||||
translog_buffer_unlock(overlay);
|
||||
translog_buffer_lock(buffer);
|
||||
if (buffer->file != fl || buffer_offset != buffer->offset ||
|
||||
ver != buffer->ver)
|
||||
{
|
||||
/*
|
||||
This means that somebody else flushed the buffer while we was
|
||||
waiting for overlay then for locking buffer again.
|
||||
*/
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
}
|
||||
if (buffer->overlay && translog_prev_buffer_flush_wait(buffer))
|
||||
DBUG_RETURN(0); /* some the thread flushed the buffer already */
|
||||
|
||||
/*
|
||||
Send page by page in the pagecache what we are going to write on the
|
||||
@ -2553,10 +2584,34 @@ static my_bool translog_buffer_flush(struct st_translog_buffer *buffer)
|
||||
file->is_sync= 0;
|
||||
|
||||
if (LSN_OFFSET(buffer->last_lsn) != 0) /* if buffer->last_lsn is set */
|
||||
translog_set_sent_to_disk(buffer->last_lsn,
|
||||
buffer->next_buffer_offset);
|
||||
{
|
||||
if (translog_prev_buffer_flush_wait(buffer))
|
||||
DBUG_RETURN(0); /* some the thread flushed the buffer already */
|
||||
translog_set_sent_to_disk(buffer);
|
||||
}
|
||||
else
|
||||
translog_set_only_in_buffers(buffer->next_buffer_offset);
|
||||
|
||||
/* say to next buffer that we are finished */
|
||||
{
|
||||
struct st_translog_buffer *next_buffer=
|
||||
log_descriptor.buffers + ((buffer->buffer_no + 1) % TRANSLOG_BUFFERS_NO);
|
||||
if (likely(translog_status == TRANSLOG_OK)){
|
||||
translog_buffer_lock(next_buffer);
|
||||
next_buffer->prev_sent_to_disk= buffer->offset;
|
||||
translog_buffer_unlock(next_buffer);
|
||||
pthread_cond_broadcast(&next_buffer->prev_sent_to_disk_cond);
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
It is shutdown =>
|
||||
1) there is only one thread
|
||||
2) mutexes of other buffers can be destroyed => we can't use them
|
||||
*/
|
||||
next_buffer->prev_sent_to_disk= buffer->offset;
|
||||
}
|
||||
}
|
||||
/* Free buffer */
|
||||
buffer->file= NULL;
|
||||
buffer->overlay= 0;
|
||||
@ -4640,6 +4695,7 @@ static my_bool translog_advance_pointer(int pages, uint16 last_page_data)
|
||||
}
|
||||
translog_start_buffer(new_buffer, &log_descriptor.bc, new_buffer_no);
|
||||
old_buffer->next_buffer_offset= new_buffer->offset;
|
||||
new_buffer->prev_buffer_offset= old_buffer->offset;
|
||||
translog_buffer_unlock(old_buffer);
|
||||
offset-= min_offset;
|
||||
}
|
||||
@ -7355,7 +7411,7 @@ static void translog_force_current_buffer_to_finish()
|
||||
log_descriptor.bc.ptr+= current_page_fill;
|
||||
log_descriptor.bc.buffer->size= log_descriptor.bc.current_page_fill=
|
||||
current_page_fill;
|
||||
new_buffer->overlay= old_buffer;
|
||||
new_buffer->overlay= 1;
|
||||
}
|
||||
else
|
||||
translog_new_page_header(&log_descriptor.horizon, &log_descriptor.bc);
|
||||
@ -7428,8 +7484,8 @@ static void translog_force_current_buffer_to_finish()
|
||||
memcpy(new_buffer->buffer, data, current_page_fill);
|
||||
}
|
||||
old_buffer->next_buffer_offset= new_buffer->offset;
|
||||
|
||||
translog_buffer_lock(new_buffer);
|
||||
new_buffer->prev_buffer_offset= old_buffer->offset;
|
||||
translog_buffer_decrease_writers(new_buffer);
|
||||
translog_buffer_unlock(new_buffer);
|
||||
|
||||
|
@ -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
|
||||
@ -824,6 +824,7 @@ MARIA_HA *maria_open(const char *name, int mode, uint open_flags)
|
||||
VOID(my_rwlock_init(&share->mmap_lock, NULL));
|
||||
|
||||
share->row_is_visible= _ma_row_visible_always;
|
||||
share->lock.get_status= _ma_reset_update_flag;
|
||||
if (!thr_lock_inited)
|
||||
{
|
||||
/* Probably a single threaded program; Don't use concurrent inserts */
|
||||
|
@ -96,6 +96,8 @@ my_bool _ma_setup_live_state(MARIA_HA *info)
|
||||
pthread_mutex_unlock(&share->intern_lock);
|
||||
/* The current item can't be deleted as it's the first one visible for us */
|
||||
tables->state_start= tables->state_current= history->state;
|
||||
tables->state_current.changed= 0;
|
||||
|
||||
DBUG_PRINT("info", ("records: %ld", (ulong) tables->state_start.records));
|
||||
|
||||
end:
|
||||
@ -262,6 +264,7 @@ void _ma_get_status(void* param, my_bool concurrent_insert)
|
||||
#endif
|
||||
info->state_save= info->s->state.state;
|
||||
info->state= &info->state_save;
|
||||
info->state->changed= 0;
|
||||
info->append_insert_at_end= concurrent_insert;
|
||||
DBUG_VOID_RETURN;
|
||||
}
|
||||
@ -315,6 +318,14 @@ void _ma_copy_status(void* to, void *from)
|
||||
}
|
||||
|
||||
|
||||
void _ma_reset_update_flag(void *param,
|
||||
my_bool concurrent_insert __attribute__((unused)))
|
||||
{
|
||||
MARIA_HA *info=(MARIA_HA*) param;
|
||||
info->state->changed= 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
@brief Check if should allow concurrent inserts
|
||||
|
||||
|
@ -24,6 +24,7 @@ typedef struct st_maria_status_info
|
||||
my_off_t key_file_length;
|
||||
my_off_t data_file_length;
|
||||
ha_checksum checksum;
|
||||
my_bool changed;
|
||||
} MARIA_STATUS_INFO;
|
||||
|
||||
|
||||
@ -62,6 +63,7 @@ void _ma_get_status(void* param, my_bool concurrent_insert);
|
||||
void _ma_update_status(void* param);
|
||||
void _ma_restore_status(void *param);
|
||||
void _ma_copy_status(void* to, void *from);
|
||||
void _ma_reset_update_flag(void *param, my_bool concurrent_insert);
|
||||
my_bool _ma_check_status(void *param);
|
||||
void _ma_block_get_status(void* param, my_bool concurrent_insert);
|
||||
void _ma_block_update_status(void *param);
|
||||
|
@ -173,6 +173,7 @@ int maria_update(register MARIA_HA *info, const uchar *oldrec, uchar *newrec)
|
||||
*/
|
||||
info->update= (HA_STATE_CHANGED | HA_STATE_ROW_CHANGED | key_changed);
|
||||
share->state.changed|= STATE_NOT_MOVABLE | STATE_NOT_ZEROFILLED;
|
||||
info->state->changed= 1;
|
||||
|
||||
/*
|
||||
Every Maria function that updates Maria table must end with
|
||||
|
@ -289,6 +289,7 @@ int maria_write(MARIA_HA *info, uchar *record)
|
||||
info->update= (HA_STATE_CHANGED | HA_STATE_AKTIV | HA_STATE_WRITTEN |
|
||||
HA_STATE_ROW_CHANGED);
|
||||
share->state.changed|= STATE_NOT_MOVABLE | STATE_NOT_ZEROFILLED;
|
||||
info->state->changed= 1;
|
||||
|
||||
info->cur_row.lastpos= filepos;
|
||||
VOID(_ma_writeinfo(info, WRITEINFO_UPDATE_KEYFILE));
|
||||
|
@ -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,
|
||||
|
@ -37,6 +37,13 @@ static TRN committed_list_min, committed_list_max;
|
||||
/* a counter, used to generate transaction ids */
|
||||
static TrID global_trid_generator;
|
||||
|
||||
/*
|
||||
The minimum existing transaction id for trnman_get_min_trid()
|
||||
The default value is used when transaction manager not initialize;
|
||||
Probably called from maria_chk
|
||||
*/
|
||||
static TrID trid_min_read_from= ~(TrID) 0;
|
||||
|
||||
/* the mutex for everything above */
|
||||
static pthread_mutex_t LOCK_trn_list;
|
||||
|
||||
@ -158,6 +165,7 @@ int trnman_init(TrID initial_trid)
|
||||
|
||||
pool= 0;
|
||||
global_trid_generator= initial_trid;
|
||||
trid_min_read_from= initial_trid;
|
||||
lf_hash_init(&trid_to_trn, sizeof(TRN*), LF_HASH_UNIQUE,
|
||||
0, 0, trn_get_hash_key, 0);
|
||||
DBUG_PRINT("info", ("pthread_mutex_init LOCK_trn_list"));
|
||||
@ -303,6 +311,7 @@ TRN *trnman_new_trn(WT_THD *wt)
|
||||
if (!trn->pins)
|
||||
{
|
||||
trnman_free_trn(trn);
|
||||
pthread_mutex_unlock(&LOCK_trn_list);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -315,6 +324,7 @@ TRN *trnman_new_trn(WT_THD *wt)
|
||||
trn->next= &active_list_max;
|
||||
trn->prev= active_list_max.prev;
|
||||
active_list_max.prev= trn->prev->next= trn;
|
||||
trid_min_read_from= active_list_min.next->min_read_from;
|
||||
DBUG_PRINT("info", ("pthread_mutex_unlock LOCK_trn_list"));
|
||||
pthread_mutex_unlock(&LOCK_trn_list);
|
||||
|
||||
@ -437,6 +447,8 @@ my_bool trnman_end_trn(TRN *trn, my_bool commit)
|
||||
trn->next= free_me;
|
||||
free_me= trn;
|
||||
}
|
||||
trid_min_read_from= active_list_min.next->min_read_from;
|
||||
|
||||
if ((*trnman_end_trans_hook)(trn, commit,
|
||||
active_list_min.next != &active_list_max))
|
||||
res= -1;
|
||||
@ -787,25 +799,14 @@ TRN *trnman_get_any_trn()
|
||||
|
||||
|
||||
/**
|
||||
Returns the minimum existing transaction id
|
||||
|
||||
@notes
|
||||
This can only be called when we have at least one running transaction.
|
||||
Returns the minimum existing transaction id. May return a too small
|
||||
number in race conditions, but this is ok as the value is used to
|
||||
remove not visible transid from index/rows.
|
||||
*/
|
||||
|
||||
TrID trnman_get_min_trid()
|
||||
{
|
||||
TrID min_read_from;
|
||||
if (short_trid_to_active_trn == NULL)
|
||||
{
|
||||
/* Transaction manager not initialize; Probably called from maria_chk */
|
||||
return ~(TrID) 0;
|
||||
}
|
||||
|
||||
pthread_mutex_lock(&LOCK_trn_list);
|
||||
min_read_from= active_list_min.next->min_read_from;
|
||||
pthread_mutex_unlock(&LOCK_trn_list);
|
||||
return min_read_from;
|
||||
return trid_min_read_from;
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user