mirror of
https://github.com/MariaDB/server.git
synced 2025-07-29 05:21:33 +03:00
Galera4
This commit is contained in:
committed by
Sergey Vojtovich
parent
382115b992
commit
36a2a185fe
@ -14,12 +14,15 @@
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */
|
||||
|
||||
#include "mariadb.h"
|
||||
#include "mysql/service_wsrep.h"
|
||||
#include "wsrep_binlog.h"
|
||||
#include "wsrep_priv.h"
|
||||
#include "log.h"
|
||||
#include "log_event.h"
|
||||
#include "wsrep_applier.h"
|
||||
|
||||
#include "transaction.h"
|
||||
|
||||
extern handlerton *binlog_hton;
|
||||
/*
|
||||
Write the contents of a cache to a memory buffer.
|
||||
@ -40,10 +43,10 @@ int wsrep_write_cache_buf(IO_CACHE *cache, uchar **buf, size_t *buf_len)
|
||||
DBUG_RETURN(ER_ERROR_ON_WRITE);
|
||||
}
|
||||
|
||||
uint length = my_b_bytes_in_cache(cache);
|
||||
if (unlikely(0 == length)) length = my_b_fill(cache);
|
||||
uint length= my_b_bytes_in_cache(cache);
|
||||
if (unlikely(0 == length)) length= my_b_fill(cache);
|
||||
|
||||
size_t total_length = 0;
|
||||
size_t total_length= 0;
|
||||
|
||||
if (likely(length > 0)) do
|
||||
{
|
||||
@ -60,7 +63,7 @@ int wsrep_write_cache_buf(IO_CACHE *cache, uchar **buf, size_t *buf_len)
|
||||
wsrep_max_ws_size, total_length);
|
||||
goto error;
|
||||
}
|
||||
uchar* tmp = (uchar *)my_realloc(*buf, total_length,
|
||||
uchar* tmp= (uchar *)my_realloc(*buf, total_length,
|
||||
MYF(MY_ALLOW_ZERO_PTR));
|
||||
if (!tmp)
|
||||
{
|
||||
@ -68,17 +71,17 @@ int wsrep_write_cache_buf(IO_CACHE *cache, uchar **buf, size_t *buf_len)
|
||||
*buf_len, length);
|
||||
goto error;
|
||||
}
|
||||
*buf = tmp;
|
||||
*buf= tmp;
|
||||
|
||||
memcpy(*buf + *buf_len, cache->read_pos, length);
|
||||
*buf_len = total_length;
|
||||
*buf_len= total_length;
|
||||
|
||||
if (cache->file < 0)
|
||||
{
|
||||
cache->read_pos= cache->read_end;
|
||||
break;
|
||||
}
|
||||
} while ((length = my_b_fill(cache)));
|
||||
} while ((length= my_b_fill(cache)));
|
||||
|
||||
if (reinit_io_cache(cache, WRITE_CACHE, saved_pos, 0, 0))
|
||||
{
|
||||
@ -111,130 +114,6 @@ heap_size(size_t length)
|
||||
return (length + HEAP_PAGE_SIZE - 1)/HEAP_PAGE_SIZE*HEAP_PAGE_SIZE;
|
||||
}
|
||||
|
||||
/* append data to writeset */
|
||||
static inline wsrep_status_t
|
||||
wsrep_append_data(wsrep_t* const wsrep,
|
||||
wsrep_ws_handle_t* const ws,
|
||||
const void* const data,
|
||||
size_t const len)
|
||||
{
|
||||
struct wsrep_buf const buff = { data, len };
|
||||
wsrep_status_t const rc(wsrep->append_data(wsrep, ws, &buff, 1,
|
||||
WSREP_DATA_ORDERED, true));
|
||||
DBUG_DUMP("buff", (uchar*) data, len);
|
||||
if (rc != WSREP_OK)
|
||||
{
|
||||
WSREP_WARN("append_data() returned %d", rc);
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
Write the contents of a cache to wsrep provider.
|
||||
|
||||
This function quite the same as MYSQL_BIN_LOG::write_cache(),
|
||||
with the exception that here we write in buffer instead of log file.
|
||||
|
||||
This version reads all of cache into single buffer and then appends to a
|
||||
writeset at once.
|
||||
*/
|
||||
static int wsrep_write_cache_once(wsrep_t* const wsrep,
|
||||
THD* const thd,
|
||||
IO_CACHE* const cache,
|
||||
size_t* const len)
|
||||
{
|
||||
my_off_t const saved_pos(my_b_tell(cache));
|
||||
DBUG_ENTER("wsrep_write_cache_once");
|
||||
|
||||
if (reinit_io_cache(cache, READ_CACHE, 0, 0, 0))
|
||||
{
|
||||
WSREP_ERROR("failed to initialize io-cache");
|
||||
DBUG_RETURN(ER_ERROR_ON_WRITE);
|
||||
}
|
||||
|
||||
int err(WSREP_OK);
|
||||
|
||||
size_t total_length(0);
|
||||
uchar stack_buf[STACK_SIZE]; /* to avoid dynamic allocations for few data*/
|
||||
uchar* heap_buf(NULL);
|
||||
uchar* buf(stack_buf);
|
||||
size_t allocated(sizeof(stack_buf));
|
||||
size_t used(0);
|
||||
|
||||
uint length(my_b_bytes_in_cache(cache));
|
||||
if (unlikely(0 == length)) length = my_b_fill(cache);
|
||||
|
||||
if (likely(length > 0)) do
|
||||
{
|
||||
total_length += length;
|
||||
/*
|
||||
Bail out if buffer grows too large.
|
||||
A temporary fix to avoid allocating indefinitely large buffer,
|
||||
not a real limit on a writeset size which includes other things
|
||||
like header and keys.
|
||||
*/
|
||||
if (unlikely(total_length > wsrep_max_ws_size))
|
||||
{
|
||||
WSREP_WARN("transaction size limit (%lu) exceeded: %zu",
|
||||
wsrep_max_ws_size, total_length);
|
||||
err = WSREP_TRX_SIZE_EXCEEDED;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (total_length > allocated)
|
||||
{
|
||||
size_t const new_size(heap_size(total_length));
|
||||
uchar* tmp = (uchar *)my_realloc(heap_buf, new_size,
|
||||
MYF(MY_ALLOW_ZERO_PTR));
|
||||
if (!tmp)
|
||||
{
|
||||
WSREP_ERROR("could not (re)allocate buffer: %zu + %u",
|
||||
allocated, length);
|
||||
err = WSREP_TRX_SIZE_EXCEEDED;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
heap_buf = tmp;
|
||||
buf = heap_buf;
|
||||
allocated = new_size;
|
||||
|
||||
if (used <= STACK_SIZE && used > 0) // there's data in stack_buf
|
||||
{
|
||||
DBUG_ASSERT(buf == stack_buf);
|
||||
memcpy(heap_buf, stack_buf, used);
|
||||
}
|
||||
}
|
||||
|
||||
memcpy(buf + used, cache->read_pos, length);
|
||||
used = total_length;
|
||||
if (cache->file < 0)
|
||||
{
|
||||
cache->read_pos= cache->read_end;
|
||||
break;
|
||||
}
|
||||
} while ((length = my_b_fill(cache)));
|
||||
|
||||
if (used > 0)
|
||||
err = wsrep_append_data(wsrep, &thd->wsrep_ws_handle, buf, used);
|
||||
|
||||
if (WSREP_OK == err) *len = total_length;
|
||||
|
||||
cleanup:
|
||||
if (reinit_io_cache(cache, WRITE_CACHE, saved_pos, 0, 0))
|
||||
{
|
||||
WSREP_ERROR("failed to reinitialize io-cache");
|
||||
}
|
||||
|
||||
if (unlikely(WSREP_OK != err))
|
||||
{
|
||||
wsrep_dump_rbr_buf_with_header(thd, buf, used);
|
||||
}
|
||||
|
||||
my_free(heap_buf);
|
||||
DBUG_RETURN(err);
|
||||
}
|
||||
|
||||
/*
|
||||
Write the contents of a cache to wsrep provider.
|
||||
|
||||
@ -243,62 +122,58 @@ cleanup:
|
||||
|
||||
This version uses incremental data appending as it reads it from cache.
|
||||
*/
|
||||
static int wsrep_write_cache_inc(wsrep_t* const wsrep,
|
||||
THD* const thd,
|
||||
static int wsrep_write_cache_inc(THD* const thd,
|
||||
IO_CACHE* const cache,
|
||||
size_t* const len)
|
||||
{
|
||||
my_off_t const saved_pos(my_b_tell(cache));
|
||||
DBUG_ENTER("wsrep_write_cache_inc");
|
||||
DBUG_ENTER("wsrep_write_cache_inc");
|
||||
my_off_t const saved_pos(my_b_tell(cache));
|
||||
|
||||
if (reinit_io_cache(cache, READ_CACHE, 0, 0, 0))
|
||||
if (reinit_io_cache(cache, READ_CACHE, thd->wsrep_sr().bytes_certified(), 0, 0))
|
||||
{
|
||||
WSREP_ERROR("failed to initialize io-cache");
|
||||
DBUG_RETURN(1);;
|
||||
}
|
||||
|
||||
int ret= 0;
|
||||
size_t total_length(0);
|
||||
|
||||
uint length(my_b_bytes_in_cache(cache));
|
||||
if (unlikely(0 == length)) length= my_b_fill(cache);
|
||||
|
||||
if (likely(length > 0))
|
||||
{
|
||||
do
|
||||
{
|
||||
WSREP_ERROR("failed to initialize io-cache");
|
||||
DBUG_RETURN(WSREP_TRX_ERROR);
|
||||
}
|
||||
|
||||
int err(WSREP_OK);
|
||||
|
||||
size_t total_length(0);
|
||||
|
||||
uint length(my_b_bytes_in_cache(cache));
|
||||
if (unlikely(0 == length)) length = my_b_fill(cache);
|
||||
|
||||
if (likely(length > 0)) do
|
||||
{
|
||||
total_length += length;
|
||||
/* bail out if buffer grows too large
|
||||
not a real limit on a writeset size which includes other things
|
||||
like header and keys.
|
||||
*/
|
||||
if (unlikely(total_length > wsrep_max_ws_size))
|
||||
{
|
||||
WSREP_WARN("transaction size limit (%lu) exceeded: %zu",
|
||||
wsrep_max_ws_size, total_length);
|
||||
err = WSREP_TRX_SIZE_EXCEEDED;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if(WSREP_OK != (err=wsrep_append_data(wsrep, &thd->wsrep_ws_handle,
|
||||
cache->read_pos, length)))
|
||||
goto cleanup;
|
||||
|
||||
if (cache->file < 0)
|
||||
{
|
||||
cache->read_pos= cache->read_end;
|
||||
break;
|
||||
}
|
||||
} while ((length = my_b_fill(cache)));
|
||||
|
||||
if (WSREP_OK == err) *len = total_length;
|
||||
total_length += length;
|
||||
/* bail out if buffer grows too large
|
||||
not a real limit on a writeset size which includes other things
|
||||
like header and keys.
|
||||
*/
|
||||
if (unlikely(total_length > wsrep_max_ws_size))
|
||||
{
|
||||
WSREP_WARN("transaction size limit (%lu) exceeded: %zu",
|
||||
wsrep_max_ws_size, total_length);
|
||||
ret= 1;
|
||||
goto cleanup;
|
||||
}
|
||||
if (thd->wsrep_cs().append_data(wsrep::const_buffer(cache->read_pos, length)))
|
||||
goto cleanup;
|
||||
cache->read_pos= cache->read_end;
|
||||
} while ((cache->file >= 0) && (length= my_b_fill(cache)));
|
||||
}
|
||||
if (ret == 0)
|
||||
{
|
||||
assert(total_length + thd->wsrep_sr().bytes_certified() == saved_pos);
|
||||
}
|
||||
|
||||
cleanup:
|
||||
if (reinit_io_cache(cache, WRITE_CACHE, saved_pos, 0, 0))
|
||||
{
|
||||
WSREP_ERROR("failed to reinitialize io-cache");
|
||||
}
|
||||
|
||||
DBUG_RETURN(err);
|
||||
*len= total_length;
|
||||
if (reinit_io_cache(cache, WRITE_CACHE, saved_pos, 0, 0))
|
||||
{
|
||||
WSREP_ERROR("failed to reinitialize io-cache");
|
||||
}
|
||||
DBUG_RETURN(ret);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -307,17 +182,11 @@ cleanup:
|
||||
This function quite the same as MYSQL_BIN_LOG::write_cache(),
|
||||
with the exception that here we write in buffer instead of log file.
|
||||
*/
|
||||
int wsrep_write_cache(wsrep_t* const wsrep,
|
||||
THD* const thd,
|
||||
int wsrep_write_cache(THD* const thd,
|
||||
IO_CACHE* const cache,
|
||||
size_t* const len)
|
||||
{
|
||||
if (wsrep_incremental_data_collection) {
|
||||
return wsrep_write_cache_inc(wsrep, thd, cache, len);
|
||||
}
|
||||
else {
|
||||
return wsrep_write_cache_once(wsrep, thd, cache, len);
|
||||
}
|
||||
return wsrep_write_cache_inc(thd, cache, len);
|
||||
}
|
||||
|
||||
void wsrep_dump_rbr_buf(THD *thd, const void* rbr_buf, size_t buf_len)
|
||||
@ -383,80 +252,17 @@ int wsrep_binlog_close_connection(THD* thd)
|
||||
int wsrep_binlog_savepoint_set(THD *thd, void *sv)
|
||||
{
|
||||
if (!wsrep_emulate_bin_log) return 0;
|
||||
int rcode = binlog_hton->savepoint_set(binlog_hton, thd, sv);
|
||||
int rcode= binlog_hton->savepoint_set(binlog_hton, thd, sv);
|
||||
return rcode;
|
||||
}
|
||||
|
||||
int wsrep_binlog_savepoint_rollback(THD *thd, void *sv)
|
||||
{
|
||||
if (!wsrep_emulate_bin_log) return 0;
|
||||
int rcode = binlog_hton->savepoint_rollback(binlog_hton, thd, sv);
|
||||
int rcode= binlog_hton->savepoint_rollback(binlog_hton, thd, sv);
|
||||
return rcode;
|
||||
}
|
||||
|
||||
#if 0
|
||||
void wsrep_dump_rbr_direct(THD* thd, IO_CACHE* cache)
|
||||
{
|
||||
char filename[PATH_MAX]= {0};
|
||||
int len= snprintf(filename, PATH_MAX, "%s/GRA_%lld_%lld.log",
|
||||
wsrep_data_home_dir, (longlong) thd->thread_id,
|
||||
(longlong) wsrep_thd_trx_seqno(thd));
|
||||
size_t bytes_in_cache = 0;
|
||||
// check path
|
||||
if (len >= PATH_MAX)
|
||||
{
|
||||
WSREP_ERROR("RBR dump path too long: %d, skipping dump.", len);
|
||||
return ;
|
||||
}
|
||||
// init cache
|
||||
my_off_t const saved_pos(my_b_tell(cache));
|
||||
if (reinit_io_cache(cache, READ_CACHE, 0, 0, 0))
|
||||
{
|
||||
WSREP_ERROR("failed to initialize io-cache");
|
||||
return ;
|
||||
}
|
||||
// open file
|
||||
FILE* of = fopen(filename, "wb");
|
||||
if (!of)
|
||||
{
|
||||
WSREP_ERROR("Failed to open file '%s': %d (%s)",
|
||||
filename, errno, strerror(errno));
|
||||
goto cleanup;
|
||||
}
|
||||
// ready to write
|
||||
bytes_in_cache= my_b_bytes_in_cache(cache);
|
||||
if (unlikely(bytes_in_cache == 0)) bytes_in_cache = my_b_fill(cache);
|
||||
if (likely(bytes_in_cache > 0)) do
|
||||
{
|
||||
if (my_fwrite(of, cache->read_pos, bytes_in_cache,
|
||||
MYF(MY_WME | MY_NABP)) == (size_t) -1)
|
||||
{
|
||||
WSREP_ERROR("Failed to write file '%s'", filename);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (cache->file < 0)
|
||||
{
|
||||
cache->read_pos= cache->read_end;
|
||||
break;
|
||||
}
|
||||
} while ((bytes_in_cache= my_b_fill(cache)));
|
||||
if (cache->error == -1)
|
||||
{
|
||||
WSREP_ERROR("RBR inconsistent");
|
||||
goto cleanup;
|
||||
}
|
||||
cleanup:
|
||||
// init back
|
||||
if (reinit_io_cache(cache, WRITE_CACHE, saved_pos, 0, 0))
|
||||
{
|
||||
WSREP_ERROR("failed to reinitialize io-cache");
|
||||
}
|
||||
// close file
|
||||
if (of) fclose(of);
|
||||
}
|
||||
#endif
|
||||
|
||||
void thd_binlog_flush_pending_rows_event(THD *thd, bool stmt_end)
|
||||
{
|
||||
thd->binlog_flush_pending_rows_event(stmt_end);
|
||||
@ -544,3 +350,31 @@ cleanup1:
|
||||
DBUG_VOID_RETURN;
|
||||
}
|
||||
|
||||
#include "log_event.h"
|
||||
|
||||
int wsrep_write_skip_event(THD* thd)
|
||||
{
|
||||
DBUG_ENTER("wsrep_write_skip_event");
|
||||
Ignorable_log_event skip_event(thd);
|
||||
int ret= mysql_bin_log.write_event(&skip_event);
|
||||
if (ret)
|
||||
{
|
||||
WSREP_WARN("wsrep_write_skip_event: write to binlog failed: %d", ret);
|
||||
}
|
||||
if (!ret && (ret= trans_commit_stmt(thd)))
|
||||
{
|
||||
WSREP_WARN("wsrep_write_skip_event: statt commit failed");
|
||||
}
|
||||
DBUG_RETURN(ret);
|
||||
}
|
||||
|
||||
int wsrep_write_dummy_event_low(THD *thd, const char *msg)
|
||||
{
|
||||
::abort();
|
||||
return 0;
|
||||
}
|
||||
|
||||
int wsrep_write_dummy_event(THD *orig_thd, const char *msg)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
Reference in New Issue
Block a user