func (l *localState) deleteService(id string) error {
	req := structs.DeregisterRequest{
		Datacenter:   l.config.Datacenter,
		Node:         l.config.NodeName,
		ServiceID:    id,
		WriteRequest: structs.WriteRequest{Token: l.config.ACLToken},
	}
	var out struct{}
	err := l.iface.RPC("Catalog.Deregister", &req, &out)
	if err == nil {
		delete(l.serviceStatus, id)
		l.logger.Printf("[INFO] agent: Deregistered service '%s'", id)
	}
	return err
}
deleteService is used to delete a service from the server
package agent
import (
	"log"
	"reflect"
	"strings"
	"sync"
	"sync/atomic"
	"time"
	"github.com/socketplane/socketplane/Godeps/_workspace/src/github.com/hashicorp/consul/consul"
	"github.com/socketplane/socketplane/Godeps/_workspace/src/github.com/hashicorp/consul/consul/structs"
)
const (
	syncStaggerIntv = 3 * time.Second
	syncRetryIntv   = 15 * time.Second
	permissionDenied = "Permission denied"
)
type syncStatus struct {
	remoteDelete bool  
	inSync       bool  
}
type localState struct {
	paused int32
	sync.Mutex
	logger *log.Logger
	config *Config
	iface consul.Interface
	services      map[string]*structs.NodeService
	serviceStatus map[string]syncStatus
	checks      map[string]*structs.HealthCheck
	checkStatus map[string]syncStatus
	deferCheck map[string]*time.Timer
	consulCh chan struct{}
	triggerCh chan struct{}
}
func (l *localState) Init(config *Config, logger *log.Logger) {
	l.config = config
	l.logger = logger
	l.services = make(map[string]*structs.NodeService)
	l.serviceStatus = make(map[string]syncStatus)
	l.checks = make(map[string]*structs.HealthCheck)
	l.checkStatus = make(map[string]syncStatus)
	l.deferCheck = make(map[string]*time.Timer)
	l.consulCh = make(chan struct{}, 1)
	l.triggerCh = make(chan struct{}, 1)
}
func (l *localState) SetIface(iface consul.Interface) {
	l.iface = iface
}
func (l *localState) changeMade() {
	select {
	case l.triggerCh <- struct{}{}:
	default:
	}
}
func (l *localState) ConsulServerUp() {
	select {
	case l.consulCh <- struct{}{}:
	default:
	}
}
func (l *localState) Pause() {
	atomic.StoreInt32(&l.paused, 1)
}
func (l *localState) Resume() {
	atomic.StoreInt32(&l.paused, 0)
	l.changeMade()
}
func (l *localState) isPaused() bool {
	return atomic.LoadInt32(&l.paused) == 1
}
func (l *localState) AddService(service *structs.NodeService) {
	if service.ID == "" && service.Service != "" {
		service.ID = service.Service
	}
	l.Lock()
	defer l.Unlock()
	l.services[service.ID] = service
	l.serviceStatus[service.ID] = syncStatus{}
	l.changeMade()
}
func (l *localState) RemoveService(serviceID string) {
	l.Lock()
	defer l.Unlock()
	delete(l.services, serviceID)
	l.serviceStatus[serviceID] = syncStatus{remoteDelete: true}
	l.changeMade()
}
func (l *localState) Services() map[string]*structs.NodeService {
	services := make(map[string]*structs.NodeService)
	l.Lock()
	defer l.Unlock()
	for name, serv := range l.services {
		services[name] = serv
	}
	return services
}
func (l *localState) AddCheck(check *structs.HealthCheck) {
	check.Node = l.config.NodeName
	l.Lock()
	defer l.Unlock()
	l.checks[check.CheckID] = check
	l.checkStatus[check.CheckID] = syncStatus{}
	l.changeMade()
}
func (l *localState) RemoveCheck(checkID string) {
	l.Lock()
	defer l.Unlock()
	delete(l.checks, checkID)
	l.checkStatus[checkID] = syncStatus{remoteDelete: true}
	l.changeMade()
}
func (l *localState) UpdateCheck(checkID, status, output string) {
	l.Lock()
	defer l.Unlock()
	check, ok := l.checks[checkID]
	if !ok {
		return
	}
	if check.Status == status && check.Output == output {
		return
	}
	if l.config.CheckUpdateInterval > 0 && check.Status == status {
		check.Output = output
		if _, ok := l.deferCheck[checkID]; !ok {
			deferSync := time.AfterFunc(l.config.CheckUpdateInterval, func() {
				l.Lock()
				if _, ok := l.checkStatus[checkID]; ok {
					l.checkStatus[checkID] = syncStatus{inSync: false}
					l.changeMade()
				}
				delete(l.deferCheck, checkID)
				l.Unlock()
			})
			l.deferCheck[checkID] = deferSync
		}
		return
	}
	check.Status = status
	check.Output = output
	l.checkStatus[checkID] = syncStatus{inSync: false}
	l.changeMade()
}
func (l *localState) Checks() map[string]*structs.HealthCheck {
	checks := make(map[string]*structs.HealthCheck)
	l.Lock()
	defer l.Unlock()
	for name, check := range l.checks {
		checks[name] = check
	}
	return checks
}
func (l *localState) antiEntropy(shutdownCh chan struct{}) {
SYNC:
	for {
		err := l.setSyncState()
		if err == nil {
			break
		}
		l.logger.Printf("[ERR] agent: failed to sync remote state: %v", err)
		select {
		case <-l.consulCh:
			select {
			case <-time.After(randomStagger(aeScale(syncStaggerIntv, len(l.iface.LANMembers())))):
			case <-shutdownCh:
				return
			}
		case <-time.After(syncRetryIntv + randomStagger(aeScale(syncRetryIntv, len(l.iface.LANMembers())))):
		case <-shutdownCh:
			return
		}
	}
	l.changeMade()
	aeIntv := aeScale(l.config.AEInterval, len(l.iface.LANMembers()))
	aeIntv = aeIntv + randomStagger(aeIntv)
	aeTimer := time.After(aeIntv)
	for {
		select {
		case <-aeTimer:
			goto SYNC
		case <-l.triggerCh:
			if l.isPaused() {
				continue
			}
			if err := l.syncChanges(); err != nil {
				l.logger.Printf("[ERR] agent: failed to sync changes: %v", err)
			}
		case <-shutdownCh:
			return
		}
	}
}
func (l *localState) setSyncState() error {
	req := structs.NodeSpecificRequest{
		Datacenter:   l.config.Datacenter,
		Node:         l.config.NodeName,
		QueryOptions: structs.QueryOptions{Token: l.config.ACLToken},
	}
	var out1 structs.IndexedNodeServices
	var out2 structs.IndexedHealthChecks
	if e := l.iface.RPC("Catalog.NodeServices", &req, &out1); e != nil {
		return e
	}
	if err := l.iface.RPC("Health.NodeChecks", &req, &out2); err != nil {
		return err
	}
	services := out1.NodeServices
	checks := out2.HealthChecks
	l.Lock()
	defer l.Unlock()
	if services != nil {
		for id, service := range services.Services {
			existing, ok := l.services[id]
			if !ok {
				l.serviceStatus[id] = syncStatus{remoteDelete: true}
				continue
			}
			equal := reflect.DeepEqual(existing, service)
			l.serviceStatus[id] = syncStatus{inSync: equal}
		}
	}
	for _, check := range checks {
		id := check.CheckID
		existing, ok := l.checks[id]
		if !ok {
			if id == consul.SerfCheckID {
				continue
			}
			l.checkStatus[id] = syncStatus{remoteDelete: true}
			continue
		}
		var equal bool
		if l.config.CheckUpdateInterval == 0 {
			equal = reflect.DeepEqual(existing, check)
		} else {
			eCopy := new(structs.HealthCheck)
			*eCopy = *existing
			eCopy.Output = ""
			check.Output = ""
			equal = reflect.DeepEqual(eCopy, check)
		}
		l.checkStatus[id] = syncStatus{inSync: equal}
	}
	return nil
}
func (l *localState) syncChanges() error {
	l.Lock()
	defer l.Unlock()
	for id, status := range l.serviceStatus {
		if status.remoteDelete {
			if err := l.deleteService(id); err != nil {
				return err
			}
		} else if !status.inSync {
			if err := l.syncService(id); err != nil {
				return err
			}
		} else {
			l.logger.Printf("[DEBUG] agent: Service '%s' in sync", id)
		}
	}
	for id, status := range l.checkStatus {
		if status.remoteDelete {
			if err := l.deleteCheck(id); err != nil {
				return err
			}
		} else if !status.inSync {
			if timer := l.deferCheck[id]; timer != nil {
				timer.Stop()
				delete(l.deferCheck, id)
			}
			if err := l.syncCheck(id); err != nil {
				return err
			}
		} else {
			l.logger.Printf("[DEBUG] agent: Check '%s' in sync", id)
		}
	}
	return nil
}