MySQL 8.4.2
Source Code Documentation
Gcs_async_buffer Class Reference

Circular buffer that can be used to asynchronously feed a sink. More...

#include <gcs_logging_system.h>

Public Member Functions

 Gcs_async_buffer (Sink_interface *sink, const int buffer_size=DEFAULT_ASYNC_BUFFERS)
 
 ~Gcs_async_buffer ()
 
enum_gcs_error initialize ()
 Asynchronous circular buffer initialization method. More...
 
enum_gcs_error finalize ()
 Asynchronous circular buffer finalization method. More...
 
const std::string get_information () const
 The purpose of this method is to return information on the associated sink such as its location. More...
 
void consume_events ()
 Consumer thread invokes this method to process log events until it is terminated. More...
 
void produce_events (const char *message, size_t message_size)
 Producer threads invoke this method to log events (i.e. More...
 
void produce_events (const std::string &message)
 Producer threads invoke this method to log events (i.e. More...
 
Gcs_log_eventget_entry ()
 Get a reference to an in-memory buffer where a message content will be written to. More...
 
void notify_entry (Gcs_log_event &buffer_entry)
 Notify that an in-memory buffer was filled in and is ready to be consumed. More...
 
Sink_interfaceget_sink () const
 

Private Member Functions

uint64_t get_index (int64_t index) const
 Get the correct index to an entry according to the buffer size. More...
 
int64_t get_write_index ()
 Get an index entry to an in-memory buffer where a message content will be written to. More...
 
void sleep_consumer () const
 Make the consumer sleep while there is no entry to be consumed. More...
 
void wake_up_consumer () const
 Wake up the consumer thread so that it can write whatever was added to the asynchronous buffer to a sink. More...
 
 Gcs_async_buffer (Gcs_async_buffer &l)
 
Gcs_async_bufferoperator= (const Gcs_async_buffer &l)
 

Private Attributes

std::vector< Gcs_log_eventm_buffer
 Slots where messages will be copied to before a consumer thread writes them to a sink. More...
 
int m_buffer_size
 Number of available slots in the buffer. More...
 
int64_t m_write_index
 Next entry in the buffer where producers will write their messages to. More...
 
int64_t m_read_index
 Next entry in the buffer that will be read by the consumer. More...
 
int64_t m_number_entries
 Number of entries written by producers and not yet consumed. More...
 
bool m_terminated
 Whether the asynchronous circular buffer has been stopped or not. More...
 
bool m_initialized
 Whether the asynchronous circular buffer has been started or not. More...
 
Sink_interfacem_sink
 Sink where the consumer will write messages to. More...
 
My_xp_threadm_consumer
 Consumer thread that is responsible for reading the entries in the circular buffer. More...
 
My_xp_condm_wait_for_events_cond
 Conditional variable that is used by the producer to notify the consumer that it should wake up. More...
 
My_xp_condm_free_buffer_cond
 Conditional variable that is used by the consumer to notify the producer that there are free slots. More...
 
My_xp_mutexm_free_buffer_mutex
 Mutex variable that is used to synchronize access to the circular buffer in particular the m_number_entries, m_write_index and m_terminated shared variables. More...
 

Detailed Description

Circular buffer that can be used to asynchronously feed a sink.

In this, messages are temporarily stored in-memory and asynchronously written to the sink. Using this in-memory intermediate buffer is possible to minimize performance drawbacks associated with the direct access to the sink which is usually the terminal, a file or a remote process.

By default, the circular buffer has DEFAULT_ASYNC_BUFFERS entries and this value can be changed by providing different contructor's parameters. Note that, however, this is not currently exposed to the end-user. If there is no free slot available, the caller thread will be temporarily blocked until it can copy its message into a free slot. Only one thread will read the entries in the circular buffer and write them to a sink.

Concurrent access to the buffer is controlled by using a mutex and atomic variables. If you are tempted to change this, please, measure the performance first before changing anything. We have done so and the bulk of the time is spent in formatting the messages and for that reason a simple circular buffer implementation is enough.

Another alternative would be to format the message within the consumer but this would require to always pass information by value. In order to give users flexibility, we have decided not to do this. Besides, XCOM almost always formats its messages within the context of the caller thread. For those reasons, we kept the current behavior but we might revisit this in the future.

Constructor & Destructor Documentation

◆ Gcs_async_buffer() [1/2]

Gcs_async_buffer::Gcs_async_buffer ( Sink_interface sink,
const int  buffer_size = DEFAULT_ASYNC_BUFFERS 
)
explicit

◆ ~Gcs_async_buffer()

Gcs_async_buffer::~Gcs_async_buffer ( )

◆ Gcs_async_buffer() [2/2]

Gcs_async_buffer::Gcs_async_buffer ( Gcs_async_buffer l)
private

Member Function Documentation

◆ consume_events()

void Gcs_async_buffer::consume_events ( )

Consumer thread invokes this method to process log events until it is terminated.

◆ finalize()

enum_gcs_error Gcs_async_buffer::finalize ( )

Asynchronous circular buffer finalization method.

Return values
GCS_OKin case everything goes well. Any other value of gcs_error in case of error.

◆ get_entry()

Gcs_log_event & Gcs_async_buffer::get_entry ( )

Get a reference to an in-memory buffer where a message content will be written to.

◆ get_index()

uint64_t Gcs_async_buffer::get_index ( int64_t  index) const
inlineprivate

Get the correct index to an entry according to the buffer size.

◆ get_information()

const std::string Gcs_async_buffer::get_information ( ) const

The purpose of this method is to return information on the associated sink such as its location.

In this particular case, it will return the string "asynchronous" along with the information returned by then sink in use.

Calling this method would return "asynchronous::output" if the sink in use was the standard output.

◆ get_sink()

Sink_interface * Gcs_async_buffer::get_sink ( ) const

◆ get_write_index()

int64_t Gcs_async_buffer::get_write_index ( )
private

Get an index entry to an in-memory buffer where a message content will be written to.

◆ initialize()

enum_gcs_error Gcs_async_buffer::initialize ( )

Asynchronous circular buffer initialization method.

Return values
GCS_OKin case everything goes well. Any other value of gcs_error in case of error.

◆ notify_entry()

void Gcs_async_buffer::notify_entry ( Gcs_log_event buffer_entry)

Notify that an in-memory buffer was filled in and is ready to be consumed.

◆ operator=()

Gcs_async_buffer & Gcs_async_buffer::operator= ( const Gcs_async_buffer l)
private

◆ produce_events() [1/2]

void Gcs_async_buffer::produce_events ( const char *  message,
size_t  message_size 
)
inline

Producer threads invoke this method to log events (i.e.

messages).

This method is only provided for the sake of completeness and is currently not used because the message would have to be copied into the circular buffer and usually it is necessary to compose the message first thus incurring an extra copy.

Currently, a producer calls directly the get_entry() and notify_entry() methods directly.

◆ produce_events() [2/2]

void Gcs_async_buffer::produce_events ( const std::string &  message)
inline

Producer threads invoke this method to log events (i.e.

messages).

This method is only provided for the sake of completeness and is currently not used because the message would have to be copied into the circular buffer and usually it is necessary to compose the message first thus incurring an extra copy.

Currently, a producer calls directly the get_entry() and notify_entry() methods directly

◆ sleep_consumer()

void Gcs_async_buffer::sleep_consumer ( ) const
inlineprivate

Make the consumer sleep while there is no entry to be consumed.

◆ wake_up_consumer()

void Gcs_async_buffer::wake_up_consumer ( ) const
inlineprivate

Wake up the consumer thread so that it can write whatever was added to the asynchronous buffer to a sink.

Member Data Documentation

◆ m_buffer

std::vector<Gcs_log_event> Gcs_async_buffer::m_buffer
private

Slots where messages will be copied to before a consumer thread writes them to a sink.

◆ m_buffer_size

int Gcs_async_buffer::m_buffer_size
private

Number of available slots in the buffer.

◆ m_consumer

My_xp_thread* Gcs_async_buffer::m_consumer
private

Consumer thread that is responsible for reading the entries in the circular buffer.

◆ m_free_buffer_cond

My_xp_cond* Gcs_async_buffer::m_free_buffer_cond
private

Conditional variable that is used by the consumer to notify the producer that there are free slots.

◆ m_free_buffer_mutex

My_xp_mutex* Gcs_async_buffer::m_free_buffer_mutex
private

Mutex variable that is used to synchronize access to the circular buffer in particular the m_number_entries, m_write_index and m_terminated shared variables.

◆ m_initialized

bool Gcs_async_buffer::m_initialized
private

Whether the asynchronous circular buffer has been started or not.

◆ m_number_entries

int64_t Gcs_async_buffer::m_number_entries
private

Number of entries written by producers and not yet consumed.

◆ m_read_index

int64_t Gcs_async_buffer::m_read_index
private

Next entry in the buffer that will be read by the consumer.

◆ m_sink

Sink_interface* Gcs_async_buffer::m_sink
private

Sink where the consumer will write messages to.

◆ m_terminated

bool Gcs_async_buffer::m_terminated
private

Whether the asynchronous circular buffer has been stopped or not.

◆ m_wait_for_events_cond

My_xp_cond* Gcs_async_buffer::m_wait_for_events_cond
private

Conditional variable that is used by the producer to notify the consumer that it should wake up.

◆ m_write_index

int64_t Gcs_async_buffer::m_write_index
private

Next entry in the buffer where producers will write their messages to.


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