// 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 }
// 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 }
// 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) }
// 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 }
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 }
/* *<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() }
// 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 }
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 }
// 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() }
// 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 }
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) }
// 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 }