1package gocql
2
3import (
4	"sync"
5	"sync/atomic"
6)
7
8type ring struct {
9	// endpoints are the set of endpoints which the driver will attempt to connect
10	// to in the case it can not reach any of its hosts. They are also used to boot
11	// strap the initial connection.
12	endpoints []string
13
14	// hosts are the set of all hosts in the cassandra ring that we know of
15	mu    sync.RWMutex
16	hosts map[string]*HostInfo
17
18	hostList []*HostInfo
19	pos      uint32
20
21	// TODO: we should store the ring metadata here also.
22}
23
24func (r *ring) rrHost() *HostInfo {
25	// TODO: should we filter hosts that get used here? These hosts will be used
26	// for the control connection, should we also provide an iterator?
27	r.mu.RLock()
28	defer r.mu.RUnlock()
29	if len(r.hostList) == 0 {
30		return nil
31	}
32
33	pos := int(atomic.AddUint32(&r.pos, 1) - 1)
34	return r.hostList[pos%len(r.hostList)]
35}
36
37func (r *ring) getHost(addr string) *HostInfo {
38	r.mu.RLock()
39	host := r.hosts[addr]
40	r.mu.RUnlock()
41	return host
42}
43
44func (r *ring) allHosts() []*HostInfo {
45	r.mu.RLock()
46	hosts := make([]*HostInfo, 0, len(r.hosts))
47	for _, host := range r.hosts {
48		hosts = append(hosts, host)
49	}
50	r.mu.RUnlock()
51	return hosts
52}
53
54func (r *ring) addHost(host *HostInfo) bool {
55	r.mu.Lock()
56	if r.hosts == nil {
57		r.hosts = make(map[string]*HostInfo)
58	}
59
60	addr := host.Peer()
61	_, ok := r.hosts[addr]
62	r.hosts[addr] = host
63	r.mu.Unlock()
64	return ok
65}
66
67func (r *ring) addHostIfMissing(host *HostInfo) (*HostInfo, bool) {
68	r.mu.Lock()
69	if r.hosts == nil {
70		r.hosts = make(map[string]*HostInfo)
71	}
72
73	addr := host.Peer()
74	existing, ok := r.hosts[addr]
75	if !ok {
76		r.hosts[addr] = host
77		existing = host
78	}
79	r.mu.Unlock()
80	return existing, ok
81}
82
83func (r *ring) removeHost(addr string) bool {
84	r.mu.Lock()
85	if r.hosts == nil {
86		r.hosts = make(map[string]*HostInfo)
87	}
88
89	_, ok := r.hosts[addr]
90	delete(r.hosts, addr)
91	r.mu.Unlock()
92	return ok
93}
94
95type clusterMetadata struct {
96	mu          sync.RWMutex
97	partitioner string
98}
99
100func (c *clusterMetadata) setPartitioner(partitioner string) {
101	c.mu.RLock()
102	defer c.mu.RUnlock()
103
104	if c.partitioner != partitioner {
105		// TODO: update other things now
106		c.partitioner = partitioner
107	}
108}
109