예제 #1
0
PHP_METHOD(MongoDB, setProfilingLevel) {
  long level;
  zval *data, *cmd_return;
  zval **ok;

  if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &level) == FAILURE) {
    return;
  }

  MAKE_STD_ZVAL(data);
  array_init(data);
  add_assoc_long(data, "profile", level);

  MAKE_STD_ZVAL(cmd_return);
  MONGO_CMD(cmd_return, getThis());

  zval_ptr_dtor(&data);

  if (EG(exception)) {
    zval_ptr_dtor(&cmd_return);
    return;
  }

  if (zend_hash_find(HASH_P(cmd_return), "ok", 3, (void**)&ok) == SUCCESS &&
      ((Z_TYPE_PP(ok) == IS_BOOL && Z_BVAL_PP(ok)) || Z_DVAL_PP(ok) == 1)) {
    zend_hash_find(HASH_P(cmd_return), "was", 4, (void**)&ok);
    RETVAL_ZVAL(*ok, 1, 0);
  }
  else {
    RETVAL_NULL();
  }
  zval_ptr_dtor(&cmd_return);
}
예제 #2
0
/* {{{ MongoCursor->doQuery
 */
PHP_METHOD(MongoCursor, doQuery) {
  int sent;
  mongo_msg_header header;
  mongo_cursor *cursor;
  CREATE_BUF(buf, INITIAL_BUF_SIZE);

  cursor = (mongo_cursor*)zend_object_store_get_object(getThis() TSRMLS_CC);
  MONGO_CHECK_INITIALIZED(cursor->link, MongoCursor);

  CREATE_HEADER_WITH_OPTS(buf, cursor->ns, OP_QUERY, cursor->opts);

  serialize_int(&buf, cursor->skip);
  serialize_int(&buf, cursor->limit);

  zval_to_bson(&buf, HASH_P(cursor->query), NO_PREP TSRMLS_CC);
  if (cursor->fields && zend_hash_num_elements(HASH_P(cursor->fields)) > 0) {
    zval_to_bson(&buf, HASH_P(cursor->fields), NO_PREP TSRMLS_CC);
  }

  serialize_size(buf.start, &buf);
  // sends
  sent = mongo_say(cursor->link, &buf TSRMLS_CC);
  efree(buf.start);
  if (sent == FAILURE) {
    zend_throw_exception(mongo_ce_CursorException, "couldn't send query.", 0 TSRMLS_CC);
    return;
  }

  get_reply(cursor TSRMLS_CC);
}
예제 #3
0
/* {{{ MongoCursor->key
 */
PHP_METHOD(MongoCursor, key) {
  zval **id;
  mongo_cursor *cursor = (mongo_cursor*)zend_object_store_get_object(getThis() TSRMLS_CC);
  MONGO_CHECK_INITIALIZED(cursor->link, MongoCursor);

  if (cursor->current && 
      Z_TYPE_P(cursor->current) == IS_ARRAY &&
      zend_hash_find(HASH_P(cursor->current), "_id", 4, (void**)&id) == SUCCESS) {

    if (Z_TYPE_PP(id) == IS_OBJECT) {
#if ZEND_MODULE_API_NO >= 20060613
      zend_std_cast_object_tostring(*id, return_value, IS_STRING TSRMLS_CC);
#else
      zend_std_cast_object_tostring(*id, return_value, IS_STRING, 0 TSRMLS_CC);
#endif /* ZEND_MODULE_API_NO >= 20060613 */
    }
    else {
      RETVAL_ZVAL(*id, 1, 0);
      convert_to_string(return_value);
    }
  }
  else {
    RETURN_STRING("", 1);
  }
}
예제 #4
0
/* {{{ MongoCursor->explain
 */
PHP_METHOD(MongoCursor, explain) {
  int temp_limit;
  zval *explain, *yes, *temp = 0;
  mongo_cursor *cursor = (mongo_cursor*)zend_object_store_get_object(getThis() TSRMLS_CC);
  MONGO_CHECK_INITIALIZED(cursor->link, MongoCursor);

  MONGO_METHOD(MongoCursor, reset, return_value, getThis());

  // make explain use a hard limit
  temp_limit = cursor->limit;
  if (cursor->limit > 0) {
    cursor->limit *= -1;
  }

  MAKE_STD_ZVAL(explain);
  ZVAL_STRING(explain, "$explain", 1);
  MAKE_STD_ZVAL(yes);
  ZVAL_TRUE(yes);

  MONGO_METHOD2(MongoCursor, addOption, return_value, getThis(), explain, yes);

  zval_ptr_dtor(&explain);
  zval_ptr_dtor(&yes);

  MONGO_METHOD(MongoCursor, getNext, return_value, getThis());

  // reset cursor to original state
  cursor->limit = temp_limit;
  zend_hash_del(HASH_P(cursor->query), "$explain", strlen("$explain")+1);

  MAKE_STD_ZVAL(temp);
  ZVAL_NULL(temp);
  MONGO_METHOD(MongoCursor, reset, temp, getThis());
  zval_ptr_dtor(&temp);
}
예제 #5
0
/* {{{ proto int MongoGridFSFile::getSize()
   Returns this file's size */
