Skip to content

Commit d03f362

Browse files
committed
PHPC-1290: Adapt server selection logic to respect session pinning
1 parent bb8728e commit d03f362

File tree

5 files changed

+62
-54
lines changed

5 files changed

+62
-54
lines changed

php_phongo.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -604,7 +604,7 @@ bool phongo_parse_read_preference(zval* options, zval** zreadPreference TSRMLS_D
604604
* not NULL, the option will be appended. If zsession is not NULL, it will be
605605
* assigned to the option. On error, false is returned and an exception is
606606
* thrown. */
607-
static bool phongo_parse_session(zval* options, mongoc_client_t* client, bson_t* mongoc_opts, zval** zsession TSRMLS_DC) /* {{{ */
607+
bool phongo_parse_session(zval* options, mongoc_client_t* client, bson_t* mongoc_opts, zval** zsession TSRMLS_DC) /* {{{ */
608608
{
609609
zval* option = NULL;
610610
const mongoc_client_session_t* client_session;

php_phongo.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,7 @@ const mongoc_write_concern_t* phongo_write_concern_from_zval(zval* zwrite_concer
147147
php_phongo_server_description_type_t php_phongo_server_description_type(mongoc_server_description_t* sd);
148148

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

151152
zval* php_phongo_prep_legacy_option(zval* options, const char* key, bool* allocated TSRMLS_DC);
152153
void php_phongo_prep_legacy_option_free(zval* options TSRMLS_DC);

src/MongoDB/Manager.c

Lines changed: 60 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -254,15 +254,28 @@ static void php_phongo_manager_prep_uri_options(zval* options TSRMLS_DC) /* {{{
254254
/* Selects a server for an execute method. If "for_writes" is true, a primary
255255
* will be selected. Otherwise, a read preference will be used to select the
256256
* server. If zreadPreference is NULL, the client's read preference will be
257-
* used.
257+
* used. If zsession is a session object in a sharded transaction, the session
258+
* will be checked whether it is pinned to a server. If so, that server will be
259+
* selected. Otherwise, server selection
258260
*
259261
* On success, server_id will be set and the function will return true;
260262
* otherwise, false is returned and an exception is thrown. */
261-
static bool php_phongo_manager_select_server(bool for_writes, zval* zreadPreference, mongoc_client_t* client, uint32_t* server_id TSRMLS_DC) /* {{{ */
263+
static bool php_phongo_manager_select_server(bool for_writes, zval* zreadPreference, zval* zsession, mongoc_client_t* client, uint32_t* server_id TSRMLS_DC) /* {{{ */
262264
{
263-
const mongoc_read_prefs_t* read_preference = NULL;
264265
mongoc_server_description_t* selected_server;
265-
bson_error_t error = { 0 };
266+
const mongoc_read_prefs_t* read_preference = NULL;
267+
bson_error_t error = { 0 };
268+
269+
if (zsession) {
270+
const mongoc_client_session_t* session = Z_SESSION_OBJ_P(zsession)->client_session;
271+
272+
/* Attempt to fetch server pinned to session */
273+
if (mongoc_client_session_get_server_id(session) > 0) {
274+
*server_id = mongoc_client_session_get_server_id(session);
275+
276+
return true;
277+
}
278+
}
266279

267280
if (!for_writes) {
268281
read_preference = zreadPreference ? phongo_read_preference_from_zval(zreadPreference TSRMLS_CC) : mongoc_client_get_read_prefs(client);
@@ -336,6 +349,7 @@ static PHP_METHOD(Manager, executeCommand)
336349
zval* options = NULL;
337350
bool free_options = false;
338351
zval* zreadPreference = NULL;
352+
zval* zsession = NULL;
339353
uint32_t server_id = 0;
340354
DECLARE_RETURN_VALUE_USED
341355

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

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

364+
if (!phongo_parse_session(options, intern->client, NULL, &zsession TSRMLS_CC)) {
365+
/* Exception should already have been thrown */
366+
goto cleanup;
367+
}
368+
350369
if (!phongo_parse_read_preference(options, &zreadPreference TSRMLS_CC)) {
351370
/* Exception should already have been thrown */
352371
goto cleanup;
353372
}
354373

355-
if (!php_phongo_manager_select_server(false, zreadPreference, intern->client, &server_id TSRMLS_CC)) {
374+
if (!php_phongo_manager_select_server(false, zreadPreference, zsession, intern->client, &server_id TSRMLS_CC)) {
356375
/* Exception should already have been thrown */
357376
goto cleanup;
358377
}
@@ -376,6 +395,7 @@ static PHP_METHOD(Manager, executeReadCommand)
376395
zval* options = NULL;
377396
zval* zreadPreference = NULL;
378397
uint32_t server_id = 0;
398+
zval* zsession = NULL;
379399
DECLARE_RETURN_VALUE_USED
380400

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

385405
intern = Z_MANAGER_OBJ_P(getThis());
386406

407+
if (!phongo_parse_session(options, intern->client, NULL, &zsession TSRMLS_CC)) {
408+
/* Exception should already have been thrown */
409+
return;
410+
}
411+
387412
if (!phongo_parse_read_preference(options, &zreadPreference TSRMLS_CC)) {
388413
/* Exception should already have been thrown */
389414
return;
390415
}
391416

392-
if (!php_phongo_manager_select_server(false, zreadPreference, intern->client, &server_id TSRMLS_CC)) {
417+
if (!php_phongo_manager_select_server(false, zreadPreference, zsession, intern->client, &server_id TSRMLS_CC)) {
393418
/* Exception should already have been thrown */
394419
return;
395420
}
@@ -407,6 +432,7 @@ static PHP_METHOD(Manager, executeWriteCommand)
407432
zval* command;
408433
zval* options = NULL;
409434
uint32_t server_id = 0;
435+
zval* zsession = NULL;
410436
DECLARE_RETURN_VALUE_USED
411437

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

416442
intern = Z_MANAGER_OBJ_P(getThis());
417443

418-
if (!php_phongo_manager_select_server(true, NULL, intern->client, &server_id TSRMLS_CC)) {
444+
if (!phongo_parse_session(options, intern->client, NULL, &zsession TSRMLS_CC)) {
445+
/* Exception should already have been thrown */
446+
return;
447+
}
448+
449+
if (!php_phongo_manager_select_server(true, NULL, zsession, intern->client, &server_id TSRMLS_CC)) {
419450
/* Exception should already have been thrown */
420451
return;
421452
}
@@ -433,6 +464,7 @@ static PHP_METHOD(Manager, executeReadWriteCommand)
433464
zval* command;
434465
zval* options = NULL;
435466
uint32_t server_id = 0;
467+
zval* zsession = NULL;
436468
DECLARE_RETURN_VALUE_USED
437469

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

442474
intern = Z_MANAGER_OBJ_P(getThis());
443475

444-
if (!php_phongo_manager_select_server(true, NULL, intern->client, &server_id TSRMLS_CC)) {
476+
if (!phongo_parse_session(options, intern->client, NULL, &zsession TSRMLS_CC)) {
477+
/* Exception should already have been thrown */
478+
return;
479+
}
480+
481+
if (!php_phongo_manager_select_server(true, NULL, zsession, intern->client, &server_id TSRMLS_CC)) {
445482
/* Exception should already have been thrown */
446483
return;
447484
}
@@ -461,6 +498,7 @@ static PHP_METHOD(Manager, executeQuery)
461498
bool free_options = false;
462499
zval* zreadPreference = NULL;
463500
uint32_t server_id = 0;
501+
zval* zsession = NULL;
464502
DECLARE_RETURN_VALUE_USED
465503

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

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

512+
if (!phongo_parse_session(options, intern->client, NULL, &zsession TSRMLS_CC)) {
513+
/* Exception should already have been thrown */
514+
goto cleanup;
515+
}
516+
474517
if (!phongo_parse_read_preference(options, &zreadPreference TSRMLS_CC)) {
475518
/* Exception should already have been thrown */
476519
goto cleanup;
477520
}
478521

479-
if (!php_phongo_manager_select_server(false, zreadPreference, intern->client, &server_id TSRMLS_CC)) {
522+
if (!php_phongo_manager_select_server(false, zreadPreference, zsession, intern->client, &server_id TSRMLS_CC)) {
480523
/* Exception should already have been thrown */
481524
goto cleanup;
482525
}
@@ -501,6 +544,7 @@ static PHP_METHOD(Manager, executeBulkWrite)
501544
zval* options = NULL;
502545
bool free_options = false;
503546
uint32_t server_id = 0;
547+
zval* zsession = NULL;
504548
DECLARE_RETURN_VALUE_USED
505549

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

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

515-
if (!php_phongo_manager_select_server(true, NULL, intern->client, &server_id TSRMLS_CC)) {
559+
if (!phongo_parse_session(options, intern->client, NULL, &zsession TSRMLS_CC)) {
560+
/* Exception should already have been thrown */
561+
return;
562+
}
563+
564+
if (!php_phongo_manager_select_server(true, NULL, zsession, intern->client, &server_id TSRMLS_CC)) {
516565
/* Exception should already have been thrown */
517566
goto cleanup;
518567
}
@@ -628,7 +677,7 @@ static PHP_METHOD(Manager, selectServer)
628677
return;
629678
}
630679

631-
if (!php_phongo_manager_select_server(false, zreadPreference, intern->client, &server_id TSRMLS_CC)) {
680+
if (!php_phongo_manager_select_server(false, zreadPreference, NULL, intern->client, &server_id TSRMLS_CC)) {
632681
/* Exception should already have been thrown */
633682
return;
634683
}

src/MongoDB/Session.c

Lines changed: 0 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -38,18 +38,6 @@ zend_class_entry* php_phongo_session_ce;
3838
return; \
3939
}
4040

41-
static bool php_phongo_topology_is_sharded_cluster(mongoc_client_t* client)
42-
{
43-
mongoc_server_description_t* sd;
44-
bool ret;
45-
46-
sd = mongoc_client_select_server(client, true, NULL, NULL);
47-
ret = (sd && !strcmp(mongoc_server_description_type(sd), php_phongo_server_description_type_map[PHONGO_SERVER_MONGOS].name));
48-
mongoc_server_description_destroy(sd);
49-
50-
return ret;
51-
}
52-
5341
static bool php_phongo_session_get_timestamp_parts(zval* obj, uint32_t* timestamp, uint32_t* increment TSRMLS_DC)
5442
{
5543
bool retval = false;
@@ -366,11 +354,6 @@ static PHP_METHOD(Session, startTransaction)
366354
return;
367355
}
368356

369-
if (php_phongo_topology_is_sharded_cluster(mongoc_client_session_get_client(intern->client_session))) {
370-
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);
371-
return;
372-
}
373-
374357
if (!mongoc_client_session_start_transaction(intern->client_session, txn_options, &error)) {
375358
phongo_throw_exception_from_bson_error_t(&error TSRMLS_CC);
376359
}

tests/session/session-startTransaction_error-004.phpt

Lines changed: 0 additions & 25 deletions
This file was deleted.

0 commit comments

Comments
 (0)