- Robert Iakobashvil added curl_multi_socket_action() to libcurl, which is a

function that deprecates the curl_multi_socket() function. Using the new
  function the application tell libcurl what action that was found in the
  socket that it passes in. This gives a significant performance boost as it
  allows libcurl to avoid a call to poll()/select() for every call to
  curl_multi_socket*().
This commit is contained in:
Daniel Stenberg 2007-04-16 16:34:08 +00:00
parent 827228bd69
commit 76627b322e
11 changed files with 106 additions and 40 deletions

View File

@ -6,6 +6,14 @@
Changelog
Daniel S (16 April 2007)
- Robert Iakobashvil added curl_multi_socket_action() to libcurl, which is a
function that deprecates the curl_multi_socket() function. Using the new
function the application tell libcurl what action that was found in the
socket that it passes in. This gives a significant performance boost as it
allows libcurl to avoid a call to poll()/select() for every call to
curl_multi_socket*().
Daniel S (14 April 2007)
- Jay Austin added "DH PARAMETERS" to the stunnel.pem certificate for the test
suite to make stunnel run better in some (most?) environments.

View File

@ -11,7 +11,8 @@ Curl and libcurl 7.16.3
This release includes the following changes:
o
o Added curl_multi_socket_action()
o Deprecated curl_multi_socket()
This release includes the following bugfixes:
@ -37,6 +38,6 @@ New curl mirrors:
This release would not have looked like this without help, code, reports and
advice from friends like these:
Song Ma, Dan Fandrich, Yang Tse, Jay Austin
Song Ma, Dan Fandrich, Yang Tse, Jay Austin, Robert Iakobashvil
Thanks! (and sorry if I forgot to mention someone)

View File

@ -4,29 +4,40 @@
.SH NAME
curl_multi_socket \- reads/writes available data
.SH SYNOPSIS
.nf
#include <curl/curl.h>
CURLMcode curl_multi_socket_action(CURLM * multi_handle,
curl_socket_t sockfd, int ev_bitmask,
int *running_handles);
CURLMcode curl_multi_socket(CURLM * multi_handle, curl_socket_t sockfd,
int *running_handles);
CURLMcode curl_multi_socket_all(CURLM *multi_handle,
int *running_handles);
.fi
.SH DESCRIPTION
Alternative versions of \fIcurl_multi_perform(3)\fP that allows the
application to pass in one of the file descriptors/sockets that have been
detected to have \&"action" on them and let libcurl perform. This allows
libcurl to not have to scan through all possible file descriptors to check for
action. When the application has detected action on a socket handled by
libcurl, it should call \fIcurl_multi_socket(3)\fP with the \fBsockfd\fP
argument set to the socket with the action.
application to pass in the file descriptor/socket that has been detected to
have \&"action" on it and let libcurl perform. This allows libcurl to not have
to scan through all possible file descriptors to check for action. When the
application has detected action on a socket handled by libcurl, it should call
\fIcurl_multi_socket_action(3)\fP with the \fBsockfd\fP argument set to the
socket with the action. When the events on a socket are known, they can be
passed as an events bitmask \fBev_bitmask\fP by first setting \fBev_bitmask\fP
to 0, and then adding using bitwise OR (|) any combination of events to be
choosen from CURL_CSELECT_IN, CURL_CSELECT_OUT or CURL_CSELECT_ERR. When the
events on a socket are unknown, pass 0 instead, and libcurl will test the
descriptor internally.
At return, the int \fBrunning_handles\fP points to will contain the number of
still running easy handles within the multi handle. When this number reaches
zero, all transfers are complete/done. Note that when you call
\fIcurl_multi_socket(3)\fP on a specific socket and the counter decreases by
one, it DOES NOT necessarily mean that this exact socket/transfer is the one
that completed. Use \fIcurl_multi_info_read(3)\fP to figure out which easy
handle that completed.
\fIcurl_multi_socket_action(3)\fP on a specific socket and the counter
decreases by one, it DOES NOT necessarily mean that this exact socket/transfer
is the one that completed. Use \fIcurl_multi_info_read(3)\fP to figure out
which easy handle that completed.
The curl_multi_socket functions inform the application about updates in the
socket (file descriptor) status by doing none, one or multiple calls to the
@ -44,6 +55,10 @@ wait for socket actions \- at most \- before doing the timeout action: call
the \fBcurl_multi_socket(3)\fP function with the \fBsockfd\fP argument set to
CURL_SOCKET_TIMEOUT.
Usage of \fIcurl_multi_socket(3)\fP is depricated, whereas the function is
equivalent to \fIcurl_multi_socket_action(3)\fP, when \fBev_bitmask\fP is set
to 0.
.SH "CALLBACK DETAILS"
The socket \fBcallback\fP function uses a prototype like this
@ -115,12 +130,15 @@ callback is called.
7. Wait for action on any of libcurl's sockets
8, When action happens, call curl_multi_socket() for the socket(s) that got
8, When action happens, call curl_multi_socket_action() for the socket(s) that got
action.
9. Go back to step 6.
.SH AVAILABILITY
This function was added in libcurl 7.15.4, although not deemed stable yet.
This function was added in libcurl 7.15.4, although deemed stablesince 7.16.0.
\fIcurl_multi_socket(3)\fP is deprecated, use
\fIcurl_multi_socket_action(3)\fP instead!
.SH "SEE ALSO"
.BR curl_multi_cleanup "(3), " curl_multi_init "(3), "
.BR curl_multi_fdset "(3), " curl_multi_info_read "(3)"

View File

@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2006, Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) 1998 - 2007, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@ -224,6 +224,10 @@ CURL_EXTERN const char *curl_multi_strerror(CURLMcode);
#define CURL_SOCKET_TIMEOUT CURL_SOCKET_BAD
#define CURL_CSELECT_IN 0x01
#define CURL_CSELECT_OUT 0x02
#define CURL_CSELECT_ERR 0x04
typedef int (*curl_socket_callback)(CURL *easy, /* easy handle */
curl_socket_t s, /* socket */
int what, /* see above */
@ -249,9 +253,21 @@ typedef int (*curl_multi_timer_callback)(CURLM *multi, /* multi handle */
CURL_EXTERN CURLMcode curl_multi_socket(CURLM *multi_handle, curl_socket_t s,
int *running_handles);
CURL_EXTERN CURLMcode curl_multi_socket_action(CURLM *multi_handle,
curl_socket_t s,
int ev_bitmask,
int *running_handles);
CURL_EXTERN CURLMcode curl_multi_socket_all(CURLM *multi_handle,
int *running_handles);
#ifndef CURL_ALLOW_OLD_MULTI_SOCKET
/* This macro below was added in 7.16.3 to push users who recompile to use
the new curl_multi_socket_action() instead of the old curl_multi_socket()
*/
#define curl_multi_socket(x,y,z) curl_multi_socket_action(x,y,0,z)
#endif
/*
* Name: curl_multi_timeout()
*

View File

@ -206,7 +206,7 @@ int waitconnect(curl_socket_t sockfd, /* socket */
/* timeout, no connect today */
return WAITCONN_TIMEOUT;
if(rc & CSELECT_ERR)
if(rc & CURL_CSELECT_ERR)
/* error condition caught */
return WAITCONN_FDSET_ERROR;

View File

@ -1661,6 +1661,7 @@ static void singlesocket(struct Curl_multi *multi,
static CURLMcode multi_socket(struct Curl_multi *multi,
bool checkall,
curl_socket_t s,
int ev_bitmask,
int *running_handles)
{
CURLMcode result = CURLM_OK;
@ -1698,8 +1699,14 @@ static CURLMcode multi_socket(struct Curl_multi *multi,
/* bad bad bad bad bad bad bad */
return CURLM_INTERNAL_ERROR;
if (data->set.one_easy->easy_conn) /* set socket event bitmask */
data->set.one_easy->easy_conn->cselect_bits = ev_bitmask;
result = multi_runsingle(multi, data->set.one_easy);
if (data->set.one_easy->easy_conn)
data->set.one_easy->easy_conn->cselect_bits = 0;
if(result == CURLM_OK)
/* get the socket(s) and check if the state has been changed since
last */
@ -1791,12 +1798,24 @@ CURLMcode curl_multi_setopt(CURLM *multi_handle,
return res;
}
/* we define curl_multi_socket() in the public multi.h header */
#undef curl_multi_socket
CURLMcode curl_multi_socket(CURLM *multi_handle, curl_socket_t s,
int *running_handles)
{
CURLMcode result = multi_socket((struct Curl_multi *)multi_handle, FALSE, s,
running_handles);
0, running_handles);
if (CURLM_OK == result)
update_timer((struct Curl_multi *)multi_handle);
return result;
}
CURLMcode curl_multi_socket_action(CURLM *multi_handle, curl_socket_t s,
int ev_bitmask, int *running_handles)
{
CURLMcode result = multi_socket((struct Curl_multi *)multi_handle, FALSE, s,
ev_bitmask, running_handles);
if (CURLM_OK == result)
update_timer((struct Curl_multi *)multi_handle);
return result;
@ -1806,7 +1825,7 @@ CURLMcode curl_multi_socket_all(CURLM *multi_handle, int *running_handles)
{
CURLMcode result = multi_socket((struct Curl_multi *)multi_handle,
TRUE, CURL_SOCKET_BAD, running_handles);
TRUE, CURL_SOCKET_BAD, 0, running_handles);
if (CURLM_OK == result)
update_timer((struct Curl_multi *)multi_handle);
return result;

View File

@ -161,7 +161,7 @@ static int wait_ms(int timeout_ms)
* Return values:
* -1 = system call error or fd >= FD_SETSIZE
* 0 = timeout
* CSELECT_IN | CSELECT_OUT | CSELECT_ERR
* CURL_CSELECT_IN | CURL_CSELECT_OUT | CURL_CSELECT_ERR
*/
int Curl_socket_ready(curl_socket_t readfd, curl_socket_t writefd, int timeout_ms)
{
@ -223,16 +223,16 @@ int Curl_socket_ready(curl_socket_t readfd, curl_socket_t writefd, int timeout_m
num = 0;
if (readfd != CURL_SOCKET_BAD) {
if (pfd[num].revents & (POLLRDNORM|POLLIN|POLLERR|POLLHUP))
ret |= CSELECT_IN;
ret |= CURL_CSELECT_IN;
if (pfd[num].revents & (POLLRDBAND|POLLPRI|POLLNVAL))
ret |= CSELECT_ERR;
ret |= CURL_CSELECT_ERR;
num++;
}
if (writefd != CURL_SOCKET_BAD) {
if (pfd[num].revents & (POLLWRNORM|POLLOUT))
ret |= CSELECT_OUT;
ret |= CURL_CSELECT_OUT;
if (pfd[num].revents & (POLLERR|POLLHUP|POLLNVAL))
ret |= CSELECT_ERR;
ret |= CURL_CSELECT_ERR;
}
return ret;
@ -279,15 +279,15 @@ int Curl_socket_ready(curl_socket_t readfd, curl_socket_t writefd, int timeout_m
ret = 0;
if (readfd != CURL_SOCKET_BAD) {
if (FD_ISSET(readfd, &fds_read))
ret |= CSELECT_IN;
ret |= CURL_CSELECT_IN;
if (FD_ISSET(readfd, &fds_err))
ret |= CSELECT_ERR;
ret |= CURL_CSELECT_ERR;
}
if (writefd != CURL_SOCKET_BAD) {
if (FD_ISSET(writefd, &fds_write))
ret |= CSELECT_OUT;
ret |= CURL_CSELECT_OUT;
if (FD_ISSET(writefd, &fds_err))
ret |= CSELECT_ERR;
ret |= CURL_CSELECT_ERR;
}
return ret;

View File

@ -76,11 +76,8 @@ struct pollfd
#define POLLRDBAND POLLPRI
#endif
#define CSELECT_IN 0x01
#define CSELECT_OUT 0x02
#define CSELECT_ERR 0x04
int Curl_socket_ready(curl_socket_t readfd, curl_socket_t writefd, int timeout_ms);
int Curl_socket_ready(curl_socket_t readfd, curl_socket_t writefd,
int timeout_ms);
int Curl_poll(struct pollfd ufds[], unsigned int nfds, int timeout_ms);

View File

@ -383,7 +383,7 @@ CURLcode Curl_SOCKS5(const char *proxy_name,
return CURLE_OPERATION_TIMEDOUT;
}
if(result & CSELECT_ERR) {
if(result & CURL_CSELECT_ERR) {
failf(conn->data, "SOCKS5: error occured during connection");
return CURLE_COULDNT_CONNECT;
}
@ -415,7 +415,7 @@ CURLcode Curl_SOCKS5(const char *proxy_name,
return CURLE_OPERATION_TIMEDOUT;
}
if(result & CSELECT_ERR) {
if(result & CURL_CSELECT_ERR) {
failf(conn->data, "SOCKS5 read error occured");
return CURLE_RECV_ERROR;
}

View File

@ -314,9 +314,10 @@ CURLcode Curl_readwrite(struct connectdata *conn,
curl_socket_t fd_read;
curl_socket_t fd_write;
int select_res;
curl_off_t contentlength;
int select_res = conn->cselect_bits;
conn->cselect_bits = 0;
/* only use the proper socket if the *_HOLD bit is not set simultaneously as
then we are in rate limiting state in that transfer direction */
@ -331,8 +332,12 @@ CURLcode Curl_readwrite(struct connectdata *conn,
else
fd_write = CURL_SOCKET_BAD;
select_res = Curl_socket_ready(fd_read, fd_write, 0);
if(select_res == CSELECT_ERR) {
if (!select_res) { /* Call for select()/poll() only, if read/write/error
status is not known. */
select_res = Curl_socket_ready(fd_read, fd_write, 0);
}
if(select_res == CURL_CSELECT_ERR) {
failf(data, "select/poll returned error");
return CURLE_SEND_ERROR;
}
@ -342,7 +347,7 @@ CURLcode Curl_readwrite(struct connectdata *conn,
the stream was rewound (in which case we have data in a
buffer) */
if((k->keepon & KEEP_READ) &&
((select_res & CSELECT_IN) || conn->bits.stream_was_rewound)) {
((select_res & CURL_CSELECT_IN) || conn->bits.stream_was_rewound)) {
/* read */
bool is_empty_data = FALSE;
@ -1350,7 +1355,7 @@ CURLcode Curl_readwrite(struct connectdata *conn,
/* If we still have writing to do, we check if we have a writable
socket. */
if((k->keepon & KEEP_WRITE) && (select_res & CSELECT_OUT)) {
if((k->keepon & KEEP_WRITE) && (select_res & CURL_CSELECT_OUT)) {
/* write */
int i, si;

View File

@ -900,6 +900,8 @@ struct connectdata {
union {
struct ftp_conn ftpc;
} proto;
int cselect_bits; /* bitmask of socket events */
};
/* The end of connectdata. */