Hi, Nikita!
Interesting trick.
That was you who proposed it! :D
On Nov 13, Nikita Malyavin wrote:
> revision-id: ad6e7b87107 (mariadb-10.5.2-477-gad6e7b87107)
> parent(s): 85fbd867b4c
> author: Nikita Malyavin
> committer: Nikita Malyavin
> timestamp: 2021-01-27 14:17:39 +1000
> message:
>
> introduce cache flipping
Could you add few lines from the Cache_flip_event_log comment here too
please?
Right, thanks for pointing out.
> diff --git a/sql/log.h b/sql/log.h
> index 74c409e1ac7..1e422ae4524 100644
> --- a/sql/log.h
> +++ b/sql/log.h
> @@ -424,10 +424,9 @@ class Event_log: public MYSQL_LOG
>
> bool open(
> const char *log_name,
> - enum_log_type log_type,
> const char *new_name, ulong next_file_number,
> enum cache_type io_cache_type_arg);
> - IO_CACHE *get_log_file() { return &log_file; }
> + virtual IO_CACHE *get_log_file() { return &log_file; }
>
> int write_description_event(enum_binlog_checksum_alg checksum_alg,
> bool encrypt, bool dont_set_created);
> @@ -435,6 +434,73 @@ class Event_log: public MYSQL_LOG
> bool write_event(Log_event *ev, binlog_cache_data *data, IO_CACHE *file);
> };
>
> +/**
> + A single-reader, multiple-writer non-blocking layer for Event_log.
> + Provides IO_CACHE for writing and IO_CACHE for reading.\
> +
> + Writers use an overrided get_log_file version for their writes, while readers
> + should use flip() to initiate reading.
> + flip() swaps pointers to allow non-blocking reads.
> +
> + Writers can block other writers and a reader with a mutex, but a reader only
> + swaps two pointers under a lock, so it won't block writers.
> +
> + TODO should be unnecessary after MDEV-24676 is done
> + */
> +class Cache_flip_event_log: public Event_log {
> + IO_CACHE alt_buf;
> + IO_CACHE *current, *alt;
> +public:
> +
> + Cache_flip_event_log() : Event_log(), alt_buf{},
> + current(&log_file), alt(&alt_buf) {}
> + bool open(enum cache_type io_cache_type_arg)
> + {
> + log_file.dir= mysql_tmpdir;
> + alt_buf.dir= log_file.dir;
> + bool res= Event_log::open(NULL, NULL, 0, io_cache_type_arg);
> + if (res)
> + return res;
> +
> + name= my_strdup(key_memory_MYSQL_LOG_name, "online-alter-binlog",
> + MYF(MY_WME));
> + if (!name)
> + return false;
> +
> + res= init_io_cache(&alt_buf, -1, LOG_BIN_IO_SIZE, io_cache_type_arg, 0, 0,
> + MYF(MY_WME | MY_NABP | MY_WAIT_IF_FULL)) != 0;
> + return res;
> + }
> +
> + /**
> + Swaps current and alt_log. Can be called only from the reader thread.
> + @return a new IO_CACHE pointer to read from.
> + */
> + IO_CACHE *flip()
> + {
> + IO_CACHE *tmp= current;
> + reinit_io_cache(alt, WRITE_CACHE, 0, 0, 0);
> + mysql_mutex_lock(get_log_lock());
> + reinit_io_cache(current, READ_CACHE, 0, 0, 0);
> + current= alt;
> + mysql_mutex_unlock(get_log_lock());
> + alt= tmp;
> +
> + return alt;
> + }
> +
> + IO_CACHE *get_log_file() override
> + {
> + return current;
may be mysql_mutex_assert_owner(get_log_lock()) ?
Good point! Seems so.
> + }
> +
> + void cleanup()
> + {
> + end_io_cache(&alt_buf);
> + Event_log::cleanup();
> + }
> +};
> +
Regards,
Sergei
VP of MariaDB Server Engineering
and security@mariadb.org