Repository: kudu
Updated Branches:
  refs/heads/master 4ec2598a3 -> 137775bdd


[util] Add ParseStringsWithScheme in net_util

This commit adds a new util to allow parsing address with scheme, e.g.
'<fs>://<host>:<port>/<path>' into a <host>:<port> pair.

Change-Id: I2447ab80e0b0737c4eb2ba8216769a52b5c07ce0
Reviewed-on: http://gerrit.cloudera.org:8080/11843
Reviewed-by: Adar Dembo <a...@cloudera.com>
Tested-by: Kudu Jenkins
Reviewed-by: Alexey Serbin <aser...@cloudera.com>


Project: http://git-wip-us.apache.org/repos/asf/kudu/repo
Commit: http://git-wip-us.apache.org/repos/asf/kudu/commit/32a4fe16
Tree: http://git-wip-us.apache.org/repos/asf/kudu/tree/32a4fe16
Diff: http://git-wip-us.apache.org/repos/asf/kudu/diff/32a4fe16

Branch: refs/heads/master
Commit: 32a4fe168aab97a0905283506da498304774748f
Parents: 4ec2598
Author: Hao Hao <hao....@cloudera.com>
Authored: Wed Oct 31 17:46:20 2018 -0700
Committer: Hao Hao <hao....@cloudera.com>
Committed: Thu Nov 1 20:03:56 2018 +0000

----------------------------------------------------------------------
 src/kudu/util/net/net_util-test.cc | 46 +++++++++++++++++++++++++++++---
 src/kudu/util/net/net_util.cc      | 47 +++++++++++++++++++++++++++++++--
 src/kudu/util/net/net_util.h       | 17 +++++++++++-
 3 files changed, 104 insertions(+), 6 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/kudu/blob/32a4fe16/src/kudu/util/net/net_util-test.cc
