github.com/matrixorigin/matrixone@v1.2.0/pkg/txn/storage/mem/kv_txn_storage_test.go (about)

     1  // Copyright 2021 - 2022 Matrix Origin
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //      http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package mem
    16  
    17  import (
    18  	"bytes"
    19  	"context"
    20  	"math"
    21  	"sync/atomic"
    22  	"testing"
    23  
    24  	"github.com/google/uuid"
    25  	"github.com/matrixorigin/matrixone/pkg/common/moerr"
    26  	"github.com/matrixorigin/matrixone/pkg/logservice"
    27  	"github.com/matrixorigin/matrixone/pkg/pb/timestamp"
    28  	"github.com/matrixorigin/matrixone/pkg/pb/txn"
    29  	"github.com/matrixorigin/matrixone/pkg/txn/clock"
    30  	"github.com/stretchr/testify/assert"
    31  )
    32  
    33  func TestWrite(t *testing.T) {
    34  	l := NewMemLog()
    35  	s := NewKVTxnStorage(0, l, newTestClock(1))
    36  
    37  	wTxn := writeTestData(t, s, 1, moerr.Ok, 1, 2)
    38  	checkUncommitted(t, s, wTxn, 1, 2)
    39  	checkLogCount(t, l, 0)
    40  }
    41  
    42  func TestWriteWithConflict(t *testing.T) {
    43  	l := NewMemLog()
    44  	s := NewKVTxnStorage(0, l, newTestClock(1))
    45  
    46  	wTxn1 := writeTestData(t, s, 1, moerr.Ok, 1)
    47  	checkUncommitted(t, s, wTxn1, 1)
    48  
    49  	writeTestData(t, s, 1, moerr.ErrTxnWriteConflict, 1)
    50  
    51  	wTxn3 := writeTestData(t, s, 1, moerr.Ok, 2)
    52  	checkUncommitted(t, s, wTxn3, 2)
    53  }
    54  
    55  func TestPrepare(t *testing.T) {
    56  	l := NewMemLog()
    57  	s := NewKVTxnStorage(0, l, newTestClock(1))
    58  
    59  	wTxn := writeTestData(t, s, 1, moerr.Ok, 1)
    60  
    61  	prepareTestTxn(t, s, &wTxn, 2, moerr.Ok)
    62  
    63  	checkUncommitted(t, s, wTxn, 1)
    64  	checkLogCount(t, l, 1)
    65  	checkLog(t, l, 1, wTxn, 1)
    66  }
    67  
    68  func TestPrepareWithConflict(t *testing.T) {
    69  	l := NewMemLog()
    70  	s := NewKVTxnStorage(0, l, newTestClock(1))
    71  
    72  	writeCommittedData(t, s, 1, 100, 1) // commit at 100
    73  
    74  	wTxn := writeTestData(t, s, 1, moerr.Ok, 1)
    75  	prepareTestTxn(t, s, &wTxn, 5, moerr.ErrTxnWriteConflict) // prepare at 5
    76  }
    77  
    78  func TestCommit(t *testing.T) {
    79  	l := NewMemLog()
    80  	s := NewKVTxnStorage(0, l, newTestClock(1))
    81  
    82  	wTxn := writeTestData(t, s, 1, moerr.Ok, 1)
    83  	commitTestTxn(t, s, &wTxn, 2, moerr.Ok)
    84  
    85  	checkCommitted(t, s, wTxn, 1)
    86  	checkLogCount(t, l, 1)
    87  	checkLog(t, l, 1, wTxn, 1)
    88  }
    89  
    90  func TestCommitWithTxnNotExist(t *testing.T) {
    91  	l := NewMemLog()
    92  	s := NewKVTxnStorage(0, l, newTestClock(1))
    93  
    94  	commitTestTxn(t, s, &txn.TxnMeta{}, 2, moerr.Ok)
    95  }
    96  
    97  func TestCommitWithConflict(t *testing.T) {
    98  	l := NewMemLog()
    99  	s := NewKVTxnStorage(0, l, newTestClock(1))
   100  
   101  	writeCommittedData(t, s, 1, 2, 1)
   102  
   103  	wTxn := writeTestData(t, s, 1, moerr.Ok, 1)
   104  	commitTestTxn(t, s, &wTxn, 5, moerr.ErrTxnWriteConflict)
   105  }
   106  
   107  func TestCommitAfterPrepared(t *testing.T) {
   108  	l := NewMemLog()
   109  	s := NewKVTxnStorage(0, l, newTestClock(1))
   110  
   111  	wTxn := writeTestData(t, s, 1, moerr.Ok, 1)
   112  	prepareTestTxn(t, s, &wTxn, 2, moerr.Ok)
   113  	commitTestTxn(t, s, &wTxn, 3, moerr.Ok)
   114  
   115  	checkCommitted(t, s, wTxn, 1)
   116  	checkLogCount(t, l, 2)
   117  	checkLog(t, l, 2, wTxn)
   118  }
   119  
   120  func TestRollback(t *testing.T) {
   121  	l := NewMemLog()
   122  	s := NewKVTxnStorage(0, l, newTestClock(1))
   123  
   124  	wTxn := writeTestData(t, s, 1, moerr.Ok, 1)
   125  	checkUncommitted(t, s, wTxn, 1)
   126  
   127  	assert.NoError(t, s.Rollback(context.TODO(), wTxn))
   128  	checkRollback(t, s, wTxn, 1)
   129  }
   130  
   131  func TestRollbackWithTxnNotExist(t *testing.T) {
   132  	l := NewMemLog()
   133  	s := NewKVTxnStorage(0, l, newTestClock(1))
   134  
   135  	assert.NoError(t, s.Rollback(context.TODO(), txn.TxnMeta{}))
   136  	checkRollback(t, s, txn.TxnMeta{})
   137  }
   138  
   139  func TestReadCommittedWithLessVersion(t *testing.T) {
   140  	l := NewMemLog()
   141  	s := NewKVTxnStorage(0, l, newTestClock(1))
   142  
   143  	writeCommittedData(t, s, 0, 1, 1)
   144  
   145  	_, rs := readTestData(t, s, 2, nil, 1)
   146  	checkReadResult(t, 0, rs, 1)
   147  }
   148  
   149  func TestReadSelfUncommitted(t *testing.T) {
   150  	l := NewMemLog()
   151  	s := NewKVTxnStorage(0, l, newTestClock(1))
   152  
   153  	wTxn := writeTestData(t, s, 1, moerr.Ok, 1)
   154  	rs := readTestDataWithTxn(t, s, &wTxn, nil, 1)
   155  	checkReadResult(t, 1, rs, 1)
   156  }
   157  
   158  func TestReadCommittedWithGTVersion(t *testing.T) {
   159  	l := NewMemLog()
   160  	s := NewKVTxnStorage(0, l, newTestClock(1))
   161  
   162  	writeCommittedData(t, s, 0, 1, 1)
   163  
   164  	_, rs := readTestData(t, s, 1, nil, 1)
   165  	checkReadResult(t, 0, rs, 0)
   166  }
   167  
   168  func TestWaitReadByPreparedTxn(t *testing.T) {
   169  	l := NewMemLog()
   170  	s := NewKVTxnStorage(0, l, newTestClock(1))
   171  
   172  	writeCommittedData(t, s, 0, 1, 1)
   173  
   174  	wTxn := writeTestData(t, s, 2, moerr.Ok, 1)
   175  	prepareTestTxn(t, s, &wTxn, 5, moerr.Ok)
   176  
   177  	readTestData(t, s, 6, [][]byte{wTxn.ID}, 1)
   178  }
   179  
   180  func TestReadByGTPreparedTxnCanNotWait(t *testing.T) {
   181  	l := NewMemLog()
   182  	s := NewKVTxnStorage(0, l, newTestClock(1))
   183  
   184  	writeCommittedData(t, s, 0, 1, 1)
   185  
   186  	wTxn := writeTestData(t, s, 2, moerr.Ok, 1)
   187  	prepareTestTxn(t, s, &wTxn, 5, moerr.Ok)
   188  
   189  	readTestData(t, s, 2, nil, 1)
   190  }
   191  
   192  func TestWaitReadByCommittingTxn(t *testing.T) {
   193  	l := NewMemLog()
   194  	s := NewKVTxnStorage(0, l, newTestClock(1))
   195  
   196  	writeCommittedData(t, s, 0, 1, 1)
   197  
   198  	wTxn := writeTestData(t, s, 2, moerr.Ok, 1)
   199  	prepareTestTxn(t, s, &wTxn, 5, moerr.Ok)
   200  	committingTestTxn(t, s, &wTxn, 6)
   201  
   202  	readTestData(t, s, 7, [][]byte{wTxn.ID}, 1)
   203  }
   204  
   205  func TestReadByGTCommittingTxnCanNotWait(t *testing.T) {
   206  	l := NewMemLog()
   207  	s := NewKVTxnStorage(0, l, newTestClock(1))
   208  
   209  	writeCommittedData(t, s, 0, 1, 1)
   210  
   211  	wTxn := writeTestData(t, s, 2, moerr.Ok, 1)
   212  	prepareTestTxn(t, s, &wTxn, 3, moerr.Ok)
   213  	committingTestTxn(t, s, &wTxn, 4)
   214  
   215  	readTestData(t, s, 3, nil, 1)
   216  }
   217  
   218  func TestReadAfterWaitTxnResloved(t *testing.T) {
   219  	l := NewMemLog()
   220  	s := NewKVTxnStorage(0, l, newTestClock(1))
   221  
   222  	wTxn1 := writeTestData(t, s, 1, moerr.Ok, 1)
   223  	prepareTestTxn(t, s, &wTxn1, 2, moerr.Ok)
   224  
   225  	wTxn2 := writeTestData(t, s, 1, moerr.Ok, 2)
   226  	prepareTestTxn(t, s, &wTxn2, 2, moerr.Ok)
   227  
   228  	_, rs := readTestData(t, s, 5, [][]byte{wTxn1.ID, wTxn2.ID}, 1, 2)
   229  	_, err := rs.Read()
   230  	assert.True(t, moerr.IsMoErrCode(err, moerr.ErrMissingTxn))
   231  
   232  	commitTestTxn(t, s, &wTxn2, 6, moerr.Ok)
   233  	_, err = rs.Read()
   234  	assert.True(t, moerr.IsMoErrCode(err, moerr.ErrMissingTxn))
   235  
   236  	commitTestTxn(t, s, &wTxn1, 4, moerr.Ok)
   237  
   238  	checkReadResult(t, 1, rs, 1, 0)
   239  }
   240  
   241  func TestRecovery(t *testing.T) {
   242  	l := NewMemLog()
   243  	s := NewKVTxnStorage(0, l, newTestClock(1))
   244  
   245  	prepareTxn := writeTestData(t, s, 1, moerr.Ok, 1)
   246  	prepareTestTxn(t, s, &prepareTxn, 2, moerr.Ok)
   247  	checkLog(t, l, 1, prepareTxn, 1)
   248  
   249  	committedTxn := writeTestData(t, s, 1, moerr.Ok, 2)
   250  	commitTestTxn(t, s, &committedTxn, 3, moerr.Ok)
   251  	checkLog(t, l, 2, committedTxn, 2)
   252  
   253  	committedAndPreparedTxn := writeTestData(t, s, 1, moerr.Ok, 3)
   254  	prepareTestTxn(t, s, &committedAndPreparedTxn, 2, moerr.Ok)
   255  	checkLog(t, l, 3, committedAndPreparedTxn, 3)
   256  	commitTestTxn(t, s, &committedAndPreparedTxn, 3, moerr.Ok)
   257  	checkLog(t, l, 4, committedAndPreparedTxn)
   258  
   259  	committingTxn := writeTestData(t, s, 1, moerr.Ok, 4)
   260  	prepareTestTxn(t, s, &committingTxn, 2, moerr.Ok)
   261  	checkLog(t, l, 5, committingTxn, 4)
   262  	committingTestTxn(t, s, &committingTxn, 3)
   263  	checkLog(t, l, 6, committingTxn)
   264  
   265  	checkLogCount(t, l, 6)
   266  
   267  	c := make(chan txn.TxnMeta, 10)
   268  	s2 := NewKVTxnStorage(1, l, newTestClock(1))
   269  	s2.StartRecovery(context.TODO(), c)
   270  
   271  	checkUncommitted(t, s2, prepareTxn, 1)
   272  	checkCommitted(t, s2, committedTxn, 2)
   273  	checkCommitted(t, s2, committedAndPreparedTxn, 3)
   274  	checkUncommitted(t, s2, committingTxn, 4)
   275  
   276  	txns := make([]txn.TxnMeta, 0, 6)
   277  	for v := range c {
   278  		txns = append(txns, v)
   279  	}
   280  	assert.Equal(t, 6, len(txns))
   281  }
   282  
   283  func TestEvent(t *testing.T) {
   284  	l := NewMemLog()
   285  	s := NewKVTxnStorage(0, l, newTestClock(1))
   286  
   287  	wTxn := writeTestData(t, s, 1, moerr.Ok, 1)
   288  	prepareTestTxn(t, s, &wTxn, 2, moerr.Ok)
   289  	e := <-s.GetEventC()
   290  	assert.Equal(t, e, Event{Type: PrepareType, Txn: wTxn})
   291  
   292  	committingTestTxn(t, s, &wTxn, 3)
   293  	e = <-s.GetEventC()
   294  	assert.Equal(t, e, Event{Type: CommittingType, Txn: wTxn})
   295  
   296  	commitTestTxn(t, s, &wTxn, 3, moerr.Ok)
   297  	e = <-s.GetEventC()
   298  	assert.Equal(t, e, Event{Type: CommitType, Txn: wTxn})
   299  
   300  	wTxn = writeTestData(t, s, 1, moerr.Ok, 2)
   301  	assert.NoError(t, s.Rollback(context.TODO(), wTxn))
   302  	checkRollback(t, s, wTxn, 2)
   303  	e = <-s.GetEventC()
   304  	assert.Equal(t, e, Event{Type: RollbackType, Txn: wTxn})
   305  }
   306  
   307  func prepareTestTxn(t *testing.T, s *KVTxnStorage, wTxn *txn.TxnMeta, ts int64, errCode uint16) {
   308  	wTxn.PreparedTS = newTimestamp(ts)
   309  	pts, perr := s.Prepare(context.TODO(), *wTxn)
   310  	assert.True(t, moerr.IsMoErrCode(perr, errCode))
   311  	wTxn.Status = txn.TxnStatus_Prepared
   312  	wTxn.PreparedTS = pts
   313  }
   314  
   315  func committingTestTxn(t *testing.T, s *KVTxnStorage, wTxn *txn.TxnMeta, ts int64) {
   316  	wTxn.CommitTS = newTimestamp(ts)
   317  	assert.NoError(t, s.Committing(context.TODO(), *wTxn))
   318  	wTxn.Status = txn.TxnStatus_Committing
   319  }
   320  
   321  func commitTestTxn(t *testing.T, s *KVTxnStorage, wTxn *txn.TxnMeta, ts int64, errCode uint16) {
   322  	wTxn.CommitTS = newTimestamp(ts)
   323  	_, e := s.Commit(context.TODO(), *wTxn)
   324  	assert.True(t, moerr.IsMoErrCode(e, errCode))
   325  	wTxn.Status = txn.TxnStatus_Committed
   326  }
   327  
   328  func checkLogCount(t *testing.T, ll logservice.Client, expect int) {
   329  	l := ll.(*memLogClient)
   330  
   331  	l.RLock()
   332  	defer l.RUnlock()
   333  
   334  	assert.Equal(t, expect, len(l.logs))
   335  }
   336  
   337  func checkLog(t *testing.T, ll logservice.Client, offset int, wTxn txn.TxnMeta, keys ...byte) {
   338  	l := ll.(*memLogClient)
   339  
   340  	l.RLock()
   341  	defer l.RUnlock()
   342  
   343  	klog := &KVLog{}
   344  	klog.Txn = wTxn
   345  	for _, k := range keys {
   346  		key := []byte{k}
   347  		value := []byte{k, byte(wTxn.SnapshotTS.PhysicalTime)}
   348  
   349  		klog.Keys = append(klog.Keys, key)
   350  		klog.Values = append(klog.Values, value)
   351  	}
   352  
   353  	assert.Equal(t, klog.MustMarshal(), l.logs[offset-1].Data)
   354  }
   355  
   356  func checkUncommitted(t *testing.T, s *KVTxnStorage, wTxn txn.TxnMeta, keys ...byte) {
   357  	for _, k := range keys {
   358  		key := []byte{k}
   359  		value := []byte{k, byte(wTxn.SnapshotTS.PhysicalTime)}
   360  		uTxn, ok := s.uncommittedKeyTxnMap[string(key)]
   361  		assert.True(t, ok)
   362  		assert.Equal(t, wTxn, *uTxn)
   363  
   364  		v, ok := s.uncommitted.Get(key)
   365  		assert.True(t, ok)
   366  		assert.Equal(t, value, v)
   367  
   368  		n := 0
   369  		s.committed.AscendRange(key,
   370  			newTimestamp(0),
   371  			newTimestamp(math.MaxInt64),
   372  			func(b []byte, _ timestamp.Timestamp) {
   373  				if bytes.Equal(b, value) {
   374  					n++
   375  				}
   376  			})
   377  		assert.Equal(t, 0, n)
   378  	}
   379  }
   380  
   381  func checkRollback(t *testing.T, s *KVTxnStorage, wTxn txn.TxnMeta, keys ...byte) {
   382  	for _, k := range keys {
   383  		key := []byte{k}
   384  		value := []byte{k, byte(wTxn.SnapshotTS.PhysicalTime)}
   385  		uTxn, ok := s.uncommittedKeyTxnMap[string(key)]
   386  		assert.False(t, ok)
   387  		assert.Nil(t, uTxn)
   388  
   389  		v, ok := s.uncommitted.Get(key)
   390  		assert.False(t, ok)
   391  		assert.Empty(t, v)
   392  
   393  		n := 0
   394  		s.committed.AscendRange(key,
   395  			newTimestamp(0),
   396  			newTimestamp(math.MaxInt64),
   397  			func(b []byte, _ timestamp.Timestamp) {
   398  				if bytes.Equal(b, value) {
   399  					n++
   400  				}
   401  			})
   402  		assert.Equal(t, 0, n)
   403  	}
   404  
   405  	uTxn, ok := s.uncommittedTxn[string(wTxn.ID)]
   406  	assert.False(t, ok)
   407  	assert.Nil(t, uTxn)
   408  }
   409  
   410  func writeTestData(t *testing.T, s *KVTxnStorage, ts int64, expectError uint16, keys ...byte) txn.TxnMeta {
   411  	req := &message{}
   412  	for _, v := range keys {
   413  		req.Keys = append(req.Keys, []byte{v})
   414  		req.Values = append(req.Values, []byte{v, byte(ts)})
   415  	}
   416  	wTxn := newTxnMeta(ts)
   417  	_, err := s.Write(context.TODO(), wTxn, setOpCode, req.mustMarshal())
   418  	assert.True(t, moerr.IsMoErrCode(err, expectError))
   419  	return wTxn
   420  }
   421  
   422  func checkCommitted(t *testing.T, s *KVTxnStorage, wTxn txn.TxnMeta, keys ...byte) {
   423  	for _, k := range keys {
   424  		key := []byte{k}
   425  		value := []byte{k, byte(wTxn.SnapshotTS.PhysicalTime)}
   426  
   427  		v, ok := s.uncommittedKeyTxnMap[string(key)]
   428  		assert.False(t, ok)
   429  		assert.Nil(t, v)
   430  
   431  		hasCommitted := false
   432  		s.committed.AscendRange(key,
   433  			newTimestamp(0),
   434  			newTimestamp(math.MaxInt64),
   435  			func(b []byte, _ timestamp.Timestamp) {
   436  				if bytes.Equal(value, b) {
   437  					hasCommitted = true
   438  				}
   439  			})
   440  		assert.True(t, hasCommitted)
   441  	}
   442  
   443  	v, ok := s.uncommittedTxn[string(wTxn.ID)]
   444  	assert.False(t, ok)
   445  	assert.Nil(t, v)
   446  }
   447  
   448  func writeCommittedData(t *testing.T, s *KVTxnStorage, sts, cts int64, keys ...byte) {
   449  	for _, k := range keys {
   450  		key := []byte{k}
   451  		value := []byte{k, byte(sts)}
   452  		s.committed.Set(key, newTimestamp(cts), value)
   453  	}
   454  }
   455  
   456  func readTestData(t *testing.T, s *KVTxnStorage, ts int64, waitTxns [][]byte, keys ...byte) (txn.TxnMeta, *readResult) {
   457  	rTxn := newTxnMeta(ts)
   458  	return rTxn, readTestDataWithTxn(t, s, &rTxn, waitTxns, keys...)
   459  }
   460  
   461  func readTestDataWithTxn(t *testing.T, s *KVTxnStorage, rTxn *txn.TxnMeta, waitTxns [][]byte, keys ...byte) *readResult {
   462  	req := &message{}
   463  	for _, k := range keys {
   464  		key := []byte{k}
   465  		req.Keys = append(req.Keys, key)
   466  	}
   467  
   468  	rs, err := s.Read(context.TODO(), *rTxn, getOpCode, req.mustMarshal())
   469  	assert.NoError(t, err)
   470  	assert.Equal(t, waitTxns, rs.WaitTxns())
   471  	return rs.(*readResult)
   472  }
   473  
   474  func checkReadResult(t *testing.T, sts byte, rs *readResult, keys ...byte) {
   475  	data, err := rs.Read()
   476  	assert.NoError(t, err)
   477  	resp := &message{}
   478  	resp.mustUnmarshal(data)
   479  
   480  	var values [][]byte
   481  	for _, k := range keys {
   482  		if k == 0 {
   483  			values = append(values, nil)
   484  		} else {
   485  			values = append(values, []byte{k, sts})
   486  		}
   487  	}
   488  
   489  	assert.Equal(t, values, resp.Values)
   490  }
   491  
   492  func newTimestamp(v int64) timestamp.Timestamp {
   493  	return timestamp.Timestamp{PhysicalTime: v}
   494  }
   495  
   496  func newTxnMeta(snapshotTS int64) txn.TxnMeta {
   497  	id := uuid.New()
   498  	return txn.TxnMeta{
   499  		ID:         id[:],
   500  		Status:     txn.TxnStatus_Active,
   501  		SnapshotTS: newTimestamp(snapshotTS),
   502  	}
   503  }
   504  
   505  func newTestClock(start int64) clock.Clock {
   506  	ts := start
   507  	return clock.NewHLCClock(func() int64 {
   508  		return atomic.AddInt64(&ts, 1)
   509  	}, math.MaxInt64)
   510  }