-
Notifications
You must be signed in to change notification settings - Fork 620
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
raft: synchronous raft conf change, safeguard on join/leave raft #131
Changes from all commits
8af45c4
a8dbe8b
5999967
637853e
2963dc7
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -6,56 +6,99 @@ import ( | |
"github.com/docker/swarm-v2/api" | ||
) | ||
|
||
// Cluster represents a set of active | ||
// Cluster represents a raft cluster | ||
type Cluster interface { | ||
// ID returns the cluster ID | ||
ID() uint64 | ||
// Members returns a map of members identified by their raft ID | ||
Members() map[uint64]*Member | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't think that map can be sorted. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think this is just a confusing description. It should say "indexed by their ID". There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think it's better to return slice here to encourage a user to use it only for iteration and use |
||
// AddMember adds a member to the cluster memberlist | ||
AddMember(*Member) error | ||
// RemoveMember removes a member from the memberlist and add | ||
// it to the remove set | ||
RemoveMember(uint64) error | ||
// Member retrieves a particular member based on ID, or nil if the | ||
// member does not exist in the cluster | ||
GetMember(id uint64) *Member | ||
// IsIDRemoved checks whether the given ID has been removed from this | ||
// cluster at some point in the past | ||
IsIDRemoved(id uint64) bool | ||
} | ||
|
||
// cluster represents a set of active | ||
// raft members | ||
type Cluster struct { | ||
lock sync.RWMutex | ||
peers map[uint64]*Peer | ||
type cluster struct { | ||
id uint64 | ||
|
||
mu sync.RWMutex | ||
members map[uint64]*Member | ||
|
||
// removed contains the list of removed members, | ||
// those ids cannot be reused | ||
removed map[uint64]bool | ||
} | ||
|
||
// Peer represents a raft cluster peer | ||
type Peer struct { | ||
// Member represents a raft cluster member | ||
type Member struct { | ||
*api.RaftNode | ||
|
||
Client *Raft | ||
} | ||
|
||
// NewCluster creates a new cluster neighbors | ||
// list for a raft member | ||
func NewCluster() *Cluster { | ||
return &Cluster{ | ||
peers: make(map[uint64]*Peer), | ||
func NewCluster() Cluster { | ||
// TODO generate cluster ID | ||
|
||
return &cluster{ | ||
members: make(map[uint64]*Member), | ||
removed: make(map[uint64]bool), | ||
} | ||
} | ||
|
||
// Peers returns the list of peers in the cluster | ||
func (c *Cluster) Peers() map[uint64]*Peer { | ||
peers := make(map[uint64]*Peer) | ||
c.lock.RLock() | ||
for k, v := range c.peers { | ||
peers[k] = v | ||
func (c *cluster) ID() uint64 { | ||
return c.id | ||
} | ||
|
||
// Members returns the list of raft members in the cluster | ||
func (c *cluster) Members() map[uint64]*Member { | ||
members := make(map[uint64]*Member) | ||
c.mu.RLock() | ||
for k, v := range c.members { | ||
members[k] = v | ||
} | ||
c.lock.RUnlock() | ||
return peers | ||
c.mu.RUnlock() | ||
return members | ||
} | ||
|
||
// GetMember returns informations on a given member | ||
func (c *cluster) GetMember(id uint64) *Member { | ||
c.mu.RLock() | ||
defer c.mu.RUnlock() | ||
return c.members[id] | ||
} | ||
|
||
// GetPeer returns informations on a given peer | ||
func (c *Cluster) GetPeer(id uint64) *Peer { | ||
c.lock.RLock() | ||
defer c.lock.RUnlock() | ||
return c.peers[id] | ||
// AddMember adds a node to the cluster memberlist | ||
func (c *cluster) AddMember(member *Member) error { | ||
c.mu.Lock() | ||
defer c.mu.Unlock() | ||
c.members[member.ID] = member | ||
return nil | ||
} | ||
|
||
// AddPeer adds a node to our neighbors | ||
func (c *Cluster) AddPeer(peer *Peer) { | ||
c.lock.Lock() | ||
c.peers[peer.ID] = peer | ||
c.lock.Unlock() | ||
// RemoveMember removes a node from the cluster memberlist | ||
func (c *cluster) RemoveMember(id uint64) error { | ||
c.mu.Lock() | ||
defer c.mu.Unlock() | ||
c.members[id].Client.Conn.Close() | ||
c.removed[id] = true | ||
delete(c.members, id) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We should call |
||
return nil | ||
} | ||
|
||
// RemovePeer removes a node from our neighbors | ||
func (c *Cluster) RemovePeer(id uint64) { | ||
c.lock.Lock() | ||
delete(c.peers, id) | ||
c.lock.Unlock() | ||
// IsIDRemoved checks if a member is in the remove set | ||
func (c *cluster) IsIDRemoved(id uint64) bool { | ||
c.mu.RLock() | ||
defer c.mu.RUnlock() | ||
return c.removed[id] | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why not defined these methods directly on the struct? Is there a plan to support multiple implementations of this interface?