Skip to content

Commit

Permalink
PHPC-1290: Adapt server selection logic to respect session pinning
Browse files Browse the repository at this point in the history
  • Loading branch information
alcaeus committed Aug 28, 2019
1 parent bb8728e commit d03f362
Show file tree
Hide file tree
Showing 5 changed files with 62 additions and 54 deletions.
2 changes: 1 addition & 1 deletion php_phongo.c
Expand Up @@ -604,7 +604,7 @@ bool phongo_parse_read_preference(zval* options, zval** zreadPreference TSRMLS_D
* not NULL, the option will be appended. If zsession is not NULL, it will be
* assigned to the option. On error, false is returned and an exception is
* thrown. */
static bool phongo_parse_session(zval* options, mongoc_client_t* client, bson_t* mongoc_opts, zval** zsession TSRMLS_DC) /* {{{ */
bool phongo_parse_session(zval* options, mongoc_client_t* client, bson_t* mongoc_opts, zval** zsession TSRMLS_DC) /* {{{ */
{
zval* option = NULL;
const mongoc_client_session_t* client_session;
Expand Down
1 change: 1 addition & 0 deletions php_phongo.h
Expand Up @@ -147,6 +147,7 @@ const mongoc_write_concern_t* phongo_write_concern_from_zval(zval* zwrite_concer
php_phongo_server_description_type_t php_phongo_server_description_type(mongoc_server_description_t* sd);

bool phongo_parse_read_preference(zval* options, zval** zreadPreference TSRMLS_DC);
bool phongo_parse_session(zval* options, mongoc_client_t* client, bson_t* mongoc_opts, zval** zsession TSRMLS_DC);

zval* php_phongo_prep_legacy_option(zval* options, const char* key, bool* allocated TSRMLS_DC);
void php_phongo_prep_legacy_option_free(zval* options TSRMLS_DC);
Expand Down
71 changes: 60 additions & 11 deletions src/MongoDB/Manager.c
Expand Up @@ -254,15 +254,28 @@ static void php_phongo_manager_prep_uri_options(zval* options TSRMLS_DC) /* {{{
/* Selects a server for an execute method. If "for_writes" is true, a primary
* will be selected. Otherwise, a read preference will be used to select the
* server. If zreadPreference is NULL, the client's read preference will be
* used.
* used. If zsession is a session object in a sharded transaction, the session
* will be checked whether it is pinned to a server. If so, that server will be
* selected. Otherwise, server selection
*
* On success, server_id will be set and the function will return true;
* otherwise, false is returned and an exception is thrown. */
static bool php_phongo_manager_select_server(bool for_writes, zval* zreadPreference, mongoc_client_t* client, uint32_t* server_id TSRMLS_DC) /* {{{ */
static bool php_phongo_manager_select_server(bool for_writes, zval* zreadPreference, zval* zsession, mongoc_client_t* client, uint32_t* server_id TSRMLS_DC) /* {{{ */
{
const mongoc_read_prefs_t* read_preference = NULL;
mongoc_server_description_t* selected_server;
bson_error_t error = { 0 };
const mongoc_read_prefs_t* read_preference = NULL;
bson_error_t error = { 0 };

if (zsession) {
const mongoc_client_session_t* session = Z_SESSION_OBJ_P(zsession)->client_session;

/* Attempt to fetch server pinned to session */
if (mongoc_client_session_get_server_id(session) > 0) {
*server_id = mongoc_client_session_get_server_id(session);

return true;
}
}

if (!for_writes) {
read_preference = zreadPreference ? phongo_read_preference_from_zval(zreadPreference TSRMLS_CC) : mongoc_client_get_read_prefs(client);
Expand Down Expand Up @@ -336,6 +349,7 @@ static PHP_METHOD(Manager, executeCommand)
zval* options = NULL;
bool free_options = false;
zval* zreadPreference = NULL;
zval* zsession = NULL;
uint32_t server_id = 0;
DECLARE_RETURN_VALUE_USED

Expand All @@ -347,12 +361,17 @@ static PHP_METHOD(Manager, executeCommand)

options = php_phongo_prep_legacy_option(options, "readPreference", &free_options TSRMLS_CC);

if (!phongo_parse_session(options, intern->client, NULL, &zsession TSRMLS_CC)) {
/* Exception should already have been thrown */
goto cleanup;
}

if (!phongo_parse_read_preference(options, &zreadPreference TSRMLS_CC)) {
/* Exception should already have been thrown */
goto cleanup;
}

if (!php_phongo_manager_select_server(false, zreadPreference, intern->client, &server_id TSRMLS_CC)) {
if (!php_phongo_manager_select_server(false, zreadPreference, zsession, intern->client, &server_id TSRMLS_CC)) {
/* Exception should already have been thrown */
goto cleanup;
}
Expand All @@ -376,6 +395,7 @@ static PHP_METHOD(Manager, executeReadCommand)
zval* options = NULL;
zval* zreadPreference = NULL;
uint32_t server_id = 0;
zval* zsession = NULL;
DECLARE_RETURN_VALUE_USED

if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sO|a!", &db, &db_len, &command, php_phongo_command_ce, &options) == FAILURE) {
Expand All @@ -384,12 +404,17 @@ static PHP_METHOD(Manager, executeReadCommand)

intern = Z_MANAGER_OBJ_P(getThis());

if (!phongo_parse_session(options, intern->client, NULL, &zsession TSRMLS_CC)) {
/* Exception should already have been thrown */
return;
}

if (!phongo_parse_read_preference(options, &zreadPreference TSRMLS_CC)) {
/* Exception should already have been thrown */
return;
}

if (!php_phongo_manager_select_server(false, zreadPreference, intern->client, &server_id TSRMLS_CC)) {
if (!php_phongo_manager_select_server(false, zreadPreference, zsession, intern->client, &server_id TSRMLS_CC)) {
/* Exception should already have been thrown */
return;
}
Expand All @@ -407,6 +432,7 @@ static PHP_METHOD(Manager, executeWriteCommand)
zval* command;
zval* options = NULL;
uint32_t server_id = 0;
zval* zsession = NULL;
DECLARE_RETURN_VALUE_USED

if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sO|a!", &db, &db_len, &command, php_phongo_command_ce, &options) == FAILURE) {
Expand All @@ -415,7 +441,12 @@ static PHP_METHOD(Manager, executeWriteCommand)

intern = Z_MANAGER_OBJ_P(getThis());

if (!php_phongo_manager_select_server(true, NULL, intern->client, &server_id TSRMLS_CC)) {
if (!phongo_parse_session(options, intern->client, NULL, &zsession TSRMLS_CC)) {
/* Exception should already have been thrown */
return;
}

if (!php_phongo_manager_select_server(true, NULL, zsession, intern->client, &server_id TSRMLS_CC)) {
/* Exception should already have been thrown */
return;
}
Expand All @@ -433,6 +464,7 @@ static PHP_METHOD(Manager, executeReadWriteCommand)
zval* command;
zval* options = NULL;
uint32_t server_id = 0;
zval* zsession = NULL;
DECLARE_RETURN_VALUE_USED

if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sO|a!", &db, &db_len, &command, php_phongo_command_ce, &options) == FAILURE) {
Expand All @@ -441,7 +473,12 @@ static PHP_METHOD(Manager, executeReadWriteCommand)

intern = Z_MANAGER_OBJ_P(getThis());

if (!php_phongo_manager_select_server(true, NULL, intern->client, &server_id TSRMLS_CC)) {
if (!phongo_parse_session(options, intern->client, NULL, &zsession TSRMLS_CC)) {
/* Exception should already have been thrown */
return;
}

if (!php_phongo_manager_select_server(true, NULL, zsession, intern->client, &server_id TSRMLS_CC)) {
/* Exception should already have been thrown */
return;
}
Expand All @@ -461,6 +498,7 @@ static PHP_METHOD(Manager, executeQuery)
bool free_options = false;
zval* zreadPreference = NULL;
uint32_t server_id = 0;
zval* zsession = NULL;
DECLARE_RETURN_VALUE_USED

if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sO|z!", &namespace, &namespace_len, &query, php_phongo_query_ce, &options) == FAILURE) {
Expand All @@ -471,12 +509,17 @@ static PHP_METHOD(Manager, executeQuery)

options = php_phongo_prep_legacy_option(options, "readPreference", &free_options TSRMLS_CC);

if (!phongo_parse_session(options, intern->client, NULL, &zsession TSRMLS_CC)) {
/* Exception should already have been thrown */
goto cleanup;
}

if (!phongo_parse_read_preference(options, &zreadPreference TSRMLS_CC)) {
/* Exception should already have been thrown */
goto cleanup;
}

if (!php_phongo_manager_select_server(false, zreadPreference, intern->client, &server_id TSRMLS_CC)) {
if (!php_phongo_manager_select_server(false, zreadPreference, zsession, intern->client, &server_id TSRMLS_CC)) {
/* Exception should already have been thrown */
goto cleanup;
}
Expand All @@ -501,6 +544,7 @@ static PHP_METHOD(Manager, executeBulkWrite)
zval* options = NULL;
bool free_options = false;
uint32_t server_id = 0;
zval* zsession = NULL;
DECLARE_RETURN_VALUE_USED

if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sO|z!", &namespace, &namespace_len, &zbulk, php_phongo_bulkwrite_ce, &options) == FAILURE) {
Expand All @@ -512,7 +556,12 @@ static PHP_METHOD(Manager, executeBulkWrite)

options = php_phongo_prep_legacy_option(options, "writeConcern", &free_options TSRMLS_CC);

if (!php_phongo_manager_select_server(true, NULL, intern->client, &server_id TSRMLS_CC)) {
if (!phongo_parse_session(options, intern->client, NULL, &zsession TSRMLS_CC)) {
/* Exception should already have been thrown */
return;
}

if (!php_phongo_manager_select_server(true, NULL, zsession, intern->client, &server_id TSRMLS_CC)) {
/* Exception should already have been thrown */
goto cleanup;
}
Expand Down Expand Up @@ -628,7 +677,7 @@ static PHP_METHOD(Manager, selectServer)
return;
}

if (!php_phongo_manager_select_server(false, zreadPreference, intern->client, &server_id TSRMLS_CC)) {
if (!php_phongo_manager_select_server(false, zreadPreference, NULL, intern->client, &server_id TSRMLS_CC)) {
/* Exception should already have been thrown */
return;
}
Expand Down
17 changes: 0 additions & 17 deletions src/MongoDB/Session.c
Expand Up @@ -38,18 +38,6 @@ zend_class_entry* php_phongo_session_ce;
return; \
}

static bool php_phongo_topology_is_sharded_cluster(mongoc_client_t* client)
{
mongoc_server_description_t* sd;
bool ret;

sd = mongoc_client_select_server(client, true, NULL, NULL);
ret = (sd && !strcmp(mongoc_server_description_type(sd), php_phongo_server_description_type_map[PHONGO_SERVER_MONGOS].name));
mongoc_server_description_destroy(sd);

return ret;
}

static bool php_phongo_session_get_timestamp_parts(zval* obj, uint32_t* timestamp, uint32_t* increment TSRMLS_DC)
{
bool retval = false;
Expand Down Expand Up @@ -366,11 +354,6 @@ static PHP_METHOD(Session, startTransaction)
return;
}

if (php_phongo_topology_is_sharded_cluster(mongoc_client_session_get_client(intern->client_session))) {
phongo_throw_exception(PHONGO_ERROR_RUNTIME TSRMLS_CC, "PHP MongoDB driver %s does not support running multi-document transactions on sharded clusters", PHP_MONGODB_VERSION);
return;
}

if (!mongoc_client_session_start_transaction(intern->client_session, txn_options, &error)) {
phongo_throw_exception_from_bson_error_t(&error TSRMLS_CC);
}
Expand Down
25 changes: 0 additions & 25 deletions tests/session/session-startTransaction_error-004.phpt

This file was deleted.

0 comments on commit d03f362

Please sign in to comment.