Skip to content

PHPC-1057: Refactor option parsing for execute methods #707

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

Merged
merged 4 commits into from
Dec 18, 2017
Merged
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
379 changes: 200 additions & 179 deletions php_phongo.c

Large diffs are not rendered by default.

32 changes: 20 additions & 12 deletions php_phongo.h
Original file line number Diff line number Diff line change
Expand Up @@ -112,35 +112,43 @@ void phongo_throw_exception(php_phongo_error_domain_t domain TSRMLS_DC, const ch
;
void phongo_throw_exception_from_bson_error_t(bson_error_t *error TSRMLS_DC);

/* This enum is used for libmongoc function selection for the
* phongo_execute_command types. The values are important, as the READ and
* WRITE fields are also used as a bit field to see whether ReadPreference,
* ReadConcern, and WriteConcern are supported for each type. */
/* This enum is used for processing options in phongo_execute_parse_options and
* selecting a libmongoc function to use in phongo_execute_command. The values
* are important, as READ and WRITE are also used as a bit field to determine
* whether readPreference, readConcern, and writeConcern options are parsed. */
typedef enum {
PHONGO_COMMAND_RAW = 0x13,
PHONGO_COMMAND_READ = 0x01,
PHONGO_COMMAND_WRITE = 0x02,
PHONGO_COMMAND_READ_WRITE = 0x03
PHONGO_OPTION_READ_CONCERN = 0x01,
PHONGO_OPTION_READ_PREFERENCE = 0x02,
PHONGO_OPTION_WRITE_CONCERN = 0x04,
PHONGO_COMMAND_RAW = 0x07,
PHONGO_COMMAND_READ = 0x03,
PHONGO_COMMAND_WRITE = 0x04,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are you sure you can have duplicate enum values?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PHONGO_COMMAND_READ_WRITE = 0x05,
} php_phongo_command_type_t;

zend_object_handlers *phongo_get_std_object_handlers(void);

void phongo_server_init (zval *return_value, mongoc_client_t *client, int server_id TSRMLS_DC);
void phongo_server_init (zval *return_value, mongoc_client_t *client, uint32_t server_id TSRMLS_DC);
void phongo_session_init (zval *return_value, mongoc_client_session_t *client_session TSRMLS_DC);
void phongo_readconcern_init (zval *return_value, const mongoc_read_concern_t *read_concern TSRMLS_DC);
void phongo_readpreference_init (zval *return_value, const mongoc_read_prefs_t *read_prefs TSRMLS_DC);
void phongo_writeconcern_init (zval *return_value, const mongoc_write_concern_t *write_concern TSRMLS_DC);
mongoc_bulk_operation_t* phongo_bulkwrite_init (zend_bool ordered);
bool phongo_execute_bulk_write (mongoc_client_t *client, const char *namespace, php_phongo_bulkwrite_t *bulk_write, zval *zwriteConcern, int server_id, zval *return_value, int return_value_used TSRMLS_DC);
int phongo_execute_command (mongoc_client_t *client, php_phongo_command_type_t type, const char *db, zval *zcommand, zval *zreadPreference, int server_id, zval *return_value, int return_value_used TSRMLS_DC);
int phongo_execute_query (mongoc_client_t *client, const char *namespace, zval *zquery, zval *zreadPreference, int server_id, zval *return_value, int return_value_used TSRMLS_DC);
bool phongo_execute_bulk_write (mongoc_client_t *client, const char *namespace, php_phongo_bulkwrite_t *bulk_write, zval *zwriteConcern, uint32_t server_id, zval *return_value, int return_value_used TSRMLS_DC);
int phongo_execute_command (mongoc_client_t *client, php_phongo_command_type_t type, const char *db, zval *zcommand, zval *zreadPreference, uint32_t server_id, zval *return_value, int return_value_used TSRMLS_DC);
int phongo_execute_query (mongoc_client_t *client, const char *namespace, zval *zquery, zval *zreadPreference, uint32_t server_id, zval *return_value, int return_value_used TSRMLS_DC);

const mongoc_read_concern_t* phongo_read_concern_from_zval (zval *zread_concern TSRMLS_DC);
const mongoc_read_prefs_t* phongo_read_preference_from_zval(zval *zread_preference TSRMLS_DC);
const mongoc_write_concern_t* phongo_write_concern_from_zval (zval *zwrite_concern TSRMLS_DC);

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);

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);

