Skip to content

Commit

Permalink
fix hmslot bug
Browse files Browse the repository at this point in the history
  • Loading branch information
zhs committed Nov 28, 2018
1 parent a4d5f0f commit 87a5179
Show file tree
Hide file tree
Showing 2 changed files with 54 additions and 51 deletions.
101 changes: 52 additions & 49 deletions db/hash.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,9 +72,10 @@ func (hm *HashMeta) Decode(b []byte) error {

// Hash implements the hashtable
type Hash struct {
meta HashMeta
key []byte
txn *Transaction
meta HashMeta
key []byte
exists bool
txn *Transaction
}

// GetHash returns a hash object, create new one if nonexists
Expand Down Expand Up @@ -104,24 +105,10 @@ func GetHash(txn *Transaction, key []byte) (*Hash, error) {
if hash.meta.Type != ObjectHash {
return nil, ErrTypeMismatch
}
hash.exists = true
return hash, nil
}

//NewHash create new hashes object
func NewHash(txn *Transaction, key []byte) *Hash {
hash := &Hash{txn: txn, key: key, meta: HashMeta{}}
now := Now()
hash.meta.CreatedAt = now
hash.meta.UpdatedAt = now
hash.meta.ExpireAt = 0
hash.meta.ID = UUID()
hash.meta.Type = ObjectHash
hash.meta.Encoding = ObjectEncodingHT
hash.meta.Len = 0
hash.meta.MetaSlot = defaultHashMetaSlot
return hash
}

func hashItemKey(key []byte, field []byte) []byte {
key = append(key, ':')
return append(key, field...)
Expand Down Expand Up @@ -154,7 +141,6 @@ func (hash *Hash) HDel(fields [][]byte) (int64, error) {
var (
keys [][]byte
num int64
now = Now()
)
dkey := DataKey(hash.txn.db, hash.meta.ID)
for _, field := range fields {
Expand Down Expand Up @@ -189,28 +175,8 @@ func (hash *Hash) HDel(fields [][]byte) (int64, error) {
}

// update Len and UpdateAt
if hash.isMetaSlot() {
slotID := hash.calculateSlotID(hash.meta.MetaSlot)
slot, err := hash.getSlot(slotID)
if err != nil {
return 0, err
}
slot.Len -= num
slot.UpdatedAt = now
if err := hash.updateSlot(slotID, slot); err != nil {
return 0, err
}

} else {
hash.meta.Len -= num
hash.meta.UpdatedAt = now
if err := hash.autoUpdateSlot(defaultHashMetaSlot); err == nil {
hash.meta.MetaSlot = defaultHashMetaSlot
}
if err := hash.updateMeta(); err != nil {
return 0, err
}

if err := hash.addLen(-num); err != nil {
return 0, err
}
return num, nil
}
Expand Down Expand Up @@ -267,8 +233,7 @@ func (hash *Hash) HSet(field []byte, value []byte) (int, error) {
if exist {
return 0, nil
}
hash.meta.Len++
if err := hash.updateMeta(); err != nil {
if err := hash.addLen(1); err != nil {
return 0, err
}
return 1, nil
Expand Down Expand Up @@ -505,6 +470,18 @@ func (hash *Hash) HMSet(fields [][]byte, values [][]byte) error {

// HMSet sets meta slot num
func (hash *Hash) HMSlot(metaSlot int64) error {

if hash.isMetaSlot() {
slot, err := hash.getAllSlot()

if err == ErrKeyNotFound {
slot = &Slot{Len: 0, UpdatedAt: Now()}
} else if err != nil {
return err
}
hash.meta.Len = slot.Len
hash.meta.UpdatedAt = slot.UpdatedAt
}
if err := hash.autoUpdateSlot(metaSlot); err != nil {
return err
}
Expand All @@ -515,6 +492,29 @@ func (hash *Hash) HMSlot(metaSlot int64) error {
return nil
}

func (hash *Hash) addLen(len int64) error {
isDirty := false
if hash.isMetaSlot() {
slotID := hash.calculateSlotID(hash.meta.MetaSlot)
if err := hash.addSlotLen(slotID, len); err != nil {
return err
}
} else {
hash.meta.Len += len
hash.meta.UpdatedAt = Now()
if err := hash.autoUpdateSlot(defaultHashMetaSlot); err == nil {
hash.meta.MetaSlot = defaultHashMetaSlot
}
isDirty = true
}
if isDirty || !hash.exists {
if err := hash.updateMeta(); err != nil {
return err
}
}
return nil
}

func (hash *Hash) autoUpdateSlot(metaSlot int64) error {
isMetaSlot := hash.isMetaSlot()
if metaSlot < 0 {
Expand Down Expand Up @@ -542,7 +542,7 @@ func (hash *Hash) autoUpdateSlot(metaSlot int64) error {
return err
}
sid := hash.calculateSlotID(metaSlot)
if err := hash.mergeSlot(sid, slot); err != nil {
if err := hash.addSlotLen(sid, slot.Len); err != nil {
return err
}
if err := hash.clearSliceSlot(metaSlot, hash.meta.MetaSlot-1); err != nil {
Expand All @@ -562,18 +562,19 @@ func (hash *Hash) clearSliceSlot(start, end int64) error {
if err := hash.txn.t.Delete(metaSlotKey); err != nil {
return err
}
i++
}
return nil
}

func (hash *Hash) mergeSlot(newID int64, old *Slot) error {
new, err := hash.getSlot(newID)
func (hash *Hash) addSlotLen(newID int64, len int64) error {
slot, err := hash.getSlot(newID)
if err != nil {
return err
}
new.Len += old.Len
new.UpdatedAt = Now()
return hash.updateSlot(newID, new)
slot.Len += len
slot.UpdatedAt = Now()
return hash.updateSlot(newID, slot)
}

func (hash *Hash) getSlot(slotID int64) (*Slot, error) {
Expand Down Expand Up @@ -636,11 +637,13 @@ func (hash *Hash) getSliceSlot(start, end int64) (*Slot, error) {
}
count++
}

if len(rawSlots) > 0 {
slot, err := hash.calculateSlot(&rawSlots)
if err != nil {
return nil, err
}

return slot, nil
}
return nil, ErrKeyNotFound
Expand Down
4 changes: 2 additions & 2 deletions db/kv.go
Original file line number Diff line number Diff line change
Expand Up @@ -79,8 +79,8 @@ func (kv *Kv) Delete(keys [][]byte) (int64, error) {
continue
}
if obj.Type == ObjectHash {
hash := NewHash(kv.txn, mapping[k])
if err := hash.meta.Decode(val); err != nil {
hash, err := kv.txn.Hash(mapping[k])
if err != nil {
continue
}
if err := hash.Destroy(); err != nil {
Expand Down

0 comments on commit 87a5179

Please sign in to comment.