func (c *etcdCtx) SetRing(ring torus.Ring) error { oldr, etcdver, err := c.getRing() if err != nil { return err } if oldr.Version() != ring.Version()-1 { return torus.ErrNonSequentialRing } b, err := ring.Marshal() if err != nil { return err } key := MkKey("meta", "the-one-ring") txn := c.etcd.Client.Txn(c.getContext()).If( etcdv3.Compare(etcdv3.Version(key), "=", etcdver), ).Then( etcdv3.OpPut(key, string(b)), ) resp, err := txn.Commit() if err != nil { return err } if resp.Succeeded { return nil } return torus.ErrAgain }
func (e *Etcd) watchRing(r torus.Ring) { ctx, cancel := context.WithCancel(e.getContext()) defer cancel() wch := e.Client.Watch(ctx, MkKey("meta", "the-one-ring")) for resp := range wch { if err := resp.Err(); err != nil { clog.Errorf("error watching ring: %s", err) return } for _, ev := range resp.Events { newRing, err := ring.Unmarshal(ev.Kv.Value) if err != nil { clog.Debugf("corrupted ring: %#v", ev.Kv.Value) clog.Errorf("Failed to unmarshal ring: %s", err) clog.Error("corrupted ring? Continuing with current ring") continue } clog.Infof("got new ring") if r.Version() == newRing.Version() { clog.Warningf("Same ring version: %d", r.Version()) } e.mut.RLock() for _, x := range e.ringListeners { x <- newRing } r = newRing e.mut.RUnlock() } } }
func setRing(cfg torus.Config, r torus.Ring) error { client, err := etcdv3.New(etcdv3.Config{Endpoints: []string{cfg.MetadataAddress}, TLS: cfg.TLS}) if err != nil { return err } defer client.Close() resp, err := client.Get(context.Background(), MkKey("meta", "the-one-ring")) if err != nil { return err } if len(resp.Kvs) == 0 { return torus.ErrNoGlobalMetadata } oldr, err := ring.Unmarshal(resp.Kvs[0].Value) if err != nil { return err } if oldr.Version() != r.Version()-1 { return torus.ErrNonSequentialRing } b, err := r.Marshal() if err != nil { return err } _, err = client.Put(context.Background(), MkKey("meta", "the-one-ring"), string(b)) return err }
func assignData(blocks []torus.BlockRef, r torus.Ring) ClusterState { out := make(map[string][]torus.BlockRef) for _, p := range r.Members() { out[p] = make([]torus.BlockRef, 0) } for _, b := range blocks { peers, err := r.GetPeers(b) if err != nil { fmt.Fprintf(os.Stderr, "error in the ring: %s\n", err) os.Exit(1) } for _, p := range peers.Peers[:peers.Replication] { out[p] = append(out[p], b) } } return out }
func (s *Server) SetRing(ring torus.Ring) error { s.mut.Lock() defer s.mut.Unlock() if ring.Version()-1 != s.ring.Version() { return torus.ErrNonSequentialRing } s.ring = ring for _, c := range s.ringListeners { c <- s.ring } return nil }
func (c ClusterState) Rebalance(oldRing, newRing torus.Ring) (ClusterState, RebalanceStats) { var stats RebalanceStats out := make(map[string][]torus.BlockRef) for _, p := range newRing.Members() { out[p] = make([]torus.BlockRef, 0) } for p, l := range c { for _, ref := range l { newp, err := newRing.GetPeers(ref) newpeers := newp.Peers[:newp.Replication] if err != nil { fmt.Fprintf(os.Stderr, "error in the new ring: %s\n", err) os.Exit(1) } oldp, err := oldRing.GetPeers(ref) oldpeers := oldp.Peers[:oldp.Replication] if err != nil { fmt.Fprintf(os.Stderr, "error in the old ring: %s\n", err) os.Exit(1) } myIndex := oldpeers.IndexAt(p) if newpeers.Has(p) { out[p] = append(out[p], ref) stats.BlocksKept++ } diffpeers := newpeers.AndNot(oldpeers) if myIndex >= len(diffpeers) { // downsizing continue } if myIndex == len(oldpeers)-1 && len(diffpeers) > len(oldpeers) { for i := myIndex; i < len(diffpeers); i++ { p := diffpeers[i] out[p] = append(out[p], ref) stats.BlocksSent++ } } else { p := diffpeers[myIndex] out[p] = append(out[p], ref) stats.BlocksSent++ } } } return out, stats }