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.Errorf("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 }
func (r *rdbReader) readLength() (uint32, error) { length, encoded, err := r.readEncodedLength() if err == nil && encoded { err = errors.Errorf("encoded-length") } return length, err }
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)) } } }
func (e *encoder) encodeResp(r Resp) error { switch x := r.(type) { default: return errors.Errorf("bad resp type <%s>", reflect.TypeOf(r)) case *String: if err := e.encodeType(typeString); err != nil { return err } return e.encodeText(x.Value) case *Error: if err := e.encodeType(typeError); err != nil { return err } return e.encodeText(x.Value) case *Int: if err := e.encodeType(typeInt); err != nil { return err } return e.encodeInt(x.Value) case *BulkBytes: if err := e.encodeType(typeBulkBytes); err != nil { return err } return e.encodeBulkBytes(x.Value) case *Array: if err := e.encodeType(typeArray); err != nil { return err } return e.encodeArray(x.Value) } }
func (e *Encoder) EncodeObject(db uint32, key []byte, expireat uint64, obj interface{}) error { o, ok := obj.(objectEncoder) if !ok { return errors.Errorf("unsupported object type") } if e.db == -1 || uint32(e.db) != db { e.db = int64(db) if err := e.enc.EncodeDatabase(int(db)); err != nil { return errors.Trace(err) } } if expireat != 0 { if err := e.enc.EncodeExpiry(expireat); err != nil { return errors.Trace(err) } } if err := o.encodeType(e.enc); err != nil { return err } if err := e.enc.EncodeString(key); err != nil { return errors.Trace(err) } if err := o.encodeValue(e.enc); err != nil { return err } return nil }
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 }
func (l *Loader) Footer() error { crc1 := l.crc.Sum64() if crc2, err := l.readUint64(); err != nil { return err } else if crc1 != crc2 { return errors.Errorf("checksum validation failed") } return nil }
func (s *Server) Dispatch(arg0 interface{}, resp Resp) (Resp, error) { if cmd, args, err := ParseArgs(resp); err != nil { return nil, err } else if f := s.t[cmd]; f == nil { return nil, errors.Errorf("unknown command '%s'", cmd) } else { return f(arg0, args...) } }
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) }
func (d *decoder) initObject(obj interface{}) { if d.err != nil { return } if d.obj != nil { d.err = errors.Errorf("invalid object, init again") } else { d.obj = obj } }
func (d *decoder) Rpush(key, value []byte) { if d.err != nil { return } switch l := d.obj.(type) { default: d.err = errors.Errorf("invalid object, not a list") case List: d.obj = append(l, value) } }
func (d *decoder) Sadd(key, member []byte) { if d.err != nil { return } switch s := d.obj.(type) { default: d.err = errors.Errorf("invalid object, not a set") case Set: d.obj = append(s, member) } }
func AsArray(r Resp, err error) ([]Resp, error) { if err != nil { return nil, err } x, ok := r.(*Array) if ok && x != nil { return x.Value, nil } else { return nil, errors.Errorf("expect Array, but got <%s>", reflect.TypeOf(r)) } }
func AsBulkBytes(r Resp, err error) ([]byte, error) { if err != nil { return nil, err } x, ok := r.(*BulkBytes) if ok && x != nil { return x.Value, nil } else { return nil, errors.Errorf("expect BulkBytes, but got <%s>", reflect.TypeOf(r)) } }
func AsInt(r Resp, err error) (int64, error) { if err != nil { return 0, err } x, ok := r.(*Int) if ok && x != nil { return x.Value, nil } else { return 0, errors.Errorf("expect Int, but got <%s>", reflect.TypeOf(r)) } }
func AsError(r Resp, err error) (string, error) { if err != nil { return "", err } x, ok := r.(*Error) if ok && x != nil { return x.Value, nil } else { return "", errors.Errorf("expect Error, but got <%s>", reflect.TypeOf(r)) } }
func (d *decoder) Zadd(key []byte, score float64, member []byte) { if d.err != nil { return } switch z := d.obj.(type) { default: d.err = errors.Errorf("invalid object, not a zset") case ZSet: v := &ZSetElement{Member: member, Score: score} d.obj = append(z, v) } }
func (d *decoder) Hset(key, field, value []byte) { if d.err != nil { return } switch h := d.obj.(type) { default: d.err = errors.Errorf("invalid object, not a hashmap") case Hash: v := &HashElement{Field: field, Value: value} d.obj = append(h, v) } }
func ParseArgs(resp Resp) (cmd string, args [][]byte, err error) { a, err := AsArray(resp, nil) if err != nil { return "", nil, err } else if len(a) == 0 { return "", nil, errors.Errorf("empty array") } bs := make([][]byte, len(a)) for i := 0; i < len(a); i++ { b, err := AsBulkBytes(a[i], nil) if err != nil { return "", nil, err } else { bs[i] = b } } cmd = strings.ToLower(string(bs[0])) if cmd == "" { return "", nil, errors.Errorf("empty command") } return cmd, bs[1:], nil }
func NewHandlerTable(o interface{}) (map[string]HandlerFunc, error) { if o == nil { return nil, errors.Errorf("handler is nil") } t := make(map[string]HandlerFunc) r := reflect.TypeOf(o) for i := 0; i < r.NumMethod(); i++ { m := r.Method(i) if m.Name[0] < 'A' || m.Name[0] > 'Z' { continue } n := strings.ToLower(m.Name) if h, err := createHandlerFunc(o, &m.Func); err != nil { return nil, err } else if _, exists := t[n]; exists { return nil, errors.Errorf("func.name = '%s' has already exists", m.Name) } else { t[n] = h } } return t, nil }
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 }
func createHandlerFunc(o interface{}, f *reflect.Value) (HandlerFunc, error) { t := f.Type() arg0Type := reflect.TypeOf((*interface{})(nil)).Elem() argsType := reflect.TypeOf([][]byte{}) if t.NumIn() != 3 || t.In(1) != arg0Type || t.In(2) != argsType { return nil, errors.Errorf("register with invalid func type = '%s'", t) } ret0Type := reflect.TypeOf((*Resp)(nil)).Elem() ret1Type := reflect.TypeOf((*error)(nil)).Elem() if t.NumOut() != 2 || t.Out(0) != ret0Type || t.Out(1) != ret1Type { return nil, errors.Errorf("register with invalid func type = '%s'", t) } return func(arg0 interface{}, args ...[]byte) (Resp, error) { var arg0Value reflect.Value if arg0 == nil { arg0Value = reflect.ValueOf((*interface{})(nil)) } else { arg0Value = reflect.ValueOf(arg0) } var input, output []reflect.Value input = []reflect.Value{reflect.ValueOf(o), arg0Value, reflect.ValueOf(args)} if t.IsVariadic() { output = f.CallSlice(input) } else { output = f.Call(input) } var ret0 Resp var ret1 error if i := output[0].Interface(); i != nil { ret0 = i.(Resp) } if i := output[1].Interface(); i != nil { ret1 = i.(error) } return ret0, ret1 }, nil }
func EncodeDump(obj interface{}) ([]byte, error) { o, ok := obj.(objectEncoder) if !ok { return nil, errors.Errorf("unsupported object type") } var b bytes.Buffer enc := rdb.NewEncoder(&b) if err := o.encodeType(enc); err != nil { return nil, err } if err := o.encodeValue(enc); err != nil { return nil, err } if err := enc.EncodeDumpFooter(); err != nil { return nil, errors.Trace(err) } return b.Bytes(), nil }
func (d *decoder) decodeResp(depth int) (Resp, error) { t, err := d.decodeType() if err != nil { return nil, err } switch t { case typeString: resp := &String{} resp.Value, err = d.decodeText() return resp, err case typeError: resp := &Error{} resp.Value, err = d.decodeText() return resp, err case typeInt: resp := &Int{} resp.Value, err = d.decodeInt() return resp, err case typeBulkBytes: resp := &BulkBytes{} resp.Value, err = d.decodeBulkBytes() return resp, err case typeArray: resp := &Array{} resp.Value, err = d.decodeArray(depth) return resp, err default: if depth != 0 { return nil, errors.Errorf("bad resp type %s", t) } if err := d.r.UnreadByte(); err != nil { return nil, errors.Trace(err) } return d.decodeSingleLineBulkBytesArray() } }
func NewServerWithTable(t HandlerTable) (*Server, error) { if t == nil { return nil, errors.Errorf("handler table is nil") } return &Server{t}, nil }