MySQL 9.0.0
Source Code Documentation
binlog::Bgc_ticket_manager Class Reference

Singleton class that manages the grouping of sessions for the Binlog Group Commit (BGC), using a ticketing system. More...

#include <bgc_ticket_manager.h>

Public Types

using queue_value_type = std::uint64_t
 
using queue_type = container::Integrals_lockfree_queue< queue_value_type >
 

Public Member Functions

virtual ~Bgc_ticket_manager ()=default
 Default destructor. More...
 
 Bgc_ticket_manager (Bgc_ticket_manager const &)=delete
 
 Bgc_ticket_manager (Bgc_ticket_manager &&)=delete
 
Bgc_ticket_manageroperator= (Bgc_ticket_manager const &)=delete
 
Bgc_ticket_manageroperator= (Bgc_ticket_manager &&)=delete
 
Bgc_ticket_managercoalesce ()
 Coalesces all tickets into a single ticket and opens new processing and assignment windows. More...
 
binlog::BgcTicket assign_session_to_ticket ()
 Assigns a session to the back ticket. More...
 
queue_value_type add_processed_sessions_to_front_ticket (queue_value_type sessions_to_add, const binlog::BgcTicket &ticket)
 Sets given session count as processed within the front ticket processing window. More...
 
binlog::BgcTicket get_front_ticket () const
 Retrieves the front ticket, for which the processing window is open. More...
 
binlog::BgcTicket get_back_ticket () const
 Retrieves the back ticket, which is open to session assignments. More...
 
binlog::BgcTicket get_coalesced_ticket () const
 Retrieves the coalesced ticket, if any coalesce. More...
 
std::pair< binlog::BgcTicket, binlog::BgcTicketpush_new_ticket (BgcTmOptions options=BgcTmOptions::empty)
 Closes the current back ticket to sesssion assignments, pushes the back ticket assgined sessions counter to the session-count queue, set it to 0 and sets the back ticket pointer to the next value. More...
 
std::pair< binlog::BgcTicket, binlog::BgcTicketpop_front_ticket (BgcTmOptions options=BgcTmOptions::empty)
 Closes the current front ticket processing window, pops the front ticket assigned sessions count from the session-count queue, sets the front ticket processed sessions counter to 0 and sets the front ticket pointer to the next value in lne. More...
 
std::string to_string () const
 Returns the textual representation of this object. More...
 
void to_string (std::ostream &out) const
 Dumps the textual representation of this object into the given output stream. More...
 

Static Public Member Functions

static Bgc_ticket_managerinstance ()
 Retrieves the single instance of the class. More...
 

Static Public Attributes

static constexpr size_t max_concurrent_tickets = 1024
 Maximum allowed number of on-wait tickets and the capacity of the underlying session-count queue. More...
 

Private Member Functions

 Bgc_ticket_manager ()=default
 Default constructor. More...
 

Private Attributes

AtomicBgcTicket m_back_ticket {binlog::BgcTicket::first_ticket_value}
 The pointer to the ticket that is open to assigning more sessions. More...
 
AtomicBgcTicket m_front_ticket {binlog::BgcTicket::first_ticket_value}
 The pointer to the ticket for which the processing window is active. More...
 
AtomicBgcTicket m_coalesced_ticket {0}
 The pointer to the coalesced ticket, 0 means that the coalescing has not been requested yet. More...
 
queue_value_type m_back_ticket_sessions_count {0}
 The number of sessions assigned to the back ticket. More...
 
queue_value_type m_front_ticket_processed_sessions_count {0}
 The number of sessions processed in the front ticket window. More...
 
queue_type m_sessions_per_ticket {max_concurrent_tickets}
 The queue keeping the total sessions assigned to each ticket that is closed to assignments (front + on-wait). More...
 

Friends

std::ostream & operator<< (std::ostream &out, Bgc_ticket_manager const &to_dump)
 Dumps the textual representation of an instance of this class into the given output stream. More...
 

Detailed Description

Singleton class that manages the grouping of sessions for the Binlog Group Commit (BGC), using a ticketing system.

Entities

