Exemple #1
0
// Bulk Reply
func (s *session) replyBulk(bulk interface{}) (err error) {
	// NULL Bulk Reply
	isnil := bulk == nil
	if !isnil {
		b, ok := bulk.([]byte)
		isnil = ok && b == nil
	}
	if isnil {
		_, err = s.Write([]byte("$-1\r\n"))
		return
	}
	buf := bytes.Buffer{}
	buf.WriteString("$")
	switch bulk.(type) {
	case []byte:
		b := bulk.([]byte)
		buf.WriteString(utils.ItoaQuick(len(b)))
		buf.WriteString(CRLF)
		buf.Write(b)
	default:
		b := []byte(bulk.(string))
		buf.WriteString(utils.ItoaQuick(len(b)))
		buf.WriteString(CRLF)
		buf.Write(b)
	}
	buf.WriteString(CRLF)
	_, err = buf.WriteTo(s)
	return
}
Exemple #2
0
// Multi-bulk replies
func (s *session) replyMultiBulks(bulks []interface{}) (err error) {
	// Null Multi Bulk Reply
	if bulks == nil {
		_, err = s.Write([]byte("*-1\r\n"))
		return
	}
	bulkCount := len(bulks)
	// Empty Multi Bulk Reply
	if bulkCount == 0 {
		_, err = s.Write([]byte("*0\r\n"))
		return
	}
	buf := bytes.Buffer{}
	buf.WriteString("*")
	buf.WriteString(utils.ItoaQuick(bulkCount))
	buf.WriteString(CRLF)
	for i := 0; i < bulkCount; i++ {
		bulk := bulks[i]
		switch bulk.(type) {
		case string:
			buf.WriteString("$")
			b := []byte(bulk.(string))
			buf.WriteString(utils.ItoaQuick(len(b)))
			buf.WriteString(CRLF)
			buf.Write(b)
			buf.WriteString(CRLF)
		case []byte:
			b := bulk.([]byte)
			if b == nil {
				buf.WriteString("$-1")
				buf.WriteString(CRLF)
			} else {
				buf.WriteString("$")
				buf.WriteString(utils.ItoaQuick(len(b)))
				buf.WriteString(CRLF)
				buf.Write(b)
				buf.WriteString(CRLF)
			}
		case int:
			buf.WriteString(":")
			buf.WriteString(utils.ItoaQuick(bulk.(int)))
			buf.WriteString(CRLF)
		case uint64:
			buf.WriteString(":")
			buf.WriteString(strconv.FormatUint(bulk.(uint64), 10))
			buf.WriteString(CRLF)
		default:
			// nil element
			buf.WriteString("$-1")
			buf.WriteString(CRLF)
		}
	}
	// flush
	_, err = buf.WriteTo(s)
	return
}
Exemple #3
0
// Confirm implements Confirm interface
func (u *UnitedQueue) Confirm(key string) error {
	key = strings.TrimPrefix(key, "/")
	key = strings.TrimSuffix(key, "/")

	parts := strings.Split(key, "/")
	if len(parts) != 3 {
		return utils.NewError(
			utils.ErrBadKey,
			`confirm key parts error: `+utils.ItoaQuick(len(parts)),
		)
	}
	topicName := parts[0]
	lineName := parts[1]
	id, err := strconv.ParseUint(parts[2], 10, 0)
	if err != nil {
		return utils.NewError(
			utils.ErrBadKey,
			`confirm key parse id error: `+err.Error(),
		)
	}

	u.topicsLock.RLock()
	t, ok := u.topics[topicName]
	u.topicsLock.RUnlock()
	if !ok {
		// log.Printf("topic[%s] not existed.", topicName)
		return utils.NewError(
			utils.ErrTopicNotExisted,
			`queue confirm`,
		)
	}

	return t.confirm(lineName, id)
}
Exemple #4
0
// Pop implements Pop interface
func (u *UnitedQueue) Pop(key string) (string, []byte, error) {
	key = strings.TrimPrefix(key, "/")
	key = strings.TrimSuffix(key, "/")

	parts := strings.Split(key, "/")
	if len(parts) != 2 {
		return "", nil, utils.NewError(
			utils.ErrBadKey,
			`pop key parts error: `+utils.ItoaQuick(len(parts)),
		)
	}

	tName := parts[0]
	lName := parts[1]

	u.topicsLock.RLock()
	t, ok := u.topics[tName]
	u.topicsLock.RUnlock()
	if !ok {
		// log.Printf("topic[%s] not existed.", tName)
		return "", nil, utils.NewError(
			utils.ErrTopicNotExisted,
			`queue pop`,
		)
	}

	id, data, err := t.pop(lName)
	if err != nil {
		return "", nil, err
	}

	return utils.Acatui(key, "/", id), data, nil
}
Exemple #5
0
func (u *UnitedQueue) create(key, rec string, fromEtcd bool) error {
	key = strings.TrimPrefix(key, "/")
	key = strings.TrimSuffix(key, "/")

	var topicName, lineName string
	var err error
	parts := strings.Split(key, "/")
	if len(parts) < 1 || len(parts) > 2 {
		return utils.NewError(
			utils.ErrBadKey,
			`create key parts error: `+utils.ItoaQuick(len(parts)),
		)
	}

	topicName = parts[0]
	if topicName == "" {
		return utils.NewError(
			utils.ErrBadKey,
			`create topic is nil`,
		)
	}

	if len(parts) == 2 {
		lineName = parts[1]
		var recycle time.Duration
		if rec != "" {
			recycle, err = time.ParseDuration(rec)
			if err != nil {
				return utils.NewError(
					utils.ErrBadRequest,
					err.Error(),
				)
			}
		}

		u.topicsLock.RLock()
		t, ok := u.topics[topicName]
		u.topicsLock.RUnlock()
		if !ok {
			return utils.NewError(
				utils.ErrTopicNotExisted,
				`queue create`,
			)
		}

		err = t.createLine(lineName, recycle, fromEtcd)
		if err != nil {
			// log.Printf("create line[%s] error: %s", lineName, err)
			return err
		}
	} else {
		err = u.createTopic(topicName, fromEtcd)
		if err != nil {
			// log.Printf("create topic[%s] error: %s", topicName, err)
			return err
		}
	}

	return err
}
Exemple #6
0
/*
*<number of arguments> CR LF
$<number of bytes of argument 1> CR LF
<argument data> CR LF
...
$<number of bytes of argument N> CR LF
<argument data> CR LF
*/
func (cmd *command) bytes() []byte {
	buf := bytes.Buffer{}
	buf.WriteByte('*')
	argCount := cmd.length()
	buf.WriteString(utils.ItoaQuick(argCount)) //<number of arguments>
	buf.WriteString(CRLF)
	for i := 0; i < argCount; i++ {
		buf.WriteByte('$')
		argSize := len(cmd.args[i])
		buf.WriteString(utils.ItoaQuick(argSize)) //<number of bytes of argument i>
		buf.WriteString(CRLF)
		buf.Write(cmd.args[i]) //<argument data>
		buf.WriteString(CRLF)
	}
	return buf.Bytes()
}
Exemple #7
0
// Integer reply
func (s *session) replyInteger(i int) (err error) {
	buf := bytes.Buffer{}
	buf.WriteString(":")
	buf.WriteString(utils.ItoaQuick(i))
	buf.WriteString(CRLF)
	_, err = buf.WriteTo(s)
	return
}
Exemple #8
0
func (s *session) writeReply(rep *reply) (err error) {
	switch rep.rType {
	case replyTypeStatus:
		err = s.replyStatus(rep.value.(string))
	case replyTypeError:
		err = s.replyError(rep.value.(string))
	case replyTypeInteger:
		err = s.replyInteger(rep.value.(int))
	case replyTypeBulk:
		err = s.replyBulk(rep.value)
	case replyTypeMultiBulks:
		err = s.replyMultiBulks(rep.value.([]interface{}))
	default:
		err = errors.New("Illegal ReplyType: " + utils.ItoaQuick(int(rep.rType)))
	}
	return
}
Exemple #9
0
// Empty implements Empty interface
func (u *UnitedQueue) Empty(key string) error {
	key = strings.TrimPrefix(key, "/")
	key = strings.TrimSuffix(key, "/")

	var topicName, lineName string
	parts := strings.Split(key, "/")
	if len(parts) < 1 || len(parts) > 2 {
		return utils.NewError(
			utils.ErrBadKey,
			`empty key parts error: `+utils.ItoaQuick(len(parts)),
		)
	}

	topicName = parts[0]

	if topicName == "" {
		return utils.NewError(
			utils.ErrBadKey,
			`empty topic is nil`,
		)
	}

	u.topicsLock.RLock()
	t, ok := u.topics[topicName]
	u.topicsLock.RUnlock()
	if !ok {
		return utils.NewError(
			utils.ErrTopicNotExisted,
			`queue empty`,
		)
	}

	if len(parts) == 2 {
		lineName = parts[1]
		return t.emptyLine(lineName)
		// err = t.emptyLine(lineName)
		// if err != nil {
		// 	log.Printf("empty line[%s] error: %s", lineName, err)
		// }
		// return err
	}

	return t.empty()
}
Exemple #10
0
// Stat implements Stat interface
func (u *UnitedQueue) Stat(key string) (*Stat, error) {
	key = strings.TrimPrefix(key, "/")
	key = strings.TrimSuffix(key, "/")

	var topicName, lineName string
	parts := strings.Split(key, "/")
	if len(parts) < 1 || len(parts) > 2 {
		return nil, utils.NewError(
			utils.ErrBadKey,
			`empty key parts error: `+utils.ItoaQuick(len(parts)),
		)
	}

	topicName = parts[0]
	if topicName == "" {
		return nil, utils.NewError(
			utils.ErrBadKey,
			`stat topic is nil`,
		)
	}

	u.topicsLock.RLock()
	t, ok := u.topics[topicName]
	u.topicsLock.RUnlock()
	if !ok {
		return nil, utils.NewError(
			utils.ErrTopicNotExisted,
			`queue stat`,
		)
	}

	if len(parts) == 2 {
		lineName = parts[1]
		return t.statLine(lineName)
	}

	qs := t.stat()
	return qs, nil
}
Exemple #11
0
func (u *UnitedQueue) remove(key string, fromEtcd bool) error {
	key = strings.TrimPrefix(key, "/")
	key = strings.TrimSuffix(key, "/")

	var topicName, lineName string
	parts := strings.Split(key, "/")
	if len(parts) < 1 || len(parts) > 2 {
		return utils.NewError(
			utils.ErrBadKey,
			`remove key parts error: `+utils.ItoaQuick(len(parts)),
		)
	}

	topicName = parts[0]
	if topicName == "" {
		return utils.NewError(
			utils.ErrBadKey,
			`rmove topic is nil`,
		)
	}

	if len(parts) == 1 {
		return u.removeTopic(topicName, fromEtcd)
	}

	u.topicsLock.RLock()
	t, ok := u.topics[topicName]
	u.topicsLock.RUnlock()
	if !ok {
		return utils.NewError(
			utils.ErrTopicNotExisted,
			`queue remove`,
		)
	}

	lineName = parts[1]
	return t.removeLine(lineName, fromEtcd)
}
Exemple #12
0
// MultiPop implements MultiPop interface
func (u *UnitedQueue) MultiPop(key string, n int) ([]string, [][]byte, error) {
	key = strings.TrimPrefix(key, "/")
	key = strings.TrimSuffix(key, "/")

	parts := strings.Split(key, "/")
	if len(parts) != 2 {
		return nil, nil, utils.NewError(
			utils.ErrBadKey,
			`mPop key parts error: `+utils.ItoaQuick(len(parts)),
		)
	}

	tName := parts[0]
	lName := parts[1]

	u.topicsLock.RLock()
	t, ok := u.topics[tName]
	u.topicsLock.RUnlock()
	if !ok {
		// log.Printf("topic[%s] not existed.", tName)
		return nil, nil, utils.NewError(
			utils.ErrTopicNotExisted,
			`queue multiPop`,
		)
	}

	ids, datas, err := t.mPop(lName, n)
	if err != nil {
		return nil, nil, err
	}

	keys := make([]string, len(ids))
	for i, id := range ids {
		keys[i] = utils.Acatui(key, "/", id)
	}
	return keys, datas, nil
}