Skip to content

[WAIT] PHPC-1274: Add function to reset manager instance #1027

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

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions config.m4
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,7 @@ if test "$PHP_MONGODB" != "no"; then
src/MongoDB/Monitoring/CommandSucceededEvent.c \
src/MongoDB/Monitoring/Subscriber.c \
src/MongoDB/Monitoring/functions.c \
src/MongoDB/functions.c \
"

PHP_ARG_WITH([libbson],
Expand Down
2 changes: 1 addition & 1 deletion config.w32
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ if (PHP_MONGODB != "no") {
EXTENSION("mongodb", "php_phongo.c phongo_compat.c", null, PHP_MONGODB_CFLAGS);
ADD_SOURCES(configure_module_dirname + "/src", "bson.c bson-encode.c", "mongodb");
ADD_SOURCES(configure_module_dirname + "/src/BSON", "Binary.c BinaryInterface.c DBPointer.c Decimal128.c Decimal128Interface.c Int64.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");
ADD_SOURCES(configure_module_dirname + "/src/MongoDB", "BulkWrite.c Command.c Cursor.c CursorId.c CursorInterface.c Manager.c Query.c ReadConcern.c ReadPreference.c Server.c Session.c WriteConcern.c WriteConcernError.c WriteError.c WriteResult.c", "mongodb");
ADD_SOURCES(configure_module_dirname + "/src/MongoDB", "BulkWrite.c Command.c Cursor.c CursorId.c CursorInterface.c Manager.c Query.c ReadConcern.c ReadPreference.c Server.c Session.c WriteConcern.c WriteConcernError.c WriteError.c WriteResult.c functions.c", "mongodb");
ADD_SOURCES(configure_module_dirname + "/src/MongoDB/Exception", "AuthenticationException.c BulkWriteException.c CommandException.c ConnectionException.c ConnectionTimeoutException.c Exception.c ExecutionTimeoutException.c InvalidArgumentException.c LogicException.c RuntimeException.c ServerException.c SSLConnectionException.c UnexpectedValueException.c WriteException.c", "mongodb");
ADD_SOURCES(configure_module_dirname + "/src/MongoDB/Monitoring", "CommandFailedEvent.c CommandStartedEvent.c CommandSubscriber.c CommandSucceededEvent.c Subscriber.c functions.c", "mongodb");
ADD_SOURCES(configure_module_dirname + "/src/libmongoc/src/common", PHP_MONGODB_COMMON_SOURCES, "mongodb");
Expand Down
8 changes: 7 additions & 1 deletion php_phongo.c
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@
#include "php_phongo.h"
#include "php_bson.h"
#include "src/BSON/functions.h"
#include "src/MongoDB/functions.h"
#include "src/MongoDB/Monitoring/functions.h"

#undef MONGOC_LOG_DOMAIN
Expand Down Expand Up @@ -3344,6 +3345,10 @@ ZEND_BEGIN_ARG_INFO_EX(ai_mongodb_driver_monitoring_subscriber, 0, 0, 1)
ZEND_ARG_OBJ_INFO(0, subscriber, MongoDB\\Driver\\Monitoring\\Subscriber, 0)
ZEND_END_ARG_INFO();

ZEND_BEGIN_ARG_INFO_EX(ai_mongodb_driver_manager, 0, 0, 1)
ZEND_ARG_OBJ_INFO(0, manager, MongoDB\\Driver\\Manager, 0)
ZEND_END_ARG_INFO();

static const zend_function_entry mongodb_functions[] = {
ZEND_NS_NAMED_FE("MongoDB\\BSON", fromPHP, PHP_FN(MongoDB_BSON_fromPHP), ai_bson_fromPHP)
ZEND_NS_NAMED_FE("MongoDB\\BSON", toPHP, PHP_FN(MongoDB_BSON_toPHP), ai_bson_toPHP)
Expand All @@ -3353,7 +3358,8 @@ static const zend_function_entry mongodb_functions[] = {
ZEND_NS_NAMED_FE("MongoDB\\BSON", fromJSON, PHP_FN(MongoDB_BSON_fromJSON), ai_bson_fromJSON)
ZEND_NS_NAMED_FE("MongoDB\\Driver\\Monitoring", addSubscriber, PHP_FN(MongoDB_Driver_Monitoring_addSubscriber), ai_mongodb_driver_monitoring_subscriber)
ZEND_NS_NAMED_FE("MongoDB\\Driver\\Monitoring", removeSubscriber, PHP_FN(MongoDB_Driver_Monitoring_removeSubscriber), ai_mongodb_driver_monitoring_subscriber)
PHP_FE_END
ZEND_NS_NAMED_FE("MongoDB\\Driver", reset, PHP_FN(MongoDB_Driver_reset), ai_mongodb_driver_manager)
PHP_FE_END
};
/* }}} */

Expand Down
50 changes: 50 additions & 0 deletions src/MongoDB/functions.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
/*
* Copyright 2019 MongoDB, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#include <php.h>

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include "phongo_compat.h"
#include "php_phongo.h"

ZEND_EXTERN_MODULE_GLOBALS(mongodb)

/* {{{ proto void MongoDB\Driver\reset(MongoDB\Driver\Manager $manager)
Resets a manager after forking */
PHP_FUNCTION(MongoDB_Driver_reset)
{
zval* zManager = NULL;
php_phongo_manager_t* intern;

if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O", &zManager, php_phongo_manager_ce) == FAILURE) {
return;
}

intern = Z_MANAGER_OBJ_P(zManager);
mongoc_client_reset(intern->client);
} /* }}} */

/*
* Local variables:
* tab-width: 4
* c-basic-offset: 4
* End:
* vim600: noet sw=4 ts=4 fdm=marker
* vim<600: noet sw=4 ts=4
*/
33 changes: 33 additions & 0 deletions src/MongoDB/functions.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/*
* Copyright 2019 MongoDB, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#ifndef PHONGO_FUNCTIONS_H
#define PHONGO_FUNCTIONS_H

#include <php.h>

PHP_FUNCTION(MongoDB_Driver_reset);

#endif /* PHONGO_FUNCTIONS_H */

/*
* Local variables:
* tab-width: 4
* c-basic-offset: 4
* End:
* vim600: noet sw=4 ts=4 fdm=marker
* vim<600: noet sw=4 ts=4
*/
78 changes: 78 additions & 0 deletions tests/manager/manager-reset-001.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
--TEST--
MongoDB\Driver\reset: Cursor destruct should not kill cursor from parent process
--SKIPIF--
<?php if (!function_exists('pcntl_fork')) { die('skip pcntl_fork() not available'); } ?>
<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
<?php skip_if_not_live(); ?>
<?php skip_if_not_clean(); ?>
<?php skip_if_ssl(); ?>
--FILE--
<?php
require_once __DIR__ . "/../utils/basic.inc";

class CommandLogger implements MongoDB\Driver\Monitoring\CommandSubscriber
{
public function commandStarted(MongoDB\Driver\Monitoring\CommandStartedEvent $event)
{
$command = $event->getCommand();

if ($event->getCommandName() === 'find') {
printf("find command specifies batchSize: %d\n", $command->batchSize);
}

if ($event->getCommandName() === 'getMore') {
printf("getMore command specifies batchSize: %d\n", $command->batchSize);
}
}

public function commandSucceeded(MongoDB\Driver\Monitoring\CommandSucceededEvent $event)
{
}

public function commandFailed(MongoDB\Driver\Monitoring\CommandFailedEvent $event)
{
}
}

MongoDB\Driver\Monitoring\addSubscriber(new CommandLogger);

$manager = new MongoDB\Driver\Manager(URI);

$bulk = new MongoDB\Driver\BulkWrite();
$bulk->insert(['x' => 1]);
$bulk->insert(['x' => 2]);
$bulk->insert(['x' => 3]);
$manager->executeBulkWrite(NS, $bulk);

$query = new MongoDB\Driver\Query([], ['batchSize' => 2]);
$cursor = $manager->executeQuery(NS, $query);

$parentPid = getmypid();
$childPid = pcntl_fork();

if ($childPid === 0) {
MongoDB\Driver\reset($manager);
echo "Child exits\n";
exit;
}

if ($childPid > 0) {
$waitPid = pcntl_waitpid($childPid, $status);

if ($waitPid === $childPid) {
echo "Parent waited for child to exit\n";
}

printf("Parent fully iterated cursor for %d documents\n", iterator_count($cursor));
}

?>
===DONE===
<?php exit(0); ?>
--EXPECT--
find command specifies batchSize: 2
Child exits
Parent waited for child to exit
getMore command specifies batchSize: 2
Parent fully iterated cursor for 3 documents
===DONE===
83 changes: 83 additions & 0 deletions tests/manager/manager-reset-002.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
--TEST--
MongoDB\Driver\reset: Child process cannot iterate cursor from parent process
--SKIPIF--
<?php if (!function_exists('pcntl_fork')) { die('skip pcntl_fork() not available'); } ?>
<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
<?php skip_if_not_live(); ?>
<?php skip_if_not_clean(); ?>
<?php skip_if_ssl(); ?>
--FILE--
<?php
require_once __DIR__ . "/../utils/basic.inc";

class CommandLogger implements MongoDB\Driver\Monitoring\CommandSubscriber
{
public function commandStarted(MongoDB\Driver\Monitoring\CommandStartedEvent $event)
{
$command = $event->getCommand();

if ($event->getCommandName() === 'find') {
printf("find command specifies batchSize: %d\n", $command->batchSize);
}

if ($event->getCommandName() === 'getMore') {
printf("getMore command specifies batchSize: %d\n", $command->batchSize);
}
}

public function commandSucceeded(MongoDB\Driver\Monitoring\CommandSucceededEvent $event)
{
}

public function commandFailed(MongoDB\Driver\Monitoring\CommandFailedEvent $event)
{
}
}

MongoDB\Driver\Monitoring\addSubscriber(new CommandLogger);

$manager = new MongoDB\Driver\Manager(URI);

$bulk = new MongoDB\Driver\BulkWrite();
$bulk->insert(['x' => 1]);
$bulk->insert(['x' => 2]);
$bulk->insert(['x' => 3]);
$manager->executeBulkWrite(NS, $bulk);

$query = new MongoDB\Driver\Query([], ['batchSize' => 2]);
$cursor = $manager->executeQuery(NS, $query);

$parentPid = getmypid();
$childPid = pcntl_fork();

if ($childPid === 0) {
MongoDB\Driver\reset($manager);
echo throws(function() use ($cursor) {
printf("Child fully iterated cursor for %d documents\n", iterator_count($cursor));
}, 'MongoDB\Driver\Exception\RuntimeException'), "\n";
echo "Child exits\n";
exit;
}

if ($childPid > 0) {
$waitPid = pcntl_waitpid($childPid, $status);

if ($waitPid === $childPid) {
echo "Parent waited for child to exit\n";
}

printf("Parent fully iterated cursor for %d documents\n", iterator_count($cursor));
}

?>
===DONE===
<?php exit(0); ?>
--EXPECT--
find command specifies batchSize: 2
OK: Got MongoDB\Driver\Exception\RuntimeException
Cannot advance cursor after client reset
Child exits
Parent waited for child to exit
getMore command specifies batchSize: 2
Parent fully iterated cursor for 3 documents
===DONE===
82 changes: 82 additions & 0 deletions tests/manager/manager-reset-003.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
--TEST--
MongoDB\Driver\reset: Resetting a manager causes socket errors on SSL connections
--SKIPIF--
<?php if (!function_exists('pcntl_fork')) { die('skip pcntl_fork() not available'); } ?>
<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
<?php skip_if_not_live(); ?>
<?php skip_if_not_clean(); ?>
<?php skip_if_not_ssl(); ?>
--FILE--
<?php
require_once __DIR__ . "/../utils/basic.inc";

class CommandLogger implements MongoDB\Driver\Monitoring\CommandSubscriber
{
public function commandStarted(MongoDB\Driver\Monitoring\CommandStartedEvent $event)
{
$command = $event->getCommand();

if ($event->getCommandName() === 'find') {
printf("find command specifies batchSize: %d\n", $command->batchSize);
}

if ($event->getCommandName() === 'getMore') {
printf("getMore command specifies batchSize: %d\n", $command->batchSize);
}
}

public function commandSucceeded(MongoDB\Driver\Monitoring\CommandSucceededEvent $event)
{
}

public function commandFailed(MongoDB\Driver\Monitoring\CommandFailedEvent $event)
{
}
}

MongoDB\Driver\Monitoring\addSubscriber(new CommandLogger);

$manager = new MongoDB\Driver\Manager(URI);

$bulk = new MongoDB\Driver\BulkWrite();
$bulk->insert(['x' => 1]);
$bulk->insert(['x' => 2]);
$bulk->insert(['x' => 3]);
$manager->executeBulkWrite(NS, $bulk);

$query = new MongoDB\Driver\Query([], ['batchSize' => 2]);
$cursor = $manager->executeQuery(NS, $query);

$parentPid = getmypid();
$childPid = pcntl_fork();

if ($childPid === 0) {
MongoDB\Driver\reset($manager);

echo "Child exits\n";
exit;
}

if ($childPid > 0) {
$waitPid = pcntl_waitpid($childPid, $status);

if ($waitPid === $childPid) {
echo "Parent waited for child to exit\n";
}

echo throws(function () use ($cursor) {
iterator_count($cursor);
}, MongoDB\Driver\Exception\ConnectionTimeoutException::class), "\n";
}

?>
===DONE===
<?php exit(0); ?>
--EXPECTF--
find command specifies batchSize: 2
Child exits
Parent waited for child to exit
getMore command specifies batchSize: 2
OK: Got MongoDB\Driver\Exception\ConnectionTimeoutException
Failed to send "getMore" command with database "%s": Failed to read 4 bytes: socket error or timeout
===DONE===
Loading