util.go 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126
  1. // Copyright 2015 The etcd Authors
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. package etcdserver
  15. import (
  16. "fmt"
  17. "time"
  18. "github.com/coreos/etcd/etcdserver/membership"
  19. "github.com/coreos/etcd/pkg/types"
  20. "github.com/coreos/etcd/rafthttp"
  21. "go.uber.org/zap"
  22. )
  23. // isConnectedToQuorumSince checks whether the local member is connected to the
  24. // quorum of the cluster since the given time.
  25. func isConnectedToQuorumSince(transport rafthttp.Transporter, since time.Time, self types.ID, members []*membership.Member) bool {
  26. return numConnectedSince(transport, since, self, members) >= (len(members)/2)+1
  27. }
  28. // isConnectedSince checks whether the local member is connected to the
  29. // remote member since the given time.
  30. func isConnectedSince(transport rafthttp.Transporter, since time.Time, remote types.ID) bool {
  31. t := transport.ActiveSince(remote)
  32. return !t.IsZero() && t.Before(since)
  33. }
  34. // isConnectedFullySince checks whether the local member is connected to all
  35. // members in the cluster since the given time.
  36. func isConnectedFullySince(transport rafthttp.Transporter, since time.Time, self types.ID, members []*membership.Member) bool {
  37. return numConnectedSince(transport, since, self, members) == len(members)
  38. }
  39. // numConnectedSince counts how many members are connected to the local member
  40. // since the given time.
  41. func numConnectedSince(transport rafthttp.Transporter, since time.Time, self types.ID, members []*membership.Member) int {
  42. connectedNum := 0
  43. for _, m := range members {
  44. if m.ID == self || isConnectedSince(transport, since, m.ID) {
  45. connectedNum++
  46. }
  47. }
  48. return connectedNum
  49. }
  50. // longestConnected chooses the member with longest active-since-time.
  51. // It returns false, if nothing is active.
  52. func longestConnected(tp rafthttp.Transporter, membs []types.ID) (types.ID, bool) {
  53. var longest types.ID
  54. var oldest time.Time
  55. for _, id := range membs {
  56. tm := tp.ActiveSince(id)
  57. if tm.IsZero() { // inactive
  58. continue
  59. }
  60. if oldest.IsZero() { // first longest candidate
  61. oldest = tm
  62. longest = id
  63. }
  64. if tm.Before(oldest) {
  65. oldest = tm
  66. longest = id
  67. }
  68. }
  69. if uint64(longest) == 0 {
  70. return longest, false
  71. }
  72. return longest, true
  73. }
  74. type notifier struct {
  75. c chan struct{}
  76. err error
  77. }
  78. func newNotifier() *notifier {
  79. return &notifier{
  80. c: make(chan struct{}),
  81. }
  82. }
  83. func (nc *notifier) notify(err error) {
  84. nc.err = err
  85. close(nc.c)
  86. }
  87. func warnOfExpensiveRequest(lg *zap.Logger, now time.Time, stringer fmt.Stringer) {
  88. warnOfExpensiveGenericRequest(lg, now, stringer, "")
  89. }
  90. func warnOfExpensiveReadOnlyRangeRequest(lg *zap.Logger, now time.Time, stringer fmt.Stringer) {
  91. warnOfExpensiveGenericRequest(lg, now, stringer, "read-only range ")
  92. }
  93. func warnOfExpensiveGenericRequest(lg *zap.Logger, now time.Time, stringer fmt.Stringer, prefix string) {
  94. // TODO: add metrics
  95. d := time.Since(now)
  96. if d > warnApplyDuration {
  97. if lg != nil {
  98. lg.Warn(
  99. "request took too long",
  100. zap.Duration("took", d),
  101. zap.Duration("expected-duration", warnApplyDuration),
  102. zap.String("prefix", prefix),
  103. zap.String("request", stringer.String()),
  104. )
  105. } else {
  106. plog.Warningf("%srequest %q took too long (%v) to execute", prefix, stringer.String(), d)
  107. }
  108. }
  109. }