forked from php/php-src
-
Notifications
You must be signed in to change notification settings - Fork 0
Pdo pool #4
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Pdo pool #4
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
…adlock detection
- Add function pointer types for pool operations (new_pool, acquire, release, close) - Add global function pointers with stub implementations - Add ZEND_ASYNC_NEW_POOL and ZEND_ASYNC_POOL_* macros - Add zend_async_pool_api_register() for extension registration
Implements transparent connection pooling for PDO when the async extension is available. Each coroutine gets its own connection from the pool, with automatic cleanup when the coroutine finishes. New PDO attributes for pool configuration: - PDO::ATTR_POOL_ENABLED - Enable connection pooling - PDO::ATTR_POOL_MIN - Minimum pool size - PDO::ATTR_POOL_MAX - Maximum pool size - PDO::ATTR_POOL_HEALTHCHECK_INTERVAL - Health check interval (ms) New PDO method: - getPool(): Returns Async\Pool object for CircuitBreaker configuration Key implementation details: - Pool created via zend_async_API.h C-level functions - Connections mapped per coroutine in HashTable - Transaction state (in_txn) tracked per pooled connection - Uncommitted transactions rolled back on connection release - Automatic connection release via coroutine event callback Files added: - ext/pdo/pdo_pool.c - Pool implementation - ext/pdo/pdo_pool.h - Pool API and helper macros
Tests require true_async and pdo_mysql extensions: - pdo_pool_001_attributes: Pool attribute constants exist - pdo_pool_002_getPool_no_pool: getPool() returns null when disabled - pdo_pool_003_pool_creation: Pool creation with ATTR_POOL_ENABLED - pdo_pool_004_coroutine_connections: Each coroutine gets own connection - pdo_pool_005_transactions: Transaction state per pooled connection - pdo_pool_006_auto_rollback: Uncommitted txn rolled back on release - pdo_pool_007_pool_stats: Pool statistics via getPool() - pdo_pool_008_no_pool_persistent: Pool not created for persistent conn
…eaks Replace driver_data swapping with per-coroutine connection slots (pool_connections[coro_id]) and stmt->pooled_conn references. Template pdo_dbh_t now has driver_data=NULL when pool is enabled — drivers receive valid pdo_dbh_t* via dispatch layer and need no pool awareness. Key changes: - Add db_handle_init_methods to pdo_driver_t (all 6 drivers) - Dispatch acquire/release at PDO level (pdo_dbh.c, pdo_stmt.c) - Fix pool memory leak: eager wrapper creation owns pool lifecycle - Fix destruction order: release connections before destroying pool - Route error_code via pdo_pool_sync_error for correct error reporting - Reject ATTR_POOL_ENABLED + ATTR_PERSISTENT with PDOException - Fix strcmp without explicit comparison in PDO_HANDLE_DBH_ERR - Remove all debug output (PDO_POOL_DBG macros) - Fix tests for deterministic output and correct connection lifetime
Avoid estrdup/efree for data_source, username, password in pooled connection factory. Borrow pointers from template dbh for the duration of the driver factory call, then null them out. Remove redundant field copies that drivers don't read during factory.
Avoid estrdup/efree for data_source, username, password in pooled connection factory. Borrow pointers from template dbh for the duration of the driver factory call, then null them out. Remove redundant field copies that drivers don't read during factory. Replace direct zend_async_new_pool_fn/zend_async_new_pool_obj_fn calls with ZEND_ASYNC_NEW_POOL/ZEND_ASYNC_NEW_POOL_OBJ macros for consistency with the rest of the async API usage.
…apper - Replace direct zend_async_*_fn calls with ZEND_ASYNC_NEW_POOL / ZEND_ASYNC_NEW_POOL_OBJ macros for consistency with async API. - Remove pdo_pool_async_available() — TrueAsync is always linked, function pointers are never NULL (stubs throw errors if not enabled). - Create pool wrapper object lazily on first getPool() call or during destroy, instead of eagerly at pool creation time. - Borrow template strings in pool factory instead of estrdup/efree.
…apper - Replace direct zend_async_*_fn calls with ZEND_ASYNC_NEW_POOL / ZEND_ASYNC_NEW_POOL_OBJ macros for consistency with async API. - Remove pdo_pool_async_available() — TrueAsync is always linked, function pointers are never NULL (stubs throw errors if not enabled). - Create pool wrapper object lazily on first getPool() call instead of eagerly at pool creation time. - Destroy pool via ZEND_ASYNC_POOL_CLOSE + ZEND_ASYNC_EVENT_RELEASE using proper event ref counting instead of wrapper hack. - Borrow template strings in pool factory instead of estrdup/efree.
…sh keys - Wrap error-path checks with UNEXPECTED() for branch prediction - Add const qualifiers where connections are read-only - Introduce pdo_pool_coro_key() helper that uses zend_object handle (sequential uint32_t) when available, falling back to pointer address
…or crash - Add pool_slot_refcount on pooled pdo_dbh_t to track how many statements borrow a connection. maybe_release() now checks in_txn || pool_slot_refcount > 0 before returning a connection to the pool, preventing use-after-release when multiple statements share one slot in the same coroutine. - Add pdo_pool_peek_conn() that returns the existing slot connection without acquiring a new one. Used by lastInsertId() (returns false when no connection held) and errorInfo() (returns SQLSTATE only, native details unavailable) to avoid silently reading wrong state from a different connection. - Fix segfault in _pdo_mysql_error() when called via pdo_mysql_error_stmt: stmt->dbh is the pool template with driver_data==NULL. Now uses S->H (the statement's own MySQL handle) when stmt is provided. - Add PDOPoolTest helper and 9 new tests covering refcount lifecycle, cross-coroutine isolation, txn+refcount interaction, lastInsertId and errorInfo with/without active connection.
When stmt is provided, use stmt->driver_data->H (the statement's cached connection handle) instead of dbh->driver_data, which is NULL when dbh is the pool template. Fixes potential segfaults in pgsql, sqlite, odbc, firebird, and dblib drivers (same pattern as the MySQL fix in b89f1cf).
Replace all blocking libpq calls (PQexec, PQexecParams, PQprepare, PQexecPrepared, PQgetResult, PQclosePrepared) with concurrent wrappers that yield to the async event loop when inside a coroutine, falling back to synchronous behavior otherwise. This enables parallel PDO PostgreSQL queries across coroutines without blocking the event loop. Concurrent helpers implemented in pgsql_driver.c: - pdo_pgsql_exec_concurrent: PQsendQuery + flush + collect results - pdo_pgsql_exec_params_concurrent: PQsendQueryParams variant - pdo_pgsql_prepare_concurrent: PQsendPrepare variant - pdo_pgsql_exec_prepared_concurrent: PQsendQueryPrepared variant - pdo_pgsql_close_prepared_concurrent: PQsendClosePrepared (PG17+) - pdo_pgsql_get_result_concurrent: async-aware PQgetResult - pdo_pgsql_flush: async-aware PQflush for unbuffered send paths
Add a `bool *supports_pool` parameter to `db_handle_init_methods`. Only MySQL and PgSQL set the flag to true. When pool is enabled for an unsupported driver, throw an exception instead of silently proceeding.
…nection closure on factory failure
…on bugs Drivers may mutate, reallocate, or free data_source/username/password during db_handle_factory (PgSQL replaces ';' with ' ', MySQL allocates username from DSN, ODBC rebuilds the entire connection string). Borrowing raw pointers from the template caused template corruption, memory leaks, and potential double-free. Now estrdup copies are made per factory call and freed afterward. Extracted pdo_pool_free_conn for unified cleanup.
4a4f692 to
71be978
Compare
71be978 to
867b4c9
Compare
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
No description provided.