if (!MySG(allow_persistent)) {
persistent=0;
}
if (persistent) {
list_entry *le;
/* try to find if we already have this link in our persistent list */
if (zend_hash_find(&EG(persistent_list), hashed_details, hashed_details_length+1, (void **) &le)==FAILURE) { /* we don't */
list_entry new_le;
if (MySG(max_links)!=-1 && MySG(num_links)>=MySG(max_links)) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Too many open links (%ld)", MySG(num_links));
efree(hashed_details);
MYSQL_DO_CONNECT_RETURN_FALSE();
}
if (MySG(max_persistent)!=-1 && MySG(num_persistent)>=MySG(max_persistent)) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Too many open persistent links (%ld)", MySG(num_persistent));
efree(hashed_details);
MYSQL_DO_CONNECT_RETURN_FALSE();
}
/* create the link */
mysql = (php_mysql_conn *) malloc(sizeof(php_mysql_conn));
mysql->active_result_id = 0;
#if MYSQL_VERSION_ID > 32199 /* this lets us set the port number */
mysql_init(&mysql->conn);
if (connect_timeout != -1)
mysql_options(&mysql->conn, MYSQL_OPT_CONNECT_TIMEOUT, (const char *)&connect_timeout);
if (mysql_real_connect(&mysql->conn, host, user, passwd, NULL, port, socket, client_flags)==NULL) {
#else
if (mysql_connect(&mysql->conn, host, user, passwd)==NULL) {
#endif
/* Populate connect error globals so that the error functions can read them */
if (MySG(connect_error)!=NULL) efree(MySG(connect_error));
MySG(connect_error)=estrdup(mysql_error(&mysql->conn));
php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", MySG(connect_error));
#if defined(HAVE_MYSQL_ERRNO)
MySG(connect_errno)=mysql_errno(&mysql->conn);
#endif
free(mysql);
efree(hashed_details);
MYSQL_DO_CONNECT_RETURN_FALSE();
}
/* hash it up */
Z_TYPE(new_le) = le_plink;
new_le.ptr = mysql;
if (zend_hash_update(&EG(persistent_list), hashed_details, hashed_details_length+1, (void *) &new_le, sizeof(list_entry), NULL)==FAILURE) {
free(mysql);
efree(hashed_details);
MYSQL_DO_CONNECT_RETURN_FALSE();
}
MySG(num_persistent)++;
MySG(num_links)++;
} else { /* The link is in our list of persistent connections */
if (Z_TYPE_P(le) != le_plink) {
MYSQL_DO_CONNECT_RETURN_FALSE();
}
/* ensure that the link did not die */
#if MYSQL_VERSION_ID > 32230 /* Use mysql_ping to ensure link is alive (and to reconnect if needed) */
if (mysql_ping(le->ptr)) {
#else /* Use mysql_stat() to check if server is alive */
handler=signal(SIGPIPE, SIG_IGN);
#if defined(HAVE_MYSQL_ERRNO) && defined(CR_SERVER_GONE_ERROR)
mysql_stat(le->ptr);
if (mysql_errno(&((php_mysql_conn *) le->ptr)->conn) == CR_SERVER_GONE_ERROR) {
#else
if (!strcasecmp(mysql_stat(le->ptr), "mysql server has gone away")) { /* the link died */
#endif
signal(SIGPIPE, handler);
#endif /* end mysql_ping */
#if MYSQL_VERSION_ID > 32199 /* this lets us set the port number */
if (mysql_real_connect(le->ptr, host, user, passwd, NULL, port, socket, client_flags)==NULL) {
#else
if (mysql_connect(le->ptr, host, user, passwd)==NULL) {
#endif
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Link to server lost, unable to reconnect");
zend_hash_del(&EG(persistent_list), hashed_details, hashed_details_length+1);
efree(hashed_details);
MYSQL_DO_CONNECT_RETURN_FALSE();
}
}
#if MYSQL_VERSION_ID < 32231
signal(SIGPIPE, handler);
#endif
mysql = (php_mysql_conn *) le->ptr;
}
ZEND_REGISTER_RESOURCE(return_value, mysql, le_plink);
} else { /* non persistent */
list_entry *index_ptr, new_index_ptr;
/* first we check the hash for the hashed_details key. if it exists,
* it should point us to the right offset where the actual mysql link sits.
* if it doesn't, open a new mysql link, add it to the resource list,
* and add a pointer to it with hashed_details as the key.
*/
if (!new_link && zend_hash_find(&EG(regular_list), hashed_details, hashed_details_length+1,(void **) &index_ptr)==SUCCESS) {
int type;
long link;
void *ptr;
if (Z_TYPE_P(index_ptr) != le_index_ptr) {
MYSQL_DO_CONNECT_RETURN_FALSE();
}
link = (long) index_ptr->ptr;
ptr = zend_list_find(link,&type); /* check if the link is still there */
if (ptr && (type==le_link || type==le_plink)) {
zend_list_addref(link);
Z_LVAL_P(return_value) = link;
php_mysql_set_default_link(link TSRMLS_CC);
Z_TYPE_P(return_value) = IS_RESOURCE;
efree(hashed_details);
MYSQL_DO_CONNECT_CLEANUP();
return;
} else {
zend_hash_del(&EG(regular_list), hashed_details, hashed_details_length+1);
}
}
if (MySG(max_links)!=-1 && MySG(num_links)>=MySG(max_links)) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Too many open links (%ld)", MySG(num_links));
efree(hashed_details);
MYSQL_DO_CONNECT_RETURN_FALSE();
}
mysql = (php_mysql_conn *) emalloc(sizeof(php_mysql_conn));
mysql->active_result_id = 0;
#if MYSQL_VERSION_ID > 32199 /* this lets us set the port number */
mysql_init(&mysql->conn);
if (connect_timeout != -1)
mysql_options(&mysql->conn, MYSQL_OPT_CONNECT_TIMEOUT, (const char *)&connect_timeout);
if (mysql_real_connect(&mysql->conn, host, user, passwd, NULL, port, socket, client_flags)==NULL) {
#else
if (mysql_connect(&mysql->conn, host, user, passwd)==NULL) {
#endif
/* Populate connect error globals so that the error functions can read them */
if (MySG(connect_error)!=NULL) efree(MySG(connect_error));
MySG(connect_error)=estrdup(mysql_error(&mysql->conn));
php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", MySG(connect_error));
#if defined(HAVE_MYSQL_ERRNO)
MySG(connect_errno)=mysql_errno(&mysql->conn);
#endif
efree(hashed_details);
efree(mysql);
MYSQL_DO_CONNECT_RETURN_FALSE();
}
/* add it to the list */
ZEND_REGISTER_RESOURCE(return_value, mysql, le_link);
/* add it to the hash */
new_index_ptr.ptr = (void *) Z_LVAL_P(return_value);
Z_TYPE(new_index_ptr) = le_index_ptr;
if (zend_hash_update(&EG(regular_list), hashed_details, hashed_details_length+1,(void *) &new_index_ptr, sizeof(list_entry), NULL)==FAILURE) {
efree(hashed_details);
MYSQL_DO_CONNECT_RETURN_FALSE();
}
MySG(num_links)++;
}
switch(ZEND_NUM_ARGS()) {///zend_num_args是输入参数的个数
case 0: /* defaults */
break;
case 1: {
if (zend_get_parameters_ex(1, &z_host)==FAILURE) {
MYSQL_DO_CONNECT_RETURN_FALSE();
}
}
break;
case 2: {
if (zend_get_parameters_ex(2, &z_host, &z_user)==FAILURE) {
MYSQL_DO_CONNECT_RETURN_FALSE();
}
convert_to_string_ex(z_user);
user = Z_STRVAL_PP(z_user);
}
break;
case 3: {
if (zend_get_parameters_ex(3, &z_host, &z_user, &z_passwd) == FAILURE) {
MYSQL_DO_CONNECT_RETURN_FALSE();
}
convert_to_string_ex(z_user);
convert_to_string_ex(z_passwd);
user = Z_STRVAL_PP(z_user);
passwd = Z_STRVAL_PP(z_passwd);
}
break;
case 4: {
if (!persistent) {
if (zend_get_parameters_ex(4, &z_host, &z_user, &z_passwd, &z_new_link) == FAILURE) {
MYSQL_DO_CONNECT_RETURN_FALSE();
}
convert_to_string_ex(z_user);
convert_to_string_ex(z_passwd);
convert_to_boolean_ex(z_new_link);
user = Z_STRVAL_PP(z_user);
passwd = Z_STRVAL_PP(z_passwd);
new_link = Z_BVAL_PP(z_new_link);
}
else {
if (zend_get_parameters_ex(4, &z_host, &z_user, &z_passwd, &z_client_flags) == FAILURE) {
MYSQL_DO_CONNECT_RETURN_FALSE();
}
convert_to_string_ex(z_user);
convert_to_string_ex(z_passwd);
convert_to_long_ex(z_client_flags);
user = Z_STRVAL_PP(z_user);
passwd = Z_STRVAL_PP(z_passwd);
client_flags = Z_LVAL_PP(z_client_flags);
}
}
break;
case 5: {
if (zend_get_parameters_ex(5, &z_host, &z_user, &z_passwd, &z_new_link, &z_client_flags) == FAILURE) {
MYSQL_DO_CONNECT_RETURN_FALSE();
}
convert_to_string_ex(z_user);
convert_to_string_ex(z_passwd);
convert_to_boolean_ex(z_new_link);
convert_to_long_ex(z_client_flags);
user = Z_STRVAL_PP(z_user);
passwd = Z_STRVAL_PP(z_passwd);
new_link = Z_BVAL_PP(z_new_link);
client_flags = Z_LVAL_PP(z_client_flags);
}
break;
default:
WRONG_PARAM_COUNT;
break;
}
/* disable local infile option for open_basedir */
if (PG(open_basedir) && strlen(PG(open_basedir)) && (client_flags & CLIENT_LOCAL_FILES)) {
client_flags ^= CLIENT_LOCAL_FILES;
}
if (z_host) {
SEPARATE_ZVAL(z_host); /* We may modify z_host if it contains a port, separate */
convert_to_string_ex(z_host);
host_and_port = Z_STRVAL_PP(z_host);
if (z_user) {
convert_to_string_ex(z_user);
user = Z_STRVAL_PP(z_user);
if (z_passwd) {
convert_to_string_ex(z_passwd);
passwd = Z_STRVAL_PP(z_passwd);
}
}
}
/* We cannot use mysql_port anymore in windows, need to use
* mysql_real_connect() to set the port.
*/
if (host_and_port && (tmp=strchr(host_and_port, ':'))) {
host = estrndup(host_and_port, tmp-host_and_port);
free_host = 1;
tmp++;
if (tmp[0] != '/') {
port = atoi(tmp);
if ((tmp=strchr(tmp, ':'))) {
tmp++;
socket=tmp;
}
} else {
socket = tmp;
}
} else {
host = host_and_port;
port = MySG(default_port);
}