PHP_METHOD(MongoGridFSFile, getSize)
{
	zval *file = zend_read_property(mongo_ce_GridFSFile, getThis(), "file", strlen("file"), NOISY TSRMLS_CC);

	if (zend_hash_find(HASH_P(file), "length", strlen("length") + 1, (void**)&return_value_ptr) == SUCCESS) {
		RETURN_ZVAL(*return_value_ptr, 1, 0);
	}
	RETURN_NULL();
}
예제 #6
0
static void php_mongo_db_profiling_level(INTERNAL_FUNCTION_PARAMETERS, int get)
{
	long level;
	zval *cmd, *cmd_return;
	zval **ok;
	mongo_db *db;

	if (get) {
		if (zend_parse_parameters_none() == FAILURE) {
			return;
		}
		level = -1;
	} else {
		if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &level) == FAILURE) {
			return;
		}
	}

	PHP_MONGO_GET_DB(getThis());

	MAKE_STD_ZVAL(cmd);
	array_init(cmd);
	add_assoc_long(cmd, "profile", level);

	cmd_return = php_mongo_runcommand(db->link, &db->read_pref, Z_STRVAL_P(db->name), Z_STRLEN_P(db->name), cmd, NULL, 0, NULL TSRMLS_CC);

	zval_ptr_dtor(&cmd);

	if (!cmd_return) {
		return;
	}

	if (
		zend_hash_find(HASH_P(cmd_return), "ok", 3, (void**)&ok) == SUCCESS &&
		((Z_TYPE_PP(ok) == IS_BOOL && Z_BVAL_PP(ok)) || Z_DVAL_PP(ok) == 1)
	) {
		zend_hash_find(HASH_P(cmd_return), "was", 4, (void**)&ok);
		RETVAL_ZVAL(*ok, 1, 0);
	} else {
		RETVAL_NULL();
	}
	zval_ptr_dtor(&cmd_return);
}
예제 #7
0
/* {{{ proto bool MongoDBRef::isRef(mixed ref)
   Checks if $ref has a $ref and $id property/key */
PHP_METHOD(MongoDBRef, isRef)
{
	zval *ref;

	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &ref) == FAILURE) {
		return;
	}

	if (IS_SCALAR_P(ref)) {
		RETURN_FALSE;
	}

	/* check that $ref and $id fields exists */
	if (zend_hash_exists(HASH_P(ref), "$ref", strlen("$ref") + 1) && zend_hash_exists(HASH_P(ref), "$id", strlen("$id") + 1)) {
		/* good enough */
		RETURN_TRUE;
	}

	RETURN_FALSE;
}
예제 #8
0
/* {{{ MongoDate::__set_state()
 */