The envolved abstract entities are:

  • Ticket: represented by a number, it has a processing window within which one may decide the amount of sessions one wish to have processed.
  • Session: the unit for what will be processed within a ticket processing window. Usually, it represent THD sessions reaching the beginning of the binlog group commit but it's just an abstract concept.
  • Front Ticket: the ticket for which the processing window is active.
  • Back Ticket: the ticket that is open to assigning more sessions, it may or may not have it's processing window active.
  • On-wait Tickets: tickets that aren't open to assigning more sessions and haven't, yet, had their processing window activacted.
  • Session-count Queue: a queue keeping the total sessions assigned to each ticket that is closed to assignments (front + on-wait).

Operations

The overall set of available operations are:

  • Request a session to be assigned to a ticket.
  • Initialize a new back ticket, meaning that after such operation any subsequent requests to assign a session to a ticket will assign to the newly created ticket.
  • Mark a given session or a set of sessions as processed within the front ticket window.
  • Close the processing window for the front ticket and activate the processing window for the next ticket in line.

Members

The class variable members are:

  • A pointer to the front ticket.
  • A pointer to the back ticket.
  • A counter for the amount of sessions processed within the front ticket window.
  • A counter for the amount of sessions assigned to the back ticket.
  • A queue that holds the amount of sessions assigned to all the tickets that are closed for assginment (front + on-wait).

There is always an active back ticket and an active front ticket. At instance initialization, both are set to 1 and, in the possibility of the underlying ticket counter variable to wrap around, the first number will still be 1. The maximum value for a ticket is 2^63-1.

Thread-safe and serialization

All operations are thread-safe. The operations of assigning a session to the back ticket (assign_sesssion_to_ticket) and of closing the back ticket to assignments and creating a new one (push_new_ticket) are serialized between them. The operations of adding a session to the front ticket processed sessions count (add_processed_sessions_to_front_ticket) and of closing the front ticket processing window (pop_front_ticket) are serialized between them. Any other type of concurrence between operations is serialized only at the atomic variable level.

Serialization between the above described operations is necessary to keep consistent and in-sync the class member values while changing or checkings the ticket session counters and changing the ticket pointers.

Operations are serialized by using the most significant bit of each of the ticket pointer atomic variables and mark them as in use (set to 1) or not in use (set to 0). The first thread to be able to compare the ticket pointer atomic variable with a value that has the most significant bit unset and exchange it by a value with the most significant bit set (using a CAS) gets the ownership over the pointer operations. This mechanism allows us to atomically compare two distinct values, the ticket value in itself and whether or not it's in use by another thread.

Usage patterns

The API usage may be divided in three common patterns:

  1. Processing-window-wait: assign a session to a ticket, wait for the assigned ticket to get to the front and have an active processing window and add the session to the front ticket processed sessions.
  2. Front-ticket-closing: assign a session to a ticket, wait for the assigned ticket to get to the front, finish the front ticket processing window and notify all waiting threads that a new front ticket processing window is activated.
  3. Back-ticket-closing: close the back ticket to assigments and create a new back ticket.

Processing-window-wait

In this pattern, the back ticket assigned sessions counter is incremented and the back ticket is returned to the API caller. The caller should wait for the returned ticket to be the front ticket, in order to be able to add the session to the front ticket processed sessions counter. The code pattern is something along the lines:

Global shared scope std::mutex ticket_processing_window_mtx; std::condition_variable ticket_processing_window; ... auto &ticket_manager = binlog::Bgc_ticket_manager::instance(); auto this_thread_ticket = ticket_manager.assign_session_to_ticket();

while (this_thread_ticket != ticket_manager.get_front_ticket()) { std::unique_lock lock{ticket_processing_window_mtx}; ticket_processing_window.wait(lock); } ticket_manager.add_processed_sessions_to_front_ticket(1); ...

Front-ticket-closing

In this pattern, the back ticket assigned sessions counter is incremented and the back ticket is returned to the API caller. The caller should wait for the returned ticket to be the front ticket, in order to be able to add the session to the front ticket processed sessions counter. Only then, it is in a position to close the front ticket processing window, start a new front ticket processing window and notify all threads. The code pattern is something along the lines:

Global shared scope std::mutex ticket_processing_window_mtx; std::condition_variable ticket_processing_window; ... auto &ticket_manager = binlog::Bgc_ticket_manager::instance(); auto this_thread_ticket = ticket_manager.assign_session_to_ticket();