----------------------------------------------------------------------
diff --git a/src/kudu/util/net/net_util-test.cc 
b/src/kudu/util/net/net_util-test.cc
index 202ec6b..8ad0fba 100644
--- a/src/kudu/util/net/net_util-test.cc
+++ b/src/kudu/util/net/net_util-test.cc
@@ -76,13 +76,53 @@ TEST_F(NetUtilTest, TestParseAddresses) {
 
   // Test some invalid addresses.
   Status s = DoParseBindAddresses("0.0.0.0:xyz", &ret);
-  ASSERT_STR_CONTAINS(s.ToString(), "Invalid port");
+  ASSERT_STR_CONTAINS(s.ToString(), "invalid port");
 
   s = DoParseBindAddresses("0.0.0.0:100000", &ret);
-  ASSERT_STR_CONTAINS(s.ToString(), "Invalid port");
+  ASSERT_STR_CONTAINS(s.ToString(), "invalid port");
 
   s = DoParseBindAddresses("0.0.0.0:", &ret);
-  ASSERT_STR_CONTAINS(s.ToString(), "Invalid port");
+  ASSERT_STR_CONTAINS(s.ToString(), "invalid port");
+}
+
+TEST_F(NetUtilTest, TestParseAddressesWithScheme) {
+  vector<HostPort> hostports;
+  const uint16_t kDefaultPort = 12345;
+
+  EXPECT_OK(HostPort::ParseStringsWithScheme("", kDefaultPort, &hostports));
+  EXPECT_TRUE(hostports.empty());
+
+  EXPECT_OK(HostPort::ParseStringsWithScheme(",,,", kDefaultPort, &hostports));
+  EXPECT_TRUE(hostports.empty());
+
+  EXPECT_OK(HostPort::ParseStringsWithScheme("http://foo-bar-baz:1234";, 
kDefaultPort, &hostports));
+  EXPECT_EQ(vector<HostPort>({ HostPort("foo-bar-baz", 1234) }), hostports);
+
+  EXPECT_OK(HostPort::ParseStringsWithScheme("http://foo-bar-baz:1234/path";,
+                                             kDefaultPort, &hostports));
+  EXPECT_EQ(vector<HostPort>({ HostPort("foo-bar-baz", 1234) }), hostports);
+
+  EXPECT_OK(HostPort::ParseStringsWithScheme("http://abc:1234,xyz";, 
kDefaultPort, &hostports));
+  EXPECT_EQ(vector<HostPort>({ HostPort("abc", 1234), HostPort("xyz", 
kDefaultPort) }),
+            hostports);
+
+  // Test some invalid addresses.
+  Status s = HostPort::ParseStringsWithScheme("abc:1234/path", kDefaultPort, 
&hostports);
+  EXPECT_TRUE(s.IsInvalidArgument());
+  ASSERT_STR_CONTAINS(s.ToString(), "invalid port");
+
+  s = HostPort::ParseStringsWithScheme("://scheme:12", kDefaultPort, 
&hostports);
+  EXPECT_TRUE(s.IsInvalidArgument());
+  ASSERT_STR_CONTAINS(s.ToString(), "invalid scheme format");
+
+  s = HostPort::ParseStringsWithScheme("http:///path";, kDefaultPort, 
&hostports);
+  EXPECT_TRUE(s.IsInvalidArgument());
+  ASSERT_STR_CONTAINS(s.ToString(), "invalid address format");
+
+  s = HostPort::ParseStringsWithScheme("http://abc:1234,://scheme,xyz";,
+                                       kDefaultPort, &hostports);
+  EXPECT_TRUE(s.IsInvalidArgument());
+  ASSERT_STR_CONTAINS(s.ToString(), "invalid scheme format");
 }
 
 TEST_F(NetUtilTest, TestResolveAddresses) {

http://git-wip-us.apache.org/repos/asf/kudu/blob/32a4fe16/src/kudu/util/net/net_util.cc
----------------------------------------------------------------------
diff --git a/src/kudu/util/net/net_util.cc b/src/kudu/util/net/net_util.cc
index 520882f..482747e 100644
--- a/src/kudu/util/net/net_util.cc
+++ b/src/kudu/util/net/net_util.cc
@@ -138,7 +138,7 @@ Status HostPort::ParseString(const string& str, uint16_t 
default_port) {
     port = default_port;
   } else if (!SimpleAtoi(p.second, &port) ||
              port > 65535) {
-    return Status::InvalidArgument("Invalid port", str);
+    return Status::InvalidArgument("invalid port", str);
   }
 
   host_.swap(p.first);
@@ -146,6 +146,31 @@ Status HostPort::ParseString(const string& str, uint16_t 
default_port) {
   return Status::OK();
 }
 
+Status HostPort::ParseStringWithScheme(const string& str, uint16_t 
default_port) {
+  string str_copy(str);
+  const string kSchemeSeparator = "://";
+  const string kPathSeparator = "/";
+
+  auto scheme_idx = str_copy.find(kSchemeSeparator);
+
+  if (scheme_idx == 0) {
+    return Status::InvalidArgument("invalid scheme format", str_copy);
+  }
+
+  if (scheme_idx != string::npos) {
+    str_copy.erase(0, scheme_idx + kSchemeSeparator.size());
+    auto path_idx = str_copy.find(kPathSeparator);
+    if (path_idx == 0) {
+      return Status::InvalidArgument("invalid address format", str_copy);
+    }
+    if (path_idx != string::npos) {
+      str_copy.erase(path_idx, str_copy.size());
+    }
+  }
+
+  return ParseString(str_copy, default_port);
+}
+
 Status HostPort::ResolveAddresses(vector<Sockaddr>* addresses) const {
   TRACE_EVENT1("net", "HostPort::ResolveAddresses",
                "host", host_);
@@ -179,11 +204,29 @@ Status HostPort::ResolveAddresses(vector<Sockaddr>* 
addresses) const {
 Status HostPort::ParseStrings(const string& comma_sep_addrs,
                               uint16_t default_port,
                               vector<HostPort>* res) {
+  res->clear();
+
   vector<string> addr_strings = strings::Split(comma_sep_addrs, ",", 
strings::SkipEmpty());
+  res->reserve(addr_strings.size());
   for (const string& addr_string : addr_strings) {
     HostPort host_port;
     RETURN_NOT_OK(host_port.ParseString(addr_string, default_port));
-    res->push_back(host_port);
+    res->emplace_back(host_port);
+  }
+  return Status::OK();
+}
+
+Status HostPort::ParseStringsWithScheme(const string& comma_sep_addrs,
+                                        uint16_t default_port,
+                                        vector<HostPort>* res) {
+  res->clear();
+
+  vector<string> addr_strings = strings::Split(comma_sep_addrs, ",", 
strings::SkipEmpty());
+  res->reserve(addr_strings.size());
+  for (const string& addr_string : addr_strings) {
+    HostPort host_port;
+    RETURN_NOT_OK(host_port.ParseStringWithScheme(addr_string, default_port));
+    res->emplace_back(host_port);
   }
   return Status::OK();
 }

http://git-wip-us.apache.org/repos/asf/kudu/blob/32a4fe16/src/kudu/util/net/net_util.h
----------------------------------------------------------------------
diff --git a/src/kudu/util/net/net_util.h b/src/kudu/util/net/net_util.h
index c471ae8..329c9f6 100644
--- a/src/kudu/util/net/net_util.h
+++ b/src/kudu/util/net/net_util.h
@@ -39,10 +39,20 @@ class HostPort {
     return !host_.empty();
   }
 
-  // Parse a "host:port" pair into this object.
+  // Parse a <host>:<port> pair into this object.
   // If there is no port specified in the string, then 'default_port' is used.
+  //
+  // Note that <host> cannot be in IPv6 address notation.
   Status ParseString(const std::string& str, uint16_t default_port);
 
+  // Similar to above but allow the address to have scheme and path, e.g.
+  //   <host>
+  //   <host>:<port>
+  //   <fs>://<host>:<port>/<path>
+  //
+  // Note that both scheme and path are ignored.
+  Status ParseStringWithScheme(const std::string& str, uint16_t default_port);
+
   // Resolve any addresses corresponding to this host:port pair.
   // Note that a host may resolve to more than one IP address.
   //
@@ -67,6 +77,11 @@ class HostPort {
   static Status ParseStrings(
       const std::string& comma_sep_addrs, uint16_t default_port, 
std::vector<HostPort>* res);
 
+  // Similar to above but allow the addresses to have scheme and path,
+  // which are ignored.
+  static Status ParseStringsWithScheme(
+      const std::string& comma_sep_addrs, uint16_t default_port, 
std::vector<HostPort>* res);
+
   // Takes a vector of HostPort objects and returns a comma separated
   // string containing of "host:port" pairs. This method is the
   // "inverse" of ParseStrings().

Reply via email to