mirror of
https://github.com/etcd-io/etcd.git
synced 2024-09-27 06:25:44 +00:00
Merge pull request #3616 from yichengq/storage-txn
storage: hold batchTx lock during KV txn
This commit is contained in:
commit
21179d929f
@ -51,6 +51,7 @@ type store struct {
|
|||||||
// the main revision of the last compaction
|
// the main revision of the last compaction
|
||||||
compactMainRev int64
|
compactMainRev int64
|
||||||
|
|
||||||
|
tx backend.BatchTx
|
||||||
tmu sync.Mutex // protect the txnID field
|
tmu sync.Mutex // protect the txnID field
|
||||||
txnID int64 // tracks the current txnID to verify txn operations
|
txnID int64 // tracks the current txnID to verify txn operations
|
||||||
|
|
||||||
@ -121,6 +122,8 @@ func (s *store) DeleteRange(key, end []byte) (n, rev int64) {
|
|||||||
func (s *store) TxnBegin() int64 {
|
func (s *store) TxnBegin() int64 {
|
||||||
s.mu.Lock()
|
s.mu.Lock()
|
||||||
s.currentRev.sub = 0
|
s.currentRev.sub = 0
|
||||||
|
s.tx = s.b.BatchTx()
|
||||||
|
s.tx.Lock()
|
||||||
|
|
||||||
s.tmu.Lock()
|
s.tmu.Lock()
|
||||||
defer s.tmu.Unlock()
|
defer s.tmu.Unlock()
|
||||||
@ -147,6 +150,7 @@ func (s *store) txnEnd(txnID int64) error {
|
|||||||
return ErrTxnIDMismatch
|
return ErrTxnIDMismatch
|
||||||
}
|
}
|
||||||
|
|
||||||
|
s.tx.Unlock()
|
||||||
if s.currentRev.sub != 0 {
|
if s.currentRev.sub != 0 {
|
||||||
s.currentRev.main += 1
|
s.currentRev.main += 1
|
||||||
}
|
}
|
||||||
@ -393,14 +397,11 @@ func (s *store) rangeKeys(key, end []byte, limit, rangeRev int64) (kvs []storage
|
|||||||
return nil, rev, nil
|
return nil, rev, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
tx := s.b.BatchTx()
|
|
||||||
tx.Lock()
|
|
||||||
defer tx.Unlock()
|
|
||||||
for _, revpair := range revpairs {
|
for _, revpair := range revpairs {
|
||||||
revbytes := newRevBytes()
|
revbytes := newRevBytes()
|
||||||
revToBytes(revpair, revbytes)
|
revToBytes(revpair, revbytes)
|
||||||
|
|
||||||
_, vs := tx.UnsafeRange(keyBucketName, revbytes, nil, 0)
|
_, vs := s.tx.UnsafeRange(keyBucketName, revbytes, nil, 0)
|
||||||
if len(vs) != 1 {
|
if len(vs) != 1 {
|
||||||
log.Fatalf("storage: range cannot find rev (%d,%d)", revpair.main, revpair.sub)
|
log.Fatalf("storage: range cannot find rev (%d,%d)", revpair.main, revpair.sub)
|
||||||
}
|
}
|
||||||
@ -447,10 +448,7 @@ func (s *store) put(key, value []byte) {
|
|||||||
log.Fatalf("storage: cannot marshal event: %v", err)
|
log.Fatalf("storage: cannot marshal event: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
tx := s.b.BatchTx()
|
s.tx.UnsafePut(keyBucketName, ibytes, d)
|
||||||
tx.Lock()
|
|
||||||
defer tx.Unlock()
|
|
||||||
tx.UnsafePut(keyBucketName, ibytes, d)
|
|
||||||
s.kvindex.Put(key, revision{main: rev, sub: s.currentRev.sub})
|
s.kvindex.Put(key, revision{main: rev, sub: s.currentRev.sub})
|
||||||
s.currentRev.sub += 1
|
s.currentRev.sub += 1
|
||||||
}
|
}
|
||||||
@ -475,10 +473,6 @@ func (s *store) deleteRange(key, end []byte) int64 {
|
|||||||
func (s *store) delete(key []byte) {
|
func (s *store) delete(key []byte) {
|
||||||
mainrev := s.currentRev.main + 1
|
mainrev := s.currentRev.main + 1
|
||||||
|
|
||||||
tx := s.b.BatchTx()
|
|
||||||
tx.Lock()
|
|
||||||
defer tx.Unlock()
|
|
||||||
|
|
||||||
ibytes := newRevBytes()
|
ibytes := newRevBytes()
|
||||||
revToBytes(revision{main: mainrev, sub: s.currentRev.sub}, ibytes)
|
revToBytes(revision{main: mainrev, sub: s.currentRev.sub}, ibytes)
|
||||||
|
|
||||||
@ -494,7 +488,7 @@ func (s *store) delete(key []byte) {
|
|||||||
log.Fatalf("storage: cannot marshal event: %v", err)
|
log.Fatalf("storage: cannot marshal event: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
tx.UnsafePut(keyBucketName, ibytes, d)
|
s.tx.UnsafePut(keyBucketName, ibytes, d)
|
||||||
err = s.kvindex.Tombstone(key, revision{main: mainrev, sub: s.currentRev.sub})
|
err = s.kvindex.Tombstone(key, revision{main: mainrev, sub: s.currentRev.sub})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("storage: cannot tombstone an existing key (%s): %v", string(key), err)
|
log.Fatalf("storage: cannot tombstone an existing key (%s): %v", string(key), err)
|
||||||
|
@ -101,6 +101,7 @@ func TestStorePut(t *testing.T) {
|
|||||||
for i, tt := range tests {
|
for i, tt := range tests {
|
||||||
s, b, index := newFakeStore()
|
s, b, index := newFakeStore()
|
||||||
s.currentRev = tt.rev
|
s.currentRev = tt.rev
|
||||||
|
s.tx = b.BatchTx()
|
||||||
index.indexGetRespc <- tt.r
|
index.indexGetRespc <- tt.r
|
||||||
|
|
||||||
s.put([]byte("foo"), []byte("bar"))
|
s.put([]byte("foo"), []byte("bar"))
|
||||||
@ -162,6 +163,7 @@ func TestStoreRange(t *testing.T) {
|
|||||||
for i, tt := range tests {
|
for i, tt := range tests {
|
||||||
s, b, index := newFakeStore()
|
s, b, index := newFakeStore()
|
||||||
s.currentRev = currev
|
s.currentRev = currev
|
||||||
|
s.tx = b.BatchTx()
|
||||||
b.tx.rangeRespc <- tt.r
|
b.tx.rangeRespc <- tt.r
|
||||||
index.indexRangeRespc <- tt.idxr
|
index.indexRangeRespc <- tt.idxr
|
||||||
|
|
||||||
@ -221,6 +223,7 @@ func TestStoreDeleteRange(t *testing.T) {
|
|||||||
for i, tt := range tests {
|
for i, tt := range tests {
|
||||||
s, b, index := newFakeStore()
|
s, b, index := newFakeStore()
|
||||||
s.currentRev = tt.rev
|
s.currentRev = tt.rev
|
||||||
|
s.tx = b.BatchTx()
|
||||||
index.indexRangeRespc <- tt.r
|
index.indexRangeRespc <- tt.r
|
||||||
|
|
||||||
n := s.deleteRange([]byte("foo"), []byte("goo"))
|
n := s.deleteRange([]byte("foo"), []byte("goo"))
|
||||||
@ -649,6 +652,32 @@ func TestRestoreContinueUnfinishedCompaction(t *testing.T) {
|
|||||||
tx.Unlock()
|
tx.Unlock()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestTxnBlockBackendForceCommit(t *testing.T) {
|
||||||
|
s := newStore(tmpPath)
|
||||||
|
defer os.Remove(tmpPath)
|
||||||
|
|
||||||
|
id := s.TxnBegin()
|
||||||
|
|
||||||
|
done := make(chan struct{})
|
||||||
|
go func() {
|
||||||
|
s.b.ForceCommit()
|
||||||
|
done <- struct{}{}
|
||||||
|
}()
|
||||||
|
select {
|
||||||
|
case <-done:
|
||||||
|
t.Fatalf("failed to block ForceCommit")
|
||||||
|
case <-time.After(100 * time.Millisecond):
|
||||||
|
}
|
||||||
|
|
||||||
|
s.TxnEnd(id)
|
||||||
|
select {
|
||||||
|
case <-done:
|
||||||
|
case <-time.After(100 * time.Millisecond):
|
||||||
|
t.Fatalf("failed to execute ForceCommit")
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
func BenchmarkStorePut(b *testing.B) {
|
func BenchmarkStorePut(b *testing.B) {
|
||||||
s := newStore(tmpPath)
|
s := newStore(tmpPath)
|
||||||
defer os.Remove(tmpPath)
|
defer os.Remove(tmpPath)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user