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