PHP_METHOD(MongoDate, __set_state)
{
	zval *state, **sec, **usec;

	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a", &state) == FAILURE) {
		return;
	}

	if (zend_hash_find(HASH_P(state), "sec", strlen("sec") + 1, (void**) &sec) == FAILURE) {
		return;
	}

	if (zend_hash_find(HASH_P(state), "usec", strlen("usec") + 1, (void**) &usec) == FAILURE) {
		return;
	}

	convert_to_long(*sec);
	convert_to_long(*usec);
	object_init_ex(return_value, mongo_ce_Date);
	php_mongo_mongodate_populate(return_value, Z_LVAL_PP(sec), Z_LVAL_PP(usec) TSRMLS_CC);
}
예제 #9
0
파일: db.cpp 프로젝트: 191919/hhvm
PHP_METHOD(MongoDB, execute)
{
	zval *code = NULL, *args = NULL, *options = NULL, *zdata;

	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z|aa", &code, &args, &options) == FAILURE) {
		return;
	}

	/* turn the first argument into MongoCode */
	if (Z_TYPE_P(code) != IS_OBJECT ||
		Z_OBJCE_P(code) != mongo_ce_Code) {
		if (Z_TYPE_P(code) == IS_STRING) {
			zval *obj;

			MAKE_STD_ZVAL(obj);
			object_init_ex(obj, mongo_ce_Code);
			MONGO_METHOD1(MongoCode, __construct, return_value, obj, code);
			code = obj;
		} else { /* This is broken code */
			php_error_docref(NULL TSRMLS_CC, E_ERROR, "The argument is neither an object of MongoCode or a string");
			return;
		}
	} else {
		zval_add_ref(&code);
	}

	if (!args) {
		MAKE_STD_ZVAL(args);
		array_init(args);
	} else {
		zval_add_ref(&args);
	}

	/* create { $eval : code, args : [] } */
	MAKE_STD_ZVAL(zdata);
	array_init(zdata);
	add_assoc_zval(zdata, "$eval", code);
	add_assoc_zval(zdata, "args", args);
	/* Check whether we have nolock as an option */
	if (options) {
		zval **nolock;

		if (zend_hash_find(HASH_P(options), "nolock", strlen("nolock") + 1, (void**) &nolock) == SUCCESS) {
			convert_to_boolean_ex(nolock);
			zval_add_ref(nolock);
			add_assoc_zval(zdata, "nolock", *nolock);
		}
	}

	MONGO_METHOD1(MongoDB, command, return_value, getThis(), zdata);

	zval_ptr_dtor(&zdata);
}
예제 #10
0
파일: db.cpp 프로젝트: 191919/hhvm
PHP_METHOD(MongoDB, createDBRef)
{
	zval *ns, *obj;
	zval **id;

	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zz", &ns, &obj) == FAILURE) {
		return;
	}

	if (Z_TYPE_P(obj) == IS_ARRAY || Z_TYPE_P(obj) == IS_OBJECT) {
		if (zend_hash_find(HASH_P(obj), "_id", 4, (void**)&id) == SUCCESS) {
			MONGO_METHOD2(MongoDBRef, create, return_value, NULL, ns, *id);
			return;
		} else if (Z_TYPE_P(obj) == IS_ARRAY) {
			return;
		}
	}

	MONGO_METHOD2(MongoDBRef, create, return_value, NULL, ns, obj);
}
예제 #11
0
/* {{{ proto int MongoGridFSFile::write([string filename = null])
   Writes this file to the filesystem */
