static PHP_METHOD()

in php_memcached.c [1214:1333]


static PHP_METHOD(Memcached, __construct)
{
	php_memc_object_t *intern;
	php_memc_user_data_t *memc_user_data;

	zend_string *persistent_id = NULL;
	zend_string *conn_str = NULL;
	zend_string *plist_key = NULL;
	zend_fcall_info fci = {0};
	zend_fcall_info_cache fci_cache;

	zend_bool is_persistent = 0;

	/* "|S!f!S" */
	ZEND_PARSE_PARAMETERS_START(0, 3)
	        Z_PARAM_OPTIONAL
	        Z_PARAM_STR_EX(persistent_id, 1, 0)
	        Z_PARAM_FUNC_EX(fci, fci_cache, 1, 0)
	        Z_PARAM_STR(conn_str)
	ZEND_PARSE_PARAMETERS_END();

	intern = Z_MEMC_OBJ_P(getThis());
	intern->is_pristine = 1;

	if (persistent_id && persistent_id->len) {
		zend_resource *le;

		plist_key = zend_string_alloc(sizeof("memcached:id=") + persistent_id->len - 1, 0);
		snprintf(ZSTR_VAL(plist_key), plist_key->len + 1, "memcached:id=%s", ZSTR_VAL(persistent_id));

		if ((le = zend_hash_find_ptr(&EG(persistent_list), plist_key)) != NULL) {
			if (le->type == php_memc_list_entry()) {
				intern->memc = le->ptr;
				intern->is_pristine = 0;
				zend_string_release (plist_key);
				return;
			}
		}
		is_persistent = 1;
	}

	if (conn_str && conn_str->len > 0) {
		intern->memc = memcached (ZSTR_VAL(conn_str), ZSTR_LEN(conn_str));
	}
	else {
		intern->memc = memcached (NULL, 0);
	}

	if (!intern->memc) {
		php_error_docref(NULL, E_ERROR, "Failed to allocate memory for memcached structure");
		/* never reached */
	}

	memc_user_data                    = pecalloc (1, sizeof(*memc_user_data), is_persistent);
	memc_user_data->serializer        = MEMC_G(serializer_type);
	memc_user_data->compression_type  = MEMC_G(compression_type);
	memc_user_data->compression_enabled = 1;
	memc_user_data->encoding_enabled  = 0;
	memc_user_data->store_retry_count = MEMC_G(store_retry_count);
	memc_user_data->set_udf_flags     = -1;
	memc_user_data->is_persistent     = is_persistent;

	memcached_set_user_data(intern->memc, memc_user_data);

	/* Set default behaviors */
	if (MEMC_G(default_behavior.consistent_hash_enabled)) {
		memcached_return rc = memcached_behavior_set(intern->memc, MEMCACHED_BEHAVIOR_DISTRIBUTION, MEMCACHED_DISTRIBUTION_CONSISTENT);
		if (rc != MEMCACHED_SUCCESS) {
			php_error_docref(NULL, E_WARNING, "Failed to turn on consistent hash: %s", memcached_strerror(intern->memc, rc));
		}
	}

	if (MEMC_G(default_behavior.binary_protocol_enabled)) {
		memcached_return rc = memcached_behavior_set(intern->memc, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL, 1);
		if (rc != MEMCACHED_SUCCESS) {
			php_error_docref(NULL, E_WARNING, "Failed to turn on binary protocol: %s", memcached_strerror(intern->memc, rc));
		}
	}

	if (MEMC_G(default_behavior.connect_timeout)) {
		memcached_return rc = memcached_behavior_set(intern->memc, MEMCACHED_BEHAVIOR_CONNECT_TIMEOUT, MEMC_G(default_behavior.connect_timeout));
		if (rc != MEMCACHED_SUCCESS) {
			php_error_docref(NULL, E_WARNING, "Failed to set connect timeout: %s", memcached_strerror(intern->memc, rc));
		}
	}

	if (fci.size) {
		if (!s_invoke_new_instance_cb(getThis(), &fci, &fci_cache, persistent_id) || EG(exception)) {
			/* error calling or exception thrown from callback */
			if (plist_key) {
				zend_string_release(plist_key);
			}
			/*
				Setting intern->memc null prevents object destruction from freeing the memcached_st
				We free it manually here because it might be persistent and has not been
				registered to persistent_list yet
			*/
			php_memc_destroy(intern->memc, memc_user_data);
			intern->memc = NULL;
			return;
		}
	}

	if (plist_key) {
		zend_resource le;

		le.type = php_memc_list_entry();
		le.ptr  = intern->memc;

		GC_SET_REFCOUNT(&le, 1);

		/* plist_key is not a persistent allocated key, thus we use str_update here */
		if (zend_hash_str_update_mem(&EG(persistent_list), ZSTR_VAL(plist_key), ZSTR_LEN(plist_key), &le, sizeof(le)) == NULL) {
			zend_string_release(plist_key);
			php_error_docref(NULL, E_ERROR, "could not register persistent entry");
			/* not reached */
		}
		zend_string_release(plist_key);
	}
}