コード例 #1
0
ファイル: set.go プロジェクト: fengshao0907/rpdb
func (o *setRow) getMembers(r rpdbReader, count int64) ([][]byte, error) {
	it := r.getIterator()
	defer r.putIterator(it)
	var members [][]byte
	for pfx := it.SeekTo(o.DataKeyPrefix()); count > 0 && it.Valid(); it.Next() {
		key := it.Key()
		if !bytes.HasPrefix(key, pfx) {
			break
		}
		sfx := key[len(pfx):]
		if err := o.ParseDataKeySuffix(sfx); err != nil {
			return nil, err
		}
		if err := o.ParseDataValue(it.Value()); err != nil {
			return nil, err
		}
		if len(o.Member) == 0 {
			return nil, errors.Errorf("len(member) = %d", len(o.Member))
		}
		members = append(members, o.Member)
		count--
	}
	if err := it.Error(); err != nil {
		return nil, err
	}
	if len(members) == 0 {
		return nil, errors.Errorf("len(members) = %d, set.size = %d", len(members), o.Size)
	}
	return members, nil
}
コード例 #2
0
ファイル: hash.go プロジェクト: fengshao0907/rpdb
func (o *hashRow) getAllValues(r rpdbReader) ([][]byte, error) {
	it := r.getIterator()
	defer r.putIterator(it)
	var values [][]byte
	for pfx := it.SeekTo(o.DataKeyPrefix()); it.Valid(); it.Next() {
		key := it.Key()
		if !bytes.HasPrefix(key, pfx) {
			break
		}
		if err := o.ParseDataValue(it.Value()); err != nil {
			return nil, err
		}
		if len(o.Value) == 0 {
			return nil, errors.Errorf("len(value) = %d", len(o.Value))
		}
		values = append(values, o.Value)
	}
	if err := it.Error(); err != nil {
		return nil, err
	}
	if len(values) == 0 || int64(len(values)) != o.Size {
		return nil, errors.Errorf("len(values) = %d, hash.size = %d", len(values), o.Size)
	}
	return values, nil
}
コード例 #3
0
ファイル: strconv.go プロジェクト: TigerZhang/redis-port
func ParseFloat64(i interface{}) (float64, error) {
	if v, ok := Num64(i); ok {
		switch x := v.(type) {
		case int64:
			return float64(x), nil
		case uint64:
			return float64(x), nil
		case float64:
			switch {
			case math.IsNaN(x):
				return 0, errors.Errorf("parse nan float64")
			case math.IsInf(x, 0):
				return 0, errors.Errorf("parse inf float64")
			}
			return float64(x), nil
		default:
			return 0, errors.Errorf("parse float64 from unknown num64")
		}
	} else {
		var s string
		switch x := i.(type) {
		case nil:
			return 0, errors.Errorf("parse float64 from nil")
		case string:
			s = x
		case []byte:
			s = string(x)
		default:
			return 0, errors.Errorf("parse float64 from <%s>", reflect.TypeOf(i))
		}
		f, err := strconv.ParseFloat(s, 64)
		return f, errors.Trace(err)
	}
}
コード例 #4
0
ファイル: row.go プロジェクト: fengshao0907/rpdb
func decodeRawBytes(r *BufReader, err error, refs ...interface{}) error {
	if err != nil {
		return err
	}
	if len(refs) == 0 {
		if r.Len() != 0 {
			return errors.Trace(ErrNotMatched)
		}
		return nil
	}
	for _, i := range refs {
		switch x := i.(type) {
		case byte:
			if v, err := r.ReadByte(); err != nil {
				return err
			} else if v != x {
				return errors.Errorf("read byte %d, expect %d", v, x)
			}
		case ObjectCode:
			if v, err := r.ReadByte(); err != nil {
				return err
			} else if v != byte(x) {
				return errors.Errorf("read code [%s], expect [%s]", ObjectCode(v), x)
			}
		case *[]byte:
			p, err := r.ReadVarbytes()
			if err != nil {
				return err
			}
			*x = p
		case *uint32:
			v, err := r.ReadUvarint()
			if err != nil {
				return err
			}
			*x = uint32(v)
		case *uint64:
			v, err := r.ReadUvarint()
			if err != nil {
				return err
			}
			*x = v
		case *int64:
			v, err := r.ReadVarint()
			if err != nil {
				return err
			}
			*x = v
		case *float64:
			v, err := r.ReadFloat64()
			if err != nil {
				return err
			}
			*x = v
		default:
			log.Panicf("unsupported type in row value: %+v", x)
		}
	}
	return nil
}
コード例 #5
0
ファイル: hash.go プロジェクト: fengshao0907/rpdb
func (o *hashRow) getAllFields(r rpdbReader) ([][]byte, error) {
	it := r.getIterator()
	defer r.putIterator(it)
	var fields [][]byte
	for pfx := it.SeekTo(o.DataKeyPrefix()); it.Valid(); it.Next() {
		key := it.Key()
		if !bytes.HasPrefix(key, pfx) {
			break
		}
		sfx := key[len(pfx):]
		if err := o.ParseDataKeySuffix(sfx); err != nil {
			return nil, err
		}
		if len(o.Field) == 0 {
			return nil, errors.Errorf("len(field) = %d", len(o.Field))
		}
		fields = append(fields, o.Field)
	}
	if err := it.Error(); err != nil {
		return nil, err
	}
	if len(fields) == 0 || int64(len(fields)) != o.Size {
		return nil, errors.Errorf("len(fields) = %d, hash.size = %d", len(fields), o.Size)
	}
	return fields, nil
}
コード例 #6
0
ファイル: format.go プロジェクト: fengshao0907/rpdb
func parseArgument(arg interface{}, ref interface{}) error {
	switch x := ref.(type) {
	default:
		return errors.Errorf("unsupported type, %v", reflect.TypeOf(x))
	case *int64:
		v, err := ParseInt(arg)
		if err != nil {
			return errors.Errorf("expect %v, %s", reflect.TypeOf(*x), err.Error())
		}
		*x = v
	case *uint32:
		v, err := ParseUint(arg)
		if err != nil {
			return errors.Errorf("expect %v, %s", reflect.TypeOf(*x), err.Error())
		} else if v > math.MaxUint32 {
			return errors.Errorf("expect %v, but got %d", reflect.TypeOf(*x), v)
		}
		*x = uint32(v)
	case *uint64:
		v, err := ParseUint(arg)
		if err != nil {
			return errors.Errorf("expect %v, %s", reflect.TypeOf(*x), err.Error())
		}
		*x = v
	case *float64:
		v, err := ParseFloat(arg)
		if err != nil {
			return errors.Errorf("expect %v, %s", reflect.TypeOf(*x), err.Error())
		}
		*x = v
	case *[]byte:
		switch y := arg.(type) {
		case []byte:
			*x = y
		case string:
			*x = []byte(y)
		default:
			return errors.Errorf("expect %v, but got %v", reflect.TypeOf(*x), reflect.TypeOf(y))
		}
		if len(*x) == 0 {
			return errors.Errorf("byte slice length = 0")
		}
	case *string:
		switch y := arg.(type) {
		case []byte:
			*x = string(y)
		case string:
			*x = y
		default:
			return errors.Errorf("expect %v, but got %v", reflect.TypeOf(*x), reflect.TypeOf(y))
		}
		if len(*x) == 0 {
			return errors.Errorf("string length = 0")
		}
	}
	return nil
}
コード例 #7
0
ファイル: loader.go プロジェクト: TigerZhang/redis-port
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
}
コード例 #8
0
ファイル: set.go プロジェクト: fengshao0907/rpdb
func (o *setRow) loadObjectValue(r rpdbReader) (interface{}, error) {
	it := r.getIterator()
	defer r.putIterator(it)
	set := make([][]byte, 0, o.Size)
	for pfx := it.SeekTo(o.DataKeyPrefix()); it.Valid(); it.Next() {
		key := it.Key()
		if !bytes.HasPrefix(key, pfx) {
			break
		}
		sfx := key[len(pfx):]
		if err := o.ParseDataKeySuffix(sfx); err != nil {
			return nil, err
		}
		if err := o.ParseDataValue(it.Value()); err != nil {
			return nil, err
		}
		set = append(set, o.Member)
	}
	if err := it.Error(); err != nil {
		return nil, err
	}
	if o.Size == 0 || int64(len(set)) != o.Size {
		return nil, errors.Errorf("len(set) = %d, set.size = %d", len(set), o.Size)
	}
	return rdb.Set(set), nil
}
コード例 #9
0
ファイル: migrate.go プロジェクト: fengshao0907/rpdb
func (c *conn) DoMustOK(cmd *redis.Array, timeout time.Duration) error {
	if rsp, err := c.Do(cmd, timeout); err != nil {
		return err
	} else {
		s, ok := rsp.(*redis.String)
		if ok {
			if s.Value == "OK" {
				return nil
			}
			c.err = errors.Errorf("not OK, got %s", s.Value)
		} else {
			c.err = errors.Errorf("not string response, got %v", rsp.Type())
		}
		return c.err
	}
}
コード例 #10
0
ファイル: encoder.go プロジェクト: hushi55/Grep
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
}
コード例 #11
0
ファイル: encoder.go プロジェクト: TigerZhang/redis-port
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)
	}
}
コード例 #12
0
ファイル: reader.go プロジェクト: hushi55/Grep
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))
		}
	}
}
コード例 #13
0
ファイル: hash.go プロジェクト: fengshao0907/rpdb
func (o *hashRow) loadObjectValue(r rpdbReader) (interface{}, error) {
	it := r.getIterator()
	defer r.putIterator(it)
	hash := make([]*rdb.HashElement, 0, o.Size)
	for pfx := it.SeekTo(o.DataKeyPrefix()); it.Valid(); it.Next() {
		key := it.Key()
		if !bytes.HasPrefix(key, pfx) {
			break
		}
		sfx := key[len(pfx):]
		if err := o.ParseDataKeySuffix(sfx); err != nil {
			return nil, err
		}
		if err := o.ParseDataValue(it.Value()); err != nil {
			return nil, err
		}
		hash = append(hash, &rdb.HashElement{Field: o.Field, Value: o.Value})
	}
	if err := it.Error(); err != nil {
		return nil, err
	}
	if o.Size == 0 || int64(len(hash)) != o.Size {
		return nil, errors.Errorf("len(hash) = %d, hash.size = %d", len(hash), o.Size)
	}
	return rdb.Hash(hash), nil
}
コード例 #14
0
ファイル: conn.go プロジェクト: fengshao0907/rpdb
func (c *conn) ping() error {
	deadline := time.Now().Add(time.Second * 5)
	if err := c.nc.SetDeadline(deadline); err != nil {
		return errors.Trace(err)
	}
	if _, err := c.w.WriteString("*1\r\n$4\r\nping\r\n"); err != nil {
		return errors.Trace(err)
	}
	if err := c.w.Flush(); err != nil {
		return errors.Trace(err)
	}
	var rsp string
	for !strings.HasSuffix(rsp, "\r\n") {
		b := []byte{0}
		if _, err := c.r.Read(b); err != nil {
			return errors.Trace(err)
		}
		if len(rsp) == 0 && b[0] == '\n' {
			continue
		}
		rsp += string(b)
	}
	rsp = rsp[:len(rsp)-2]

	if strings.ToLower(rsp) != "+pong" {
		return errors.Errorf("invalid response of command ping: %s", rsp)
	} else {
		return nil
	}
}
コード例 #15
0
ファイル: reader.go プロジェクト: hushi55/Grep
func (r *rdbReader) readLength() (uint32, error) {
	length, encoded, err := r.readEncodedLength()
	if err == nil && encoded {
		err = errors.Errorf("encoded-length")
	}
	return length, err
}
コード例 #16
0
ファイル: reader.go プロジェクト: hushi55/Grep
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
}
コード例 #17
0
ファイル: loader.go プロジェクト: TigerZhang/redis-port
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
}
コード例 #18
0
ファイル: server.go プロジェクト: TigerZhang/redis-port
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...)
	}
}
コード例 #19
0
ファイル: decoder.go プロジェクト: hushi55/Grep
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
	}
}
コード例 #20
0
ファイル: main.go プロジェクト: fysoft2006/redis-port
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)
}
コード例 #21
0
ファイル: resp.go プロジェクト: TigerZhang/redis-port
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))
	}
}
コード例 #22
0
ファイル: resp.go プロジェクト: TigerZhang/redis-port
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))
	}
}
コード例 #23
0
ファイル: resp.go プロジェクト: TigerZhang/redis-port
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))
	}
}
コード例 #24
0
ファイル: decoder.go プロジェクト: hushi55/Grep
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)
	}
}
コード例 #25
0
ファイル: resp.go プロジェクト: TigerZhang/redis-port
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))
	}
}
コード例 #26
0
ファイル: decoder.go プロジェクト: hushi55/Grep
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)
	}
}
コード例 #27
0
ファイル: snapshot.go プロジェクト: fengshao0907/rpdb
func (s *RpdbSnapshot) LoadObjCron(wait time.Duration, ncpu, step int) ([]*rdb.ObjEntry, bool, error) {
	if err := s.acquire(); err != nil {
		return nil, false, err
	}
	defer s.release()

	if wait <= 0 || ncpu <= 0 || step <= 0 {
		return nil, false, errors.Errorf("wait = %d, ncpu = %d, step = %d", wait, ncpu, step)
	}

	ctrl := make(chan int, 0)
	exit := make(chan int, ncpu)
	rets := &struct {
		sync.Mutex
		objs []*rdb.ObjEntry
		more bool
		err  error
	}{}

	var wg sync.WaitGroup
	for i := 0; i < ncpu; i++ {
		wg.Add(1)
		go func() {
			defer wg.Done()
			objs, more, err := s.loadObjCron(ctrl, exit)
			rets.Lock()
			if len(objs) != 0 {
				rets.objs = append(rets.objs, objs...)
			}
			if more {
				rets.more = true
			}
			if rets.err == nil && err != nil {
				rets.err = err
			}
			rets.Unlock()
		}()
	}

	deadline := time.Now().Add(wait)
	for stop := false; !stop && step != 0; step-- {
		select {
		case ctrl <- 0:
		case <-exit:
			stop = true
		}
		if time.Now().After(deadline) {
			stop = true
		}
	}
	close(ctrl)
	wg.Wait()
	return rets.objs, rets.more, rets.err
}
コード例 #28
0
ファイル: main.go プロジェクト: fengshao0907/rpdb
func session(arg0 interface{}, args [][]byte) (Session, error) {
	s, _ := arg0.(Session)
	if s == nil {
		return nil, errors.New("invalid session")
	}
	for i, v := range args {
		if len(v) == 0 {
			return nil, errors.Errorf("args[%d] is nil", i)
		}
	}
	return s, nil
}
コード例 #29
0
ファイル: decoder.go プロジェクト: hushi55/Grep
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)
	}
}
コード例 #30
0
ファイル: decoder.go プロジェクト: hushi55/Grep
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)
	}
}