Skip to content

Commit 9fd1dc8

Browse files
committed
Merge branch 'v1.5' and add check for Session::isInTransaction
2 parents 70204c9 + 1ded6fb commit 9fd1dc8

File tree

4 files changed

+171
-5
lines changed

4 files changed

+171
-5
lines changed

src/MongoDB/Session.c

Lines changed: 31 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,12 @@
2929

3030
zend_class_entry* php_phongo_session_ce;
3131

32+
#define SESSION_CHECK_LIVELINESS(i,m) \
33+
if (!(i)->client_session) { \
34+
phongo_throw_exception(PHONGO_ERROR_LOGIC TSRMLS_CC, "Cannot call '%s', as the session has already been ended.", (m)); \
35+
return; \
36+
}
37+
3238
static bool php_phongo_session_get_timestamp_parts(zval* obj, uint32_t* timestamp, uint32_t* increment TSRMLS_DC)
3339
{
3440
bool retval = false;
@@ -95,6 +101,7 @@ static PHP_METHOD(Session, advanceClusterTime)
95101
SUPPRESS_UNUSED_WARNING(return_value_used)
96102

97103
intern = Z_SESSION_OBJ_P(getThis());
104+
SESSION_CHECK_LIVELINESS(intern, "advanceClusterTime")
98105

99106
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "A", &zcluster_time) == FAILURE) {
100107
return;
@@ -125,6 +132,7 @@ static PHP_METHOD(Session, advanceOperationTime)
125132
SUPPRESS_UNUSED_WARNING(return_value_used)
126133

127134
intern = Z_SESSION_OBJ_P(getThis());
135+
SESSION_CHECK_LIVELINESS(intern, "advanceOperationTime")
128136

129137
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O", &ztimestamp, php_phongo_timestamp_interface_ce) == FAILURE) {
130138
return;
@@ -148,6 +156,7 @@ static PHP_METHOD(Session, getClusterTime)
148156
SUPPRESS_UNUSED_WARNING(return_value_used)
149157

150158
intern = Z_SESSION_OBJ_P(getThis());
159+
SESSION_CHECK_LIVELINESS(intern, "getClusterTime")
151160

152161
if (zend_parse_parameters_none() == FAILURE) {
153162
return;
@@ -183,6 +192,7 @@ static PHP_METHOD(Session, getLogicalSessionId)
183192
SUPPRESS_UNUSED_WARNING(return_value_used)
184193

185194
intern = Z_SESSION_OBJ_P(getThis());
195+
SESSION_CHECK_LIVELINESS(intern, "getLogicalSessionId")
186196

187197
if (zend_parse_parameters_none() == FAILURE) {
188198
return;
@@ -213,6 +223,7 @@ static PHP_METHOD(Session, getOperationTime)
213223
SUPPRESS_UNUSED_WARNING(return_value_used)
214224

215225
intern = Z_SESSION_OBJ_P(getThis());
226+
SESSION_CHECK_LIVELINESS(intern, "getOperationTime")
216227

217228
if (zend_parse_parameters_none() == FAILURE) {
218229
return;
@@ -310,6 +321,7 @@ static PHP_METHOD(Session, startTransaction)
310321
SUPPRESS_UNUSED_WARNING(return_value_used)
311322

312323
intern = Z_SESSION_OBJ_P(getThis());
324+
SESSION_CHECK_LIVELINESS(intern, "startTransaction")
313325

314326
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|a", &options) == FAILURE) {
315327
return;
@@ -342,6 +354,7 @@ static PHP_METHOD(Session, commitTransaction)
342354
SUPPRESS_UNUSED_WARNING(return_value_used)
343355

344356
intern = Z_SESSION_OBJ_P(getThis());
357+
SESSION_CHECK_LIVELINESS(intern, "commitTransaction")
345358

346359
if (zend_parse_parameters_none() == FAILURE) {
347360
return;
@@ -363,6 +376,7 @@ static PHP_METHOD(Session, abortTransaction)
363376
SUPPRESS_UNUSED_WARNING(return_value_used)
364377

365378
intern = Z_SESSION_OBJ_P(getThis());
379+
SESSION_CHECK_LIVELINESS(intern, "abortTransaction")
366380

367381
if (zend_parse_parameters_none() == FAILURE) {
368382
return;
@@ -388,6 +402,7 @@ static PHP_METHOD(Session, endSession)
388402
}
389403

390404
mongoc_client_session_destroy(intern->client_session);
405+
intern->client_session = NULL;
391406
} /* }}} */
392407

393408
/* {{{ proto void MongoDB\Driver\Session::isInTransaction(void)
@@ -399,6 +414,7 @@ static PHP_METHOD(Session, isInTransaction)
399414
SUPPRESS_UNUSED_WARNING(return_value_used)
400415

401416
intern = Z_SESSION_OBJ_P(getThis());
417+
SESSION_CHECK_LIVELINESS(intern, "isInTransaction")
402418

403419
if (zend_parse_parameters_none() == FAILURE) {
404420
return;
@@ -496,7 +512,7 @@ static HashTable* php_phongo_session_get_debug_info(zval* object, int* is_temp T
496512

497513
array_init(&retval);
498514

499-
{
515+
if (intern->client_session) {
500516
const bson_t* lsid;
501517

502518
php_phongo_bson_state state = PHONGO_BSON_STATE_INITIALIZER;
@@ -513,9 +529,11 @@ static HashTable* php_phongo_session_get_debug_info(zval* object, int* is_temp T
513529
#else
514530
ADD_ASSOC_ZVAL_EX(&retval, "logicalSessionId", state.zchild);
515531
#endif
532+
} else {
533+
ADD_ASSOC_NULL_EX(&retval, "logicalSessionId");
516534
}
517535

518-
{
536+
if (intern->client_session) {
519537
const bson_t* cluster_time;
520538

521539
php_phongo_bson_state state = PHONGO_BSON_STATE_INITIALIZER;
@@ -536,12 +554,18 @@ static HashTable* php_phongo_session_get_debug_info(zval* object, int* is_temp T
536554
} else {
537555
ADD_ASSOC_NULL_EX(&retval, "clusterTime");
538556
}
557+
} else {
558+
ADD_ASSOC_NULL_EX(&retval, "clusterTime");
539559
}
540560

541-
cs_opts = mongoc_client_session_get_opts(intern->client_session);
542-
ADD_ASSOC_BOOL_EX(&retval, "causalConsistency", mongoc_session_opts_get_causal_consistency(cs_opts));
561+
if (intern->client_session) {
562+
cs_opts = mongoc_client_session_get_opts(intern->client_session);
563+
ADD_ASSOC_BOOL_EX(&retval, "causalConsistency", mongoc_session_opts_get_causal_consistency(cs_opts));
564+
} else {
565+
ADD_ASSOC_NULL_EX(&retval, "causalConsistency");
566+
}
543567

544-
{
568+
if (intern->client_session) {
545569
uint32_t timestamp, increment;
546570

547571
mongoc_client_session_get_operation_time(intern->client_session, &timestamp, &increment);
@@ -562,6 +586,8 @@ static HashTable* php_phongo_session_get_debug_info(zval* object, int* is_temp T
562586
} else {
563587
ADD_ASSOC_NULL_EX(&retval, "operationTime");
564588
}
589+
} else {
590+
ADD_ASSOC_NULL_EX(&retval, "operationTime");
565591
}
566592

567593
return Z_ARRVAL(retval);

tests/session/session-debug-004.phpt

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
--TEST--
2+
MongoDB\Driver\Session debug output (after ending session)
3+
--SKIPIF--
4+
<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
5+
<?php skip_if_not_libmongoc_crypto(); ?>
6+
<?php skip_if_not_live(); ?>
7+
<?php skip_if_server_version('<', '3.6'); ?>
8+
--FILE--
9+
<?php
10+
require_once __DIR__ . "/../utils/basic.inc";
11+
12+
$manager = new MongoDB\Driver\Manager(URI);
13+
$session = $manager->startSession();
14+
15+
$command = new MongoDB\Driver\Command(['ping' => 1]);
16+
$manager->executeCommand(DATABASE_NAME, $command, ['session' => $session]);
17+
18+
$session->endSession();
19+
20+
var_dump($session);
21+
22+
?>
23+
===DONE===
24+
<?php exit(0); ?>
25+
--EXPECTF--
26+
object(MongoDB\Driver\Session)#%d (%d) {
27+
["logicalSessionId"]=>
28+
NULL
29+
["clusterTime"]=>
30+
NULL
31+
["causalConsistency"]=>
32+
NULL
33+
["operationTime"]=>
34+
NULL
35+
}
36+
===DONE===
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
--TEST--
2+
MongoDB\Driver\Session::endSession() Calling methods after session has been ended
3+
--SKIPIF--
4+
<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
5+
<?php skip_if_not_replica_set(); ?>
6+
<?php skip_if_server_version('<', '4.0'); ?>
7+
--FILE--
8+
<?php
9+
require_once __DIR__ . "/../utils/basic.inc";
10+
11+
$manager = new MongoDB\Driver\Manager(URI);
12+
13+
$sessionA = $manager->startSession();
14+
$sessionA->endSession();
15+
16+
echo throws(function() use ($sessionA) {
17+
$sessionA->startTransaction();
18+
}, 'MongoDB\Driver\Exception\LogicException'), "\n";
19+
20+
echo throws(function() use ($sessionA) {
21+
$sessionA->abortTransaction();
22+
}, 'MongoDB\Driver\Exception\LogicException'), "\n";
23+
24+
/* The reason that startTransaction is in here twice is that this script can run without exception
25+
* if the endSession() call is taken out. */
26+
echo throws(function() use ($sessionA) {
27+
$sessionA->startTransaction();
28+
}, 'MongoDB\Driver\Exception\LogicException'), "\n";
29+
30+
echo throws(function() use ($sessionA) {
31+
$sessionA->commitTransaction();
32+
}, 'MongoDB\Driver\Exception\LogicException'), "\n";
33+
34+
echo throws(function() use ($sessionA) {
35+
$sessionA->advanceOperationTime(new \MongoDB\BSON\Timestamp(1900123000, 1900123000));
36+
}, 'MongoDB\Driver\Exception\LogicException'), "\n";
37+
38+
echo throws(function() use ($sessionA) {
39+
$sessionA->advanceClusterTime([]);
40+
}, 'MongoDB\Driver\Exception\LogicException'), "\n";
41+
42+
echo throws(function() use ($sessionA) {
43+
var_dump($sessionA->getClusterTime());
44+
}, 'MongoDB\Driver\Exception\LogicException'), "\n";
45+
46+
echo throws(function() use ($sessionA) {
47+
var_dump($sessionA->getLogicalSessionId());
48+
}, 'MongoDB\Driver\Exception\LogicException'), "\n";
49+
50+
echo throws(function() use ($sessionA) {
51+
var_dump($sessionA->getOperationTime());
52+
}, 'MongoDB\Driver\Exception\LogicException'), "\n";
53+
54+
echo throws(function() use ($sessionA) {
55+
$sessionA->isInTransaction();
56+
}, 'MongoDB\Driver\Exception\LogicException'), "\n";
57+
58+
?>
59+
===DONE===
60+
<?php exit(0); ?>
61+
--EXPECT--
62+
OK: Got MongoDB\Driver\Exception\LogicException
63+
Cannot call 'startTransaction', as the session has already been ended.
64+
OK: Got MongoDB\Driver\Exception\LogicException
65+
Cannot call 'abortTransaction', as the session has already been ended.
66+
OK: Got MongoDB\Driver\Exception\LogicException
67+
Cannot call 'startTransaction', as the session has already been ended.
68+
OK: Got MongoDB\Driver\Exception\LogicException
69+
Cannot call 'commitTransaction', as the session has already been ended.
70+
OK: Got MongoDB\Driver\Exception\LogicException
71+
Cannot call 'advanceOperationTime', as the session has already been ended.
72+
OK: Got MongoDB\Driver\Exception\LogicException
73+
Cannot call 'advanceClusterTime', as the session has already been ended.
74+
OK: Got MongoDB\Driver\Exception\LogicException
75+
Cannot call 'getClusterTime', as the session has already been ended.
76+
OK: Got MongoDB\Driver\Exception\LogicException
77+
Cannot call 'getLogicalSessionId', as the session has already been ended.
78+
OK: Got MongoDB\Driver\Exception\LogicException
79+
Cannot call 'getOperationTime', as the session has already been ended.
80+
OK: Got MongoDB\Driver\Exception\LogicException
81+
Cannot call 'isInTransaction', as the session has already been ended.
82+
===DONE===
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
--TEST--
2+
MongoDB\Driver\Session::endSession() Calling method multiple times
3+
--SKIPIF--
4+
<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
5+
<?php skip_if_not_libmongoc_crypto(); ?>
6+
<?php skip_if_not_live(); ?>
7+
<?php skip_if_server_version('<', '3.6'); ?>
8+
--FILE--
9+
<?php
10+
require_once __DIR__ . "/../utils/basic.inc";
11+
12+
$manager = new MongoDB\Driver\Manager(URI);
13+
14+
$sessionA = $manager->startSession();
15+
$sessionA->endSession();
16+
$sessionA->endSession();
17+
$sessionA->endSession();
18+
?>
19+
===DONE===
20+
<?php exit(0); ?>
21+
--EXPECT--
22+
===DONE===

0 commit comments

Comments
 (0)