Skip to content

Commit d1d9d4a

Browse files
committed
PHPC-980: MongoDB\Driver\Session and "session" option
This introduces a Session class, which wraps libmongoc's client session object. Additionally, we support a "session" option on Manager and Server execute methods to allow operations to be associated with an explicit session (mostly relevant for causal consistency).
1 parent d39bf88 commit d1d9d4a

14 files changed

+613
-1
lines changed

config.m4

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,7 @@ if test "$MONGODB" != "no"; then
190190
src/MongoDB/ReadConcern.c \
191191
src/MongoDB/ReadPreference.c \
192192
src/MongoDB/Server.c \
193+
src/MongoDB/Session.c \
193194
src/MongoDB/WriteConcern.c \
194195
src/MongoDB/WriteConcernError.c \
195196
src/MongoDB/WriteError.c \

config.w32

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ if (PHP_MONGODB != "no") {
8585
EXTENSION("mongodb", "php_phongo.c phongo_compat.c", null, PHP_MONGODB_CFLAGS);
8686
ADD_SOURCES(configure_module_dirname + "/src", "bson.c bson-encode.c", "mongodb");
8787
ADD_SOURCES(configure_module_dirname + "/src/BSON", "Binary.c BinaryInterface.c DBPointer.c Decimal128.c Decimal128Interface.c Javascript.c JavascriptInterface.c MaxKey.c MaxKeyInterface.c MinKey.c MinKeyInterface.c ObjectId.c ObjectIdInterface.c Persistable.c Regex.c RegexInterface.c Serializable.c Symbol.c Timestamp.c TimestampInterface.c Type.c Undefined.c Unserializable.c UTCDateTime.c UTCDateTimeInterface.c functions.c", "mongodb");
88-
ADD_SOURCES(configure_module_dirname + "/src/MongoDB", "BulkWrite.c Command.c Cursor.c CursorId.c Manager.c Query.c ReadConcern.c ReadPreference.c Server.c WriteConcern.c WriteConcernError.c WriteError.c WriteResult.c", "mongodb");
88+
ADD_SOURCES(configure_module_dirname + "/src/MongoDB", "BulkWrite.c Command.c Cursor.c CursorId.c Manager.c Query.c ReadConcern.c ReadPreference.c Server.c Session.c WriteConcern.c WriteConcernError.c WriteError.c WriteResult.c", "mongodb");
8989
ADD_SOURCES(configure_module_dirname + "/src/MongoDB/Exception", "AuthenticationException.c BulkWriteException.c ConnectionException.c ConnectionTimeoutException.c Exception.c ExecutionTimeoutException.c InvalidArgumentException.c LogicException.c RuntimeException.c SSLConnectionException.c UnexpectedValueException.c WriteException.c", "mongodb");
9090
ADD_SOURCES(configure_module_dirname + "/src/MongoDB/Monitoring", "CommandFailedEvent.c CommandStartedEvent.c CommandSubscriber.c CommandSucceededEvent.c Subscriber.c functions.c", "mongodb");
9191
ADD_SOURCES(configure_module_dirname + "/src/libbson/src/bson", PHP_MONGODB_BSON_SOURCES, "mongodb");

php_phongo.c

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -306,6 +306,17 @@ void phongo_server_init(zval *return_value, mongoc_client_t *client, int server_
306306
}
307307
/* }}} */
308308

309+
void phongo_session_init(zval *return_value, mongoc_client_session_t *client_session TSRMLS_DC) /* {{{ */
310+
{
311+
php_phongo_session_t *session;
312+
313+
object_init_ex(return_value, php_phongo_session_ce);
314+
315+
session = Z_SESSION_OBJ_P(return_value);
316+
session->client_session = client_session;
317+
}
318+
/* }}} */
319+
309320
void phongo_readconcern_init(zval *return_value, const mongoc_read_concern_t *read_concern TSRMLS_DC) /* {{{ */
310321
{
311322
php_phongo_readconcern_t *intern;
@@ -527,6 +538,25 @@ static bool process_read_preference(zval *option, bson_t *mongoc_opts, zval **zr
527538
return true;
528539
}
529540

541+
static bool process_session(zval *option, bson_t *mongoc_opts TSRMLS_DC)
542+
{
543+
const mongoc_client_session_t *client_session;
544+
545+
if (Z_TYPE_P(option) != IS_OBJECT || !instanceof_function(Z_OBJCE_P(option), php_phongo_session_ce TSRMLS_CC)) {
546+
phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT TSRMLS_CC, "Expected \"session\" option to be %s, %s given", ZSTR_VAL(php_phongo_session_ce->name), PHONGO_ZVAL_CLASS_OR_TYPE_NAME_P(option));
547+
return false;
548+
}
549+
550+
client_session = Z_SESSION_OBJ_P(option)->client_session;
551+
552+
if (!mongoc_client_session_append(Z_SESSION_OBJ_P(option)->client_session, mongoc_opts, NULL)) {
553+
phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT TSRMLS_CC, "Error appending \"session\" option");
554+
return false;
555+
}
556+
557+
return true;
558+
}
559+
530560
static bool process_write_concern(zval *option, bson_t *mongoc_opts, zval **zwriteConcern TSRMLS_DC)
531561
{
532562
if (Z_TYPE_P(option) == IS_OBJECT && instanceof_function(Z_OBJCE_P(option), php_phongo_writeconcern_ce TSRMLS_CC)) {
@@ -573,6 +603,10 @@ static int phongo_execute_parse_options(mongoc_client_t* client, int server_id,
573603
if (!process_read_preference(driver_option, mongoc_opts, zreadPreference, client, server_id)) {
574604
return false;
575605
}
606+
} else if ((!strcmp(ZSTR_VAL(string_key), "session"))) {
607+
if (!process_session(driver_option, mongoc_opts)) {
608+
return false;
609+
}
576610
} else if ((!strcasecmp(ZSTR_VAL(string_key), "writeConcern")) && (type & PHONGO_COMMAND_WRITE)) {
577611
if (!process_write_concern(driver_option, mongoc_opts, zwriteConcern)) {
578612
return false;
@@ -606,6 +640,10 @@ static int phongo_execute_parse_options(mongoc_client_t* client, int server_id,
606640
if (!process_read_preference(*driver_option, mongoc_opts, zreadPreference, client, server_id TSRMLS_CC)) {
607641
return false;
608642
}
643+
} else if ((!strcmp(ZSTR_VAL(string_key), "session"))) {
644+
if (!process_session(*driver_option, mongoc_opts)) {
645+
return false;
646+
}
609647
} else if ((!strcasecmp(string_key, "writeConcern")) && (type & PHONGO_COMMAND_WRITE)) {
610648
if (!process_write_concern(*driver_option, mongoc_opts, zwriteConcern TSRMLS_CC)) {
611649
return false;
@@ -2693,6 +2731,7 @@ PHP_MINIT_FUNCTION(mongodb)
26932731
php_phongo_readconcern_init_ce(INIT_FUNC_ARGS_PASSTHRU);
26942732
php_phongo_readpreference_init_ce(INIT_FUNC_ARGS_PASSTHRU);
26952733
php_phongo_server_init_ce(INIT_FUNC_ARGS_PASSTHRU);
2734+
php_phongo_session_init_ce(INIT_FUNC_ARGS_PASSTHRU);
26962735
php_phongo_writeconcern_init_ce(INIT_FUNC_ARGS_PASSTHRU);
26972736
php_phongo_writeconcernerror_init_ce(INIT_FUNC_ARGS_PASSTHRU);
26982737
php_phongo_writeerror_init_ce(INIT_FUNC_ARGS_PASSTHRU);

php_phongo.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,7 @@ typedef enum {
126126
zend_object_handlers *phongo_get_std_object_handlers(void);
127127

128128
void phongo_server_init (zval *return_value, mongoc_client_t *client, int server_id TSRMLS_DC);
129+
void phongo_session_init (zval *return_value, mongoc_client_session_t *client_session TSRMLS_DC);
129130
void phongo_readconcern_init (zval *return_value, const mongoc_read_concern_t *read_concern TSRMLS_DC);
130131
void phongo_readpreference_init (zval *return_value, const mongoc_read_prefs_t *read_prefs TSRMLS_DC);
131132
void phongo_writeconcern_init (zval *return_value, const mongoc_write_concern_t *write_concern TSRMLS_DC);

php_phongo_classes.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,9 @@ static inline php_phongo_readpreference_t* php_readpreference_fetch_object(zend_
5252
static inline php_phongo_server_t* php_server_fetch_object(zend_object *obj) {
5353
return (php_phongo_server_t *)((char *)obj - XtOffsetOf(php_phongo_server_t, std));
5454
}
55+
static inline php_phongo_session_t* php_session_fetch_object(zend_object *obj) {
56+
return (php_phongo_session_t *)((char *)obj - XtOffsetOf(php_phongo_session_t, std));
57+
}
5558
static inline php_phongo_writeconcern_t* php_writeconcern_fetch_object(zend_object *obj) {
5659
return (php_phongo_writeconcern_t *)((char *)obj - XtOffsetOf(php_phongo_writeconcern_t, std));
5760
}
@@ -118,6 +121,7 @@ static inline php_phongo_commandsucceededevent_t* php_commandsucceededevent_fetc
118121
# define Z_READCONCERN_OBJ_P(zv) (php_readconcern_fetch_object(Z_OBJ_P(zv)))
119122
# define Z_READPREFERENCE_OBJ_P(zv) (php_readpreference_fetch_object(Z_OBJ_P(zv)))
120123
# define Z_SERVER_OBJ_P(zv) (php_server_fetch_object(Z_OBJ_P(zv)))
124+
# define Z_SESSION_OBJ_P(zv) (php_session_fetch_object(Z_OBJ_P(zv)))
121125
# define Z_BULKWRITE_OBJ_P(zv) (php_bulkwrite_fetch_object(Z_OBJ_P(zv)))
122126
# define Z_WRITECONCERN_OBJ_P(zv) (php_writeconcern_fetch_object(Z_OBJ_P(zv)))
123127
# define Z_WRITECONCERNERROR_OBJ_P(zv) (php_writeconcernerror_fetch_object(Z_OBJ_P(zv)))
@@ -147,6 +151,7 @@ static inline php_phongo_commandsucceededevent_t* php_commandsucceededevent_fetc
147151
# define Z_OBJ_READCONCERN(zo) (php_readconcern_fetch_object(zo))
148152
# define Z_OBJ_READPREFERENCE(zo) (php_readpreference_fetch_object(zo))
149153
# define Z_OBJ_SERVER(zo) (php_server_fetch_object(zo))
154+
# define Z_OBJ_SESSION(zo) (php_session_fetch_object(zo))
150155
# define Z_OBJ_BULKWRITE(zo) (php_bulkwrite_fetch_object(zo))
151156
# define Z_OBJ_WRITECONCERN(zo) (php_writeconcern_fetch_object(zo))
152157
# define Z_OBJ_WRITECONCERNERROR(zo) (php_writeconcernerror_fetch_object(zo))
@@ -178,6 +183,7 @@ static inline php_phongo_commandsucceededevent_t* php_commandsucceededevent_fetc
178183
# define Z_READCONCERN_OBJ_P(zv) ((php_phongo_readconcern_t *)zend_object_store_get_object(zv TSRMLS_CC))
179184
# define Z_READPREFERENCE_OBJ_P(zv) ((php_phongo_readpreference_t *)zend_object_store_get_object(zv TSRMLS_CC))
180185
# define Z_SERVER_OBJ_P(zv) ((php_phongo_server_t *)zend_object_store_get_object(zv TSRMLS_CC))
186+
# define Z_SESSION_OBJ_P(zv) ((php_phongo_session_t *)zend_object_store_get_object(zv TSRMLS_CC))
181187
# define Z_BULKWRITE_OBJ_P(zv) ((php_phongo_bulkwrite_t *)zend_object_store_get_object(zv TSRMLS_CC))
182188
# define Z_WRITECONCERN_OBJ_P(zv) ((php_phongo_writeconcern_t *)zend_object_store_get_object(zv TSRMLS_CC))
183189
# define Z_WRITECONCERNERROR_OBJ_P(zv) ((php_phongo_writeconcernerror_t *)zend_object_store_get_object(zv TSRMLS_CC))
@@ -207,6 +213,7 @@ static inline php_phongo_commandsucceededevent_t* php_commandsucceededevent_fetc
207213
# define Z_OBJ_READCONCERN(zo) ((php_phongo_readconcern_t *)zo)
208214
# define Z_OBJ_READPREFERENCE(zo) ((php_phongo_readpreference_t *)zo)
209215
# define Z_OBJ_SERVER(zo) ((php_phongo_server_t *)zo)
216+
# define Z_OBJ_SESSION(zo) ((php_phongo_session_t *)zo)
210217
# define Z_OBJ_BULKWRITE(zo) ((php_phongo_bulkwrite_t *)zo)
211218
# define Z_OBJ_WRITECONCERN(zo) ((php_phongo_writeconcern_t *)zo)
212219
# define Z_OBJ_WRITECONCERNERROR(zo) ((php_phongo_writeconcernerror_t *)zo)
@@ -244,6 +251,7 @@ extern zend_class_entry *php_phongo_query_ce;
244251
extern zend_class_entry *php_phongo_readconcern_ce;
245252
extern zend_class_entry *php_phongo_readpreference_ce;
246253
extern zend_class_entry *php_phongo_server_ce;
254+
extern zend_class_entry *php_phongo_session_ce;
247255
extern zend_class_entry *php_phongo_bulkwrite_ce;
248256
extern zend_class_entry *php_phongo_writeconcern_ce;
249257
extern zend_class_entry *php_phongo_writeconcernerror_ce;
@@ -332,6 +340,7 @@ extern void php_phongo_query_init_ce(INIT_FUNC_ARGS);
332340
extern void php_phongo_readconcern_init_ce(INIT_FUNC_ARGS);
333341
extern void php_phongo_readpreference_init_ce(INIT_FUNC_ARGS);
334342
extern void php_phongo_server_init_ce(INIT_FUNC_ARGS);
343+
extern void php_phongo_session_init_ce(INIT_FUNC_ARGS);
335344
extern void php_phongo_writeconcern_init_ce(INIT_FUNC_ARGS);
336345
extern void php_phongo_writeconcernerror_init_ce(INIT_FUNC_ARGS);
337346
extern void php_phongo_writeerror_init_ce(INIT_FUNC_ARGS);

php_phongo_structs.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,12 @@ typedef struct {
106106
PHONGO_ZEND_OBJECT_POST
107107
} php_phongo_server_t;
108108

109+
typedef struct {
110+
PHONGO_ZEND_OBJECT_PRE
111+
mongoc_client_session_t *client_session;
112+
PHONGO_ZEND_OBJECT_POST
113+
} php_phongo_session_t;
114+
109115
typedef struct {
110116
PHONGO_ZEND_OBJECT_PRE
111117
mongoc_write_concern_t *write_concern;

src/MongoDB/Manager.c

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -538,6 +538,42 @@ static PHP_METHOD(Manager, selectServer)
538538
}
539539
} /* }}} */
540540

541+
/* {{{ proto MongoDB\Driver\Session MongoDB\Driver\Manager::startSession([array $options = null])
542+
Returns a new client session */
543+
static PHP_METHOD(Manager, startSession)
544+
{
545+
php_phongo_manager_t *intern;
546+
zval *options = NULL;
547+
mongoc_session_opt_t *cs_opts = NULL;
548+
mongoc_client_session_t *cs;
549+
bson_error_t error;
550+
SUPPRESS_UNUSED_WARNING(return_value_ptr) SUPPRESS_UNUSED_WARNING(return_value_used)
551+
552+
553+
intern = Z_MANAGER_OBJ_P(getThis());
554+
555+
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|a!", &options) == FAILURE) {
556+
return;
557+
}
558+
559+
if (options && php_array_exists(options, "causalConsistency")) {
560+
cs_opts = mongoc_session_opts_new();
561+
mongoc_session_opts_set_causal_consistency(cs_opts, php_array_fetchc_bool(options, "causalConsistency"));
562+
}
563+
564+
cs = mongoc_client_start_session(intern->client, cs_opts, &error);
565+
566+
if (cs_opts) {
567+
mongoc_session_opts_destroy(cs_opts);
568+
}
569+
570+
if (cs) {
571+
phongo_session_init(return_value, cs TSRMLS_CC);
572+
} else {
573+
phongo_throw_exception_from_bson_error_t(&error TSRMLS_CC);
574+
}
575+
} /* }}} */
576+
541577
/* {{{ MongoDB\Driver\Manager function entries */
542578
ZEND_BEGIN_ARG_INFO_EX(ai_Manager___construct, 0, 0, 0)
543579
ZEND_ARG_INFO(0, uri)
@@ -573,6 +609,10 @@ ZEND_BEGIN_ARG_INFO_EX(ai_Manager_selectServer, 0, 0, 1)
573609
ZEND_ARG_OBJ_INFO(0, readPreference, MongoDB\\Driver\\ReadPreference, 1)
574610
ZEND_END_ARG_INFO()
575611

612+
ZEND_BEGIN_ARG_INFO_EX(ai_Manager_startSession, 0, 0, 0)
613+
ZEND_ARG_ARRAY_INFO(0, options, 1)
614+
ZEND_END_ARG_INFO()
615+
576616
ZEND_BEGIN_ARG_INFO_EX(ai_Manager_void, 0, 0, 0)
577617
ZEND_END_ARG_INFO()
578618

@@ -589,6 +629,7 @@ static zend_function_entry php_phongo_manager_me[] = {
589629
PHP_ME(Manager, getServers, ai_Manager_void, ZEND_ACC_PUBLIC|ZEND_ACC_FINAL)
590630
PHP_ME(Manager, getWriteConcern, ai_Manager_void, ZEND_ACC_PUBLIC|ZEND_ACC_FINAL)
591631
PHP_ME(Manager, selectServer, ai_Manager_selectServer, ZEND_ACC_PUBLIC|ZEND_ACC_FINAL)
632+
PHP_ME(Manager, startSession, ai_Manager_startSession, ZEND_ACC_PUBLIC|ZEND_ACC_FINAL)
592633
ZEND_NAMED_ME(__wakeup, PHP_FN(MongoDB_disabled___wakeup), ai_Manager_void, ZEND_ACC_PUBLIC|ZEND_ACC_FINAL)
593634
PHP_FE_END
594635
};

0 commit comments

Comments
 (0)