while (this_thread_ticket != ticket_manager.get_front_ticket()) { std::this_thread::yield(); } ticket_manager.add_processed_sessions_to_front_ticket(1);

while (std::get<1>(ticket_manager.pop_front_ticket()) == this_thread_ticket) { { std::unique_lock lock{ticket_processing_window_mtx}; ticket_processing_window.notify_all(); } std::this_thread::yield(); } ...

Note that there is a loop associated with pop_front_ticket. This operation only closes the front ticket processing window if the counter for the front ticket assigned sessions equals the counter for the front ticket processed sessions. Since the function returns an std::pair with the front ticket values before and after the operation, one may need to check if the values are different.

When pop_front_ticket returns different before and after values, it means that the front ticket pointer now points to the after value and that the assigned sessions count for the before value was poped from the session-count queue.

Back-ticket-closing

In this pattern, the back ticket assigned sessions count is pushed into the session-count queue, set to 0 and the back ticket pointer is set to the next value. The code pattern is something along the lines:

auto [before_ticket, after_ticket] = ticket_manager.push_new_ticket();

If there is the need to assign a session to the finishing back ticket before it's finished and do it atomically with the finish operation, the following code pattern is also supported:

auto [before_ticket, after_ticket] = ticket_manager.push_new_ticket( binlog::BgcTmOptions::inc_session_count);

The above means that a session was assigned to the before_ticket (added to assigned sessions counter) before such value was pushed to the session-count queue.

See also
unittest/gunit/bgc_ticket_manager-t.cc

Member Typedef Documentation

◆ queue_type

◆ queue_value_type

Constructor & Destructor Documentation

◆ ~Bgc_ticket_manager()

virtual binlog::Bgc_ticket_manager::~Bgc_ticket_manager ( )
virtualdefault

Default destructor.

◆ Bgc_ticket_manager() [1/3]

binlog::Bgc_ticket_manager::Bgc_ticket_manager ( Bgc_ticket_manager const &  )
delete

◆ Bgc_ticket_manager() [2/3]

binlog::Bgc_ticket_manager::Bgc_ticket_manager ( Bgc_ticket_manager &&  )
delete

◆ Bgc_ticket_manager() [3/3]

binlog::Bgc_ticket_manager::Bgc_ticket_manager ( )
privatedefault

Default constructor.

Member Function Documentation

◆ add_processed_sessions_to_front_ticket()

binlog::Bgc_ticket_manager::queue_value_type binlog::Bgc_ticket_manager::add_processed_sessions_to_front_ticket ( queue_value_type  sessions_to_add,
const binlog::BgcTicket ticket 
)

Sets given session count as processed within the front ticket processing window.

It adds the given sessions parameter to the front ticket processed sessions counter.

Parameters
sessions_to_addThe number of sessions to set as processed with the front ticket window.
ticketThe session ticket (used for validations).
Returns
The number of sessions processed in the front ticket window after the operation sucessfully concluded.

◆ assign_session_to_ticket()

binlog::BgcTicket binlog::Bgc_ticket_manager::assign_session_to_ticket ( )

Assigns a session to the back ticket.

It increments the back ticket assigned sessions counter.

Returns
The ticket the session was assigned to.

◆ coalesce()

binlog::Bgc_ticket_manager & binlog::Bgc_ticket_manager::coalesce ( )

Coalesces all tickets into a single ticket and opens new processing and assignment windows.

Returns
The ticket manager instance, for chaining purposes.

◆ get_back_ticket()

binlog::BgcTicket binlog::Bgc_ticket_manager::get_back_ticket ( ) const

Retrieves the back ticket, which is open to session assignments.

Returns
The back ticket.

◆ get_coalesced_ticket()

binlog::BgcTicket binlog::Bgc_ticket_manager::get_coalesced_ticket ( ) const

Retrieves the coalesced ticket, if any coalesce.

Returns
The coalesced ticket, which may be 0 if no coalesce operation has been performed.

◆ get_front_ticket()

binlog::BgcTicket binlog::Bgc_ticket_manager::get_front_ticket ( ) const

Retrieves the front ticket, for which the processing window is open.

Returns
The front ticket.

◆ instance()

binlog::Bgc_ticket_manager & binlog::Bgc_ticket_manager::instance ( )
static

Retrieves the single instance of the class.

Returns
The single instance of the class.

◆ operator=() [1/2]

