/* {{{ MongoDB::__construct */ PHP_METHOD(MongoDB, __construct) { zval *zlink; char *name; int name_len; mongo_db *db; mongo_link *link; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Os", &zlink, mongo_ce_Mongo, &name, &name_len) == FAILURE) { zval *object = getThis(); ZVAL_NULL(object); return; } if (0 == name_len || 0 != strchr(name, ' ') || 0 != strchr(name, '.') || 0 != strchr(name, '\\') || 0 != strchr(name, '/') || 0 != strchr(name, '$')) { #if ZEND_MODULE_API_NO >= 20060613 zend_throw_exception_ex(zend_exception_get_default(TSRMLS_C), 0 TSRMLS_CC, "MongoDB::__construct(): invalid name %s", name); #else zend_throw_exception_ex(zend_exception_get_default(), 0 TSRMLS_CC, "MongoDB::__construct(): invalid name %s", name); #endif /* ZEND_MODULE_API_NO >= 20060613 */ return; } db = (mongo_db*)zend_object_store_get_object(getThis() TSRMLS_CC); db->link = zlink; zval_add_ref(&db->link); PHP_MONGO_GET_LINK(zlink); db->slave_okay = link->slave_okay; MAKE_STD_ZVAL(db->name); ZVAL_STRING(db->name, name, 1); }
PHP_METHOD(Mongo, setSlaveOkay) { zend_bool slave_okay = 1; mongoclient *link; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|b", &slave_okay) == FAILURE) { return; } PHP_MONGO_GET_LINK(getThis()); RETVAL_BOOL(link->servers->read_pref.type != MONGO_RP_PRIMARY); link->servers->read_pref.type = slave_okay ? MONGO_RP_SECONDARY_PREFERRED : MONGO_RP_PRIMARY; }
PHP_METHOD(Mongo, getSlave) { mongoclient *link; mongo_connection *con; PHP_MONGO_GET_LINK(getThis()); con = php_mongo_connect(link, MONGO_CON_FLAG_READ 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); }
/* {{{ MongoDB::__construct */ PHP_METHOD(MongoDB, __construct) { zval *zlink; char *name; int name_len; mongo_db *db; mongoclient *link; 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; } if (0 == name_len || 0 != strchr(name, ' ') || 0 != strchr(name, '.') || 0 != strchr(name, '\\') || 0 != strchr(name, '/') || 0 != strchr(name, '$')) { #if ZEND_MODULE_API_NO >= 20060613 zend_throw_exception_ex(zend_exception_get_default(TSRMLS_C), 0 TSRMLS_CC, "MongoDB::__construct(): invalid name %s", name); #else zend_throw_exception_ex(zend_exception_get_default(), 0 TSRMLS_CC, "MongoDB::__construct(): invalid name %s", name); #endif /* ZEND_MODULE_API_NO >= 20060613 */ return; } db = (mongo_db*)zend_object_store_get_object(getThis() TSRMLS_CC); db->link = zlink; zval_add_ref(&db->link); PHP_MONGO_GET_LINK(zlink); if (link->servers->options.default_w != -1) { zend_update_property_long(mongo_ce_DB, getThis(), "w", strlen("w"), link->servers->options.default_w TSRMLS_CC); } else if (link->servers->options.default_wstring != NULL) { zend_update_property_string(mongo_ce_DB, getThis(), "w", strlen("w"), link->servers->options.default_wstring TSRMLS_CC); } if (link->servers->options.default_wtimeout != -1) { zend_update_property_long(mongo_ce_DB, getThis(), "wtimeout", strlen("wtimeout"), link->servers->options.default_wtimeout TSRMLS_CC); } mongo_read_preference_copy(&link->servers->read_pref, &db->read_pref); MAKE_STD_ZVAL(db->name); ZVAL_STRING(db->name, name, 1); }
PHP_METHOD(MongoDB, command) { zval limit, *temp, *cmd, *cursor, *ns, *options = 0; mongo_db *db; mongo_link *link; char *cmd_ns; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z|a", &cmd, &options) == FAILURE) { return; } if (IS_SCALAR_P(cmd)) { zend_error(E_WARNING, "MongoDB::command() expects parameter 1 to be an array or object"); return; } PHP_MONGO_GET_DB(getThis()); // create db.$cmd MAKE_STD_ZVAL(ns); cmd_ns = get_cmd_ns(Z_STRVAL_P(db->name), Z_STRLEN_P(db->name)); ZVAL_STRING(ns, cmd_ns, 0); // create cursor MAKE_STD_ZVAL(cursor); object_init_ex(cursor, mongo_ce_Cursor); MAKE_STD_ZVAL(temp); ZVAL_NULL(temp); MONGO_METHOD3(MongoCursor, __construct, temp, cursor, db->link, ns, cmd); zval_ptr_dtor(&ns); zval_ptr_dtor(&temp); MAKE_STD_ZVAL(temp); ZVAL_NULL(temp); // limit Z_TYPE(limit) = IS_LONG; Z_LVAL(limit) = -1; MONGO_METHOD1(MongoCursor, limit, temp, cursor, &limit); zval_ptr_dtor(&temp); if (options) { zval **timeout; if (zend_hash_find(HASH_P(options), "timeout", strlen("timeout")+1, (void**)&timeout) == SUCCESS) { MAKE_STD_ZVAL(temp); ZVAL_NULL(temp); MONGO_METHOD1(MongoCursor, timeout, temp, cursor, *timeout); zval_ptr_dtor(&temp); } } // make sure commands aren't be sent to slaves PHP_MONGO_GET_LINK(db->link); if (link->rs) { zval slave_okay; Z_TYPE(slave_okay) = IS_BOOL; Z_LVAL(slave_okay) = 0; MAKE_STD_ZVAL(temp); ZVAL_NULL(temp); MONGO_METHOD1(MongoCursor, slaveOkay, temp, cursor, &slave_okay); zval_ptr_dtor(&temp); } // query MONGO_METHOD(MongoCursor, getNext, return_value, cursor); clear_exception(return_value TSRMLS_CC); zend_objects_store_del_ref(cursor TSRMLS_CC); zval_ptr_dtor(&cursor); }
PHP_METHOD(Mongo, getSlaveOkay) { mongoclient *link; PHP_MONGO_GET_LINK(getThis()); RETURN_BOOL(link->servers->read_pref.type != MONGO_RP_PRIMARY); }
/* {{{ MongoCursor->__construct */ PHP_METHOD(MongoCursor, __construct) { zval *zlink = 0, *zns = 0, *zquery = 0, *zfields = 0, *empty, *timeout; zval **data; mongo_cursor *cursor; mongo_link *link; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Oz|zz", &zlink, mongo_ce_Mongo, &zns, &zquery, &zfields) == FAILURE) { return; } if ((zquery && IS_SCALAR_P(zquery)) || (zfields && IS_SCALAR_P(zfields))) { zend_error(E_WARNING, "MongoCursor::__construct() expects parameters 3 and 4 to be arrays or objects"); return; } // if query or fields weren't passed, make them default to an empty array MAKE_STD_ZVAL(empty); object_init(empty); // these are both initialized to the same zval, but that's okay because // there's no way to change them without creating a new cursor if (!zquery || (Z_TYPE_P(zquery) == IS_ARRAY && zend_hash_num_elements(HASH_P(zquery)) == 0)) { zquery = empty; } if (!zfields) { zfields = empty; } cursor = (mongo_cursor*)zend_object_store_get_object(getThis() TSRMLS_CC); // db connection cursor->resource = zlink; zval_add_ref(&zlink); // db connection resource PHP_MONGO_GET_LINK(zlink); cursor->link = link; // change ['x', 'y', 'z'] into {'x' : 1, 'y' : 1, 'z' : 1} if (Z_TYPE_P(zfields) == IS_ARRAY) { HashPosition pointer; zval *fields; MAKE_STD_ZVAL(fields); array_init(fields); // fields to return for(zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(zfields), &pointer); zend_hash_get_current_data_ex(Z_ARRVAL_P(zfields), (void**) &data, &pointer) == SUCCESS; zend_hash_move_forward_ex(Z_ARRVAL_P(zfields), &pointer)) { int key_type, key_len; ulong index; char *key; key_type = zend_hash_get_current_key_ex(Z_ARRVAL_P(zfields), &key, (uint*)&key_len, &index, NO_DUP, &pointer); if (key_type == HASH_KEY_IS_LONG) { if (Z_TYPE_PP(data) == IS_STRING) { add_assoc_long(fields, Z_STRVAL_PP(data), 1); } else { zval_ptr_dtor(&empty); zval_ptr_dtor(&fields); zend_throw_exception(mongo_ce_Exception, "field names must be strings", 0 TSRMLS_CC); return; } } else { add_assoc_zval(fields, key, *data); zval_add_ref(data); } } cursor->fields = fields; } // if it's already an object, we don't have to worry else { cursor->fields = zfields; zval_add_ref(&zfields); } // ns convert_to_string(zns); cursor->ns = estrdup(Z_STRVAL_P(zns)); // query cursor->query = zquery; zval_add_ref(&zquery); // reset iteration pointer, just in case MONGO_METHOD(MongoCursor, reset, return_value, getThis()); cursor->at = 0; cursor->num = 0; cursor->special = 0; cursor->persist = 0; timeout = zend_read_static_property(mongo_ce_Cursor, "timeout", strlen("timeout"), NOISY TSRMLS_CC); cursor->timeout = Z_LVAL_P(timeout); cursor->opts = link->slave_okay ? (1 << 2) : 0; // get rid of extra ref zval_ptr_dtor(&empty); }
PHP_METHOD(MongoDB, command) { zval limit, *temp, *cmd, *cursor, *ns, *options = 0; mongo_db *db; mongoclient *link; char *cmd_ns; mongo_cursor *cursor_tmp; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z|a", &cmd, &options) == FAILURE) { return; } MUST_BE_ARRAY_OR_OBJECT(1, cmd); PHP_MONGO_GET_DB(getThis()); // create db.$cmd MAKE_STD_ZVAL(ns); cmd_ns = get_cmd_ns(Z_STRVAL_P(db->name), Z_STRLEN_P(db->name)); ZVAL_STRING(ns, cmd_ns, 0); // create cursor MAKE_STD_ZVAL(cursor); object_init_ex(cursor, mongo_ce_Cursor); MAKE_STD_ZVAL(temp); ZVAL_NULL(temp); MONGO_METHOD3(MongoCursor, __construct, temp, cursor, db->link, ns, cmd); zval_ptr_dtor(&ns); zval_ptr_dtor(&temp); MAKE_STD_ZVAL(temp); ZVAL_NULL(temp); // limit Z_TYPE(limit) = IS_LONG; Z_LVAL(limit) = -1; MONGO_METHOD1(MongoCursor, limit, temp, cursor, &limit); zval_ptr_dtor(&temp); if (options) { zval **timeout; if (zend_hash_find(HASH_P(options), "timeout", strlen("timeout")+1, (void**)&timeout) == SUCCESS) { MAKE_STD_ZVAL(temp); ZVAL_NULL(temp); MONGO_METHOD1(MongoCursor, timeout, temp, cursor, *timeout); zval_ptr_dtor(&temp); } } /* Make sure commands aren't be sent to slaves */ /* TODO: The read preferences spec has a list of commands that *can* be send * to slave */ /* This should be refactored alongside with the getLastError redirection in * collection.c/append_getlasterror. The Cursor creation should be done through * an init method. */ PHP_MONGO_GET_LINK(db->link); cursor_tmp = (mongo_cursor*)zend_object_store_get_object(cursor TSRMLS_CC); mongo_manager_log(link->manager, MLOG_CON, MLOG_INFO, "forcing primary for command"); php_mongo_connection_force_primary(cursor_tmp); // query MONGO_METHOD(MongoCursor, getNext, return_value, cursor); clear_exception(return_value TSRMLS_CC); zend_objects_store_del_ref(cursor TSRMLS_CC); zval_ptr_dtor(&cursor); }