converger: Update the API for errors and naming
We updated the API and behaviour to make two changes: 1) We remove the log.* stuff, and replace the Fatal calls with straight calls to panic(). These are meant to be like an assert, and shouldn't happen unless there is a user error or a bug. 2) We made the !uuid.IsValid() checks return an error instead of causing a panic. These returns errors instead, and makes the process safer for users who are okay calling a function that won't have an effect.
This commit is contained in:
45
converger.go
45
converger.go
@@ -18,7 +18,7 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"log"
|
"fmt"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
@@ -27,7 +27,7 @@ import (
|
|||||||
type Converger interface { // TODO: need a better name
|
type Converger interface { // TODO: need a better name
|
||||||
Register() ConvergerUUID
|
Register() ConvergerUUID
|
||||||
IsConverged(ConvergerUUID) bool // is the UUID converged ?
|
IsConverged(ConvergerUUID) bool // is the UUID converged ?
|
||||||
SetConverged(ConvergerUUID, bool) // set the converged state of the UUID
|
SetConverged(ConvergerUUID, bool) error // set the converged state of the UUID
|
||||||
Unregister(ConvergerUUID)
|
Unregister(ConvergerUUID)
|
||||||
Start()
|
Start()
|
||||||
Pause()
|
Pause()
|
||||||
@@ -39,10 +39,12 @@ type Converger interface { // TODO: need a better name
|
|||||||
// you'll need to use part of the Converger interface to Register initially too
|
// you'll need to use part of the Converger interface to Register initially too
|
||||||
type ConvergerUUID interface {
|
type ConvergerUUID interface {
|
||||||
ID() uint64 // get Id
|
ID() uint64 // get Id
|
||||||
|
Name() string // get a friendly name
|
||||||
|
SetName(string)
|
||||||
IsValid() bool // has Id been initialized ?
|
IsValid() bool // has Id been initialized ?
|
||||||
InvalidateID() // set Id to nil
|
InvalidateID() // set Id to nil
|
||||||
IsConverged() bool
|
IsConverged() bool
|
||||||
SetConverged(bool)
|
SetConverged(bool) error
|
||||||
Unregister()
|
Unregister()
|
||||||
ConvergedTimer() <-chan time.Time
|
ConvergedTimer() <-chan time.Time
|
||||||
}
|
}
|
||||||
@@ -62,6 +64,7 @@ type converger struct {
|
|||||||
type convergerUUID struct {
|
type convergerUUID struct {
|
||||||
converger Converger
|
converger Converger
|
||||||
id uint64
|
id uint64
|
||||||
|
name string // user defined, friendly name
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewConverger builds a new converger struct
|
// NewConverger builds a new converger struct
|
||||||
@@ -85,31 +88,32 @@ func (obj *converger) Register() ConvergerUUID {
|
|||||||
return &convergerUUID{
|
return &convergerUUID{
|
||||||
converger: obj,
|
converger: obj,
|
||||||
id: obj.lastid,
|
id: obj.lastid,
|
||||||
|
name: fmt.Sprintf("%d", obj.lastid), // some default
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsConverged gets the converged status of a uuid
|
// IsConverged gets the converged status of a uuid
|
||||||
func (obj *converger) IsConverged(uuid ConvergerUUID) bool {
|
func (obj *converger) IsConverged(uuid ConvergerUUID) bool {
|
||||||
if !uuid.IsValid() {
|
if !uuid.IsValid() {
|
||||||
log.Fatal("Id of ConvergerUUID is nil!")
|
panic(fmt.Sprintf("Id of ConvergerUUID(%s) is nil!", uuid.Name()))
|
||||||
}
|
}
|
||||||
obj.mutex.RLock()
|
obj.mutex.RLock()
|
||||||
isConverged, found := obj.status[uuid.ID()] // lookup
|
isConverged, found := obj.status[uuid.ID()] // lookup
|
||||||
obj.mutex.RUnlock()
|
obj.mutex.RUnlock()
|
||||||
if !found {
|
if !found {
|
||||||
log.Fatal("Id of ConvergerUUID is unregistered!")
|
panic("Id of ConvergerUUID is unregistered!")
|
||||||
}
|
}
|
||||||
return isConverged
|
return isConverged
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetConverged updates the converger with the converged state of the UUID
|
// SetConverged updates the converger with the converged state of the UUID
|
||||||
func (obj *converger) SetConverged(uuid ConvergerUUID, isConverged bool) {
|
func (obj *converger) SetConverged(uuid ConvergerUUID, isConverged bool) error {
|
||||||
if !uuid.IsValid() {
|
if !uuid.IsValid() {
|
||||||
log.Fatal("Id of ConvergerUUID is nil!")
|
return fmt.Errorf("Id of ConvergerUUID(%s) is nil!", uuid.Name())
|
||||||
}
|
}
|
||||||
obj.mutex.Lock()
|
obj.mutex.Lock()
|
||||||
if _, found := obj.status[uuid.ID()]; !found {
|
if _, found := obj.status[uuid.ID()]; !found {
|
||||||
log.Fatal("Id of ConvergerUUID is unregistered!")
|
panic("Id of ConvergerUUID is unregistered!")
|
||||||
}
|
}
|
||||||
obj.status[uuid.ID()] = isConverged // set
|
obj.status[uuid.ID()] = isConverged // set
|
||||||
obj.mutex.Unlock() // unlock *before* poke or deadlock!
|
obj.mutex.Unlock() // unlock *before* poke or deadlock!
|
||||||
@@ -118,6 +122,7 @@ func (obj *converger) SetConverged(uuid ConvergerUUID, isConverged bool) {
|
|||||||
// this allows us to send events, even if we haven't started...
|
// this allows us to send events, even if we haven't started...
|
||||||
go func() { obj.channel <- struct{}{} }()
|
go func() { obj.channel <- struct{}{} }()
|
||||||
}
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// isConverged returns true if *every* registered uuid has converged
|
// isConverged returns true if *every* registered uuid has converged
|
||||||
@@ -135,7 +140,7 @@ func (obj *converger) isConverged() bool {
|
|||||||
// Unregister dissociates the ConvergedUUID from the converged checking
|
// Unregister dissociates the ConvergedUUID from the converged checking
|
||||||
func (obj *converger) Unregister(uuid ConvergerUUID) {
|
func (obj *converger) Unregister(uuid ConvergerUUID) {
|
||||||
if !uuid.IsValid() {
|
if !uuid.IsValid() {
|
||||||
log.Fatal("Id of ConvergerUUID is nil!")
|
panic(fmt.Sprintf("Id of ConvergerUUID(%s) is nil!", uuid.Name()))
|
||||||
}
|
}
|
||||||
obj.mutex.Lock()
|
obj.mutex.Lock()
|
||||||
delete(obj.status, uuid.ID())
|
delete(obj.status, uuid.ID())
|
||||||
@@ -160,13 +165,13 @@ func (obj *converger) Pause() { // FIXME: add a sync ACK on pause before return
|
|||||||
// have joined the map, then it might appears as if we converged before we did!
|
// have joined the map, then it might appears as if we converged before we did!
|
||||||
func (obj *converger) Loop(startPaused bool) {
|
func (obj *converger) Loop(startPaused bool) {
|
||||||
if obj.control == nil {
|
if obj.control == nil {
|
||||||
log.Fatal("Converger not initialized correctly")
|
panic("Converger not initialized correctly")
|
||||||
}
|
}
|
||||||
if startPaused { // start paused without racing
|
if startPaused { // start paused without racing
|
||||||
select {
|
select {
|
||||||
case e := <-obj.control:
|
case e := <-obj.control:
|
||||||
if !e {
|
if !e {
|
||||||
log.Fatal("Converger expected true!")
|
panic("Converger expected true!")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -174,13 +179,13 @@ func (obj *converger) Loop(startPaused bool) {
|
|||||||
select {
|
select {
|
||||||
case e := <-obj.control: // expecting "false" which means pause!
|
case e := <-obj.control: // expecting "false" which means pause!
|
||||||
if e {
|
if e {
|
||||||
log.Fatal("Converger expected false!")
|
panic("Converger expected false!")
|
||||||
}
|
}
|
||||||
// now i'm paused...
|
// now i'm paused...
|
||||||
select {
|
select {
|
||||||
case e := <-obj.control:
|
case e := <-obj.control:
|
||||||
if !e {
|
if !e {
|
||||||
log.Fatal("Converger expected true!")
|
panic("Converger expected true!")
|
||||||
}
|
}
|
||||||
// restart
|
// restart
|
||||||
// kick once to refresh the check...
|
// kick once to refresh the check...
|
||||||
@@ -230,6 +235,16 @@ func (obj *convergerUUID) ID() uint64 {
|
|||||||
return obj.id
|
return obj.id
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Name returns a user defined name for the specific convergerUUID.
|
||||||
|
func (obj *convergerUUID) Name() string {
|
||||||
|
return obj.name
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetName sets a user defined name for the specific convergerUUID.
|
||||||
|
func (obj *convergerUUID) SetName(name string) {
|
||||||
|
obj.name = name
|
||||||
|
}
|
||||||
|
|
||||||
// IsValid tells us if the id is valid or has already been destroyed
|
// IsValid tells us if the id is valid or has already been destroyed
|
||||||
func (obj *convergerUUID) IsValid() bool {
|
func (obj *convergerUUID) IsValid() bool {
|
||||||
return obj.id != 0 // an id of 0 is invalid
|
return obj.id != 0 // an id of 0 is invalid
|
||||||
@@ -246,8 +261,8 @@ func (obj *convergerUUID) IsConverged() bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// SetConverged is a helper function to the regular SetConverged notification
|
// SetConverged is a helper function to the regular SetConverged notification
|
||||||
func (obj *convergerUUID) SetConverged(isConverged bool) {
|
func (obj *convergerUUID) SetConverged(isConverged bool) error {
|
||||||
obj.converger.SetConverged(obj, isConverged)
|
return obj.converger.SetConverged(obj, isConverged)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Unregister is a helper function to unregister myself
|
// Unregister is a helper function to unregister myself
|
||||||
|
|||||||
2
etcd.go
2
etcd.go
@@ -678,6 +678,7 @@ func (obj *EmbdEtcd) CtxError(ctx context.Context, err error) (context.Context,
|
|||||||
// CbLoop is the loop where callback execution is serialized
|
// CbLoop is the loop where callback execution is serialized
|
||||||
func (obj *EmbdEtcd) CbLoop() {
|
func (obj *EmbdEtcd) CbLoop() {
|
||||||
cuuid := obj.converger.Register()
|
cuuid := obj.converger.Register()
|
||||||
|
cuuid.SetName("Etcd: CbLoop")
|
||||||
defer cuuid.Unregister()
|
defer cuuid.Unregister()
|
||||||
if e := obj.Connect(false); e != nil {
|
if e := obj.Connect(false); e != nil {
|
||||||
return // fatal
|
return // fatal
|
||||||
@@ -731,6 +732,7 @@ func (obj *EmbdEtcd) CbLoop() {
|
|||||||
// Loop is the main loop where everything is serialized
|
// Loop is the main loop where everything is serialized
|
||||||
func (obj *EmbdEtcd) Loop() {
|
func (obj *EmbdEtcd) Loop() {
|
||||||
cuuid := obj.converger.Register()
|
cuuid := obj.converger.Register()
|
||||||
|
cuuid.SetName("Etcd: Loop")
|
||||||
defer cuuid.Unregister()
|
defer cuuid.Unregister()
|
||||||
if e := obj.Connect(false); e != nil {
|
if e := obj.Connect(false); e != nil {
|
||||||
return // fatal
|
return // fatal
|
||||||
|
|||||||
Reference in New Issue
Block a user