Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Merged pull request #217

  • Loading branch information...
commit c649c13731ac77e56cc13ecd9203d8e8a11774b9 2 parents 6bfb094 + 5e882a6
@derickr derickr authored
View
178 collection.c
@@ -25,7 +25,7 @@
#include "mcon/manager.h"
#include "mcon/io.h"
-extern zend_class_entry *mongo_ce_Mongo,
+extern zend_class_entry *mongo_ce_MongoClient,
*mongo_ce_DB,
*mongo_ce_Cursor,
*mongo_ce_Code,
@@ -43,8 +43,8 @@ ZEND_EXTERN_MODULE_GLOBALS(mongo);
zend_class_entry *mongo_ce_Collection = NULL;
static mongo_connection* get_server(mongo_collection *c, int connection_flags TSRMLS_DC);
-static int is_safe_op(zval *options, int default_do_gle TSRMLS_DC);
-static void safe_op(mongo_con_manager *manager, mongo_connection *connection, zval *cursor_z, buffer *buf, zval *return_value TSRMLS_DC);
+static int is_gle_op(zval *options, int default_do_gle TSRMLS_DC);
+static void do_safe_op(mongo_con_manager *manager, mongo_connection *connection, zval *cursor_z, buffer *buf, zval *return_value TSRMLS_DC);
static zval* append_getlasterror(zval *coll, buffer *buf, zval *options TSRMLS_DC);
static int php_mongo_trigger_error_on_command_failure(zval *document TSRMLS_DC);
@@ -226,50 +226,84 @@ PHP_METHOD(MongoCollection, validate) {
* this should probably be split into two methods... right now appends the
* getlasterror query to the buffer and alloc & inits the cursor zval.
*/
-static zval* append_getlasterror(zval *coll, buffer *buf, zval *options TSRMLS_DC) {
+static zval* append_getlasterror(zval *coll, buffer *buf, zval *options TSRMLS_DC)
+{
zval *cmd_ns_z, *cmd, *cursor_z, *temp, *timeout_p;
- char *cmd_ns, *safe_str = NULL;
+ char *cmd_ns, *w_str = NULL;
mongo_cursor *cursor;
mongo_collection *c = (mongo_collection*)zend_object_store_get_object(coll TSRMLS_CC);
mongo_db *db = (mongo_db*)zend_object_store_get_object(c->parent TSRMLS_CC);
- int response, safe = 0, fsync = 0, timeout = -1;
- mongo_link *link = (mongo_link*) zend_object_store_get_object(c->link TSRMLS_CC);
+ int response, w = 0, fsync = 0, timeout = -1;
+ mongoclient *link = (mongoclient*) zend_object_store_get_object(c->link TSRMLS_CC);
+
+ mongo_manager_log(MonGlo(manager), MLOG_IO, MLOG_FINE, "append_getlasterror");
timeout_p = zend_read_static_property(mongo_ce_Cursor, "timeout", strlen("timeout"), NOISY TSRMLS_CC);
convert_to_long(timeout_p);
timeout = Z_LVAL_P(timeout_p);
/* Read the default_* properties from the link */
- if (link->servers->default_do_gle != -1) {
- safe = link->servers->default_do_gle;
+ if (link->servers->default_w != -1) {
+ w = link->servers->default_w;
+ }
+ if (link->servers->default_wstring != NULL) {
+ w_str = link->servers->default_wstring;
+ }
+
+ /* This picks up the default "w" through the properties of MongoCollection
+ * and MongoDb, but only if w is still 1 - as otherwise it was perhaps
+ * overridden with the "w" (or "safe") option. */
+ {
+ zval *w_prop = zend_read_property(mongo_ce_Collection, coll, "w", strlen("w"), NOISY TSRMLS_CC);
+
+ if (Z_TYPE_P(w_prop) == IS_STRING) {
+ w_str = Z_STRVAL_P(w_prop);
+ } else {
+ convert_to_long(w_prop);
+ if (Z_LVAL_P(w_prop) != 1) {
+ w = Z_LVAL_P(w_prop);
+ w_str = NULL;
+ }
+ }
}
/* Fetch all the options from the options array*/
if (options && !IS_SCALAR_P(options)) {
- zval **safe_pp, **fsync_pp, **timeout_pp;
-
- if (SUCCESS == zend_hash_find(HASH_P(options), "safe", strlen("safe") + 1, (void**)&safe_pp)) {
- switch (Z_TYPE_PP(safe_pp)) {
+ zval **w_pp = NULL, **fsync_pp, **timeout_pp;
+
+ /* First we try "w", and if that is not found we check for "safe" */
+ if (zend_hash_find(HASH_P(options), "w", strlen("w") + 1, (void**) &w_pp) == FAILURE) {
+ zend_hash_find(HASH_P(options), "safe", strlen("safe") + 1, (void**) &w_pp);
+ }
+ /* After that, w_pp is either still NULL, or set to something if one of
+ * the options was found */
+ if (w_pp) {
+ switch (Z_TYPE_PP(w_pp)) {
case IS_STRING:
- safe_str = Z_STRVAL_PP(safe_pp);
+ w_str = Z_STRVAL_PP(w_pp);
break;
case IS_BOOL:
case IS_LONG:
- safe = Z_LVAL_PP(safe_pp); /* This is actually "wrong" for bools, but it works */
+ w = Z_LVAL_PP(w_pp); /* This is actually "wrong" for bools, but it works */
break;
default:
php_error_docref(NULL TSRMLS_CC, E_WARNING, "The value of the 'safe' option either needs to be a boolean or a string");
}
}
- if (SUCCESS == zend_hash_find(HASH_P(options), "fsync", strlen("fsync") + 1, (void**)&fsync_pp)) {
+
+ if (SUCCESS == zend_hash_find(HASH_P(options), "fsync", strlen("fsync") + 1, (void**) &fsync_pp)) {
convert_to_boolean(*fsync_pp);
fsync = Z_BVAL_PP(fsync_pp);
- if (fsync && !safe) {
- safe = 1;
+ /* fsync forces "w" to be atleast 1, so don't touch it if it's
+ * already set to something else above while parsing "w" (and
+ * "safe") */
+ if (fsync && w == 0) {
+ w = 1;
}
}
- if (SUCCESS == zend_hash_find(HASH_P(options), "timeout", strlen("timeout") + 1, (void**)&timeout_pp)) {
+
+ if (SUCCESS == zend_hash_find(HASH_P(options), "timeout", strlen("timeout") + 1, (void**) &timeout_pp)) {
convert_to_long(*timeout_pp);
timeout = Z_LVAL_PP(timeout_pp);
}
@@ -286,39 +320,28 @@ static zval* append_getlasterror(zval *coll, buffer *buf, zval *options TSRMLS_D
array_init(cmd);
add_assoc_long(cmd, "getlasterror", 1);
- /* This picks up the default "w" through the properties of MongoCollection
- * and MongoDb, but only if safe is still 1. */
- if (safe == 1) {
- zval *w = zend_read_property(mongo_ce_Collection, coll, "w", strlen("w"), NOISY TSRMLS_CC);
- if (Z_TYPE_P(w) == IS_STRING) {
- safe_str = Z_STRVAL_P(w);
+ /* if we have either a string, or w > 1, then we need to add "w" and perhaps "wtimeout" to GLE */
+ if (w_str || w > 1) {
+ zval *wtimeout;
+
+ if (w_str) {
+ add_assoc_string(cmd, "w", w_str, 1);
+ mongo_manager_log(MonGlo(manager), MLOG_IO, MLOG_FINE, "append_getlasterror: added w='%s'", w_str);
} else {
- convert_to_long(w);
- safe = Z_LVAL_P(w);
+ add_assoc_long(cmd, "w", w);
+ mongo_manager_log(MonGlo(manager), MLOG_IO, MLOG_FINE, "append_getlasterror: added w=%d", w);
}
- }
-
- if (safe_str || safe > 1) {
- zval *wtimeout;
- if (safe_str) {
- add_assoc_string(cmd, "w", safe_str, 1);
- mongo_manager_log(MonGlo(manager), MLOG_IO, MLOG_FINE, "append_getlasterror: added w='%s'", safe_str);
- }
- else {
- add_assoc_long(cmd, "w", safe);
- mongo_manager_log(MonGlo(manager), MLOG_IO, MLOG_FINE, "append_getlasterror: added w=%d", safe);
- }
-
- wtimeout = zend_read_property(mongo_ce_Collection, coll, "wtimeout", strlen("wtimeout"), NOISY TSRMLS_CC);
- convert_to_long(wtimeout);
- add_assoc_long(cmd, "wtimeout", Z_LVAL_P(wtimeout));
+ wtimeout = zend_read_property(mongo_ce_Collection, coll, "wtimeout", strlen("wtimeout"), NOISY TSRMLS_CC);
+ convert_to_long(wtimeout);
+ add_assoc_long(cmd, "wtimeout", Z_LVAL_P(wtimeout));
mongo_manager_log(MonGlo(manager), MLOG_IO, MLOG_FINE, "append_getlasterror: added wtimeout=%d", Z_LVAL_P(wtimeout));
- }
- if (fsync) {
- add_assoc_bool(cmd, "fsync", 1);
+ }
+
+ if (fsync) {
+ add_assoc_bool(cmd, "fsync", 1);
mongo_manager_log(MonGlo(manager), MLOG_IO, MLOG_FINE, "append_getlasterror: added fsync=1");
- }
+ }
// get cursor
MAKE_STD_ZVAL(cursor_z);
@@ -364,11 +387,11 @@ static zval* append_getlasterror(zval *coll, buffer *buf, zval *options TSRMLS_D
*/
static mongo_connection* get_server(mongo_collection *c, int connection_flags TSRMLS_DC)
{
- mongo_link *link;
+ mongoclient *link;
mongo_connection *connection;
char *error_message = NULL;
- link = (mongo_link*)zend_object_store_get_object((c->link) TSRMLS_CC);
+ link = (mongoclient*)zend_object_store_get_object((c->link) TSRMLS_CC);
if (!link) {
zend_throw_exception(mongo_ce_Exception, "The MongoCollection object has not been correctly initialized by its constructor", 17 TSRMLS_CC);
return 0;
@@ -392,7 +415,7 @@ static int send_message(zval *this_ptr, mongo_connection *connection, buffer *bu
{
int retval = 1;
char *error_message = NULL;
- mongo_link *link;
+ mongoclient *link;
mongo_collection *c;
c = (mongo_collection*)zend_object_store_get_object(this_ptr TSRMLS_CC);
@@ -401,16 +424,16 @@ static int send_message(zval *this_ptr, mongo_connection *connection, buffer *bu
return 0;
}
- link = (mongo_link*)zend_object_store_get_object((c->link) TSRMLS_CC);
+ link = (mongoclient*)zend_object_store_get_object((c->link) TSRMLS_CC);
if (!link) {
zend_throw_exception(mongo_ce_Exception, "The MongoCollection object has not been correctly initialized by its constructor", 17 TSRMLS_CC);
return 0;
}
- if (is_safe_op(options, link->servers->default_do_gle TSRMLS_CC)) {
+ if (is_gle_op(options, link->servers->default_w TSRMLS_CC)) {
zval *cursor = append_getlasterror(getThis(), buf, options TSRMLS_CC);
if (cursor) {
- safe_op(link->manager, connection, cursor, buf, return_value TSRMLS_CC);
+ do_safe_op(link->manager, connection, cursor, buf, return_value TSRMLS_CC);
retval = -1;
} else {
retval = 0;
@@ -426,42 +449,49 @@ static int send_message(zval *this_ptr, mongo_connection *connection, buffer *bu
}
-static int is_safe_op(zval *options, int default_do_gle TSRMLS_DC)
+static int is_gle_op(zval *options, int default_do_gle TSRMLS_DC)
{
- zval **safe_pp = 0, **fsync_pp = 0;
- int safe_op = 0;
+ zval **gle_pp = 0, **fsync_pp = 0;
+ int gle_op = 0;
/* First we check for the global (connection string) default */
if (default_do_gle != -1) {
- safe_op = default_do_gle;
+ gle_op = default_do_gle;
}
/* Then we check the options array that could overwrite the default */
if (options && Z_TYPE_P(options) == IS_ARRAY) {
- /* Check for "safe" in options array */
- if (zend_hash_find(HASH_P(options), "safe", strlen("safe")+1, (void**)&safe_pp) == SUCCESS) {
+
+ /* First we try "w", and if that is not found we check for "safe" */
+ if (zend_hash_find(HASH_P(options), "w", strlen("w") + 1, (void**) &gle_pp) == FAILURE) {
+ zend_hash_find(HASH_P(options), "safe", strlen("safe") + 1, (void**) &gle_pp);
+ }
+ /* After that, gle_pp is either still NULL, or set to something if one of
+ * the options was found */
+ if (gle_pp) {
/* Check for bool/int value >= 1 */
- if ((Z_TYPE_PP(safe_pp) == IS_LONG || Z_TYPE_PP(safe_pp) == IS_BOOL)) {
- safe_op = (Z_LVAL_PP(safe_pp) >= 1);
- goto ok;
- }
+ if ((Z_TYPE_PP(gle_pp) == IS_LONG || Z_TYPE_PP(gle_pp) == IS_BOOL)) {
+ gle_op = (Z_LVAL_PP(gle_pp) >= 1);
+
/* Check for string value ("majority", or a tag) */
- if (Z_TYPE_PP(safe_pp) == IS_STRING) {
- safe_op = 1;
- goto ok;
+ } else if (Z_TYPE_PP(gle_pp) == IS_STRING) {
+ gle_op = 1;
+
+ } else {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "The value of the 'safe' option either needs to be a boolean or a string");
}
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "The value of the 'safe' option either needs to be a boolean or a string");
}
+
/* Check for "fsync" in options array */
if (zend_hash_find(HASH_P(options), "fsync", strlen("fsync")+1, (void**)&fsync_pp) == SUCCESS) {
/* Check for bool/int value of 1 */
if ((Z_TYPE_PP(fsync_pp) == IS_LONG || Z_TYPE_PP(fsync_pp) == IS_BOOL) && Z_LVAL_PP(fsync_pp) == 1) {
- safe_op = 1;
- goto ok;
+ gle_op = 1;
}
}
}
-ok:
- return safe_op;
+
+ mongo_manager_log(MonGlo(manager), MLOG_IO, MLOG_FINE, "is_gle_op: %s", gle_op ? "yes" : "no");
+ return gle_op;
}
#if PHP_VERSION_ID >= 50300
@@ -496,7 +526,7 @@ static void connection_deregister_wrapper(mongo_con_manager *manager, mongo_conn
MONGO_ERROR_G(error_handling) = orig_error_handling;
}
-static void safe_op(mongo_con_manager *manager, mongo_connection *connection, zval *cursor_z, buffer *buf, zval *return_value TSRMLS_DC)
+static void do_safe_op(mongo_con_manager *manager, mongo_connection *connection, zval *cursor_z, buffer *buf, zval *return_value TSRMLS_DC)
{
zval *errmsg, **err;
mongo_cursor *cursor;
@@ -509,7 +539,7 @@ static void safe_op(mongo_con_manager *manager, mongo_connection *connection, zv
if (-1 == mongo_io_send(connection->socket, buf->start, buf->pos - buf->start, (char **) &error_message)) {
/* TODO: Figure out what to do on FAIL
mongo_util_link_failed(cursor->link, server TSRMLS_CC); */
- mongo_manager_log(manager, MLOG_IO, MLOG_WARN, "safe_op: sending data failed, removing connection %s", connection->hash);
+ mongo_manager_log(manager, MLOG_IO, MLOG_WARN, "do_safe_op: sending data failed, removing connection %s", connection->hash);
mongo_cursor_throw(connection, 16 TSRMLS_CC, error_message);
connection_deregister_wrapper(manager, connection TSRMLS_CC);
@@ -661,7 +691,7 @@ PHP_METHOD(MongoCollection, find)
{
zval *query = 0, *fields = 0;
mongo_collection *c;
- mongo_link *link;
+ mongoclient *link;
zval temp;
mongo_cursor *cursor;
View
2  config.m4
@@ -5,7 +5,7 @@ PHP_MONGO_CFLAGS="-I@ext_builddir@/util"
if test "$PHP_MONGO" != "no"; then
AC_DEFINE(HAVE_MONGO, 1, [Whether you have Mongo extension])
- PHP_NEW_EXTENSION(mongo, php_mongo.c mongo.c mongo_types.c bson.c cursor.c collection.c db.c gridfs.c gridfs_stream.c util/hash.c util/log.c util/pool.c mcon/bson_helpers.c mcon/collection.c mcon/connections.c mcon/io.c mcon/manager.c mcon/mini_bson.c mcon/parse.c mcon/read_preference.c mcon/str.c mcon/utils.c, $ext_shared,, $PHP_MONGO_CFLAGS)
+ PHP_NEW_EXTENSION(mongo, php_mongo.c mongo.c mongoclient.c mongo_types.c bson.c cursor.c collection.c db.c gridfs.c gridfs_stream.c util/hash.c util/log.c util/pool.c mcon/bson_helpers.c mcon/collection.c mcon/connections.c mcon/io.c mcon/manager.c mcon/mini_bson.c mcon/parse.c mcon/read_preference.c mcon/str.c mcon/utils.c, $ext_shared,, $PHP_MONGO_CFLAGS)
PHP_ADD_BUILD_DIR([$ext_builddir/util], 1)
PHP_ADD_INCLUDE([$ext_builddir/util])
View
10 cursor.c
@@ -63,7 +63,7 @@ static pthread_mutex_t cursor_mutex = PTHREAD_MUTEX_INITIALIZER;
// externs
extern zend_class_entry *mongo_ce_Id,
- *mongo_ce_Mongo,
+ *mongo_ce_MongoClient,
*mongo_ce_DB,
*mongo_ce_Collection,
*mongo_ce_Exception,
@@ -227,7 +227,7 @@ PHP_METHOD(MongoCursor, __construct) {
mongo_cursor *cursor;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Oz|zz", &zlink,
- mongo_ce_Mongo, &zns, &zquery, &zfields) == FAILURE) {
+ mongo_ce_MongoClient, &zns, &zquery, &zfields) == FAILURE) {
return;
}
MUST_BE_ARRAY_OR_OBJECT(3, zquery);
@@ -839,7 +839,7 @@ int mongo_cursor__do_query(zval *this_ptr, zval *return_value TSRMLS_DC) {
buffer buf;
zval *errmsg;
char *error_message;
- mongo_link *link;
+ mongoclient *link;
mongo_read_preference rp;
cursor = (mongo_cursor*)zend_object_store_get_object(getThis() TSRMLS_CC);
@@ -851,7 +851,7 @@ int mongo_cursor__do_query(zval *this_ptr, zval *return_value TSRMLS_DC) {
}
/* db connection resource */
- link = (mongo_link*)zend_object_store_get_object(cursor->resource TSRMLS_CC);
+ link = (mongoclient*)zend_object_store_get_object(cursor->resource TSRMLS_CC);
if (!link->servers) {
zend_throw_exception(mongo_ce_Exception, "The Mongo object has not been correctly initialized by its constructor", 0 TSRMLS_CC);
return FAILURE;
@@ -1244,7 +1244,7 @@ PHP_METHOD(MongoCursor, count) {
}
ZEND_BEGIN_ARG_INFO_EX(arginfo___construct, 0, ZEND_RETURN_VALUE, 2)
- ZEND_ARG_OBJ_INFO(0, connection, Mongo, 0)
+ ZEND_ARG_OBJ_INFO(0, connection, MongoClient, 0)
ZEND_ARG_INFO(0, database_and_collection_name)
ZEND_ARG_INFO(0, query)
ZEND_ARG_INFO(0, array_of_fields_OR_object)
View
19 db.c
@@ -27,7 +27,12 @@
#include "mongo_types.h"
#include "mcon/manager.h"
-extern zend_class_entry *mongo_ce_Mongo,
+#ifndef zend_parse_parameters_none
+#define zend_parse_parameters_none() \
+ zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "")
+#endif
+
+extern zend_class_entry *mongo_ce_MongoClient,
*mongo_ce_Collection,
*mongo_ce_Cursor,
*mongo_ce_GridFS,
@@ -46,7 +51,7 @@ zend_class_entry *mongo_ce_DB = NULL;
static void clear_exception(zval* return_value TSRMLS_DC);
-void php_mongo_connection_force_primary(mongo_cursor *cursor, mongo_link *link TSRMLS_DC)
+void php_mongo_connection_force_primary(mongo_cursor *cursor, mongoclient *link TSRMLS_DC)
{
char *error_message = NULL;
@@ -66,9 +71,9 @@ PHP_METHOD(MongoDB, __construct) {
char *name;
int name_len;
mongo_db *db;
- mongo_link *link;
+ mongoclient *link;
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Os", &zlink, mongo_ce_Mongo, &name, &name_len) == FAILURE) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Os", &zlink, mongo_ce_MongoClient, &name, &name_len) == FAILURE) {
zval *object = getThis();
ZVAL_NULL(object);
return;
@@ -583,7 +588,7 @@ static char *get_cmd_ns(char *db, int db_len) {
PHP_METHOD(MongoDB, command) {
zval limit, *temp, *cmd, *cursor, *ns, *options = 0;
mongo_db *db;
- mongo_link *link;
+ mongoclient *link;
char *cmd_ns;
mongo_cursor *cursor_tmp;
@@ -722,7 +727,7 @@ zval* mongo_db_cmd(mongo_connection *connection, char *database, zval *cmd TSRML
PHP_METHOD(MongoDB, authenticate)
{
mongo_db *db;
- mongo_link *link;
+ mongoclient *link;
char *username, *password;
int ulen, plen, i;
@@ -825,7 +830,7 @@ PHP_METHOD(MongoDB, __get) {
/* }}} */
MONGO_ARGINFO_STATIC ZEND_BEGIN_ARG_INFO_EX(arginfo___construct, 0, ZEND_RETURN_VALUE, 2)
- ZEND_ARG_OBJ_INFO(0, connection, Mongo, 0)
+ ZEND_ARG_OBJ_INFO(0, connection, MongoClient, 0)
ZEND_ARG_INFO(0, database_name)
ZEND_END_ARG_INFO()
View
2  db.h
@@ -31,7 +31,7 @@ zval* mongo_db_cmd(mongo_connection *connection, char *database, zval *cmd TSRML
/**
* Switch to primary connection, or throw exception on failure
*/
-void php_mongo_connection_force_primary(mongo_cursor *cursor, mongo_link *link TSRMLS_DC);
+void php_mongo_connection_force_primary(mongo_cursor *cursor, mongoclient *link TSRMLS_DC);
PHP_METHOD(MongoDB, __construct);
PHP_METHOD(MongoDB, __toString);
View
22 mcon/parse.c
@@ -39,7 +39,6 @@ mongo_servers* mongo_parse_init(void)
servers->repl_set_name = NULL;
servers->con_type = MONGO_CON_TYPE_STANDALONE;
- servers->default_do_gle = -1;
servers->default_w = -1;
servers->default_wstring = NULL;
servers->default_wtimeout = -1;
@@ -421,30 +420,18 @@ int mongo_store_option(mongo_con_manager *manager, mongo_servers *servers, char
servers->connectTimeoutMS = atoi(option_value);
return 0;
}
-#if 0
- if (strcasecmp(option_name, "fireAndForget") == 0) {
- mongo_manager_log(manager, MLOG_PARSE, MLOG_INFO, "- Found option 'fireAndForget': %s", option_value);
- if (strcmp(option_value, "true") == 0) {
- servers->default_do_gle = 1;
- } else if (strcmp(option_value, "false") == 0) {
- servers->default_do_gle = 0;
- } else {
- *error_message = strdup("The value of 'fireAndForget' needs to be either 'true' or 'false'");
- return 3;
- }
- return 0;
- }
-#endif
+
if (strcasecmp(option_name, "w") == 0) {
/* Rough check to see whether this is a numeric string or not */
if ((option_value[0] >= '0' && option_value[0] <= '9') || option_value[0] == '-') {
servers->default_w = atoi(option_value);
mongo_manager_log(manager, MLOG_PARSE, MLOG_INFO, "- Found option 'w': %d", servers->default_w);
- if (servers->default_w < 1) {
- *error_message = strdup("The value of 'w' needs to be 1 or higher (or a string).");
+ if (servers->default_w < 0) {
+ *error_message = strdup("The value of 'w' needs to be 0 or higher (or a string).");
return 3;
}
} else {
+ servers->default_w = 1;
servers->default_wstring = strdup(option_value);
mongo_manager_log(manager, MLOG_PARSE, MLOG_INFO, "- Found option 'w': '%s'", servers->default_wstring);
}
@@ -565,7 +552,6 @@ void mongo_servers_copy(mongo_servers *to, mongo_servers *from, int flags)
to->connectTimeoutMS = from->connectTimeoutMS;
- to->default_do_gle = from->default_do_gle;
to->default_w = from->default_w;
to->default_wtimeout = from->default_wtimeout;
if (from->default_wstring) {
View
1  mcon/types.h
@@ -173,7 +173,6 @@ typedef struct _mongo_servers
int con_type; /* One of MONGO_CON_TYPE_STANDALONE, MONGO_CON_TYPE_MULTIPLE or MONGO_CON_TYPE_REPLSET */
char *repl_set_name;
int connectTimeoutMS;
- int default_do_gle; /* Sets a flag whether all operations should be "safe" by default or not, -1 is not set, where 0 and 1 are explicit sets. */
int default_w; /* The number specifies the number of replica nodes */
char *default_wstring; /* If the value for "w" is a string, then it means a getLastError error-mode */
int default_wtimeout; /* How many milliseconds to wait for replication to "w" nodes */
View
965 mongo.c
@@ -13,687 +13,113 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-#include <stdlib.h>
-#include <string.h>
-#include <errno.h>
-
-#ifndef WIN32
-#include <sys/types.h>
-#endif
-
#include <php.h>
#include <zend_exceptions.h>
-#include "ext/standard/php_smart_str.h"
-
#include "php_mongo.h"
+#include "mongoclient.h"
#include "mongo.h"
#include "db.h"
-#include "cursor.h"
-#include "mongo_types.h"
-#include "bson.h"
-
-#include "util/log.h"
#include "util/pool.h"
-#include "mcon/types.h"
-#include "mcon/read_preference.h"
-#include "mcon/parse.h"
-#include "mcon/manager.h"
-#include "mcon/utils.h"
-
-
-static void php_mongo_link_free(void* TSRMLS_DC);
-static void run_err(int, zval*, zval* TSRMLS_DC);
-static void stringify_server(mongo_server_def *server, smart_str *str);
-static int close_connection(mongo_con_manager *manager, mongo_connection *connection);
-
-zend_object_handlers mongo_default_handlers;
-zend_object_handlers mongo_link_handlers;
+extern zend_object_handlers mongoclient_handlers;
ZEND_EXTERN_MODULE_GLOBALS(mongo);
zend_class_entry *mongo_ce_Mongo;
-extern zend_class_entry *mongo_ce_DB,
- *mongo_ce_Cursor,
- *mongo_ce_Exception,
- *mongo_ce_ConnectionException;
+extern zend_class_entry *mongo_ce_MongoClient,
+ *mongo_ce_DB,
+ *mongo_ce_Exception;
MONGO_ARGINFO_STATIC ZEND_BEGIN_ARG_INFO_EX(arginfo___construct, 0, ZEND_RETURN_VALUE, 0)
ZEND_ARG_INFO(0, server)
ZEND_ARG_ARRAY_INFO(0, options, 0)
ZEND_END_ARG_INFO()
-MONGO_ARGINFO_STATIC ZEND_BEGIN_ARG_INFO_EX(arginfo___get, 0, ZEND_RETURN_VALUE, 1)
- ZEND_ARG_INFO(0, name)
-ZEND_END_ARG_INFO()
-
MONGO_ARGINFO_STATIC ZEND_BEGIN_ARG_INFO_EX(arginfo_no_parameters, 0, ZEND_RETURN_VALUE, 0)
ZEND_END_ARG_INFO()
-MONGO_ARGINFO_STATIC ZEND_BEGIN_ARG_INFO_EX(arginfo_selectDB, 0, ZEND_RETURN_VALUE, 1)
- ZEND_ARG_INFO(0, database_name)
-ZEND_END_ARG_INFO()
-
-MONGO_ARGINFO_STATIC ZEND_BEGIN_ARG_INFO_EX(arginfo_selectCollection, 0, ZEND_RETURN_VALUE, 1)
- ZEND_ARG_INFO(0, database_name)
- ZEND_ARG_INFO(0, collection_name)
-ZEND_END_ARG_INFO()
-
MONGO_ARGINFO_STATIC ZEND_BEGIN_ARG_INFO_EX(arginfo_setSlaveOkay, 0, ZEND_RETURN_VALUE, 0)
ZEND_ARG_INFO(0, slave_okay)
ZEND_END_ARG_INFO()
-MONGO_ARGINFO_STATIC ZEND_BEGIN_ARG_INFO_EX(arginfo_setReadPreference, 0, ZEND_RETURN_VALUE, 1)
- ZEND_ARG_INFO(0, read_preference)
- ZEND_ARG_ARRAY_INFO(0, tags, 0)
-ZEND_END_ARG_INFO()
-
-MONGO_ARGINFO_STATIC ZEND_BEGIN_ARG_INFO_EX(arginfo_dropDB, 0, ZEND_RETURN_VALUE, 1)
- ZEND_ARG_INFO(0, MongoDB_object_OR_database_name)
-ZEND_END_ARG_INFO()
-
MONGO_ARGINFO_STATIC ZEND_BEGIN_ARG_INFO_EX(arginfo_setPoolSize, 0, ZEND_RETURN_VALUE, 1)
- ZEND_ARG_INFO(0, maximum_pool_size)
+ ZEND_ARG_INFO(0, size)
ZEND_END_ARG_INFO()
static zend_function_entry mongo_methods[] = {
- PHP_ME(Mongo, __construct, arginfo___construct, ZEND_ACC_PUBLIC)
- PHP_ME(Mongo, getConnections, arginfo_no_parameters, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
- PHP_ME(Mongo, connect, arginfo_no_parameters, ZEND_ACC_PUBLIC)
- PHP_ME(Mongo, connectUtil, arginfo_no_parameters, ZEND_ACC_PROTECTED)
- PHP_ME(Mongo, __toString, arginfo_no_parameters, ZEND_ACC_PUBLIC)
- PHP_ME(Mongo, __get, arginfo___get, ZEND_ACC_PUBLIC)
- PHP_ME(Mongo, selectDB, arginfo_selectDB, ZEND_ACC_PUBLIC)
- PHP_ME(Mongo, selectCollection, arginfo_selectCollection, ZEND_ACC_PUBLIC)
- PHP_ME(Mongo, getSlaveOkay, arginfo_no_parameters, ZEND_ACC_PUBLIC|ZEND_ACC_DEPRECATED)
- PHP_ME(Mongo, setSlaveOkay, arginfo_setSlaveOkay, ZEND_ACC_PUBLIC|ZEND_ACC_DEPRECATED)
- PHP_ME(Mongo, getReadPreference, arginfo_no_parameters, ZEND_ACC_PUBLIC)
- PHP_ME(Mongo, setReadPreference, arginfo_setReadPreference, ZEND_ACC_PUBLIC)
- PHP_ME(Mongo, dropDB, arginfo_dropDB, ZEND_ACC_PUBLIC)
- PHP_ME(Mongo, lastError, arginfo_no_parameters, ZEND_ACC_PUBLIC|ZEND_ACC_DEPRECATED)
- PHP_ME(Mongo, prevError, arginfo_no_parameters, ZEND_ACC_PUBLIC|ZEND_ACC_DEPRECATED)
- PHP_ME(Mongo, resetError, arginfo_no_parameters, ZEND_ACC_PUBLIC|ZEND_ACC_DEPRECATED)
- PHP_ME(Mongo, forceError, arginfo_no_parameters, ZEND_ACC_PUBLIC|ZEND_ACC_DEPRECATED)
- PHP_ME(Mongo, listDBs, arginfo_no_parameters, ZEND_ACC_PUBLIC)
- PHP_ME(Mongo, getHosts, arginfo_no_parameters, ZEND_ACC_PUBLIC)
- PHP_ME(Mongo, getSlave, arginfo_no_parameters, ZEND_ACC_PUBLIC|ZEND_ACC_DEPRECATED)
- PHP_ME(Mongo, switchSlave, arginfo_no_parameters, ZEND_ACC_PUBLIC|ZEND_ACC_DEPRECATED)
- PHP_ME(Mongo, close, arginfo_no_parameters, ZEND_ACC_PUBLIC)
+ PHP_ME(Mongo, __construct, arginfo___construct, ZEND_ACC_PUBLIC)
+
+ /* All these methods only exist in Mongo, and no longer in MongoClient */
+ PHP_ME(Mongo, connectUtil, arginfo_no_parameters, ZEND_ACC_PROTECTED)
+ PHP_ME(Mongo, getSlaveOkay, arginfo_no_parameters, ZEND_ACC_PUBLIC|ZEND_ACC_DEPRECATED)
+ PHP_ME(Mongo, setSlaveOkay, arginfo_setSlaveOkay, ZEND_ACC_PUBLIC|ZEND_ACC_DEPRECATED)
+ PHP_ME(Mongo, lastError, arginfo_no_parameters, ZEND_ACC_PUBLIC|ZEND_ACC_DEPRECATED)
+ PHP_ME(Mongo, prevError, arginfo_no_parameters, ZEND_ACC_PUBLIC|ZEND_ACC_DEPRECATED)
+ PHP_ME(Mongo, resetError, arginfo_no_parameters, ZEND_ACC_PUBLIC|ZEND_ACC_DEPRECATED)
+ PHP_ME(Mongo, forceError, arginfo_no_parameters, ZEND_ACC_PUBLIC|ZEND_ACC_DEPRECATED)
+ PHP_ME(Mongo, getSlave, arginfo_no_parameters, ZEND_ACC_PUBLIC|ZEND_ACC_DEPRECATED)
+ PHP_ME(Mongo, switchSlave, arginfo_no_parameters, ZEND_ACC_PUBLIC|ZEND_ACC_DEPRECATED)
PHP_ME(Mongo, setPoolSize, arginfo_setPoolSize, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC|ZEND_ACC_DEPRECATED)
PHP_ME(Mongo, getPoolSize, arginfo_no_parameters, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC|ZEND_ACC_DEPRECATED)
PHP_ME(Mongo, poolDebug, arginfo_no_parameters, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC|ZEND_ACC_DEPRECATED)
- { NULL, NULL, NULL }
+ { NULL, NULL, NULL }
};
-/* {{{ php_mongo_link_free
- */
-static void php_mongo_link_free(void *object TSRMLS_DC)
-{
- mongo_link *link = (mongo_link*)object;
-
- /* already freed */
- if (!link) {
- return;
- }
-
- if (link->servers) {
- mongo_servers_dtor(link->servers);
- }
-
- zend_object_std_dtor(&link->std TSRMLS_CC);
-
- efree(link);
-}
-/* }}} */
-
-#if PHP_VERSION_ID >= 50400
-static zval *mongo_read_property(zval *object, zval *member, int type, const zend_literal *key TSRMLS_DC)
-#else
-static zval *mongo_read_property(zval *object, zval *member, int type TSRMLS_DC)
-#endif
-{
- zval *retval;
- zval tmp_member;
- mongo_link *obj;
-
- if (member->type != IS_STRING) {
- tmp_member = *member;
- zval_copy_ctor(&tmp_member);
- convert_to_string(&tmp_member);
- member = &tmp_member;
- }
-
- obj = (mongo_link *)zend_objects_get_address(object TSRMLS_CC);
- if (strcmp(Z_STRVAL_P(member), "connected") == 0) {
- char *error_message = NULL;
- mongo_connection *conn = mongo_get_read_write_connection(obj->manager, obj->servers, MONGO_CON_FLAG_READ|MONGO_CON_FLAG_DONT_CONNECT, (char**) &error_message);
- ALLOC_INIT_ZVAL(retval);
- Z_SET_REFCOUNT_P(retval, 0);
- ZVAL_BOOL(retval, conn ? 1 : 0);
- if (error_message) {
- free(error_message);
- }
- return retval;
- }
-
-#if PHP_VERSION_ID >= 50400
- retval = (zend_get_std_object_handlers())->read_property(object, member, type, key TSRMLS_CC);
-#else
- retval = (zend_get_std_object_handlers())->read_property(object, member, type TSRMLS_CC);
-#endif
- if (member == &tmp_member) {
- zval_dtor(member);
- }
- return retval;
-}
-#if PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION >= 3
-HashTable *mongo_get_debug_info(zval *object, int *is_temp TSRMLS_DC)
+void mongo_init_Mongo(TSRMLS_D)
{
- HashPosition pos;
- HashTable *props = zend_std_get_properties(object TSRMLS_CC);
- zval **entry;
- ulong num_key;
-
- zend_hash_internal_pointer_reset_ex(props, &pos);
- while (zend_hash_get_current_data_ex(props, (void **)&entry, &pos) == SUCCESS) {
- char *key;
- uint key_len;
-
- switch (zend_hash_get_current_key_ex(props, &key, &key_len, &num_key, 0, &pos)) {
- case HASH_KEY_IS_STRING: {
- /* Override the connected property like we do for the read_property handler */
- if (strcmp(key, "connected") == 0) {
- zval member;
- zval *tmp;
- INIT_ZVAL(member);
- ZVAL_STRINGL(&member, key, key_len, 0);
-
-#if PHP_VERSION_ID >= 50400
- tmp = mongo_read_property(object, &member, BP_VAR_IS, NULL TSRMLS_CC);
-#else
- tmp = mongo_read_property(object, &member, BP_VAR_IS TSRMLS_CC);
-#endif
- convert_to_boolean_ex(entry);
- ZVAL_BOOL(*entry, Z_BVAL_P(tmp));
- /* the var is set to refcount = 0, need to set it to 1 so it'll get free()d */
- if (Z_REFCOUNT_P(tmp) == 0) {
- Z_SET_REFCOUNT_P(tmp, 1);
- }
- zval_ptr_dtor(&tmp);
- }
- break;
- }
- case HASH_KEY_IS_LONG:
- case HASH_KEY_NON_EXISTANT:
- break;
- }
- zend_hash_move_forward_ex(props, &pos);
- }
-
- *is_temp = 0;
- return props;
-}
-#endif
-
-
-/* {{{ php_mongo_link_new
- */
-static zend_object_value php_mongo_link_new(zend_class_entry *class_type TSRMLS_DC) {
- zend_object_value retval;
- mongo_link *intern;
- zval *tmp;
+ zend_class_entry ce;
- intern = (mongo_link*)emalloc(sizeof(mongo_link));
- memset(intern, 0, sizeof(mongo_link));
+ INIT_CLASS_ENTRY(ce, "Mongo", mongo_methods); /* FIXME: Use mongo_methods here */
+ ce.create_object = php_mongoclient_new;
+ mongo_ce_Mongo = zend_register_internal_class_ex(&ce, mongo_ce_MongoClient, NULL TSRMLS_CC);
- zend_object_std_init(&intern->std, class_type TSRMLS_CC);
- init_properties(intern);
-
- retval.handle = zend_objects_store_put(intern,
- (zend_objects_store_dtor_t) zend_objects_destroy_object,
- php_mongo_link_free, NULL TSRMLS_CC);
- retval.handlers = &mongo_link_handlers;
-
- return retval;
-}
-/* }}} */
-
-void mongo_init_Mongo(TSRMLS_D) {
- zend_class_entry ce;
-
- INIT_CLASS_ENTRY(ce, "Mongo", mongo_methods);
- ce.create_object = php_mongo_link_new;
- mongo_ce_Mongo = zend_register_internal_class(&ce TSRMLS_CC);
-
- /* make mongo_link object uncloneable, and with its own read_property */
- memcpy(&mongo_link_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers));
- mongo_link_handlers.clone_obj = NULL;
- mongo_link_handlers.read_property = mongo_read_property;
+ /* make mongoclient object uncloneable, and with its own read_property */
+ memcpy(&mongoclient_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers));
+ mongoclient_handlers.clone_obj = NULL;
+ mongoclient_handlers.read_property = mongo_read_property;
#if PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION >= 3
- mongo_link_handlers.get_debug_info = mongo_get_debug_info;
+ mongoclient_handlers.get_debug_info = mongo_get_debug_info;
#endif
-
-
- /* Mongo class constants */
- zend_declare_class_constant_string(mongo_ce_Mongo, "DEFAULT_HOST", strlen("DEFAULT_HOST"), "localhost" TSRMLS_CC);
- zend_declare_class_constant_long(mongo_ce_Mongo, "DEFAULT_PORT", strlen("DEFAULT_PORT"), 27017 TSRMLS_CC);
- zend_declare_class_constant_string(mongo_ce_Mongo, "VERSION", strlen("VERSION"), PHP_MONGO_VERSION TSRMLS_CC);
-
- /* Read preferences types */
- zend_declare_class_constant_long(mongo_ce_Mongo, "RP_PRIMARY", strlen("RP_PRIMARY"), MONGO_RP_PRIMARY TSRMLS_CC);
- zend_declare_class_constant_long(mongo_ce_Mongo, "RP_PRIMARY_PREFERRED", strlen("RP_PRIMARY_PREFERRED"), MONGO_RP_PRIMARY_PREFERRED TSRMLS_CC);
- zend_declare_class_constant_long(mongo_ce_Mongo, "RP_SECONDARY", strlen("RP_SECONDARY"), MONGO_RP_SECONDARY TSRMLS_CC);
- zend_declare_class_constant_long(mongo_ce_Mongo, "RP_SECONDARY_PREFERRED", strlen("RP_SECONDARY_PREFERRED"), MONGO_RP_SECONDARY_PREFERRED TSRMLS_CC);
- zend_declare_class_constant_long(mongo_ce_Mongo, "RP_NEAREST", strlen("RP_NEAREST"), MONGO_RP_NEAREST TSRMLS_CC);
-
- /* Mongo fields */
- zend_declare_property_bool(mongo_ce_Mongo, "connected", strlen("connected"), 0, ZEND_ACC_PUBLIC TSRMLS_CC);
- zend_declare_property_null(mongo_ce_Mongo, "status", strlen("status"), ZEND_ACC_PUBLIC TSRMLS_CC);
- zend_declare_property_null(mongo_ce_Mongo, "server", strlen("server"), ZEND_ACC_PROTECTED TSRMLS_CC);
- zend_declare_property_null(mongo_ce_Mongo, "persistent", strlen("persistent"), ZEND_ACC_PROTECTED TSRMLS_CC);
}
/* {{{ Mongo->__construct
- */
+*/
PHP_METHOD(Mongo, __construct)
{
- char *server = 0;
- int server_len = 0;
- zend_bool connect = 1;
- zval *options = 0, *slave_okay = 0;
- mongo_link *link;
- zval **opt_entry;
- char *opt_key, *error_message = NULL;
- uint opt_key_len;
- ulong num_key;
- HashPosition pos;
-
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s!a!/", &server, &server_len, &options) == FAILURE) {
- zval *object = getThis();
- ZVAL_NULL(object);
- return;
- }
-
- link = (mongo_link*)zend_object_store_get_object(getThis() TSRMLS_CC);
-
- /* Set the manager from the global manager */
- link->manager = MonGlo(manager);
-
- /* Parse the server specification
- * Default to the mongo.default_host & mongo.default_port INI options */
- link->servers = mongo_parse_init();
- if (server) {
- if (mongo_parse_server_spec(link->manager, link->servers, server, (char **)&error_message)) {
- zend_throw_exception(mongo_ce_ConnectionException, error_message, 0 TSRMLS_CC);
- free(error_message);
- return;
- }
- } else {
- char *tmp;
- int error;
-
- spprintf(&tmp, 0, "%s:%d", MonGlo(default_host), MonGlo(default_port));
- error = mongo_parse_server_spec(link->manager, link->servers, tmp, (char **)&error_message);
- efree(tmp);
-
- if (error) {
- zend_throw_exception(mongo_ce_ConnectionException, error_message, 0 TSRMLS_CC);
- free(error_message);
- return;
- }
- }
-
- /* Options through array */
- if (options) {
- for (zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(options), &pos);
- zend_hash_get_current_data_ex(Z_ARRVAL_P(options), (void **)&opt_entry, &pos) == SUCCESS;
- zend_hash_move_forward_ex(Z_ARRVAL_P(options), &pos)
- ) {
- switch (zend_hash_get_current_key_ex(Z_ARRVAL_P(options), &opt_key, &opt_key_len, &num_key, 0, &pos)) {
- case HASH_KEY_IS_STRING: {
- int error = 0;
- convert_to_string_ex(opt_entry);
- error = mongo_store_option(link->manager, link->servers, opt_key, Z_STRVAL_PP(opt_entry), (char **)&error_message);
-
- switch (error) {
- case 3: /* Logical error (i.e. conflicting options)*/
- case 1: /* Empty option name or value */
- zend_throw_exception(mongo_ce_ConnectionException, error_message, 0 TSRMLS_CC);
- free(error_message);
- return;
-
- case 2: /* Unknown connection string option, additional options for object configuration are checked here */
- if (strcasecmp(opt_key, "connect") == 0) {
- convert_to_boolean_ex(opt_entry);
- connect = Z_BVAL_PP(opt_entry);
- free(error_message);
- } else {
- zend_throw_exception(mongo_ce_ConnectionException, error_message, 0 TSRMLS_CC);
- free(error_message);
- return;
- }
- break;
- }
- } break;
-
- case HASH_KEY_IS_LONG:
- zend_throw_exception(mongo_ce_ConnectionException, "Unrecognized or unsupported option", 0 TSRMLS_CC);
- return;
- }
- }
- }
-
- slave_okay = zend_read_static_property(mongo_ce_Cursor, "slaveOkay", strlen("slaveOkay"), NOISY TSRMLS_CC);
- if (Z_BVAL_P(slave_okay)) {
- if (link->servers->read_pref.type != MONGO_RP_PRIMARY) {
- /* the server already has read preferences configured, but we're still
- * trying to set slave okay. The spec says that's an error */
- zend_throw_exception(mongo_ce_ConnectionException, "You can not use both slaveOkay and read-preferences. Please switch to read-preferences.", 0 TSRMLS_CC);
- return;
- } else {
- /* Old style option, that needs to be removed. For now, spec dictates
- * it needs to be ReadPreference=SECONDARY_PREFERRED */
- link->servers->read_pref.type = MONGO_RP_SECONDARY_PREFERRED;
- }
- }
-
- if (connect) {
- MONGO_METHOD(Mongo, connectUtil, NULL, getThis());
- }
-}
-/* }}} */
-
-/* {{{ Helper for connecting the servers */
-static mongo_connection *php_mongo_connect(mongo_link *link TSRMLS_DC)
-{
- mongo_connection *con;
- char *error_message = NULL;
-
- /* We don't care about the result so although we assign it to a var, we
- * only do that to handle errors and return it so that the calling function
- * knows whether a connection could be obtained or not. */
- con = mongo_get_read_write_connection(link->manager, link->servers, MONGO_CON_FLAG_READ, (char **) &error_message);
- if (!con) {
- if (error_message) {
- zend_throw_exception(mongo_ce_ConnectionException, error_message, 71 TSRMLS_CC);
- free(error_message);
- } else {
- zend_throw_exception(mongo_ce_ConnectionException, "Unknown error obtaining connection", 72 TSRMLS_CC);
- }
- return NULL;
- }
- return con;
-}
-
-/* {{{ Mongo->connect
- */
-PHP_METHOD(Mongo, connect)
-{
- mongo_link *link;
-
- PHP_MONGO_GET_LINK(getThis());
- RETURN_BOOL(php_mongo_connect(link TSRMLS_CC) != NULL);
+ php_mongo_ctor(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
}
/* }}} */
-/* {{{ Mongo->connectUtil
- */
-PHP_METHOD(Mongo, connectUtil)
+PHP_METHOD(Mongo, getSlaveOkay)
{
- mongo_link *link;
-
+ mongoclient *link;
PHP_MONGO_GET_LINK(getThis());
- php_mongo_connect(link TSRMLS_CC);
+ RETURN_BOOL(link->servers->read_pref.type != MONGO_RP_PRIMARY);
}
-/* }}} */
-
-/* {{{ proto int Mongo->close([string|bool hash|all])
- Closes the connection to $hash, or only master - or all open connections. Returns how many connections were closed */
-PHP_METHOD(Mongo, close)
+PHP_METHOD(Mongo, getSlave)
{
- char *hash = NULL;
- int hash_len;
- mongo_link *link;
- mongo_connection *connection;
- char *error_message = NULL;
- zval *all = NULL;
+ mongoclient *link;
+ mongo_connection *con;
PHP_MONGO_GET_LINK(getThis());
-
- if (ZEND_NUM_ARGS() == 0) {
- /* BC: Close master when no arguments passed */
- connection = mongo_get_read_write_connection(link->manager, link->servers, MONGO_CON_FLAG_WRITE|MONGO_CON_FLAG_DONT_CONNECT, (char **) &error_message);
- RETVAL_LONG(close_connection(link->manager, connection));
- } else if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS() TSRMLS_CC, "z", &all) == SUCCESS && Z_TYPE_P(all) == IS_BOOL) {
- if (Z_BVAL_P(all)) {
- /* Close all connections */
- mongo_con_manager_item *ptr = link->manager->connections;
- mongo_con_manager_item *current;
- long count = 0;
-
- while (ptr) {
- current = ptr;
- ptr = ptr->next;
- close_connection(link->manager, current->connection);
- count++;
- }
-
- RETVAL_LONG(count);
- } else {
- /* Close master */
- connection = mongo_get_read_write_connection(link->manager, link->servers, MONGO_CON_FLAG_WRITE|MONGO_CON_FLAG_DONT_CONNECT, (char **) &error_message);
- RETVAL_LONG(close_connection(link->manager, connection));
- }
- } else if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &hash, &hash_len) == SUCCESS) {
- /* Lookup hash and destroy it */
- connection = mongo_manager_connection_find_by_hash(link->manager, hash);
- if (!connection) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "A connection with hash '%s' does not exist.", hash);
- RETURN_LONG(0);
- }
- RETVAL_LONG(close_connection(link->manager, connection));
- } else {
+ con = php_mongo_connect(link TSRMLS_CC);
+ if (!con) {
+ /* We have to return here, as otherwise the exception doesn't trigger
+ * before we return the hash at the end. */
return;
}
- if (error_message) {
- free(error_message);
- }
-}
-/* }}} */
-
-static int close_connection(mongo_con_manager *manager, mongo_connection *connection)
-{
- if (connection) {
- mongo_manager_connection_deregister(manager, connection);
- return 1;
- } else {
- return 0;
- }
-}
-
-static void stringify_server(mongo_server_def *server, smart_str *str)
-{
- /* if this host is not connected, enclose in []s: [localhost:27017]
- if (!server->connected) {
- str[*pos] = '[';
- *(pos) = *pos + 1;
- }
- */
-
- /* copy host */
- smart_str_appends(str, server->host);
- smart_str_appendc(str, ':');
- smart_str_append_long(str, server->port);
-
- /* close []s
- if (!server->connected) {
- str[*pos] = ']';
- *(pos) = *pos + 1;
- }
- */
-}
-
-
-/* {{{ Mongo->__toString()
- */
-PHP_METHOD(Mongo, __toString) {
- smart_str str = { 0 };
- mongo_link *link;
- int i;
-
- PHP_MONGO_GET_LINK(getThis());
-
- for (i = 0; i < link->servers->count; i++) {
- /* if this is not the first one, add a comma */
- if (i) {
- smart_str_appendc(&str, ',');
- }
-
- stringify_server(link->servers->server[i], &str);
- }
-
- smart_str_0(&str);
-
- RETURN_STRING(str.c, 0);
-}
-/* }}} */
-
-
-/* {{{ Mongo->selectDB()
- */
-PHP_METHOD(Mongo, selectDB) {
- zval temp, *name;
- char *db;
- int db_len;
- mongo_link *link;
-
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &db, &db_len) == FAILURE) {
- return;
- }
-
- MAKE_STD_ZVAL(name);
- ZVAL_STRING(name, db, 1);
-
- PHP_MONGO_GET_LINK(getThis());
-
- /* We need to check whether we are switching to a database that was not
- * part of the connection string. This is not a problem if we are not using
- * authentication, but it is if we are. If we are, we need to do some fancy
- * cloning and creating a new mongo_servers structure. Authentication is a
- * pain™ */
- if (link->servers->server[0]->db && strcmp(link->servers->server[0]->db, db) != 0) {
- mongo_manager_log(
- link->manager, MLOG_CON, MLOG_FINE,
- "The requested database (%s) is not what we have in the link info (%s)",
- db, link->servers->server[0]->db
- );
- /* So here we check if a username and password are used. If so, the
- * madness starts */
- if (link->servers->server[0]->username && link->servers->server[0]->password) {
- zval *new_link;
- mongo_link *tmp_link;
-
- if (strcmp(link->servers->server[0]->db, "admin") == 0) {
- mongo_manager_log(
- link->manager, MLOG_CON, MLOG_FINE,
- "The link info has 'admin' as database, no need to clone it then"
- );
- } else {
- mongo_manager_log(
- link->manager, MLOG_CON, MLOG_INFO,
- "We are in an authenticated link (db: %s, user: %s), so we need to clone it.",
- link->servers->server[0]->db, link->servers->server[0]->username
- );
-
- /* Create the new link object */
- MAKE_STD_ZVAL(new_link);
- object_init_ex(new_link, mongo_ce_Mongo);
- tmp_link = (mongo_link*) zend_object_store_get_object(new_link TSRMLS_CC);
-
- tmp_link->manager = link->manager;
- tmp_link->servers = calloc(1, sizeof(mongo_servers));
- mongo_servers_copy(tmp_link->servers, link->servers, MONGO_SERVER_COPY_NONE);
-
- this_ptr = new_link;
- }
- }
- }
-
- object_init_ex(return_value, mongo_ce_DB);
- MONGO_METHOD2(MongoDB, __construct, &temp, return_value, getThis(), name);
-
- zval_ptr_dtor(&name);
-}
-/* }}} */
-
-
-/* {{{ Mongo::__get
- */
-PHP_METHOD(Mongo, __get) {
- zval *name;
- char *str;
- int str_len;
-
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &str, &str_len) == FAILURE) {
- return;
- }
-
- MAKE_STD_ZVAL(name);
- ZVAL_STRING(name, str, 1);
-
- // select this db
- MONGO_METHOD1(Mongo, selectDB, return_value, getThis(), name);
-
- zval_ptr_dtor(&name);
-}
-/* }}} */
-
-
-/* {{{ Mongo::selectCollection()
- */
-PHP_METHOD(Mongo, selectCollection) {
- char *db, *coll;
- int db_len, coll_len;
- zval *db_name, *coll_name, *temp_db;
-
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss", &db, &db_len, &coll, &coll_len) == FAILURE) {
- return;
- }
-
- MAKE_STD_ZVAL(db_name);
- ZVAL_STRING(db_name, db, 1);
-
- MAKE_STD_ZVAL(temp_db);
- MONGO_METHOD1(Mongo, selectDB, temp_db, getThis(), db_name);
- zval_ptr_dtor(&db_name);
- PHP_MONGO_CHECK_EXCEPTION1(&temp_db);
-
- MAKE_STD_ZVAL(coll_name);
- ZVAL_STRING(coll_name, coll, 1);
-
- MONGO_METHOD1(MongoDB, selectCollection, return_value, temp_db, coll_name);
-
- zval_ptr_dtor(&coll_name);
- zval_ptr_dtor(&temp_db);
-}
-/* }}} */
-
-PHP_METHOD(Mongo, getSlaveOkay)
-{
- mongo_link *link;
- PHP_MONGO_GET_LINK(getThis());
- RETURN_BOOL(link->servers->read_pref.type != MONGO_RP_PRIMARY);
+ RETURN_STRING(con->hash, 1);
}
PHP_METHOD(Mongo, setSlaveOkay)
{
zend_bool slave_okay = 1;
- mongo_link *link;
+ mongoclient *link;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|b", &slave_okay) == FAILURE) {
return;
@@ -706,290 +132,75 @@ PHP_METHOD(Mongo, setSlaveOkay)
}
-PHP_METHOD(Mongo, getReadPreference)
-{
- mongo_link *link;
- PHP_MONGO_GET_LINK(getThis());
-
- array_init(return_value);
- add_assoc_long(return_value, "type", link->servers->read_pref.type);
- add_assoc_string(return_value, "type_string", mongo_read_preference_type_to_name(link->servers->read_pref.type), 1);
- php_mongo_add_tagsets(return_value, &link->servers->read_pref);
-}
-
-/* {{{ Mongo::setReadPreference(int read_preference [, array tags ])
- * Sets a read preference to be used for all read queries.*/
-PHP_METHOD(Mongo, setReadPreference)
-{
- long read_preference;
- mongo_link *link;
- HashTable *tags = NULL;
-
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l|h", &read_preference, &tags) == FAILURE) {
- return;
- }
-
- PHP_MONGO_GET_LINK(getThis());
-
- if (read_preference >= MONGO_RP_FIRST && read_preference <= MONGO_RP_LAST) {
- link->servers->read_pref.type = read_preference;
- } else {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "The value %ld is not valid as read preference type", read_preference);
- RETURN_FALSE;
- }
- if (tags) {
- if (read_preference == MONGO_RP_PRIMARY) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "You can't use read preference tags with a read preference of PRIMARY");
- RETURN_FALSE;
- }
-
- if (!php_mongo_use_tagsets(&link->servers->read_pref, tags TSRMLS_CC)) {
- RETURN_FALSE;
- }
- }
- RETURN_TRUE;
-}
-/* }}} */
-
-/* {{{ Mongo::dropDB()
- */
-PHP_METHOD(Mongo, dropDB) {
- zval *db, *temp_db;
-
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &db) == FAILURE) {
- RETURN_FALSE;
- }
-
- if (Z_TYPE_P(db) != IS_OBJECT ||
- Z_OBJCE_P(db) != mongo_ce_DB) {
- MAKE_STD_ZVAL(temp_db);
- ZVAL_NULL(temp_db);
-
- // reusing db param from Mongo::drop call
- MONGO_METHOD_BASE(Mongo, selectDB)(1, temp_db, NULL, getThis(), 0 TSRMLS_CC);
- db = temp_db;
- }
- else {
- zval_add_ref(&db);
- }
-
- MONGO_METHOD(MongoDB, drop, return_value, db);
- zval_ptr_dtor(&db);
-}
-/* }}} */
-
-/* {{{ Mongo->listDBs
- */
-PHP_METHOD(Mongo, listDBs) {
- zval *admin, *data, *db;
-
- MAKE_STD_ZVAL(admin);
- ZVAL_STRING(admin, "admin", 1);
-
- MAKE_STD_ZVAL(db);
-
- MONGO_METHOD1(Mongo, selectDB, db, getThis(), admin);
-
- zval_ptr_dtor(&admin);
-
- MAKE_STD_ZVAL(data);
- array_init(data);
- add_assoc_long(data, "listDatabases", 1);
-
- MONGO_CMD(return_value, db);
-
- zval_ptr_dtor(&data);
- zval_ptr_dtor(&db);
-}
-/* }}} */
-
-PHP_METHOD(Mongo, getHosts)
-{
- mongo_link *link;
- mongo_con_manager_item *item;
-
- PHP_MONGO_GET_LINK(getThis());
- item = link->manager->connections;
-
- array_init(return_value);
-
- while (item) {
- zval *infoz;
- char *host;
- int port;
-
- MAKE_STD_ZVAL(infoz);
- array_init(infoz);
-
- mongo_server_split_hash(item->connection->hash, (char**) &host, (int*) &port, NULL, NULL, NULL, NULL, NULL);
- add_assoc_string(infoz, "host", host, 1);
- add_assoc_long(infoz, "port", port);
- free(host);
-
- add_assoc_long(infoz, "health", 1);
- add_assoc_long(infoz, "state", item->connection->connection_type == MONGO_NODE_PRIMARY ? 1 : (item->connection->connection_type == MONGO_NODE_SECONDARY ? 2 : 0));
- add_assoc_long(infoz, "ping", item->connection->ping_ms);
- add_assoc_long(infoz, "lastPing", item->connection->last_ping);
-
- add_assoc_zval(return_value, item->connection->hash, infoz);
- item = item->next;
- }
-}
-
-PHP_METHOD(Mongo, getSlave)
-{
- mongo_link *link;
- mongo_connection *con;
-
- PHP_MONGO_GET_LINK(getThis());
- con = php_mongo_connect(link TSRMLS_CC);
- if (!con) {
- /* We have to return here, as otherwise the exception doesn't trigger
- * before we return the hash at the end. */
- return;
- }
-
- RETURN_STRING(con->hash, 1);
-}
-
-/* {{{ proto static array Mongo::getConnections(void)
- Returns an array of all open connections, and information about each of the servers */
-PHP_METHOD(Mongo, getConnections)
-{
- mongo_con_manager_item *ptr;
+static void run_err(int err_type, zval *return_value, zval *this_ptr TSRMLS_DC) {
+ zval *db_name, *db;
+ MAKE_STD_ZVAL(db_name);
+ ZVAL_STRING(db_name, "admin", 1);
- if (zend_parse_parameters_none() == FAILURE) {
- return;
- }
+ MAKE_STD_ZVAL(db);
+ MONGO_METHOD1(MongoClient, selectDB, db, getThis(), db_name);
+ zval_ptr_dtor(&db_name);
- ptr = MonGlo(manager)->connections;
-
- array_init(return_value);
- while (ptr) {
- zval *entry, *server, *connection, *tags;
- char *host, *repl_set_name, *database, *username, *auth_hash;
- int port, pid, i;
-
- MAKE_STD_ZVAL(entry);
- array_init(entry);
-
- MAKE_STD_ZVAL(server);
- array_init(server);
-
- MAKE_STD_ZVAL(connection);
- array_init(connection);
-
- MAKE_STD_ZVAL(tags);
- array_init(tags);
-
- /* Grab server information */
- mongo_server_split_hash(ptr->connection->hash, &host, &port, &repl_set_name, &database, &username, &auth_hash, &pid);
-
- add_assoc_string(server, "host", host, 1);
- free(host);
- add_assoc_long(server, "port", port);
- if (repl_set_name) {
- add_assoc_string(server, "repl_set_name", repl_set_name, 1);
- free(repl_set_name);
- }
- if (database) {
- add_assoc_string(server, "database", database, 1);
- free(database);
- }
- if (username) {
- add_assoc_string(server, "username", username, 1);
- free(username);
- }
- if (auth_hash) {
- add_assoc_string(server, "auth_hash", auth_hash, 1);
- free(auth_hash);
- }
- add_assoc_long(server, "pid", pid);
-
- /* Grab connection info */
- add_assoc_long(connection, "last_ping", ptr->connection->last_ping);
- add_assoc_long(connection, "last_ismaster", ptr->connection->last_ismaster);
- add_assoc_long(connection, "ping_ms", ptr->connection->ping_ms);
- add_assoc_long(connection, "connection_type", ptr->connection->connection_type);
- add_assoc_string(connection, "connection_type_desc", mongo_connection_type(ptr->connection->connection_type), 1);
- add_assoc_long(connection, "max_bson_size", ptr->connection->max_bson_size);
- add_assoc_long(connection, "tag_count", ptr->connection->tag_count);
- for (i = 0; i < ptr->connection->tag_count; i++) {
- add_next_index_string(tags, ptr->connection->tags[i], 1);
- }
- add_assoc_zval(connection, "tags", tags);
-
- /* Top level elements */
- add_assoc_string(entry, "hash", ptr->connection->hash, 1);
- add_assoc_zval(entry, "server", server);
- add_assoc_zval(entry, "connection", connection);
- add_next_index_zval(return_value, entry);
-
- ptr = ptr->next;
+ switch (err_type) {
+ case LAST_ERROR:
+ MONGO_METHOD(MongoDB, lastError, return_value, db);
+ break;
+ case PREV_ERROR:
+ MONGO_METHOD(MongoDB, prevError, return_value, db);
+ break;
+ case RESET_ERROR:
+ MONGO_METHOD(MongoDB, resetError, return_value, db);
+ break;
+ case FORCE_ERROR:
+ MONGO_METHOD(MongoDB, forceError, return_value, db);
+ break;
}
-}
-/* }}} */
-
-PHP_METHOD(Mongo, switchSlave)
-{
- zim_Mongo_switchSlave(INTERNAL_FUNCTION_PARAM_PASSTHRU);
-}
-static void run_err(int err_type, zval *return_value, zval *this_ptr TSRMLS_DC) {
- zval *db_name, *db;
- MAKE_STD_ZVAL(db_name);
- ZVAL_STRING(db_name, "admin", 1);
-
- MAKE_STD_ZVAL(db);
- MONGO_METHOD1(Mongo, selectDB, db, getThis(), db_name);
- zval_ptr_dtor(&db_name);
-
- switch (err_type) {
- case LAST_ERROR:
- MONGO_METHOD(MongoDB, lastError, return_value, db);
- break;
- case PREV_ERROR:
- MONGO_METHOD(MongoDB, prevError, return_value, db);
- break;
- case RESET_ERROR:
- MONGO_METHOD(MongoDB, resetError, return_value, db);
- break;
- case FORCE_ERROR:
- MONGO_METHOD(MongoDB, forceError, return_value, db);
- break;
- }
-
- zval_ptr_dtor(&db);
+ zval_ptr_dtor(&db);
}
-
/* {{{ Mongo->lastError()
- */
+*/
PHP_METHOD(Mongo, lastError) {
- run_err(LAST_ERROR, return_value, getThis() TSRMLS_CC);
+ run_err(LAST_ERROR, return_value, getThis() TSRMLS_CC);
}
/* }}} */
/* {{{ Mongo->prevError()
- */
+*/
PHP_METHOD(Mongo, prevError) {
- run_err(PREV_ERROR, return_value, getThis() TSRMLS_CC);
+ run_err(PREV_ERROR, return_value, getThis() TSRMLS_CC);
}
/* }}} */
/* {{{ Mongo->resetError()
- */
+*/
PHP_METHOD(Mongo, resetError) {
- run_err(RESET_ERROR, return_value, getThis() TSRMLS_CC);
+ run_err(RESET_ERROR, return_value, getThis() TSRMLS_CC);
}
/* }}} */
-
/* {{{ Mongo->forceError()
- */
+*/
PHP_METHOD(Mongo, forceError) {
- run_err(FORCE_ERROR, return_value, getThis() TSRMLS_CC);
+ run_err(FORCE_ERROR, return_value, getThis() TSRMLS_CC);
}
/* }}} */
+/* {{{ Mongo->connectUtil
+ */
+PHP_METHOD(Mongo, connectUtil)
+{
+ mongoclient *link;
+
+ PHP_MONGO_GET_LINK(getThis());
+ php_mongo_connect(link TSRMLS_CC);
+}
+/* }}} */
+
+PHP_METHOD(Mongo, switchSlave)
+{
+ zim_Mongo_getSlave(INTERNAL_FUNCTION_PARAM_PASSTHRU);
+}
+/* }}} */
View
21 mongo.h
@@ -13,8 +13,9 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-#ifndef MONGO_H
-#define MONGO_H
+
+#ifndef __MONGO_H__
+#define __MONGO_H__
int php_mongo_create_le(mongo_cursor *cursor, char *name TSRMLS_DC);
@@ -24,30 +25,14 @@ void mongo_init_Mongo(TSRMLS_D);
* Mongo class
*/
PHP_METHOD(Mongo, __construct);
-PHP_METHOD(Mongo, getConnections);
-PHP_METHOD(Mongo, connect);
-PHP_METHOD(Mongo, pairConnect);
-PHP_METHOD(Mongo, persistConnect);
-PHP_METHOD(Mongo, pairPersistConnect);
PHP_METHOD(Mongo, connectUtil);
-PHP_METHOD(Mongo, __toString);
-PHP_METHOD(Mongo, __get);
-PHP_METHOD(Mongo, selectDB);
-PHP_METHOD(Mongo, selectCollection);
PHP_METHOD(Mongo, getSlaveOkay);
PHP_METHOD(Mongo, setSlaveOkay);
-PHP_METHOD(Mongo, getReadPreference);
-PHP_METHOD(Mongo, setReadPreference);
-PHP_METHOD(Mongo, dropDB);
PHP_METHOD(Mongo, lastError);
PHP_METHOD(Mongo, prevError);
PHP_METHOD(Mongo, resetError);
PHP_METHOD(Mongo, forceError);
-PHP_METHOD(Mongo, close);
-PHP_METHOD(Mongo, listDBs);
-PHP_METHOD(Mongo, getHosts);
PHP_METHOD(Mongo, getSlave);
PHP_METHOD(Mongo, switchSlave);
#endif
-
View
5 mongo_types.c
@@ -27,9 +27,8 @@
#include <ext/standard/php_rand.h>
#include "php_mongo.h"
-#include "mongo.h"
+#include "mongoclient.h"
#include "mongo_types.h"
-#include "php_mongo.h"
#include "db.h"
#include "collection.h"
#include "bson.h"
@@ -728,7 +727,7 @@ PHP_METHOD(MongoDBRef, get) {
MAKE_STD_ZVAL(new_db_z);
ZVAL_NULL(new_db_z);
- MONGO_METHOD1(Mongo, selectDB, new_db_z, temp_db->link, *dbname);
+ MONGO_METHOD1(MongoClient, selectDB, new_db_z, temp_db->link, *dbname);
// make the new db the current one
db = new_db_z;
View
881 mongoclient.c
@@ -0,0 +1,881 @@
+/**
+ * Copyright 2009-2012 10gen, 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 <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
+#ifndef WIN32
+#include <sys/types.h>
+#endif
+
+#include <php.h>
+#include <zend_exceptions.h>
+#include "ext/standard/php_smart_str.h"
+
+#include "php_mongo.h"
+#include "mongoclient.h"
+#include "db.h"
+#include "cursor.h"
+#include "mongo_types.h"
+#include "bson.h"
+
+#include "util/log.h"
+#include "util/pool.h"
+
+#include "mcon/types.h"
+#include "mcon/read_preference.h"
+#include "mcon/parse.h"
+#include "mcon/manager.h"
+#include "mcon/utils.h"
+
+
+static void php_mongoclient_free(void* TSRMLS_DC);
+static void run_err(int, zval*, zval* TSRMLS_DC);
+static void stringify_server(mongo_server_def *server, smart_str *str);
+static int close_connection(mongo_con_manager *manager, mongo_connection *connection);
+
+zend_object_handlers mongo_default_handlers;
+zend_object_handlers mongoclient_handlers;
+
+ZEND_EXTERN_MODULE_GLOBALS(mongo);
+
+zend_class_entry *mongo_ce_MongoClient;
+
+extern zend_class_entry *mongo_ce_DB,
+ *mongo_ce_Cursor,
+ *mongo_ce_Exception,
+ *mongo_ce_ConnectionException;
+
+MONGO_ARGINFO_STATIC ZEND_BEGIN_ARG_INFO_EX(arginfo___construct, 0, ZEND_RETURN_VALUE, 0)
+ ZEND_ARG_INFO(0, server)
+ ZEND_ARG_ARRAY_INFO(0, options, 0)
+ZEND_END_ARG_INFO()
+
+MONGO_ARGINFO_STATIC ZEND_BEGIN_ARG_INFO_EX(arginfo___get, 0, ZEND_RETURN_VALUE, 1)
+ ZEND_ARG_INFO(0, name)
+ZEND_END_ARG_INFO()
+
+MONGO_ARGINFO_STATIC ZEND_BEGIN_ARG_INFO_EX(arginfo_no_parameters, 0, ZEND_RETURN_VALUE, 0)
+ZEND_END_ARG_INFO()
+
+MONGO_ARGINFO_STATIC ZEND_BEGIN_ARG_INFO_EX(arginfo_selectDB, 0, ZEND_RETURN_VALUE, 1)
+ ZEND_ARG_INFO(0, database_name)
+ZEND_END_ARG_INFO()
+
+MONGO_ARGINFO_STATIC ZEND_BEGIN_ARG_INFO_EX(arginfo_selectCollection, 0, ZEND_RETURN_VALUE, 1)
+ ZEND_ARG_INFO(0, database_name)
+ ZEND_ARG_INFO(0, collection_name)
+ZEND_END_ARG_INFO()
+
+MONGO_ARGINFO_STATIC ZEND_BEGIN_ARG_INFO_EX(arginfo_setReadPreference, 0, ZEND_RETURN_VALUE, 1)
+ ZEND_ARG_INFO(0, read_preference)
+ ZEND_ARG_ARRAY_INFO(0, tags, 0)
+ZEND_END_ARG_INFO()
+
+MONGO_ARGINFO_STATIC ZEND_BEGIN_ARG_INFO_EX(arginfo_dropDB, 0, ZEND_RETURN_VALUE, 1)
+ ZEND_ARG_INFO(0, MongoDB_object_OR_database_name)
+ZEND_END_ARG_INFO()
+
+static zend_function_entry mongo_methods[] = {
+ PHP_ME(MongoClient, __construct, arginfo___construct, ZEND_ACC_PUBLIC)
+ PHP_ME(MongoClient, getConnections, arginfo_no_parameters, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
+ PHP_ME(MongoClient, connect, arginfo_no_parameters, ZEND_ACC_PUBLIC)
+ PHP_ME(MongoClient, __toString, arginfo_no_parameters, ZEND_ACC_PUBLIC)
+ PHP_ME(MongoClient, __get, arginfo___get, ZEND_ACC_PUBLIC)
+ PHP_ME(MongoClient, selectDB, arginfo_selectDB, ZEND_ACC_PUBLIC)
+ PHP_ME(MongoClient, selectCollection, arginfo_selectCollection, ZEND_ACC_PUBLIC)
+ PHP_ME(MongoClient, getReadPreference, arginfo_no_parameters, ZEND_ACC_PUBLIC)
+ PHP_ME(MongoClient, setReadPreference, arginfo_setReadPreference, ZEND_ACC_PUBLIC)
+ PHP_ME(MongoClient, dropDB, arginfo_dropDB, ZEND_ACC_PUBLIC)
+ PHP_ME(MongoClient, listDBs, arginfo_no_parameters, ZEND_ACC_PUBLIC)
+ PHP_ME(MongoClient, getHosts, arginfo_no_parameters, ZEND_ACC_PUBLIC)
+ PHP_ME(MongoClient, close, arginfo_no_parameters, ZEND_ACC_PUBLIC)
+
+{ NULL, NULL, NULL }
+};
+
+/* {{{ php_mongoclient_free
+ */
+static void php_mongoclient_free(void *object TSRMLS_DC)
+{
+ mongoclient *link = (mongoclient*)object;
+
+ /* already freed */
+ if (!link) {
+ return;
+ }
+
+ if (link->servers) {
+ mongo_servers_dtor(link->servers);
+ }
+
+ zend_object_std_dtor(&link->std TSRMLS_CC);
+
+ efree(link);
+}
+/* }}} */
+
+#if PHP_VERSION_ID >= 50400
+zval *mongo_read_property(zval *object, zval *member, int type, const zend_literal *key TSRMLS_DC)
+#else
+zval *mongo_read_property(zval *object, zval *member, int type TSRMLS_DC)
+#endif
+{
+ zval *retval;
+ zval tmp_member;
+ mongoclient *obj;
+
+ if (member->type != IS_STRING) {
+ tmp_member = *member;
+ zval_copy_ctor(&tmp_member);
+ convert_to_string(&tmp_member);
+ member = &tmp_member;
+ }
+
+ obj = (mongoclient *)zend_objects_get_address(object TSRMLS_CC);
+ if (strcmp(Z_STRVAL_P(member), "connected") == 0) {
+ char *error_message = NULL;
+ mongo_connection *conn = mongo_get_read_write_connection(obj->manager, obj->servers, MONGO_CON_FLAG_READ|MONGO_CON_FLAG_DONT_CONNECT, (char**) &error_message);
+ ALLOC_INIT_ZVAL(retval);
+ Z_SET_REFCOUNT_P(retval, 0);
+ ZVAL_BOOL(retval, conn ? 1 : 0);
+ if (error_message) {
+ free(error_message);
+ }
+ return retval;
+ }
+
+#if PHP_VERSION_ID >= 50400
+ retval = (zend_get_std_object_handlers())->read_property(object, member, type, key TSRMLS_CC);
+#else
+ retval = (zend_get_std_object_handlers())->read_property(object, member, type TSRMLS_CC);
+#endif
+ if (member == &tmp_member) {
+ zval_dtor(member);
+ }
+ return retval;
+}
+
+#if PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION >= 3
+HashTable *mongo_get_debug_info(zval *object, int *is_temp TSRMLS_DC)
+{
+ HashPosition pos;
+ HashTable *props = zend_std_get_properties(object TSRMLS_CC);
+ zval **entry;
+ ulong num_key;
+
+ zend_hash_internal_pointer_reset_ex(props, &pos);
+ while (zend_hash_get_current_data_ex(props, (void **)&entry, &pos) == SUCCESS) {
+ char *key;
+ uint key_len;
+
+ switch (zend_hash_get_current_key_ex(props, &key, &key_len, &num_key, 0, &pos)) {
+ case HASH_KEY_IS_STRING: {
+ /* Override the connected property like we do for the read_property handler */
+ if (strcmp(key, "connected") == 0) {
+ zval member;
+ zval *tmp;
+ INIT_ZVAL(member);
+ ZVAL_STRINGL(&member, key, key_len, 0);
+
+#if PHP_VERSION_ID >= 50400
+ tmp = mongo_read_property(object, &member, BP_VAR_IS, NULL TSRMLS_CC);
+#else
+ tmp = mongo_read_property(object, &member, BP_VAR_IS TSRMLS_CC);
+#endif
+ convert_to_boolean_ex(entry);
+ ZVAL_BOOL(*entry, Z_BVAL_P(tmp));
+ /* the var is set to refcount = 0, need to set it to 1 so it'll get free()d */
+ if (Z_REFCOUNT_P(tmp) == 0) {
+ Z_SET_REFCOUNT_P(tmp, 1);
+ }
+ zval_ptr_dtor(&tmp);
+ }
+ break;
+ }
+ case HASH_KEY_IS_LONG:
+ case HASH_KEY_NON_EXISTANT:
+ break;
+ }
+ zend_hash_move_forward_ex(props, &pos);
+ }
+
+ *is_temp = 0;
+ return props;
+}
+#endif
+
+
+/* {{{ php_mongoclient_new
+ */
+zend_object_value php_mongoclient_new(zend_class_entry *class_type TSRMLS_DC)
+{
+ zend_object_value retval;
+ mongoclient *intern;
+ zval *tmp;
+
+ intern = (mongoclient*)emalloc(sizeof(mongoclient));
+ memset(intern, 0, sizeof(mongoclient));
+
+ zend_object_std_init(&intern->std, class_type TSRMLS_CC);
+ init_properties(intern);
+
+ retval.handle = zend_objects_store_put(intern, (zend_objects_store_dtor_t) zend_objects_destroy_object, php_mongoclient_free, NULL TSRMLS_CC);
+ retval.handlers = &mongoclient_handlers;
+
+ return retval;
+}
+/* }}} */
+
+void mongo_init_MongoClient(TSRMLS_D)
+{
+ zend_class_entry ce;
+
+ INIT_CLASS_ENTRY(ce, "MongoClient", mongo_methods);
+ ce.create_object = php_mongoclient_new;
+ mongo_ce_MongoClient = zend_register_internal_class(&ce TSRMLS_CC);
+
+ /* make mongoclient object uncloneable, and with its own read_property */
+ memcpy(&mongoclient_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers));
+ mongoclient_handlers.clone_obj = NULL;
+ mongoclient_handlers.read_property = mongo_read_property;
+#if PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION >= 3
+ mongoclient_handlers.get_debug_info = mongo_get_debug_info;
+#endif
+
+ /* Mongo class constants */
+ zend_declare_class_constant_string(mongo_ce_MongoClient, "DEFAULT_HOST", strlen("DEFAULT_HOST"), "localhost" TSRMLS_CC);
+ zend_declare_class_constant_long(mongo_ce_MongoClient, "DEFAULT_PORT", strlen("DEFAULT_PORT"), 27017 TSRMLS_CC);
+ zend_declare_class_constant_string(mongo_ce_MongoClient, "VERSION", strlen("VERSION"), PHP_MONGO_VERSION TSRMLS_CC);
+
+ /* Read preferences types */
+ zend_declare_class_constant_long(mongo_ce_MongoClient, "RP_PRIMARY", strlen("RP_PRIMARY"), MONGO_RP_PRIMARY TSRMLS_CC);
+ zend_declare_class_constant_long(mongo_ce_MongoClient, "RP_PRIMARY_PREFERRED", strlen("RP_PRIMARY_PREFERRED"), MONGO_RP_PRIMARY_PREFERRED TSRMLS_CC);
+ zend_declare_class_constant_long(mongo_ce_MongoClient, "RP_SECONDARY", strlen("RP_SECONDARY"), MONGO_RP_SECONDARY TSRMLS_CC);
+ zend_declare_class_constant_long(mongo_ce_MongoClient, "RP_SECONDARY_PREFERRED", strlen("RP_SECONDARY_PREFERRED"), MONGO_RP_SECONDARY_PREFERRED TSRMLS_CC);
+ zend_declare_class_constant_long(mongo_ce_MongoClient, "RP_NEAREST", strlen("RP_NEAREST"), MONGO_RP_NEAREST TSRMLS_CC);
+
+ /* Mongo fields */
+ zend_declare_property_bool(mongo_ce_MongoClient, "connected", strlen("connected"), 0, ZEND_ACC_PUBLIC TSRMLS_CC);
+ zend_declare_property_null(mongo_ce_MongoClient, "status", strlen("status"), ZEND_ACC_PUBLIC TSRMLS_CC);
+ zend_declare_property_null(mongo_ce_MongoClient, "server", strlen("server"), ZEND_ACC_PROTECTED TSRMLS_CC);
+ zend_declare_property_null(mongo_ce_MongoClient, "persistent", strlen("persistent"), ZEND_ACC_PROTECTED TSRMLS_CC);
+}
+
+/* {{{ Helper for connecting the servers */
+mongo_connection *php_mongo_connect(mongoclient *link TSRMLS_DC)
+{
+ mongo_connection *con;
+ char *error_message = NULL;
+
+ /* We don't care about the result so although we assign it to a var, we
+ * only do that to handle errors and return it so that the calling function
+ * knows whether a connection could be obtained or not. */
+ con = mongo_get_read_write_connection(link->manager, link->servers, MONGO_CON_FLAG_READ, (char **) &error_message);
+ if (!con) {
+ if (error_message) {
+ zend_throw_exception(mongo_ce_ConnectionException, error_message, 71 TSRMLS_CC);
+ free(error_message);
+ } else {
+ zend_throw_exception(mongo_ce_ConnectionException, "Unknown error obtaining connection", 72 TSRMLS_CC);
+ }
+ return NULL;
+ }
+ return con;
+}
+/* }}} */
+
+/* {{{ MongoClient->__construct
+ */
+PHP_METHOD(MongoClient, __construct)
+{
+ php_mongo_ctor(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
+}
+
+void php_mongo_ctor(INTERNAL_FUNCTION_PARAMETERS, int bc)
+{
+ char *server = 0;
+ int server_len = 0;
+ zend_bool connect = 1;
+ zval *options = 0;
+ zval *slave_okay = 0;
+ mongoclient *link;
+ zval **opt_entry;
+ char *opt_key;
+ char *error_message = NULL;
+ uint opt_key_len;
+ ulong num_key;
+ HashPosition pos;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s!a!/", &server, &server_len, &options) == FAILURE) {
+ zval *object = getThis();
+ ZVAL_NULL(object);
+ return;
+ }
+
+ link = (mongoclient*)zend_object_store_get_object(getThis() TSRMLS_CC);
+
+ /* Set the manager from the global manager */
+ link->manager = MonGlo(manager);
+
+ /* Parse the server specification
+ * Default to the mongo.default_host & mongo.default_port INI options */
+ link->servers = mongo_parse_init();
+ if (server) {
+ if (mongo_parse_server_spec(link->manager, link->servers, server, (char **)&error_message)) {
+ zend_throw_exception(mongo_ce_ConnectionException, error_message, 0 TSRMLS_CC);
+ free(error_message);
+ return;
+ }
+ } else {
+ char *tmp;
+ int error;
+
+ spprintf(&tmp, 0, "%s:%d", MonGlo(default_host), MonGlo(default_port));
+ error = mongo_parse_server_spec(link->manager, link->servers, tmp, (char **)&error_message);
+ efree(tmp);
+
+ if (error) {
+ zend_throw_exception(mongo_ce_ConnectionException, error_message, 0 TSRMLS_CC);
+ free(error_message);
+ return;
+ }
+ }
+
+ /* If "w" was *not* set as an option, then assign the default */
+ if (link->servers->default_w == -1) {
+ if (bc) {
+ /* Default to WriteConcern=0 for Mongo */
+ link->servers->default_w = 0;
+ } else {
+ /* Default to WriteConcern=1 for MongoClient */
+ link->servers->default_w = 1;
+ }
+ }
+
+ /* Options through array */
+ if (options) {
+ for (zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(options), &pos);
+ zend_hash_get_current_data_ex(Z_ARRVAL_P(options), (void **)&opt_entry, &pos) == SUCCESS;
+ zend_hash_move_forward_ex(Z_ARRVAL_P(options), &pos)
+ ) {
+ switch (zend_hash_get_current_key_ex(Z_ARRVAL_P(options), &opt_key, &opt_key_len, &num_key, 0, &pos)) {
+ case HASH_KEY_IS_STRING: {
+ int error = 0;
+ convert_to_string_ex(opt_entry);
+ error = mongo_store_option(link->manager, link->servers, opt_key, Z_STRVAL_PP(opt_entry), (char **)&error_message);
+
+ switch (error) {
+ case 3: /* Logical error (i.e. conflicting options)*/
+ case 1: /* Empty option name or value */
+ zend_throw_exception(mongo_ce_ConnectionException, error_message, 0 TSRMLS_CC);
+ free(error_message);
+ return;
+
+ case 2: /* Unknown connection string option, additional options for object configuration are checked here */
+ if (strcasecmp(opt_key, "connect") == 0) {
+ convert_to_boolean_ex(opt_entry);
+ connect = Z_BVAL_PP(opt_entry);
+ free(error_message);
+ } else {
+ zend_throw_exception(mongo_ce_ConnectionException, error_message, 0 TSRMLS_CC);
+ free(error_message);
+ return;
+ }
+ break;
+ }
+ } break;
+
+ case HASH_KEY_IS_LONG:
+ zend_throw_exception(mongo_ce_ConnectionException, "Unrecognized or unsupported option", 0 TSRMLS_CC);
+ return;
+ }
+ }
+ }
+
+ slave_okay = zend_read_static_property(mongo_ce_Cursor, "slaveOkay", strlen("slaveOkay"), NOISY TSRMLS_CC);
+ if (Z_BVAL_P(slave_okay)) {
+ if (link->servers->read_pref.type != MONGO_RP_PRIMARY) {
+ /* the server already has read preferences configured, but we're still
+ * trying to set slave okay. The spec says that's an error */
+ zend_throw_exception(mongo_ce_ConnectionException, "You can not use both slaveOkay and read-preferences. Please switch to read-preferences.", 0 TSRMLS_CC);
+ return;
+ } else {
+ /* Old style option, that needs to be removed. For now, spec dictates
+ * it needs to be ReadPreference=SECONDARY_PREFERRED */
+ link->servers->read_pref.type = MONGO_RP_SECONDARY_PREFERRED;
+ }
+ }
+
+ if (connect) {
+ php_mongo_connect(link TSRMLS_CC);
+ }
+}
+/* }}} */
+
+
+/* {{{ MongoClient->connect
+ */
+PHP_METHOD(MongoClient, connect)
+{
+ mongoclient *link;
+
+ PHP_MONGO_GET_LINK(getThis());
+ RETURN_BOOL(php_mongo_connect(link TSRMLS_CC) != NULL);
+}
+/* }}} */
+
+
+/* {{{ proto int MongoClient->close([string|bool hash|all])
+ Closes the connection to $hash, or only master - or all open connections. Returns how many connections were closed */
+PHP_METHOD(MongoClient, close)
+{
+ char *hash = NULL;
+ int hash_len;
+ mongoclient *link;
+ mongo_connection *connection;
+ char *error_message = NULL;
+ zval *all = NULL;
+
+ PHP_MONGO_GET_LINK(getThis());
+ if (ZEND_NUM_ARGS() == 0) {
+ /* BC: Close master when no arguments passed */
+ connection = mongo_get_read_write_connection(link->manager, link->servers, MONGO_CON_FLAG_WRITE|MONGO_CON_FLAG_DONT_CONNECT, (char **) &error_message);
+ RETVAL_LONG(close_connection(link->manager, connection));
+ } else if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS() TSRMLS_CC, "z", &all) == SUCCESS && Z_TYPE_P(all) == IS_BOOL) {
+ if (Z_BVAL_P(all)) {
+ /* Close all connections */
+ mongo_con_manager_item *ptr = link->manager->connections;
+ mongo_con_manager_item *current;
+ long count = 0;
+
+ while (ptr) {
+ current = ptr;
+ ptr = ptr->next;
+ close_connection(link->manager, current->connection);
+ count++;
+ }
+
+ RETVAL_LONG(count);
+ } else {
+ /* Close master */
+ connection = mongo_get_read_write_connection(link->manager, link->servers, MONGO_CON_FLAG_WRITE|MONGO_CON_FLAG_DONT_CONNECT, (char **) &error_message);
+ RETVAL_LONG(close_connection(link->manager, connection));
+ }
+ } else if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &hash, &hash_len) == SUCCESS) {
+ /* Lookup hash and destroy it */
+ connection = mongo_manager_connection_find_by_hash(link->manager, hash);
+ if (!connection) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "A connection with hash '%s' does not exist.", hash);
+ RETURN_LONG(0);
+ }
+ RETVAL_LONG(close_connection(link->manager, connection));
+ } else {
+ return;
+ }
+
+ if (error_message) {
+ free(error_message);
+ }
+ RETURN_TRUE;
+}
+/* }}} */
+
+static int close_connection(mongo_con_manager *manager, mongo_connection *connection)
+{
+ if (connection) {
+ mongo_manager_connection_deregister(manager, connection);
+ return 1;
+ } else {
+ return 0;
+ }
+}
+
+static void stringify_server(mongo_server_def *server, smart_str *str)
+{
+ /* copy host */
+ smart_str_appends(str, server->host);
+ smart_str_appendc(str, ':');
+ smart_str_append_long(str, server->port);
+}
+
+
+/* {{{ MongoClient->__toString()
+ */
+PHP_METHOD(MongoClient, __toString)
+{
+ smart_str str = { 0 };
+ mongoclient *link;
+ int i;
+
+ PHP_MONGO_GET_LINK(getThis());
+
+ for (i = 0; i < link->servers->count; i++) {
+ /* if this is not the first one, add a comma */
+ if (i) {
+ smart_str_appendc(&str, ',');
+ }
+
+ stringify_server(link->servers->server[i], &str);
+ }
+
+ smart_str_0(&str);
+
+ RETURN_STRING(str.c, 0);
+}
+/* }}} */
+
+
+/* {{{ MongoClient->selectDB()
+ */
+PHP_METHOD(MongoClient, selectDB)
+{
+ zval temp, *name;
+ char *db;
+ int db_len;
+ mongoclient *link;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &db, &db_len) == FAILURE) {
+ return;
+ }
+
+ MAKE_STD_ZVAL(name);
+ ZVAL_STRING(name, db, 1);
+
+ PHP_MONGO_GET_LINK(getThis());
+
+ /* We need to check whether we are switching to a database that was not
+ * part of the connection string. This is not a problem if we are not using
+ * authentication, but it is if we are. If we are, we need to do some fancy
+ * cloning and creating a new mongo_servers structure. Authentication is a
+ * pain™ */
+ if (link->servers->server[0]->db && strcmp(link->servers->server[0]->db, db) != 0) {
+ mongo_manager_log(
+ link->manager, MLOG_CON, MLOG_FINE,
+ "The requested database (%s) is not what we have in the link info (%s)",
+ db, link->servers->server[0]->db
+ );
+ /* So here we check if a username and password are used. If so, the
+ * madness starts */
+ if (link->servers->server[0]->username && link->servers->server[0]->password) {
+ zval *new_link;
+ mongoclient *tmp_link;
+
+ if (strcmp(link->servers->server[0]->db, "admin") == 0) {
+ mongo_manager_log(
+ link->manager, MLOG_CON, MLOG_FINE,
+ "The link info has 'admin' as database, no need to clone it then"
+ );
+ } else {
+ mongo_manager_log(
+ link->manager, MLOG_CON, MLOG_INFO,
+ "We are in an authenticated link (db: %s, user: %s), so we need to clone it.",
+ link->servers->server[0]->db, link->servers->server[0]->username
+ );
+
+ /* Create the new link object */
+ MAKE_STD_ZVAL(new_link);
+ object_init_ex(new_link, mongo_ce_MongoClient);
+ tmp_link = (mongoclient*) zend_object_store_get_object(new_link TSRMLS_CC);
+
+ tmp_link->manager = link->manager;
+ tmp_link->servers = calloc(1, sizeof(mongo_servers));
+ mongo_servers_copy(tmp_link->servers, link->servers, MONGO_SERVER_COPY_NONE);
+
+ this_ptr = new_link;
+ }
+ }
+ }
+
+ object_init_ex(return_value, mongo_ce_DB);
+ MONGO_METHOD2(MongoDB, __construct, &temp, return_value, getThis(), name);
+
+ zval_ptr_dtor(&name);
+}
+/* }}} */
+
+
+/* {{{ Mongo::__get
+ */
+PHP_METHOD(MongoClient, __get)
+{
+ zval *name;
+ char *str;
+ int str_len;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &str, &str_len) == FAILURE) {
+ return;
+ }
+
+ MAKE_STD_ZVAL(name);
+ ZVAL_STRING(name, str, 1);
+
+ /* select this db */
+ MONGO_METHOD1(MongoClient, selectDB, return_value, getThis(), name);
+
+ zval_ptr_dtor(&name);
+}
+/* }}} */
+
+
+/* {{{ Mongo::selectCollection()
+ */
+PHP_METHOD(MongoClient, selectCollection)
+{
+ char *db, *coll;
+ int db_len, coll_len;
+ zval *db_name, *coll_name, *temp_db;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss", &db, &db_len, &coll, &coll_len) == FAILURE) {
+ return;
+ }
+
+ MAKE_STD_ZVAL(db_name);
+ ZVAL_STRING(db_name, db, 1);
+
+ MAKE_STD_ZVAL(temp_db);
+ MONGO_METHOD1(MongoClient, selectDB, temp_db, getThis(), db_name);
+ zval_ptr_dtor(&db_name);
+ PHP_MONGO_CHECK_EXCEPTION1(&temp_db);
+
+ MAKE_STD_ZVAL(coll_name);
+ ZVAL_STRING(coll_name, coll, 1);
+
+ MONGO_METHOD1(MongoDB, selectCollection, return_value, temp_db, coll_name);
+
+ zval_ptr_dtor(&coll_name);
+ zval_ptr_dtor(&temp_db);
+}
+/* }}} */
+
+
+/* {{{ array Mongo::getReadPreference()
+ * Returns the currently set read preference.*/
+PHP_METHOD(MongoClient, getReadPreference)
+{
+ mongoclient *link;
+ PHP_MONGO_GET_LINK(getThis());
+
+ array_init(return_value);
+ add_assoc_long(return_value, "type", link->servers->read_pref.type);
+ add_assoc_string(return_value, "type_string", mongo_read_preference_type_to_name(link->servers->read_pref.type), 1);
+ php_mongo_add_tagsets(return_value, &link->servers->read_pref);
+}
+/* }}} */
+
+
+/* {{{ Mongo::setReadPreference(int read_preference [, array tags ])
+ * Sets a read preference to be used for all read queries.*/
+PHP_METHOD(MongoClient, setReadPreference)
+{
+ long read_preference;
+ mongoclient *link;
+ HashTable *tags = NULL;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l|h", &read_preference, &tags) == FAILURE) {
+ return;
+ }
+
+ PHP_MONGO_GET_LINK(getThis());
+
+ if (read_preference >= MONGO_RP_FIRST && read_preference <= MONGO_RP_LAST) {
+ link->servers->read_pref.type = read_preference;
+ } else {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "The value %ld is not valid as read preference type", read_preference);
+ RETURN_FALSE;
+ }
+ if (tags) {
+ if (read_preference == MONGO_RP_PRIMARY) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "You can't use read preference tags with a read preference of PRIMARY");
+ RETURN_FALSE;
+ }
+
+ if (!php_mongo_use_tagsets(&link->servers->read_pref, tags TSRMLS_CC)) {
+ RETURN_FALSE;
+ }
+ }
+ RETURN_TRUE;
+}
+/* }}} */
+
+
+/* {{{ Mongo::dropDB()
+ */
+PHP_METHOD(MongoClient, dropDB)
+{
+ zval *db, *temp_db;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &db) == FAILURE) {
+ RETURN_FALSE;
+ }
+
+ if (Z_TYPE_P(db) != IS_OBJECT || Z_OBJCE_P(db) != mongo_ce_DB) {