void php_phongo_read_preference_prep_tagsets(zval *tagSets TSRMLS_DC);
bool php_phongo_read_preference_tags_are_valid(const bson_t *tags);

Expand Down
6 changes: 3 additions & 3 deletions php_phongo_structs.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ typedef struct {
PHONGO_ZEND_OBJECT_PRE
mongoc_cursor_t *cursor;
mongoc_client_t *client;
int server_id;
uint32_t server_id;
php_phongo_bson_state visitor_data;
int got_iterator;
long current;
Expand Down Expand Up @@ -102,7 +102,7 @@ typedef struct {
typedef struct {
PHONGO_ZEND_OBJECT_PRE
mongoc_client_t *client;
int server_id;
uint32_t server_id;
PHONGO_ZEND_OBJECT_POST
} php_phongo_server_t;

Expand Down Expand Up @@ -140,7 +140,7 @@ typedef struct {
mongoc_write_concern_t *write_concern;
bson_t *reply;
mongoc_client_t *client;
int server_id;
uint32_t server_id;
PHONGO_ZEND_OBJECT_POST
} php_phongo_writeresult_t;

Expand Down
147 changes: 125 additions & 22 deletions src/MongoDB/Manager.c
Original file line number Diff line number Diff line change
Expand Up @@ -242,6 +242,40 @@ static void php_phongo_manager_prep_uri_options(zval *options TSRMLS_DC) /* {{{
return;
} /* }}} */

/* 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.
*
* 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) /* {{{ */
{
const mongoc_read_prefs_t *read_preference = NULL;
mongoc_server_description_t *selected_server;
bson_error_t error;

if (!for_writes) {
read_preference = zreadPreference ? phongo_read_preference_from_zval(zreadPreference TSRMLS_CC) : mongoc_client_get_read_prefs(client);
}

selected_server = mongoc_client_select_server(client, for_writes, read_preference, &error);

if (selected_server) {
*server_id = mongoc_server_description_id(selected_server);
mongoc_server_description_destroy(selected_server);

return true;
}

/* Check for connection related exceptions */
if (!EG(exception)) {
phongo_throw_exception_from_bson_error_t(&error TSRMLS_CC);
}

return false;
} /* }}} */

/* {{{ proto void MongoDB\Driver\Manager::__construct([string $uri = "mongodb://127.0.0.1/"[, array $options = array()[, array $driverOptions = array()]]])
Constructs a new Manager */
static PHP_METHOD(Manager, __construct)
Expand Down Expand Up @@ -292,6 +326,9 @@ static PHP_METHOD(Manager, executeCommand)
phongo_zpp_char_len db_len;
zval *command;
zval *options = NULL;
bool free_options = false;
zval *zreadPreference = NULL;
uint32_t server_id = 0;
DECLARE_RETURN_VALUE_USED
SUPPRESS_UNUSED_WARNING(return_value_ptr)

Expand All @@ -301,7 +338,24 @@ static PHP_METHOD(Manager, executeCommand)

intern = Z_MANAGER_OBJ_P(getThis());

phongo_execute_command(intern->client, PHONGO_COMMAND_RAW, db, command, options, -1, return_value, return_value_used TSRMLS_CC);
options = php_phongo_prep_legacy_option(options, "readPreference", &free_options TSRMLS_CC);

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)) {
/* Exception should already have been thrown */
goto cleanup;
}

phongo_execute_command(intern->client, PHONGO_COMMAND_RAW, db, command, options, server_id, return_value, return_value_used TSRMLS_CC);

