-
Notifications
You must be signed in to change notification settings - Fork 41
/
node.go
121 lines (100 loc) · 3.25 KB
/
node.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
/*
Copyright 2016 The Smudge 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.
*/
package smudge
import (
"fmt"
"net"
"time"
)
const (
// PingNoData is returned by n.PingMillis() to indicate that a node has
// not yet been pinged, and therefore no ping data exists.
PingNoData int = -1
// PingTimedOut is returned by n.PingMillis() to indicate that a node's
// last PING timed out. This is the typical value for dead nodes.
PingTimedOut int = -2
)
// Node represents a single node in the cluster and its status
type Node struct {
ip net.IP
port uint16
timestamp uint32
address string
pingMillis int
status NodeStatus
emitCounter int8
heartbeat uint32
statusSource *Node
}
// Address rReturns the address for this node in string format, which is simply
// the node's local IP and listen port. This is used as a unique identifier
// throughout the code base.
func (n *Node) Address() string {
if n.address == "" {
n.address = nodeAddressString(n.ip, n.port)
}
return n.address
}
// Age returns the time since we last heard from this node, in milliseconds.
func (n *Node) Age() uint32 {
return GetNowInMillis() - n.timestamp
}
// EmitCounter returns the number of times remaining that current status
// will be emitted by this node to other nodes.
func (n *Node) EmitCounter() int8 {
return n.emitCounter
}
// IP returns the IP associated with this node.
func (n *Node) IP() net.IP {
return n.ip
}
// PingMillis returns the milliseconds transpired between the most recent
// PING to this node and its responded ACK. If this node has not yet been
// pinged, this vaue will be PingNoData (-1). If this node's last PING timed
// out, this value will be PingTimedOut (-2).
func (n *Node) PingMillis() int {
return n.pingMillis
}
// Port returns the port associated with this node.
func (n *Node) Port() uint16 {
return n.port
}
// Status returns this node's current status.
func (n *Node) Status() NodeStatus {
return n.status
}
// StatusSource returns a pointer to the node that originally stated this
// node's Status; the source of the gossip.
func (n *Node) StatusSource() *Node {
return n.statusSource
}
// Timestamp returns the timestamp of this node's last ping or status update,
// in milliseconds from the epoch
func (n *Node) Timestamp() uint32 {
return n.timestamp
}
// Touch updates the timestamp to the local time in milliseconds.
func (n *Node) Touch() {
n.timestamp = GetNowInMillis()
}
func nodeAddressString(ip net.IP, port uint16) string {
if ip.To4() != nil {
return fmt.Sprintf("%s:%d", ip.String(), port)
}
return fmt.Sprintf("[%s]:%d", ip.String(), port)
}
// GetNowInMillis returns the current local time in milliseconds since the
// epoch.
func GetNowInMillis() uint32 {
return uint32(time.Now().UnixNano() / int64(time.Millisecond))
}