예제 #1
0
func checkslotsmgrt(t *testing.T, r *bufio.Reader, w *bufio.Writer, c chan error, expect ...interface{}) {
	if len(expect) != 0 {
		req1, err := redis.Decode(r)
		checkerror(t, err, true)
		cmd1, args1, err := redis.ParseArgs(req1)
		checkerror(t, err, cmd1 == "select" && len(args1) == 1)

		checkerror(t, redis.Encode(w, redis.NewString("OK")), true)
		checkerror(t, w.Flush(), true)

		req2, err := redis.Decode(r)
		cmd2, args2, err := redis.ParseArgs(req2)
		checkerror(t, err, cmd2 == "slotsrestore" && len(args2) == len(expect))

		m := make(map[string]*struct {
			key, value string
			ttlms      uint64
		})
		for i := 0; i < len(expect)/3; i++ {
			v := &struct {
				key, value string
				ttlms      uint64
			}{key: expect[i*3].(string), value: expect[i*3+2].(string)}
			v.ttlms, err = ParseUint(expect[i*3+1])
			checkerror(t, err, true)
			m[v.key] = v
		}

		for i := 0; i < len(expect)/3; i++ {
			key := args2[i*3]
			ttlms := args2[i*3+1]
			value := args2[i*3+2]

			v := m[string(key)]
			checkerror(t, nil, v != nil)
			checkerror(t, nil, string(key) == v.key)
			b, err := rdb.DecodeDump(value)
			checkerror(t, err, string(b.(rdb.String)) == v.value)
			x, err := strconv.Atoi(string(ttlms))
			checkerror(t, err, true)
			if v.ttlms == 0 {
				checkerror(t, nil, x == 0)
			} else {
				checkerror(t, nil, x != 0)
				checkerror(t, nil, math.Abs(float64(x)-float64(v.ttlms)) < 500)
			}
		}

		checkerror(t, redis.Encode(w, redis.NewString("OK")), true)
		checkerror(t, w.Flush(), true)
	}

	select {
	case err := <-c:
		checkerror(t, err, true)
	case <-time.After(time.Second):
		checkerror(t, nil, false)
	}
}
예제 #2
0
파일: slots.go 프로젝트: fengshao0907/rpdb
// SLOTSRESTORE key ttlms value [key ttlms value ...]
func (b *Rpdb) SlotsRestore(db uint32, args ...interface{}) error {
	if len(args) == 0 || len(args)%3 != 0 {
		return errArguments("len(args) = %d, expect != 0 && mod 3 = 0", len(args))
	}

	objs := make([]*rdb.ObjEntry, len(args)/3)
	for i := 0; i < len(objs); i++ {
		var key, value []byte
		var ttlms int64
		for j, ref := range []interface{}{&key, &ttlms, &value} {
			if err := parseArgument(args[i*3+j], ref); err != nil {
				return errArguments("parse args[%d] failed, %s", i*3+j, err)
			}
		}
		expireat := uint64(0)
		if ttlms != 0 {
			if v, ok := TTLmsToExpireAt(ttlms); ok && v > 0 {
				expireat = v
			} else {
				return errArguments("parse args[%d] ttlms = %d", i*3+1, ttlms)
			}
		}
		obj, err := rdb.DecodeDump(value)
		if err != nil {
			return errArguments("decode args[%d] failed, %s", i*3+2, err)
		}
		objs[i] = &rdb.ObjEntry{
			DB:       db,
			Key:      key,
			ExpireAt: expireat,
			Value:    obj,
		}
	}

	if err := b.acquire(); err != nil {
		return err
	}
	defer b.release()

	ms := &markSet{}
	bt := store.NewBatch()
	for i := len(objs) - 1; i >= 0; i-- {
		e := objs[i]
		if ms.Has(e.Key) {
			log.Debugf("[%d] restore batch, db = %d, key = %v, ignore", i, e.DB, e.Key)
			continue
		} else {
			log.Debugf("[%d] restore batch, db = %d, key = %v", i, e.DB, e.Key)
		}
		if err := b.restore(bt, e.DB, e.Key, e.ExpireAt, e.Value); err != nil {
			log.DebugErrorf(err, "restore object failed, db = %d, key = %v", e.DB, e.Key)
			return err
		}
		ms.Set(e.Key)
	}
	fw := &Forward{DB: db, Op: "SlotsRestore", Args: args}
	return b.commit(bt, fw)
}
예제 #3
0
파일: keys.go 프로젝트: fengshao0907/rpdb
// RESTORE key ttlms value
func (b *Rpdb) Restore(db uint32, args ...interface{}) error {
	if len(args) != 3 {
		return errArguments("len(args) = %d, expect = 3", len(args))
	}

	var key, value []byte
	var ttlms int64
	for i, ref := range []interface{}{&key, &ttlms, &value} {
		if err := parseArgument(args[i], ref); err != nil {
			return errArguments("parse args[%d] failed, %s", i, err)
		}
	}

	expireat := uint64(0)
	if ttlms != 0 {
		if v, ok := TTLmsToExpireAt(ttlms); ok && v > 0 {
			expireat = v
		} else {
			return errArguments("parse ttlms = %d", ttlms)
		}
	}

	obj, err := rdb.DecodeDump(value)
	if err != nil {
		return err
	}

	if err := b.acquire(); err != nil {
		return err
	}
	defer b.release()

	fw := &Forward{DB: db, Op: "Restore", Args: args}
	bt := store.NewBatch()
	if err := b.restore(bt, db, key, expireat, obj); err != nil {
		return err
	}
	return b.commit(bt, fw)
}
예제 #4
0
func TestBgsaveTo(t *testing.T) {
	c := client(t)
	k := random(t)
	checkok(t, c, "reset")
	const max = 100
	for i := 0; i < max; i++ {
		checkok(t, c, "set", k+strconv.Itoa(i), i)
	}
	path := "/tmp/testdb-dump.rdb"
	checkok(t, c, "bgsaveto", path)
	f, err := os.Open(path)
	checkerror(t, err, true)
	defer f.Close()
	l := rdb.NewLoader(f)
	checkerror(t, l.Header(), true)
	m := make(map[string][]byte)
	for {
		e, err := l.NextBinEntry()
		checkerror(t, err, true)
		if e == nil {
			break
		}
		checkerror(t, nil, e.DB == 0)
		checkerror(t, nil, e.ExpireAt == 0)
		m[string(e.Key)] = e.Value
	}
	checkerror(t, l.Footer(), true)
	for i := 0; i < max; i++ {
		b := m[k+strconv.Itoa(i)]
		o, err := rdb.DecodeDump(b)
		checkerror(t, err, true)
		x, ok := o.(rdb.String)
		checkerror(t, nil, ok)
		checkerror(t, nil, string(x) == string(rpdb.FormatInt(int64(i))))
	}
}
예제 #5
0
func (cmd *cmdDecode) decoderMain(ipipe <-chan *rdb.BinEntry, opipe chan<- string) {
	toText := func(p []byte) string {
		var b bytes.Buffer
		for _, c := range p {
			switch {
			case c >= '#' && c <= '~':
				b.WriteByte(c)
			default:
				b.WriteByte('.')
			}
		}
		return b.String()
	}
	toBase64 := func(p []byte) string {
		return base64.StdEncoding.EncodeToString(p)
	}
	toJson := func(o interface{}) string {
		b, err := json.Marshal(o)
		if err != nil {
			log.PanicError(err, "encode to json failed")
		}
		return string(b)
	}
	for e := range ipipe {
		o, err := rdb.DecodeDump(e.Value)
		if err != nil {
			log.PanicError(err, "decode failed")
		}
		var b bytes.Buffer
		switch obj := o.(type) {
		default:
			log.Panicf("unknown object %v", o)
		case rdb.String:
			o := &struct {
				DB       uint32 `json:"db"`
				Type     string `json:"type"`
				ExpireAt uint64 `json:"expireat"`
				Key      string `json:"key"`
				Key64    string `json:"key64"`
				Value64  string `json:"value64"`
			}{
				e.DB, "string", e.ExpireAt, toText(e.Key), toBase64(e.Key),
				toBase64(obj),
			}
			fmt.Fprintf(&b, "%s\n", toJson(o))
		case rdb.List:
			for i, ele := range obj {
				o := &struct {
					DB       uint32 `json:"db"`
					Type     string `json:"type"`
					ExpireAt uint64 `json:"expireat"`
					Key      string `json:"key"`
					Key64    string `json:"key64"`
					Index    int    `json:"index"`
					Value64  string `json:"value64"`
				}{
					e.DB, "list", e.ExpireAt, toText(e.Key), toBase64(e.Key),
					i, toBase64(ele),
				}
				fmt.Fprintf(&b, "%s\n", toJson(o))
			}
		case rdb.Hash:
			for _, ele := range obj {
				o := &struct {
					DB       uint32 `json:"db"`
					Type     string `json:"type"`
					ExpireAt uint64 `json:"expireat"`
					Key      string `json:"key"`
					Key64    string `json:"key64"`
					Field    string `json:"field"`
					Field64  string `json:"field64"`
					Value64  string `json:"value64"`
				}{
					e.DB, "hash", e.ExpireAt, toText(e.Key), toBase64(e.Key),
					toText(ele.Field), toBase64(ele.Field), toBase64(ele.Value),
				}
				fmt.Fprintf(&b, "%s\n", toJson(o))
			}
		case rdb.Set:
			for _, mem := range obj {
				o := &struct {
					DB       uint32 `json:"db"`
					Type     string `json:"type"`
					ExpireAt uint64 `json:"expireat"`
					Key      string `json:"key"`
					Key64    string `json:"key64"`
					Member   string `json:"member"`
					Member64 string `json:"member64"`
				}{
					e.DB, "set", e.ExpireAt, toText(e.Key), toBase64(e.Key),
					toText(mem), toBase64(mem),
				}
				fmt.Fprintf(&b, "%s\n", toJson(o))
			}
		case rdb.ZSet:
			for _, ele := range obj {
				o := &struct {
					DB       uint32  `json:"db"`
					Type     string  `json:"type"`
					ExpireAt uint64  `json:"expireat"`
					Key      string  `json:"key"`
					Key64    string  `json:"key64"`
					Member   string  `json:"member"`
					Member64 string  `json:"member64"`
					Score    float64 `json:"score"`
				}{
					e.DB, "zset", e.ExpireAt, toText(e.Key), toBase64(e.Key),
					toText(ele.Member), toBase64(ele.Member), ele.Score,
				}
				fmt.Fprintf(&b, "%s\n", toJson(o))
			}
		}
		cmd.nentry.Incr()
		opipe <- b.String()
	}
}