func evServer(w http.ResponseWriter, r *http.Request) { wevs := make(chan store.Event) path := r.URL.Path[len("/$events"):] glob, err := store.CompileGlob(path + "**") if err != nil { w.WriteHeader(400) return } rev, _ := Store.Snap() go func() { walk(path, Store, wevs) for { ch, err := Store.Wait(glob, rev+1) if err != nil { break } ev, ok := <-ch if !ok { break } wevs <- ev rev = ev.Rev } close(wevs) }() websocket.Handler(func(ws *websocket.Conn) { send(ws, path, wevs) ws.Close() }).ServeHTTP(w, r) }
func (c *conn) walk(t *T, tx txn) { pat := pb.GetString(t.Path) glob, err := store.CompileGlob(pat) if err != nil { c.respond(t, Valid|Done, nil, errResponse(err)) return } offset := pb.GetInt32(t.Offset) if offset < 0 { c.respond(t, Valid|Done, nil, erange) return } if g := c.getterFor(t); g != nil { var r R f := func(path, body string, rev int64) (stop bool) { if offset == 0 { r.Path = &path r.Value = []byte(body) r.Rev = &rev return true } offset-- return false } if store.Walk(g, glob, f) { c.respond(t, Set|Valid|Done, nil, &r) } else { c.respond(t, Valid|Done, nil, erange) } } }
func (c *conn) watch(t *T, tx txn) { pat := pb.GetString(t.Path) glob, err := store.CompileGlob(pat) if err != nil { c.respond(t, Valid|Done, nil, errResponse(err)) return } var w *store.Watch rev := pb.GetInt64(t.Rev) if rev == 0 { w, err = store.NewWatch(c.s.St, glob), nil } else { w, err = store.NewWatchFrom(c.s.St, glob, rev) } switch err { case nil: // nothing case store.ErrTooLate: c.respond(t, Valid|Done, nil, tooLate) default: c.respond(t, Valid|Done, nil, errResponse(err)) } go func() { defer w.Stop() // TODO buffer (and possibly discard) events for { select { case ev := <-w.C: if closed(w.C) { return } r := R{ Path: &ev.Path, Value: []byte(ev.Body), Rev: &ev.Seqn, } var flag int32 switch { case ev.IsSet(): flag = Set case ev.IsDel(): flag = Del } c.respond(t, Valid|flag, tx.cancel, &r) case <-tx.cancel: c.closeTxn(*t.Tag) return } } }() }
func removeInfo(p consensus.Proposer, g store.Getter, name string) { glob, err := store.CompileGlob("/ctl/node/" + name + "/**") if err != nil { log.Println(err) return } store.Walk(g, glob, func(path, _ string, rev int64) bool { consensus.Del(p, path, rev) return false }) }
func (t *txn) walk() { if t.c.access == false { t.respondOsError(os.EACCES) return } if t.req.Path == nil || t.req.Offset == nil { t.respondErrCode(response_MISSING_ARG) return } glob, err := store.CompileGlob(*t.req.Path) if err != nil { t.respondOsError(err) return } offset := *t.req.Offset if offset < 0 { t.respondErrCode(response_RANGE) return } go func() { g, err := t.getter() if err != nil { t.respondOsError(err) return } f := func(path, body string, rev int64) (stop bool) { if offset == 0 { t.resp.Path = &path t.resp.Value = []byte(body) t.resp.Rev = &rev t.resp.Flags = proto.Int32(set) t.respond() return true } offset-- return false } if !store.Walk(g, glob, f) { t.respondErrCode(response_RANGE) } }() }
func (c *conn) walk(t *T, tx txn) { pat := pb.GetString(t.Path) glob, err := store.CompileGlob(pat) if err != nil { c.respond(t, Valid|Done, nil, errResponse(err)) return } offset := pb.GetInt32(t.Offset) var limit int32 = math.MaxInt32 if t.Limit != nil { limit = pb.GetInt32(t.Limit) } if g := c.getterFor(t); g != nil { go func() { f := func(path, body string, rev int64) (stop bool) { select { case <-tx.cancel: c.closeTxn(*t.Tag) return true default: } if offset <= 0 && limit > 0 { var r R r.Path = &path r.Value = []byte(body) r.Rev = &rev c.respond(t, Valid|Set, tx.cancel, &r) limit-- } offset-- return false } stopped := store.Walk(g, glob, f) if !stopped { c.respond(t, Done, nil, &R{}) } }() } }
func (c *conn) wait(t *T, tx txn) { pat := pb.GetString(t.Path) glob, err := store.CompileGlob(pat) if err != nil { c.respond(t, Valid|Done, nil, errResponse(err)) return } var w *store.Watch rev := pb.GetInt64(t.Rev) if rev == 0 { w, err = store.NewWatch(c.s.St, glob), nil } else { w, err = store.NewWatchFrom(c.s.St, glob, rev) } switch err { case nil: // nothing case store.ErrTooLate: c.respond(t, Valid|Done, nil, tooLate) default: c.respond(t, Valid|Done, nil, errResponse(err)) } go func() { defer w.Stop() ev := <-w.C r := R{ Path: &ev.Path, Value: []byte(ev.Body), Rev: &ev.Seqn, } var flag int32 switch { case ev.IsSet(): flag = Set case ev.IsDel(): flag = Del } c.respond(t, Valid|flag, nil, &r) }() }
func (t *txn) wait() { if t.c.access == false { t.respondOsError(os.EACCES) return } if t.req.Path == nil || t.req.Rev == nil { t.respondErrCode(response_MISSING_ARG) return } glob, err := store.CompileGlob(*t.req.Path) if err != nil { t.respondOsError(err) return } ch, err := t.c.st.Wait(glob, *t.req.Rev) if err != nil { t.respondOsError(err) return } go func() { ev := <-ch t.resp.Path = &ev.Path t.resp.Value = []byte(ev.Body) t.resp.Rev = &ev.Seqn switch { case ev.IsSet(): t.resp.Flags = proto.Int32(set) case ev.IsDel(): t.resp.Flags = proto.Int32(del) default: t.resp.Flags = proto.Int32(0) } t.respond() }() }
func evServer(w http.ResponseWriter, r *http.Request) { wevs := make(chan store.Event) path := r.URL.Path[len("/$events"):] glob, err := store.CompileGlob(path + "**") if err != nil { w.WriteHeader(400) return } wt := store.NewWatch(Store, glob) go func() { walk(path, Store, wevs) close(wevs) }() websocket.Handler(func(ws *websocket.Conn) { send(ws, path, wevs) send(ws, path, wt.C) wt.Stop() ws.Close() }).ServeHTTP(w, r) }