Commit 120b73a0 authored by Monty's avatar Monty

Speed up writing to encrypted binlogs

MDEV-21604

Added "virtual" low level write function encrypt_or_write that is set
to point to either normal or encrypted write functions.

This patch also fixes a possible memory leak if writing to binary log fails.
parent 91ab42a8
......@@ -5444,7 +5444,10 @@ bool MYSQL_BIN_LOG::write_event(Log_event *ev, binlog_cache_data *cache_data,
{
Log_event_writer writer(file, 0, &crypto);
if (crypto.scheme && file == &log_file)
{
writer.ctx= alloca(crypto.ctx_size);
writer.set_encrypted_writer();
}
if (cache_data)
cache_data->add_status(ev->logged_status());
return writer.write(ev);
......@@ -7242,8 +7245,10 @@ int MYSQL_BIN_LOG::write_cache(THD *thd, IO_CACHE *cache)
CacheWriter writer(thd, &log_file, binlog_checksum_options, &crypto);
if (crypto.scheme)
{
writer.ctx= alloca(crypto.ctx_size);
writer.set_encrypted_writer();
}
// while there is just one alg the following must hold:
DBUG_ASSERT(binlog_checksum_options == BINLOG_CHECKSUM_ALG_OFF ||
binlog_checksum_options == BINLOG_CHECKSUM_ALG_CRC32);
......
......@@ -932,6 +932,8 @@ typedef struct st_print_event_info
class Log_event_writer
{
/* Log_event_writer is updated when ctx is set */
int (Log_event_writer::*encrypt_or_write)(const uchar *pos, size_t len);
public:
ulonglong bytes_written;
void *ctx; ///< Encryption context or 0 if no encryption is needed
......@@ -943,10 +945,13 @@ class Log_event_writer
my_off_t pos() { return my_b_safe_tell(file); }
void add_status(enum_logged_status status);
void set_incident();
void set_encrypted_writer()
{ encrypt_or_write= &Log_event_writer::encrypt_and_write; }
Log_event_writer(IO_CACHE *file_arg, binlog_cache_data *cache_data_arg,
Binlog_crypt_data *cr= 0)
: bytes_written(0), ctx(0),
:encrypt_or_write(&Log_event_writer::write_internal),
bytes_written(0), ctx(0),
file(file_arg), cache_data(cache_data_arg), crypto(cr) { }
private:
......
......@@ -798,6 +798,7 @@ my_bool Log_event::need_checksum()
int Log_event_writer::write_internal(const uchar *pos, size_t len)
{
DBUG_ASSERT(!ctx || encrypt_or_write == &Log_event_writer::encrypt_and_write);
if (my_b_safe_write(file, pos, len))
{
DBUG_PRINT("error", ("write to log failed: %d", my_errno));
......@@ -826,35 +827,37 @@ int Log_event_writer::maybe_write_event_len(uchar *pos, size_t len)
int Log_event_writer::encrypt_and_write(const uchar *pos, size_t len)
{
uchar *dst= 0;
size_t dstsize= 0;
uchar *dst;
size_t dstsize;
uint dstlen;
int res; // Safe as res is always set
DBUG_ASSERT(ctx);
if (ctx)
{
dstsize= encryption_encrypted_length((uint)len, ENCRYPTION_KEY_SYSTEM_DATA,
crypto->key_version);
if (!(dst= (uchar*)my_safe_alloca(dstsize)))
return 1;
if (!len)
return 0;
uint dstlen;
if (len == 0)
dstlen= 0;
else if (encryption_ctx_update(ctx, pos, (uint)len, dst, &dstlen))
goto err;
dstsize= encryption_encrypted_length((uint)len, ENCRYPTION_KEY_SYSTEM_DATA,
crypto->key_version);
if (!(dst= (uchar*)my_safe_alloca(dstsize)))
return 1;
if (maybe_write_event_len(dst, dstlen))
return 1;
pos= dst;
len= dstlen;
if (encryption_ctx_update(ctx, pos, (uint)len, dst, &dstlen))
{
res= 1;
goto err;
}
if (write_internal(pos, len))
if (maybe_write_event_len(dst, dstlen))
{
res= 1;
goto err;
}
res= write_internal(dst, dstlen);
my_safe_afree(dst, dstsize);
return 0;
err:
my_safe_afree(dst, dstsize);
return 1;
return res;
}
int Log_event_writer::write_header(uchar *pos, size_t len)
......@@ -890,7 +893,7 @@ int Log_event_writer::write_header(uchar *pos, size_t len)
pos+= 4;
len-= 4;
}
DBUG_RETURN(encrypt_and_write(pos, len));
DBUG_RETURN((this->*encrypt_or_write)(pos, len));
}
int Log_event_writer::write_data(const uchar *pos, size_t len)
......@@ -899,7 +902,7 @@ int Log_event_writer::write_data(const uchar *pos, size_t len)
if (checksum_len)
crc= my_checksum(crc, pos, len);
DBUG_RETURN(encrypt_and_write(pos, len));
DBUG_RETURN((this->*encrypt_or_write)(pos, len));
}
int Log_event_writer::write_footer()
......@@ -909,7 +912,7 @@ int Log_event_writer::write_footer()
{
uchar checksum_buf[BINLOG_CHECKSUM_LEN];
int4store(checksum_buf, crc);
if (encrypt_and_write(checksum_buf, BINLOG_CHECKSUM_LEN))
if ((this->*encrypt_or_write)(checksum_buf, BINLOG_CHECKSUM_LEN))
DBUG_RETURN(ER_ERROR_ON_WRITE);
}
if (ctx)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment