Skip to content

Instantly share code, notes, and snippets.

@mdg
Last active August 29, 2015 14:01
Show Gist options
  • Save mdg/fde0fedafb0de42ae411 to your computer and use it in GitHub Desktop.
Save mdg/fde0fedafb0de42ae411 to your computer and use it in GitHub Desktop.
Keyur's patches for Etsy API Concurrency
Here's the source RPM we built on:
http://vault.centos.org/6.5/os/Source/SPackages/curl-7.19.7-37.el6_4.src.rpm
The PHP release we applied the patch on is 5.4.26:
http://us1.php.net/get/php-5.4.26.tar.gz/from/a/mirror
diff --git a/include/curl/multi.h b/include/curl/multi.h
index 153f772..0f4cc74 100644
--- a/include/curl/multi.h
+++ b/include/curl/multi.h
@@ -68,6 +68,31 @@ typedef enum {
CURLM_LAST
} CURLMcode;
+/* NOTE: if you add a state here, add the name to the statename[] array
+ * in multi.c as well!
+ */
+typedef enum {
+ CURLM_STATE_FIRST = -1, /* not a true state, never use this */
+ CURLM_STATE_INIT, /* start in this state */
+ CURLM_STATE_CONNECT, /* resolve/connect has been sent off */
+ CURLM_STATE_WAITRESOLVE, /* awaiting the resolve to finalize */
+ CURLM_STATE_WAITCONNECT, /* awaiting the connect to finalize */
+ CURLM_STATE_WAITPROXYCONNECT, /* awaiting proxy CONNECT to finalize */
+ CURLM_STATE_PROTOCONNECT, /* completing the protocol-specific connect phase */
+ CURLM_STATE_WAITDO, /* wait for our turn to send the request */
+ CURLM_STATE_DO, /* start send off the request (part 1) */
+ CURLM_STATE_DOING, /* sending off the request (part 1) */
+ CURLM_STATE_DO_MORE, /* send off the request (part 2) */
+ CURLM_STATE_DO_DONE, /* done sending off request */
+ CURLM_STATE_WAITPERFORM, /* wait for our turn to read the response */
+ CURLM_STATE_PERFORM, /* transfer data */
+ CURLM_STATE_TOOFAST, /* wait because limit-rate exceeded */
+ CURLM_STATE_DONE, /* post data transfer operation */
+ CURLM_STATE_COMPLETED, /* operation complete */
+
+ CURLM_STATE_LAST /* not a true state, never use this */
+} CURLMstate;
+
/* just to make code nicer when using curl_multi_socket() you can now check
for CURLM_CALL_MULTI_SOCKET too in the same style it works for
curl_multi_perform() and CURLM_CALL_MULTI_PERFORM */
@@ -120,6 +144,17 @@ CURL_EXTERN CURLMcode curl_multi_remove_handle(CURLM *multi_handle,
CURL *curl_handle);
/*
+ * Name: curl_multi_get_handle_state()
+ *
+ * Desc: get the state of the handle from the multi stack
+ *
+ * Returns: CURLMcode type, general multi error code.
+ */
+CURL_EXTERN CURLMcode curl_multi_get_handle_state(CURLM *multi_handle,
+ CURL *curl_handle,
+ CURLMstate *state);
+
+ /*
* Name: curl_multi_fdset()
*
* Desc: Ask curl for its fd_set sets. The app can use these to select() or
diff --git a/lib/multi.c b/lib/multi.c
index 48df928..572aae1 100644
--- a/lib/multi.c
+++ b/lib/multi.c
@@ -65,30 +65,6 @@ struct Curl_message {
struct Curl_message *next;
};
-/* NOTE: if you add a state here, add the name to the statename[] array as
- well!
-*/
-typedef enum {
- CURLM_STATE_INIT, /* start in this state */
- CURLM_STATE_CONNECT, /* resolve/connect has been sent off */
- CURLM_STATE_WAITRESOLVE, /* awaiting the resolve to finalize */
- CURLM_STATE_WAITCONNECT, /* awaiting the connect to finalize */
- CURLM_STATE_WAITPROXYCONNECT, /* awaiting proxy CONNECT to finalize */
- CURLM_STATE_PROTOCONNECT, /* completing the protocol-specific connect phase */
- CURLM_STATE_WAITDO, /* wait for our turn to send the request */
- CURLM_STATE_DO, /* start send off the request (part 1) */
- CURLM_STATE_DOING, /* sending off the request (part 1) */
- CURLM_STATE_DO_MORE, /* send off the request (part 2) */
- CURLM_STATE_DO_DONE, /* done sending off request */
- CURLM_STATE_WAITPERFORM, /* wait for our turn to read the response */
- CURLM_STATE_PERFORM, /* transfer data */
- CURLM_STATE_TOOFAST, /* wait because limit-rate exceeded */
- CURLM_STATE_DONE, /* post data transfer operation */
- CURLM_STATE_COMPLETED, /* operation complete */
-
- CURLM_STATE_LAST /* not a true state, never use this */
-} CURLMstate;
-
/* we support N sockets per easy handle. Set the corresponding bit to what
action we should wait for */
#define MAX_SOCKSPEREASYHANDLE 5
@@ -732,6 +708,30 @@ CURLMcode curl_multi_remove_handle(CURLM *multi_handle,
return CURLM_BAD_EASY_HANDLE; /* twasn't found */
}
+CURLMcode curl_multi_get_handle_state(CURLM *multi_handle,
+ CURL *curl_handle,
+ CURLMstate *state)
+{
+ struct Curl_multi *multi=(struct Curl_multi *)multi_handle;
+ struct Curl_one_easy *easy;
+
+ /* First, make some basic checks that the CURLM handle is a good handle */
+ if(!GOOD_MULTI_HANDLE(multi))
+ return CURLM_BAD_HANDLE;
+
+ /* Verify that we got a somewhat good easy handle too */
+ if(!GOOD_EASY_HANDLE(curl_handle))
+ return CURLM_BAD_EASY_HANDLE;
+
+ /* pick-up from the 'curl_handle' the kept position in the list */
+ easy = ((struct SessionHandle *)curl_handle)->multi_pos;
+ if (!easy)
+ return CURLM_BAD_EASY_HANDLE;
+
+ *state = easy->state;
+ return CURLM_OK;
+}
+
bool Curl_multi_canPipeline(const struct Curl_multi* multi)
{
return multi->pipelining_enabled;
From ed7b42be199d3c8ccd5d4fdcf17726b8875a4757 Mon Sep 17 00:00:00 2001
From: Keyur Govande <keyur@php.net>
Date: Wed, 17 Jul 2013 00:04:24 +0000
Subject: [PATCH] Add in new curl method
---
ext/curl/config.m4 | 7 +++++++
ext/curl/interface.c | 34 +++++++++++++++++++++++++++++++++-
ext/curl/multi.c | 28 ++++++++++++++++++++++++++++
ext/curl/php_curl.h | 3 +++
4 files changed, 71 insertions(+), 1 deletion(-)
diff --git a/ext/curl/config.m4 b/ext/curl/config.m4
index fbb4f5b..385f52b 100644
--- a/ext/curl/config.m4
+++ b/ext/curl/config.m4
@@ -152,6 +152,13 @@ int main(int argc, char *argv[])
$CURL_LIBS -L$CURL_DIR/$PHP_LIBDIR
])
+ PHP_CHECK_LIBRARY(curl,curl_multi_get_handle_state,
+ [
+ AC_DEFINE(HAVE_CURL_MULTI_HANDLE_STATE,1,[ ])
+ ],[],[
+ $CURL_LIBS -L$CURL_DIR/$PHP_LIBDIR
+ ])
+
if test "$PHP_CURLWRAPPERS" != "no" ; then
AC_DEFINE(PHP_CURL_URL_WRAPPERS,1,[ ])
fi
diff --git a/ext/curl/interface.c b/ext/curl/interface.c
index 531f15b..999e763 100644
--- a/ext/curl/interface.c
+++ b/ext/curl/interface.c
@@ -327,6 +327,14 @@ ZEND_BEGIN_ARG_INFO(arginfo_curl_multi_remove_handle, 0)
ZEND_ARG_INFO(0, ch)
ZEND_END_ARG_INFO()
+#if HAVE_CURL_MULTI_HANDLE_STATE
+ZEND_BEGIN_ARG_INFO(arginfo_curl_multi_get_handle_state, 0)
+ ZEND_ARG_INFO(0, mh)
+ ZEND_ARG_INFO(0, ch)
+ ZEND_ARG_INFO(0, state)
+ZEND_END_ARG_INFO()
+#endif
+
ZEND_BEGIN_ARG_INFO_EX(arginfo_curl_multi_select, 0, 0, 1)
ZEND_ARG_INFO(0, mh)
ZEND_ARG_INFO(0, timeout)
@@ -367,6 +375,9 @@ const zend_function_entry curl_functions[] = {
PHP_FE(curl_multi_init, arginfo_curl_multi_init)
PHP_FE(curl_multi_add_handle, arginfo_curl_multi_add_handle)
PHP_FE(curl_multi_remove_handle, arginfo_curl_multi_remove_handle)
+#if HAVE_CURL_MULTI_HANDLE_STATE
+ PHP_FE(curl_multi_get_handle_state, arginfo_curl_multi_get_handle_state)
+#endif
PHP_FE(curl_multi_select, arginfo_curl_multi_select)
PHP_FE(curl_multi_exec, arginfo_curl_multi_exec)
PHP_FE(curl_multi_getcontent, arginfo_curl_multi_getcontent)
@@ -722,7 +733,6 @@ PHP_MINIT_FUNCTION(curl)
REGISTER_CURL_CONSTANT(CURLINFO_LOCAL_PORT);
#endif
-
/* cURL protocol constants (curl_version) */
REGISTER_CURL_CONSTANT(CURL_VERSION_IPV6);
REGISTER_CURL_CONSTANT(CURL_VERSION_KERBEROS4);
@@ -732,6 +742,28 @@ PHP_MINIT_FUNCTION(curl)
/* version constants */
REGISTER_CURL_CONSTANT(CURLVERSION_NOW);
+#if HAVE_CURL_MULTI_HANDLE_STATE
+ /* Curl handle state during multi */
+ REGISTER_CURL_CONSTANT(CURLM_STATE_FIRST);
+ REGISTER_CURL_CONSTANT(CURLM_STATE_INIT);
+ REGISTER_CURL_CONSTANT(CURLM_STATE_CONNECT);
+ REGISTER_CURL_CONSTANT(CURLM_STATE_WAITRESOLVE);
+ REGISTER_CURL_CONSTANT(CURLM_STATE_WAITCONNECT);
+ REGISTER_CURL_CONSTANT(CURLM_STATE_WAITPROXYCONNECT);
+ REGISTER_CURL_CONSTANT(CURLM_STATE_PROTOCONNECT);
+ REGISTER_CURL_CONSTANT(CURLM_STATE_WAITDO);
+ REGISTER_CURL_CONSTANT(CURLM_STATE_DO);
+ REGISTER_CURL_CONSTANT(CURLM_STATE_DOING);
+ REGISTER_CURL_CONSTANT(CURLM_STATE_DO_MORE);
+ REGISTER_CURL_CONSTANT(CURLM_STATE_DO_DONE);
+ REGISTER_CURL_CONSTANT(CURLM_STATE_WAITPERFORM);
+ REGISTER_CURL_CONSTANT(CURLM_STATE_PERFORM);
+ REGISTER_CURL_CONSTANT(CURLM_STATE_TOOFAST);
+ REGISTER_CURL_CONSTANT(CURLM_STATE_DONE);
+ REGISTER_CURL_CONSTANT(CURLM_STATE_COMPLETED);
+ REGISTER_CURL_CONSTANT(CURLM_STATE_LAST);
+#endif
+
/* Error Constants */
REGISTER_CURL_CONSTANT(CURLE_OK);
REGISTER_CURL_CONSTANT(CURLE_UNSUPPORTED_PROTOCOL);
diff --git a/ext/curl/multi.c b/ext/curl/multi.c
index 38c1f1a..d5556bd 100644
--- a/ext/curl/multi.c
+++ b/ext/curl/multi.c
@@ -155,6 +155,34 @@ PHP_FUNCTION(curl_multi_remove_handle)
}
/* }}} */
+#if HAVE_CURL_MULTI_HANDLE_STATE
+/* {{{ proto int curl_multi_get_handle_state(resource mh, resource ch, int &current_state)
+ Get the state of the curl-handle which is part of the multi-handle */
+PHP_FUNCTION(curl_multi_get_handle_state)
+{
+ zval *z_mh;
+ zval *z_ch;
+ zval *z_cur_state;
+ php_curlm *mh;
+ php_curl *ch;
+ CURLMstate cur_state = CURLM_STATE_FIRST;
+ int result;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rrz", &z_mh, &z_ch, &z_cur_state) == FAILURE) {
+ return;
+ }
+
+ ZEND_FETCH_RESOURCE(mh, php_curlm *, &z_mh, -1, le_curl_multi_handle_name, le_curl_multi_handle);
+ ZEND_FETCH_RESOURCE(ch, php_curl *, &z_ch, -1, le_curl_name, le_curl);
+
+ result = curl_multi_get_handle_state(mh->multi, ch->cp, &cur_state);
+ ZVAL_LONG(z_cur_state, cur_state);
+
+ RETURN_LONG(result);
+}
+/* }}} */
+#endif // HAVE_CURL_MULTI_HANDLE_STATE
+
static void _make_timeval_struct(struct timeval *to, double timeout) /* {{{ */
{
unsigned long conv;
diff --git a/ext/curl/php_curl.h b/ext/curl/php_curl.h
index 945f0a4..0080703 100644
--- a/ext/curl/php_curl.h
+++ b/ext/curl/php_curl.h
@@ -72,6 +72,9 @@ PHP_FUNCTION(curl_close);
PHP_FUNCTION(curl_multi_init);
PHP_FUNCTION(curl_multi_add_handle);
PHP_FUNCTION(curl_multi_remove_handle);
+#if HAVE_CURL_MULTI_HANDLE_STATE
+PHP_FUNCTION(curl_multi_get_handle_state);
+#endif
PHP_FUNCTION(curl_multi_select);
PHP_FUNCTION(curl_multi_exec);
PHP_FUNCTION(curl_multi_getcontent);
--
1.8.1.6
@swestcott
Copy link

Just watched https://vimeo.com/channels/phpday/104905610. Has this PR been accepted upstream?

@jazzdan
Copy link

jazzdan commented Apr 29, 2015

@swestcott I don't believe so. You can see the discussion on the curl mailing list from a couple years back.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment