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.Seqn } close(wevs) }() websocket.Handler(func(ws *websocket.Conn) { send(ws, path, wevs) ws.Close() }).ServeHTTP(w, r) }
func (t *txn) walk() { trace := t.instrumentVerb() if !t.c.raccess { t.respondOsError(syscall.EACCES) trace("eacces") return } if t.req.Path == nil || t.req.Offset == nil { t.respondErrCode(Response_MISSING_ARG) trace("emissingarg") return } glob, err := store.CompileGlob(*t.req.Path) if err != nil { t.respondOsError(err) trace("eunknown") return } offset := *t.req.Offset if offset < 0 { t.respondErrCode(Response_RANGE) trace("erange") return } go func() { g, err := t.getter() if err != nil { t.respondOsError(err) trace("eunknown") 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() trace("success") return true } offset-- return false } if !store.Walk(g, glob, f) { t.respondErrCode(Response_RANGE) trace("erange") } }() }
func (t *txn) wait() { trace := t.instrumentVerb() if !t.c.raccess { t.respondOsError(syscall.EACCES) trace("eacces") return } if t.req.Path == nil || t.req.Rev == nil { t.respondErrCode(Response_MISSING_ARG) trace("emissingarg") return } glob, err := store.CompileGlob(*t.req.Path) if err != nil { t.respondOsError(err) trace("eunknown") return } ch, err := t.c.st.Wait(glob, *t.req.Rev) if err != nil { t.respondOsError(err) trace("eunknown") return } go func() { var ev store.Event select { case ev = <-ch: case <-t.c.closed: t.c.st.Cancel(ch) return } 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() trace("success") }() }
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 }) }