diff --git a/build/teamcity-local-roachtest.sh b/build/teamcity-local-roachtest.sh index 11b10b958e35..4cbf88256517 100755 --- a/build/teamcity-local-roachtest.sh +++ b/build/teamcity-local-roachtest.sh @@ -22,10 +22,8 @@ run build/builder.sh make bin/workload bin/roachtest tc_end_block "Compile workload/roachtest" tc_start_block "Run local roachtests" -# TODO(dan): Run kv/splits as a proof of concept of running roachtest on every -# PR. After we're sure this is stable, curate a suite of the tests that work -# locally. -run build/builder.sh ./bin/roachtest run kv/splits \ +# TODO(peter,dan): curate a suite of the tests that works locally. +run build/builder.sh ./bin/roachtest run '(cli|kv/splits)' \ --local \ --cockroach "cockroach" \ --workload "bin/workload" \ diff --git a/c-deps/libroach/protos/roachpb/metadata.pb.cc b/c-deps/libroach/protos/roachpb/metadata.pb.cc index 712684f6abd4..59933aa77d7e 100644 --- a/c-deps/libroach/protos/roachpb/metadata.pb.cc +++ b/c-deps/libroach/protos/roachpb/metadata.pb.cc @@ -2394,6 +2394,8 @@ const int NodeDescriptor::kAddressFieldNumber; const int NodeDescriptor::kAttrsFieldNumber; const int NodeDescriptor::kLocalityFieldNumber; const int NodeDescriptor::kServerVersionFieldNumber; +const int NodeDescriptor::kBuildTagFieldNumber; +const int NodeDescriptor::kStartedAtFieldNumber; #endif // !defined(_MSC_VER) || _MSC_VER >= 1900 NodeDescriptor::NodeDescriptor() @@ -2408,6 +2410,10 @@ NodeDescriptor::NodeDescriptor(const NodeDescriptor& from) _internal_metadata_(NULL), _has_bits_(from._has_bits_) { _internal_metadata_.MergeFrom(from._internal_metadata_); + build_tag_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + if (from.has_build_tag()) { + build_tag_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.build_tag_); + } if (from.has_address()) { address_ = new ::cockroach::util::UnresolvedAddr(*from.address_); } else { @@ -2428,11 +2434,14 @@ NodeDescriptor::NodeDescriptor(const NodeDescriptor& from) } else { serverversion_ = NULL; } - node_id_ = from.node_id_; + ::memcpy(&started_at_, &from.started_at_, + static_cast(reinterpret_cast(&node_id_) - + reinterpret_cast(&started_at_)) + sizeof(node_id_)); // @@protoc_insertion_point(copy_constructor:cockroach.roachpb.NodeDescriptor) } void NodeDescriptor::SharedCtor() { + build_tag_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); ::memset(&address_, 0, static_cast( reinterpret_cast(&node_id_) - reinterpret_cast(&address_)) + sizeof(node_id_)); @@ -2444,6 +2453,7 @@ NodeDescriptor::~NodeDescriptor() { } void NodeDescriptor::SharedDtor() { + build_tag_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); if (this != internal_default_instance()) delete address_; if (this != internal_default_instance()) delete attrs_; if (this != internal_default_instance()) delete locality_; @@ -2466,25 +2476,32 @@ void NodeDescriptor::Clear() { (void) cached_has_bits; cached_has_bits = _has_bits_[0]; - if (cached_has_bits & 15u) { + if (cached_has_bits & 31u) { if (cached_has_bits & 0x00000001u) { + build_tag_.ClearNonDefaultToEmptyNoArena(); + } + if (cached_has_bits & 0x00000002u) { GOOGLE_DCHECK(address_ != NULL); address_->Clear(); } - if (cached_has_bits & 0x00000002u) { + if (cached_has_bits & 0x00000004u) { GOOGLE_DCHECK(attrs_ != NULL); attrs_->Clear(); } - if (cached_has_bits & 0x00000004u) { + if (cached_has_bits & 0x00000008u) { GOOGLE_DCHECK(locality_ != NULL); locality_->Clear(); } - if (cached_has_bits & 0x00000008u) { + if (cached_has_bits & 0x00000010u) { GOOGLE_DCHECK(serverversion_ != NULL); serverversion_->Clear(); } } - node_id_ = 0; + if (cached_has_bits & 96u) { + ::memset(&started_at_, 0, static_cast( + reinterpret_cast(&node_id_) - + reinterpret_cast(&started_at_)) + sizeof(node_id_)); + } _has_bits_.Clear(); _internal_metadata_.Clear(); } @@ -2562,6 +2579,30 @@ bool NodeDescriptor::MergePartialFromCodedStream( break; } + case 6: { + if (static_cast< ::google::protobuf::uint8>(tag) == + static_cast< ::google::protobuf::uint8>(50u /* 50 & 0xFF */)) { + DO_(::google::protobuf::internal::WireFormatLite::ReadString( + input, this->mutable_build_tag())); + } else { + goto handle_unusual; + } + break; + } + + case 7: { + if (static_cast< ::google::protobuf::uint8>(tag) == + static_cast< ::google::protobuf::uint8>(56u /* 56 & 0xFF */)) { + set_has_started_at(); + DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< + ::google::protobuf::int64, ::google::protobuf::internal::WireFormatLite::TYPE_INT64>( + input, &started_at_))); + } else { + goto handle_unusual; + } + break; + } + default: { handle_unusual: if (tag == 0) { @@ -2589,30 +2630,39 @@ void NodeDescriptor::SerializeWithCachedSizes( (void) cached_has_bits; cached_has_bits = _has_bits_[0]; - if (cached_has_bits & 0x00000010u) { + if (cached_has_bits & 0x00000040u) { ::google::protobuf::internal::WireFormatLite::WriteInt32(1, this->node_id(), output); } - if (cached_has_bits & 0x00000001u) { + if (cached_has_bits & 0x00000002u) { ::google::protobuf::internal::WireFormatLite::WriteMessage( 2, this->_internal_address(), output); } - if (cached_has_bits & 0x00000002u) { + if (cached_has_bits & 0x00000004u) { ::google::protobuf::internal::WireFormatLite::WriteMessage( 3, this->_internal_attrs(), output); } - if (cached_has_bits & 0x00000004u) { + if (cached_has_bits & 0x00000008u) { ::google::protobuf::internal::WireFormatLite::WriteMessage( 4, this->_internal_locality(), output); } - if (cached_has_bits & 0x00000008u) { + if (cached_has_bits & 0x00000010u) { ::google::protobuf::internal::WireFormatLite::WriteMessage( 5, this->_internal_serverversion(), output); } + if (cached_has_bits & 0x00000001u) { + ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased( + 6, this->build_tag(), output); + } + + if (cached_has_bits & 0x00000020u) { + ::google::protobuf::internal::WireFormatLite::WriteInt64(7, this->started_at(), output); + } + output->WriteRaw(_internal_metadata_.unknown_fields().data(), static_cast(_internal_metadata_.unknown_fields().size())); // @@protoc_insertion_point(serialize_end:cockroach.roachpb.NodeDescriptor) @@ -2624,7 +2674,13 @@ size_t NodeDescriptor::ByteSizeLong() const { total_size += _internal_metadata_.unknown_fields().size(); - if (_has_bits_[0 / 32] & 31u) { + if (_has_bits_[0 / 32] & 127u) { + if (has_build_tag()) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::StringSize( + this->build_tag()); + } + if (has_address()) { total_size += 1 + ::google::protobuf::internal::WireFormatLite::MessageSize( @@ -2649,6 +2705,12 @@ size_t NodeDescriptor::ByteSizeLong() const { *serverversion_); } + if (has_started_at()) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::Int64Size( + this->started_at()); + } + if (has_node_id()) { total_size += 1 + ::google::protobuf::internal::WireFormatLite::Int32Size( @@ -2674,20 +2736,27 @@ void NodeDescriptor::MergeFrom(const NodeDescriptor& from) { (void) cached_has_bits; cached_has_bits = from._has_bits_[0]; - if (cached_has_bits & 31u) { + if (cached_has_bits & 127u) { if (cached_has_bits & 0x00000001u) { - mutable_address()->::cockroach::util::UnresolvedAddr::MergeFrom(from.address()); + set_has_build_tag(); + build_tag_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.build_tag_); } if (cached_has_bits & 0x00000002u) { - mutable_attrs()->::cockroach::roachpb::Attributes::MergeFrom(from.attrs()); + mutable_address()->::cockroach::util::UnresolvedAddr::MergeFrom(from.address()); } if (cached_has_bits & 0x00000004u) { - mutable_locality()->::cockroach::roachpb::Locality::MergeFrom(from.locality()); + mutable_attrs()->::cockroach::roachpb::Attributes::MergeFrom(from.attrs()); } if (cached_has_bits & 0x00000008u) { - mutable_serverversion()->::cockroach::roachpb::Version::MergeFrom(from.serverversion()); + mutable_locality()->::cockroach::roachpb::Locality::MergeFrom(from.locality()); } if (cached_has_bits & 0x00000010u) { + mutable_serverversion()->::cockroach::roachpb::Version::MergeFrom(from.serverversion()); + } + if (cached_has_bits & 0x00000020u) { + started_at_ = from.started_at_; + } + if (cached_has_bits & 0x00000040u) { node_id_ = from.node_id_; } _has_bits_[0] |= cached_has_bits; @@ -2711,10 +2780,13 @@ void NodeDescriptor::Swap(NodeDescriptor* other) { } void NodeDescriptor::InternalSwap(NodeDescriptor* other) { using std::swap; + build_tag_.Swap(&other->build_tag_, &::google::protobuf::internal::GetEmptyStringAlreadyInited(), + GetArenaNoVirtual()); swap(address_, other->address_); swap(attrs_, other->attrs_); swap(locality_, other->locality_); swap(serverversion_, other->serverversion_); + swap(started_at_, other->started_at_); swap(node_id_, other->node_id_); swap(_has_bits_[0], other->_has_bits_[0]); _internal_metadata_.Swap(&other->_internal_metadata_); diff --git a/c-deps/libroach/protos/roachpb/metadata.pb.h b/c-deps/libroach/protos/roachpb/metadata.pb.h index fc3bfe82010d..c15912fb635d 100644 --- a/c-deps/libroach/protos/roachpb/metadata.pb.h +++ b/c-deps/libroach/protos/roachpb/metadata.pb.h @@ -1233,6 +1233,20 @@ class NodeDescriptor : public ::google::protobuf::MessageLite /* @@protoc_insert // accessors ------------------------------------------------------- + bool has_build_tag() const; + void clear_build_tag(); + static const int kBuildTagFieldNumber = 6; + const ::std::string& build_tag() const; + void set_build_tag(const ::std::string& value); + #if LANG_CXX11 + void set_build_tag(::std::string&& value); + #endif + void set_build_tag(const char* value); + void set_build_tag(const char* value, size_t size); + ::std::string* mutable_build_tag(); + ::std::string* release_build_tag(); + void set_allocated_build_tag(::std::string* build_tag); + bool has_address() const; void clear_address(); static const int kAddressFieldNumber = 2; @@ -1277,6 +1291,12 @@ class NodeDescriptor : public ::google::protobuf::MessageLite /* @@protoc_insert ::cockroach::roachpb::Version* mutable_serverversion(); void set_allocated_serverversion(::cockroach::roachpb::Version* serverversion); + bool has_started_at() const; + void clear_started_at(); + static const int kStartedAtFieldNumber = 7; + ::google::protobuf::int64 started_at() const; + void set_started_at(::google::protobuf::int64 value); + bool has_node_id() const; void clear_node_id(); static const int kNodeIdFieldNumber = 1; @@ -1295,14 +1315,20 @@ class NodeDescriptor : public ::google::protobuf::MessageLite /* @@protoc_insert void clear_has_locality(); void set_has_serverversion(); void clear_has_serverversion(); + void set_has_build_tag(); + void clear_has_build_tag(); + void set_has_started_at(); + void clear_has_started_at(); ::google::protobuf::internal::InternalMetadataWithArenaLite _internal_metadata_; ::google::protobuf::internal::HasBits<1> _has_bits_; mutable ::google::protobuf::internal::CachedSize _cached_size_; + ::google::protobuf::internal::ArenaStringPtr build_tag_; ::cockroach::util::UnresolvedAddr* address_; ::cockroach::roachpb::Attributes* attrs_; ::cockroach::roachpb::Locality* locality_; ::cockroach::roachpb::Version* serverversion_; + ::google::protobuf::int64 started_at_; ::google::protobuf::int32 node_id_; friend struct ::protobuf_roachpb_2fmetadata_2eproto::TableStruct; }; @@ -2938,13 +2964,13 @@ inline void StoreCapacity::set_allocated_writes_per_replica(::cockroach::roachpb // NodeDescriptor inline bool NodeDescriptor::has_node_id() const { - return (_has_bits_[0] & 0x00000010u) != 0; + return (_has_bits_[0] & 0x00000040u) != 0; } inline void NodeDescriptor::set_has_node_id() { - _has_bits_[0] |= 0x00000010u; + _has_bits_[0] |= 0x00000040u; } inline void NodeDescriptor::clear_has_node_id() { - _has_bits_[0] &= ~0x00000010u; + _has_bits_[0] &= ~0x00000040u; } inline void NodeDescriptor::clear_node_id() { node_id_ = 0; @@ -2961,13 +2987,13 @@ inline void NodeDescriptor::set_node_id(::google::protobuf::int32 value) { } inline bool NodeDescriptor::has_address() const { - return (_has_bits_[0] & 0x00000001u) != 0; + return (_has_bits_[0] & 0x00000002u) != 0; } inline void NodeDescriptor::set_has_address() { - _has_bits_[0] |= 0x00000001u; + _has_bits_[0] |= 0x00000002u; } inline void NodeDescriptor::clear_has_address() { - _has_bits_[0] &= ~0x00000001u; + _has_bits_[0] &= ~0x00000002u; } inline const ::cockroach::util::UnresolvedAddr& NodeDescriptor::_internal_address() const { return *address_; @@ -3014,13 +3040,13 @@ inline void NodeDescriptor::set_allocated_address(::cockroach::util::UnresolvedA } inline bool NodeDescriptor::has_attrs() const { - return (_has_bits_[0] & 0x00000002u) != 0; + return (_has_bits_[0] & 0x00000004u) != 0; } inline void NodeDescriptor::set_has_attrs() { - _has_bits_[0] |= 0x00000002u; + _has_bits_[0] |= 0x00000004u; } inline void NodeDescriptor::clear_has_attrs() { - _has_bits_[0] &= ~0x00000002u; + _has_bits_[0] &= ~0x00000004u; } inline void NodeDescriptor::clear_attrs() { if (attrs_ != NULL) attrs_->Clear(); @@ -3071,13 +3097,13 @@ inline void NodeDescriptor::set_allocated_attrs(::cockroach::roachpb::Attributes } inline bool NodeDescriptor::has_locality() const { - return (_has_bits_[0] & 0x00000004u) != 0; + return (_has_bits_[0] & 0x00000008u) != 0; } inline void NodeDescriptor::set_has_locality() { - _has_bits_[0] |= 0x00000004u; + _has_bits_[0] |= 0x00000008u; } inline void NodeDescriptor::clear_has_locality() { - _has_bits_[0] &= ~0x00000004u; + _has_bits_[0] &= ~0x00000008u; } inline void NodeDescriptor::clear_locality() { if (locality_ != NULL) locality_->Clear(); @@ -3128,13 +3154,13 @@ inline void NodeDescriptor::set_allocated_locality(::cockroach::roachpb::Localit } inline bool NodeDescriptor::has_serverversion() const { - return (_has_bits_[0] & 0x00000008u) != 0; + return (_has_bits_[0] & 0x00000010u) != 0; } inline void NodeDescriptor::set_has_serverversion() { - _has_bits_[0] |= 0x00000008u; + _has_bits_[0] |= 0x00000010u; } inline void NodeDescriptor::clear_has_serverversion() { - _has_bits_[0] &= ~0x00000008u; + _has_bits_[0] &= ~0x00000010u; } inline void NodeDescriptor::clear_serverversion() { if (serverversion_ != NULL) serverversion_->Clear(); @@ -3184,6 +3210,94 @@ inline void NodeDescriptor::set_allocated_serverversion(::cockroach::roachpb::Ve // @@protoc_insertion_point(field_set_allocated:cockroach.roachpb.NodeDescriptor.ServerVersion) } +inline bool NodeDescriptor::has_build_tag() const { + return (_has_bits_[0] & 0x00000001u) != 0; +} +inline void NodeDescriptor::set_has_build_tag() { + _has_bits_[0] |= 0x00000001u; +} +inline void NodeDescriptor::clear_has_build_tag() { + _has_bits_[0] &= ~0x00000001u; +} +inline void NodeDescriptor::clear_build_tag() { + build_tag_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + clear_has_build_tag(); +} +inline const ::std::string& NodeDescriptor::build_tag() const { + // @@protoc_insertion_point(field_get:cockroach.roachpb.NodeDescriptor.build_tag) + return build_tag_.GetNoArena(); +} +inline void NodeDescriptor::set_build_tag(const ::std::string& value) { + set_has_build_tag(); + build_tag_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value); + // @@protoc_insertion_point(field_set:cockroach.roachpb.NodeDescriptor.build_tag) +} +#if LANG_CXX11 +inline void NodeDescriptor::set_build_tag(::std::string&& value) { + set_has_build_tag(); + build_tag_.SetNoArena( + &::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::move(value)); + // @@protoc_insertion_point(field_set_rvalue:cockroach.roachpb.NodeDescriptor.build_tag) +} +#endif +inline void NodeDescriptor::set_build_tag(const char* value) { + GOOGLE_DCHECK(value != NULL); + set_has_build_tag(); + build_tag_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value)); + // @@protoc_insertion_point(field_set_char:cockroach.roachpb.NodeDescriptor.build_tag) +} +inline void NodeDescriptor::set_build_tag(const char* value, size_t size) { + set_has_build_tag(); + build_tag_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), + ::std::string(reinterpret_cast(value), size)); + // @@protoc_insertion_point(field_set_pointer:cockroach.roachpb.NodeDescriptor.build_tag) +} +inline ::std::string* NodeDescriptor::mutable_build_tag() { + set_has_build_tag(); + // @@protoc_insertion_point(field_mutable:cockroach.roachpb.NodeDescriptor.build_tag) + return build_tag_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} +inline ::std::string* NodeDescriptor::release_build_tag() { + // @@protoc_insertion_point(field_release:cockroach.roachpb.NodeDescriptor.build_tag) + if (!has_build_tag()) { + return NULL; + } + clear_has_build_tag(); + return build_tag_.ReleaseNonDefaultNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} +inline void NodeDescriptor::set_allocated_build_tag(::std::string* build_tag) { + if (build_tag != NULL) { + set_has_build_tag(); + } else { + clear_has_build_tag(); + } + build_tag_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), build_tag); + // @@protoc_insertion_point(field_set_allocated:cockroach.roachpb.NodeDescriptor.build_tag) +} + +inline bool NodeDescriptor::has_started_at() const { + return (_has_bits_[0] & 0x00000020u) != 0; +} +inline void NodeDescriptor::set_has_started_at() { + _has_bits_[0] |= 0x00000020u; +} +inline void NodeDescriptor::clear_has_started_at() { + _has_bits_[0] &= ~0x00000020u; +} +inline void NodeDescriptor::clear_started_at() { + started_at_ = GOOGLE_LONGLONG(0); + clear_has_started_at(); +} +inline ::google::protobuf::int64 NodeDescriptor::started_at() const { + // @@protoc_insertion_point(field_get:cockroach.roachpb.NodeDescriptor.started_at) + return started_at_; +} +inline void NodeDescriptor::set_started_at(::google::protobuf::int64 value) { + set_has_started_at(); + started_at_ = value; + // @@protoc_insertion_point(field_set:cockroach.roachpb.NodeDescriptor.started_at) +} + // ------------------------------------------------------------------- // StoreDescriptor diff --git a/pkg/cli/cli_test.go b/pkg/cli/cli_test.go index c88b5dcb6f7f..11619caed971 100644 --- a/pkg/cli/cli_test.go +++ b/pkg/cli/cli_test.go @@ -1861,14 +1861,15 @@ func TestCLITimeout(t *testing.T) { // Wrap the meat of the test in a retry loop. Setting a timeout like this is // racy as the operation may have succeeded by the time the scheduler gives - // the timeout a chance to have an effect. + // the timeout a chance to have an effect. We specify --all to include some + // slower to access virtual tables in the query. testutils.SucceedsSoon(t, func() error { - out, err := c.RunWithCapture("node status 1 --timeout 1ns") + out, err := c.RunWithCapture("node status 1 --all --timeout 1ns") if err != nil { t.Fatal(err) } - const exp = `node status 1 --timeout 1ns + const exp = `node status 1 --all --timeout 1ns pq: query execution canceled due to statement timeout ` if out != exp { diff --git a/pkg/cli/node.go b/pkg/cli/node.go index 28ae9d9021d2..4d98ec22db79 100644 --- a/pkg/cli/node.go +++ b/pkg/cli/node.go @@ -111,8 +111,8 @@ var statusNodeCmd = &cobra.Command{ Use: "status []", Short: "shows the status of a node or all nodes", Long: ` - If a node ID is specified, this will show the status for the corresponding node. If no node ID - is specified, this will display the status for all nodes in the cluster. +If a node ID is specified, this will show the status for the corresponding node. If no node ID +is specified, this will display the status for all nodes in the cluster. `, Args: cobra.MaximumNArgs(1), RunE: MaybeDecorateGRPCError(runStatusNode), @@ -150,8 +150,13 @@ func runStatusNodeInner(showDecommissioned bool, args []string) ([]string, [][]s } baseQuery := joinUsingID( - []string{ - "SELECT node_id AS id, address, tag AS build, started_at, updated_at from crdb_internal.kv_node_status", + []string{` +SELECT node_id AS id, + address, + build_tag AS build, + started_at, + updated_at +FROM crdb_internal.gossip_liveness JOIN crdb_internal.gossip_nodes USING (node_id)`, maybeAddActiveNodesFilter( `SELECT node_id AS id, CASE WHEN split_part(expiration,',',1)::decimal > now()::decimal @@ -183,14 +188,12 @@ SELECT node_id AS id, FROM crdb_internal.kv_store_status GROUP BY node_id` - decommissionQuery := joinUsingID( - []string{ - `SELECT node_id AS id, sum((metrics->>'replicas')::DECIMAL)::INT AS gossiped_replicas - FROM crdb_internal.kv_store_status GROUP BY node_id`, - `SELECT node_id AS id, decommissioning AS is_decommissioning, draining AS is_draining - FROM crdb_internal.gossip_liveness`, - }, - ) + decommissionQuery := ` +SELECT node_id AS id, + decommissioning AS is_decommissioning, + draining AS is_draining, + ranges AS gossiped_replicas +FROM crdb_internal.gossip_liveness JOIN crdb_internal.gossip_nodes USING (node_id)` conn, err := getPasswordAndMakeSQLClient("cockroach node status") if err != nil { diff --git a/pkg/cmd/roachtest/cli.go b/pkg/cmd/roachtest/cli.go new file mode 100644 index 000000000000..d20f3239905a --- /dev/null +++ b/pkg/cmd/roachtest/cli.go @@ -0,0 +1,103 @@ +// Copyright 2018 The Cockroach Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +// implied. See the License for the specific language governing +// permissions and limitations under the License. See the AUTHORS file +// for names of contributors. + +package main + +import ( + "context" + "reflect" + "strings" + "time" +) + +func runCLINodeStatus(ctx context.Context, t *test, c *cluster) { + c.Put(ctx, cockroach, "./cockroach", c.All()) + c.Start(ctx, c.All()) + + lastWords := func(s string) []string { + var result []string + for _, line := range strings.Split(s, "\n") { + words := strings.Fields(line) + if n := len(words); n > 0 { + result = append(result, words[n-1]) + } + } + return result + } + + nodeStatus := func() []string { + out, err := c.RunWithBuffer(ctx, c.l, c.Node(1), + "./cockroach node status --insecure -p {pgport:1}") + if err != nil { + t.Fatalf("%v\n%s", err, out) + } + return lastWords(string(out)) + } + + { + expected := []string{"is_live", "true", "true", "true"} + actual := nodeStatus() + if !reflect.DeepEqual(expected, actual) { + t.Fatalf("expected %s, but found %s:\n", expected, actual) + } + } + + { + // Kill nodes 2 and 3 and wait for all of the nodes to be marked as + // !is_live. Node 1 is not live because the liveness check can no longer + // write to the liveness range due to lack of quorum. This test is + // verifying that "node status" still returns info in this situation sa it + // only accesses gossip info. + c.Stop(ctx, c.Range(2, 3)) + expected := []string{"is_live", "false", "false", "false"} + var actual []string + // Node liveness takes ~9s to time out. Give the test double that time. + for i := 0; i < 20; i++ { + actual = nodeStatus() + if reflect.DeepEqual(expected, actual) { + break + } + c.l.printf("not done: %s vs %s\n", expected, actual) + time.Sleep(time.Second) + } + if !reflect.DeepEqual(expected, actual) { + t.Fatalf("expected %s, but found %s:\n", expected, actual) + } + } +} + +func registerCLI(r *registry) { + spec := testSpec{ + Name: "cli", + Stable: true, // DO NOT COPY to new tests + Nodes: nodes(3), + } + + testCases := []struct { + name string + fn func(ctx context.Context, t *test, c *cluster) + }{ + {"node-status", runCLINodeStatus}, + } + for _, tc := range testCases { + spec.SubTests = append(spec.SubTests, testSpec{ + Name: tc.name, + Stable: true, // DO NOT COPY to new tests + Run: tc.fn, + }) + } + + r.Add(spec) +} diff --git a/pkg/cmd/roachtest/registry.go b/pkg/cmd/roachtest/registry.go index 4252af419d84..5d9319b83cc2 100644 --- a/pkg/cmd/roachtest/registry.go +++ b/pkg/cmd/roachtest/registry.go @@ -18,13 +18,14 @@ package main func registerTests(r *registry) { // Helpful shell pipeline to generate the list below: // - // grep -h -E 'func register[^(]+\(.*registry\) {' *.go | grep -E -o 'register[^(]+' | grep -v '^registerTests$' | grep -v '^\w*Bench$' | sort | awk '{printf "\t%s(r)\n", $0}' + // grep -h -E 'func register[^(]+\(.*registry\) {' *.go | grep -E -o 'register[^(]+' | grep -E -v '^register(Tests|Benchmarks)$' | grep -v '^\w*Bench$' | sort -f | awk '{printf "\t%s(r)\n", $0}' registerAllocator(r) registerBackup(r) registerCancel(r) registerCDC(r) registerClearRange(r) + registerCLI(r) registerClock(r) registerCopy(r) registerDebug(r) @@ -34,14 +35,14 @@ func registerTests(r *registry) { registerElectionAfterRestart(r) registerEncryption(r) registerHotSpotSplits(r) - registerInterleaved(r) registerImportTPCC(r) registerImportTPCH(r) + registerInterleaved(r) registerJepsen(r) registerKV(r) + registerKVQuiescenceDead(r) registerKVScalability(r) registerKVSplits(r) - registerKVQuiescenceDead(r) registerLargeRange(r) registerQueue(r) registerRestore(r) diff --git a/pkg/roachpb/metadata.pb.go b/pkg/roachpb/metadata.pb.go index e0124e3a75fe..6d7997356a4b 100644 --- a/pkg/roachpb/metadata.pb.go +++ b/pkg/roachpb/metadata.pb.go @@ -161,6 +161,8 @@ type NodeDescriptor struct { Attrs Attributes `protobuf:"bytes,3,opt,name=attrs" json:"attrs"` Locality Locality `protobuf:"bytes,4,opt,name=locality" json:"locality"` ServerVersion Version `protobuf:"bytes,5,opt,name=ServerVersion" json:"ServerVersion"` + BuildTag string `protobuf:"bytes,6,opt,name=build_tag,json=buildTag" json:"build_tag"` + StartedAt int64 `protobuf:"varint,7,opt,name=started_at,json=startedAt" json:"started_at"` } func (m *NodeDescriptor) Reset() { *m = NodeDescriptor{} } @@ -674,6 +676,13 @@ func (m *NodeDescriptor) MarshalTo(dAtA []byte) (int, error) { return 0, err } i += n7 + dAtA[i] = 0x32 + i++ + i = encodeVarintMetadata(dAtA, i, uint64(len(m.BuildTag))) + i += copy(dAtA[i:], m.BuildTag) + dAtA[i] = 0x38 + i++ + i = encodeVarintMetadata(dAtA, i, uint64(m.StartedAt)) return i, nil } @@ -1090,6 +1099,9 @@ func (m *NodeDescriptor) Size() (n int) { n += 1 + l + sovMetadata(uint64(l)) l = m.ServerVersion.Size() n += 1 + l + sovMetadata(uint64(l)) + l = len(m.BuildTag) + n += 1 + l + sovMetadata(uint64(l)) + n += 1 + sovMetadata(uint64(m.StartedAt)) return n } @@ -2268,6 +2280,54 @@ func (m *NodeDescriptor) Unmarshal(dAtA []byte) error { return err } iNdEx = postIndex + case 6: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field BuildTag", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowMetadata + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthMetadata + } + postIndex := iNdEx + intStringLen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.BuildTag = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 7: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field StartedAt", wireType) + } + m.StartedAt = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowMetadata + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.StartedAt |= (int64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } default: iNdEx = preIndex skippy, err := skipMetadata(dAtA[iNdEx:]) @@ -2971,73 +3031,75 @@ var ( func init() { proto.RegisterFile("roachpb/metadata.proto", fileDescriptorMetadata) } var fileDescriptorMetadata = []byte{ - // 1086 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x56, 0xcf, 0x6f, 0x1b, 0xc5, - 0x17, 0xcf, 0xda, 0xeb, 0x78, 0xfd, 0x12, 0x7f, 0x53, 0x8f, 0xbe, 0x94, 0x95, 0x11, 0x76, 0xb2, - 0xa2, 0x52, 0xf9, 0xa1, 0x24, 0x0d, 0xb2, 0xaa, 0x04, 0x15, 0x88, 0x1b, 0x2a, 0x85, 0xd2, 0x2a, - 0xda, 0x94, 0x1e, 0xb8, 0x58, 0x93, 0x9d, 0xc1, 0x5d, 0xb2, 0xd9, 0x35, 0xb3, 0xe3, 0x34, 0xbe, - 0x23, 0x71, 0x40, 0x48, 0x1c, 0x39, 0xe6, 0xd2, 0xff, 0x81, 0x7f, 0x00, 0x29, 0xe2, 0xc4, 0x81, - 0x03, 0xa7, 0x08, 0xc2, 0x85, 0x33, 0xc7, 0x9c, 0xd0, 0xbc, 0x9d, 0x59, 0xaf, 0x5d, 0x57, 0x22, - 0x45, 0xe2, 0xb6, 0xf9, 0xbc, 0xcf, 0xe7, 0xf9, 0xcd, 0xe7, 0xcd, 0xbc, 0x17, 0xb8, 0x2e, 0x12, - 0x1a, 0x3c, 0x19, 0x1c, 0xac, 0x1d, 0x71, 0x49, 0x19, 0x95, 0x74, 0x75, 0x20, 0x12, 0x99, 0x90, - 0x46, 0x90, 0x04, 0x87, 0x18, 0x5b, 0xd5, 0x8c, 0x66, 0x73, 0x28, 0xc3, 0x68, 0x6d, 0x18, 0x0b, - 0x9e, 0x26, 0xd1, 0x31, 0x67, 0x3d, 0xca, 0x98, 0xc8, 0xe8, 0xcd, 0xff, 0xf7, 0x93, 0x7e, 0x82, - 0x9f, 0x6b, 0xea, 0x2b, 0x43, 0xbd, 0x0f, 0x00, 0xb6, 0xa5, 0x14, 0xe1, 0xc1, 0x50, 0xf2, 0x94, - 0xbc, 0x0d, 0x15, 0x2a, 0xa5, 0x48, 0x5d, 0x6b, 0xb9, 0x7c, 0xb3, 0xd6, 0x7d, 0xe5, 0xaf, 0xf3, - 0x76, 0x63, 0x44, 0x8f, 0xa2, 0x2d, 0x0f, 0xe1, 0x77, 0x3e, 0x8f, 0x92, 0xa7, 0x9e, 0x9f, 0x71, - 0xb6, 0xec, 0xef, 0x4f, 0xdb, 0x73, 0xde, 0xd7, 0x16, 0x34, 0x7c, 0x3e, 0x88, 0xc2, 0x80, 0xca, - 0x30, 0x89, 0x1f, 0x51, 0xd1, 0xe7, 0x92, 0xdc, 0x82, 0x6a, 0x9c, 0x30, 0xde, 0x0b, 0x99, 0x6b, - 0x2d, 0x5b, 0x37, 0x2b, 0x5d, 0xf7, 0xec, 0xbc, 0x3d, 0x77, 0x71, 0xde, 0x9e, 0x7f, 0x98, 0x30, - 0xbe, 0xbb, 0x73, 0x99, 0x7f, 0xf9, 0xf3, 0x8a, 0xb8, 0xcb, 0x48, 0x07, 0x9c, 0x54, 0x26, 0x02, - 0x35, 0x25, 0xd4, 0x34, 0xb5, 0xa6, 0xba, 0xaf, 0x70, 0x14, 0x99, 0x4f, 0xbf, 0x8a, 0xdc, 0x5d, - 0xb6, 0xe5, 0xa8, 0x2a, 0xfe, 0x3c, 0x6d, 0x5b, 0xde, 0x4f, 0xe3, 0x4a, 0x76, 0x78, 0x1a, 0x88, - 0x70, 0x20, 0x13, 0xf1, 0xdf, 0x55, 0x42, 0xee, 0x00, 0x88, 0xec, 0xe7, 0x95, 0xb0, 0x8c, 0xc2, - 0x96, 0x16, 0xd6, 0x74, 0x61, 0x28, 0x1d, 0xff, 0xe1, 0xd7, 0xb4, 0x62, 0x97, 0x6d, 0x2d, 0xaa, - 0x83, 0xfc, 0x70, 0xda, 0xb6, 0xf0, 0x30, 0xdf, 0x58, 0xb0, 0x68, 0x68, 0x8c, 0xc7, 0x52, 0x15, - 0x25, 0x68, 0xdc, 0xcf, 0x0f, 0x52, 0x1e, 0x17, 0xe5, 0x2b, 0x3c, 0x2b, 0x4a, 0x7f, 0xfa, 0x55, - 0xe4, 0xee, 0x32, 0xb2, 0x03, 0x55, 0xfd, 0x13, 0x78, 0x94, 0x85, 0x8d, 0x37, 0x56, 0x9f, 0xbb, - 0x36, 0xab, 0xcf, 0xb9, 0xd6, 0xb5, 0x55, 0x6e, 0xdf, 0x48, 0xbd, 0x5f, 0x4a, 0xb0, 0x84, 0xa9, - 0x0b, 0xc6, 0xbe, 0x64, 0x41, 0x37, 0xa0, 0x96, 0x4a, 0x2a, 0x64, 0xef, 0x90, 0x8f, 0xb0, 0xa4, - 0xc5, 0xae, 0x73, 0x79, 0xde, 0xb6, 0xfd, 0xfb, 0x7c, 0xe4, 0x3b, 0x18, 0xba, 0xcf, 0x47, 0x64, - 0x05, 0xaa, 0x3c, 0x66, 0x48, 0x2a, 0x4f, 0x91, 0xe6, 0x79, 0xcc, 0x14, 0xe5, 0x1e, 0x38, 0xba, - 0xbe, 0xd4, 0xb5, 0x97, 0xcb, 0x57, 0x3c, 0x5b, 0xae, 0x25, 0x1f, 0xc3, 0x52, 0xcc, 0x4f, 0x64, - 0xaf, 0xd0, 0xbc, 0x0a, 0x36, 0xcf, 0xd3, 0xe7, 0xa9, 0x3f, 0xe4, 0x27, 0xf2, 0x05, 0x0d, 0xac, - 0xc7, 0x85, 0x18, 0x23, 0x2d, 0x80, 0x3e, 0x8f, 0xb9, 0xc0, 0xb7, 0xe0, 0xce, 0x2b, 0x5b, 0xfc, - 0x02, 0x32, 0xd5, 0xe4, 0x67, 0x16, 0x2c, 0xec, 0x71, 0x11, 0xf0, 0x58, 0x86, 0x11, 0x4f, 0xc9, - 0x75, 0x28, 0x0f, 0x6e, 0xad, 0xa3, 0x9b, 0x96, 0x2e, 0x53, 0x01, 0x88, 0x6f, 0x74, 0xd0, 0xad, - 0x31, 0xbe, 0xd1, 0x41, 0xbc, 0xb3, 0x8e, 0x06, 0x8d, 0xf1, 0x4e, 0xc6, 0xbf, 0xdd, 0x71, 0xed, - 0x09, 0xfc, 0x76, 0xc6, 0xdf, 0x5c, 0xc7, 0xd3, 0x8d, 0xf1, 0xcd, 0x75, 0xe2, 0x82, 0x3d, 0x78, - 0x40, 0x4f, 0xb0, 0x5e, 0x13, 0x40, 0x44, 0xbf, 0xf1, 0xcb, 0x32, 0xd4, 0xf1, 0xba, 0xdf, 0xa5, - 0x03, 0x1a, 0x84, 0x72, 0x44, 0x96, 0xc1, 0x09, 0xf4, 0xb7, 0x6e, 0xbe, 0x76, 0xd5, 0xa0, 0xc4, - 0x83, 0x1a, 0x3d, 0xa6, 0x61, 0x44, 0x0f, 0x22, 0x8e, 0x95, 0x1b, 0xca, 0x18, 0x26, 0x37, 0x60, - 0x21, 0xbb, 0x42, 0x41, 0x32, 0x8c, 0xa5, 0x7e, 0x32, 0x19, 0x0b, 0x30, 0x70, 0x57, 0xe1, 0x8a, - 0x16, 0x71, 0x9a, 0x1a, 0x9a, 0x5d, 0xa4, 0x61, 0x20, 0xa3, 0xad, 0x43, 0xe3, 0xa9, 0x08, 0x25, - 0x4f, 0x7b, 0x03, 0x2e, 0x7a, 0x29, 0x0f, 0x92, 0x98, 0x4d, 0x9c, 0x75, 0x29, 0x0b, 0xef, 0x71, - 0xb1, 0x8f, 0x41, 0xb2, 0x07, 0x8d, 0x83, 0x91, 0x11, 0x98, 0x67, 0x32, 0x8f, 0xcf, 0xa4, 0x35, - 0xe3, 0x2a, 0x15, 0x5a, 0x65, 0x32, 0xa2, 0x7c, 0x8f, 0x0b, 0x7d, 0x03, 0x88, 0x0f, 0xa4, 0x50, - 0x83, 0x49, 0x59, 0xbd, 0x42, 0xca, 0x6b, 0x79, 0x91, 0x26, 0xa7, 0x0b, 0xf6, 0x30, 0xe5, 0xcc, - 0x75, 0x0a, 0x26, 0x22, 0x42, 0xde, 0x84, 0x7a, 0x94, 0xf4, 0xc3, 0x80, 0x46, 0x3d, 0x2c, 0xc4, - 0xad, 0x15, 0x28, 0x8b, 0x3a, 0xd4, 0x55, 0x11, 0xb2, 0x01, 0xe4, 0xcb, 0x21, 0x17, 0xe1, 0xa4, - 0x3b, 0x50, 0x70, 0xe7, 0x9a, 0x8e, 0xe7, 0xf6, 0xe8, 0xe6, 0xff, 0x58, 0x82, 0xff, 0xa9, 0x01, - 0xf9, 0xef, 0x66, 0xea, 0xfb, 0x50, 0x55, 0xbb, 0x88, 0xa7, 0xa9, 0x9e, 0x43, 0x45, 0x37, 0xd4, - 0xd6, 0x5a, 0xfd, 0x34, 0xdf, 0x5a, 0xdb, 0x8c, 0xe5, 0x13, 0x48, 0x8b, 0xc8, 0xa6, 0xd9, 0x4c, - 0x65, 0x54, 0xbf, 0x3e, 0xc3, 0xcb, 0xf1, 0x1e, 0xd3, 0xe2, 0x4c, 0x41, 0xee, 0x80, 0x13, 0x25, - 0x01, 0x8d, 0xd4, 0x5d, 0xb5, 0x51, 0xfd, 0xda, 0x0c, 0xf5, 0x27, 0x9a, 0x62, 0x2e, 0xb2, 0x91, - 0x90, 0x7b, 0x50, 0xdf, 0xe7, 0xe2, 0x98, 0x8b, 0xc7, 0x5c, 0xa4, 0xea, 0x55, 0x57, 0x30, 0x47, - 0x73, 0x46, 0x0e, 0xcd, 0xd0, 0x29, 0x26, 0x65, 0xde, 0x57, 0x25, 0x58, 0xc2, 0x47, 0x34, 0x39, - 0x43, 0xf3, 0x4d, 0x63, 0xfd, 0xf3, 0x4d, 0x93, 0x9b, 0x51, 0xba, 0xb2, 0x19, 0xef, 0x81, 0xad, - 0x3a, 0xa2, 0x6d, 0x5c, 0x99, 0xa1, 0x9c, 0xec, 0xb5, 0xb9, 0x6f, 0x4a, 0x44, 0xba, 0x85, 0x57, - 0x9f, 0x39, 0xb9, 0x3c, 0x23, 0xc1, 0xc4, 0xa4, 0x98, 0x9e, 0x0b, 0xde, 0xb7, 0x16, 0x34, 0xb4, - 0x0d, 0x94, 0xf9, 0x66, 0x06, 0xbf, 0xa4, 0x11, 0xdb, 0x85, 0x15, 0x50, 0xc2, 0x15, 0xd0, 0x7e, - 0xf1, 0x0a, 0xc0, 0x3d, 0x3a, 0x3d, 0xfd, 0xbd, 0x8f, 0xc0, 0x31, 0xad, 0x27, 0xef, 0x42, 0x45, - 0x86, 0x5c, 0xff, 0xfb, 0xb3, 0xb0, 0xf1, 0xea, 0x8c, 0x5c, 0x8f, 0x42, 0x6e, 0x3c, 0xc9, 0xb8, - 0xfa, 0x95, 0x7c, 0x08, 0xb6, 0x0a, 0xa9, 0x11, 0xab, 0x76, 0x96, 0x3a, 0x43, 0xcd, 0x8c, 0xd8, - 0x43, 0x3e, 0x22, 0x4d, 0xa8, 0x1c, 0xd3, 0x68, 0x98, 0x8d, 0x42, 0x13, 0xc9, 0x20, 0x9d, 0xe1, - 0x99, 0x05, 0x55, 0x7d, 0x57, 0xc8, 0x5b, 0x50, 0x3b, 0xa2, 0x5f, 0x24, 0xa2, 0x77, 0x4c, 0x23, - 0xed, 0x47, 0x5d, 0xfb, 0x51, 0x79, 0xa0, 0x02, 0xbe, 0x83, 0xf1, 0xc7, 0x34, 0x42, 0x6e, 0x18, - 0x6b, 0x6e, 0x69, 0x8a, 0xab, 0x02, 0xbe, 0x83, 0x71, 0xc5, 0x6d, 0x42, 0x65, 0x40, 0x65, 0xf0, - 0x64, 0x62, 0xd4, 0x66, 0x90, 0x1a, 0xe9, 0xc3, 0x38, 0x95, 0x38, 0xaf, 0x8b, 0x23, 0x36, 0x47, - 0xb3, 0x3a, 0xbb, 0x2b, 0x67, 0xbf, 0xb7, 0xe6, 0xce, 0x2e, 0x5a, 0xd6, 0xcf, 0x17, 0x2d, 0xeb, - 0xd7, 0x8b, 0x96, 0xf5, 0xdb, 0x45, 0xcb, 0xfa, 0xee, 0x8f, 0xd6, 0xdc, 0x67, 0x55, 0x6d, 0xd2, - 0xdf, 0x01, 0x00, 0x00, 0xff, 0xff, 0x76, 0x32, 0xdb, 0xde, 0xb2, 0x0a, 0x00, 0x00, + // 1114 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x56, 0xcf, 0x6f, 0x1b, 0x45, + 0x14, 0xce, 0xda, 0xeb, 0x78, 0xfd, 0x12, 0x93, 0x7a, 0x04, 0x65, 0x65, 0x84, 0x9d, 0x2c, 0x54, + 0x2a, 0x3f, 0x94, 0xa6, 0x41, 0x56, 0x95, 0xa0, 0x02, 0x71, 0x43, 0xa5, 0x50, 0x5a, 0x45, 0x9b, + 0xd0, 0x03, 0x17, 0x6b, 0xb2, 0x33, 0xb8, 0x4b, 0x37, 0xbb, 0x66, 0x76, 0x9c, 0xc6, 0x77, 0x24, + 0x0e, 0xa8, 0x12, 0x47, 0x8e, 0xb9, 0xf4, 0x7f, 0xe0, 0x4f, 0x88, 0x38, 0x71, 0xe0, 0xc0, 0x29, + 0x82, 0x70, 0xe1, 0xcc, 0x31, 0x27, 0x34, 0x6f, 0x67, 0xd6, 0x6b, 0xd7, 0x95, 0x48, 0x91, 0xb8, + 0x6d, 0xbe, 0xf7, 0x7d, 0xcf, 0x6f, 0xbe, 0x79, 0xf3, 0x5e, 0xe0, 0xaa, 0x48, 0x68, 0xf0, 0x68, + 0x70, 0x70, 0xe3, 0x90, 0x4b, 0xca, 0xa8, 0xa4, 0xab, 0x03, 0x91, 0xc8, 0x84, 0x34, 0x82, 0x24, + 0x78, 0x8c, 0xb1, 0x55, 0xcd, 0x68, 0x36, 0x87, 0x32, 0x8c, 0x6e, 0x0c, 0x63, 0xc1, 0xd3, 0x24, + 0x3a, 0xe2, 0xac, 0x47, 0x19, 0x13, 0x19, 0xbd, 0xf9, 0x6a, 0x3f, 0xe9, 0x27, 0xf8, 0x79, 0x43, + 0x7d, 0x65, 0xa8, 0xf7, 0x31, 0xc0, 0x96, 0x94, 0x22, 0x3c, 0x18, 0x4a, 0x9e, 0x92, 0xf7, 0xa0, + 0x42, 0xa5, 0x14, 0xa9, 0x6b, 0x2d, 0x97, 0xaf, 0xd7, 0xba, 0xaf, 0xfd, 0x7d, 0xd6, 0x6e, 0x8c, + 0xe8, 0x61, 0xb4, 0xe9, 0x21, 0xfc, 0xfe, 0x57, 0x51, 0xf2, 0xc4, 0xf3, 0x33, 0xce, 0xa6, 0xfd, + 0xe3, 0x49, 0x7b, 0xce, 0xfb, 0xce, 0x82, 0x86, 0xcf, 0x07, 0x51, 0x18, 0x50, 0x19, 0x26, 0xf1, + 0x3e, 0x15, 0x7d, 0x2e, 0xc9, 0x4d, 0xa8, 0xc6, 0x09, 0xe3, 0xbd, 0x90, 0xb9, 0xd6, 0xb2, 0x75, + 0xbd, 0xd2, 0x75, 0x4f, 0xcf, 0xda, 0x73, 0xe7, 0x67, 0xed, 0xf9, 0x07, 0x09, 0xe3, 0x3b, 0xdb, + 0x17, 0xf9, 0x97, 0x3f, 0xaf, 0x88, 0x3b, 0x8c, 0x74, 0xc0, 0x49, 0x65, 0x22, 0x50, 0x53, 0x42, + 0x4d, 0x53, 0x6b, 0xaa, 0x7b, 0x0a, 0x47, 0x91, 0xf9, 0xf4, 0xab, 0xc8, 0xdd, 0x61, 0x9b, 0x8e, + 0xaa, 0xe2, 0xaf, 0x93, 0xb6, 0xe5, 0xfd, 0x3c, 0xae, 0x64, 0x9b, 0xa7, 0x81, 0x08, 0x07, 0x32, + 0x11, 0xff, 0x5f, 0x25, 0xe4, 0x36, 0x80, 0xc8, 0x7e, 0x5e, 0x09, 0xcb, 0x28, 0x6c, 0x69, 0x61, + 0x4d, 0x17, 0x86, 0xd2, 0xf1, 0x1f, 0x7e, 0x4d, 0x2b, 0x76, 0xd8, 0xe6, 0xa2, 0x3a, 0xc8, 0x4f, + 0x27, 0x6d, 0x0b, 0x0f, 0xf3, 0xbd, 0x05, 0x8b, 0x86, 0xc6, 0x78, 0x2c, 0x55, 0x51, 0x82, 0xc6, + 0xfd, 0xfc, 0x20, 0xe5, 0x71, 0x51, 0xbe, 0xc2, 0xb3, 0xa2, 0xf4, 0xa7, 0x5f, 0x45, 0xee, 0x0e, + 0x23, 0xdb, 0x50, 0xd5, 0x3f, 0x81, 0x47, 0x59, 0x58, 0x7f, 0x7b, 0xf5, 0xb9, 0xb6, 0x59, 0x7d, + 0xce, 0xb5, 0xae, 0xad, 0x72, 0xfb, 0x46, 0xea, 0xfd, 0x5a, 0x82, 0x25, 0x4c, 0x5d, 0x30, 0xf6, + 0x25, 0x0b, 0xba, 0x06, 0xb5, 0x54, 0x52, 0x21, 0x7b, 0x8f, 0xf9, 0x08, 0x4b, 0x5a, 0xec, 0x3a, + 0x17, 0x67, 0x6d, 0xdb, 0xbf, 0xc7, 0x47, 0xbe, 0x83, 0xa1, 0x7b, 0x7c, 0x44, 0x56, 0xa0, 0xca, + 0x63, 0x86, 0xa4, 0xf2, 0x14, 0x69, 0x9e, 0xc7, 0x4c, 0x51, 0xee, 0x82, 0xa3, 0xeb, 0x4b, 0x5d, + 0x7b, 0xb9, 0x7c, 0xc9, 0xb3, 0xe5, 0x5a, 0xf2, 0x19, 0x2c, 0xc5, 0xfc, 0x58, 0xf6, 0x0a, 0x97, + 0x57, 0xc1, 0xcb, 0xf3, 0xf4, 0x79, 0xea, 0x0f, 0xf8, 0xb1, 0x7c, 0xc1, 0x05, 0xd6, 0xe3, 0x42, + 0x8c, 0x91, 0x16, 0x40, 0x9f, 0xc7, 0x5c, 0xe0, 0x5b, 0x70, 0xe7, 0x95, 0x2d, 0x7e, 0x01, 0x99, + 0xba, 0xe4, 0x67, 0x16, 0x2c, 0xec, 0x72, 0x11, 0xf0, 0x58, 0x86, 0x11, 0x4f, 0xc9, 0x55, 0x28, + 0x0f, 0x6e, 0xae, 0xa1, 0x9b, 0x96, 0x2e, 0x53, 0x01, 0x88, 0xaf, 0x77, 0xd0, 0xad, 0x31, 0xbe, + 0xde, 0x41, 0xbc, 0xb3, 0x86, 0x06, 0x8d, 0xf1, 0x4e, 0xc6, 0xbf, 0xd5, 0x71, 0xed, 0x09, 0xfc, + 0x56, 0xc6, 0xdf, 0x58, 0xc3, 0xd3, 0x8d, 0xf1, 0x8d, 0x35, 0xe2, 0x82, 0x3d, 0xb8, 0x4f, 0x8f, + 0xb1, 0x5e, 0x13, 0x40, 0x44, 0xbf, 0xf1, 0x8b, 0x32, 0xd4, 0xb1, 0xdd, 0xef, 0xd0, 0x01, 0x0d, + 0x42, 0x39, 0x22, 0xcb, 0xe0, 0x04, 0xfa, 0x5b, 0x5f, 0xbe, 0x76, 0xd5, 0xa0, 0xc4, 0x83, 0x1a, + 0x3d, 0xa2, 0x61, 0x44, 0x0f, 0x22, 0x8e, 0x95, 0x1b, 0xca, 0x18, 0x26, 0xd7, 0x60, 0x21, 0x6b, + 0xa1, 0x20, 0x19, 0xc6, 0x52, 0x3f, 0x99, 0x8c, 0x05, 0x18, 0xb8, 0xa3, 0x70, 0x45, 0x8b, 0x38, + 0x4d, 0x0d, 0xcd, 0x2e, 0xd2, 0x30, 0x90, 0xd1, 0xd6, 0xa0, 0xf1, 0x44, 0x84, 0x92, 0xa7, 0xbd, + 0x01, 0x17, 0xbd, 0x94, 0x07, 0x49, 0xcc, 0x26, 0xce, 0xba, 0x94, 0x85, 0x77, 0xb9, 0xd8, 0xc3, + 0x20, 0xd9, 0x85, 0xc6, 0xc1, 0xc8, 0x08, 0xcc, 0x33, 0x99, 0xc7, 0x67, 0xd2, 0x9a, 0xd1, 0x4a, + 0x85, 0xab, 0x32, 0x19, 0x51, 0xbe, 0xcb, 0x85, 0xee, 0x00, 0xe2, 0x03, 0x29, 0xd4, 0x60, 0x52, + 0x56, 0x2f, 0x91, 0xf2, 0x4a, 0x5e, 0xa4, 0xc9, 0xe9, 0x82, 0x3d, 0x4c, 0x39, 0x73, 0x9d, 0x82, + 0x89, 0x88, 0x90, 0x77, 0xa0, 0x1e, 0x25, 0xfd, 0x30, 0xa0, 0x51, 0x0f, 0x0b, 0x71, 0x6b, 0x05, + 0xca, 0xa2, 0x0e, 0x75, 0x55, 0x84, 0xac, 0x03, 0xf9, 0x66, 0xc8, 0x45, 0x38, 0xe9, 0x0e, 0x14, + 0xdc, 0xb9, 0xa2, 0xe3, 0xb9, 0x3d, 0xfa, 0xf2, 0x9f, 0x96, 0xe1, 0x15, 0x35, 0x20, 0xff, 0xdb, + 0x4c, 0xfd, 0x08, 0xaa, 0x6a, 0x17, 0xf1, 0x34, 0xd5, 0x73, 0xa8, 0xe8, 0x86, 0xda, 0x5a, 0xab, + 0x5f, 0xe4, 0x5b, 0x6b, 0x8b, 0xb1, 0x7c, 0x02, 0x69, 0x11, 0xd9, 0x30, 0x9b, 0xa9, 0x8c, 0xea, + 0x37, 0x67, 0x78, 0x39, 0xde, 0x63, 0x5a, 0x9c, 0x29, 0xc8, 0x6d, 0x70, 0xa2, 0x24, 0xa0, 0x91, + 0xea, 0x55, 0x1b, 0xd5, 0x6f, 0xcc, 0x50, 0x7f, 0xae, 0x29, 0xa6, 0x91, 0x8d, 0x84, 0xdc, 0x85, + 0xfa, 0x1e, 0x17, 0x47, 0x5c, 0x3c, 0xe4, 0x22, 0x55, 0xaf, 0xba, 0x82, 0x39, 0x9a, 0x33, 0x72, + 0x68, 0x86, 0x4e, 0x31, 0x29, 0x23, 0x2b, 0x50, 0x3b, 0x18, 0x86, 0x11, 0xeb, 0x49, 0xda, 0xc7, + 0x26, 0xab, 0x99, 0x9f, 0x42, 0x78, 0x9f, 0xf6, 0xc9, 0x5b, 0x00, 0x38, 0x00, 0xd5, 0xe2, 0x96, + 0xd8, 0x35, 0xf9, 0xa3, 0xd1, 0xf8, 0x96, 0xf4, 0xbe, 0x2d, 0xc1, 0x12, 0x3e, 0xc6, 0xc9, 0x59, + 0x9c, 0x6f, 0x2c, 0xeb, 0xdf, 0x6f, 0xac, 0xdc, 0xd4, 0xd2, 0xa5, 0x4d, 0xfd, 0x10, 0x6c, 0x75, + 0xb3, 0xfa, 0x3a, 0x56, 0x66, 0x28, 0x27, 0x7b, 0xc6, 0xf4, 0xad, 0x12, 0x91, 0x6e, 0x61, 0x7a, + 0x64, 0x37, 0xb2, 0x3c, 0x23, 0xc1, 0xc4, 0xc4, 0x99, 0x9e, 0x2f, 0xde, 0x53, 0x0b, 0x1a, 0xda, + 0x06, 0xca, 0x7c, 0x33, 0xcb, 0x5f, 0xd2, 0x88, 0xad, 0xc2, 0x2a, 0x29, 0xe1, 0x2a, 0x69, 0xbf, + 0x78, 0x95, 0xe0, 0x3e, 0x9e, 0xde, 0x22, 0xde, 0xa7, 0xe0, 0x98, 0x16, 0x22, 0x1f, 0x40, 0x45, + 0x86, 0x5c, 0xff, 0x1b, 0xb5, 0xb0, 0xfe, 0xfa, 0x8c, 0x5c, 0xfb, 0x21, 0x37, 0x9e, 0x64, 0x5c, + 0xfd, 0xda, 0x3e, 0x01, 0x5b, 0x85, 0xd4, 0xa8, 0x56, 0xbb, 0xcf, 0x2a, 0xf4, 0x89, 0x02, 0x48, + 0x13, 0x2a, 0x47, 0x34, 0x1a, 0x66, 0x23, 0xd5, 0x44, 0x32, 0x48, 0x67, 0x78, 0x66, 0x41, 0xd5, + 0xf4, 0xdc, 0xbb, 0x50, 0x3b, 0xa4, 0x5f, 0x27, 0xa2, 0x77, 0x44, 0x23, 0xed, 0x47, 0x5d, 0xfb, + 0x51, 0xb9, 0xaf, 0x02, 0xbe, 0x83, 0xf1, 0x87, 0x34, 0x42, 0x6e, 0x18, 0x6b, 0x6e, 0x69, 0x8a, + 0xab, 0x02, 0xbe, 0x83, 0x71, 0xc5, 0x6d, 0x42, 0x65, 0x40, 0x65, 0xf0, 0x68, 0x62, 0x64, 0x67, + 0x90, 0x5a, 0x0d, 0xc3, 0x38, 0x95, 0x38, 0xf7, 0x8b, 0xa3, 0x3a, 0x47, 0xb3, 0x3a, 0xbb, 0x2b, + 0xa7, 0x7f, 0xb4, 0xe6, 0x4e, 0xcf, 0x5b, 0xd6, 0x2f, 0xe7, 0x2d, 0xeb, 0xb7, 0xf3, 0x96, 0xf5, + 0xfb, 0x79, 0xcb, 0xfa, 0xe1, 0xcf, 0xd6, 0xdc, 0x97, 0x55, 0x6d, 0xd2, 0x3f, 0x01, 0x00, 0x00, + 0xff, 0xff, 0x78, 0x29, 0xdb, 0xc0, 0xfa, 0x0a, 0x00, 0x00, } diff --git a/pkg/roachpb/metadata.proto b/pkg/roachpb/metadata.proto index 4905489ed6e5..3d6462e4de7d 100644 --- a/pkg/roachpb/metadata.proto +++ b/pkg/roachpb/metadata.proto @@ -161,6 +161,8 @@ message NodeDescriptor { optional Attributes attrs = 3 [(gogoproto.nullable) = false]; optional Locality locality = 4 [(gogoproto.nullable) = false]; optional Version ServerVersion = 5 [(gogoproto.nullable) = false]; + optional string build_tag = 6 [(gogoproto.nullable) = false]; + optional int64 started_at = 7 [(gogoproto.nullable) = false]; } // StoreDescriptor holds store information including store attributes, node diff --git a/pkg/server/node.go b/pkg/server/node.go index a4f3c6dcd483..0da1362fddf3 100644 --- a/pkg/server/node.go +++ b/pkg/server/node.go @@ -28,6 +28,7 @@ import ( "github.com/pkg/errors" "github.com/cockroachdb/cockroach/pkg/base" + "github.com/cockroachdb/cockroach/pkg/build" "github.com/cockroachdb/cockroach/pkg/gossip" "github.com/cockroachdb/cockroach/pkg/internal/client" "github.com/cockroachdb/cockroach/pkg/keys" @@ -427,12 +428,16 @@ func (n *Node) start( span.Finish() nodeID = newID } + + n.startedAt = n.storeCfg.Clock.Now().WallTime n.Descriptor = roachpb.NodeDescriptor{ NodeID: nodeID, Address: util.MakeUnresolvedAddr(addr.Network(), addr.String()), Attrs: attrs, Locality: locality, ServerVersion: n.storeCfg.Settings.Version.ServerVersion, + BuildTag: build.GetInfo().Tag, + StartedAt: n.startedAt, } // Invoke any passed in nodeDescriptorCallback as soon as it's available, to // ensure that other components (currently the DistSQLPlanner) are initialized @@ -529,8 +534,6 @@ func (n *Node) start( } } - n.startedAt = n.storeCfg.Clock.Now().WallTime - n.startComputePeriodicMetrics(n.stopper, DefaultMetricsSampleInterval) // Be careful about moving this line above `startStores`; store migrations rely // on the fact that the cluster version has not been updated via Gossip (we diff --git a/pkg/server/node_test.go b/pkg/server/node_test.go index f93d9850c085..11a664d7b731 100644 --- a/pkg/server/node_test.go +++ b/pkg/server/node_test.go @@ -439,7 +439,7 @@ func compareNodeStatus( // Descriptor values should be exactly equal to expected. if a, e := nodeStatus.Desc, expectedNodeStatus.Desc; !reflect.DeepEqual(a, e) { - t.Errorf("%d: Descriptor does not match expected.\nexpected: %s\nactual: %s", testNumber, e, a) + t.Errorf("%d: Descriptor does not match expected.\nexpected: %s\nactual: %s", testNumber, &e, &a) } // ======================================== diff --git a/pkg/sql/crdb_internal.go b/pkg/sql/crdb_internal.go index 999153c675fe..a424726d7f61 100644 --- a/pkg/sql/crdb_internal.go +++ b/pkg/sql/crdb_internal.go @@ -1745,7 +1745,11 @@ CREATE TABLE crdb_internal.gossip_nodes ( address STRING NOT NULL, attrs JSON NOT NULL, locality JSON NOT NULL, - server_version STRING NOT NULL + server_version STRING NOT NULL, + build_tag STRING NOT NULL, + started_at TIMESTAMP NOT NULL, + ranges INT NOT NULL, + leases INT NOT NULL ) `, populate: func(ctx context.Context, p *planner, _ *DatabaseDescriptor, addRow func(...tree.Datum) error) error { @@ -1775,6 +1779,32 @@ CREATE TABLE crdb_internal.gossip_nodes ( return descriptors[i].NodeID < descriptors[j].NodeID }) + type nodeStats struct { + ranges int32 + leases int32 + } + + stats := make(map[roachpb.NodeID]nodeStats) + if err := g.IterateInfos(gossip.KeyStorePrefix, func(key string, i gossip.Info) error { + bytes, err := i.Value.GetBytes() + if err != nil { + return errors.Wrapf(err, "failed to extract bytes for key %q", key) + } + + var desc roachpb.StoreDescriptor + if err := protoutil.Unmarshal(bytes, &desc); err != nil { + return errors.Wrapf(err, "failed to parse value for key %q", key) + } + + s := stats[desc.Node.NodeID] + s.ranges += desc.Capacity.RangeCount + s.leases += desc.Capacity.LeaseCount + stats[desc.Node.NodeID] = s + return nil + }); err != nil { + return err + } + for _, d := range descriptors { attrs := json.NewArrayBuilder(len(d.Attrs.Attrs)) for _, a := range d.Attrs.Attrs { @@ -1793,6 +1823,10 @@ CREATE TABLE crdb_internal.gossip_nodes ( tree.NewDJSON(attrs.Build()), tree.NewDJSON(locality.Build()), tree.NewDString(d.ServerVersion.String()), + tree.NewDString(d.BuildTag), + tree.MakeDTimestamp(timeutil.Unix(0, d.StartedAt), time.Microsecond), + tree.NewDInt(tree.DInt(stats[d.NodeID].ranges)), + tree.NewDInt(tree.DInt(stats[d.NodeID].leases)), ); err != nil { return err } @@ -1801,7 +1835,9 @@ CREATE TABLE crdb_internal.gossip_nodes ( }, } -// crdbInternalGossipLivenessTable exposes local information about the nodes' liveness. +// crdbInternalGossipLivenessTable exposes local information about the nodes' +// liveness. The data exposed in this table can be stale/incomplete because +// gossip doesn't provide guarantees around freshness or consistency. var crdbInternalGossipLivenessTable = virtualSchemaTable{ schema: ` CREATE TABLE crdb_internal.gossip_liveness ( @@ -1809,16 +1845,27 @@ CREATE TABLE crdb_internal.gossip_liveness ( epoch INT NOT NULL, expiration STRING NOT NULL, draining BOOL NOT NULL, - decommissioning BOOL NOT NULL + decommissioning BOOL NOT NULL, + updated_at TIMESTAMP ) `, populate: func(ctx context.Context, p *planner, _ *DatabaseDescriptor, addRow func(...tree.Datum) error) error { + // ATTENTION: This contents of this table should only access gossip data + // which is highly available. DO NOT CALL functions which require the + // cluster to be healthy, such as StatusServer.Nodes(). + if err := p.RequireSuperUser(ctx, "read crdb_internal.gossip_liveness"); err != nil { return err } g := p.ExecCfg().Gossip - var livenesses []storage.Liveness + + type nodeInfo struct { + liveness storage.Liveness + updatedAt int64 + } + + var nodes []nodeInfo if err := g.IterateInfos(gossip.KeyNodeLivenessPrefix, func(key string, i gossip.Info) error { bytes, err := i.Value.GetBytes() if err != nil { @@ -1829,23 +1876,29 @@ CREATE TABLE crdb_internal.gossip_liveness ( if err := protoutil.Unmarshal(bytes, &l); err != nil { return errors.Wrapf(err, "failed to parse value for key %q", key) } - livenesses = append(livenesses, l) + nodes = append(nodes, nodeInfo{ + liveness: l, + updatedAt: i.OrigStamp, + }) return nil }); err != nil { return err } - sort.Slice(livenesses, func(i, j int) bool { - return livenesses[i].NodeID < livenesses[j].NodeID + sort.Slice(nodes, func(i, j int) bool { + return nodes[i].liveness.NodeID < nodes[j].liveness.NodeID }) - for _, l := range livenesses { + for i := range nodes { + n := &nodes[i] + l := &n.liveness if err := addRow( tree.NewDInt(tree.DInt(l.NodeID)), tree.NewDInt(tree.DInt(l.Epoch)), tree.NewDString(l.Expiration.String()), tree.MakeDBool(tree.DBool(l.Draining)), tree.MakeDBool(tree.DBool(l.Decommissioning)), + tree.MakeDTimestamp(timeutil.Unix(0, n.updatedAt), time.Microsecond), ); err != nil { return err } diff --git a/pkg/sql/logictest/testdata/planner_test/explain b/pkg/sql/logictest/testdata/planner_test/explain index 0143b6918d17..43b8756fbf7e 100644 --- a/pkg/sql/logictest/testdata/planner_test/explain +++ b/pkg/sql/logictest/testdata/planner_test/explain @@ -223,7 +223,7 @@ sort · · ├── render · · │ └── filter · · │ └── values · · - │ size 17 columns, 901 rows + │ size 17 columns, 906 rows └── render · · └── filter · · └── values · · diff --git a/pkg/sql/opt/exec/execbuilder/testdata/explain b/pkg/sql/opt/exec/execbuilder/testdata/explain index fddd4cdddfcd..68a31405bd3c 100644 --- a/pkg/sql/opt/exec/execbuilder/testdata/explain +++ b/pkg/sql/opt/exec/execbuilder/testdata/explain @@ -216,7 +216,7 @@ sort · · ├── render · · │ └── filter · · │ └── values · · - │ size 17 columns, 901 rows + │ size 17 columns, 906 rows └── render · · └── filter · · └── values · ·