Repository: kudu Updated Branches: refs/heads/master ebe4d78bf -> 43d2749dd
Rolling-upgrades compat for changing TSRegistrationPB This should allow for adding fields to TSRegistrationPB. Only the host/port is checked. Change-Id: I794517d200b1c9ad74b3897b17aa808d68d7924b Reviewed-on: http://gerrit.cloudera.org:8080/4062 Tested-by: Kudu Jenkins Reviewed-by: Adar Dembo <[email protected]> Project: http://git-wip-us.apache.org/repos/asf/kudu/repo Commit: http://git-wip-us.apache.org/repos/asf/kudu/commit/43d2749d Tree: http://git-wip-us.apache.org/repos/asf/kudu/tree/43d2749d Diff: http://git-wip-us.apache.org/repos/asf/kudu/diff/43d2749d Branch: refs/heads/master Commit: 43d2749ddb096d5534507d71314a558cbf420537 Parents: ebe4d78 Author: Mike Percy <[email protected]> Authored: Fri Aug 19 03:06:09 2016 -0600 Committer: Mike Percy <[email protected]> Committed: Thu Aug 25 23:02:50 2016 +0000 ---------------------------------------------------------------------- src/kudu/master/master-test.cc | 15 +++++++++++++++ src/kudu/master/ts_descriptor.cc | 26 +++++++++++++++++++++++++- src/kudu/util/net/net_util.cc | 12 ++++++++++++ src/kudu/util/net/net_util.h | 18 ++++++++++++++++++ 4 files changed, 70 insertions(+), 1 deletion(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/kudu/blob/43d2749d/src/kudu/master/master-test.cc ---------------------------------------------------------------------- diff --git a/src/kudu/master/master-test.cc b/src/kudu/master/master-test.cc index ccd75b1..e47ec07 100644 --- a/src/kudu/master/master-test.cc +++ b/src/kudu/master/master-test.cc @@ -25,6 +25,7 @@ #include "kudu/common/partial_row.h" #include "kudu/common/row_operations.h" +#include "kudu/generated/version_defines.h" #include "kudu/gutil/strings/join.h" #include "kudu/master/master.h" #include "kudu/master/master.proxy.h" @@ -277,6 +278,20 @@ TEST_F(MasterTest, TestRegisterAndHeartbeat) { ASSERT_EQ(1, resp.servers(0).instance_id().instance_seqno()); } + // Ensure that trying to re-register with a different version is OK. + { + TSHeartbeatRequestPB req; + TSHeartbeatResponsePB resp; + RpcController rpc; + req.mutable_common()->CopyFrom(common); + req.mutable_registration()->CopyFrom(fake_reg); + // This string should never match the actual VersionInfo string, although + // the numeric portion will match. + req.mutable_registration()->set_software_version(Substitute("kudu $0 (rev SOME_NON_GIT_HASH)", + KUDU_VERSION_STRING)); + ASSERT_OK(proxy_->TSHeartbeat(req, &resp, &rpc)); + } + // Ensure that trying to re-register with a different port fails. { TSHeartbeatRequestPB req; http://git-wip-us.apache.org/repos/asf/kudu/blob/43d2749d/src/kudu/master/ts_descriptor.cc ---------------------------------------------------------------------- diff --git a/src/kudu/master/ts_descriptor.cc b/src/kudu/master/ts_descriptor.cc index 35c8629..1f3ef11 100644 --- a/src/kudu/master/ts_descriptor.cc +++ b/src/kudu/master/ts_descriptor.cc @@ -19,6 +19,7 @@ #include <math.h> #include <mutex> +#include <unordered_set> #include <vector> #include "kudu/common/wire_protocol.h" @@ -55,6 +56,27 @@ TSDescriptor::TSDescriptor(std::string perm_id) TSDescriptor::~TSDescriptor() { } +// Compares two repeated HostPortPB fields. Returns true if equal, false otherwise. +static bool HostPortPBsEqual(const google::protobuf::RepeatedPtrField<HostPortPB>& pb1, + const google::protobuf::RepeatedPtrField<HostPortPB>& pb2) { + if (pb1.size() != pb2.size()) { + return false; + } + + // Do a set-based equality search. + std::unordered_set<HostPort, HostPortHasher, HostPortEqualityPredicate> hostports1; + std::unordered_set<HostPort, HostPortHasher, HostPortEqualityPredicate> hostports2; + for (int i = 0; i < pb1.size(); i++) { + HostPort hp1; + HostPort hp2; + if (!HostPortFromPB(pb1.Get(i), &hp1).ok()) return false; + if (!HostPortFromPB(pb2.Get(i), &hp2).ok()) return false; + hostports1.insert(hp1); + hostports2.insert(hp2); + } + return hostports1 == hostports2; +} + Status TSDescriptor::Register(const NodeInstancePB& instance, const TSRegistrationPB& registration) { std::lock_guard<simple_spinlock> l(lock_); @@ -62,7 +84,9 @@ Status TSDescriptor::Register(const NodeInstancePB& instance, // TODO(KUDU-418): we don't currently support changing IPs or hosts since the // host/port is stored persistently in each tablet's metadata. - if (registration_ && registration_->ShortDebugString() != registration.ShortDebugString()) { + if (registration_ && + (!HostPortPBsEqual(registration_->rpc_addresses(), registration.rpc_addresses()) || + !HostPortPBsEqual(registration_->http_addresses(), registration.http_addresses()))) { string msg = strings::Substitute( "Tablet server $0 is attempting to re-register with a different host/port. " "This is not currently supported. Old: {$1} New: {$2}", http://git-wip-us.apache.org/repos/asf/kudu/blob/43d2749d/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 6b1d4f6..0564398 100644 --- a/src/kudu/util/net/net_util.cc +++ b/src/kudu/util/net/net_util.cc @@ -21,6 +21,7 @@ #include <netdb.h> #include <algorithm> +#include <boost/functional/hash.hpp> #include <gflags/gflags.h> #include <unordered_set> #include <utility> @@ -78,6 +79,17 @@ HostPort::HostPort(const Sockaddr& addr) port_(addr.port()) { } +bool operator==(const HostPort& hp1, const HostPort& hp2) { + return hp1.port() == hp2.port() && hp1.host() == hp2.host(); +} + +size_t HostPort::HashCode() const { + size_t seed = 0; + boost::hash_combine(seed, host_); + boost::hash_combine(seed, port_); + return seed; +} + Status HostPort::ParseString(const string& str, uint16_t default_port) { std::pair<string, string> p = strings::Split(str, strings::delimiter::Limit(":", 1)); http://git-wip-us.apache.org/repos/asf/kudu/blob/43d2749d/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 d0bb92e..3086f4a 100644 --- a/src/kudu/util/net/net_util.h +++ b/src/kudu/util/net/net_util.h @@ -52,6 +52,8 @@ class HostPort { uint16_t port() const { return port_; } void set_port(uint16_t port) { port_ = port; } + size_t HashCode() const; + // Parse a comma separated list of "host:port" pairs into a vector // HostPort objects. If no port is specified for an entry in the // comma separated list, 'default_port' is used for that entry's @@ -69,6 +71,22 @@ class HostPort { uint16_t port_; }; +bool operator==(const HostPort& hp1, const HostPort& hp2); + +// Hasher of HostPort objects for UnorderedAssociativeContainers. +struct HostPortHasher { + size_t operator()(const HostPort& hp) const { + return hp.HashCode(); + } +}; + +// Equality BinaryPredicate of HostPort objects for UnorderedAssociativeContainers. +struct HostPortEqualityPredicate { + bool operator()(const HostPort& hp1, const HostPort& hp2) const { + return hp1 == hp2; + } +}; + // Parse and resolve the given comma-separated list of addresses. // // The resulting addresses will be resolved, made unique, and added to