PHP_METHOD(MongoGridFSFile, write)
{
	char *filename = 0;
	int filename_len, total = 0;
	zval *gridfs, *file, *chunks, *query, *cursor, *sort, tmp;
	zval **id, **size;
	int len;
	FILE *fp;

	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s", &filename, &filename_len) == FAILURE) {
		return;
	}

	gridfs = zend_read_property(mongo_ce_GridFSFile, getThis(), "gridfs", strlen("gridfs"), NOISY TSRMLS_CC);
	file = zend_read_property(mongo_ce_GridFSFile, getThis(), "file", strlen("file"), NOISY TSRMLS_CC);

	if (zend_hash_find(HASH_P(file), "length", strlen("length") + 1, (void**)&size) == FAILURE) {
		zend_throw_exception(mongo_ce_GridFSException, "couldn't find file size", 14 TSRMLS_CC);
		return;
	}

	if (Z_TYPE_PP(size) == IS_DOUBLE) {
		len = (int)Z_DVAL_PP(size);
	} else if (Z_TYPE_PP(size) == IS_LONG) {
		len = Z_LVAL_PP(size);
	} else if (Z_TYPE_PP(size) == IS_OBJECT && (Z_OBJCE_PP(size) == mongo_ce_Int32 || Z_OBJCE_PP(size) == mongo_ce_Int64)) {
		zval *sizet = zend_read_property(mongo_ce_Int64, *size, "value", strlen("value"), NOISY TSRMLS_CC);
		if (Z_TYPE_P(sizet) != IS_STRING) {
			zval_ptr_dtor(&cursor);
			zend_throw_exception(mongo_ce_GridFSException, "couldn't find file size, value object broken", 0 TSRMLS_CC);
			return;
		}
		len = atoi(Z_STRVAL_P(sizet));
	} else {
		zval_ptr_dtor(&cursor);
		zend_throw_exception(mongo_ce_GridFSException, "couldn't find file size, property invalid", 0 TSRMLS_CC);
		return;
	}

	/* Make sure that there's an index on chunks so we can sort by chunk num */
	chunks = zend_read_property(mongo_ce_GridFS, gridfs, "chunks", strlen("chunks"), NOISY TSRMLS_CC);

	php_mongo_ensure_gridfs_index(&tmp, chunks TSRMLS_CC);
	zval_dtor(&tmp);

	if (!filename) {
		zval **temp;
		if (zend_hash_find(HASH_P(file), "filename", strlen("filename") + 1, (void**) &temp) == SUCCESS) {
			convert_to_string_ex(temp);
			filename = Z_STRVAL_PP(temp);
		} else {
			zend_throw_exception(mongo_ce_GridFSException, "Cannot find filename", 15 TSRMLS_CC);
			return;
		}
	}

	fp = fopen(filename, "wb");
	if (!fp) {
		zend_throw_exception_ex(mongo_ce_GridFSException, 16 TSRMLS_CC, "could not open destination file %s", filename);
		return;
	}

	zend_hash_find(HASH_P(file), "_id", strlen("_id") + 1, (void**)&id);

	MAKE_STD_ZVAL(query);
	array_init(query);
	zval_add_ref(id);
	add_assoc_zval(query, "files_id", *id);

	MAKE_STD_ZVAL(cursor);
	MONGO_METHOD1(MongoCollection, find, cursor, chunks, query);

	MAKE_STD_ZVAL(sort);
	array_init(sort);
	add_assoc_long(sort, "n", 1);

	MONGO_METHOD1(MongoCursor, sort, cursor, cursor, sort);

	if ((total = apply_to_cursor(cursor, copy_file, fp, len TSRMLS_CC)) == FAILURE) {
		zend_throw_exception(mongo_ce_GridFSException, "error reading chunk of file", 17 TSRMLS_CC);
	}

	fclose(fp);

	zval_ptr_dtor(&cursor);
	zval_ptr_dtor(&sort);
	zval_ptr_dtor(&query);

	RETURN_LONG(total);
}
예제 #12
0
static int apply_to_cursor(zval *cursor, apply_copy_func_t apply_copy_func, void *to, int max TSRMLS_DC)
{
	int total = 0;
	zval *next;

	MAKE_STD_ZVAL(next);
	MONGO_METHOD(MongoCursor, getNext, next, cursor);

	if (EG(exception)) {
		return FAILURE;
	}
    
	if (Z_TYPE_P(next) != IS_ARRAY) {
		zval_ptr_dtor(&next);
		return FAILURE;
	}

	while (Z_TYPE_P(next) == IS_ARRAY) {
		zval **zdata;

		/* Check if data field exists. If it doesn't, we've probably got an
		 * error message from the db, so return that */
		if (zend_hash_find(HASH_P(next), "data", 5, (void**)&zdata) == FAILURE) {
			if (zend_hash_exists(HASH_P(next), "$err", 5)) {
				zval_ptr_dtor(&next);
				return FAILURE;
			}
			continue;
		}

		/* This copies the next chunk -> *to
		 * Due to a talent I have for not reading directions, older versions of
		 * the driver store files as raw bytes, not MongoBinData. So, we'll
		 * check for and handle both cases. */
		if (Z_TYPE_PP(zdata) == IS_STRING) {
			/* raw bytes */
			if (total + Z_STRLEN_PP(zdata) > max) {
				zend_throw_exception_ex(mongo_ce_GridFSException, 1 TSRMLS_CC, "There is more data associated with this file than the metadata specifies");
				return FAILURE;
			}
			total += apply_copy_func(to, Z_STRVAL_PP(zdata), Z_STRLEN_PP(zdata));

		} else if (Z_TYPE_PP(zdata) == IS_OBJECT && Z_OBJCE_PP(zdata) == mongo_ce_BinData) {
			/* MongoBinData */
			zval *bin = zend_read_property(mongo_ce_BinData, *zdata, "bin", strlen("bin"), NOISY TSRMLS_CC);

			if (total + Z_STRLEN_P(bin) > max) {
				zval **n;

				if (zend_hash_find(HASH_P(next), "n", strlen("n") + 1, (void**)&n) == SUCCESS) {
					convert_to_long_ex(n);
					zend_throw_exception_ex(mongo_ce_GridFSException, 1 TSRMLS_CC, "There is more data associated with this file than the metadata specifies (reading chunk %d)", Z_LVAL_PP(n));
				} else {
					zend_throw_exception_ex(mongo_ce_GridFSException, 1 TSRMLS_CC, "There is more data associated with this file than the metadata specifies");
				}
				zval_ptr_dtor(&next);

				return FAILURE;
			}
			total += apply_copy_func(to, Z_STRVAL_P(bin), Z_STRLEN_P(bin));

		} else {
			/* If it's not a string or a MongoBinData, give up */
			zval_ptr_dtor(&next);
			return FAILURE;
		}

		/* get ready for the next iteration */
		zval_ptr_dtor(&next);
		MAKE_STD_ZVAL(next);
		MONGO_METHOD(MongoCursor, getNext, next, cursor);
	}
	zval_ptr_dtor(&next);

	/* return the number of bytes copied */
	return total;
}
예제 #13
0
/* {{{ proto string MongoGridFSFile::getBytes()
   Returns this file's contents as a string of bytes */
