Repository: incubator-hawq Updated Branches: refs/heads/master 0abbac2d8 -> 90bd061ba
HAWQ-1083. Do not use CURLOPT_RESOLVE when call curl. Project: http://git-wip-us.apache.org/repos/asf/incubator-hawq/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-hawq/commit/90bd061b Tree: http://git-wip-us.apache.org/repos/asf/incubator-hawq/tree/90bd061b Diff: http://git-wip-us.apache.org/repos/asf/incubator-hawq/diff/90bd061b Branch: refs/heads/master Commit: 90bd061ba899a80d856db7b305727c920a894af0 Parents: 0abbac2 Author: Oleksandr Diachenko <[email protected]> Authored: Thu Oct 6 12:00:36 2016 -0700 Committer: Oleksandr Diachenko <[email protected]> Committed: Thu Oct 6 12:00:36 2016 -0700 ---------------------------------------------------------------------- src/backend/access/external/libchurl.c | 35 +++++++---- src/backend/access/external/pxfutils.c | 92 +++++++++++++++++++++++++++++ src/include/access/libchurl.h | 1 - src/include/access/pxfutils.h | 8 ++- 4 files changed, 123 insertions(+), 13 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/90bd061b/src/backend/access/external/libchurl.c ---------------------------------------------------------------------- diff --git a/src/backend/access/external/libchurl.c b/src/backend/access/external/libchurl.c index 2d4aab4..964b3b0 100644 --- a/src/backend/access/external/libchurl.c +++ b/src/backend/access/external/libchurl.c @@ -21,6 +21,7 @@ #include "lib/stringinfo.h" #include "utils/guc.h" #include "miscadmin.h" +#include "access/pxfutils.h" /* include libcurl without typecheck. * This allows wrapping curl_easy_setopt to be wrapped @@ -310,17 +311,6 @@ CHURL_HANDLE churl_init(const char* url, CHURL_HEADERS headers) create_curl_handle(context); clear_error_buffer(context); - /* needed to resolve localhost */ - if (strstr(url, LocalhostIpV4) != NULL) { - struct curl_slist *resolve_hosts = NULL; - char *pxf_host_entry = (char *) palloc0(strlen(pxf_service_address) + strlen(LocalhostIpV4Entry) + 1); - strcat(pxf_host_entry, pxf_service_address); - strcat(pxf_host_entry, LocalhostIpV4Entry); - resolve_hosts = curl_slist_append(NULL, pxf_host_entry); - set_curl_option(context, CURLOPT_RESOLVE, resolve_hosts); - pfree(pxf_host_entry); - } - set_curl_option(context, CURLOPT_URL, url); set_curl_option(context, CURLOPT_VERBOSE, (const void*)FALSE); set_curl_option(context, CURLOPT_ERRORBUFFER, context->curl_error_buffer); @@ -491,6 +481,29 @@ void create_curl_handle(churl_context* context) void set_curl_option(churl_context* context, CURLoption option, const void* data) { int curl_error; + + if (option == CURLOPT_URL) + { + const char* url = (char* )data; + /* needed to resolve localhost */ + if (strstr(url, LocalhostIpV4) != NULL) { + //get loopback interface ip address + char* loopback_addr = get_loopback_ip_addr(); + elog(DEBUG1, "Loopback interface IP address: %s", loopback_addr); + char* replaced_url = replace_string(url, LocalhostIpV4, loopback_addr); + elog(DEBUG1, "Replaced url: %s", replaced_url); + if (CURLE_OK != (curl_error = curl_easy_setopt(context->curl_handle, option, replaced_url))) + elog(ERROR, "internal error: curl_easy_setopt %d error (%d - %s)", + option, curl_error, curl_easy_strerror(curl_error)); + + //release memory + pfree(replaced_url); + pfree(loopback_addr); + return; + } + } + + if (CURLE_OK != (curl_error = curl_easy_setopt(context->curl_handle, option, data))) elog(ERROR, "internal error: curl_easy_setopt %d error (%d - %s)", option, curl_error, curl_easy_strerror(curl_error)); http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/90bd061b/src/backend/access/external/pxfutils.c ---------------------------------------------------------------------- diff --git a/src/backend/access/external/pxfutils.c b/src/backend/access/external/pxfutils.c index 1b53a4a..fec3223 100644 --- a/src/backend/access/external/pxfutils.c +++ b/src/backend/access/external/pxfutils.c @@ -24,6 +24,10 @@ #include "commands/dbcommands.h" #include "miscadmin.h" #include "utils/builtins.h" +#include <net/if.h> +#include <ifaddrs.h> +#include <sys/socket.h> +#include <netdb.h> /* Wrapper for libchurl */ static void process_request(ClientContext* client_context, char *uri); @@ -133,3 +137,91 @@ static void process_request(ClientContext* client_context, char *uri) } + +/* + * Finds ip address of any available loopback interface(ipv4/ipv6). + * Returns ip for ipv4 addresses and [ip] for ipv6 addresses. + * + */ +char* get_loopback_ip_addr() +{ + struct ifaddrs *ifaddr, *ifa; + int family, s, n; + char host[NI_MAXHOST]; + char *loopback_addr = NULL; + + if (getifaddrs(&ifaddr) == -1) { + elog(ERROR, "Unable to obtain list of network interfaces."); + } + + for (ifa = ifaddr, n = 0; ifa != NULL; ifa = ifa->ifa_next, n++) { + if (ifa->ifa_addr == NULL) + continue; + + family = ifa->ifa_addr->sa_family; + + if (family == AF_INET || family == AF_INET6) { + s = getnameinfo(ifa->ifa_addr, + (family == AF_INET) ? + sizeof(struct sockaddr_in) : + sizeof(struct sockaddr_in6), host, NI_MAXHOST, + NULL, 0, NI_NUMERICHOST); + if (s != 0) { + elog(WARNING, "Unable to get name information for interface, getnameinfo() failed: %s\n", gai_strerror(s)); + } + + //get loopback interface + if (ifa->ifa_flags & IFF_LOOPBACK) { + if (family == AF_INET) + { + loopback_addr = palloc0(strlen(host) + 1); + sprintf(loopback_addr, "%s", host); + } + else + { + loopback_addr = palloc0(strlen(host) + 3); + sprintf(loopback_addr, "[%s]", host); + } + break; + } + } + } + + freeifaddrs(ifaddr); + + if (loopback_addr == NULL || !loopback_addr[0]) + elog(ERROR, "Unable to get loop back address"); + + return loopback_addr; +} + + +/* + * Replaces first occurrence of replace in string with replacement. + * Caller is responsible for releasing memory allocated for result. + * + */ +char* replace_string(const char* string, const char* replace, const char* replacement) +{ + char* replaced = NULL; + char* start = strstr(string, replace); + if (start) + { + char* before_token = pnstrdup(string, start - string); + char* after_token = pstrdup(string + (start - string) + strlen(replace)); + replaced = palloc0(strlen(before_token) + strlen(replacement) + strlen(after_token) + 1); + sprintf(replaced, "%s%s%s", before_token, replacement, after_token); + + //release memory + pfree(before_token); + pfree(after_token); + } else + { + replaced = palloc0(strlen(string) + 1); + sprintf(replaced, "%s", string); + } + + return replaced; + +} + http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/90bd061b/src/include/access/libchurl.h ---------------------------------------------------------------------- diff --git a/src/include/access/libchurl.h b/src/include/access/libchurl.h index c3ad17d..1aa810d 100644 --- a/src/include/access/libchurl.h +++ b/src/include/access/libchurl.h @@ -141,7 +141,6 @@ void churl_cleanup(CHURL_HANDLE handle, bool after_error); */ void print_http_headers(CHURL_HEADERS headers); - #endif #define LocalhostIpV4Entry ":127.0.0.1" http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/90bd061b/src/include/access/pxfutils.h ---------------------------------------------------------------------- diff --git a/src/include/access/pxfutils.h b/src/include/access/pxfutils.h index 74fd998..e9bd0c2 100644 --- a/src/include/access/pxfutils.h +++ b/src/include/access/pxfutils.h @@ -42,7 +42,13 @@ void port_to_str(char** port, int new_port); /* get hdfs location from current session's filespace entry */ void get_hdfs_location_from_filespace(char** path); -/* Parse the REST message and issue the libchurl call */ +/* parse the REST message and issue the libchurl call */ void call_rest(GPHDUri *hadoop_uri, ClientContext *client_context, char* rest_msg); +/* get ip address of loopback interface */ +char* get_loopback_ip_addr(void); + +/* replace first occurrence of replace in string with replacement*/ +char* replace_string(const char* string, const char* replace, const char* replacement); + #endif // _PXF_UTILS_H_
