Esempio n. 1
0
// PERSIST key
func (s *Store) Persist(db uint32, args [][]byte) (int64, error) {
	if len(args) != 1 {
		return 0, errArguments("len(args) = %d, expect = 1", len(args))
	}

	key := args[0]

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

	o, err := s.loadStoreRow(db, key)
	if err != nil || o == nil {
		return 0, errors.Trace(err)
	}
	if o.GetExpireAt() == 0 {
		return 0, nil
	}

	fw := &Forward{DB: db, Op: "Persist", Args: args}
	bt := engine.NewBatch()
	o.SetExpireAt(0)
	bt.Set(o.MetaKey(), o.MetaValue())
	return 1, s.commit(bt, fw)
}
Esempio n. 2
0
func (s *Store) incrInt(db uint32, key []byte, delta int64) (int64, error) {
	o, err := s.loadStringRow(db, key)
	if err != nil {
		return 0, errors.Trace(err)
	}

	bt := engine.NewBatch()
	if o != nil {
		_, err := o.LoadDataValue(s)
		if err != nil {
			return 0, errors.Trace(err)
		}
		v, err := ParseInt(o.Value)
		if err != nil {
			return 0, errors.Trace(err)
		}
		delta += v
	} else {
		o = newStringRow(db, key)
		bt.Set(o.MetaKey(), o.MetaValue())
	}

	o.Value = FormatInt(delta)
	bt.Set(o.DataKey(), o.DataValue())

	fw := &Forward{DB: db, Op: "IncrBy", Args: [][]byte{key, FormatInt(delta)}}
	return delta, s.commit(bt, fw)
}
Esempio n. 3
0
// SPOP key
func (s *Store) SPop(db uint32, args [][]byte) ([]byte, error) {
	if len(args) != 1 {
		return nil, errArguments("len(args) = %d, expect = 1", len(args))
	}

	key := args[0]

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

	o, err := s.loadSetRow(db, key)
	if err != nil || o == nil {
		return nil, errors.Trace(err)
	}

	members, err := o.getMembers(s, 1)
	if err != nil || len(members) == 0 {
		return nil, errors.Trace(err)
	}
	o.Member = members[0]

	bt := engine.NewBatch()
	bt.Del(o.DataKey())
	if o.Size--; o.Size > 0 {
		bt.Set(o.MetaKey(), o.MetaValue())
	} else {
		bt.Del(o.MetaKey())
	}
	fw := &Forward{DB: db, Op: "SRem", Args: [][]byte{key, members[0]}}
	return o.Member, s.commit(bt, fw)
}
Esempio n. 4
0
// MSETNX key value [key value ...]
func (s *Store) MSetNX(db uint32, args [][]byte) (int64, error) {
	if len(args) == 0 || len(args)%2 != 0 {
		return 0, errArguments("len(args) = %d, expect != 0 && mod 2 = 0", len(args))
	}

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

	for i := 0; i < len(args); i += 2 {
		o, err := s.loadStoreRow(db, args[i])
		if err != nil || o != nil {
			return 0, errors.Trace(err)
		}
	}

	ms := &markSet{}
	bt := engine.NewBatch()
	for i := len(args)/2 - 1; i >= 0; i-- {
		key, value := args[i*2], args[i*2+1]
		if !ms.Has(key) {
			o := newStringRow(db, key)
			o.Value = value
			bt.Set(o.DataKey(), o.DataValue())
			bt.Set(o.MetaKey(), o.MetaValue())
			ms.Set(key)
		}
	}

	fw := &Forward{DB: db, Op: "MSet", Args: args}
	return 1, s.commit(bt, fw)
}
Esempio n. 5
0
// 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)
}
Esempio n. 6
0
// RPOP key
func (s *Store) RPop(db uint32, args [][]byte) ([]byte, error) {
	if len(args) != 1 {
		return nil, errArguments("len(args) = %d, expect = 1", len(args))
	}

	key := args[0]

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

	o, err := s.loadListRow(db, key)
	if err != nil || o == nil {
		return nil, errors.Trace(err)
	}

	o.Index = o.Rindex - 1
	if _, err := o.LoadDataValue(s); err != nil {
		return nil, errors.Trace(err)
	} else {
		bt := engine.NewBatch()
		bt.Del(o.DataKey())
		if o.Rindex--; o.Lindex < o.Rindex {
			bt.Set(o.MetaKey(), o.MetaValue())
		} else {
			bt.Del(o.MetaKey())
		}
		fw := &Forward{DB: db, Op: "RPop", Args: args}
		return o.Value, s.commit(bt, fw)
	}
}
Esempio n. 7
0
// DEL key [key ...]
func (s *Store) Del(db uint32, args [][]byte) (int64, error) {
	if len(args) == 0 {
		return 0, errArguments("len(args) = %d, expect != 0", len(args))
	}

	keys := args

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

	ms := &markSet{}
	bt := engine.NewBatch()
	for _, key := range keys {
		if !ms.Has(key) {
			exists, err := s.deleteIfExists(bt, db, key)
			if err != nil {
				return 0, errors.Trace(err)
			}
			if exists {
				ms.Set(key)
			}
		}
	}
	fw := &Forward{DB: db, Op: "Del", Args: args}
	return ms.Len(), s.commit(bt, fw)
}
Esempio n. 8
0
func (s *Store) incrFloat(db uint32, key []byte, delta float64) (float64, error) {
	o, err := s.loadStringRow(db, key)
	if err != nil {
		return 0, errors.Trace(err)
	}

	bt := engine.NewBatch()
	if o != nil {
		_, err := o.LoadDataValue(s)
		if err != nil {
			return 0, errors.Trace(err)
		}
		v, err := ParseFloat(o.Value)
		if err != nil {
			return 0, errors.Trace(err)
		}
		delta += v
	} else {
		o = newStringRow(db, key)
		bt.Set(o.MetaKey(), o.MetaValue())
	}

	if math.IsNaN(delta) || math.IsInf(delta, 0) {
		return 0, errors.New("increment would produce NaN or Infinity")
	}

	o.Value = FormatFloat(delta)
	bt.Set(o.DataKey(), o.DataValue())

	fw := &Forward{DB: db, Op: "IncrByFloat", Args: [][]byte{key, FormatFloat(delta)}}
	return delta, s.commit(bt, fw)
}
Esempio n. 9
0
// ZINCRBY key delta member
func (s *Store) ZIncrBy(db uint32, args [][]byte) (float64, error) {
	if len(args) != 3 {
		return 0, errArguments("len(args) = %d, expect = 3", len(args))
	}

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

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

	o, err := s.loadZSetRow(db, key)
	if err != nil {
		return 0, errors.Trace(err)
	}

	bt := engine.NewBatch()

	var exists bool = false
	if o != nil {
		o.Member = member
		exists, err = o.LoadDataValue(s)
		if err != nil {
			return 0, errors.Trace(err)
		} else if exists {
			bt.Del(o.IndexKey())
		}
	} else {
		o = newZSetRow(db, key)
		o.Member = member
	}

	if exists {
		delta += o.Score
	} else {
		o.Size++
		bt.Set(o.MetaKey(), o.MetaValue())
	}
	o.Score = delta
	if math.IsNaN(delta) {
		return 0, errors.New("invalid nan score")
	}

	bt.Set(o.DataKey(), o.DataValue())
	bt.Set(o.IndexKey(), o.IndexValue())

	fw := &Forward{DB: db, Op: "ZIncrBy", Args: args}
	return delta, s.commit(bt, fw)
}
Esempio n. 10
0
// HINCRBYFLOAT key field delta
func (s *Store) HIncrByFloat(db uint32, args [][]byte) (float64, error) {
	if len(args) != 3 {
		return 0, errArguments("len(args) = %d, expect = 2", len(args))
	}

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

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

	o, err := s.loadHashRow(db, key)
	if err != nil {
		return 0, errors.Trace(err)
	}

	var exists bool = false
	if o != nil {
		o.Field = field
		exists, err = o.LoadDataValue(s)
		if err != nil {
			return 0, errors.Trace(err)
		}
	} else {
		o = newHashRow(db, key)
		o.Field = field
	}

	bt := engine.NewBatch()
	if exists {
		v, err := ParseFloat(o.Value)
		if err != nil {
			return 0, errors.Trace(err)
		}
		delta += v
	} else {
		o.Size++
		bt.Set(o.MetaKey(), o.MetaValue())
	}

	if math.IsNaN(delta) || math.IsInf(delta, 0) {
		return 0, errors.New("increment would produce NaN or Infinity")
	}

	o.Value = FormatFloat(delta)
	bt.Set(o.DataKey(), o.DataValue())
	fw := &Forward{DB: db, Op: "HIncrByFloat", Args: args}
	return delta, s.commit(bt, fw)
}
Esempio n. 11
0
// ZREMRANGEBYSCORE key min max
func (s *Store) ZRemRangeByScore(db uint32, args [][]byte) (int64, error) {
	if len(args) != 3 {
		return 0, errArguments("len(args) = %d, expect 3", len(args))
	}

	key := args[0]
	min := args[1]
	max := args[2]

	r, err := parseRangeSpec(min, max)
	if err != nil {
		return 0, errors.Trace(err)
	}

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

	o, err := s.loadZSetRow(db, key)
	if err != nil {
		return 0, errors.Trace(err)
	} else if o == nil {
		return 0, nil
	}

	bt := engine.NewBatch()
	n := int64(0)

	f := func(o *zsetRow) error {
		bt.Del(o.DataKey())
		bt.Del(o.IndexKey())
		n++
		return nil
	}

	if err := o.travelInRange(s, r, f); err != nil {
		return 0, errors.Trace(err)
	}

	if n > 0 {
		if o.Size -= n; o.Size > 0 {
			bt.Set(o.MetaKey(), o.MetaValue())
		} else {
			bt.Del(o.MetaKey())
		}
	}

	fw := &Forward{DB: db, Op: "ZRemRangeByScore", Args: args}
	return n, s.commit(bt, fw)
}
Esempio n. 12
0
// HMSET key field value [field value ...]
func (s *Store) HMSet(db uint32, args [][]byte) error {
	if len(args) == 1 || len(args)%2 != 1 {
		return errArguments("len(args) = %d, expect != 1 && mod 2 = 1", len(args))
	}

	key := args[0]

	var eles = make([]*rdb.HashElement, len(args)/2)
	for i := 0; i < len(eles); i++ {
		e := &rdb.HashElement{}
		e.Field = args[i*2+1]
		e.Value = args[i*2+2]
		eles[i] = e
	}

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

	o, err := s.loadHashRow(db, key)
	if err != nil {
		return errors.Trace(err)
	}

	if o == nil {
		o = newHashRow(db, key)
	}

	ms := &markSet{}
	bt := engine.NewBatch()
	for _, e := range eles {
		o.Field, o.Value = e.Field, e.Value
		exists, err := o.TestDataValue(s)
		if err != nil {
			return errors.Trace(err)
		}
		if !exists {
			ms.Set(o.Field)
		}
		bt.Set(o.DataKey(), o.DataValue())
	}

	n := ms.Len()
	if n != 0 {
		o.Size += n
		bt.Set(o.MetaKey(), o.MetaValue())
	}
	fw := &Forward{DB: db, Op: "HMSet", Args: args}
	return s.commit(bt, fw)
}
Esempio n. 13
0
// LTRIM key beg end
func (s *Store) LTrim(db uint32, args [][]byte) error {
	if len(args) != 3 {
		return errArguments("len(args) = %d, expect = 2", len(args))
	}

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

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

	o, err := s.loadListRow(db, key)
	if err != nil || o == nil {
		return errors.Trace(err)
	}

	beg = maxIntValue(adjustIndex(beg, o.Lindex, o.Rindex), o.Lindex)
	end = minIntValue(adjustIndex(end, o.Lindex, o.Rindex), o.Rindex-1)
	if beg == o.Lindex && end == o.Rindex-1 {
		return nil
	}

	bt := engine.NewBatch()
	if beg <= end {
		for o.Index = o.Lindex; o.Index < beg; o.Index++ {
			bt.Del(o.DataKey())
		}
		for o.Index = o.Rindex - 1; o.Index > end; o.Index-- {
			bt.Del(o.DataKey())
		}
		o.Lindex, o.Rindex = beg, end+1
		bt.Set(o.MetaKey(), o.MetaValue())
	} else {
		for o.Index = o.Lindex; o.Index < o.Rindex; o.Index++ {
			bt.Del(o.DataKey())
		}
		bt.Del(o.MetaKey())
	}
	fw := &Forward{DB: db, Op: "LTrim", Args: args}
	return s.commit(bt, fw)
}
Esempio n. 14
0
func (s *Store) loadStoreRow(db uint32, key []byte) (storeRow, error) {
	o, err := loadStoreRow(s, db, key)
	if err != nil || o == nil {
		return nil, errors.Trace(err)
	}

	if s.needDeleteIfExpired() && o.IsExpired() {
		bt := engine.NewBatch()
		if err := o.deleteObject(s, bt); err != nil {
			return nil, errors.Trace(err)
		}
		fw := &Forward{DB: db, Op: "Del", Args: [][]byte{key}}
		return nil, s.commit(bt, fw)
	}
	return o, nil
}
Esempio n. 15
0
// SETRANGE key offset value
func (s *Store) SetRange(db uint32, args [][]byte) (int64, error) {
	if len(args) != 3 {
		return 0, errArguments("len(args) = %d, expect = 3", len(args))
	}

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

	if offset > maxVarbytesLen {
		return 0, errArguments("offset = %d", offset)
	}

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

	o, err := s.loadStringRow(db, key)
	if err != nil {
		return 0, errors.Trace(err)
	}

	bt := engine.NewBatch()
	if o != nil {
		_, err := o.LoadDataValue(s)
		if err != nil {
			return 0, errors.Trace(err)
		}
	} else {
		o = newStringRow(db, key)
		bt.Set(o.MetaKey(), o.MetaValue())
	}

	if n := int(offset) + len(value); n > len(o.Value) {
		o.Value = append(o.Value, make([]byte, n-len(o.Value))...)
	}

	copy(o.Value[offset:], value)
	bt.Set(o.DataKey(), o.DataValue())

	fw := &Forward{DB: db, Op: "SetRange", Args: args}
	return int64(len(o.Value)), s.commit(bt, fw)
}
Esempio n. 16
0
// HSET key field value
func (s *Store) HSet(db uint32, args [][]byte) (int64, error) {
	if len(args) != 3 {
		return 0, errArguments("len(args) = %d, expect = 2", len(args))
	}

	key := args[0]
	field := args[1]
	value := args[2]

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

	o, err := s.loadHashRow(db, key)
	if err != nil {
		return 0, errors.Trace(err)
	}

	var exists bool = false
	if o != nil {
		o.Field = field
		exists, err = o.TestDataValue(s)
		if err != nil {
			return 0, errors.Trace(err)
		}
	} else {
		o = newHashRow(db, key)
		o.Field = field
	}

	var n int64

	bt := engine.NewBatch()
	if exists {
		n, o.Value = 0, value
		bt.Set(o.DataKey(), o.DataValue())
	} else {
		o.Size++
		n, o.Value = 1, value
		bt.Set(o.DataKey(), o.DataValue())
		bt.Set(o.MetaKey(), o.MetaValue())
	}
	fw := &Forward{DB: db, Op: "HSet", Args: args}
	return n, s.commit(bt, fw)
}
Esempio n. 17
0
func (s *Store) migrate(addr string, timeout time.Duration, db uint32, keys ...[]byte) (int64, error) {
	var rows []storeRow
	var bins []*rdb.BinEntry

	for i, key := range keys {
		o, bin, err := loadBinEntry(s, db, key)
		if err != nil {
			return 0, errors.Trace(err)
		}
		if o == nil {
			log.Debugf("[%d] missing, db = %d, key = %v", i, db, key)
			continue
		}

		rows = append(rows, o)
		if bin != nil {
			log.Debugf("[%d] migrate, db = %d, key = %v, expireat = %d", i, db, key, o.GetExpireAt())
			bins = append(bins, bin)
		} else {
			log.Debugf("[%d] expired, db = %d, key = %v, expireat = %d", i, db, key, o.GetExpireAt())
		}
	}

	if len(bins) != 0 {
		if err := doMigrate(addr, timeout, db, bins); err != nil {
			return 0, errors.Trace(err)
		}
	}

	if len(rows) == 0 {
		return 0, nil
	}

	bt := engine.NewBatch()
	for _, o := range rows {
		if err := o.deleteObject(s, bt); err != nil {
			return 0, errors.Trace(err)
		}
	}
	fw := &Forward{DB: db, Op: "Del"}
	for _, key := range keys {
		fw.Args = append(fw.Args, key)
	}
	return int64(len(rows)), s.commit(bt, fw)
}
Esempio n. 18
0
// ZREM key member [member ...]
func (s *Store) ZRem(db uint32, args [][]byte) (int64, error) {
	if len(args) < 2 {
		return 0, errArguments("len(args) = %d, expect >= 2", len(args))
	}

	key := args[0]
	members := args[1:]

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

	o, err := s.loadZSetRow(db, key)
	if err != nil || o == nil {
		return 0, errors.Trace(err)
	}

	ms := &markSet{}
	bt := engine.NewBatch()
	for _, o.Member = range members {
		if !ms.Has(o.Member) {
			exists, err := o.LoadDataValue(s)
			if err != nil {
				return 0, errors.Trace(err)
			}
			if exists {
				bt.Del(o.DataKey())
				bt.Del(o.IndexKey())
				ms.Set(o.Member)
			}
		}
	}

	n := ms.Len()
	if n != 0 {
		if o.Size -= n; o.Size > 0 {
			bt.Set(o.MetaKey(), o.MetaValue())
		} else {
			bt.Del(o.MetaKey())
		}
	}
	fw := &Forward{DB: db, Op: "ZRem", Args: args}
	return n, s.commit(bt, fw)
}
Esempio n. 19
0
// SADD key member [member ...]
func (s *Store) SAdd(db uint32, args [][]byte) (int64, error) {
	if len(args) < 2 {
		return 0, errArguments("len(args) = %d, expect >= 2", len(args))
	}

	key := args[0]
	members := args[1:]

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

	o, err := s.loadSetRow(db, key)
	if err != nil {
		return 0, errors.Trace(err)
	}

	if o == nil {
		o = newSetRow(db, key)
	}

	ms := &markSet{}
	bt := engine.NewBatch()
	for _, o.Member = range members {
		exists, err := o.TestDataValue(s)
		if err != nil {
			return 0, errors.Trace(err)
		}
		if !exists {
			ms.Set(o.Member)
		}
		bt.Set(o.DataKey(), o.DataValue())
	}

	n := ms.Len()
	if n != 0 {
		o.Size += n
		bt.Set(o.MetaKey(), o.MetaValue())
	}
	fw := &Forward{DB: db, Op: "SAdd", Args: args}
	return n, s.commit(bt, fw)
}
Esempio n. 20
0
func (s *Store) setExpireAt(db uint32, key []byte, expireat int64) (int64, error) {
	o, err := s.loadStoreRow(db, key)
	if err != nil || o == nil {
		return 0, errors.Trace(err)
	}
	bt := engine.NewBatch()
	if !IsExpired(expireat) {
		o.SetExpireAt(expireat)
		bt.Set(o.MetaKey(), o.MetaValue())
		fw := &Forward{DB: db, Op: "PExpireAt", Args: [][]byte{key, FormatInt(expireat)}}
		return 1, s.commit(bt, fw)
	} else {
		_, err := s.deleteIfExists(bt, db, key)
		if err != nil {
			return 0, errors.Trace(err)
		}
		fw := &Forward{DB: db, Op: "Del", Args: [][]byte{key}}
		return 1, s.commit(bt, fw)
	}
}
Esempio n. 21
0
// GETSET key value
func (s *Store) GetSet(db uint32, args [][]byte) ([]byte, error) {
	if len(args) != 2 {
		return nil, errArguments("len(args) = %d, expect = 2", len(args))
	}

	key := args[0]
	value := args[1]

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

	o, err := s.loadStringRow(db, key)
	if err != nil {
		return nil, errors.Trace(err)
	}

	bt := engine.NewBatch()
	if o != nil {
		_, err := o.LoadDataValue(s)
		if err != nil {
			return nil, errors.Trace(err)
		}

		if o.ExpireAt != 0 {
			o.ExpireAt = 0
			bt.Set(o.MetaKey(), o.MetaValue())
		}
	} else {
		o = newStringRow(db, key)
		bt.Set(o.MetaKey(), o.MetaValue())
	}

	o.Value, value = value, o.Value
	bt.Set(o.DataKey(), o.DataValue())

	fw := &Forward{DB: db, Op: "Set", Args: args}
	return value, s.commit(bt, fw)
}
Esempio n. 22
0
// 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)
}
Esempio n. 23
0
// LSET key index value
func (s *Store) LSet(db uint32, args [][]byte) error {
	if len(args) != 3 {
		return errArguments("len(args) = %d, expect = 2", len(args))
	}

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

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

	o, err := s.loadListRow(db, key)
	if err != nil {
		return errors.Trace(err)
	}

	if o == nil {
		return errors.Trace(ErrNoSuchList)
	}

	o.Index = adjustIndex(index, o.Lindex, o.Rindex)
	if o.Index >= o.Lindex && o.Index < o.Rindex {
		o.Value = value
		bt := engine.NewBatch()
		bt.Set(o.DataKey(), o.DataValue())
		fw := &Forward{DB: db, Op: "LSet", Args: args}
		return s.commit(bt, fw)
	} else {
		return errors.Trace(ErrOutOfRange)
	}
}
Esempio n. 24
0
// APPEND key value
func (s *Store) Append(db uint32, args [][]byte) (int64, error) {
	if len(args) != 2 {
		return 0, errArguments("len(args) = %d, expect = 2", len(args))
	}

	key := args[0]
	value := args[1]

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

	o, err := s.loadStringRow(db, key)
	if err != nil {
		return 0, errors.Trace(err)
	}

	bt := engine.NewBatch()
	if o != nil {
		_, err := o.LoadDataValue(s)
		if err != nil {
			return 0, errors.Trace(err)
		}
		o.Value = append(o.Value, value...)
	} else {
		o = newStringRow(db, key)
		o.Value = value
		bt.Set(o.MetaKey(), o.MetaValue())
	}

	bt.Set(o.DataKey(), o.DataValue())
	fw := &Forward{DB: db, Op: "Append", Args: args}

	return int64(len(o.Value)), s.commit(bt, fw)
}
Esempio n. 25
0
func (s *Store) rpush(db uint32, key []byte, create bool, values ...[]byte) (int64, error) {
	o, err := s.loadListRow(db, key)
	if err != nil {
		return 0, errors.Trace(err)
	}

	if o == nil {
		if !create {
			return 0, nil
		}
		o = newListRow(db, key)
	}

	fw := &Forward{DB: db, Op: "RPush", Args: [][]byte{key}}
	bt := engine.NewBatch()
	for _, value := range values {
		o.Index, o.Value = o.Rindex, value
		o.Rindex++
		bt.Set(o.DataKey(), o.DataValue())
		fw.Args = append(fw.Args, value)
	}
	bt.Set(o.MetaKey(), o.MetaValue())
	return o.Rindex - o.Lindex, s.commit(bt, fw)
}
Esempio n. 26
0
// ZADD key score member [score member ...]
func (s *Store) ZAdd(db uint32, args [][]byte) (int64, error) {
	if len(args) == 1 || len(args)%2 != 1 {
		return 0, errArguments("len(args) = %d, expect != 1 && mod 2 = 1", len(args))
	}

	key := args[0]

	var eles = make([]struct {
		Member []byte
		Score  float64
	}, len(args)/2)

	var err error
	for i := 0; i < len(eles); i++ {
		e := &eles[i]
		e.Score, err = ParseFloat(args[i*2+1])
		if err != nil {
			return 0, errArguments("parse args failed - %s", err)
		}

		e.Member = args[i*2+2]
		if len(e.Member) == 0 {
			return 0, errArguments("parse args[%d] failed, empty empty", i*2+2)
		}
	}

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

	o, err := s.loadZSetRow(db, key)
	if err != nil {
		return 0, errors.Trace(err)
	}

	if o == nil {
		o = newZSetRow(db, key)
	}

	ms := &markSet{}
	bt := engine.NewBatch()
	for _, e := range eles {
		o.Member = e.Member
		exists, err := o.LoadDataValue(s)
		if err != nil {
			return 0, errors.Trace(err)
		}
		if !exists {
			ms.Set(o.Member)
		} else {
			// if old exists, remove index key first
			bt.Del(o.IndexKey())
		}

		o.Score = e.Score

		bt.Set(o.DataKey(), o.DataValue())
		bt.Set(o.IndexKey(), o.IndexValue())
	}

	n := ms.Len()
	if n != 0 {
		o.Size += n
		bt.Set(o.MetaKey(), o.MetaValue())
	}
	fw := &Forward{DB: db, Op: "ZAdd", Args: args}
	return n, s.commit(bt, fw)
}
Esempio n. 27
0
// BITOP op destkey key [key ...]
func (s *Store) BitOp(db uint32, args [][]byte) (int64, error) {
	if len(args) < 3 {
		return 0, errArguments("len(args) = %d, expect >= 3", len(args))
	}

	op := args[0]
	destKey := args[1]
	srcKeys := args[2:]

	if string(op) == BitNot && len(srcKeys) > 1 {
		return 0, errArguments("BITOP NOT must be called with a single source key, len(srcKeys)=%d", len(srcKeys))
	}

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

	var value []byte
	o, err := s.loadStringRow(db, srcKeys[0])
	if err != nil {
		return 0, errors.Trace(err)
	}

	if o != nil {
		_, err := o.LoadDataValue(s)
		if err != nil {
			return 0, errors.Trace(err)
		}

		if string(op) == BitNot {
			for i := 0; i < len(o.Value); i++ {
				o.Value[i] = ^o.Value[i]
			}
		}

		value = o.Value
	}

	for i := 1; i < len(srcKeys); i++ {
		ro, err := s.loadStringRow(db, srcKeys[i])
		if err != nil {
			return 0, errors.Trace(err)
		}

		if ro != nil {
			_, err = ro.LoadDataValue(s)
			if err != nil {
				return 0, errors.Trace(err)
			}
		} else {
			ro = newStringRow(db, srcKeys[i])
		}

		if len(value) < len(ro.Value) {
			value, ro.Value = ro.Value, value
		}

		for j := 0; j < len(ro.Value); j++ {
			switch string(op) {
			case BitAND:
				value[j] &= ro.Value[j]
			case BitOR:
				value[j] |= ro.Value[j]
			case BitXOR:
				value[j] ^= ro.Value[j]
			default:
				return 0, errors.Errorf("invalid op type: %s", op)
			}
		}

		for j := len(ro.Value); j < len(value); j++ {
			switch string(op) {
			case BitAND:
				value[j] &= 0
			case BitOR:
				value[j] |= 0
			case BitXOR:
				value[j] ^= 0
			}
		}
	}

	bt := engine.NewBatch()

	_, err = s.deleteIfExists(bt, db, destKey)
	if err != nil {
		return 0, errors.Trace(err)
	}

	no := newStringRow(db, destKey)
	no.Value = value
	bt.Set(no.DataKey(), no.DataValue())
	bt.Set(no.MetaKey(), no.MetaValue())

	fw := &Forward{DB: db, Op: "BitOp", Args: args}
	return int64(len(no.Value)), s.commit(bt, fw)
}
Esempio n. 28
0
// SET key value [EX seconds] [PX milliseconds] [NX|XX]
func (s *Store) Set(db uint32, args [][]byte) error {
	if len(args) < 2 {
		return errArguments("len(args) = %d, expect >= 2", len(args))
	}

	key := args[0]
	value := args[1]

	expireat := int64(0)
	flag := uint8(0)

	for i := 2; i < len(args); {
		switch strings.ToUpper(string(args[i])) {
		case "EX":
			if i+1 >= len(args) {
				return errArguments("invalid set argument for EX")
			}
			ttls, err := ParseInt(args[i+1])
			if err != nil {
				return errArguments("parse EX arg failed %v", err)
			}

			if v, ok := TTLsToExpireAt(ttls); ok && v > 0 {
				expireat = v
			} else {
				return errArguments("invalid EX seconds = %d", ttls)
			}
			i += 2
		case "PX":
			if i+1 >= len(args) {
				return errArguments("invalid set argument for PX")
			}
			ttlms, err := ParseInt(args[i+1])
			if err != nil {
				return errArguments("parse PX arg failed %v", err)
			}
			if v, ok := TTLmsToExpireAt(ttlms); ok && v > 0 {
				expireat = v
			} else {
				return errArguments("invalid PX milliseconds = %d", ttlms)
			}
			i += 2
		case "NX":
			flag |= setNXFlag
			i++
		case "XX":
			flag |= setXXFlag
			i++
		default:
			return errArguments("invalid set argument at %d", i)
		}
	}

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

	bt := engine.NewBatch()

	if o, err := loadStoreRow(s, db, key); err != nil {
		return errors.Trace(err)
	} else {
		// handle NX and XX flag
		// NX: key is nil or expired
		// XX: key is not nil and not expired
		// otherwise, abort
		if (flag&setNXFlag > 0) && (o != nil && !o.IsExpired()) {
			return ErrSetAborted
		} else if (flag&setXXFlag > 0) && (o == nil || o.IsExpired()) {
			return ErrSetAborted
		}

		// if we are string type, we will overwrite it directly
		// if not, we may delete it first
		if o != nil && o.Code() != StringCode {
			if err := o.deleteObject(s, bt); err != nil {
				return errors.Trace(err)
			}
		}
	}

	no := newStringRow(db, key)
	no.Value = value
	no.ExpireAt = expireat
	bt.Set(no.DataKey(), no.DataValue())
	bt.Set(no.MetaKey(), no.MetaValue())

	fw := &Forward{DB: db, Op: "Set", Args: args}
	return s.commit(bt, fw)
}
Esempio n. 29
0
// SETBIT key offset value
func (s *Store) SetBit(db uint32, args [][]byte) (int64, error) {
	if len(args) != 3 {
		return 0, errArguments("len(args) = %d, expect = 3", len(args))
	}

	key := args[0]
	offset, err := ParseUint(args[1])
	if err != nil {
		return 0, errArguments("bit offset is not an integer or out of range - %s", err)
	}
	value, err := ParseUint(args[2])
	if err != nil {
		return 0, errArguments("bit is not an integer or out of range - %s", err)
	}

	if offset > maxVarbytesLen {
		return 0, errArguments("bit offset is not an integer or out of range, offset = %d", offset)
	}

	if value != 0 && value != 1 {
		return 0, errArguments("bit is not an integer or out of range, bit = %d", value)
	}

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

	o, err := s.loadStringRow(db, key)
	if err != nil {
		return 0, errors.Trace(err)
	}

	bt := engine.NewBatch()
	if o != nil {
		_, err := o.LoadDataValue(s)
		if err != nil {
			return 0, errors.Trace(err)
		}
	} else {
		o = newStringRow(db, key)
		bt.Set(o.MetaKey(), o.MetaValue())
	}

	byteOffset := int(uint32(offset) >> 3)
	extra := byteOffset + 1 - len(o.Value)
	if extra > 0 {
		o.Value = append(o.Value, make([]byte, extra)...)
	}

	byteVal := o.Value[byteOffset]
	bit := 7 - uint8(uint32(offset)&0x7)
	bitVal := byteVal & (1 << bit)

	byteVal &= ^(1 << bit)
	byteVal |= (uint8(value&0x1) << bit)

	o.Value[byteOffset] = byteVal

	bt.Set(o.DataKey(), o.DataValue())

	var n int64 = 0
	if bitVal > 0 {
		n = 1
	}

	fw := &Forward{DB: db, Op: "SetBit", Args: args}
	return n, s.commit(bt, fw)
}
Esempio n. 30
0
// ZREMRANGEBYRANK key start stop
func (s *Store) ZRemRangeByRank(db uint32, args [][]byte) (int64, error) {
	if len(args) != 3 {
		return 0, errArguments("len(args) = %d, expect 3", len(args))
	}

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

	r := &rangeSpec{Min: math.Inf(-1), Max: math.Inf(1), MinEx: true, MaxEx: true}

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

	o, err := s.loadZSetRow(db, key)
	if err != nil {
		return 0, errors.Trace(err)
	} else if o == nil {
		return 0, nil
	}

	var rangeLen int64
	start, stop, rangeLen = sanitizeIndexes(start, stop, o.Size)

	if rangeLen == 0 {
		return 0, nil
	}

	bt := engine.NewBatch()
	n := int64(0)

	offset := int64(0)

	f := func(o *zsetRow) error {
		if offset >= start {
			bt.Del(o.DataKey())
			bt.Del(o.IndexKey())
			n++
			rangeLen--
			if rangeLen <= 0 {
				return errors.Trace(errTravelBreak)
			}

		}
		offset++
		return nil
	}

	if err := o.travelInRange(s, r, f); err != nil {
		return 0, errors.Trace(err)
	}

	if n > 0 {
		if o.Size -= n; o.Size > 0 {
			bt.Set(o.MetaKey(), o.MetaValue())
		} else {
			bt.Del(o.MetaKey())
		}
	}

	fw := &Forward{DB: db, Op: "ZRemRangeByRank", Args: args}
	return n, s.commit(bt, fw)
}