예제 #1
0
파일: handler.go 프로젝트: husio/maze
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
}
예제 #2
0
파일: handler.go 프로젝트: husio/maze
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
}
예제 #3
0
파일: handler.go 프로젝트: husio/maze
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
}
예제 #4
0
파일: handler.go 프로젝트: husio/maze
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
}
예제 #5
0
파일: append.go 프로젝트: husio/maze
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)
	}
}
예제 #6
0
파일: slice.go 프로젝트: husio/maze
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("")
	}
}
예제 #7
0
파일: topics.go 프로젝트: husio/maze
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)
	}
}