diff --git a/store/localstore/txn.go b/store/localstore/txn.go index e31ff236be..4a30423d5d 100644 --- a/store/localstore/txn.go +++ b/store/localstore/txn.go @@ -231,7 +231,7 @@ func (txn *dbTxn) Commit() error { txn.close() }() - return txn.doCommit() + return errors.Trace(txn.doCommit()) } func (txn *dbTxn) CommittedVersion() (kv.Version, error) { diff --git a/structure/hash.go b/structure/hash.go index 3162e819c4..5195c945a8 100644 --- a/structure/hash.go +++ b/structure/hash.go @@ -92,34 +92,40 @@ func (t *TxStructure) HGetInt64(key []byte, field []byte) (int64, error) { } func (t *TxStructure) updateHash(key []byte, field []byte, fn func(oldValue []byte) ([]byte, error)) error { - metaKey := t.encodeHashMetaKey(key) - meta, err := t.loadHashMeta(metaKey) - if err != nil { - return errors.Trace(err) - } - dataKey := t.encodeHashDataKey(key, field) - var oldValue []byte - oldValue, err = t.loadHashValue(dataKey) + oldValue, err := t.loadHashValue(dataKey) if err != nil { return errors.Trace(err) } - if oldValue == nil { - meta.Length++ - } - - var newValue []byte - newValue, err = fn(oldValue) + newValue, err := fn(oldValue) if err != nil { return errors.Trace(err) } + // Check if new value is equal to old value. + if bytes.Equal(oldValue, newValue) { + return nil + } + if err = t.txn.Set(dataKey, newValue); err != nil { return errors.Trace(err) } - return errors.Trace(t.txn.Set(metaKey, meta.Value())) + metaKey := t.encodeHashMetaKey(key) + meta, err := t.loadHashMeta(metaKey) + if err != nil { + return errors.Trace(err) + } + + if oldValue == nil { + meta.Length++ + if err = t.txn.Set(metaKey, meta.Value()); err != nil { + return errors.Trace(err) + } + } + + return nil } // HLen gets the number of fields in a hash. diff --git a/structure/structure_test.go b/structure/structure_test.go index 3b1afd348d..76c2cdd13c 100644 --- a/structure/structure_test.go +++ b/structure/structure_test.go @@ -193,7 +193,7 @@ func (s *tesTxStructureSuite) TestHash(c *C) { value, err = tx.HGet(key, []byte("fake")) c.Assert(err, IsNil) - c.Assert(err, IsNil) + c.Assert(value, IsNil) keys, err := tx.HKeys(key) c.Assert(err, IsNil) @@ -224,13 +224,41 @@ func (s *tesTxStructureSuite) TestHash(c *C) { c.Assert(err, IsNil) c.Assert(l, Equals, int64(2)) + // Test set new value which equals to old value. + value, err = tx.HGet(key, []byte("1")) + c.Assert(err, IsNil) + c.Assert(value, DeepEquals, []byte("1")) + + err = tx.HSet(key, []byte("1"), []byte("1")) + c.Assert(err, IsNil) + + value, err = tx.HGet(key, []byte("1")) + c.Assert(err, IsNil) + c.Assert(value, DeepEquals, []byte("1")) + + l, err = tx.HLen(key) + c.Assert(err, IsNil) + c.Assert(l, Equals, int64(2)) + n, err = tx.HInc(key, []byte("1"), 1) c.Assert(err, IsNil) c.Assert(n, Equals, int64(2)) + l, err = tx.HLen(key) + c.Assert(err, IsNil) + c.Assert(l, Equals, int64(2)) + + n, err = tx.HInc(key, []byte("1"), 1) + c.Assert(err, IsNil) + c.Assert(n, Equals, int64(3)) + + l, err = tx.HLen(key) + c.Assert(err, IsNil) + c.Assert(l, Equals, int64(2)) + n, err = tx.HGetInt64(key, []byte("1")) c.Assert(err, IsNil) - c.Assert(n, Equals, int64(2)) + c.Assert(n, Equals, int64(3)) l, err = tx.HLen(key) c.Assert(err, IsNil) @@ -246,6 +274,55 @@ func (s *tesTxStructureSuite) TestHash(c *C) { err = tx.HDel(key, []byte("fake_key")) c.Assert(err, IsNil) + // Test set nil value. + value, err = tx.HGet(key, []byte("nil_key")) + c.Assert(err, IsNil) + c.Assert(value, IsNil) + + l, err = tx.HLen(key) + c.Assert(err, IsNil) + c.Assert(l, Equals, int64(0)) + + err = tx.HSet(key, []byte("nil_key"), nil) + c.Assert(err, IsNil) + + l, err = tx.HLen(key) + c.Assert(err, IsNil) + c.Assert(l, Equals, int64(0)) + + err = tx.HSet(key, []byte("nil_key"), []byte("1")) + c.Assert(err, IsNil) + + l, err = tx.HLen(key) + c.Assert(err, IsNil) + c.Assert(l, Equals, int64(1)) + + value, err = tx.HGet(key, []byte("nil_key")) + c.Assert(err, IsNil) + c.Assert(value, DeepEquals, []byte("1")) + + err = tx.HSet(key, []byte("nil_key"), nil) + c.Assert(err, NotNil) + + l, err = tx.HLen(key) + c.Assert(err, IsNil) + c.Assert(l, Equals, int64(1)) + + value, err = tx.HGet(key, []byte("nil_key")) + c.Assert(err, IsNil) + c.Assert(value, DeepEquals, []byte("1")) + + err = tx.HSet(key, []byte("nil_key"), []byte("2")) + c.Assert(err, IsNil) + + l, err = tx.HLen(key) + c.Assert(err, IsNil) + c.Assert(l, Equals, int64(1)) + + value, err = tx.HGet(key, []byte("nil_key")) + c.Assert(err, IsNil) + c.Assert(value, DeepEquals, []byte("2")) + err = txn.Commit() c.Assert(err, IsNil)