From b5598d8d5337e4b472e3221eda669a7debed5e8a Mon Sep 17 00:00:00 2001 From: Rene Cannao Date: Fri, 9 Jan 2026 07:08:11 +0000 Subject: [PATCH] Add comprehensive ProxySQL_Poll usage documentation throughout codebase Enhance ProxySQL_Poll class documentation with detailed usage patterns: - lib/ProxySQL_Poll.cpp: Enhanced file-level documentation with architecture overview, template specialization, memory management, and event processing pipeline explanations - lib/MySQL_Thread.cpp: Added usage documentation for listener registration, removal patterns, client session setup, and main poll loop - lib/PgSQL_Thread.cpp: Added equivalent PostgreSQL usage documentation mirroring MySQL patterns with protocol-specific details - lib/mysql_data_stream.cpp: Documented cleanup, receive activity tracking, and send activity tracking patterns - lib/PgSQL_Data_Stream.cpp: Documented equivalent PostgreSQL data stream patterns for cleanup and activity tracking All documentation is placed directly where code is used, avoiding specific line numbers for better maintainability. Includes comprehensive explanations of when, why, and how ProxySQL_Poll methods are used throughout ProxySQL's event-driven architecture. [skip-ci] --- lib/MySQL_Thread.cpp | 93 +++++++++++++++++++++++ lib/PgSQL_Data_Stream.cpp | 57 ++++++++++++++ lib/PgSQL_Thread.cpp | 77 ++++++++++++++++++- lib/ProxySQL_Poll.cpp | 153 +++++++++++++++++++++++++++++++------- lib/mysql_data_stream.cpp | 57 ++++++++++++++ 5 files changed, 410 insertions(+), 27 deletions(-) diff --git a/lib/MySQL_Thread.cpp b/lib/MySQL_Thread.cpp index f8191ba9e..745273d44 100644 --- a/lib/MySQL_Thread.cpp +++ b/lib/MySQL_Thread.cpp @@ -3009,10 +3009,46 @@ void MySQL_Thread::poll_listener_add(int sock) { listener_DS->fd=sock; proxy_debug(PROXY_DEBUG_NET,1,"Created listener %p for socket %d\n", listener_DS, sock); + + /** + * @brief Register listener socket with ProxySQL_Poll for incoming connections + * + * This usage pattern registers a listener socket file descriptor with the ProxySQL_Poll instance + * to monitor for incoming client connections. The listener data stream handles the accept() + * operation when connection events are detected. + * + * Usage pattern: mypolls.add(POLLIN, sock, listener_DS, monotonic_time()) + * - POLLIN: Monitor for read events (new connections ready to accept) + * - sock: Listener socket file descriptor + * - listener_DS: Data stream associated with the listener (accepts connections) + * - monotonic_time(): Current timestamp for tracking socket registration time + * + * Called during: Listener setup and initialization + * Purpose: Enables the thread to accept incoming MySQL client connections + */ mypolls.add(POLLIN, sock, listener_DS, monotonic_time()); } void MySQL_Thread::poll_listener_del(int sock) { + /** + * @brief Remove listener socket from the poll set using efficient index lookup + * + * This usage pattern demonstrates the complete removal workflow for listener sockets: + * 1. Find the index of the socket in the poll set using find_index() + * 2. Remove the socket using remove_index_fast() with the found index + * + * Usage pattern: + * int i = mypollolls.find_index(sock); // Find index by file descriptor + * if (i>=0) { + * mypolls.remove_index_fast(i); // Remove by index (O(1) operation) + * } + * + * find_index(sock): Returns index of socket or -1 if not found + * remove_index_fast(i): Removes the entry at index i efficiently + * + * Called during: Listener shutdown and cleanup + * Purpose: Properly removes listener sockets from polling to prevent memory leaks + */ int i=mypolls.find_index(sock); if (i>=0) { MySQL_Data_Stream *myds=mypolls.myds[i]; @@ -3288,6 +3324,26 @@ __run_skip_1: //this is the only portion of code not protected by a global mutex proxy_debug(PROXY_DEBUG_NET,5,"Calling poll with timeout %d\n", ttw ); // poll is called with a timeout of mypolls.poll_timeout if set , or mysql_thread___poll_timeout + /** + * @brief Execute main poll() loop to monitor all registered FDs + * + * This usage pattern demonstrates the core polling mechanism that drives ProxySQL's event loop. + * The poll() system call blocks until one of the registered file descriptors becomes ready + * or the timeout expires. + * + * Usage pattern: rc = poll(mypolls.fds, mypolls.len, ttw) + * - mypollolls.fds: Array of pollfd structures containing file descriptors and events + * - mypolls.len: Number of file descriptors to monitor + * - ttw: Timeout in milliseconds (mydynamic poll timeout) + * + * Return codes: + * - > 0: Number of file descriptors with events + * - 0: Timeout occurred + * - -1: Error (errno set) + * + * Called during: Main event loop iteration + * Purpose: Enables efficient I/O multiplexing across all connections + */ rc=poll(mypolls.fds,mypolls.len, ttw); proxy_debug(PROXY_DEBUG_NET,5,"%s\n", "Returning poll"); #ifdef IDLE_THREADS @@ -3594,6 +3650,23 @@ void MySQL_Thread::worker_thread_gets_sessions_from_idle_thread() { MySQL_Session *mysess=(MySQL_Session *)myexchange.resume_mysql_sessions->remove_index_fast(0); register_session(this, mysess, false); MySQL_Data_Stream *myds=mysess->client_myds; + + /** + * @brief Add client session to poll set for resumed connections + * + * This usage pattern registers a client data stream for resumed connections + * during session restoration in IDLE_THREADS mode. + * + * Usage pattern: mypolls.add(POLLIN, myds->fd, myds, monotonic_time()) + * - POLLIN: Monitor for read events (client data available) + * - myds->fd: Client socket file descriptor + * - myds: MySQL_Data_Stream instance for the client session + * - monotonic_time(): Current timestamp for tracking session registration time + * + * Called during: Session restoration in IDLE_THREADS mode + * Purpose: Enables the thread to receive and process client MySQL protocol data + * for resumed sessions + */ mypolls.add(POLLIN, myds->fd, myds, monotonic_time()); } } @@ -4510,6 +4583,26 @@ void MySQL_Thread::listener_handle_new_connection(MySQL_Data_Stream *myds, unsig } sess->client_myds->myprot.generate_pkt_initial_handshake(true,NULL,NULL, &sess->thread_session_id, true); ioctl_FIONBIO(sess->client_myds->fd, 1); + + /** + * @brief Add client socket to poll set with both read and write monitoring + * + * This usage pattern registers a client socket with both POLLIN and POLLOUT events, + * which is typically done during initial client setup when we need to send the + * initial handshake packet and also be ready to receive client responses. + * + * Usage pattern: mypolls.add(POLLIN|POLLOUT, sess->client_myds->fd, sess->client_myds, curtime) + * - POLLIN|POLLOUT: Monitor both read and write events + * - sess->client_myds->fd: Client socket file descriptor + * - sess->client_myds: MySQL_Data_Stream instance for the client + * - curtime: Current timestamp for tracking + * + * Called during: Initial client connection setup after handshake packet generation + * Purpose: Enables bidirectional communication with the client during setup phase + * + * Note: This ensures we can send the initial handshake immediately and also handle + * any client packets that might arrive before the handshake is complete. + */ mypolls.add(POLLIN|POLLOUT, sess->client_myds->fd, sess->client_myds, curtime); proxy_debug(PROXY_DEBUG_NET,1,"Session=%p -- Adding client FD %d\n", sess, sess->client_myds->fd); diff --git a/lib/PgSQL_Data_Stream.cpp b/lib/PgSQL_Data_Stream.cpp index 9a7a0c0a0..ff326f2c7 100644 --- a/lib/PgSQL_Data_Stream.cpp +++ b/lib/PgSQL_Data_Stream.cpp @@ -321,6 +321,24 @@ PgSQL_Data_Stream::~PgSQL_Data_Stream() { delete PSarrayOUT; } + /** + * @brief Remove PostgreSQL data stream from poll set during destruction + * + * This usage pattern demonstrates how ProxySQL_Poll is used during PgSQL_Data_Stream cleanup: + * - Removes the data stream entry from the poll set to prevent polling on closed socket + * - Uses the stored poll_fds_idx for efficient removal (O(1) operation) + * - Called only if mypolls is not NULL (data stream is registered with a poll instance) + * + * Usage pattern: if (mypolls) mypolls->remove_index_fast(poll_fds_idx) + * - mypolls: Check if data stream is registered with a poll instance + * - remove_index_fast(poll_fds_idx): Remove by stored index from data stream + * + * Called during: PgSQL_Data_Stream destructor + * Purpose: Prevent memory leaks and ensure proper cleanup of poll entries + * + * Note: Each data stream maintains its poll_fds_idx to track its position in the poll array + * for efficient removal without requiring find_index() lookup. + */ if (mypolls) mypolls->remove_index_fast(poll_fds_idx); if (fd > 0) { @@ -652,6 +670,26 @@ int PgSQL_Data_Stream::read_from_net() { else { queue_w(queueIN, r); bytes_info.bytes_recv += r; + + /** + * @brief Update receive timestamp in ProxySQL_Poll for PostgreSQL activity tracking + * + * This usage pattern demonstrates how ProxySQL_Poll is used for PostgreSQL activity monitoring: + * - Updates the last receive timestamp in the poll entry for timeout management + * - Called after successful data reception to track connection activity + * - Uses the stored poll_fds_idx for direct array access (O(1) operation) + * + * Usage pattern: if (mypolls) mypolls->last_recv[poll_fds_idx] = sess->thread->curtime + * - mypolls: Check if data stream is registered with a poll instance + * - last_recv[poll_fds_idx]: Update the receive timestamp for this data stream + * - sess->thread->curtime: Current timestamp from the thread + * + * Called during: After receiving data on the PostgreSQL data stream + * Purpose: Enable timeout management and connection activity monitoring + * + * Note: This timestamp is used by the idle connection timeout system to detect + * inactive PostgreSQL connections that should be closed. + */ if (mypolls) mypolls->last_recv[poll_fds_idx] = sess->thread->curtime; } return r; @@ -759,6 +797,25 @@ int PgSQL_Data_Stream::write_to_net() { } else { queue_r(queueOUT, bytes_io); + /** + * @brief Update send timestamp in ProxySQL_Poll for PostgreSQL activity tracking + * + * This usage pattern demonstrates how ProxySQL_Poll is used for PostgreSQL activity monitoring: + * - Updates the last send timestamp in the poll entry for timeout management + * - Called after successful data transmission to track connection activity + * - Uses the stored poll_fds_idx for direct array access (O(1) operation) + * + * Usage pattern: if (mypolls) mypolls->last_sent[poll_fds_idx] = sess->thread->curtime + * - mypolls: Check if data stream is registered with a poll instance + * - last_sent[poll_fds_idx]: Update the send timestamp for this data stream + * - sess->thread->curtime: Current timestamp from the thread + * + * Called during: After sending data on the PostgreSQL data stream + * Purpose: Enable timeout management and connection activity monitoring + * + * Note: This timestamp is used by the idle connection timeout system to detect + * inactive PostgreSQL connections that should be closed. + */ if (mypolls) mypolls->last_sent[poll_fds_idx] = sess->thread->curtime; bytes_info.bytes_sent += bytes_io; } diff --git a/lib/PgSQL_Thread.cpp b/lib/PgSQL_Thread.cpp index 94c8494cc..dbf42d8b8 100644 --- a/lib/PgSQL_Thread.cpp +++ b/lib/PgSQL_Thread.cpp @@ -2782,10 +2782,46 @@ void PgSQL_Thread::poll_listener_add(int sock) { listener_DS->fd = sock; proxy_debug(PROXY_DEBUG_NET, 1, "Created listener %p for socket %d\n", listener_DS, sock); + + /** + * @brief Register PostgreSQL listener socket with ProxySQL_Poll for incoming connections + * + * This usage pattern registers a PostgreSQL listener socket file descriptor with the ProxySQL_Poll instance + * to monitor for incoming PostgreSQL client connections. The listener data stream handles the accept() + * operation when connection events are detected. + * + * Usage pattern: mypolls.add(POLLIN, sock, listener_DS, monotonic_time()) + * - POLLIN: Monitor for read events (new connections ready to accept) + * - sock: Listener socket file descriptor + * - listener_DS: Data stream associated with the listener (accepts connections) + * - monotonic_time(): Current timestamp for tracking socket registration time + * + * Called during: PostgreSQL listener setup and initialization + * Purpose: Enables the thread to accept incoming PostgreSQL client connections + */ mypolls.add(POLLIN, sock, listener_DS, monotonic_time()); } void PgSQL_Thread::poll_listener_del(int sock) { + /** + * @brief Remove PostgreSQL listener socket from the poll set using efficient index lookup + * + * This usage pattern demonstrates the complete removal workflow for PostgreSQL listener sockets: + * 1. Find the index of the socket in the poll set using find_index() + * 2. Remove the socket using remove_index_fast() with the found index + * + * Usage pattern: + * int i = mypolls.find_index(sock); // Find index by file descriptor + * if (i>=0) { + * mypolls.remove_index_fast(i); // Remove by index (O(1) operation) + * } + * + * find_index(sock): Returns index of socket or -1 if not found + * remove_index_fast(i): Removes the entry at index i efficiently + * + * Called during: PostgreSQL listener shutdown and cleanup + * Purpose: Properly removes listener sockets from polling to prevent memory leaks + */ int i = mypolls.find_index(sock); if (i >= 0) { PgSQL_Data_Stream* myds = mypolls.myds[i]; @@ -2961,7 +2997,27 @@ void PgSQL_Thread::run() { #endif // IDLE_THREADS //this is the only portion of code not protected by a global mutex proxy_debug(PROXY_DEBUG_NET, 5, "Calling poll with timeout %d\n", ttw); - // poll is called with a timeout of mypolls.poll_timeout if set , or pgsql_thread___poll_timeout + /** + * @brief Execute main poll() loop to monitor all registered FDs for PostgreSQL thread + * + * This usage pattern demonstrates the core polling mechanism that drives ProxySQL's PostgreSQL event loop. + * The poll() system call blocks until one of the registered file descriptors becomes ready + * or the timeout expires. + * + * Usage pattern: rc = poll(mypolls.fds, mypolls.len, ttw) + * - mypollolls.fds: Array of pollfd structures containing file descriptors and events + * - mypolls.len: Number of file descriptors to monitor + * - ttw: Timeout in milliseconds (dynamic poll timeout) + * + * Return codes: + * - > 0: Number of file descriptors with events + * - 0: Timeout occurred + * - -1: Error (errno set) + * + * Called during: Main PostgreSQL event loop iteration + * Purpose: Enables efficient I/O multiplexing across all PostgreSQL connections + */ + // poll is called with a timeout of mypolls.poll_timeout if set , or pgsql_thread___poll_timeout rc = poll(mypolls.fds, mypolls.len, ttw); proxy_debug(PROXY_DEBUG_NET, 5, "%s\n", "Returning poll"); #ifdef IDLE_THREADS @@ -4065,6 +4121,25 @@ void PgSQL_Thread::listener_handle_new_connection(PgSQL_Data_Stream * myds, unsi sess->status = CONNECTING_CLIENT; ioctl_FIONBIO(sess->client_myds->fd, 1); + /** + * @brief Add PostgreSQL client socket to poll set with both read and write monitoring + * + * This usage pattern registers a PostgreSQL client socket with both POLLIN and POLLOUT events, + * which is typically done during initial client setup when we need to establish the connection + * and also be ready to receive client responses. + * + * Usage pattern: mypolls.add(POLLIN|POLLOUT, sess->client_myds->fd, sess->client_myds, curtime) + * - POLLIN|POLLOUT: Monitor both read and write events + * - sess->client_myds->fd: Client socket file descriptor + * - sess->client_myds: PgSQL_Data_Stream instance for the client + * - curtime: Current timestamp for tracking + * + * Called during: Initial PostgreSQL client connection setup + * Purpose: Enables bidirectional communication with the client during setup phase + * + * Note: This ensures we can establish the connection immediately and also handle + * any client packets that might arrive during the connection process. + */ mypolls.add(POLLIN | POLLOUT, sess->client_myds->fd, sess->client_myds, curtime); proxy_debug(PROXY_DEBUG_NET, 1, "Session=%p -- Adding client FD %d\n", sess, sess->client_myds->fd); diff --git a/lib/ProxySQL_Poll.cpp b/lib/ProxySQL_Poll.cpp index 637a28879..aadb91cea 100644 --- a/lib/ProxySQL_Poll.cpp +++ b/lib/ProxySQL_Poll.cpp @@ -12,17 +12,80 @@ /** * @file ProxySQL_Poll.cpp * - * These functions provide functionality for managing file descriptors (FDs) and associated data streams in the ProxySQL_Poll class. - * They handle memory allocation, addition, removal, and searching of FDs within the poll object. - * Additionally, they ensure that memory is managed efficiently by dynamically resizing the internal arrays as needed. -*/ + * @brief Core I/O Multiplexing Engine for ProxySQL's Event-Driven Architecture + * + * The ProxySQL_Poll class is the heart of ProxySQL's event-driven I/O system, managing file descriptors + * and their associated data streams using the poll() system call. It serves as the central mechanism + * for handling thousands of concurrent connections efficiently. + * + * @section Architecture Integration + * + * ProxySQL_Poll is integrated throughout the ProxySQL codebase as follows: + * + * - **Thread Classes**: Each MySQL_Thread and PgSQL_Thread contains a ProxySQL_Poll instance + * - **Data Stream Classes**: MySQL_Data_Stream and PgSQL_Data_Stream maintain pointers to their poll instance + * - **Main Event Loop**: Forms the core of the poll() loop in both thread types + * + * @section Template Specialization + * + * ProxySQL_Poll is templated to work with different data stream types: + * - ProxySQL_Poll for MySQL protocol connections + * - ProxySQL_Poll for PostgreSQL protocol connections + * + * @section Memory Management + * + * The class implements sophisticated memory management: + * - Initial allocation: MIN_POLL_LEN (32) FDs + * - Dynamic expansion: Uses l_near_pow_2() for power-of-2 sizing + * - Automatic shrinking: When FD count drops below threshold + * - Efficient cleanup: Proper deallocation in destructor + * + * @section Event Processing Pipeline + * + * ProxySQL_Poll integrates into the event processing pipeline: + * 1. Before Poll: ProcessAllMyDS_BeforePoll() - set up poll events, handle timeouts + * 2. Poll Execution: poll() system call with dynamic timeout + * 3. After Poll: ProcessAllMyDS_AfterPoll() - process events, handle new connections + * + * @section Key Features + * + * - **Scalability**: Efficiently handles thousands of concurrent connections + * - **Event-Driven**: Non-blocking I/O for high performance + * - **Bidirectional Integration**: Data streams maintain poll array indices + * - **Memory Efficiency**: Dynamic resizing optimizes memory usage + * - **Thread Safety**: Each thread maintains its own poll instance + * + * @section Integration with Data Streams + * + * Each data stream maintains critical integration fields: + * - `mypolls`: Pointer to parent ProxySQL_Poll instance + * - `poll_fds_idx`: Index in poll array for quick lookup + * - `last_recv/sent`: Timestamps managed by poll system + * + * This tight integration enables ProxySQL to achieve high performance by minimizing + * lookup overhead and maintaining efficient event-driven processing across all connections. + * + * For usage patterns and examples, see the documentation in: + * - MySQL_Thread.cpp + * - PgSQL_Thread.cpp + * - MySQL_Data_Stream.cpp + * - PgSQL_Data_Stream.cpp + * + * @see MySQL_Thread + * @see PgSQL_Thread + * @see MySQL_Data_Stream + * @see PgSQL_Data_Stream + */ /** * @brief Shrinks the ProxySQL_Poll object by reallocating memory to fit the current number of elements. - * + * * This function reduces the size of the ProxySQL_Poll object by reallocating memory to fit the current number of elements. * It adjusts the size of internal arrays to a size that is a power of two near the current number of elements. + * + * @note Called automatically when FD count drops below MIN_POLL_DELETE_RATIO threshold + * (see lib/ProxySQL_Poll.cpp:166 in remove_index_fast()) */ template void ProxySQL_Poll::shrink() { @@ -36,10 +99,13 @@ void ProxySQL_Poll::shrink() { /** * @brief Expands the ProxySQL_Poll object to accommodate additional elements. - * + * * This function expands the ProxySQL_Poll object to accommodate the specified number of additional elements. * If the resulting size after expansion exceeds the current size, it reallocates memory to fit the expanded size. - * + * + * @note Called automatically in add() method when current capacity is exhausted + * (see lib/ProxySQL_Poll.cpp:114 in add()) + * * @param more The number of additional elements to accommodate. */ template @@ -98,15 +164,27 @@ ProxySQL_Poll::~ProxySQL_Poll() { } /** - * @brief Adds a new file descriptor (FD) and its associated MySQL_Data_Stream to the ProxySQL_Poll object. - * - * This function adds a new file descriptor (FD) along with its associated MySQL_Data_Stream and relevant metadata + * @brief Adds a new file descriptor (FD) and its associated data stream to the ProxySQL_Poll object. + * + * This function adds a new file descriptor (FD) along with its associated data stream and relevant metadata * to the ProxySQL_Poll object. It automatically expands the internal arrays if needed. - * - * @param _events The events to monitor for the FD. - * @param _fd The file descriptor (FD) to add. - * @param _myds The MySQL_Data_Stream associated with the FD. - * @param sent_time The time when data was last sent on the FD. + * + * @section Integration + * - Sets up bidirectional relationship: data stream -> poll instance via myds[i]->mypolls=this + * - Sets up index tracking: data stream -> poll array index via myds[i]->poll_fds_idx=i + * - Initializes timestamps for connection timeout management + * + * @section Usage Patterns + * Called during: + * - New client connections (MySQL_Thread.cpp:4518) + * - New server connections (MySQL_Thread.cpp:3600) + * - Listener socket registration (MySQL_Thread.cpp:3015) + * - PostgreSQL session establishment (PgSQL_Session.cpp:1094) + * + * @param _events The events to monitor for the FD (POLLIN, POLLOUT, POLLIN|POLLOUT) + * @param _fd The file descriptor (FD) to add + * @param _myds The data stream object associated with the FD + * @param sent_time The timestamp when data was last sent on the FD */ template void ProxySQL_Poll::add(uint32_t _events, int _fd, T *_myds, unsigned long long sent_time) { @@ -142,12 +220,24 @@ void ProxySQL_Poll::update_fd_at_index(unsigned int idx, int _fd) { } /** - * @brief Removes a file descriptor (FD) and its associated MySQL_Data_Stream from the ProxySQL_Poll object. - * - * This function removes a file descriptor (FD) along with its associated MySQL_Data_Stream from the ProxySQL_Poll object. - * It also adjusts internal arrays and may shrink the ProxySQL_Poll object if necessary. - * - * @param i The index of the file descriptor (FD) to remove. + * @brief Removes a file descriptor (FD) and its associated data stream from the ProxySQL_Poll object. + * + * This function removes a file descriptor (FD) along with its associated data stream from the ProxySQL_Poll object. + * It uses a swap-and-pop technique for efficient removal and may shrink the object if necessary. + * + * @section Removal Algorithm + * 1. Sets data stream's poll_fds_idx to -1 to prevent double-free + * 2. If not last element, swaps with last element (O(1) removal) + * 3. Updates swapped element's poll_fds_idx to new position + * 4. Decrement length and potentially shrink arrays + * + * @section Usage Patterns + * Called during: + * - Data stream destruction (MySQL_Data_Stream.cpp:337, PgSQL_Data_Stream.cpp:1114) + * - Thread cleanup operations (MySQL_Thread.cpp:3451) + * - Connection termination and cleanup + * + * @param i The index of the file descriptor (FD) to remove */ template void ProxySQL_Poll::remove_index_fast(unsigned int i) { @@ -170,12 +260,23 @@ void ProxySQL_Poll::remove_index_fast(unsigned int i) { /** * @brief Finds the index of a file descriptor (FD) in the ProxySQL_Poll object. - * - * This function searches for a file descriptor (FD) in the ProxySQL_Poll object and returns its index if found. + * + * This function performs a linear search for a file descriptor (FD) in the ProxySQL_Poll object and returns its index if found. * If the FD is not found, it returns -1. - * - * @param fd The file descriptor (FD) to search for. - * @return The index of the file descriptor (FD) if found, otherwise -1. + * + * @section Performance Notes + * - O(n) complexity where n is number of FDs in poll set + * - Used for lookup operations where FD is known but poll index is needed + * - Data streams maintain their own poll_fds_idx for O(1) access in most cases + * + * @section Usage Patterns + * Called during: + * - Listener socket operations (MySQL_Thread.cpp:3019) + * - Connection management and lookup (PgSQL_Thread.cpp:2789) + * - Debugging and diagnostic operations + * + * @param fd The file descriptor (FD) to search for + * @return The index of the file descriptor (FD) if found, otherwise -1 */ template int ProxySQL_Poll::find_index(int fd) { diff --git a/lib/mysql_data_stream.cpp b/lib/mysql_data_stream.cpp index ea3df59e7..e76fbe840 100644 --- a/lib/mysql_data_stream.cpp +++ b/lib/mysql_data_stream.cpp @@ -334,6 +334,24 @@ MySQL_Data_Stream::~MySQL_Data_Stream() { } delete resultset; } + /** + * @brief Remove data stream from poll set during MySQL_Data_Stream destruction + * + * This usage pattern demonstrates how ProxySQL_Poll is used during data stream cleanup: + * - Removes the data stream entry from the poll set to prevent polling on closed socket + * - Uses the stored poll_fds_idx for efficient removal (O(1) operation) + * - Called only if mypolls is not NULL (data stream is registered with a poll instance) + * + * Usage pattern: if (mypolls) mypolls->remove_index_fast(poll_fds_idx) + * - mypolls: Check if data stream is registered with a poll instance + * - remove_index_fast(poll_fds_idx): Remove by stored index from data stream + * + * Called during: MySQL_Data_Stream destructor + * Purpose: Prevent memory leaks and ensure proper cleanup of poll entries + * + * Note: Each data stream maintains its poll_fds_idx to track its position in the poll array + * for efficient removal without requiring find_index() lookup. + */ if (mypolls) mypolls->remove_index_fast(poll_fds_idx); @@ -738,6 +756,25 @@ int MySQL_Data_Stream::read_from_net() { } else { queue_w(queueIN,r); bytes_info.bytes_recv+=r; + /** + * @brief Update receive timestamp in ProxySQL_Poll for activity tracking + * + * This usage pattern demonstrates how ProxySQL_Poll is used for activity monitoring: + * - Updates the last receive timestamp in the poll entry for timeout management + * - Called after successful data reception to track connection activity + * - Uses the stored poll_fds_idx for direct array access (O(1) operation) + * + * Usage pattern: if (mypolls) mypolls->last_recv[poll_fds_idx] = sess->thread->curtime + * - mypolls: Check if data stream is registered with a poll instance + * - last_recv[poll_fds_idx]: Update the receive timestamp for this data stream + * - sess->thread->curtime: Current timestamp from the thread + * + * Called during: After receiving data on the data stream + * Purpose: Enable timeout management and connection activity monitoring + * + * Note: This timestamp is used by the idle connection timeout system to detect + * inactive connections that should be closed. + */ if (mypolls) mypolls->last_recv[poll_fds_idx]=sess->thread->curtime; } return r; @@ -839,6 +876,26 @@ int MySQL_Data_Stream::write_to_net() { } } else { queue_r(queueOUT, bytes_io); + + /** + * @brief Update send timestamp in ProxySQL_Poll for activity tracking + * + * This usage pattern demonstrates how ProxySQL_Poll is used for activity monitoring: + * - Updates the last send timestamp in the poll entry for timeout management + * - Called after successful data transmission to track connection activity + * - Uses the stored poll_fds_idx for direct array access (O(1) operation) + * + * Usage pattern: if (mypolls) mypolls->last_sent[poll_fds_idx] = sess->thread->curtime + * - mypolls: Check if data stream is registered with a poll instance + * - last_sent[poll_fds_idx]: Update the send timestamp for this data stream + * - sess->thread->curtime: Current timestamp from the thread + * + * Called during: After sending data on the data stream + * Purpose: Enable timeout management and connection activity monitoring + * + * Note: This timestamp is used by the idle connection timeout system to detect + * inactive connections that should be closed. + */ if (mypolls) mypolls->last_sent[poll_fds_idx]=sess->thread->curtime; bytes_info.bytes_sent+=bytes_io; }