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; }