func Srem(args [][]byte, wb *levigo.WriteBatch) interface{} { mk := metaKey(args[0]) card, err := scard(mk, nil) if err != nil { return err } if card == 0 { return card } var deleted uint32 key := NewKeyBuffer(SetKey, args[0], len(args[1])) for _, member := range args[1:] { key.SetSuffix(member) res, err := DB.Get(ReadWithoutCacheFill, key.Key()) if err != nil { return err } if res == nil { continue } wb.Delete(key.Key()) deleted++ } if deleted == card { wb.Delete(mk) } else if deleted > 0 { // decrement the cardinality setCard(mk, card-deleted, wb) } return deleted }
func Hdel(args [][]byte, wb *levigo.WriteBatch) interface{} { mk := metaKey(args[0]) length, err := hlen(mk, nil) if err != nil { return err } if length == 0 { return 0 } var deleted uint32 key := NewKeyBuffer(HashKey, args[0], len(args[1])) for _, field := range args[1:] { key.SetSuffix(field) res, err := DB.Get(ReadWithoutCacheFill, key.Key()) if err != nil { return err } if res == nil { continue } wb.Delete(key.Key()) deleted++ } if deleted == length { wb.Delete(mk) } else if deleted > 0 { setHlen(mk, length-deleted, wb) } return deleted }
func DelHash(key []byte, wb *levigo.WriteBatch) { it := DB.NewIterator(ReadWithoutCacheFill) defer it.Close() iterKey := NewKeyBuffer(HashKey, key, 0) for it.Seek(iterKey.Key()); it.Valid(); it.Next() { k := it.Key() if !iterKey.IsPrefixOf(k) { break } wb.Delete(k) } }
func DelSet(key []byte, wb *levigo.WriteBatch) { it := DB.NewIterator(ReadWithoutCacheFill) defer it.Close() iterKey := NewKeyBuffer(SetKey, key, 0) for it.Seek(iterKey.Key()); it.Valid(); it.Next() { k := it.Key() // If the prefix of the current key doesn't match the iteration key, // we have reached the end of the set if !iterKey.IsPrefixOf(k) { break } wb.Delete(k) } }
// TODO: refactor with above. func RemoveIndex(index [2]string, key []byte, indexDb *levigo.DB, wb *levigo.WriteBatch) error { searchKey := []byte(index[0] + "~" + index[1]) keys, err := indexDb.Get(LReadOptions, searchKey) if err != nil { return err } keys = removeDataKey(keys, key) if len(keys) > 0 { wb.Put(searchKey, keys) } else { wb.Delete(searchKey) } return nil }
func delKey(key []byte, wb *levigo.WriteBatch) (deleted bool, err error) { res, err := DB.Get(ReadWithoutCacheFill, key) if err != nil { return } if res == nil { return } if len(res) < 1 { return false, InvalidDataError } del(key[1:], res[0], wb) wb.Delete(key) return true, nil }
func lpop(key []byte, left bool, wb *levigo.WriteBatch) (interface{}, error) { mk := metaKey(key) l, err := llen(mk, nil) if err != nil { return nil, err } if l.length == 0 { return nil, nil } iterKey := NewKeyBuffer(ListKey, key, 0) it := DB.NewIterator(ReadWithoutCacheFill) defer it.Close() if !left { iterKey.ReverseIterKey() } it.Seek(iterKey.Key()) if !left { it.Prev() } if !it.Valid() { return nil, nil } k := it.Key() if !iterKey.IsPrefixOf(k) { return nil, nil } res := it.Value() wb.Delete(k) l.length-- if l.length == 0 { wb.Delete(mk) } else { // decode the sequence number from the list item key seq := int64(binary.BigEndian.Uint64(k[len(key)+5:])) + math.MinInt64 if left { l.left = seq } else { l.right = seq } setLlen(mk, l, wb) } return res, nil }
func DelZset(key []byte, wb *levigo.WriteBatch) { // TODO: count keys to verify everything works as expected? it := DB.NewIterator(ReadWithoutCacheFill) defer it.Close() iterKey := NewKeyBuffer(ZSetKey, key, 0) scoreKey := NewKeyBuffer(ZScoreKey, key, 0) for it.Seek(iterKey.Key()); it.Valid(); it.Next() { k := it.Key() // If the prefix of the current key doesn't match the iteration key, // we have reached the end of the zset if !iterKey.IsPrefixOf(k) { break } wb.Delete(k) setZScoreKeyMember(scoreKey, k[len(iterKey.Key()):]) setZScoreKeyScore(scoreKey, btof(it.Value())) wb.Delete(scoreKey.Key()) } }
func Spop(args [][]byte, wb *levigo.WriteBatch) interface{} { mk := metaKey(args[0]) card, err := scard(mk, nil) if err != nil { return err } if card == 0 { return nil } key := NewKeyBuffer(SetKey, args[0], 1) member := srand(key) if member == nil { return nil } key.SetSuffix(member) wb.Delete(key.Key()) if card == 1 { // we're removing the last remaining member wb.Delete(mk) } else { setCard(mk, card-1, wb) } return member }
func Zrem(args [][]byte, wb *levigo.WriteBatch) interface{} { mk := metaKey(args[0]) card, err := zcard(mk, nil) if err != nil { return err } if card == 0 { return 0 } var deleted uint32 setKey := NewKeyBuffer(ZSetKey, args[0], len(args[1])) scoreKey := NewKeyBuffer(ZScoreKey, args[0], 8+len(args[1])) // Delete each of the members for _, member := range args[1:] { setKey.SetSuffix(member) res, err := DB.Get(ReadWithoutCacheFill, setKey.Key()) if err != nil { return nil } if res == nil { continue } if len(res) != 8 { return InvalidDataError } score := btof(res) setZScoreKeyMember(scoreKey, member) setZScoreKeyScore(scoreKey, score) wb.Delete(setKey.Key()) wb.Delete(scoreKey.Key()) deleted++ } if deleted == card { // We deleted all of the members, so delete the meta key wb.Delete(mk) } else if deleted > 0 { // Decrement the cardinality setZcard(mk, card-deleted, wb) } return deleted }
func zrangebyscore(args [][]byte, flag zrangeFlag, wb *levigo.WriteBatch) interface{} { // use a snapshot for this read so that the zcard is consistent snapshot := DB.NewSnapshot() opts := levigo.NewReadOptions() opts.SetSnapshot(snapshot) defer opts.Close() defer DB.ReleaseSnapshot(snapshot) mk := metaKey(args[0]) card, err := zcard(mk, opts) if err != nil { return err } var minExclusive, maxExclusive bool if args[1][0] == '(' { minExclusive = true args[1] = args[1][1:] } if args[2][0] == '(' { maxExclusive = true args[2] = args[2][1:] } min, err := bconv.ParseFloat(args[1], 64) max, err2 := bconv.ParseFloat(args[2], 64) if err != nil || err2 != nil { return fmt.Errorf("min or max is not a float") } if flag == zrangeReverse { min, max = max, min minExclusive, maxExclusive = maxExclusive, minExclusive } if card == 0 || min > max { if flag <= zrangeReverse { return []interface{}{} } else { return 0 } } // shortcut for zcount of -Inf to +Inf if flag == zrangeCount && math.IsInf(min, -1) && math.IsInf(max, 1) { return card } var withscores bool var offset, total int64 = 0, -1 if flag <= zrangeReverse && len(args) > 3 { if len(args) == 4 || len(args) == 7 { if EqualIgnoreCase(args[3], []byte("withscores")) { withscores = true } } else if len(args) != 6 { return SyntaxError } if len(args) >= 6 { if EqualIgnoreCase(args[len(args)-3], []byte("limit")) { offset, err = bconv.ParseInt(args[len(args)-2], 10, 64) total, err2 = bconv.ParseInt(args[len(args)-1], 10, 64) if err != nil || err2 != nil { return InvalidIntError } if offset < 0 || total < 1 { return []interface{}{} } } else { return SyntaxError } } } it := DB.NewIterator(opts) defer it.Close() var deleted, count uint32 var deleteKey *KeyBuffer if flag == zrangeDelete { deleteKey = NewKeyBuffer(ZSetKey, args[0], 0) } res := []interface{}{} iterKey := NewKeyBuffer(ZScoreKey, args[0], 8) if flag != zrangeReverse { setZScoreKeyScore(iterKey, min) } else { setZScoreKeyScore(iterKey, max) iterKey.ReverseIterKey() } it.Seek(iterKey.Key()) for i := int64(0); it.Valid(); i++ { if flag == zrangeReverse { it.Prev() } if i >= offset { if total > -1 && i-offset >= total { break } k := it.Key() if !iterKey.IsPrefixOf(k) { break } score, member := parseZScoreKey(it.Key(), len(args[0])) if (!minExclusive && score < min) || (minExclusive && score <= min) { if flag != zrangeReverse { it.Next() } continue } if (!maxExclusive && score > max) || (maxExclusive && score >= max) { break } if flag <= zrangeReverse { res = append(res, member) if withscores { res = append(res, ftoa(score)) } } if flag == zrangeDelete { deleteKey.SetSuffix(member) wb.Delete(k) wb.Delete(deleteKey.Key()) deleted++ } if flag == zrangeCount { count++ } } if flag != zrangeReverse { it.Next() } } if flag == zrangeDelete && deleted == card { wb.Delete(mk) } else if deleted > 0 { setZcard(mk, card-deleted, wb) } if flag == zrangeDelete { return deleted } if flag == zrangeCount { return count } return res }
func zadd(args [][]byte, wb *levigo.WriteBatch, incr bool) interface{} { var newMembers uint32 var score float64 scoreBytes := make([]byte, 8) setKey := NewKeyBuffer(ZSetKey, args[0], len(args[2])) scoreKey := NewKeyBuffer(ZScoreKey, args[0], 8+len(args[2])) mk := metaKey(args[0]) card, err := zcard(mk, nil) if err != nil { return err } // Iterate through each of the score/member pairs for i := 1; i < len(args); i += 2 { var err error score, err = bconv.ParseFloat(args[i], 64) if err != nil { return fmt.Errorf("'%s' is not a valid float", string(args[1])) } // Check if the member exists setKey.SetSuffix(args[i+1]) var res []byte if card > 0 { res, err = DB.Get(DefaultReadOptions, setKey.Key()) if err != nil { return err } } // set the score key with 8 empty bytes before the member for the score setZScoreKeyMember(scoreKey, args[i+1]) if res != nil { // We got a score from the db, so the member already exists if len(res) != 8 { return InvalidDataError } actualScore := math.Float64frombits(binary.BigEndian.Uint64(res)) if incr { // this is a ZINCRBY, so increment the score score += actualScore } if score == actualScore { // Member already exists with the same score, do nothing continue } // Delete score key for member setZScoreKeyScore(scoreKey, actualScore) wb.Delete(scoreKey.Key()) } else { // No score found, we're adding a new member newMembers++ } // Store the set and score keys binary.BigEndian.PutUint64(scoreBytes, math.Float64bits(score)) setZScoreKeyScore(scoreKey, score) wb.Put(setKey.Key(), scoreBytes) wb.Put(scoreKey.Key(), []byte{}) // The score key is only used for sorting, the value is empty } // Update the set metadata with the new cardinality if newMembers > 0 { setZcard(mk, card+newMembers, wb) } if incr { // This is a ZINCRBY, return the new score return ftoa(score) } return newMembers }
func DelString(key []byte, wb *levigo.WriteBatch) { wb.Delete(stringKey(key)) }