func activate(st *store.Store, self string, c *doozer.Client) int64 { w := store.NewWatch(st, calGlob) 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 } w.Stop() return seqn } } for ev := range w.C { // 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 } w.Stop() return seqn } } return 0 }
func mustWait(s *store.Store, n int64) <-chan store.Event { c, err := s.Wait(store.Any, n) if err != nil { panic(err) } return c }
func Clean(s *store.Store, p paxos.Proposer) { timer := timer.New("/session/**", timer.OneSecond, s) for tick := range timer.C { _, cas := s.Get(tick.Path) paxos.Del(p, tick.Path, cas) } }
// This thing keeps track of who is supposed to be in the cluster for every // seqn. It also remembers the network address of every member. // TODO remove the `start` param when store.Get provides a version func NewRegistrar(st *store.Store, start uint64, alpha int) *Registrar { rg := &Registrar{ alpha: alpha, st: st, evs: st.Watch("**"), // watch absolutely everything lookupCh: make(chan *lookup), lookups: new(lookupQueue), } go rg.process(start, readdirMap(st, membersKey), readdirMap(st, slotKey)) return rg }
func Clean(st *store.Store) { cl := &cleaner{ st: st, table: make(map[string]uint64), logger: util.NewLogger("clean"), } for ev := range st.Watch("/doozer/info/*/applied") { cl.update(ev) cl.check() } }
func Clean(c chan string, st *store.Store, p consensus.Proposer) { for addr := range c { _, g := st.Snap() name := getName(addr, g) if name != "" { go func() { clearSlot(p, g, name) removeInfo(p, g, name) }() } } }
func readdirMap(st *store.Store, path string) map[string]string { m := map[string]string{} keys, cas := st.Get(path) if cas != store.Dir { return map[string]string{} } for _, key := range keys { v, cas := st.Get(path + "/" + key) if cas != store.Dir && cas != store.Missing { m[key] = v[0] } } return m }
func Clean(st *store.Store, p paxos.Proposer) { logger := util.NewLogger("member") for ev := range st.Watch("/session/*") { if !ev.IsDel() { continue } parts := strings.Split(ev.Path, "/", 3) name := parts[2] logger.Printf("lost session %s", name) clearSlot(p, ev, name) removeMember(p, ev, name) removeInfo(p, ev, name) } }
func walk(path string, st *store.Store, ch chan store.Event) { for path != "/" && strings.HasSuffix(path, "/") { // TODO generalize and factor this into pkg store. path = path[0 : len(path)-1] } v, rev := st.Get(path) if rev != store.Dir { ch <- store.Event{0, path, v[0], rev, "", nil, nil} return } if path == "/" { path = "" } for _, ent := range v { walk(path+"/"+ent, st, ch) } }
func activate(st *store.Store, self string, c *client.Client, cal chan int) { logger := util.NewLogger("activate") ch := make(chan store.Event) st.GetDirAndWatch("/doozer/slot", ch) for ev := range ch { // TODO ev.IsEmpty() if ev.IsSet() && ev.Body == "" { _, err := c.Set(ev.Path, self, ev.Cas) if err != nil { logger.Println(err) continue } close(cal) close(ch) } } }
func sendLearn(out chan<- Packet, p *packet, st *store.Store) { if p.msg.Cmd != nil && *p.msg.Cmd == msg_INVITE { ch, err := st.Wait(store.Any, *p.Seqn) if err == store.ErrTooLate { log.Println(err) } else { e := <-ch m := msg{ Seqn: &e.Seqn, Cmd: learn, Value: []byte(e.Mut), } buf, _ := proto.Marshal(&m) out <- Packet{p.Addr, buf} } } }
func Clean(st *store.Store, pp paxos.Proposer) { logger := util.NewLogger("lock") for ev := range st.Watch("/session/*") { if !ev.IsDel() { continue } parts := strings.Split(ev.Path, "/", 3) name := parts[2] logger.Printf("lost session %s", name) ch, err := store.Walk(ev, "/lock/**") if err != nil { continue } for ev := range ch { if ev.Body == name { paxos.Del(pp, ev.Path, ev.Cas) } } } }
func generateRuns(rev, alpha int64, st *store.Store, runs chan<- *run, t run) { for { ch, err := st.Wait(store.Any, rev) if err != nil { panic(err) // can't happen } e := <-ch if closed(ch) { break } rev = e.Seqn + 1 r := t r.seqn = e.Seqn + alpha r.cals = getCals(e) r.addrs = getAddrs(e) r.c.size = len(r.cals) r.c.quor = r.quorum() r.c.crnd = r.indexOf(r.self) + int64(len(r.cals)) r.l.init(int64(r.quorum())) runs <- &r } }
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(os.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 Monitor(self string, st *store.Store, cl SetDeler) os.Error { mon := &monitor{ self: self, st: st, cl: cl, clock: make(chan ticker), units: make(map[string]unit), refs: make(map[string]int), exitCh: make(chan exit), readyCh: make(chan ready), logger: util.NewLogger("monitor"), } mon.logger.Println("reading units") evs := make(chan store.Event) st.GetDirAndWatch(ctlKey, evs) go func(c <-chan store.Event) { for e := range c { evs <- e } close(evs) }(st.Watch(lockKey + "/*")) for { select { case t := <-mon.clock: t.tick() case ev := <-evs: prefix, id := path.Split(ev.Path) switch prefix { case ctlDir: if ev.IsDel() { mon.logger.Println("\n\n\ndel", id) mon.decrefUnit(id) break } ut := mon.increfUnit(id) if ut == nil { break } switch ev.Body { case "start": ut.start() case "stop": ut.stop() case "auto", "": fallthrough default: // nothing } case lockDir: ut := mon.units[id] if ut == nil { break } ut.dispatchLockEvent(ev) } case e := <-mon.exitCh: e.e.exited(e.w) case r := <-mon.readyCh: r.r.ready(r.f) } } panic("unreachable") }
func Clean(st *store.Store, keep int64, ticker <-chan time.Time) { for _ = range ticker { last := (<-st.Seqns) - keep st.Clean(last) } }