/* {{{ MongoCursor::timeout */ PHP_METHOD(MongoCursor, timeout) { long timeout; mongo_cursor *cursor; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &timeout) == FAILURE) { return; } PHP_MONGO_GET_CURSOR(getThis()); cursor->timeout = timeout; RETURN_ZVAL(getThis(), 1, 0); }
/* {{{ MongoCursor->doQuery */ PHP_METHOD(MongoCursor, doQuery) { mongo_cursor *cursor; PHP_MONGO_GET_CURSOR(getThis()); do { MONGO_METHOD(MongoCursor, reset, return_value, getThis()); if (mongo_cursor__do_query(getThis(), return_value TSRMLS_CC) == SUCCESS || EG(exception)) { return; } } while (mongo_cursor__should_retry(cursor)); if (strcmp(".$cmd", cursor->ns+(strlen(cursor->ns)-5)) == 0) { mongo_cursor_throw(cursor->server, 19 TSRMLS_CC, "couldn't send command"); return; } mongo_cursor_throw(cursor->server, 19 TSRMLS_CC, "max number of retries exhausted, couldn't send query"); }
PHP_METHOD(MongoCursor, count) { zval *db_z, *coll, *query; mongo_cursor *cursor; mongo_collection *c; mongo_db *db; zend_bool all = 0; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|b", &all) == FAILURE) { return; } PHP_MONGO_GET_CURSOR(getThis()); // fake a MongoDB object MAKE_STD_ZVAL(db_z); object_init_ex(db_z, mongo_ce_DB); db = (mongo_db*)zend_object_store_get_object(db_z TSRMLS_CC); db->link = cursor->resource; MAKE_STD_ZVAL(db->name); ZVAL_STRING(db->name, estrndup(cursor->ns, strchr(cursor->ns, '.') - cursor->ns), 0); // fake a MongoCollection object MAKE_STD_ZVAL(coll); object_init_ex(coll, mongo_ce_Collection); c = (mongo_collection*)zend_object_store_get_object(coll TSRMLS_CC); MAKE_STD_ZVAL(c->ns); ZVAL_STRING(c->ns, estrdup(cursor->ns), 0); MAKE_STD_ZVAL(c->name); ZVAL_STRING(c->name, estrdup(cursor->ns + (strchr(cursor->ns, '.') - cursor->ns) + 1), 0); c->parent = db_z; if (cursor->query) { zval **inner_query = 0; if (!cursor->special) { query = cursor->query; zval_add_ref(&query); } else if (zend_hash_find(HASH_P(cursor->query), "$query", strlen("$query")+1, (void**)&inner_query) == SUCCESS) { query = *inner_query; zval_add_ref(&query); } } else { MAKE_STD_ZVAL(query); array_init(query); } if (all) { zval *limit_z, *skip_z; MAKE_STD_ZVAL(limit_z); MAKE_STD_ZVAL(skip_z); ZVAL_LONG(limit_z, cursor->limit); ZVAL_LONG(skip_z, cursor->skip); MONGO_METHOD3(MongoCollection, count, return_value, coll, query, limit_z, skip_z); zval_ptr_dtor(&limit_z); zval_ptr_dtor(&skip_z); } else { MONGO_METHOD1(MongoCollection, count, return_value, coll, query); } zval_ptr_dtor(&query); c->parent = 0; zend_objects_store_del_ref(coll TSRMLS_CC); zval_ptr_dtor(&coll); db->link = 0; zend_objects_store_del_ref(db_z TSRMLS_CC); zval_ptr_dtor(&db_z); }
/* {{{ MongoCursor->next */ PHP_METHOD(MongoCursor, next) { zval has_next; mongo_cursor *cursor; PHP_MONGO_GET_CURSOR(getThis()); if (!cursor->started_iterating) { MONGO_METHOD(MongoCursor, doQuery, return_value, getThis()); if (EG(exception)) { return; } cursor->started_iterating = 1; } // destroy old current if (cursor->current) { zval_ptr_dtor(&cursor->current); cursor->current = 0; } // check for results MONGO_METHOD(MongoCursor, hasNext, &has_next, getThis()); if (EG(exception)) { return; } if (!Z_BVAL(has_next)) { // we're out of results RETURN_NULL(); } // we got more results if (cursor->at < cursor->num) { zval **err; MAKE_STD_ZVAL(cursor->current); array_init(cursor->current); cursor->buf.pos = bson_to_zval((char*)cursor->buf.pos, Z_ARRVAL_P(cursor->current) TSRMLS_CC); if (EG(exception)) { zval_ptr_dtor(&cursor->current); cursor->current = 0; return; } // increment cursor position cursor->at++; // check for err if (cursor->num == 1 && zend_hash_find(Z_ARRVAL_P(cursor->current), "$err", strlen("$err")+1, (void**)&err) == SUCCESS) { zval **code_z; // default error code int code = 4; if (zend_hash_find(Z_ARRVAL_P(cursor->current), "code", strlen("code")+1, (void**)&code_z) == SUCCESS) { // check for not master if (Z_TYPE_PP(code_z) == IS_LONG) { code = Z_LVAL_PP(code_z); } else if (Z_TYPE_PP(code_z) == IS_DOUBLE) { code = (int)Z_DVAL_PP(code_z); } // else code == 4 // this shouldn't be necessary after 1.7.* is standard, it forces // failover in case the master steps down. // not master: 10107 // not master and slaveok=false (more recent): 13435 // not master or secondary: 13436 if (cursor->link->rs && (code == 10107 || code == 13435 || code == 13436)) { php_mongo_disconnect_server(cursor->server); } } zend_throw_exception(mongo_ce_CursorException, Z_STRVAL_PP(err), code TSRMLS_CC); zval_ptr_dtor(&cursor->current); cursor->current = 0; RETURN_FALSE; } } RETURN_NULL(); }
/* {{{ MongoCursor->doQuery */ PHP_METHOD(MongoCursor, doQuery) { mongo_cursor *cursor; buffer buf; zval *errmsg; PHP_MONGO_GET_CURSOR(getThis()); CREATE_BUF(buf, INITIAL_BUF_SIZE); if (php_mongo_write_query(&buf, cursor TSRMLS_CC) == FAILURE) { efree(buf.start); return; } MAKE_STD_ZVAL(errmsg); ZVAL_NULL(errmsg); // If slave_okay is set, read from a slave. if ((cursor->link->rs && cursor->opts & SLAVE_OKAY && (cursor->server = php_mongo_get_slave_socket(cursor->link, errmsg TSRMLS_CC)) == 0)) { // ignore errors and reset errmsg zval_ptr_dtor(&errmsg); MAKE_STD_ZVAL(errmsg); ZVAL_NULL(errmsg); } // if getting the slave didn't work (or we're not using a rs), just get master socket if (cursor->server == 0 && (cursor->server = php_mongo_get_socket(cursor->link, errmsg TSRMLS_CC)) == 0) { efree(buf.start); zend_throw_exception(mongo_ce_CursorException, Z_STRVAL_P(errmsg), 14 TSRMLS_CC); zval_ptr_dtor(&errmsg); return; } if (mongo_say(cursor->server->socket, &buf, errmsg TSRMLS_CC) == FAILURE) { php_mongo_disconnect_server(cursor->server); if (Z_TYPE_P(errmsg) == IS_STRING) { zend_throw_exception_ex(mongo_ce_CursorException, 14 TSRMLS_CC, "couldn't send query: %s", Z_STRVAL_P(errmsg)); } else { zend_throw_exception(mongo_ce_CursorException, "couldn't send query", 14 TSRMLS_CC); } efree(buf.start); zval_ptr_dtor(&errmsg); return; } efree(buf.start); if (php_mongo_get_reply(cursor, errmsg TSRMLS_CC) == FAILURE) { zval_ptr_dtor(&errmsg); return; } zval_ptr_dtor(&errmsg); /* we've got something to kill, make a note */ if (cursor->cursor_id != 0) { php_mongo_create_le(cursor, "cursor_list" TSRMLS_CC); } }