cleanup:
if (free_options) {
php_phongo_prep_legacy_option_free(options TSRMLS_CC);
}
} /* }}} */

/* {{{ proto MongoDB\Driver\Cursor MongoDB\Driver\Manager::executeReadCommand(string $db, MongoDB\Driver\Command $command[, array $options = null])
Expand All @@ -313,6 +367,8 @@ static PHP_METHOD(Manager, executeReadCommand)
phongo_zpp_char_len db_len;
zval *command;
zval *options = NULL;
zval *zreadPreference = NULL;
uint32_t server_id = 0;
DECLARE_RETURN_VALUE_USED
SUPPRESS_UNUSED_WARNING(return_value_ptr)

Expand All @@ -322,7 +378,17 @@ static PHP_METHOD(Manager, executeReadCommand)

intern = Z_MANAGER_OBJ_P(getThis());

phongo_execute_command(intern->client, PHONGO_COMMAND_READ, db, command, options, -1, return_value, return_value_used TSRMLS_CC);
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)) {
/* Exception should already have been thrown */
return;
}

phongo_execute_command(intern->client, PHONGO_COMMAND_READ, db, command, options, server_id, return_value, return_value_used TSRMLS_CC);
} /* }}} */

/* {{{ proto MongoDB\Driver\Cursor MongoDB\Driver\Manager::executeWriteCommand(string $db, MongoDB\Driver\Command $command[, array $options = null])
Expand All @@ -334,6 +400,7 @@ static PHP_METHOD(Manager, executeWriteCommand)
phongo_zpp_char_len db_len;
zval *command;
zval *options = NULL;
uint32_t server_id = 0;
DECLARE_RETURN_VALUE_USED
SUPPRESS_UNUSED_WARNING(return_value_ptr)

Expand All @@ -343,7 +410,12 @@ static PHP_METHOD(Manager, executeWriteCommand)

intern = Z_MANAGER_OBJ_P(getThis());

phongo_execute_command(intern->client, PHONGO_COMMAND_WRITE, db, command, options, -1, return_value, return_value_used TSRMLS_CC);
if (!php_phongo_manager_select_server(true, NULL, intern->client, &server_id TSRMLS_CC)) {
/* Exception should already have been thrown */
return;
}

phongo_execute_command(intern->client, PHONGO_COMMAND_WRITE, db, command, options, server_id, return_value, return_value_used TSRMLS_CC);
} /* }}} */

/* {{{ proto MongoDB\Driver\Cursor MongoDB\Driver\Manager::executeReadWriteCommand(string $db, MongoDB\Driver\Command $command[, array $options = null])
Expand All @@ -355,6 +427,7 @@ static PHP_METHOD(Manager, executeReadWriteCommand)
phongo_zpp_char_len db_len;
zval *command;
zval *options = NULL;
uint32_t server_id = 0;
DECLARE_RETURN_VALUE_USED
SUPPRESS_UNUSED_WARNING(return_value_ptr)

Expand All @@ -364,7 +437,12 @@ static PHP_METHOD(Manager, executeReadWriteCommand)

intern = Z_MANAGER_OBJ_P(getThis());

phongo_execute_command(intern->client, PHONGO_COMMAND_READ_WRITE, db, command, options, -1, return_value, return_value_used TSRMLS_CC);
if (!php_phongo_manager_select_server(true, NULL, intern->client, &server_id TSRMLS_CC)) {
/* Exception should already have been thrown */
return;
}

phongo_execute_command(intern->client, PHONGO_COMMAND_READ_WRITE, db, command, options, server_id, return_value, return_value_used TSRMLS_CC);
} /* }}} */

