func (m *MapStore) rotateServices(serviceName string) error {
	mod := int32(len(m.services[serviceName]))
	m.muServices.Lock()
	for i, s := range m.services[serviceName] {
		m.services[serviceName][i].Priority = (s.Priority + 1) % mod
	}
	m.muServices.Unlock()
	return nil
}
rotateServices updates service priority
package mapstore
import (
	"errors"
	"fmt"
	"net"
	"regexp"
	"sort"
	"sync"
	"github.com/forestgiant/stela"
)
type MapStore struct {
	services      map[string][]*stela.Service  
	clients       []*stela.Client
	subscribers   map[string][]*stela.Client  
	muServices    sync.RWMutex                
	muSubscribers sync.RWMutex                
	muClients     sync.RWMutex                
}
type byPriority []*stela.Service
func (s byPriority) Len() int           { return len(s) }
func (s byPriority) Swap(i, j int)      { s[i], s[j] = s[j], s[i] }
func (s byPriority) Less(i, j int) bool { return s[i].Priority < s[j].Priority }
func (m *MapStore) init() {
	if m.services == nil {
		m.services = make(map[string][]*stela.Service)
	}
	if m.subscribers == nil {
		m.subscribers = make(map[string][]*stela.Client)
	}
}
func (m *MapStore) Register(s *stela.Service) error {
	if !s.Valid() {
		return fmt.Errorf("%v registered is invalid", s)
	}
	m.init()
	if m.hasService(s) {
		return fmt.Errorf("%v is already registered", s)
	}
	m.rotateServices(s.Name)
	s.Priority = 0
	if err := s.GenerateID(); err != nil {
		return err
	}
	m.muServices.Lock()
	defer m.muServices.Unlock()
	m.services[s.Name] = append([]*stela.Service{s}, m.services[s.Name]...)  
	return nil
}
func (m *MapStore) Deregister(s *stela.Service) *stela.Service {
	m.muServices.Lock()
	defer m.muServices.Unlock()
	services := m.services[s.Name]
	for i := len(services) - 1; i >= 0; i-- {
		rs := services[i]
		if rs.Equal(s) {
			services = append(services[:i], services[i+1:]...)
			if len(services) == 0 {
				delete(m.services, s.Name)
			} else {
				m.services[s.Name] = services
			}
			rs.Action = stela.DeregisterAction
			return rs
		}
	}
	return nil
}
func (m *MapStore) NotifyClients(s *stela.Service) {
	for _, c := range m.subscribers[s.Name] {
		c.Notify(s)
	}
}
func (m *MapStore) Subscribe(serviceName string, c *stela.Client) error {
	if serviceName == "" {
		return errors.New("Unable to subscribe to empty serviceName")
	}
	if c == nil {
		return errors.New("Client must not be nil")
	}
	m.init()
	m.muSubscribers.Lock()
	defer m.muSubscribers.Unlock()
	m.subscribers[serviceName] = append(m.subscribers[serviceName], c)
	return nil
}
func (m *MapStore) Unsubscribe(serviceName string, c *stela.Client) error {
	m.init()
	m.muSubscribers.Lock()
	defer m.muSubscribers.Unlock()
	subscribers := m.subscribers[serviceName]
	for i := len(subscribers) - 1; i >= 0; i-- {
		rc := subscribers[i]
		if c == rc {
			subscribers = append(subscribers[:i], subscribers[i+1:]...)
			if len(subscribers) == 0 {
				delete(m.subscribers, serviceName)
			} else {
				m.subscribers[serviceName] = subscribers
			}
			return nil
		}
	}
	return fmt.Errorf("Client not find in subscriber list: %v", c)
}
func (m *MapStore) Discover(serviceName string) ([]*stela.Service, error) {
	m.muServices.RLock()
	results := m.services[serviceName]
	m.muServices.RUnlock()
	if len(results) == 0 {
		return nil, fmt.Errorf("No services discovered with the service name: %s", serviceName)
	}
	return results, nil
}
func (m *MapStore) DiscoverRegex(reg string) ([]*stela.Service, error) {
	results := []*stela.Service{}
	r, err := regexp.Compile(reg)
	if err != nil {
		return nil, fmt.Errorf("No services discovered with the regex: %s", reg)
	}
	m.muServices.RLock()
	for k, v := range m.services {
		if r.MatchString(k) {
			results = append(results, v...)
		}
	}
	m.muServices.RUnlock()
	if len(results) == 0 {
		return nil, fmt.Errorf("No services discovered with the regex: %s", reg)
	}
	return results, nil
}
func (m *MapStore) DiscoverOne(serviceName string) (*stela.Service, error) {
	services, err := m.Discover(serviceName)
	if err != nil {
		return nil, err
	}
	sort.Sort(byPriority(services))
	s := services[0]
	m.rotateServices(serviceName)
	return s, nil
}
func (m *MapStore) DiscoverAll() []*stela.Service {
	var all []*stela.Service
	m.muServices.RLock()
	for _, v := range m.services {
		all = append(all, v...)
	}
	m.muServices.RUnlock()
	return all
}
func (m *MapStore) AddClient(c *stela.Client) error {
	if ip := net.ParseIP(c.Address); ip == nil {
		return fmt.Errorf("Client has invalid address: %s", c.Address)
	}
	if m.hasClient(c) {
		return errors.New("Client is already registered")
	}
	m.init()
	m.muClients.Lock()
	defer m.muClients.Unlock()
	m.clients = append(m.clients, c)
	if err := c.GenerateID(); err != nil {
		return err
	}
	return nil
}
func (m *MapStore) RemoveClient(c *stela.Client) {
	m.init()
	m.muClients.Lock()
	defer m.muClients.Unlock()
	for i := len(m.clients) - 1; i >= 0; i-- {
		rc := m.clients[i]
		if rc == c {
			m.clients = append(m.clients[:i], m.clients[i+1:]...)
		}
	}
	m.muSubscribers.Lock()
	defer m.muSubscribers.Unlock()
	for k, v := range m.subscribers {
		for i := len(v) - 1; i >= 0; i-- {
			rc := v[i]
			if rc == c {
				v = append(v[:i], v[i+1:]...)
			}
		}
		if len(v) == 0 {
			delete(m.subscribers, k)
		} else {
			m.subscribers[k] = v
		}
	}
}
func (m *MapStore) ServicesByClient(c *stela.Client) []*stela.Service {
	var clientServices []*stela.Service
	m.muServices.RLock()
	for _, services := range m.services {
		for i := len(services) - 1; i >= 0; i-- {
			s := services[i]
			if s == nil || s.Client == nil {
				continue
			}
			if s.Client.Equal(c) {
				clientServices = append(clientServices, s)
			}
		}
	}
	m.muServices.RUnlock()
	return clientServices
}
func (m *MapStore) Client(id string) (*stela.Client, error) {
	m.init()
	m.muClients.Lock()
	defer m.muClients.Unlock()
	for _, c := range m.clients {
		if c.ID == id {
			return c, nil
		}
	}
	return nil, fmt.Errorf("Couldn't find a client from id: %s", id)
}
func (m *MapStore) hasService(s *stela.Service) bool {
	m.init()
	m.muServices.RLock()
	defer m.muServices.RUnlock()
	for _, rs := range m.services[s.Name] {
		if s.Equal(rs) {
			return true  
		}
	}
	return false
}
func (m *MapStore) hasClient(c *stela.Client) bool {
	m.init()
	m.muClients.Lock()
	defer m.muClients.Unlock()
	for _, rc := range m.clients {
		if c.Equal(rc) {
			return true  
		}
	}
	return false
}