func (m *Memberlist) probe() {
	numCheck := 0
START:
	m.nodeLock.RLock()
	if numCheck >= len(m.nodes) {
		m.nodeLock.RUnlock()
		return
	}
	if m.probeIndex >= len(m.nodes) {
		m.nodeLock.RUnlock()
		m.resetNodes()
		m.probeIndex = 0
		numCheck++
		goto START
	}
	skip := false
	var node nodeState
	node = *m.nodes[m.probeIndex]
	if node.Name == m.config.Name {
		skip = true
	} else if node.State == stateDead {
		skip = true
	}
	m.nodeLock.RUnlock()
	m.probeIndex++
	if skip {
		numCheck++
		goto START
	}
	m.probeNode(&node)
}
Tick is used to perform a single round of failure detection and gossip
package memberlist
import (
	"bytes"
	"fmt"
	"math"
	"math/rand"
	"net"
	"sync/atomic"
	"time"
	"github.com/socketplane/socketplane/Godeps/_workspace/src/github.com/armon/go-metrics"
)
type nodeStateType int
const (
	stateAlive nodeStateType = iota
	stateSuspect
	stateDead
)
type Node struct {
	Name string
	Addr net.IP
	Port uint16
	Meta []byte  
	PMin uint8   
	PMax uint8   
	PCur uint8   
	DMin uint8   
	DMax uint8   
	DCur uint8   
}
type nodeState struct {
	Node
	Incarnation uint32         
	State       nodeStateType  
	StateChange time.Time      
}
type ackHandler struct {
	handler func()
	timer   *time.Timer
}
func (m *Memberlist) schedule() {
	m.tickerLock.Lock()
	defer m.tickerLock.Unlock()
	if len(m.tickers) > 0 {
		return
	}
	stopCh := make(chan struct{})
	if m.config.ProbeInterval > 0 {
		t := time.NewTicker(m.config.ProbeInterval)
		go m.triggerFunc(m.config.ProbeInterval, t.C, stopCh, m.probe)
		m.tickers = append(m.tickers, t)
	}
	if m.config.PushPullInterval > 0 {
		go m.pushPullTrigger(stopCh)
	}
	if m.config.GossipInterval > 0 && m.config.GossipNodes > 0 {
		t := time.NewTicker(m.config.GossipInterval)
		go m.triggerFunc(m.config.GossipInterval, t.C, stopCh, m.gossip)
		m.tickers = append(m.tickers, t)
	}
	if len(m.tickers) > 0 {
		m.stopTick = stopCh
	}
}
func (m *Memberlist) triggerFunc(stagger time.Duration, C <-chan time.Time, stop <-chan struct{}, f func()) {
	randStagger := time.Duration(uint64(rand.Int63()) % uint64(stagger))
	select {
	case <-time.After(randStagger):
	case <-stop:
		return
	}
	for {
		select {
		case <-C:
			f()
		case <-stop:
			return
		}
	}
}
func (m *Memberlist) pushPullTrigger(stop <-chan struct{}) {
	interval := m.config.PushPullInterval
	randStagger := time.Duration(uint64(rand.Int63()) % uint64(interval))
	select {
	case <-time.After(randStagger):
	case <-stop:
		return
	}
	for {
		m.nodeLock.RLock()
		tickTime := pushPullScale(interval, len(m.nodes))
		m.nodeLock.RUnlock()
		select {
		case <-time.After(tickTime):
			m.pushPull()
		case <-stop:
			return
		}
	}
}
func (m *Memberlist) deschedule() {
	m.tickerLock.Lock()
	defer m.tickerLock.Unlock()
	if len(m.tickers) == 0 {
		return
	}
	close(m.stopTick)
	for _, t := range m.tickers {
		t.Stop()
	}
	m.tickers = nil
}