// Elect chooses a seed node, and returns a connection to a cal. // If this process is the seed, returns nil. func elect(name, id, laddr string, b *doozer.Conn) *doozer.Conn { // advertise our presence, since we might become a cal nspath := "/ctl/ns/" + name + "/" + id r, err := b.Set(nspath, 0, []byte(laddr)) if err != nil { panic(err) } // fight to be the seed _, err = b.Set("/ctl/boot/"+name, 0, []byte(id)) if err, ok := err.(*doozer.Error); ok && err.Err == doozer.ErrOldRev { // we lost, lookup addresses again cl := lookupAndAttach(b, name) if cl == nil { panic("failed to attach after losing election") } // also delete our entry, since we're not officially a cal yet. // it gets set again in peer.Main when we become a cal. err := b.Del(nspath, r) if err != nil { panic(err) } return cl } else if err != nil { panic(err) } return nil // we are the seed node -- don't attach }
// watch updates the peer list of servers based on changes to the // doozer configuration or signals from the OS. func watch(d *doozer.Conn) { peerFile := "/peers" var peers []string var rev int64 // Run the initial get. data, rev, err := d.Get(peerFile, nil) if err != nil { log.Println("initial peer list get:", err) log.Println("using empty set to start") peers = []string{} } else { peers = strings.Split(string(data), " ") } // Add myself to the list. peers = append(peers, "http://"+addr) rev, err = d.Set(peerFile, rev, []byte(strings.Join(peers, " "))) if err != nil { log.Println("unable to add myself to the peer list (no longer watching).") return } pool.Set(peers...) log.Println("added myself to the peer list.") // Setup signal handling to deal with ^C and others. sigs := make(chan os.Signal, 1) signal.Notify(sigs, os.Interrupt, os.Kill) // Get the channel that's listening for changes. updates := wait(d, peerFile, &rev) for { select { case <-sigs: // Remove ourselves from the peer list and exit. for i, peer := range peers { if peer == "http://"+addr { peers = append(peers[:i], peers[i+1:]...) d.Set(peerFile, rev, []byte(strings.Join(peers, " "))) log.Println("removed myself from peer list before exiting.") } } os.Exit(1) case update, ok := <-updates: // If the channel was closed, we should stop selecting on it. if !ok { updates = nil continue } // Otherwise, update the peer list. peers = update log.Println("got new peer list:", strings.Join(peers, " ")) pool.Set(peers...) } } }
func set(cl *doozer.Conn, id, iter int, path string, value []byte, f cb) { for i := 0; i < iter; i++ { s := time.Nanoseconds() rev, err := cl.Set(path, math.MaxInt64, value) e := time.Nanoseconds() f(id, i, rev, s, e, err) } }
func activate(st *store.Store, self string, c *doozer.Conn) int64 { rev, _ := st.Snap() entries := store.Getdir(st, calDir) base := entries[len(entries)-1] index, _ := strconv.ParseInt(base, 10, 32) index += 1 p := calDir + "/" + strconv.Itoa(int(index)) seqn, err := c.Set(p, rev, []byte(self)) if err != nil { panic(err) } // for _, base := range store.Getdir(st, calDir) { // p := calDir + "/" + base // v, rev := st.Get(p) // if rev != store.Dir && v[0] == "" { // seqn, err := c.Set(p, rev, []byte(self)) // if err != nil { // log.Println(err) // continue // } // return seqn // } // } // for { // ch, err := st.Wait(calGlob, rev+1) // if err != nil { // panic(err) // } // ev, ok := <-ch // if !ok { // panic(io.EOF) // } // rev = ev.Rev // // TODO ev.IsEmpty() // if ev.IsSet() && ev.Body == "" { // seqn, err := c.Set(ev.Path, ev.Rev, []byte(self)) // if err != nil { // log.Println(err) // continue // } // return seqn // } else if ev.IsSet() && ev.Body == self { // return ev.Seqn // } // } return seqn }
func activate(st *store.Store, self string, c *doozer.Conn) int64 { rev, _ := st.Snap() for _, base := range store.Getdir(st, calDir) { p := calDir + "/" + base v, rev := st.Get(p) if rev != store.Dir && v[0] == "" { seqn, err := c.Set(p, rev, []byte(self)) if err != nil { log.Println(err) continue } return seqn } } for { ch, err := st.Wait(calGlob, rev+1) if err != nil { panic(err) } ev, ok := <-ch if !ok { panic(io.EOF) } rev = ev.Rev // TODO ev.IsEmpty() if ev.IsSet() && ev.Body == "" { seqn, err := c.Set(ev.Path, ev.Rev, []byte(self)) if err != nil { log.Println(err) continue } return seqn } else if ev.IsSet() && ev.Body == self { return ev.Seqn } } return 0 }
func setC(cl *doozer.Conn, path, body string, rev int64) { _, err := cl.Set(path, rev, []byte(body)) if err != nil { panic(err) } }