func handleReqTopics(r io.Reader, w io.Writer, pool *topicPool) error { dec := proto.NewDecoder(r) cid := dec.DecodeUint32() topics := pool.Topics() var b bytes.Buffer enc := proto.NewEncoder(&b) enc.EncodeUint8(proto.TopicsResp) enc.EncodeUint32(cid) enc.EncodeArrayLen(len(topics)) for _, t := range topics { enc.EncodeShortBytes([]byte(t.Name)) enc.EncodeUint64(t.Offset) } if err := enc.Err(); err != nil { _ = writeErrResp(w, cid, "cannot encode response") return errwrap.Err(err, "cannot encode response") } if _, err := b.WriteTo(w); err != nil { _ = writeErrResp(w, cid, "cannot write response") return errwrap.Err(err, "cannot write response") } return nil }
func handleReqSlice(r io.Reader, w io.Writer, pool *topicPool) error { dec := proto.NewDecoder(r) cid := dec.DecodeUint32() topic := dec.DecodeShortBytes() offset := dec.DecodeUint64() limit := dec.DecodeUint16() timeout := time.Duration(int64(dec.DecodeUint16())) * time.Millisecond if err := dec.Err(); err != nil { _ = writeErrResp(w, cid, "cannot decode request") return errwrap.Err(err, "cannot decode request") } if len(topic) == 0 { _ = writeErrResp(w, cid, "topic name not given") return nil } s, err := pool.Topic(string(topic)) if err != nil { _ = writeErrResp(w, cid, "topic not available") return errwrap.Err(err, "cannot decode") } msgs, err := s.Slice(offset, uint64(limit), timeout) if err != nil { _ = writeErrResp(w, cid, "cannot slice") return errwrap.Err(err, "cannot slice") } var b bytes.Buffer enc := proto.NewEncoder(&b) enc.EncodeUint8(proto.SliceResp) enc.EncodeUint32(cid) enc.EncodeArrayLen(len(msgs)) if err := enc.Err(); err != nil { _ = writeErrResp(w, cid, "cannot encode response") return errwrap.Err(err, "cannot encode response") } if _, err := b.WriteTo(w); err != nil { _ = writeErrResp(w, cid, "cannot write response") return errwrap.Err(err, "cannot write response") } for _, b := range msgs { if n, err := w.Write(b); err != nil { _ = writeErrResp(w, cid, "cannot write response") return errwrap.Err(err, "cannot write response") } else if n != len(b) { _ = writeErrResp(w, cid, "cannot write response") return errors.New("cannot write full response") } } return nil }
func handleReqAppend(r io.Reader, w io.Writer, pool *topicPool) error { dec := proto.NewDecoder(r) cid := dec.DecodeUint32() topic := dec.DecodeShortBytes() msgs := make([][]byte, dec.DecodeArrayLen()) if err := dec.Err(); err != nil { _ = writeErrResp(w, cid, "cannot decode request") return errwrap.Err(err, "cannot decode") } if len(topic) == 0 { _ = writeErrResp(w, cid, "topic name not given") return nil } if len(msgs) == 0 { return writeErrResp(w, cid, "no messages") } var mrd proto.MsgReader for i := range msgs { b, err := mrd.ReadBytes(r) if err != nil { _ = writeErrResp(w, cid, "cannot read message") return errwrap.Err(err, "cannot read message") } msgs[i] = b } s, err := pool.Topic(string(topic)) if err != nil { _ = writeErrResp(w, cid, "topic not available") return errwrap.Err(err, "cannot decode") } index, err := s.Append(msgs) if err != nil { _ = writeErrResp(w, cid, "cannot store messages") return errwrap.Err(err, "storage error: cannot append") } var b bytes.Buffer enc := proto.NewEncoder(&b) enc.EncodeUint8(proto.AppendResp) enc.EncodeUint32(cid) enc.EncodeUint64(index) if err := enc.Err(); err != nil { _ = writeErrResp(w, cid, "cannot encode response") return errwrap.Err(err, "cannot encode response") } if _, err := b.WriteTo(w); err != nil { _ = writeErrResp(w, cid, "cannot write response") return errwrap.Err(err, "cannot write response") } return nil }
func writeErrResp(w io.Writer, corelationID uint32, text string) error { var b bytes.Buffer enc := proto.NewEncoder(&b) enc.EncodeUint8(proto.ErrResp) enc.EncodeUint32(corelationID) enc.EncodeBytes([]byte(text)) if err := enc.Err(); err != nil { return errwrap.Err(err, "cannot encode response") } if _, err := b.WriteTo(w); err != nil { return errwrap.Err(err, "cannot write response") } return nil }
func write(c io.ReadWriter, topic string, values []string) { cid := uint32(time.Now().Unix()) var b bytes.Buffer enc := proto.NewEncoder(&b) enc.EncodeUint8(proto.AppendReq) enc.EncodeUint32(cid) enc.EncodeShortBytes([]byte(topic)) enc.EncodeArrayLen(len(values)) for _, v := range values { enc.EncodeUint8(0) enc.EncodeUint16(0) enc.EncodeUint64(0) enc.EncodeUint64(0) enc.EncodeUint8(0) enc.EncodeUint32(uint32(len(v))) enc.Write([]byte(v)) } if err := enc.Err(); err != nil { log.Fatalf("cannot encode request: %s", err) } if _, err := b.WriteTo(c); err != nil { log.Fatalf("cannot send request: %s", err) } dec := proto.NewDecoder(c) switch kind := dec.DecodeUint8(); kind { case proto.AppendResp: case proto.ErrResp: if rcid := dec.DecodeUint32(); rcid != cid { log.Printf("correlation ID missmatch, want %d, got %d", cid, rcid) } log.Fatalf("error response: %q", dec.DecodeBytes()) default: log.Fatalf("unknown response kind: %d", kind) } if rcid := dec.DecodeUint32(); rcid != cid { log.Printf("correlation ID missmatch, want %d, got %d", cid, rcid) } log.Printf("OK %d", dec.DecodeUint64()) if err := dec.Err(); err != nil { log.Fatalf("decoder error: %s", err) } }
func main() { log.SetOutput(os.Stdout) log.SetFlags(0) addr := flag.String("addr", "localhost:12345", "Server address") flag.Parse() if a := len(flag.Args()); a < 3 || a > 4 { fmt.Fprintf(os.Stderr, ` Usage: %s <topic> <offset> <limit> [<timeout>] `, os.Args[0]) os.Exit(2) } topic := flag.Args()[0] offset, err := strconv.ParseInt(flag.Args()[1], 10, 64) if err != nil { log.Fatalf("invalid offset value: %s", err) } limit, err := strconv.ParseInt(flag.Args()[2], 10, 64) if err != nil { log.Fatalf("invalid limit value: %s", err) } if limit < 1 { log.Fatal("limit must be greater than 0") } var timeout int64 if len(flag.Args()) == 4 { timeout, err = strconv.ParseInt(flag.Args()[3], 10, 64) if err != nil { log.Fatalf("invalid timeout value: %s", err) } } cid := uint32(time.Now().Unix()) var b bytes.Buffer enc := proto.NewEncoder(&b) enc.EncodeUint8(proto.SliceReq) enc.EncodeUint32(cid) enc.EncodeShortBytes([]byte(topic)) enc.EncodeUint64(uint64(offset)) enc.EncodeUint16(uint16(limit)) enc.EncodeUint16(uint16(timeout)) c, err := net.Dial("tcp", *addr) if err != nil { log.Fatalf("cannot connect to server: %s", err) } defer c.Close() if _, err := b.WriteTo(c); err != nil { log.Fatalf("cannot send request: %s", err) } dec := proto.NewDecoder(c) switch kind := dec.DecodeUint8(); kind { case proto.SliceResp: case proto.ErrResp: if rcid := dec.DecodeUint32(); rcid != cid { log.Printf("correlation ID missmatch, want %d, got %d", cid, rcid) } log.Fatalf("error response: %q", dec.DecodeBytes()) default: log.Fatalf("unknown response kind: %d", kind) } if rcid := dec.DecodeUint32(); rcid != cid { log.Printf("correlation ID missmatch, want %d, got %d", cid, rcid) } msgcnt := dec.DecodeArrayLen() var rw proto.MsgReader for i := 0; i < int(msgcnt); i++ { b, err := rw.ReadBytes(c) if err != nil { log.Fatalf("cannot read message: %s", err) } dec := proto.NewDecoder(bytes.NewBuffer(b)) show("[f%d k%d t%d #%d]", dec.DecodeUint8(), dec.DecodeUint16(), dec.DecodeUint64(), dec.DecodeUint64()) show("%q", dec.DecodeShortBytes()) show("%s", dec.DecodeBytes()) show("") } }
func main() { log.SetOutput(os.Stdout) log.SetFlags(0) addr := flag.String("addr", "localhost:12345", "Server address") flag.Parse() if len(flag.Args()) != 0 { fmt.Fprintf(os.Stderr, ` Usage: %s `, os.Args[0]) os.Exit(2) } cid := uint32(time.Now().Unix()) var b bytes.Buffer enc := proto.NewEncoder(&b) enc.EncodeUint8(proto.TopicsReq) enc.EncodeUint32(cid) if err := enc.Err(); err != nil { log.Fatalf("cannot encode message: %s", err) } c, err := net.Dial("tcp", *addr) if err != nil { log.Fatalf("cannot connect to server: %s", err) } defer c.Close() if _, err := b.WriteTo(c); err != nil { log.Fatalf("cannot send request: %s", err) } dec := proto.NewDecoder(c) switch kind := dec.DecodeUint8(); kind { case proto.TopicsResp: case proto.ErrResp: if rcid := dec.DecodeUint32(); rcid != cid { log.Printf("correlation ID missmatch, want %d, got %d", cid, rcid) } log.Fatalf("error response: %q", dec.DecodeBytes()) default: log.Fatalf("unknown response kind: %d", kind) } if rcid := dec.DecodeUint32(); rcid != cid { log.Printf("correlation ID missmatch, want %d, got %d", cid, rcid) } tcnt := dec.DecodeArrayLen() for i := 0; i < int(tcnt); i++ { name := dec.DecodeShortBytes() off := dec.DecodeUint64() if err := dec.Err(); err != nil { log.Fatalf("cannot decode topic: %s", err) } show("%s\t%d", name, off) } }