Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Fetching contributors…

Cannot retrieve contributors at this time

775 lines (621 sloc) 21.058 kB
// mongo.c
/**
* Copyright 2009-2011 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 "php_mongo.h"
#include "mongo.h"
#include "db.h"
#include "cursor.h"
#include "mongo_types.h"
#include "bson.h"
#include "util/rs.h"
#include "util/parse.h"
#include "util/io.h"
#include "util/hash.h"
#include "util/connect.h"
#include "util/pool.h"
#include "util/link.h"
#include "util/server.h"
#include "util/log.h"
static void php_mongo_link_free(void* TSRMLS_DC);
static void run_err(int, zval*, zval* TSRMLS_DC);
static char* stringify_server(mongo_server*, char*, int*, int*);
zend_object_handlers mongo_default_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;
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)
/* Those two used to be there, but no longer it seems
ZEND_ARG_INFO(0, persist)
ZEND_ARG_INFO(0, garbage)
*/
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_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_END_ARG_INFO()
static zend_function_entry mongo_methods[] = {
PHP_ME(Mongo, __construct, arginfo___construct, ZEND_ACC_PUBLIC)
PHP_ME(Mongo, connect, arginfo_no_parameters, ZEND_ACC_PUBLIC)
PHP_ME(Mongo, pairConnect, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_DEPRECATED)
PHP_ME(Mongo, persistConnect, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_DEPRECATED)
PHP_ME(Mongo, pairPersistConnect, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_DEPRECATED)
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)
PHP_ME(Mongo, setSlaveOkay, arginfo_setSlaveOkay, 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)
PHP_ME(Mongo, switchSlave, arginfo_no_parameters, ZEND_ACC_PUBLIC)
PHP_ME(Mongo, close, arginfo_no_parameters, ZEND_ACC_PUBLIC)
PHP_ME(Mongo, setPoolSize, arginfo_setPoolSize, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
PHP_ME(Mongo, getPoolSize, arginfo_no_parameters, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
PHP_ME(Mongo, poolDebug, arginfo_no_parameters, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
PHP_ME(Mongo, serverInfo, arginfo_no_parameters, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
{ NULL, NULL, NULL }
};
void php_mongo_server_free(mongo_server *server, int persist TSRMLS_DC) {
// return this connection to the pool
mongo_util_pool_done(server TSRMLS_CC);
if (server->host) {
pefree(server->host, persist);
server->host = 0;
}
if (server->label) {
pefree(server->label, persist);
server->label = 0;
}
if (server->username) {
pefree(server->username, persist);
server->username = 0;
}
if (server->password) {
pefree(server->password, persist);
server->password = 0;
}
if (server->db) {
pefree(server->db, persist);
server->db = 0;
}
pefree(server, persist);
}
static void php_mongo_server_set_free(mongo_server_set *server_set TSRMLS_DC) {
mongo_server *current;
if (!server_set) {
return;
}
current = server_set->server;
while (current) {
mongo_server *temp = current->next;
php_mongo_server_free(current, NO_PERSIST TSRMLS_CC);
current = temp;
}
efree(server_set);
}
/* {{{ 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->rs) {
mongo_server *current = link->server_set->server;
if (link->server_set->master) {
php_mongo_server_free(link->server_set->master, NO_PERSIST TSRMLS_CC);
}
if (link->slave) {
php_mongo_server_free(link->slave, NO_PERSIST TSRMLS_CC);
}
}
php_mongo_server_set_free(link->server_set TSRMLS_CC);
if (link->username) efree(link->username);
if (link->password) efree(link->password);
if (link->db) efree(link->db);
if (link->rs) efree(link->rs);
zend_object_std_dtor(&link->std TSRMLS_CC);
efree(link);
}
/* }}} */
/* {{{ php_mongo_link_new
*/
static zend_object_value php_mongo_link_new(zend_class_entry *class_type TSRMLS_DC) {
php_mongo_obj_new(mongo_link);
}
/* }}} */
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);
/* 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);
/* 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 persist = 0, garbage = 0, connect = 1;
zval *options = 0, *slave_okay = 0;
mongo_link *link;
mongo_server *current;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|szbb", &server, &server_len, &options, &persist, &garbage) == FAILURE) {
return;
}
link = (mongo_link*)zend_object_store_get_object(getThis() TSRMLS_CC);
slave_okay = zend_read_static_property(mongo_ce_Cursor, "slaveOkay", strlen("slaveOkay"), NOISY TSRMLS_CC);
link->slave_okay = Z_BVAL_P(slave_okay);
// new format
if (options) {
if (!IS_SCALAR_P(options)) {
zval **timeout_z, **replica_z, **slave_okay_z, **username_z, **password_z,
**db_z, **connect_z;
if (zend_hash_find(HASH_P(options), "timeout", strlen("timeout")+1, (void**)&timeout_z) == SUCCESS) {
link->timeout = Z_LVAL_PP(timeout_z);
}
if (zend_hash_find(HASH_P(options), "replicaSet", strlen("replicaSet")+1, (void**)&replica_z) == SUCCESS) {
if (Z_TYPE_PP(replica_z) == IS_STRING) {
link->rs = estrdup(Z_STRVAL_PP(replica_z));
}
else if (Z_BVAL_PP(replica_z)) {
link->rs = estrdup("replicaSet");
}
}
if (zend_hash_find(HASH_P(options), "slaveOkay", strlen("slaveOkay")+1, (void**)&slave_okay_z) == SUCCESS) {
link->slave_okay = Z_BVAL_PP(slave_okay_z);
}
if (zend_hash_find(HASH_P(options), "username", sizeof("username"), (void**)&username_z) == SUCCESS) {
link->username = estrdup(Z_STRVAL_PP(username_z));
}
if (zend_hash_find(HASH_P(options), "password", sizeof("password"), (void**)&password_z) == SUCCESS) {
link->password = estrdup(Z_STRVAL_PP(password_z));
}
if (zend_hash_find(HASH_P(options), "db", sizeof("db"), (void**)&db_z) == SUCCESS) {
link->db = estrdup(Z_STRVAL_PP(db_z));
}
if (zend_hash_find(HASH_P(options), "connect", sizeof("connect"), (void**)&connect_z) == SUCCESS) {
connect = Z_BVAL_PP(connect_z);
}
}
else {
// backwards compatibility
connect = Z_BVAL_P(options);
if (MonGlo(allow_persistent) && persist) {
zend_update_property_string(mongo_ce_Mongo, getThis(), "persistent", strlen("persistent"), "" TSRMLS_CC);
}
}
}
// If someone accidently does something like $hst instead of $host, we'll get
// the empty string.
if (server && strlen(server) == 0) {
zend_throw_exception(mongo_ce_ConnectionException, "no server name given", 1 TSRMLS_CC);
}
zend_update_property_stringl(mongo_ce_Mongo, getThis(), "server", strlen("server"), server, server_len TSRMLS_CC);
// parse the server name given
if (php_mongo_parse_server(getThis() TSRMLS_CC) == FAILURE) {
// exception thrown in parse_server
return;
}
// initialize any connection pools needed (doesn't actually connect)
current = link->server_set->server;
while (current) {
mongo_util_pool_init(current, (time_t)link->timeout TSRMLS_CC);
current = current->next;
}
if (connect) {
MONGO_METHOD(Mongo, connectUtil, NULL, getThis());
}
}
/* }}} */
/* {{{ Mongo->connect
*/
PHP_METHOD(Mongo, connect) {
MONGO_METHOD(Mongo, connectUtil, return_value, getThis());
}
/* {{{ Mongo->pairConnect
*/
PHP_METHOD(Mongo, pairConnect) {
zend_error(E_WARNING, "Deprecated, use constructor instead");
}
/* {{{ Mongo->persistConnect
*/
PHP_METHOD(Mongo, persistConnect) {
zend_error(E_WARNING, "Deprecated, use constructor instead");
}
/* {{{ Mongo->pairPersistConnect
*/
PHP_METHOD(Mongo, pairPersistConnect) {
zend_error(E_WARNING, "Deprecated, use constructor instead");
}
PHP_METHOD(Mongo, connectUtil) {
int connected = 0;
mongo_link *link;
char *msg = 0;
zval *connected_z = 0;
connected_z = zend_read_property(mongo_ce_Mongo, getThis(), "connected", strlen("connected"),
QUIET TSRMLS_CC);
if (Z_TYPE_P(connected_z) == IS_BOOL && Z_BVAL_P(connected_z)) {
RETURN_TRUE;
}
link = (mongo_link*)zend_object_store_get_object(getThis() TSRMLS_CC);
if (link->rs) {
// connected will be 1 unless something goes very wrong. we might not
// actually be connected
connected = (mongo_util_rs_init(link TSRMLS_CC) == SUCCESS);
if (!connected && !EG(exception)) {
msg = estrdup("Could not create replica set connection");
}
}
else {
mongo_server *current;
current = link->server_set->server;
while (current) {
zval *errmsg;
MAKE_STD_ZVAL(errmsg);
ZVAL_NULL(errmsg);
connected |= (mongo_util_pool_get(current, errmsg TSRMLS_CC) == SUCCESS);
if (!msg && Z_TYPE_P(errmsg) == IS_STRING) {
msg = estrndup(Z_STRVAL_P(errmsg), Z_STRLEN_P(errmsg));
}
zval_ptr_dtor(&errmsg);
current = current->next;
}
}
if (!connected) {
zend_throw_exception(mongo_ce_ConnectionException, msg, 0 TSRMLS_CC);
}
else {
zend_update_property_bool(mongo_ce_Mongo, getThis(), "connected",
strlen("connected"), 1 TSRMLS_CC);
if (return_value) {
ZVAL_BOOL(return_value, 1);
}
}
if (msg) {
efree(msg);
}
}
/* {{{ Mongo->close()
*/
PHP_METHOD(Mongo, close) {
mongo_link *link;
PHP_MONGO_GET_LINK(getThis());
mongo_util_link_disconnect(link TSRMLS_CC);
zend_update_property_bool(mongo_ce_Mongo, getThis(), "connected",
strlen("connected"), 0 TSRMLS_CC);
RETURN_TRUE;
}
/* }}} */
static char* stringify_server(mongo_server *server, char *str, int *pos, int *len) {
// length: "[" + strlen(hostname) + ":" + strlen(port (maxint=12)) + "]"
if (*len - *pos < (int)strlen(server->host)+15) {
int new_len = *len + 256 + (2 * (strlen(server->host)+15));
str = (char*)erealloc(str, new_len);
*(len) = new_len;
}
// if this host is not connected, enclose in []s: [localhost:27017]
if (!server->connected) {
str[*pos] = '[';
*(pos) = *pos + 1;
}
// copy host
memcpy(str+*pos, server->label, strlen(server->label));
*(pos) = *pos + strlen(server->label);
// close []s
if (!server->connected) {
str[*pos] = ']';
*(pos) = *pos + 1;
}
return str;
}
/* {{{ Mongo->__toString()
*/
PHP_METHOD(Mongo, __toString) {
int tpos = 0, tlen = 256, *pos, *len;
char *str;
mongo_server *server;
mongo_link *link = (mongo_link*)zend_object_store_get_object(getThis() TSRMLS_CC);
// if we haven't connected yet, we should still be able to get the __toString
// from the server field
if (!link->server_set) {
zval *server = zend_read_property(mongo_ce_Mongo, getThis(), "server", strlen("server"), NOISY TSRMLS_CC);
RETURN_ZVAL(server, 1, 0);
}
pos = &tpos;
len = &tlen;
str = (char*)emalloc(*len);
// stringify the master, if there is one
if (link->server_set->master) {
str = stringify_server(link->server_set->master, str, pos, len);
}
server = link->server_set->server;
// stringify each server
while (server) {
if (server == link->server_set->master) {
server = server->next;
continue;
}
// if this is not the first one, add a comma
if (*pos != 0) {
str[*pos] = ',';
*(pos) = *pos+1;
}
str = stringify_server(server, str, pos, len);
server = server->next;
}
str[*pos] = '\0';
RETURN_STRING(str, 0);
}
/* }}} */
/* {{{ Mongo->selectDB()
*/
PHP_METHOD(Mongo, selectDB) {
zval temp, *name;
char *db;
int db_len;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &db, &db_len) == FAILURE) {
return;
}
MAKE_STD_ZVAL(name);
ZVAL_STRING(name, db, 1);
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->slave_okay);
}
PHP_METHOD(Mongo, setSlaveOkay) {
zend_bool slave_okay = 1;
mongo_link *link;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|b", &slave_okay) == FAILURE) {
return;
}
PHP_MONGO_GET_LINK(getThis());
RETVAL_BOOL(link->slave_okay);
link->slave_okay = slave_okay;
}
/* {{{ 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;
rsm_server *current;
rs_monitor *monitor;
array_init(return_value);
PHP_MONGO_GET_LINK(getThis());
monitor = mongo_util_rs__get_monitor(link TSRMLS_CC);
current = monitor->servers;
while (current) {
zval *infoz;
server_info *info;
MAKE_STD_ZVAL(infoz);
array_init(infoz);
info = mongo_util_server__get_info(current->server TSRMLS_CC);
add_assoc_long(infoz, "health", info->guts->readable);
add_assoc_long(infoz, "state", info->guts->master ? 1 : info->guts->readable ? 2 : 0);
if (info->guts->pinged) {
add_assoc_long(infoz, "ping", info->guts->ping);
add_assoc_long(infoz, "lastPing", info->guts->last_ping);
}
add_assoc_zval(return_value, current->server->label, infoz);
current = current->next;
}
}
PHP_METHOD(Mongo, getSlave) {
mongo_link *link;
PHP_MONGO_GET_LINK(getThis());
if (link->rs && link->slave) {
RETURN_STRING(link->slave->label, 1);
}
}
PHP_METHOD(Mongo, switchSlave) {
mongo_link *link;
char *errmsg = 0;
PHP_MONGO_GET_LINK(getThis());
if (!link->rs) {
zend_throw_exception(mongo_ce_Exception,
"Reading from slaves won't work without using the replicaSet option on connect",
15 TSRMLS_CC);
return;
}
mongo_util_rs_ping(link TSRMLS_CC);
if (mongo_util_rs__set_slave(link, &errmsg TSRMLS_CC) == FAILURE) {
if (!EG(exception)) {
if (errmsg) {
zend_throw_exception(mongo_ce_Exception, errmsg, 16 TSRMLS_CC);
efree(errmsg);
}
else {
zend_throw_exception(mongo_ce_Exception, "No server found for reads", 16 TSRMLS_CC);
}
}
return;
}
MONGO_METHOD(Mongo, getSlave, return_value, getThis());
}
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);
}
/* {{{ Mongo->lastError()
*/
PHP_METHOD(Mongo, lastError) {
run_err(LAST_ERROR, return_value, getThis() TSRMLS_CC);
}
/* }}} */
/* {{{ Mongo->prevError()
*/
PHP_METHOD(Mongo, prevError) {
run_err(PREV_ERROR, return_value, getThis() TSRMLS_CC);
}
/* }}} */
/* {{{ Mongo->resetError()
*/
PHP_METHOD(Mongo, resetError) {
run_err(RESET_ERROR, return_value, getThis() TSRMLS_CC);
}
/* }}} */
/* {{{ Mongo->forceError()
*/
PHP_METHOD(Mongo, forceError) {
run_err(FORCE_ERROR, return_value, getThis() TSRMLS_CC);
}
/* }}} */
Jump to Line
Something went wrong with that request. Please try again.