github.com/cockroachdb/cockroach@v20.2.0-alpha.1+incompatible/pkg/kv/kvserver/tscache/cache_test.go (about)

     1  // Copyright 2017 The Cockroach Authors.
     2  //
     3  // Use of this software is governed by the Business Source License
     4  // included in the file licenses/BSL.txt.
     5  //
     6  // As of the Change Date specified in that file, in accordance with
     7  // the Business Source License, use of this software will be governed
     8  // by the Apache License, Version 2.0, included in the file
     9  // licenses/APL.txt.
    10  
    11  package tscache
    12  
    13  import (
    14  	"bytes"
    15  	"context"
    16  	"fmt"
    17  	"math/rand"
    18  	"reflect"
    19  	"runtime"
    20  	"testing"
    21  	"time"
    22  
    23  	"github.com/cockroachdb/cockroach/pkg/roachpb"
    24  	"github.com/cockroachdb/cockroach/pkg/testutils"
    25  	"github.com/cockroachdb/cockroach/pkg/util"
    26  	"github.com/cockroachdb/cockroach/pkg/util/hlc"
    27  	"github.com/cockroachdb/cockroach/pkg/util/leaktest"
    28  	"github.com/cockroachdb/cockroach/pkg/util/timeutil"
    29  	"github.com/cockroachdb/cockroach/pkg/util/uuid"
    30  	"github.com/cockroachdb/errors"
    31  	"golang.org/x/sync/errgroup"
    32  )
    33  
    34  var cacheImplConstrs = []func(clock *hlc.Clock) Cache{
    35  	func(clock *hlc.Clock) Cache { return newTreeImpl(clock) },
    36  	func(clock *hlc.Clock) Cache { return newSklImpl(clock) },
    37  }
    38  
    39  func forEachCacheImpl(
    40  	t *testing.T, fn func(t *testing.T, tc Cache, clock *hlc.Clock, manual *hlc.ManualClock),
    41  ) {
    42  	for _, constr := range cacheImplConstrs {
    43  		const baseTS = 100
    44  		manual := hlc.NewManualClock(baseTS)
    45  		clock := hlc.NewClock(manual.UnixNano, time.Nanosecond)
    46  
    47  		tc := constr(clock)
    48  		tcName := reflect.TypeOf(tc).Elem().Name()
    49  		t.Run(tcName, func(t *testing.T) {
    50  			fn(t, tc, clock, manual)
    51  		})
    52  	}
    53  }
    54  
    55  func TestTimestampCache(t *testing.T) {
    56  	defer leaktest.AfterTest(t)()
    57  
    58  	forEachCacheImpl(t, func(t *testing.T, tc Cache, clock *hlc.Clock, manual *hlc.ManualClock) {
    59  		baseTS := manual.UnixNano()
    60  
    61  		// First simulate a read of just "a" at time 50.
    62  		tc.Add(roachpb.Key("a"), nil, hlc.Timestamp{WallTime: 50}, noTxnID)
    63  		// Verify GetMax returns the lowWater mark.
    64  		if rTS, rTxnID := tc.GetMax(roachpb.Key("a"), nil); rTS.WallTime != baseTS || rTxnID != noTxnID {
    65  			t.Errorf("expected baseTS for key \"a\"; txnID=%s", rTxnID)
    66  		}
    67  		if rTS, rTxnID := tc.GetMax(roachpb.Key("notincache"), nil); rTS.WallTime != baseTS || rTxnID != noTxnID {
    68  			t.Errorf("expected baseTS for key \"notincache\"; txnID=%s", rTxnID)
    69  		}
    70  
    71  		// Advance the clock and verify same low water mark.
    72  		manual.Increment(100)
    73  		if rTS, rTxnID := tc.GetMax(roachpb.Key("a"), nil); rTS.WallTime != baseTS || rTxnID != noTxnID {
    74  			t.Errorf("expected baseTS for key \"a\"; txnID=%s", rTxnID)
    75  		}
    76  		if rTS, rTxnID := tc.GetMax(roachpb.Key("notincache"), nil); rTS.WallTime != baseTS || rTxnID != noTxnID {
    77  			t.Errorf("expected baseTS for key \"notincache\"; txnID=%s", rTxnID)
    78  		}
    79  
    80  		// Sim a read of "b"-"c" at a time above the low-water mark.
    81  		ts := clock.Now()
    82  		tc.Add(roachpb.Key("b"), roachpb.Key("c"), ts, noTxnID)
    83  
    84  		// Verify all permutations of direct and range access.
    85  		if rTS, rTxnID := tc.GetMax(roachpb.Key("b"), nil); rTS != ts || rTxnID != noTxnID {
    86  			t.Errorf("expected current time for key \"b\"; got %s; txnID=%s", rTS, rTxnID)
    87  		}
    88  		if rTS, rTxnID := tc.GetMax(roachpb.Key("bb"), nil); rTS != ts || rTxnID != noTxnID {
    89  			t.Errorf("expected current time for key \"bb\"; txnID=%s", rTxnID)
    90  		}
    91  		if rTS, rTxnID := tc.GetMax(roachpb.Key("c"), nil); rTS.WallTime != baseTS || rTxnID != noTxnID {
    92  			t.Errorf("expected baseTS for key \"c\"; txnID=%s", rTxnID)
    93  		}
    94  		if rTS, rTxnID := tc.GetMax(roachpb.Key("b"), roachpb.Key("c")); rTS != ts || rTxnID != noTxnID {
    95  			t.Errorf("expected current time for key \"b\"-\"c\"; txnID=%s", rTxnID)
    96  		}
    97  		if rTS, rTxnID := tc.GetMax(roachpb.Key("bb"), roachpb.Key("bz")); rTS != ts || rTxnID != noTxnID {
    98  			t.Errorf("expected current time for key \"bb\"-\"bz\"; txnID=%s", rTxnID)
    99  		}
   100  		if rTS, rTxnID := tc.GetMax(roachpb.Key("a"), roachpb.Key("b")); rTS.WallTime != baseTS || rTxnID != noTxnID {
   101  			t.Errorf("expected baseTS for key \"a\"-\"b\"; txnID=%s", rTxnID)
   102  		}
   103  		if rTS, rTxnID := tc.GetMax(roachpb.Key("a"), roachpb.Key("bb")); rTS != ts || rTxnID != noTxnID {
   104  			t.Errorf("expected current time for key \"a\"-\"bb\"; txnID=%s", rTxnID)
   105  		}
   106  		if rTS, rTxnID := tc.GetMax(roachpb.Key("a"), roachpb.Key("d")); rTS != ts || rTxnID != noTxnID {
   107  			t.Errorf("expected current time for key \"a\"-\"d\"; txnID=%s", rTxnID)
   108  		}
   109  		if rTS, rTxnID := tc.GetMax(roachpb.Key("bz"), roachpb.Key("c")); rTS != ts || rTxnID != noTxnID {
   110  			t.Errorf("expected current time for key \"bz\"-\"c\"; txnID=%s", rTxnID)
   111  		}
   112  		if rTS, rTxnID := tc.GetMax(roachpb.Key("bz"), roachpb.Key("d")); rTS != ts || rTxnID != noTxnID {
   113  			t.Errorf("expected current time for key \"bz\"-\"d\"; txnID=%s", rTxnID)
   114  		}
   115  		if rTS, rTxnID := tc.GetMax(roachpb.Key("c"), roachpb.Key("d")); rTS.WallTime != baseTS || rTxnID != noTxnID {
   116  			t.Errorf("expected baseTS for key \"c\"-\"d\"; txnID=%s", rTxnID)
   117  		}
   118  	})
   119  }
   120  
   121  type txnState struct {
   122  	ts hlc.Timestamp
   123  	id uuid.UUID
   124  }
   125  
   126  type layeredIntervalTestCase struct {
   127  	spans     []roachpb.Span
   128  	validator func(t *testing.T, tc Cache, txns []txnState)
   129  }
   130  
   131  // assertTS is a helper function for layeredIntervalTestCase
   132  // validators. It queries the timestamp cache for the given keys and
   133  // reports a test error if it doesn't match the given timestamp and
   134  // transaction ID.
   135  func assertTS(
   136  	t *testing.T, tc Cache, start, end roachpb.Key, expectedTS hlc.Timestamp, expectedTxnID uuid.UUID,
   137  ) {
   138  	var keys string
   139  	if len(end) == 0 {
   140  		keys = fmt.Sprintf("%q", start)
   141  	} else {
   142  		keys = fmt.Sprintf("%q-%q", start, end)
   143  	}
   144  	ts, txnID := tc.GetMax(start, end)
   145  	if ts != expectedTS {
   146  		t.Errorf("expected %s to have timestamp %v, found %v", keys, expectedTS, ts)
   147  	}
   148  	if txnID != expectedTxnID {
   149  		t.Errorf("expected %s to have txn id %s, but found %s", keys, expectedTxnID.Short(), txnID.Short())
   150  	}
   151  }
   152  
   153  // zeroIfSimul returns a zero UUID if this test involves multiple transactions
   154  // with the same timestamp (i.e. the timestamps in txns are identical but the
   155  // transaction ids are not), and the given txnID if they are not. This is
   156  // because timestampCache.GetMax must not return a transaction ID when two
   157  // different transactions have the same timestamp.
   158  func zeroIfSimul(txns []txnState, txnID uuid.UUID) uuid.UUID {
   159  	if txns[0].ts == txns[1].ts && txns[0].id != txns[1].id {
   160  		return noTxnID
   161  	}
   162  	return txnID
   163  }
   164  
   165  // layeredIntervalTestCase1 tests the left partial overlap and old containing
   166  // new cases for adding intervals to the interval cache when tested in order,
   167  // and tests the cases' inverses when tested in reverse.
   168  var layeredIntervalTestCase1 = layeredIntervalTestCase{
   169  	spans: []roachpb.Span{
   170  		// No overlap forwards.
   171  		// Right partial overlap backwards.
   172  		{Key: roachpb.Key("a"), EndKey: roachpb.Key("bb")},
   173  		// Left partial overlap forwards.
   174  		// New contains old backwards.
   175  		{Key: roachpb.Key("b"), EndKey: roachpb.Key("e")},
   176  		// Old contains new forwards.
   177  		// No overlap backwards.
   178  		{Key: roachpb.Key("c")},
   179  	},
   180  	validator: func(t *testing.T, tc Cache, txns []txnState) {
   181  		abbTx, beTx, cTx := txns[0], txns[1], txns[2]
   182  
   183  		assertTS(t, tc, roachpb.Key("a"), nil, abbTx.ts, abbTx.id)
   184  		assertTS(t, tc, roachpb.Key("b"), nil, beTx.ts, zeroIfSimul(txns, beTx.id))
   185  		assertTS(t, tc, roachpb.Key("c"), nil, cTx.ts, zeroIfSimul(txns, cTx.id))
   186  		assertTS(t, tc, roachpb.Key("d"), nil, beTx.ts, beTx.id)
   187  		assertTS(t, tc, roachpb.Key("a"), roachpb.Key("b"), abbTx.ts, abbTx.id)
   188  		assertTS(t, tc, roachpb.Key("a"), roachpb.Key("c"), beTx.ts, zeroIfSimul(txns, beTx.id))
   189  		assertTS(t, tc, roachpb.Key("a"), roachpb.Key("d"), cTx.ts, zeroIfSimul(txns, cTx.id))
   190  		assertTS(t, tc, roachpb.Key("b"), roachpb.Key("d"), cTx.ts, zeroIfSimul(txns, cTx.id))
   191  		assertTS(t, tc, roachpb.Key("c"), roachpb.Key("d"), cTx.ts, zeroIfSimul(txns, cTx.id))
   192  		assertTS(t, tc, roachpb.Key("c0"), roachpb.Key("d"), beTx.ts, beTx.id)
   193  	},
   194  }
   195  
   196  // layeredIntervalTestCase2 tests the right partial overlap and new containing
   197  // old cases for adding intervals to the interval cache when tested in order,
   198  // and tests the cases' inverses when tested in reverse.
   199  var layeredIntervalTestCase2 = layeredIntervalTestCase{
   200  	spans: []roachpb.Span{
   201  		// No overlap forwards.
   202  		// Old contains new backwards.
   203  		{Key: roachpb.Key("d"), EndKey: roachpb.Key("f")},
   204  		// New contains old forwards.
   205  		// Left partial overlap backwards.
   206  		{Key: roachpb.Key("b"), EndKey: roachpb.Key("f")},
   207  		// Right partial overlap forwards.
   208  		// No overlap backwards.
   209  		{Key: roachpb.Key("a"), EndKey: roachpb.Key("c")},
   210  	},
   211  	validator: func(t *testing.T, tc Cache, txns []txnState) {
   212  		_, bfTx, acTx := txns[0], txns[1], txns[2]
   213  
   214  		assertTS(t, tc, roachpb.Key("a"), nil, acTx.ts, acTx.id)
   215  		assertTS(t, tc, roachpb.Key("b"), nil, acTx.ts, zeroIfSimul(txns, acTx.id))
   216  		assertTS(t, tc, roachpb.Key("c"), nil, bfTx.ts, bfTx.id)
   217  		assertTS(t, tc, roachpb.Key("d"), nil, bfTx.ts, zeroIfSimul(txns, bfTx.id))
   218  		assertTS(t, tc, roachpb.Key("a"), roachpb.Key("c"), acTx.ts, zeroIfSimul(txns, acTx.id))
   219  		assertTS(t, tc, roachpb.Key("b"), roachpb.Key("d"), acTx.ts, zeroIfSimul(txns, acTx.id))
   220  		assertTS(t, tc, roachpb.Key("c"), roachpb.Key("d"), bfTx.ts, bfTx.id)
   221  		assertTS(t, tc, roachpb.Key("c0"), roachpb.Key("d"), bfTx.ts, bfTx.id)
   222  	},
   223  }
   224  
   225  // layeredIntervalTestCase3 tests a right partial overlap with a shared end
   226  // for adding intervals to the interval cache when tested in order, and
   227  // tests a left partial overlap with a shared end when tested in reverse.
   228  var layeredIntervalTestCase3 = layeredIntervalTestCase{
   229  	spans: []roachpb.Span{
   230  		// No overlap forwards.
   231  		// Right partial overlap backwards.
   232  		{Key: roachpb.Key("a"), EndKey: roachpb.Key("c")},
   233  		// Left partial overlap forwards.
   234  		// No overlap backwards.
   235  		{Key: roachpb.Key("b"), EndKey: roachpb.Key("c")},
   236  	},
   237  	validator: func(t *testing.T, tc Cache, txns []txnState) {
   238  		acTx, bcTx := txns[0], txns[1]
   239  
   240  		assertTS(t, tc, roachpb.Key("a"), nil, acTx.ts, acTx.id)
   241  		assertTS(t, tc, roachpb.Key("b"), nil, bcTx.ts, zeroIfSimul(txns, bcTx.id))
   242  		assertTS(t, tc, roachpb.Key("c"), nil, tc.getLowWater(), noTxnID)
   243  		assertTS(t, tc, roachpb.Key("a"), roachpb.Key("c"), bcTx.ts, zeroIfSimul(txns, bcTx.id))
   244  		assertTS(t, tc, roachpb.Key("a"), roachpb.Key("b"), acTx.ts, acTx.id)
   245  		assertTS(t, tc, roachpb.Key("b"), roachpb.Key("c"), bcTx.ts, zeroIfSimul(txns, bcTx.id))
   246  	},
   247  }
   248  
   249  // layeredIntervalTestCase4 tests a left partial overlap with a shared start
   250  // for adding intervals to the interval cache when tested in order, and
   251  // tests a right partial overlap with a shared start when tested in reverse.
   252  var layeredIntervalTestCase4 = layeredIntervalTestCase{
   253  	spans: []roachpb.Span{
   254  		// No overlap forwards.
   255  		// Left partial overlap backwards.
   256  		{Key: roachpb.Key("a"), EndKey: roachpb.Key("c")},
   257  		// Right partial overlap forwards.
   258  		// No overlap backwards.
   259  		{Key: roachpb.Key("a"), EndKey: roachpb.Key("b")},
   260  	},
   261  	validator: func(t *testing.T, tc Cache, txns []txnState) {
   262  		acTx, abTx := txns[0], txns[1]
   263  
   264  		assertTS(t, tc, roachpb.Key("a"), nil, abTx.ts, zeroIfSimul(txns, abTx.id))
   265  		assertTS(t, tc, roachpb.Key("b"), nil, acTx.ts, acTx.id)
   266  		assertTS(t, tc, roachpb.Key("c"), nil, tc.getLowWater(), noTxnID)
   267  		assertTS(t, tc, roachpb.Key("a"), roachpb.Key("c"), abTx.ts, zeroIfSimul(txns, abTx.id))
   268  		assertTS(t, tc, roachpb.Key("a"), roachpb.Key("b"), abTx.ts, zeroIfSimul(txns, abTx.id))
   269  		assertTS(t, tc, roachpb.Key("b"), roachpb.Key("c"), acTx.ts, acTx.id)
   270  	},
   271  }
   272  
   273  var layeredIntervalTestCase5 = layeredIntervalTestCase{
   274  	spans: []roachpb.Span{
   275  		// Two identical spans
   276  		{Key: roachpb.Key("a"), EndKey: roachpb.Key("b")},
   277  		{Key: roachpb.Key("a"), EndKey: roachpb.Key("b")},
   278  	},
   279  	validator: func(t *testing.T, tc Cache, txns []txnState) {
   280  		assertTS(t, tc, roachpb.Key("a"), nil, txns[1].ts, zeroIfSimul(txns, txns[1].id))
   281  	},
   282  }
   283  
   284  // TestTimestampCacheLayeredIntervals verifies the maximum timestamp
   285  // is chosen if previous entries have ranges which are layered over
   286  // each other.
   287  //
   288  // The test uses the layeredIntervalTestCase struct to allow reordering
   289  // of interval insertions while keeping each interval's timestamp fixed.
   290  // This can be used to verify that only the provided timestamp is used to
   291  // determine layering, and that the interval insertion order is irrelevant.
   292  func TestTimestampCacheLayeredIntervals(t *testing.T) {
   293  	defer leaktest.AfterTest(t)()
   294  
   295  	forEachCacheImpl(t, func(t *testing.T, tc Cache, clock *hlc.Clock, manual *hlc.ManualClock) {
   296  		// Run each test case in several configurations.
   297  		for _, testCase := range []layeredIntervalTestCase{
   298  			layeredIntervalTestCase1,
   299  			layeredIntervalTestCase2,
   300  			layeredIntervalTestCase3,
   301  			layeredIntervalTestCase4,
   302  			layeredIntervalTestCase5,
   303  		} {
   304  			t.Run("", func(t *testing.T) {
   305  				// In simultaneous runs, each span in the test case is given the same
   306  				// time. Otherwise each gets a distinct timestamp (in the order of
   307  				// definition).
   308  				testutils.RunTrueAndFalse(t, "simultaneous", func(t *testing.T, simultaneous bool) {
   309  					// In reverse runs, spans are inserted into the timestamp cache out
   310  					// of order (so spans with higher timestamps are inserted before
   311  					// those with lower timestamps). In simultaneous+reverse runs,
   312  					// timestamps are all the same, but running in both directions is
   313  					// still necessary to exercise all branches in the code.
   314  					testutils.RunTrueAndFalse(t, "reverse", func(t *testing.T, reverse bool) {
   315  						// In sameTxn runs, all spans are inserted as a part of the same
   316  						// transaction; otherwise each is a separate transaction.
   317  						testutils.RunTrueAndFalse(t, "sameTxn", func(t *testing.T, sameTxn bool) {
   318  							defer func() {
   319  								tc.clear(clock.Now())
   320  							}()
   321  
   322  							txns := make([]txnState, len(testCase.spans))
   323  							if sameTxn {
   324  								id := uuid.MakeV4()
   325  								for i := range testCase.spans {
   326  									txns[i].id = id
   327  								}
   328  							} else {
   329  								for i := range testCase.spans {
   330  									txns[i].id = uuid.MakeV4()
   331  								}
   332  							}
   333  
   334  							tc.clear(clock.Now())
   335  							if simultaneous {
   336  								now := clock.Now()
   337  								for i := range txns {
   338  									txns[i].ts = now
   339  								}
   340  							} else {
   341  								manual.Increment(1)
   342  								for i := range txns {
   343  									txns[i].ts = clock.Now()
   344  								}
   345  							}
   346  
   347  							if reverse {
   348  								for i := len(testCase.spans) - 1; i >= 0; i-- {
   349  									tc.Add(testCase.spans[i].Key, testCase.spans[i].EndKey, txns[i].ts, txns[i].id)
   350  								}
   351  							} else {
   352  								for i := range testCase.spans {
   353  									tc.Add(testCase.spans[i].Key, testCase.spans[i].EndKey, txns[i].ts, txns[i].id)
   354  								}
   355  							}
   356  							testCase.validator(t, tc, txns)
   357  						})
   358  					})
   359  				})
   360  			})
   361  		}
   362  	})
   363  }
   364  
   365  func TestTimestampCacheClear(t *testing.T) {
   366  	defer leaktest.AfterTest(t)()
   367  
   368  	forEachCacheImpl(t, func(t *testing.T, tc Cache, clock *hlc.Clock, manual *hlc.ManualClock) {
   369  		key := roachpb.Key("a")
   370  
   371  		ts := clock.Now()
   372  		tc.Add(key, nil, ts, noTxnID)
   373  
   374  		manual.Increment(5000000)
   375  
   376  		expTS := clock.Now()
   377  		// Clear the cache, which will reset the low water mark to
   378  		// the current time.
   379  		tc.clear(expTS)
   380  
   381  		// Fetching any keys should give current time.
   382  		if rTS, rTxnID := tc.GetMax(key, nil); rTxnID != noTxnID {
   383  			t.Errorf("%s unexpectedly associated to txn %s", key, rTxnID)
   384  		} else if rTS != expTS {
   385  			t.Errorf("expected %s, got %s", rTS, expTS)
   386  		}
   387  	})
   388  }
   389  
   390  // TestTimestampCacheEqualTimestamp verifies that in the event of two
   391  // non-overlapping transactions with equal timestamps, the returned
   392  // timestamp is not owned by either one.
   393  func TestTimestampCacheEqualTimestamps(t *testing.T) {
   394  	defer leaktest.AfterTest(t)()
   395  
   396  	forEachCacheImpl(t, func(t *testing.T, tc Cache, clock *hlc.Clock, manual *hlc.ManualClock) {
   397  		txn1 := uuid.MakeV4()
   398  		txn2 := uuid.MakeV4()
   399  
   400  		// Add two non-overlapping transactions at the same timestamp.
   401  		ts1 := clock.Now()
   402  		tc.Add(roachpb.Key("a"), roachpb.Key("b"), ts1, txn1)
   403  		tc.Add(roachpb.Key("b"), roachpb.Key("c"), ts1, txn2)
   404  
   405  		// When querying either side separately, the transaction ID is returned.
   406  		if ts, txn := tc.GetMax(roachpb.Key("a"), roachpb.Key("b")); ts != ts1 {
   407  			t.Errorf("expected 'a'-'b' to have timestamp %s, but found %s", ts1, ts)
   408  		} else if txn != txn1 {
   409  			t.Errorf("expected 'a'-'b' to have txn id %s, but found %s", txn1, txn)
   410  		}
   411  		if ts, txn := tc.GetMax(roachpb.Key("b"), roachpb.Key("c")); ts != ts1 {
   412  			t.Errorf("expected 'b'-'c' to have timestamp %s, but found %s", ts1, ts)
   413  		} else if txn != txn2 {
   414  			t.Errorf("expected 'b'-'c' to have txn id %s, but found %s", txn2, txn)
   415  		}
   416  
   417  		// Querying a span that overlaps both returns a nil txn ID; neither
   418  		// can proceed here.
   419  		if ts, txn := tc.GetMax(roachpb.Key("a"), roachpb.Key("c")); ts != ts1 {
   420  			t.Errorf("expected 'a'-'c' to have timestamp %s, but found %s", ts1, ts)
   421  		} else if txn != (noTxnID) {
   422  			t.Errorf("expected 'a'-'c' to have zero txn id, but found %s", txn)
   423  		}
   424  	})
   425  }
   426  
   427  // TestTimestampCacheLargeKeys verifies that the timestamp cache implementations
   428  // can support arbitrarily large keys lengths. This is important because we don't
   429  // place a hard limit on this anywhere else.
   430  func TestTimestampCacheLargeKeys(t *testing.T) {
   431  	defer leaktest.AfterTest(t)()
   432  
   433  	forEachCacheImpl(t, func(t *testing.T, tc Cache, clock *hlc.Clock, manual *hlc.ManualClock) {
   434  		keyStart := roachpb.Key(make([]byte, 5*maximumSklPageSize))
   435  		keyEnd := keyStart.Next()
   436  		ts1 := clock.Now()
   437  		txn1 := uuid.MakeV4()
   438  
   439  		tc.Add(keyStart, keyEnd, ts1, txn1)
   440  		if ts, txn := tc.GetMax(keyStart, keyEnd); ts != ts1 {
   441  			t.Errorf("expected key range to have timestamp %s, but found %s", ts1, ts)
   442  		} else if txn != txn1 {
   443  			t.Errorf("expected key range to have txn id %s, but found %s", txn1, txn)
   444  		}
   445  	})
   446  }
   447  
   448  // TestTimestampCacheImplsIdentical verifies that all timestamp cache
   449  // implementations return the same results for the same inputs, even under
   450  // concurrent load.
   451  func TestTimestampCacheImplsIdentical(t *testing.T) {
   452  	defer leaktest.AfterTest(t)()
   453  	defer util.EnableRacePreemptionPoints()()
   454  
   455  	// Run one subtest using a real clock to generate timestamps and one subtest
   456  	// using a fake clock to generate timestamps. The former is good for
   457  	// simulating real conditions while the latter is good for testing timestamp
   458  	// collisions.
   459  	testutils.RunTrueAndFalse(t, "useClock", func(t *testing.T, useClock bool) {
   460  		clock := hlc.NewClock(hlc.UnixNano, time.Nanosecond)
   461  		caches := make([]Cache, len(cacheImplConstrs))
   462  		start := clock.Now()
   463  		for i, constr := range cacheImplConstrs {
   464  			tc := constr(clock)
   465  			tc.clear(start) // set low water mark
   466  			caches[i] = tc
   467  		}
   468  
   469  		// Context cancellations are used to shutdown goroutines and prevent
   470  		// deadlocks once any test failures are found. errgroup.WithContext will
   471  		// cancel the context either when any goroutine returns an error or when
   472  		// all goroutines finish and Wait returns.
   473  		doneWG, ctx := errgroup.WithContext(context.Background())
   474  
   475  		// We run a goroutine for each slot. Goroutines insert new value over
   476  		// random intervals, but verify that the value in their slot always
   477  		// ratchets.
   478  		slots := 4 * runtime.NumCPU()
   479  		if util.RaceEnabled {
   480  			// We add in a lot of preemption points when race detection
   481  			// is enabled, so things will already be very slow. Reduce
   482  			// the concurrency to that we don't time out.
   483  			slots /= 2
   484  		}
   485  
   486  		// semC and retC force all goroutines to work in lockstep, first adding
   487  		// intervals to all caches together, then reading from all caches
   488  		// together.
   489  		semC, retC := make(chan struct{}), make(chan struct{})
   490  		go func() {
   491  			populate := func() {
   492  				for i := 0; i < slots; i++ {
   493  					select {
   494  					case semC <- struct{}{}:
   495  					case <-ctx.Done():
   496  						return
   497  					}
   498  				}
   499  			}
   500  			populate()
   501  
   502  			left := slots
   503  			for {
   504  				select {
   505  				case <-retC:
   506  					left--
   507  					if left == 0 {
   508  						// Reset left count and populate.
   509  						left = slots
   510  						populate()
   511  					}
   512  				case <-ctx.Done():
   513  					return
   514  				}
   515  			}
   516  		}()
   517  
   518  		for i := 0; i < slots; i++ {
   519  			i := i
   520  			doneWG.Go(func() error {
   521  				rng := rand.New(rand.NewSource(timeutil.Now().UnixNano()))
   522  				slotKey := []byte(fmt.Sprintf("%05d", i))
   523  				txnID := uuid.MakeV4()
   524  				maxVal := cacheValue{}
   525  
   526  				rounds := 1000
   527  				if util.RaceEnabled {
   528  					// Reduce the number of rounds for race builds.
   529  					rounds /= 2
   530  				}
   531  				for j := 0; j < rounds; j++ {
   532  					// This is a lot of log output so only un-comment to debug.
   533  					// t.Logf("goroutine %d at iter %d", i, j)
   534  
   535  					// Wait for all goroutines to synchronize.
   536  					select {
   537  					case <-semC:
   538  					case <-ctx.Done():
   539  						return nil
   540  					}
   541  
   542  					// Add the same random range to each cache.
   543  					from, middle, to := randRange(rng, slots+1)
   544  					if bytes.Equal(from, to) {
   545  						to = nil
   546  					}
   547  
   548  					ts := start.Add(int64(j), 100)
   549  					if useClock {
   550  						ts = clock.Now()
   551  					}
   552  
   553  					newVal := cacheValue{ts: ts, txnID: txnID}
   554  					for _, tc := range caches {
   555  						// This is a lot of log output so only un-comment to debug.
   556  						// t.Logf("adding (%T) [%s,%s) = %s", tc, string(from), string(to), newVal)
   557  						tc.Add(from, to, ts, txnID)
   558  					}
   559  
   560  					// Return semaphore.
   561  					select {
   562  					case retC <- struct{}{}:
   563  					case <-ctx.Done():
   564  						return nil
   565  					}
   566  
   567  					// Wait for all goroutines to synchronize.
   568  					select {
   569  					case <-semC:
   570  					case <-ctx.Done():
   571  						return nil
   572  					}
   573  
   574  					// Check the value for the newly added interval. Should be
   575  					// equal across all caches and be a ratcheted version of the
   576  					// interval added above.
   577  					var err error
   578  					if _, err = identicalAndRatcheted(caches, from, to, newVal); err != nil {
   579  						return errors.Wrapf(err, "interval=[%s,%s)", string(from), string(to))
   580  					}
   581  
   582  					// Check the value for the start key of the newly added
   583  					// interval. Should be equal across all caches and be a
   584  					// ratcheted version of the interval added above.
   585  					if _, err = identicalAndRatcheted(caches, from, nil, newVal); err != nil {
   586  						return errors.Wrapf(err, "startKey=%s", string(from))
   587  					}
   588  
   589  					// Check the value right after the start key of the newly
   590  					// added interval, if possible. Should be equal across all
   591  					// caches and be a ratcheted version of the interval added
   592  					// above.
   593  					if middle != nil {
   594  						if _, err = identicalAndRatcheted(caches, middle, nil, newVal); err != nil {
   595  							return errors.Wrapf(err, "middleKey=%s", string(middle))
   596  						}
   597  					}
   598  
   599  					// Check the value for the goroutine's slot. Should be equal
   600  					// across all caches and be a ratcheted version of the
   601  					// maximum value we've seen in the slot.
   602  					if maxVal, err = identicalAndRatcheted(caches, slotKey, nil, maxVal); err != nil {
   603  						return errors.Wrapf(err, "slotKey=%s", string(slotKey))
   604  					}
   605  
   606  					// Return semaphore.
   607  					select {
   608  					case retC <- struct{}{}:
   609  					case <-ctx.Done():
   610  						return nil
   611  					}
   612  				}
   613  				return nil
   614  			})
   615  		}
   616  		if err := doneWG.Wait(); err != nil {
   617  			t.Fatal(err)
   618  		}
   619  	})
   620  }
   621  
   622  // identicalAndRatcheted asserts that all caches have identical values for the
   623  // specified range and that the value is a ratcheted version of previous value.
   624  // It returns an error if the assertion fails and the value found if it doesn't.
   625  func identicalAndRatcheted(
   626  	caches []Cache, from, to roachpb.Key, prevVal cacheValue,
   627  ) (cacheValue, error) {
   628  	var vals []cacheValue
   629  	for _, tc := range caches {
   630  		keyTS, keyTxnID := tc.GetMax(from, to)
   631  		vals = append(vals, cacheValue{ts: keyTS, txnID: keyTxnID})
   632  	}
   633  
   634  	// Assert same values for each cache.
   635  	firstVal := vals[0]
   636  	firstCache := caches[0]
   637  	for i := 1; i < len(caches); i++ {
   638  		if !reflect.DeepEqual(firstVal, vals[i]) {
   639  			return firstVal, errors.Errorf("expected %s (%T) and %s (%T) to be equal",
   640  				firstVal, firstCache, vals[i], caches[i])
   641  		}
   642  	}
   643  
   644  	// Assert that the value is a ratcheted version of prevVal.
   645  	// See assertRatchet.
   646  	if _, ratchet := ratchetValue(firstVal, prevVal); ratchet {
   647  		return firstVal, errors.Errorf("ratchet inversion from %s to %s", prevVal, firstVal)
   648  	}
   649  
   650  	return firstVal, nil
   651  }
   652  
   653  func BenchmarkTimestampCacheInsertion(b *testing.B) {
   654  	manual := hlc.NewManualClock(123)
   655  	clock := hlc.NewClock(manual.UnixNano, time.Nanosecond)
   656  	tc := New(clock)
   657  
   658  	for i := 0; i < b.N; i++ {
   659  		cdTS := clock.Now()
   660  		tc.Add(roachpb.Key("c"), roachpb.Key("d"), cdTS, noTxnID)
   661  
   662  		beTS := clock.Now()
   663  		tc.Add(roachpb.Key("b"), roachpb.Key("e"), beTS, noTxnID)
   664  
   665  		adTS := clock.Now()
   666  		tc.Add(roachpb.Key("a"), roachpb.Key("d"), adTS, noTxnID)
   667  
   668  		cfTS := clock.Now()
   669  		tc.Add(roachpb.Key("c"), roachpb.Key("f"), cfTS, noTxnID)
   670  	}
   671  }