|
|
|
@ -5,7 +5,6 @@ import (
|
|
|
|
|
"time" |
|
|
|
|
|
|
|
|
|
"github.com/hashicorp/consul/consul/structs" |
|
|
|
|
"github.com/hashicorp/serf/coordinate" |
|
|
|
|
) |
|
|
|
|
|
|
|
|
|
type Coordinate struct { |
|
|
|
@ -41,16 +40,22 @@ func (c *Coordinate) GetLAN(args *structs.NodeSpecificRequest, reply *structs.In
|
|
|
|
|
//
|
|
|
|
|
// Note that the server does not necessarily know about *all* servers in the given datacenter.
|
|
|
|
|
// It just returns the coordinates of those that it knows.
|
|
|
|
|
func (c *Coordinate) GetWAN(args *structs.DCSpecificRequest, reply *[]*coordinate.Coordinate) error { |
|
|
|
|
func (c *Coordinate) GetWAN(args *structs.DCSpecificRequest, reply *structs.CoordinateList) error { |
|
|
|
|
if args.Datacenter == c.srv.config.Datacenter { |
|
|
|
|
*reply = make([]*coordinate.Coordinate, 1) |
|
|
|
|
(*reply)[0] = c.srv.GetWANCoordinate() |
|
|
|
|
reply.Coords = make([]structs.Coordinate, 1) |
|
|
|
|
reply.Coords[0] = structs.Coordinate{ |
|
|
|
|
Node: c.srv.config.NodeName, |
|
|
|
|
Coord: c.srv.GetWANCoordinate(), |
|
|
|
|
} |
|
|
|
|
} else { |
|
|
|
|
servers := c.srv.remoteConsuls[args.Datacenter] // servers in the specified DC
|
|
|
|
|
*reply = make([]*coordinate.Coordinate, 0) |
|
|
|
|
reply.Coords = make([]structs.Coordinate, 0) |
|
|
|
|
for i := 0; i < len(servers); i++ { |
|
|
|
|
if coord := c.srv.serfWAN.GetCachedCoordinate(servers[i].Name); coord != nil { |
|
|
|
|
*reply = append(*reply, coord) |
|
|
|
|
reply.Coords = append(reply.Coords, structs.Coordinate{ |
|
|
|
|
Node: servers[i].Name, |
|
|
|
|
Coord: coord, |
|
|
|
|
}) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
@ -58,6 +63,13 @@ func (c *Coordinate) GetWAN(args *structs.DCSpecificRequest, reply *[]*coordinat
|
|
|
|
|
return nil |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func flushCoordinates(c *Coordinate, buf []*structs.CoordinateUpdateRequest) { |
|
|
|
|
_, err := c.srv.raftApply(structs.CoordinateRequestType, buf) |
|
|
|
|
if err != nil { |
|
|
|
|
c.srv.logger.Printf("[ERR] consul.coordinate: Update failed: %v", err) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Update updates the the LAN coordinate of a node.
|
|
|
|
|
func (c *Coordinate) Update(args *structs.CoordinateUpdateRequest, reply *struct{}) error { |
|
|
|
|
if done, err := c.srv.forward("Coordinate.Update", args, args, reply); done { |
|
|
|
@ -65,24 +77,18 @@ func (c *Coordinate) Update(args *structs.CoordinateUpdateRequest, reply *struct
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
c.updateBufferLock.Lock() |
|
|
|
|
defer c.updateBufferLock.Unlock() |
|
|
|
|
c.updateBuffer = append(c.updateBuffer, args) |
|
|
|
|
|
|
|
|
|
if time.Since(c.updateLastSent) > c.srv.config.CoordinateUpdatePeriod || len(c.updateBuffer) > c.srv.config.CoordinateUpdateMaxBatchSize { |
|
|
|
|
c.srv.logger.Printf("sending update for %v", args.Node) |
|
|
|
|
// Apply the potentially time-consuming transaction out of band
|
|
|
|
|
go func() { |
|
|
|
|
defer c.updateBufferLock.Unlock() |
|
|
|
|
_, err := c.srv.raftApply(structs.CoordinateRequestType, c.updateBuffer) |
|
|
|
|
// We clear the buffer regardless of whether the raft transaction succeeded, just so the
|
|
|
|
|
// buffer doesn't keep growing without bound.
|
|
|
|
|
c.updateBuffer = nil |
|
|
|
|
c.updateLastSent = time.Now() |
|
|
|
|
go flushCoordinates(c, c.updateBuffer) |
|
|
|
|
|
|
|
|
|
if err != nil { |
|
|
|
|
c.srv.logger.Printf("[ERR] consul.coordinate: Update failed: %v", err) |
|
|
|
|
} |
|
|
|
|
}() |
|
|
|
|
} else { |
|
|
|
|
c.updateBufferLock.Unlock() |
|
|
|
|
// We clear the buffer regardless of whether the raft transaction succeeded, just so the
|
|
|
|
|
// buffer doesn't keep growing without bound.
|
|
|
|
|
c.updateLastSent = time.Now() |
|
|
|
|
c.updateBuffer = nil |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return nil |
|
|
|
|