Esempio n. 1
0
func (r *rdbReader) readString() ([]byte, error) {
	length, encoded, err := r.readEncodedLength()
	if err != nil {
		return nil, err
	}
	if !encoded {
		return r.readBytes(int(length))
	}
	switch t := uint8(length); t {
	default:
		return nil, errors.Errorf("invalid encoded-string %02x", t)
	case rdbEncInt8:
		i, err := r.readInt8()
		return []byte(strconv.FormatInt(int64(i), 10)), err
	case rdbEncInt16:
		i, err := r.readInt16()
		return []byte(strconv.FormatInt(int64(i), 10)), err
	case rdbEncInt32:
		i, err := r.readInt32()
		return []byte(strconv.FormatInt(int64(i), 10)), err
	case rdbEncLZF:
		var inlen, outlen uint32
		if inlen, err = r.readLength(); err != nil {
			return nil, err
		}
		if outlen, err = r.readLength(); err != nil {
			return nil, err
		}
		if in, err := r.readBytes(int(inlen)); err != nil {
			return nil, err
		} else {
			return lzfDecompress(in, int(outlen))
		}
	}
}
Esempio n. 2
0
func (r *rdbReader) readObjectValue(t byte) ([]byte, error) {
	var b bytes.Buffer
	r = newRdbReader(io.TeeReader(r, &b))
	switch t {
	default:
		return nil, errors.Errorf("unknown object-type %02x", t)
	case rdbTypeHashZipmap:
		fallthrough
	case rdbTypeListZiplist:
		fallthrough
	case rdbTypeSetIntset:
		fallthrough
	case rdbTypeZSetZiplist:
		fallthrough
	case rdbTypeHashZiplist:
		fallthrough
	case rdbTypeString:
		if _, err := r.readString(); err != nil {
			return nil, err
		}
	case rdbTypeList, rdbTypeSet:
		if n, err := r.readLength(); err != nil {
			return nil, err
		} else {
			for i := 0; i < int(n); i++ {
				if _, err := r.readString(); err != nil {
					return nil, err
				}
			}
		}
	case rdbTypeZSet:
		if n, err := r.readLength(); err != nil {
			return nil, err
		} else {
			for i := 0; i < int(n); i++ {
				if _, err := r.readString(); err != nil {
					return nil, err
				}
				if _, err := r.readFloat(); err != nil {
					return nil, err
				}
			}
		}
	case rdbTypeHash:
		if n, err := r.readLength(); err != nil {
			return nil, err
		} else {
			for i := 0; i < int(n); i++ {
				if _, err := r.readString(); err != nil {
					return nil, err
				}
				if _, err := r.readString(); err != nil {
					return nil, err
				}
			}
		}
	}
	return b.Bytes(), nil
}
Esempio n. 3
0
func parseInt(s string, min, max int) (int, error) {
	n, err := strconv.Atoi(s)
	if err != nil {
		return 0, err
	}
	if n >= min && n <= max {
		return n, nil
	}
	return 0, errors.Errorf("out of range [%d,%d], got %d", min, max, n)
}
Esempio n. 4
0
func ParseArgs(resp Resp) (cmd string, args [][]byte, err error) {
	var array []Resp
	if o, ok := resp.(*Array); !ok {
		return "", nil, errors.Errorf("expect array, but got type = '%s'", resp.Type())
	} else if o == nil || len(o.Value) == 0 {
		return "", nil, errors.New("request is an empty array")
	} else {
		array = o.Value
	}
	slices := make([][]byte, 0, len(array))
	for i, resp := range array {
		if o, ok := resp.(*BulkBytes); !ok {
			return "", nil, errors.Errorf("args[%d], expect bulkbytes, but got '%s'", i, resp.Type())
		} else if i == 0 && len(o.Value) == 0 {
			return "", nil, errors.New("command is empty")
		} else {
			slices = append(slices, o.Value)
		}
	}
	return strings.ToLower(string(slices[0])), slices[1:], nil
}
Esempio n. 5
0
func lzfDecompress(in []byte, outlen int) (out []byte, err error) {
	defer func() {
		if x := recover(); x != nil {
			err = errors.Errorf("decompress exception: %v", x)
		}
	}()
	out = make([]byte, outlen)
	i, o := 0, 0
	for i < len(in) {
		ctrl := int(in[i])
		i++
		if ctrl < 32 {
			for x := 0; x <= ctrl; x++ {
				out[o] = in[i]
				i++
				o++
			}
		} else {
			length := ctrl >> 5
			if length == 7 {
				length = length + int(in[i])
				i++
			}
			ref := o - ((ctrl & 0x1f) << 8) - int(in[i]) - 1
			i++
			for x := 0; x <= length+1; x++ {
				out[o] = out[ref]
				ref++
				o++
			}
		}
	}
	if o != outlen {
		return nil, errors.Errorf("decompress length is %d != expected %d", o, outlen)
	}
	return out, nil
}
Esempio n. 6
0
func (l *Loader) Header() error {
	header := make([]byte, 9)
	if err := l.readFull(header); err != nil {
		return err
	}
	if !bytes.Equal(header[:5], []byte("REDIS")) {
		return errors.New("verify magic string, invalid file format")
	}
	if version, err := strconv.ParseInt(string(header[5:]), 10, 64); err != nil {
		return errors.Trace(err)
	} else if version <= 0 || version > Version {
		return errors.Errorf("verify version, invalid RDB version number %d", version)
	}
	return nil
}