2016-03-28 20:28:57 -04:00
|
|
|
package networkdb
|
|
|
|
|
|
|
|
import (
|
2016-11-21 20:29:53 -05:00
|
|
|
"errors"
|
2016-09-15 01:24:14 -04:00
|
|
|
"time"
|
|
|
|
|
2016-03-28 20:28:57 -04:00
|
|
|
"github.com/hashicorp/memberlist"
|
|
|
|
"github.com/hashicorp/serf/serf"
|
|
|
|
)
|
|
|
|
|
2016-09-15 01:24:14 -04:00
|
|
|
const broadcastTimeout = 5 * time.Second
|
|
|
|
|
2016-03-28 20:28:57 -04:00
|
|
|
type networkEventMessage struct {
|
|
|
|
id string
|
|
|
|
node string
|
|
|
|
msg []byte
|
|
|
|
}
|
|
|
|
|
|
|
|
func (m *networkEventMessage) Invalidates(other memberlist.Broadcast) bool {
|
|
|
|
otherm := other.(*networkEventMessage)
|
|
|
|
return m.id == otherm.id && m.node == otherm.node
|
|
|
|
}
|
|
|
|
|
|
|
|
func (m *networkEventMessage) Message() []byte {
|
|
|
|
return m.msg
|
|
|
|
}
|
|
|
|
|
|
|
|
func (m *networkEventMessage) Finished() {
|
|
|
|
}
|
|
|
|
|
2016-05-17 00:42:35 -04:00
|
|
|
func (nDB *NetworkDB) sendNetworkEvent(nid string, event NetworkEvent_Type, ltime serf.LamportTime) error {
|
|
|
|
nEvent := NetworkEvent{
|
|
|
|
Type: event,
|
2016-03-28 20:28:57 -04:00
|
|
|
LTime: ltime,
|
2017-09-11 14:35:18 -04:00
|
|
|
NodeName: nDB.config.NodeID,
|
2016-03-28 20:28:57 -04:00
|
|
|
NetworkID: nid,
|
|
|
|
}
|
|
|
|
|
2016-05-17 00:42:35 -04:00
|
|
|
raw, err := encodeMessage(MessageTypeNetworkEvent, &nEvent)
|
2016-03-28 20:28:57 -04:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
nDB.networkBroadcasts.QueueBroadcast(&networkEventMessage{
|
|
|
|
msg: raw,
|
|
|
|
id: nid,
|
2017-09-11 14:35:18 -04:00
|
|
|
node: nDB.config.NodeID,
|
2016-03-28 20:28:57 -04:00
|
|
|
})
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2016-09-15 01:24:14 -04:00
|
|
|
type nodeEventMessage struct {
|
|
|
|
msg []byte
|
|
|
|
notify chan<- struct{}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (m *nodeEventMessage) Invalidates(other memberlist.Broadcast) bool {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
|
|
|
func (m *nodeEventMessage) Message() []byte {
|
|
|
|
return m.msg
|
|
|
|
}
|
|
|
|
|
|
|
|
func (m *nodeEventMessage) Finished() {
|
|
|
|
if m.notify != nil {
|
|
|
|
close(m.notify)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (nDB *NetworkDB) sendNodeEvent(event NodeEvent_Type) error {
|
|
|
|
nEvent := NodeEvent{
|
|
|
|
Type: event,
|
|
|
|
LTime: nDB.networkClock.Increment(),
|
2017-09-11 14:35:18 -04:00
|
|
|
NodeName: nDB.config.NodeID,
|
2016-09-15 01:24:14 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
raw, err := encodeMessage(MessageTypeNodeEvent, &nEvent)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
notifyCh := make(chan struct{})
|
|
|
|
nDB.nodeBroadcasts.QueueBroadcast(&nodeEventMessage{
|
|
|
|
msg: raw,
|
|
|
|
notify: notifyCh,
|
|
|
|
})
|
|
|
|
|
2017-04-08 01:25:04 -04:00
|
|
|
nDB.RLock()
|
|
|
|
noPeers := len(nDB.nodes) <= 1
|
|
|
|
nDB.RUnlock()
|
|
|
|
|
|
|
|
// Message enqueued, do not wait for a send if no peer is present
|
|
|
|
if noPeers {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2016-09-15 01:24:14 -04:00
|
|
|
// Wait for the broadcast
|
|
|
|
select {
|
|
|
|
case <-notifyCh:
|
|
|
|
case <-time.After(broadcastTimeout):
|
2016-11-21 20:29:53 -05:00
|
|
|
return errors.New("timed out broadcasting node event")
|
2016-09-15 01:24:14 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2016-03-28 20:28:57 -04:00
|
|
|
type tableEventMessage struct {
|
|
|
|
id string
|
|
|
|
tname string
|
|
|
|
key string
|
|
|
|
msg []byte
|
|
|
|
}
|
|
|
|
|
|
|
|
func (m *tableEventMessage) Invalidates(other memberlist.Broadcast) bool {
|
2017-07-11 16:18:58 -04:00
|
|
|
otherm := other.(*tableEventMessage)
|
|
|
|
return m.tname == otherm.tname && m.id == otherm.id && m.key == otherm.key
|
2016-03-28 20:28:57 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
func (m *tableEventMessage) Message() []byte {
|
|
|
|
return m.msg
|
|
|
|
}
|
|
|
|
|
|
|
|
func (m *tableEventMessage) Finished() {
|
|
|
|
}
|
|
|
|
|
2016-05-17 00:42:35 -04:00
|
|
|
func (nDB *NetworkDB) sendTableEvent(event TableEvent_Type, nid string, tname string, key string, entry *entry) error {
|
|
|
|
tEvent := TableEvent{
|
|
|
|
Type: event,
|
2016-03-28 20:28:57 -04:00
|
|
|
LTime: entry.ltime,
|
2017-09-11 14:35:18 -04:00
|
|
|
NodeName: nDB.config.NodeID,
|
2016-03-28 20:28:57 -04:00
|
|
|
NetworkID: nid,
|
|
|
|
TableName: tname,
|
|
|
|
Key: key,
|
|
|
|
Value: entry.value,
|
2017-09-19 16:42:35 -04:00
|
|
|
// The duration in second is a float that below would be truncated
|
|
|
|
ResidualReapTime: int32(entry.reapTime.Seconds()),
|
2016-03-28 20:28:57 -04:00
|
|
|
}
|
|
|
|
|
2016-05-17 00:42:35 -04:00
|
|
|
raw, err := encodeMessage(MessageTypeTableEvent, &tEvent)
|
2016-03-28 20:28:57 -04:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2016-06-12 14:58:03 -04:00
|
|
|
var broadcastQ *memberlist.TransmitLimitedQueue
|
2016-03-28 20:28:57 -04:00
|
|
|
nDB.RLock()
|
2017-09-11 14:35:18 -04:00
|
|
|
thisNodeNetworks, ok := nDB.networks[nDB.config.NodeID]
|
2016-06-12 14:58:03 -04:00
|
|
|
if ok {
|
|
|
|
// The network may have been removed
|
|
|
|
network, networkOk := thisNodeNetworks[nid]
|
|
|
|
if !networkOk {
|
|
|
|
nDB.RUnlock()
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
broadcastQ = network.tableBroadcasts
|
|
|
|
}
|
2016-03-28 20:28:57 -04:00
|
|
|
nDB.RUnlock()
|
|
|
|
|
2016-06-12 14:58:03 -04:00
|
|
|
// The network may have been removed
|
|
|
|
if broadcastQ == nil {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2016-03-28 20:28:57 -04:00
|
|
|
broadcastQ.QueueBroadcast(&tableEventMessage{
|
|
|
|
msg: raw,
|
|
|
|
id: nid,
|
|
|
|
tname: tname,
|
|
|
|
key: key,
|
|
|
|
})
|
|
|
|
return nil
|
|
|
|
}
|