示例#1
0
文件: slots.go 项目: guileen/ferrydb
// SLOTSRESTORE key ttlms value [key ttlms value ...]
func (s *Store) SlotsRestore(db uint32, args [][]byte) 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++ {
		key := args[i*3]
		ttlms, err := ParseInt(args[i*3+1])
		if err != nil {
			return errArguments("parse args failed - %s", err)
		}
		value := args[i*3+2]

		expireat := int64(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: uint64(expireat),
			Value:    obj,
		}
	}

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

	ms := &markSet{}
	bt := engine.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 := s.restore(bt, e.DB, e.Key, int64(e.ExpireAt), e.Value); err != nil {
			log.Warningf("restore object failed, db = %d, key = %v, err = %s", e.DB, e.Key, err)
			return errors.Trace(err)
		}
		ms.Set(e.Key)
	}
	fw := &Forward{DB: db, Op: "SlotsRestore", Args: args}
	return s.commit(bt, fw)
}
示例#2
0
文件: keys.go 项目: guileen/ferrydb
// RESTORE key ttlms value
func (s *Store) Restore(db uint32, args [][]byte) error {
	if len(args) != 3 {
		return errArguments("len(args) = %d, expect = 3", len(args))
	}

	key := args[0]
	ttlms, err := ParseInt(args[1])
	if err != nil {
		return errArguments("parse args failed - %s", err)
	}
	value := args[2]

	expireat := int64(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 errors.Trace(err)
	}

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

	fw := &Forward{DB: db, Op: "Restore", Args: args}
	bt := engine.NewBatch()
	if err := s.restore(bt, db, key, expireat, obj); err != nil {
		return errors.Trace(err)
	}
	return s.commit(bt, fw)
}
示例#3
0
func (s *testStoreSuite) checkSlotsMgrt(c *C, r *bufio.Reader, w *bufio.Writer, cc chan error, expect ...interface{}) {
	if len(expect) != 0 {
		req1, err := redis.Decode(r)
		c.Assert(err, IsNil)

		cmd1, args1, err := redis.ParseArgs(req1)
		c.Assert(err, IsNil)
		c.Assert(cmd1, Equals, "select")
		c.Assert(len(args1), Equals, 1)

		err = redis.Encode(w, redis.NewString("OK"))
		c.Assert(err, IsNil)

		err = w.Flush()
		c.Assert(err, IsNil)

		req2, err := redis.Decode(r)
		cmd2, args2, err := redis.ParseArgs(req2)
		c.Assert(err, IsNil)
		c.Assert(cmd2, Equals, "slotsrestore")
		c.Assert(len(args2), Equals, 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])
			c.Assert(err, IsNil)
			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)]
			c.Assert(v, NotNil)
			c.Assert(string(key), Equals, v.key)

			b, err := rdb.DecodeDump(value)
			c.Assert(err, IsNil)
			c.Assert(string(b.(rdb.String)), Equals, v.value)

			x, err := strconv.Atoi(string(ttlms))
			c.Assert(err, IsNil)

			if v.ttlms == 0 {
				c.Assert(x, Equals, 0)
			} else {
				c.Assert(x, Not(Equals), 0)
				c.Assert(math.Abs(float64(x)-float64(v.ttlms)) < 1000, Equals, true)
			}
		}

		err = redis.Encode(w, redis.NewString("OK"))
		c.Assert(err, IsNil)

		err = w.Flush()
		c.Assert(err, IsNil)
	}

	select {
	case err := <-cc:
		c.Assert(err, IsNil)
	case <-time.After(time.Second):
		c.Fatal("timeout error")
	}
}