Skip to content

PHPC-1491: Add ReadPreference::getModeString #1062

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 3 commits into from
Dec 6, 2019
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
111 changes: 74 additions & 37 deletions src/MongoDB/ReadPreference.c
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,12 @@

zend_class_entry* php_phongo_readpreference_ce;

#define PHONGO_READ_PRIMARY "primary"
#define PHONGO_READ_PRIMARY_PREFERRED "primaryPreferred"
#define PHONGO_READ_SECONDARY "secondary"
#define PHONGO_READ_SECONDARY_PREFERRED "secondaryPreferred"
#define PHONGO_READ_NEAREST "nearest"

/* Initialize the object from a HashTable and return whether it was successful.
* An exception will be thrown on error. */
static bool php_phongo_readpreference_init_from_hash(php_phongo_readpreference_t* intern, HashTable* props TSRMLS_DC) /* {{{ */
Expand All @@ -42,15 +48,15 @@ static bool php_phongo_readpreference_init_from_hash(php_phongo_readpreference_t
zval *mode, *tagSets, *maxStalenessSeconds;

if ((mode = zend_hash_str_find(props, "mode", sizeof("mode") - 1)) && Z_TYPE_P(mode) == IS_STRING) {
if (strcasecmp(Z_STRVAL_P(mode), "primary") == 0) {
if (strcasecmp(Z_STRVAL_P(mode), PHONGO_READ_PRIMARY) == 0) {
intern->read_preference = mongoc_read_prefs_new(MONGOC_READ_PRIMARY);
} else if (strcasecmp(Z_STRVAL_P(mode), "primaryPreferred") == 0) {
} else if (strcasecmp(Z_STRVAL_P(mode), PHONGO_READ_PRIMARY_PREFERRED) == 0) {
intern->read_preference = mongoc_read_prefs_new(MONGOC_READ_PRIMARY_PREFERRED);
} else if (strcasecmp(Z_STRVAL_P(mode), "secondary") == 0) {
} else if (strcasecmp(Z_STRVAL_P(mode), PHONGO_READ_SECONDARY) == 0) {
intern->read_preference = mongoc_read_prefs_new(MONGOC_READ_SECONDARY);
} else if (strcasecmp(Z_STRVAL_P(mode), "secondaryPreferred") == 0) {
} else if (strcasecmp(Z_STRVAL_P(mode), PHONGO_READ_SECONDARY_PREFERRED) == 0) {
intern->read_preference = mongoc_read_prefs_new(MONGOC_READ_SECONDARY_PREFERRED);
} else if (strcasecmp(Z_STRVAL_P(mode), "nearest") == 0) {
} else if (strcasecmp(Z_STRVAL_P(mode), PHONGO_READ_NEAREST) == 0) {
intern->read_preference = mongoc_read_prefs_new(MONGOC_READ_NEAREST);
} else {
phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT TSRMLS_CC, "%s initialization requires specific values for \"mode\" string field", ZSTR_VAL(php_phongo_readpreference_ce->name));
Expand Down Expand Up @@ -113,15 +119,15 @@ static bool php_phongo_readpreference_init_from_hash(php_phongo_readpreference_t
zval **mode, **tagSets, **maxStalenessSeconds;

if (zend_hash_find(props, "mode", sizeof("mode"), (void**) &mode) == SUCCESS && Z_TYPE_PP(mode) == IS_STRING) {
if (strcasecmp(Z_STRVAL_PP(mode), "primary") == 0) {
if (strcasecmp(Z_STRVAL_PP(mode), PHONGO_READ_PRIMARY) == 0) {
intern->read_preference = mongoc_read_prefs_new(MONGOC_READ_PRIMARY);
} else if (strcasecmp(Z_STRVAL_PP(mode), "primaryPreferred") == 0) {
} else if (strcasecmp(Z_STRVAL_PP(mode), PHONGO_READ_PRIMARY_PREFERRED) == 0) {
intern->read_preference = mongoc_read_prefs_new(MONGOC_READ_PRIMARY_PREFERRED);
} else if (strcasecmp(Z_STRVAL_PP(mode), "secondary") == 0) {
} else if (strcasecmp(Z_STRVAL_PP(mode), PHONGO_READ_SECONDARY) == 0) {
intern->read_preference = mongoc_read_prefs_new(MONGOC_READ_SECONDARY);
} else if (strcasecmp(Z_STRVAL_PP(mode), "secondaryPreferred") == 0) {
} else if (strcasecmp(Z_STRVAL_PP(mode), PHONGO_READ_SECONDARY_PREFERRED) == 0) {
intern->read_preference = mongoc_read_prefs_new(MONGOC_READ_SECONDARY_PREFERRED);
} else if (strcasecmp(Z_STRVAL_PP(mode), "nearest") == 0) {
} else if (strcasecmp(Z_STRVAL_PP(mode), PHONGO_READ_NEAREST) == 0) {
intern->read_preference = mongoc_read_prefs_new(MONGOC_READ_NEAREST);
} else {
phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT TSRMLS_CC, "%s initialization requires specific values for \"mode\" string field", ZSTR_VAL(php_phongo_readpreference_ce->name));
Expand Down Expand Up @@ -190,6 +196,28 @@ static bool php_phongo_readpreference_init_from_hash(php_phongo_readpreference_t
return false;
} /* }}} */

static const char* php_phongo_readpreference_get_mode_string(mongoc_read_mode_t mode TSRMLS_DC) /* {{{ */
{
switch (mode) {
case MONGOC_READ_PRIMARY:
return PHONGO_READ_PRIMARY;
case MONGOC_READ_PRIMARY_PREFERRED:
return PHONGO_READ_PRIMARY_PREFERRED;
case MONGOC_READ_SECONDARY:
return PHONGO_READ_SECONDARY;
case MONGOC_READ_SECONDARY_PREFERRED:
return PHONGO_READ_SECONDARY_PREFERRED;
case MONGOC_READ_NEAREST:
return PHONGO_READ_NEAREST;
default:
/* Should never happen, but if it does: exception */
phongo_throw_exception(PHONGO_ERROR_LOGIC TSRMLS_CC, "Mode '%d' should never have been passed to php_phongo_readpreference_get_mode_string, please file a bug report", mode);
break;
}

return NULL;
} /* }}} */

/* {{{ proto void MongoDB\Driver\ReadPreference::__construct(int|string $mode[, array $tagSets = array()[, array $options = array()]])
Constructs a new ReadPreference */
static PHP_METHOD(ReadPreference, __construct)
Expand Down Expand Up @@ -225,15 +253,15 @@ static PHP_METHOD(ReadPreference, __construct)
return;
}
} else if (Z_TYPE_P(mode) == IS_STRING) {
if (strcasecmp(Z_STRVAL_P(mode), "primary") == 0) {
if (strcasecmp(Z_STRVAL_P(mode), PHONGO_READ_PRIMARY) == 0) {
intern->read_preference = mongoc_read_prefs_new(MONGOC_READ_PRIMARY);
} else if (strcasecmp(Z_STRVAL_P(mode), "primaryPreferred") == 0) {
} else if (strcasecmp(Z_STRVAL_P(mode), PHONGO_READ_PRIMARY_PREFERRED) == 0) {
intern->read_preference = mongoc_read_prefs_new(MONGOC_READ_PRIMARY_PREFERRED);
} else if (strcasecmp(Z_STRVAL_P(mode), "secondary") == 0) {
} else if (strcasecmp(Z_STRVAL_P(mode), PHONGO_READ_SECONDARY) == 0) {
intern->read_preference = mongoc_read_prefs_new(MONGOC_READ_SECONDARY);
} else if (strcasecmp(Z_STRVAL_P(mode), "secondaryPreferred") == 0) {
} else if (strcasecmp(Z_STRVAL_P(mode), PHONGO_READ_SECONDARY_PREFERRED) == 0) {
intern->read_preference = mongoc_read_prefs_new(MONGOC_READ_SECONDARY_PREFERRED);
} else if (strcasecmp(Z_STRVAL_P(mode), "nearest") == 0) {
} else if (strcasecmp(Z_STRVAL_P(mode), PHONGO_READ_NEAREST) == 0) {
intern->read_preference = mongoc_read_prefs_new(MONGOC_READ_NEAREST);
} else {
phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT TSRMLS_CC, "Invalid mode: '%s'", Z_STRVAL_P(mode));
Expand Down Expand Up @@ -343,6 +371,28 @@ static PHP_METHOD(ReadPreference, getMode)
RETURN_LONG(mongoc_read_prefs_get_mode(intern->read_preference));
} /* }}} */

/* {{{ proto string MongoDB\Driver\ReadPreference::getModeString()
Returns the ReadPreference mode as string */
static PHP_METHOD(ReadPreference, getModeString)
{
php_phongo_readpreference_t* intern;
const char* mode_string;

intern = Z_READPREFERENCE_OBJ_P(getThis());

if (zend_parse_parameters_none() == FAILURE) {
return;
}

mode_string = php_phongo_readpreference_get_mode_string(mongoc_read_prefs_get_mode(intern->read_preference) TSRMLS_CC);
if (!mode_string) {
/* Exception already thrown */
return;
}

PHONGO_RETURN_STRING(mode_string);
} /* }}} */

/* {{{ proto array MongoDB\Driver\ReadPreference::getTagSets()
Returns the ReadPreference tag sets */
static PHP_METHOD(ReadPreference, getTagSets)
Expand Down Expand Up @@ -378,26 +428,6 @@ static PHP_METHOD(ReadPreference, getTagSets)
}
} /* }}} */

static const char* php_phongo_readpreference_get_mode_string(mongoc_read_mode_t mode) /* {{{ */
{
switch (mode) {
case MONGOC_READ_PRIMARY:
return "primary";
case MONGOC_READ_PRIMARY_PREFERRED:
return "primaryPreferred";
case MONGOC_READ_SECONDARY:
return "secondary";
case MONGOC_READ_SECONDARY_PREFERRED:
return "secondaryPreferred";
case MONGOC_READ_NEAREST:
return "nearest";
default: /* Do nothing */
break;
}

return NULL;
} /* }}} */

static HashTable* php_phongo_readpreference_get_properties_hash(zval* object, bool is_debug TSRMLS_DC) /* {{{ */
{
php_phongo_readpreference_t* intern;
Expand All @@ -416,7 +446,7 @@ static HashTable* php_phongo_readpreference_get_properties_hash(zval* object, bo

tags = mongoc_read_prefs_get_tags(intern->read_preference);
mode = mongoc_read_prefs_get_mode(intern->read_preference);
modeString = php_phongo_readpreference_get_mode_string(mode);
modeString = php_phongo_readpreference_get_mode_string(mode TSRMLS_CC);

if (modeString) {
#if PHP_VERSION_ID >= 70000
Expand Down Expand Up @@ -510,7 +540,7 @@ static PHP_METHOD(ReadPreference, serialize)

tags = mongoc_read_prefs_get_tags(intern->read_preference);
mode = mongoc_read_prefs_get_mode(intern->read_preference);
modeString = php_phongo_readpreference_get_mode_string(mode);
modeString = php_phongo_readpreference_get_mode_string(mode TSRMLS_CC);
maxStalenessSeconds = mongoc_read_prefs_get_max_staleness_seconds(intern->read_preference);

#if PHP_VERSION_ID >= 70000
Expand Down Expand Up @@ -638,6 +668,7 @@ static zend_function_entry php_phongo_readpreference_me[] = {
PHP_ME(ReadPreference, __set_state, ai_ReadPreference___set_state, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC)
PHP_ME(ReadPreference, getMaxStalenessSeconds, ai_ReadPreference_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
PHP_ME(ReadPreference, getMode, ai_ReadPreference_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
PHP_ME(ReadPreference, getModeString, ai_ReadPreference_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
PHP_ME(ReadPreference, getTagSets, ai_ReadPreference_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
PHP_ME(ReadPreference, bsonSerialize, ai_ReadPreference_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
PHP_ME(ReadPreference, serialize, ai_ReadPreference_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
Expand Down Expand Up @@ -733,6 +764,12 @@ void php_phongo_readpreference_init_ce(INIT_FUNC_ARGS) /* {{{ */
zend_declare_class_constant_long(php_phongo_readpreference_ce, ZEND_STRL("RP_NEAREST"), MONGOC_READ_NEAREST TSRMLS_CC);
zend_declare_class_constant_long(php_phongo_readpreference_ce, ZEND_STRL("NO_MAX_STALENESS"), MONGOC_NO_MAX_STALENESS TSRMLS_CC);
zend_declare_class_constant_long(php_phongo_readpreference_ce, ZEND_STRL("SMALLEST_MAX_STALENESS_SECONDS"), MONGOC_SMALLEST_MAX_STALENESS_SECONDS TSRMLS_CC);

zend_declare_class_constant_string(php_phongo_readpreference_ce, ZEND_STRL("PRIMARY"), PHONGO_READ_PRIMARY TSRMLS_CC);
Copy link
Member Author

Choose a reason for hiding this comment

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

As in #1061, I'm exposing constants here. Since the class name is ReadPreference, I decided to avoid using any prefix. This also resolves a naming conflict with the RP_ constants that expose the integer values for read preference modes.

I'm not too happy about having two very similar constants (RP_PRIMARY and PRIMARY) in the same class, as this may confuse users. We don't need to expose these values as constants now and may opt to only do that in 2.0 when the RP_ constants are dropped.

Copy link
Member

Choose a reason for hiding this comment

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

I'm OK with adding the constants now, as it's consistent with what we're already doing in ReadConcern. If we don't already have tickets to deprecate and remove the RP_ constants, feel free to create those.

Copy link
Member Author

Choose a reason for hiding this comment

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

Deprecation is tracked in PHPC-1489. I've added tests for all constants, including int ones for good measure.

zend_declare_class_constant_string(php_phongo_readpreference_ce, ZEND_STRL("PRIMARY_PREFERRED"), PHONGO_READ_PRIMARY_PREFERRED TSRMLS_CC);
zend_declare_class_constant_string(php_phongo_readpreference_ce, ZEND_STRL("SECONDARY"), PHONGO_READ_SECONDARY TSRMLS_CC);
zend_declare_class_constant_string(php_phongo_readpreference_ce, ZEND_STRL("SECONDARY_PREFERRED"), PHONGO_READ_SECONDARY_PREFERRED TSRMLS_CC);
zend_declare_class_constant_string(php_phongo_readpreference_ce, ZEND_STRL("NEAREST"), PHONGO_READ_NEAREST TSRMLS_CC);
} /* }}} */

/*
Expand Down
36 changes: 36 additions & 0 deletions tests/readPreference/readpreference-constants.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
--TEST--
MongoDB\Driver\ReadPreference constants
--FILE--
<?php

var_dump(MongoDB\Driver\ReadPreference::RP_PRIMARY);
var_dump(MongoDB\Driver\ReadPreference::RP_PRIMARY_PREFERRED);
var_dump(MongoDB\Driver\ReadPreference::RP_SECONDARY);
var_dump(MongoDB\Driver\ReadPreference::RP_SECONDARY_PREFERRED);
var_dump(MongoDB\Driver\ReadPreference::RP_NEAREST);
var_dump(MongoDB\Driver\ReadPreference::NO_MAX_STALENESS);
var_dump(MongoDB\Driver\ReadPreference::SMALLEST_MAX_STALENESS_SECONDS);

var_dump(MongoDB\Driver\ReadPreference::PRIMARY);
var_dump(MongoDB\Driver\ReadPreference::PRIMARY_PREFERRED);
var_dump(MongoDB\Driver\ReadPreference::SECONDARY);
var_dump(MongoDB\Driver\ReadPreference::SECONDARY_PREFERRED);
var_dump(MongoDB\Driver\ReadPreference::NEAREST);

?>
===DONE===
<?php exit(0); ?>
--EXPECTF--
int(1)
int(5)
int(2)
int(6)
int(10)
int(-1)
int(90)
string(7) "primary"
string(16) "primaryPreferred"
string(9) "secondary"
string(18) "secondaryPreferred"
string(7) "nearest"
===DONE===
28 changes: 28 additions & 0 deletions tests/readPreference/readpreference-getModeString-001.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
--TEST--
MongoDB\Driver\ReadPreference::getModeString()
--FILE--
<?php

$tests = [
MongoDB\Driver\ReadPreference::RP_PRIMARY,
MongoDB\Driver\ReadPreference::RP_PRIMARY_PREFERRED,
MongoDB\Driver\ReadPreference::RP_SECONDARY,
MongoDB\Driver\ReadPreference::RP_SECONDARY_PREFERRED,
MongoDB\Driver\ReadPreference::RP_NEAREST,
];

foreach ($tests as $test) {
$rp = new MongoDB\Driver\ReadPreference($test);
var_dump($rp->getModeString());
}

?>
===DONE===
<?php exit(0); ?>
--EXPECT--
string(7) "primary"
string(16) "primaryPreferred"
string(9) "secondary"
string(18) "secondaryPreferred"
string(7) "nearest"
===DONE===