Bgc_ticket_manager & binlog::Bgc_ticket_manager::operator= ( Bgc_ticket_manager &&  )
delete

◆ operator=() [2/2]

Bgc_ticket_manager & binlog::Bgc_ticket_manager::operator= ( Bgc_ticket_manager const &  )
delete

◆ pop_front_ticket()

std::pair< binlog::BgcTicket, binlog::BgcTicket > binlog::Bgc_ticket_manager::pop_front_ticket ( BgcTmOptions  options = BgcTmOptions::empty)

Closes the current front ticket processing window, pops the front ticket assigned sessions count from the session-count queue, sets the front ticket processed sessions counter to 0 and sets the front ticket pointer to the next value in lne.

If the front ticket processed sessions count doesn't match the front ticket assgined sessions count, this function is a no-op and the returned pair will have matching values.

If the options parameter has the inc_session_count option set, the front ticket processed sessions count is incremented before being compared with the front ticket assigned sessions count.

Parameters
optionsAllowed values are combinations of empty and inc_session_count
Returns
A pair holding the before and after invocation front ticket pointer values.

◆ push_new_ticket()

std::pair< binlog::BgcTicket, binlog::BgcTicket > binlog::Bgc_ticket_manager::push_new_ticket ( BgcTmOptions  options = BgcTmOptions::empty)

Closes the current back ticket to sesssion assignments, pushes the back ticket assgined sessions counter to the session-count queue, set it to 0 and sets the back ticket pointer to the next value.

If the back ticket assigned sessions counter is 0 just before pushing it to the session-count queue and changing the back ticket pointer, none of these two operations will happen and the returned pair will have matching values.

If the options parameter has the inc_session_count option set, the back ticket assigned sessions count is incremented before being pusheed to the session-count queue.

Parameters
optionsAllowed values are combinations of empty and inc_session_count
Returns
A pair holding the before and after invocation back ticket pointer values.

◆ to_string() [1/2]

std::string binlog::Bgc_ticket_manager::to_string ( ) const

Returns the textual representation of this object.

Returns
a string containing the textual representation of this object.

◆ to_string() [2/2]

void binlog::Bgc_ticket_manager::to_string ( std::ostream &  out) const

Dumps the textual representation of this object into the given output stream.

Parameters
outThe stream to dump this object into.

Friends And Related Function Documentation

◆ operator<<

std::ostream & operator<< ( std::ostream &  out,
Bgc_ticket_manager const &  to_dump 
)
friend

Dumps the textual representation of an instance of this class into the given output stream.

Parameters
outThe output stream to dump the instance to.
to_dumpThe class instance to dump to the output stream.
Returns
The output stream to which the instance was dumped to.

Member Data Documentation

◆ m_back_ticket

AtomicBgcTicket binlog::Bgc_ticket_manager::m_back_ticket {binlog::BgcTicket::first_ticket_value}
private

The pointer to the ticket that is open to assigning more sessions.

◆ m_back_ticket_sessions_count

queue_value_type binlog::Bgc_ticket_manager::m_back_ticket_sessions_count {0}
private

The number of sessions assigned to the back ticket.

◆ m_coalesced_ticket

AtomicBgcTicket binlog::Bgc_ticket_manager::m_coalesced_ticket {0}
private

The pointer to the coalesced ticket, 0 means that the coalescing has not been requested yet.

◆ m_front_ticket

AtomicBgcTicket binlog::Bgc_ticket_manager::m_front_ticket {binlog::BgcTicket::first_ticket_value}
private

The pointer to the ticket for which the processing window is active.

◆ m_front_ticket_processed_sessions_count

queue_value_type binlog::Bgc_ticket_manager::m_front_ticket_processed_sessions_count {0}
private

The number of sessions processed in the front ticket window.

◆ m_sessions_per_ticket

queue_type binlog::Bgc_ticket_manager::m_sessions_per_ticket {max_concurrent_tickets}
private

The queue keeping the total sessions assigned to each ticket that is closed to assignments (front + on-wait).

◆ max_concurrent_tickets

constexpr size_t binlog::Bgc_ticket_manager::max_concurrent_tickets = 1024
staticconstexpr

Maximum allowed number of on-wait tickets and the capacity of the underlying session-count queue.


The documentation for this class was generated from the following files: