112 lines
3.0 KiB
Go
112 lines
3.0 KiB
Go
|
/*
|
||
|
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.
|
||
|
type Node struct {
|
||
|
ip net.IP
|
||
|
port uint16
|
||
|
timestamp uint32
|
||
|
address string
|
||
|
pingMillis int
|
||
|
status NodeStatus
|
||
|
emitCounter int8
|
||
|
heartbeat uint32
|
||
|
}
|
||
|
|
||
|
// 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
|
||
|
}
|
||
|
|
||
|
// 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 {
|
||
|
return fmt.Sprintf("%s:%d", ip, port)
|
||
|
}
|
||
|
|
||
|
// GetNowInMillis returns the current local time in milliseconds since the
|
||
|
// epoch.
|
||
|
func GetNowInMillis() uint32 {
|
||
|
return uint32(time.Now().UnixNano() / int64(time.Millisecond))
|
||
|
}
|