mirror of
https://github.com/moby/moby.git
synced 2022-11-09 12:21:53 -05:00
28f4561e3f
Network DB is a network scoped gossip database built on top of hashicorp/memberlist providing an eventually consistent state store. It limits the scope of the gossip and periodic bulk syncing for table entries to only the nodes which participate in the network to which the gossip belongs. This designs make the gossip layer scale better and only consumes resources for the network state that the node participates in. Since the complete state for a network is maintained by all nodes participating in the network, all nodes will eventually converge to the same state. NetworkDB also provides facilities for the users of the package to watch on any table (or all tables) and get notified if there are state changes of interest that happened anywhere in the cluster when that state change eventually finds it's way to the watcher's node. Signed-off-by: Jana Radhakrishnan <mrjana@docker.com>
122 lines
2.8 KiB
Go
122 lines
2.8 KiB
Go
package networkdb
|
|
|
|
import (
|
|
"bytes"
|
|
"encoding/binary"
|
|
"fmt"
|
|
|
|
"github.com/hashicorp/go-msgpack/codec"
|
|
)
|
|
|
|
type messageType uint8
|
|
|
|
const (
|
|
// For network join/leave event message
|
|
networkEventMsg messageType = 1 + iota
|
|
|
|
// For pushing/pulling network/node association state
|
|
networkPushPullMsg
|
|
|
|
// For table entry CRUD event message
|
|
tableEventMsg
|
|
|
|
// For building a compound message which packs many different
|
|
// message types together
|
|
compoundMsg
|
|
|
|
// For syncing table entries in bulk b/w nodes.
|
|
bulkSyncMsg
|
|
)
|
|
|
|
const (
|
|
// Max udp message size chosen to avoid network packet
|
|
// fragmentation.
|
|
udpSendBuf = 1400
|
|
|
|
// Compound message header overhead 1 byte(message type) + 4
|
|
// bytes (num messages)
|
|
compoundHeaderOverhead = 5
|
|
|
|
// Overhead for each embedded message in a compound message 2
|
|
// bytes (len of embedded message)
|
|
compoundOverhead = 2
|
|
)
|
|
|
|
func decodeMessage(buf []byte, out interface{}) error {
|
|
var handle codec.MsgpackHandle
|
|
return codec.NewDecoder(bytes.NewReader(buf), &handle).Decode(out)
|
|
}
|
|
|
|
func encodeMessage(t messageType, msg interface{}) ([]byte, error) {
|
|
buf := bytes.NewBuffer(nil)
|
|
buf.WriteByte(uint8(t))
|
|
|
|
handle := codec.MsgpackHandle{}
|
|
encoder := codec.NewEncoder(buf, &handle)
|
|
err := encoder.Encode(msg)
|
|
return buf.Bytes(), err
|
|
}
|
|
|
|
// makeCompoundMessage takes a list of messages and generates
|
|
// a single compound message containing all of them
|
|
func makeCompoundMessage(msgs [][]byte) *bytes.Buffer {
|
|
// Create a local buffer
|
|
buf := bytes.NewBuffer(nil)
|
|
|
|
// Write out the type
|
|
buf.WriteByte(uint8(compoundMsg))
|
|
|
|
// Write out the number of message
|
|
binary.Write(buf, binary.BigEndian, uint32(len(msgs)))
|
|
|
|
// Add the message lengths
|
|
for _, m := range msgs {
|
|
binary.Write(buf, binary.BigEndian, uint16(len(m)))
|
|
}
|
|
|
|
// Append the messages
|
|
for _, m := range msgs {
|
|
buf.Write(m)
|
|
}
|
|
|
|
return buf
|
|
}
|
|
|
|
// decodeCompoundMessage splits a compound message and returns
|
|
// the slices of individual messages. Also returns the number
|
|
// of truncated messages and any potential error
|
|
func decodeCompoundMessage(buf []byte) (trunc int, parts [][]byte, err error) {
|
|
if len(buf) < 1 {
|
|
err = fmt.Errorf("missing compound length byte")
|
|
return
|
|
}
|
|
numParts := binary.BigEndian.Uint32(buf[0:4])
|
|
buf = buf[4:]
|
|
|
|
// Check we have enough bytes
|
|
if len(buf) < int(numParts*2) {
|
|
err = fmt.Errorf("truncated len slice")
|
|
return
|
|
}
|
|
|
|
// Decode the lengths
|
|
lengths := make([]uint16, numParts)
|
|
for i := 0; i < int(numParts); i++ {
|
|
lengths[i] = binary.BigEndian.Uint16(buf[i*2 : i*2+2])
|
|
}
|
|
buf = buf[numParts*2:]
|
|
|
|
// Split each message
|
|
for idx, msgLen := range lengths {
|
|
if len(buf) < int(msgLen) {
|
|
trunc = int(numParts) - idx
|
|
return
|
|
}
|
|
|
|
// Extract the slice, seek past on the buffer
|
|
slice := buf[:msgLen]
|
|
buf = buf[msgLen:]
|
|
parts = append(parts, slice)
|
|
}
|
|
return
|
|
}
|