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_

Reply via email to