PHP_METHOD(MongoGridFSFile, getBytes)
{
	zval *file, *gridfs, *chunks, *query, *cursor, *sort, *temp;
	zval **id, **size;
	char *str, *str_ptr;
	int len;
	mongo_cursor *cursorobj;
	zval *flags;

	file = zend_read_property(mongo_ce_GridFSFile, getThis(), "file", strlen("file"), NOISY TSRMLS_CC);
	zend_hash_find(HASH_P(file), "_id", strlen("_id") + 1, (void**)&id);

	if (zend_hash_find(HASH_P(file), "length", strlen("length") + 1, (void**)&size) == FAILURE) {
		zend_throw_exception(mongo_ce_GridFSException, "couldn't find file size", 14 TSRMLS_CC);
		return;
	}

	/* make sure that there's an index on chunks so we can sort by chunk num */
	gridfs = zend_read_property(mongo_ce_GridFSFile, getThis(), "gridfs", strlen("gridfs"), NOISY TSRMLS_CC);
	chunks = zend_read_property(mongo_ce_GridFS, gridfs, "chunks", strlen("chunks"), NOISY TSRMLS_CC);

	MAKE_STD_ZVAL(temp);
	php_mongo_ensure_gridfs_index(temp, chunks TSRMLS_CC);
	zval_dtor(temp);

	/* query for chunks */
	MAKE_STD_ZVAL(query);
	array_init(query);
	zval_add_ref(id);
	add_assoc_zval(query, "files_id", *id);

	MAKE_STD_ZVAL(cursor);
	MONGO_METHOD1(MongoCollection, find, cursor, chunks, query);

	/* Copy the flags from the original cursor and apply it to this one */
	flags = zend_read_property(mongo_ce_GridFSFile, getThis(), "flags", strlen("flags"), NOISY TSRMLS_CC);
	cursorobj = (mongo_cursor*)zend_object_store_get_object(cursor TSRMLS_CC);
	convert_to_long(flags);
	cursorobj->opts = Z_LVAL_P(flags);

	MAKE_STD_ZVAL(sort);
	array_init(sort);
	add_assoc_long(sort, "n", 1);

	MONGO_METHOD1(MongoCursor, sort, temp, cursor, sort);
	zval_ptr_dtor(&temp);

	zval_ptr_dtor(&query);
	zval_ptr_dtor(&sort);

	if (Z_TYPE_PP(size) == IS_DOUBLE) {
		len = (int)Z_DVAL_PP(size);
	} else if (Z_TYPE_PP(size) == IS_LONG) {
		len = Z_LVAL_PP(size);
	} else if (Z_TYPE_PP(size) == IS_OBJECT && (Z_OBJCE_PP(size) == mongo_ce_Int32 || Z_OBJCE_PP(size) == mongo_ce_Int64)) {
		zval *sizet = zend_read_property(mongo_ce_Int64, *size, "value", strlen("value"), NOISY TSRMLS_CC);
		if (Z_TYPE_P(sizet) != IS_STRING) {
			zval_ptr_dtor(&cursor);
			zend_throw_exception(mongo_ce_GridFSException, "couldn't find file size, value object broken", 0 TSRMLS_CC);
			return;
		}
		len = atoi(Z_STRVAL_P(sizet));
	} else {
		zval_ptr_dtor(&cursor);
		zend_throw_exception(mongo_ce_GridFSException, "couldn't find file size, property invalid", 0 TSRMLS_CC);
		return;
	}

	str = (char *)ecalloc(len + 1, 1);
	str_ptr = str;

	if (apply_to_cursor(cursor, copy_bytes, &str, len + 1 TSRMLS_CC) == FAILURE) {
		zval_ptr_dtor(&cursor);
		efree(str_ptr);

		if (EG(exception)) {
			return;
		}
		zend_throw_exception(mongo_ce_GridFSException, "error reading chunk of file", 17 TSRMLS_CC);
		return;
	}

	zval_ptr_dtor(&cursor);

	str_ptr[len] = '\0';

	RETURN_STRINGL(str_ptr, len, 0);
}
예제 #14
0
static void php_mongo_enumerate_collections(INTERNAL_FUNCTION_PARAMETERS, int full_collection)
{
	zend_bool system_col = 0;
	zval *nss, *collection, *cursor, *list, *next;

	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|b", &system_col) == FAILURE) {
		return;
	}

  // select db.system.namespaces collection
  MAKE_STD_ZVAL(nss);
  ZVAL_STRING(nss, "system.namespaces", 1);

  MAKE_STD_ZVAL(collection);
  MONGO_METHOD1(MongoDB, selectCollection, collection, getThis(), nss);

  // list to return
  MAKE_STD_ZVAL(list);
  array_init(list);

  // do find
  MAKE_STD_ZVAL(cursor);
  MONGO_METHOD(MongoCollection, find, cursor, collection);

  // populate list
  MAKE_STD_ZVAL(next);
  MONGO_METHOD(MongoCursor, getNext, next, cursor);
  while (!IS_SCALAR_P(next)) {
    zval *c, *zname;
    zval **collection;
    char *name, *first_dot, *system;

    // check that the ns is valid and not an index (contains $)
    if (zend_hash_find(HASH_P(next), "name", 5, (void**)&collection) == FAILURE ||
        strchr(Z_STRVAL_PP(collection), '$')) {

      zval_ptr_dtor(&next);
      MAKE_STD_ZVAL(next);
      ZVAL_NULL(next);

      MONGO_METHOD(MongoCursor, getNext, next, cursor);
      continue;
    }

    first_dot = strchr(Z_STRVAL_PP(collection), '.');
    system = strstr(Z_STRVAL_PP(collection), ".system.");
    // check that this isn't a system ns
    if (!system_col && (system && first_dot == system) ||
      (name = strchr(Z_STRVAL_PP(collection), '.')) == 0) {

      zval_ptr_dtor(&next);
      MAKE_STD_ZVAL(next);
      ZVAL_NULL(next);

      MONGO_METHOD(MongoCursor, getNext, next, cursor);
      continue;
    }

    // take a substring after the first "."
    name++;

    // "foo." was allowed in earlier versions
    if (name == '\0') {
      zval_ptr_dtor(&next);
      MAKE_STD_ZVAL(next);
      ZVAL_NULL(next);

      MONGO_METHOD(MongoCursor, getNext, next, cursor);
      continue;
    }

	if (full_collection) {
		MAKE_STD_ZVAL(c);
		ZVAL_NULL(c);

		MAKE_STD_ZVAL(zname);
		ZVAL_NULL(zname);

		// name must be copied because it is a substring of
		// a string that will be garbage collected in a sec
		ZVAL_STRING(zname, name, 1);
		MONGO_METHOD1(MongoDB, selectCollection, c, getThis(), zname);

		add_next_index_zval(list, c);

		zval_ptr_dtor(&zname);
	} else {
		add_next_index_string(list, name, 1);
	}
    zval_ptr_dtor(&next);
    MAKE_STD_ZVAL(next);

    MONGO_METHOD(MongoCursor, getNext, next, cursor);
  }

  zval_ptr_dtor(&next);
  zval_ptr_dtor(&nss);
  zval_ptr_dtor(&cursor);
  zval_ptr_dtor(&collection);

  RETURN_ZVAL(list, 0, 1);
}
예제 #15
0
/* {{{ 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);
}
예제 #16
0
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);
}
예제 #17
0
PHP_METHOD(MongoDB, listCollections) {
  // select db.system.namespaces collection
  zval *nss, *collection, *cursor, *list, *next;

  MAKE_STD_ZVAL(nss);
  ZVAL_STRING(nss, "system.namespaces", 1);

  MAKE_STD_ZVAL(collection);
  MONGO_METHOD1(MongoDB, selectCollection, collection, getThis(), nss);

  // list to return
  MAKE_STD_ZVAL(list);
  array_init(list);

  // do find
  MAKE_STD_ZVAL(cursor);
  MONGO_METHOD(MongoCollection, find, cursor, collection);

  // populate list
  MAKE_STD_ZVAL(next);
  MONGO_METHOD(MongoCursor, getNext, next, cursor);
  while (!IS_SCALAR_P(next)) {
    zval *c, *zname;
    zval **collection;
    char *name, *first_dot, *system;

    // check that the ns is valid and not an index (contains $)
    if (zend_hash_find(HASH_P(next), "name", 5, (void**)&collection) == FAILURE ||
        strchr(Z_STRVAL_PP(collection), '$')) {

      zval_ptr_dtor(&next);
      MAKE_STD_ZVAL(next);
      ZVAL_NULL(next);

      MONGO_METHOD(MongoCursor, getNext, next, cursor);
      continue;
    }

    first_dot = strchr(Z_STRVAL_PP(collection), '.');
    system = strstr(Z_STRVAL_PP(collection), ".system.");
    // check that this isn't a system ns
    if ((system && first_dot == system) ||
	(name = strchr(Z_STRVAL_PP(collection), '.')) == 0) {

      zval_ptr_dtor(&next);
      MAKE_STD_ZVAL(next);
      ZVAL_NULL(next);

      MONGO_METHOD(MongoCursor, getNext, next, cursor);
      continue;
    }

    // take a substring after the first "."
    name++;

    // "foo." was allowed in earlier versions
    if (name == '\0') {
      zval_ptr_dtor(&next);
      MAKE_STD_ZVAL(next);
      ZVAL_NULL(next);

      MONGO_METHOD(MongoCursor, getNext, next, cursor);
      continue;
    }

    MAKE_STD_ZVAL(c);
    ZVAL_NULL(c);

    MAKE_STD_ZVAL(zname);
    ZVAL_NULL(zname);

    // name must be copied because it is a substring of
    // a string that will be garbage collected in a sec
    ZVAL_STRING(zname, name, 1);
    MONGO_METHOD1(MongoDB, selectCollection, c, getThis(), zname);

    add_next_index_zval(list, c);

    zval_ptr_dtor(&zname);
    zval_ptr_dtor(&next);
    MAKE_STD_ZVAL(next);

    MONGO_METHOD(MongoCursor, getNext, next, cursor);
  }

  zval_ptr_dtor(&next);
  zval_ptr_dtor(&nss);
  zval_ptr_dtor(&cursor);
  zval_ptr_dtor(&collection);

  RETURN_ZVAL(list, 0, 1);
}
예제 #18
0
/* {{{ MongoDBRef::get()
 */