/* {{{ proto MongoDB\Driver\Cursor MongoDB\Driver\Manager::executeQuery(string $namespace, MongoDB\Driver\Query $query[, array $options = null])
Expand All @@ -376,6 +454,9 @@ static PHP_METHOD(Manager, executeQuery)
phongo_zpp_char_len namespace_len;
zval *query;
zval *options = NULL;
bool free_options = false;
zval *zreadPreference = NULL;
uint32_t server_id = 0;
DECLARE_RETURN_VALUE_USED
SUPPRESS_UNUSED_WARNING(return_value_ptr)

Expand All @@ -385,7 +466,24 @@ static PHP_METHOD(Manager, executeQuery)

intern = Z_MANAGER_OBJ_P(getThis());

phongo_execute_query(intern->client, namespace, query, options, -1, return_value, return_value_used TSRMLS_CC);
options = php_phongo_prep_legacy_option(options, "readPreference", &free_options TSRMLS_CC);

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)) {
/* Exception should already have been thrown */
goto cleanup;
}

phongo_execute_query(intern->client, namespace, query, options, server_id, return_value, return_value_used TSRMLS_CC);

cleanup:
if (free_options) {
php_phongo_prep_legacy_option_free(options TSRMLS_CC);
}
} /* }}} */

/* {{{ proto MongoDB\Driver\WriteResult MongoDB\Driver\Manager::executeBulkWrite(string $namespace, MongoDB\Driver\BulkWrite $zbulk[, array $options = null])
Expand All @@ -396,8 +494,10 @@ static PHP_METHOD(Manager, executeBulkWrite)
char *namespace;
phongo_zpp_char_len namespace_len;
zval *zbulk;
zval *options = NULL;
php_phongo_bulkwrite_t *bulk;
zval *options = NULL;
bool free_options = false;
uint32_t server_id = 0;
DECLARE_RETURN_VALUE_USED
SUPPRESS_UNUSED_WARNING(return_value_ptr)

Expand All @@ -408,7 +508,19 @@ static PHP_METHOD(Manager, executeBulkWrite)
intern = Z_MANAGER_OBJ_P(getThis());
bulk = Z_BULKWRITE_OBJ_P(zbulk);

phongo_execute_bulk_write(intern->client, namespace, bulk, options, -1, return_value, return_value_used TSRMLS_CC);
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)) {
/* Exception should already have been thrown */
goto cleanup;
}

phongo_execute_bulk_write(intern->client, namespace, bulk, options, server_id, return_value, return_value_used TSRMLS_CC);

cleanup:
if (free_options) {
php_phongo_prep_legacy_option_free(options TSRMLS_CC);
}
} /* }}} */

/* {{{ proto MongoDB\Driver\ReadConcern MongoDB\Driver\Manager::getReadConcern()
Expand Down Expand Up @@ -511,9 +623,7 @@ static PHP_METHOD(Manager, selectServer)
{
php_phongo_manager_t *intern;
zval *zreadPreference = NULL;
const mongoc_read_prefs_t *readPreference;
bson_error_t error;
mongoc_server_description_t *selected_server = NULL;
uint32_t server_id = 0;
SUPPRESS_UNUSED_WARNING(return_value_ptr) SUPPRESS_UNUSED_WARNING(return_value_used)


Expand All @@ -523,19 +633,12 @@ static PHP_METHOD(Manager, selectServer)
return;
}

readPreference = phongo_read_preference_from_zval(zreadPreference TSRMLS_CC);
selected_server = mongoc_client_select_server(intern->client, false, readPreference, &error);
if (selected_server) {
phongo_server_init(return_value, intern->client, mongoc_server_description_id(selected_server) TSRMLS_CC);
mongoc_server_description_destroy(selected_server);
} else {
/* Check for connection related exceptions */
if (EG(exception)) {
return;
}

phongo_throw_exception_from_bson_error_t(&error TSRMLS_CC);
if (!php_phongo_manager_select_server(false, zreadPreference, intern->client, &server_id TSRMLS_CC)) {
/* Exception should already have been thrown */
return;
}

phongo_server_init(return_value, intern->client, server_id TSRMLS_CC);
} /* }}} */

/* {{{ proto MongoDB\Driver\Session MongoDB\Driver\Manager::startSession([array $options = null])
Expand Down
Loading