PHP_METHOD(MongoDBRef, get)
{
	zval *db, *ref, *collection, *query;
	zval **ns, **id, **dbname;
	zend_bool alloced_db = 0;

	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Oz", &db, mongo_ce_DB, &ref) == FAILURE) {
		return;
	}

	if (
		IS_SCALAR_P(ref) ||
		zend_hash_find(HASH_P(ref), "$ref", strlen("$ref") + 1, (void**)&ns) == FAILURE ||
		zend_hash_find(HASH_P(ref), "$id", strlen("$id") + 1, (void**)&id) == FAILURE
	) {
		RETURN_NULL();
	}

	if (Z_TYPE_PP(ns) != IS_STRING) {
		zend_throw_exception(mongo_ce_Exception, "MongoDBRef::get: $ref field must be a string", 10 TSRMLS_CC);
		return;
	}

	/* if this reference contains a db name, we have to switch dbs */
	if (zend_hash_find(HASH_P(ref), "$db", strlen("$db") + 1, (void**)&dbname) == SUCCESS) {
		mongo_db *temp_db = (mongo_db*)zend_object_store_get_object(db TSRMLS_CC);

		/* just to be paranoid, make sure dbname is a string */
		if (Z_TYPE_PP(dbname) != IS_STRING) {
			zend_throw_exception(mongo_ce_Exception, "MongoDBRef::get: $db field must be a string", 11 TSRMLS_CC);
			return;
		}

		/* if the name in the $db field doesn't match the current db, make up
		 * a new db */
		if (strcmp(Z_STRVAL_PP(dbname), Z_STRVAL_P(temp_db->name)) != 0) {
			zval *new_db_z;

			MAKE_STD_ZVAL(new_db_z);
			ZVAL_NULL(new_db_z);

			MONGO_METHOD1(MongoClient, selectDB, new_db_z, temp_db->link, *dbname);

			/* make the new db the current one */
			db = new_db_z;

			/* so we can dtor this later */
			alloced_db = 1;
		}
	}

	/* get the collection */
	MAKE_STD_ZVAL(collection);
	MONGO_METHOD1(MongoDB, selectCollection, collection, db, *ns);

	/* query for the $id */
	MAKE_STD_ZVAL(query);
	array_init(query);
	add_assoc_zval(query, "_id", *id);
	zval_add_ref(id);

	/* return whatever's there */
	MONGO_METHOD1(MongoCollection, findOne, return_value, collection, query);

	/* cleanup */
	zval_ptr_dtor(&collection);
	zval_ptr_dtor(&query);
	if (alloced_db) {
		zval_ptr_dtor(&db);
	}
}
예제 #19
0
int mongo_util_server_ping(mongo_server *server, time_t now TSRMLS_DC) {
  server_info* info;
  zval *response = 0, **secondary = 0, **bson = 0, **self = 0;
  struct timeval start, end;

  if ((info = mongo_util_server__get_info(server TSRMLS_CC)) == 0) {
    return FAILURE;
  }

  if (info->guts->last_ping + MONGO_PING_INTERVAL > now) {
    return info->guts->master ? SUCCESS : FAILURE;
  }

  gettimeofday(&start, 0);
  response = mongo_util_rs__ismaster(server TSRMLS_CC);
  gettimeofday(&end, 0);

  mongo_util_server__set_ping(info, start, end);

  if (!response) {
    return FAILURE;
  }

  zend_hash_find(HASH_P(response), "me", strlen("me")+1, (void**)&self);
  if (!info->guts->pinged && self &&
      strncmp(Z_STRVAL_PP(self), server->label, Z_STRLEN_PP(self)) != 0) {

    // this server thinks its name is different than what we have recorded
    mongo_log(MONGO_LOG_SERVER, MONGO_LOG_INFO TSRMLS_CC, "server: found another name for %s: %s",
              server->label, Z_STRVAL_PP(self));

    // make a new info entry for this name, pointing to our info
    make_other_le(Z_STRVAL_PP(self), info TSRMLS_CC);
  }

  // now we have pinged it at least once
  info->guts->pinged = 1;

  zend_hash_find(HASH_P(response), "secondary", strlen("secondary")+1, (void**)&secondary);
  if (secondary && Z_BVAL_PP(secondary)) {
    if (!info->guts->readable) {
      mongo_log(MONGO_LOG_SERVER, MONGO_LOG_INFO TSRMLS_CC, "server: %s is now a secondary", server->label);
    }

    info->guts->readable = 1;
    info->guts->master = 0;
  }
  else {
    if (info->guts->readable) {
      mongo_log(MONGO_LOG_SERVER, MONGO_LOG_INFO TSRMLS_CC, "server: %s is now not readable", server->label);
    }

    info->guts->readable = 0;
    info->guts->master = 0;
  }

  zend_hash_find(HASH_P(response), "maxBsonObjectSize", strlen("maxBsonObjectSize")+1, (void**)&bson);
  if (bson) {
    if (Z_TYPE_PP(bson) == IS_LONG) {
      info->guts->max_bson_size = Z_LVAL_PP(bson);
    }
    else if (Z_TYPE_PP(bson) == IS_DOUBLE) {
      info->guts->max_bson_size = (int)Z_DVAL_PP(bson);
    }
    // otherwise, leave as the default
    else {
      mongo_log(MONGO_LOG_SERVER, MONGO_LOG_WARNING TSRMLS_CC,
                "server: could not find max bson size on %s, consider upgrading your server", server->label);
    }
  }

  if (mongo_util_rs__get_ismaster(response TSRMLS_CC)) {
    if (!info->guts->master) {
      mongo_log(MONGO_LOG_SERVER, MONGO_LOG_INFO TSRMLS_CC, "server: %s is now primary", server->label);
    }

    info->guts->master = 1;
    info->guts->readable = 1;
    zval_ptr_dtor(&response);
    return SUCCESS;
  }

  zval_ptr_dtor(&response);
  return FAILURE;
}
예제 #20
0
PHP_METHOD(MongoCursor, count) {
  zval *response, *data, *db;
  zval **n;
  mongo_cursor *cursor;
  mongo_db *db_struct;

  cursor = (mongo_cursor*)zend_object_store_get_object(getThis() TSRMLS_CC);
  MONGO_CHECK_INITIALIZED(cursor->link, MongoCursor);


  // fake a MongoDB object
  MAKE_STD_ZVAL(db);
  object_init_ex(db, mongo_ce_DB);
  db_struct = (mongo_db*)zend_object_store_get_object(db TSRMLS_CC);

  db_struct->link = cursor->resource;
  zval_add_ref(&cursor->resource);
  MAKE_STD_ZVAL(db_struct->name);
  ZVAL_STRING(db_struct->name, estrndup(cursor->ns, strchr(cursor->ns, '.') - cursor->ns), 0);


  // create query
  MAKE_STD_ZVAL(data);
  object_init(data);

  // "count" => "collectionName"
  add_property_string(data, "count", strchr(cursor->ns, '.')+1, 1);

  if (cursor->query) {
    zval **inner_query;
    if (zend_hash_find(HASH_P(cursor->query), "query", strlen("query")+1, (void**)&inner_query) == SUCCESS) {
      add_property_zval(data, "query", *inner_query);
      zval_add_ref(inner_query);
    }
  }
  if (cursor->fields) {
    add_property_zval(data, "fields", cursor->fields);
    zval_add_ref(&cursor->fields);
  }

  MAKE_STD_ZVAL(response);

  PUSH_PARAM(data); PUSH_PARAM((void*)1);
  PUSH_EO_PARAM();
  MONGO_METHOD(MongoDB, command)(1, response, &response, db, return_value_used TSRMLS_CC);
  POP_EO_PARAM();
  POP_PARAM(); POP_PARAM();

  zval_ptr_dtor(&data);

  // prep results
  if (zend_hash_find(HASH_P(response), "n", 2, (void**)&n) == SUCCESS) {
    // don't allow count to return more than cursor->limit
    if (cursor->limit > 0 && Z_DVAL_PP(n) > cursor->limit) {
      RETVAL_LONG(cursor->limit);
    }
    else {
      convert_to_long(*n);
      RETVAL_ZVAL(*n, 1, 0);
    }
    zval_ptr_dtor(&response);
  }
  else {
    RETURN_ZVAL(response, 0, 0);
  }

  zend_objects_store_del_ref(db TSRMLS_CC);
  zval_ptr_dtor(&db);
}
예제 #21
0
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);
}
예제 #22
0
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);
}