github.com/cockroachdb/cockroach@v20.2.0-alpha.1+incompatible/pkg/sql/catalog/lease/lease_internal_test.go (about)

     1  // Copyright 2015 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  // Note that there's also a lease_test.go, in package sql_test.
    12  
    13  package lease
    14  
    15  import (
    16  	"context"
    17  	"fmt"
    18  	"sync"
    19  	"sync/atomic"
    20  	"testing"
    21  
    22  	"github.com/cockroachdb/cockroach/pkg/base"
    23  	"github.com/cockroachdb/cockroach/pkg/keys"
    24  	"github.com/cockroachdb/cockroach/pkg/sql/sqlbase"
    25  	"github.com/cockroachdb/cockroach/pkg/testutils/serverutils"
    26  	"github.com/cockroachdb/cockroach/pkg/util/hlc"
    27  	"github.com/cockroachdb/cockroach/pkg/util/leaktest"
    28  	"github.com/cockroachdb/logtags"
    29  )
    30  
    31  func TestTableSet(t *testing.T) {
    32  	defer leaktest.AfterTest(t)()
    33  
    34  	type data struct {
    35  		version    sqlbase.DescriptorVersion
    36  		expiration int64
    37  	}
    38  	type insert data
    39  	type remove data
    40  
    41  	type newest struct {
    42  		version sqlbase.DescriptorVersion
    43  	}
    44  
    45  	testData := []struct {
    46  		op       interface{}
    47  		expected string
    48  	}{
    49  		{newest{0}, "<nil>"},
    50  		{insert{2, 3}, "2:3"},
    51  		{newest{0}, "2:3"},
    52  		{newest{2}, "2:3"},
    53  		{newest{3}, "<nil>"},
    54  		{remove{2, 3}, ""},
    55  		{insert{2, 4}, "2:4"},
    56  		{newest{0}, "2:4"},
    57  		{newest{2}, "2:4"},
    58  		{newest{3}, "<nil>"},
    59  		{insert{3, 1}, "2:4 3:1"},
    60  		{newest{0}, "3:1"},
    61  		{newest{1}, "<nil>"},
    62  		{newest{2}, "2:4"},
    63  		{newest{3}, "3:1"},
    64  		{newest{4}, "<nil>"},
    65  		{insert{1, 1}, "1:1 2:4 3:1"},
    66  		{newest{0}, "3:1"},
    67  		{newest{1}, "1:1"},
    68  		{newest{2}, "2:4"},
    69  		{newest{3}, "3:1"},
    70  		{newest{4}, "<nil>"},
    71  		{remove{3, 1}, "1:1 2:4"},
    72  		{remove{1, 1}, "2:4"},
    73  		{remove{2, 4}, ""},
    74  	}
    75  
    76  	set := &tableSet{}
    77  	for i, d := range testData {
    78  		switch op := d.op.(type) {
    79  		case insert:
    80  			s := &tableVersionState{}
    81  			s.Version = op.version
    82  			s.expiration = hlc.Timestamp{WallTime: op.expiration}
    83  			set.insert(s)
    84  
    85  		case remove:
    86  			s := &tableVersionState{}
    87  			s.Version = op.version
    88  			s.expiration = hlc.Timestamp{WallTime: op.expiration}
    89  			set.remove(s)
    90  
    91  		case newest:
    92  			n := set.findNewest()
    93  			if op.version != 0 {
    94  				n = set.findVersion(op.version)
    95  			}
    96  			s := "<nil>"
    97  			if n != nil {
    98  				s = fmt.Sprintf("%d:%d", n.Version, n.expiration.WallTime)
    99  			}
   100  			if d.expected != s {
   101  				t.Fatalf("%d: expected %s, but found %s", i, d.expected, s)
   102  			}
   103  			continue
   104  		}
   105  		if s := set.String(); d.expected != s {
   106  			t.Fatalf("%d: expected %s, but found %s", i, d.expected, s)
   107  		}
   108  	}
   109  }
   110  
   111  func getNumVersions(ts *tableState) int {
   112  	ts.mu.Lock()
   113  	defer ts.mu.Unlock()
   114  	return len(ts.mu.active.data)
   115  }
   116  
   117  func TestPurgeOldVersions(t *testing.T) {
   118  	defer leaktest.AfterTest(t)()
   119  	// We're going to block gossip so it doesn't come randomly and clear up the
   120  	// leases we're artificially setting up.
   121  	gossipSem := make(chan struct{}, 1)
   122  	serverParams := base.TestServerArgs{
   123  		Knobs: base.TestingKnobs{
   124  			SQLLeaseManager: &ManagerTestingKnobs{
   125  				TestingTableUpdateEvent: func(t *sqlbase.TableDescriptor) error {
   126  					gossipSem <- struct{}{}
   127  					<-gossipSem
   128  					return nil
   129  				},
   130  			},
   131  		},
   132  	}
   133  	s, db, kvDB := serverutils.StartServer(t, serverParams)
   134  	defer s.Stopper().Stop(context.Background())
   135  	leaseManager := s.LeaseManager().(*Manager)
   136  
   137  	// Block gossip.
   138  	gossipSem <- struct{}{}
   139  	defer func() {
   140  		// Unblock gossip.
   141  		<-gossipSem
   142  	}()
   143  
   144  	if _, err := db.Exec(`
   145  CREATE DATABASE t;
   146  CREATE TABLE t.test (k CHAR PRIMARY KEY, v CHAR);
   147  `); err != nil {
   148  		t.Fatal(err)
   149  	}
   150  
   151  	tableDesc := sqlbase.GetTableDescriptor(kvDB, keys.SystemSQLCodec, "t", "test")
   152  
   153  	var tables []sqlbase.ImmutableTableDescriptor
   154  	var expiration hlc.Timestamp
   155  	getLeases := func() {
   156  		for i := 0; i < 3; i++ {
   157  			if err := leaseManager.AcquireFreshestFromStore(context.Background(), tableDesc.ID); err != nil {
   158  				t.Fatal(err)
   159  			}
   160  			table, exp, err := leaseManager.Acquire(context.Background(), s.Clock().Now(), tableDesc.ID)
   161  			if err != nil {
   162  				t.Fatal(err)
   163  			}
   164  			tables = append(tables, *table)
   165  			expiration = exp
   166  			if err := leaseManager.Release(table); err != nil {
   167  				t.Fatal(err)
   168  			}
   169  		}
   170  	}
   171  	getLeases()
   172  	ts := leaseManager.findTableState(tableDesc.ID, false)
   173  	if numLeases := getNumVersions(ts); numLeases != 1 {
   174  		t.Fatalf("found %d versions instead of 1", numLeases)
   175  	}
   176  
   177  	// Verifies that ErrDidntUpdateDescriptor doesn't leak from Publish().
   178  	if _, err := leaseManager.Publish(context.Background(), tableDesc.ID, func(*sqlbase.MutableTableDescriptor) error {
   179  		return ErrDidntUpdateDescriptor
   180  	}, nil); err != nil {
   181  		t.Fatal(err)
   182  	}
   183  
   184  	// Publish a new version for the table
   185  	if _, err := leaseManager.Publish(context.Background(), tableDesc.ID, func(*sqlbase.MutableTableDescriptor) error {
   186  		return nil
   187  	}, nil); err != nil {
   188  		t.Fatal(err)
   189  	}
   190  
   191  	getLeases()
   192  	ts = leaseManager.findTableState(tableDesc.ID, false)
   193  	if numLeases := getNumVersions(ts); numLeases != 2 {
   194  		t.Fatalf("found %d versions instead of 2", numLeases)
   195  	}
   196  	if err := purgeOldVersions(
   197  		context.Background(), kvDB, tableDesc.ID, false, 2 /* minVersion */, leaseManager); err != nil {
   198  		t.Fatal(err)
   199  	}
   200  
   201  	if numLeases := getNumVersions(ts); numLeases != 1 {
   202  		t.Fatalf("found %d versions instead of 1", numLeases)
   203  	}
   204  	ts.mu.Lock()
   205  	correctLease := ts.mu.active.data[0].TableDescriptor.ID == tables[5].ID &&
   206  		ts.mu.active.data[0].TableDescriptor.Version == tables[5].Version
   207  	correctExpiration := ts.mu.active.data[0].expiration == expiration
   208  	ts.mu.Unlock()
   209  	if !correctLease {
   210  		t.Fatalf("wrong lease survived purge")
   211  	}
   212  	if !correctExpiration {
   213  		t.Fatalf("wrong lease expiration survived purge")
   214  	}
   215  
   216  	// Test that purgeOldVersions correctly removes a table version
   217  	// without a lease.
   218  	ts.mu.Lock()
   219  	tableVersion := &tableVersionState{
   220  		ImmutableTableDescriptor: tables[0],
   221  		expiration:               tables[5].ModificationTime,
   222  	}
   223  	ts.mu.active.insert(tableVersion)
   224  	ts.mu.Unlock()
   225  	if numLeases := getNumVersions(ts); numLeases != 2 {
   226  		t.Fatalf("found %d versions instead of 2", numLeases)
   227  	}
   228  	if err := purgeOldVersions(
   229  		context.Background(), kvDB, tableDesc.ID, false, 2 /* minVersion */, leaseManager); err != nil {
   230  		t.Fatal(err)
   231  	}
   232  	if numLeases := getNumVersions(ts); numLeases != 1 {
   233  		t.Fatalf("found %d versions instead of 1", numLeases)
   234  	}
   235  }
   236  
   237  // Test that a database with conflicting table names under different schemas
   238  // do not cause issues.
   239  func TestNameCacheDBConflictingTableNames(t *testing.T) {
   240  	defer leaktest.AfterTest(t)()
   241  
   242  	s, db, kvDB := serverutils.StartServer(t, base.TestServerArgs{})
   243  	defer s.Stopper().Stop(context.Background())
   244  	leaseManager := s.LeaseManager().(*Manager)
   245  
   246  	if _, err := db.Exec(`SET experimental_enable_temp_tables = true`); err != nil {
   247  		t.Fatal(err)
   248  	}
   249  
   250  	if _, err := db.Exec(`
   251  CREATE TABLE t (public int);
   252  CREATE TEMP TABLE t (temp int);
   253  CREATE TABLE t2 (public int);
   254  CREATE TEMP TABLE t2 (temp int);
   255  `); err != nil {
   256  		t.Fatal(err)
   257  	}
   258  
   259  	// Select in different orders, and make sure the right one is returned.
   260  	if _, err := db.Exec("SELECT * FROM pg_temp.t;"); err != nil {
   261  		t.Fatal(err)
   262  	}
   263  	if _, err := db.Exec("SELECT * FROM public.t;"); err != nil {
   264  		t.Fatal(err)
   265  	}
   266  	if _, err := db.Exec("SELECT * FROM public.t2;"); err != nil {
   267  		t.Fatal(err)
   268  	}
   269  	if _, err := db.Exec("SELECT * FROM pg_temp.t2;"); err != nil {
   270  		t.Fatal(err)
   271  	}
   272  
   273  	for _, tableName := range []string{"t", "t2"} {
   274  		tableDesc := sqlbase.GetTableDescriptor(kvDB, keys.SystemSQLCodec, "defaultdb", tableName)
   275  		lease := leaseManager.tableNames.get(
   276  			tableDesc.ParentID,
   277  			sqlbase.ID(keys.PublicSchemaID),
   278  			tableName,
   279  			s.Clock().Now(),
   280  		)
   281  		if lease.ID != tableDesc.ID {
   282  			t.Fatalf("lease has wrong ID: %d (expected: %d)", lease.ID, tableDesc.ID)
   283  		}
   284  	}
   285  }
   286  
   287  // Test that changing a descriptor's name updates the name cache.
   288  func TestNameCacheIsUpdated(t *testing.T) {
   289  	defer leaktest.AfterTest(t)()
   290  	s, db, kvDB := serverutils.StartServer(t, base.TestServerArgs{})
   291  	defer s.Stopper().Stop(context.Background())
   292  	leaseManager := s.LeaseManager().(*Manager)
   293  
   294  	if _, err := db.Exec(`
   295  CREATE DATABASE t;
   296  CREATE DATABASE t1;
   297  CREATE TABLE t.test (k CHAR PRIMARY KEY, v CHAR);
   298  `); err != nil {
   299  		t.Fatal(err)
   300  	}
   301  
   302  	// Populate the name cache.
   303  	if _, err := db.Exec("SELECT * FROM t.test;"); err != nil {
   304  		t.Fatal(err)
   305  	}
   306  
   307  	tableDesc := sqlbase.GetTableDescriptor(kvDB, keys.SystemSQLCodec, "t", "test")
   308  
   309  	// Rename.
   310  	if _, err := db.Exec("ALTER TABLE t.test RENAME TO t.test2;"); err != nil {
   311  		t.Fatal(err)
   312  	}
   313  
   314  	// Check that the cache has been updated.
   315  	if leaseManager.tableNames.get(tableDesc.ParentID, tableDesc.GetParentSchemaID(), "test", s.Clock().Now()) != nil {
   316  		t.Fatalf("old name still in cache")
   317  	}
   318  
   319  	lease := leaseManager.tableNames.get(tableDesc.ParentID, tableDesc.GetParentSchemaID(), "test2", s.Clock().Now())
   320  	if lease == nil {
   321  		t.Fatalf("new name not found in cache")
   322  	}
   323  	if lease.ID != tableDesc.ID {
   324  		t.Fatalf("new name has wrong ID: %d (expected: %d)", lease.ID, tableDesc.ID)
   325  	}
   326  	if err := leaseManager.Release(&lease.ImmutableTableDescriptor); err != nil {
   327  		t.Fatal(err)
   328  	}
   329  
   330  	// Rename to a different database.
   331  	if _, err := db.Exec("ALTER TABLE t.test2 RENAME TO t1.test2;"); err != nil {
   332  		t.Fatal(err)
   333  	}
   334  
   335  	// Re-read the descriptor, to get the new ParentID.
   336  	newTableDesc := sqlbase.GetTableDescriptor(kvDB, keys.SystemSQLCodec, "t1", "test2")
   337  	if tableDesc.ParentID == newTableDesc.ParentID {
   338  		t.Fatalf("database didn't change")
   339  	}
   340  
   341  	// Check that the cache has been updated.
   342  	if leaseManager.tableNames.get(tableDesc.ParentID, tableDesc.GetParentSchemaID(), "test2", s.Clock().Now()) != nil {
   343  		t.Fatalf("old name still in cache")
   344  	}
   345  
   346  	lease = leaseManager.tableNames.get(newTableDesc.ParentID, tableDesc.GetParentSchemaID(), "test2", s.Clock().Now())
   347  	if lease == nil {
   348  		t.Fatalf("new name not found in cache")
   349  	}
   350  	if lease.ID != tableDesc.ID {
   351  		t.Fatalf("new name has wrong ID: %d (expected: %d)", lease.ID, tableDesc.ID)
   352  	}
   353  	if err := leaseManager.Release(&lease.ImmutableTableDescriptor); err != nil {
   354  		t.Fatal(err)
   355  	}
   356  }
   357  
   358  // Tests that a name cache entry with by an expired lease is not returned.
   359  func TestNameCacheEntryDoesntReturnExpiredLease(t *testing.T) {
   360  	defer leaktest.AfterTest(t)()
   361  	s, db, kvDB := serverutils.StartServer(t, base.TestServerArgs{})
   362  	defer s.Stopper().Stop(context.Background())
   363  	leaseManager := s.LeaseManager().(*Manager)
   364  
   365  	const tableName = "test"
   366  
   367  	if _, err := db.Exec(fmt.Sprintf(`
   368  CREATE DATABASE t;
   369  CREATE TABLE t.%s (k CHAR PRIMARY KEY, v CHAR);
   370  `, tableName)); err != nil {
   371  		t.Fatal(err)
   372  	}
   373  
   374  	// Populate the name cache.
   375  	if _, err := db.Exec("SELECT * FROM t.test;"); err != nil {
   376  		t.Fatal(err)
   377  	}
   378  
   379  	tableDesc := sqlbase.GetTableDescriptor(kvDB, keys.SystemSQLCodec, "t", tableName)
   380  
   381  	// Check the assumptions this tests makes: that there is a cache entry
   382  	// (with a valid lease).
   383  	if lease := leaseManager.tableNames.get(tableDesc.ParentID, tableDesc.GetParentSchemaID(), tableName, s.Clock().Now()); lease == nil {
   384  		t.Fatalf("name cache has no unexpired entry for (%d, %s)", tableDesc.ParentID, tableName)
   385  	} else {
   386  		if err := leaseManager.Release(&lease.ImmutableTableDescriptor); err != nil {
   387  			t.Fatal(err)
   388  		}
   389  	}
   390  
   391  	leaseManager.ExpireLeases(s.Clock())
   392  
   393  	// Check the name no longer resolves.
   394  	if lease := leaseManager.tableNames.get(tableDesc.ParentID, tableDesc.GetParentSchemaID(), tableName, s.Clock().Now()); lease != nil {
   395  		t.Fatalf("name cache has unexpired entry for (%d, %s): %s", tableDesc.ParentID, tableName, lease)
   396  	}
   397  }
   398  
   399  // Tests that a name cache entry always exists for the latest lease and
   400  // the lease expiration time is monotonically increasing.
   401  func TestNameCacheContainsLatestLease(t *testing.T) {
   402  	defer leaktest.AfterTest(t)()
   403  	removalTracker := NewLeaseRemovalTracker()
   404  	testingKnobs := base.TestingKnobs{
   405  		SQLLeaseManager: &ManagerTestingKnobs{
   406  			LeaseStoreTestingKnobs: StorageTestingKnobs{
   407  				LeaseReleasedEvent: removalTracker.LeaseRemovedNotification,
   408  			},
   409  		},
   410  	}
   411  	s, db, kvDB := serverutils.StartServer(t, base.TestServerArgs{Knobs: testingKnobs})
   412  	defer s.Stopper().Stop(context.Background())
   413  	leaseManager := s.LeaseManager().(*Manager)
   414  
   415  	const tableName = "test"
   416  
   417  	if _, err := db.Exec(fmt.Sprintf(`
   418  CREATE DATABASE t;
   419  CREATE TABLE t.%s (k CHAR PRIMARY KEY, v CHAR);
   420  `, tableName)); err != nil {
   421  		t.Fatal(err)
   422  	}
   423  
   424  	tableDesc := sqlbase.GetTableDescriptor(kvDB, keys.SystemSQLCodec, "t", tableName)
   425  
   426  	// Populate the name cache.
   427  	if _, err := db.Exec("SELECT * FROM t.test;"); err != nil {
   428  		t.Fatal(err)
   429  	}
   430  
   431  	// There is a cache entry.
   432  	lease := leaseManager.tableNames.get(tableDesc.ParentID, tableDesc.GetParentSchemaID(), tableName, s.Clock().Now())
   433  	if lease == nil {
   434  		t.Fatalf("name cache has no unexpired entry for (%d, %s)", tableDesc.ParentID, tableName)
   435  	}
   436  
   437  	tracker := removalTracker.TrackRemoval(&lease.ImmutableTableDescriptor)
   438  
   439  	// Acquire another lease.
   440  	if _, err := acquireNodeLease(context.Background(), leaseManager, tableDesc.ID); err != nil {
   441  		t.Fatal(err)
   442  	}
   443  
   444  	// Check the name resolves to the new lease.
   445  	newLease := leaseManager.tableNames.get(tableDesc.ParentID, tableDesc.GetParentSchemaID(), tableName, s.Clock().Now())
   446  	if newLease == nil {
   447  		t.Fatalf("name cache doesn't contain entry for (%d, %s)", tableDesc.ParentID, tableName)
   448  	}
   449  	if newLease == lease {
   450  		t.Fatalf("same lease %s", newLease.expiration.GoTime())
   451  	}
   452  
   453  	if err := leaseManager.Release(&lease.ImmutableTableDescriptor); err != nil {
   454  		t.Fatal(err)
   455  	}
   456  
   457  	// The first lease acquisition was released.
   458  	if err := tracker.WaitForRemoval(); err != nil {
   459  		t.Fatal(err)
   460  	}
   461  
   462  	if err := leaseManager.Release(&newLease.ImmutableTableDescriptor); err != nil {
   463  		t.Fatal(err)
   464  	}
   465  }
   466  
   467  // Test that table names are treated as case sensitive by the name cache.
   468  func TestTableNameCaseSensitive(t *testing.T) {
   469  	defer leaktest.AfterTest(t)()
   470  	s, db, kvDB := serverutils.StartServer(t, base.TestServerArgs{})
   471  	defer s.Stopper().Stop(context.Background())
   472  	leaseManager := s.LeaseManager().(*Manager)
   473  
   474  	if _, err := db.Exec(`
   475  CREATE DATABASE t;
   476  CREATE TABLE t.test (k CHAR PRIMARY KEY, v CHAR);
   477  `); err != nil {
   478  		t.Fatal(err)
   479  	}
   480  
   481  	// Populate the name cache.
   482  	if _, err := db.Exec("SELECT * FROM t.test;"); err != nil {
   483  		t.Fatal(err)
   484  	}
   485  
   486  	tableDesc := sqlbase.GetTableDescriptor(kvDB, keys.SystemSQLCodec, "t", "test")
   487  
   488  	// Check that we cannot get the table by a different name.
   489  	if leaseManager.tableNames.get(tableDesc.ParentID, tableDesc.GetParentSchemaID(), "tEsT", s.Clock().Now()) != nil {
   490  		t.Fatalf("lease manager incorrectly found table with different case")
   491  	}
   492  }
   493  
   494  // Test that there's no deadlock between AcquireByName and Release.
   495  // We used to have one due to lock inversion between the tableNameCache lock and
   496  // the tableVersionState lock, triggered when the same lease was Release()d after the
   497  // table had been dropped (which means it's removed from the tableNameCache) and
   498  // AcquireByName()d at the same time.
   499  func TestReleaseAcquireByNameDeadlock(t *testing.T) {
   500  	defer leaktest.AfterTest(t)()
   501  	removalTracker := NewLeaseRemovalTracker()
   502  	testingKnobs := base.TestingKnobs{
   503  		SQLLeaseManager: &ManagerTestingKnobs{
   504  			LeaseStoreTestingKnobs: StorageTestingKnobs{
   505  				LeaseReleasedEvent:     removalTracker.LeaseRemovedNotification,
   506  				RemoveOnceDereferenced: true,
   507  			},
   508  		},
   509  	}
   510  	s, sqlDB, kvDB := serverutils.StartServer(
   511  		t, base.TestServerArgs{Knobs: testingKnobs})
   512  	defer s.Stopper().Stop(context.Background())
   513  	leaseManager := s.LeaseManager().(*Manager)
   514  
   515  	if _, err := sqlDB.Exec(`
   516  CREATE DATABASE t;
   517  CREATE TABLE t.test (k CHAR PRIMARY KEY, v CHAR);
   518  `); err != nil {
   519  		t.Fatal(err)
   520  	}
   521  
   522  	tableDesc := sqlbase.GetTableDescriptor(kvDB, keys.SystemSQLCodec, "t", "test")
   523  
   524  	// Populate the name cache.
   525  	ctx := context.Background()
   526  	table, _, err := leaseManager.AcquireByName(
   527  		ctx,
   528  		leaseManager.clock.Now(),
   529  		tableDesc.ParentID,
   530  		tableDesc.GetParentSchemaID(),
   531  		"test",
   532  	)
   533  	if err != nil {
   534  		t.Fatal(err)
   535  	}
   536  	if err := leaseManager.Release(table); err != nil {
   537  		t.Fatal(err)
   538  	}
   539  
   540  	// Try to trigger the race repeatedly: race an AcquireByName against a
   541  	// Release.
   542  	// tableChan acts as a barrier, synchronizing the two routines at every
   543  	// iteration.
   544  	tableChan := make(chan *sqlbase.ImmutableTableDescriptor)
   545  	errChan := make(chan error)
   546  	go func() {
   547  		for table := range tableChan {
   548  			// Move errors to the main goroutine.
   549  			errChan <- leaseManager.Release(table)
   550  		}
   551  	}()
   552  
   553  	for i := 0; i < 50; i++ {
   554  		timestamp := leaseManager.clock.Now()
   555  		ctx := context.Background()
   556  		table, _, err := leaseManager.AcquireByName(
   557  			ctx,
   558  			timestamp,
   559  			tableDesc.ParentID,
   560  			tableDesc.GetParentSchemaID(),
   561  			"test",
   562  		)
   563  		if err != nil {
   564  			t.Fatal(err)
   565  		}
   566  		// This test will need to wait until leases are removed from the store
   567  		// before creating new leases because the jitter used in the leases'
   568  		// expiration causes duplicate key errors when trying to create new
   569  		// leases. This is not a problem in production, since leases are not
   570  		// removed from the store until they expire, and the jitter is small
   571  		// compared to their lifetime, but it is a problem in this test because
   572  		// we churn through leases quickly.
   573  		tracker := removalTracker.TrackRemoval(table)
   574  		// Start the race: signal the other guy to release, and we do another
   575  		// acquire at the same time.
   576  		tableChan <- table
   577  		tableByName, _, err := leaseManager.AcquireByName(
   578  			ctx,
   579  			timestamp,
   580  			tableDesc.ParentID,
   581  			tableDesc.GetParentSchemaID(),
   582  			"test",
   583  		)
   584  		if err != nil {
   585  			t.Fatal(err)
   586  		}
   587  
   588  		// See if there was an error releasing lease.
   589  		err = <-errChan
   590  		if err != nil {
   591  			t.Fatal(err)
   592  		}
   593  
   594  		// Even after waiting for the error above, the lease might still
   595  		// need removal from the store because lease removal is asynchronous.
   596  		// Depending on how the race went, there are two cases - either the
   597  		// AcquireByName ran first, and got the same lease as we already had,
   598  		// or the Release ran first and so we got a new lease and can wait here
   599  		// for the old lease to be released.
   600  		if tableByName != table {
   601  			if err := tracker.WaitForRemoval(); err != nil {
   602  				t.Fatal(err)
   603  			}
   604  		}
   605  
   606  		// Track removal only after the above call to WaitForRemoval
   607  		// so that if there is an existing removal of a lease
   608  		// (Release occurred before AcquireByName) it is guaranteed
   609  		// to not reuse an existing tracker.
   610  		tracker2 := removalTracker.TrackRemoval(tableByName)
   611  
   612  		if err := leaseManager.Release(tableByName); err != nil {
   613  			t.Fatal(err)
   614  		}
   615  
   616  		if err := tracker2.WaitForRemoval(); err != nil {
   617  			t.Fatal(err)
   618  		}
   619  	}
   620  	close(tableChan)
   621  }
   622  
   623  // TestAcquireFreshestFromStoreRaces runs
   624  // Manager.acquireFreshestFromStore() in parallel to test for races.
   625  func TestAcquireFreshestFromStoreRaces(t *testing.T) {
   626  	defer leaktest.AfterTest(t)()
   627  	s, db, kvDB := serverutils.StartServer(t, base.TestServerArgs{})
   628  	defer s.Stopper().Stop(context.Background())
   629  	leaseManager := s.LeaseManager().(*Manager)
   630  
   631  	if _, err := db.Exec(`
   632  CREATE DATABASE t;
   633  CREATE TABLE t.test (k CHAR PRIMARY KEY, v CHAR);
   634  `); err != nil {
   635  		t.Fatal(err)
   636  	}
   637  
   638  	tableDesc := sqlbase.GetTableDescriptor(kvDB, keys.SystemSQLCodec, "t", "test")
   639  
   640  	var wg sync.WaitGroup
   641  	numRoutines := 10
   642  	wg.Add(numRoutines)
   643  	for i := 0; i < numRoutines; i++ {
   644  		go func() {
   645  			defer wg.Done()
   646  			if err := leaseManager.AcquireFreshestFromStore(context.Background(), tableDesc.ID); err != nil {
   647  				t.Error(err)
   648  			}
   649  			table, _, err := leaseManager.Acquire(context.Background(), s.Clock().Now(), tableDesc.ID)
   650  			if err != nil {
   651  				t.Error(err)
   652  			}
   653  			if err := leaseManager.Release(table); err != nil {
   654  				t.Error(err)
   655  			}
   656  		}()
   657  	}
   658  	wg.Wait()
   659  }
   660  
   661  // This test checks that multiple threads can simultaneously acquire the
   662  // latest table version with a lease. When multiple threads
   663  // wait on a particular thread acquiring a lease for the latest table version,
   664  // they are able to check after waiting that the lease they were waiting on
   665  // is still valid. They are able to reacquire a lease if needed.
   666  func TestParallelLeaseAcquireWithImmediateRelease(t *testing.T) {
   667  	defer leaktest.AfterTest(t)()
   668  	testingKnobs := base.TestingKnobs{
   669  		SQLLeaseManager: &ManagerTestingKnobs{
   670  			LeaseStoreTestingKnobs: StorageTestingKnobs{
   671  				// Immediate remove tableVersionState and release its
   672  				// lease when it is dereferenced. This forces threads
   673  				// waiting on a lease to reacquire the lease.
   674  				RemoveOnceDereferenced: true,
   675  			},
   676  		},
   677  	}
   678  	s, sqlDB, kvDB := serverutils.StartServer(
   679  		t, base.TestServerArgs{Knobs: testingKnobs})
   680  	defer s.Stopper().Stop(context.Background())
   681  	leaseManager := s.LeaseManager().(*Manager)
   682  
   683  	if _, err := sqlDB.Exec(`
   684  CREATE DATABASE t;
   685  CREATE TABLE t.test (k CHAR PRIMARY KEY, v CHAR);
   686  `); err != nil {
   687  		t.Fatal(err)
   688  	}
   689  
   690  	tableDesc := sqlbase.GetTableDescriptor(kvDB, keys.SystemSQLCodec, "t", "test")
   691  
   692  	var wg sync.WaitGroup
   693  	numRoutines := 10
   694  	now := s.Clock().Now()
   695  	wg.Add(numRoutines)
   696  	for i := 0; i < numRoutines; i++ {
   697  		go func() {
   698  			defer wg.Done()
   699  			table, _, err := leaseManager.Acquire(context.Background(), now, tableDesc.ID)
   700  			if err != nil {
   701  				t.Error(err)
   702  			}
   703  			if err := leaseManager.Release(table); err != nil {
   704  				t.Error(err)
   705  			}
   706  		}()
   707  	}
   708  
   709  	wg.Wait()
   710  }
   711  
   712  // Test one possible outcome of a race between a lease acquisition (the first
   713  // case through tableState.acquire(), the second through
   714  // tableState.acquireFreshestFromStore()) and a release of the lease that was
   715  // just acquired. Precisely:
   716  // 1. Thread 1 calls either acquireFreshestFromStore() or acquire().
   717  // 2. Thread 1 releases the lock on tableState and starts acquisition of a lease
   718  //    from the store, blocking until it's finished.
   719  // 3. Thread 2 calls acquire(). The lease has not been acquired yet, so it
   720  //    also enters the acquisition code path (calling DoChan).
   721  // 4. Thread 2 proceeds to release the lock on tableState waiting for the
   722  //    in-flight acquisition.
   723  // 4. The lease is acquired from the store and the waiting routines are
   724  //    unblocked.
   725  // 5. Thread 2 unblocks first, and releases the new lease, for whatever reason.
   726  // 5. Thread 1 wakes up. At this point, a naive implementation would use the
   727  //    newly acquired lease, which would be incorrect. The test checks that
   728  //    acquireFreshestFromStore() or acquire() notices, after re-acquiring the
   729  //    tableState lock, that the new lease has been released and acquires a new
   730  //    one.
   731  func TestLeaseAcquireAndReleaseConcurrently(t *testing.T) {
   732  	defer leaktest.AfterTest(t)()
   733  
   734  	t.Skip("fails in the presence of migrations requiring backfill, but cannot import sqlmigrations")
   735  
   736  	// Result is a struct for moving results to the main result routine.
   737  	type Result struct {
   738  		table *sqlbase.ImmutableTableDescriptor
   739  		exp   hlc.Timestamp
   740  		err   error
   741  	}
   742  
   743  	descID := sqlbase.ID(keys.LeaseTableID)
   744  
   745  	// acquireBlock calls Acquire.
   746  	acquireBlock := func(
   747  		ctx context.Context,
   748  		m *Manager,
   749  		acquireChan chan Result,
   750  	) {
   751  		table, e, err := m.Acquire(ctx, m.clock.Now(), descID)
   752  		acquireChan <- Result{err: err, exp: e, table: table}
   753  	}
   754  
   755  	testCases := []struct {
   756  		name string
   757  		// Whether the second routine is a call to Manager.acquireFreshest or
   758  		// not. This determines which channel we unblock.
   759  		isSecondCallAcquireFreshest bool
   760  	}{
   761  
   762  		// Checks what happens when the race between between acquire() and
   763  		// lease release occurs.
   764  		{
   765  			name:                        "CallAcquireConcurrently",
   766  			isSecondCallAcquireFreshest: false,
   767  		},
   768  		// Checks what happens when the race between
   769  		// acquireFreshestFromStore() and lease release occurs.
   770  		{
   771  			name:                        "CallAcquireFreshestAndAcquireConcurrently",
   772  			isSecondCallAcquireFreshest: true,
   773  		},
   774  	}
   775  
   776  	for _, test := range testCases {
   777  		ctx := logtags.AddTag(context.Background(), "test: Lease", nil)
   778  
   779  		t.Run(test.name, func(t *testing.T) {
   780  			// blockChan and freshestBlockChan is used to set up the race condition.
   781  			blockChan := make(chan struct{})
   782  			freshestBlockChan := make(chan struct{})
   783  			// acquisitionBlock is used to prevent acquireNodeLease from
   784  			// completing, to force a lease to delay its acquisition.
   785  			acquisitionBlock := make(chan struct{})
   786  
   787  			// preblock is used for the main routine to wait for all acquisition
   788  			// routines to catch up.
   789  			var preblock sync.WaitGroup
   790  			// acquireArrivals and acquireFreshestArrivals tracks how many times
   791  			// we've arrived at the knob codepath for the corresponding functions.
   792  			// This is needed because the fix to the race condition hits the knob more
   793  			// than once in a single routine, so we need to ignore any extra passes.
   794  			var acquireArrivals int32
   795  			var acquireFreshestArrivals int32
   796  			// leasesAcquiredCount counts how many leases were acquired in total.
   797  			var leasesAcquiredCount int32
   798  
   799  			removalTracker := NewLeaseRemovalTracker()
   800  			testingKnobs := base.TestingKnobs{
   801  				SQLLeaseManager: &ManagerTestingKnobs{
   802  					LeaseStoreTestingKnobs: StorageTestingKnobs{
   803  						RemoveOnceDereferenced: true,
   804  						LeaseReleasedEvent:     removalTracker.LeaseRemovedNotification,
   805  						LeaseAcquireResultBlockEvent: func(leaseBlockType AcquireBlockType) {
   806  							if leaseBlockType == AcquireBlock {
   807  								if count := atomic.LoadInt32(&acquireArrivals); (count < 1 && test.isSecondCallAcquireFreshest) ||
   808  									(count < 2 && !test.isSecondCallAcquireFreshest) {
   809  									atomic.AddInt32(&acquireArrivals, 1)
   810  									preblock.Done()
   811  									<-blockChan
   812  								}
   813  							} else if leaseBlockType == AcquireFreshestBlock {
   814  								if atomic.LoadInt32(&acquireFreshestArrivals) < 1 {
   815  									atomic.AddInt32(&acquireFreshestArrivals, 1)
   816  									preblock.Done()
   817  									<-freshestBlockChan
   818  								}
   819  							}
   820  						},
   821  						LeaseAcquiredEvent: func(_ sqlbase.TableDescriptor, _ error) {
   822  							atomic.AddInt32(&leasesAcquiredCount, 1)
   823  							<-acquisitionBlock
   824  						},
   825  					},
   826  				},
   827  			}
   828  
   829  			serverArgs := base.TestServerArgs{Knobs: testingKnobs}
   830  
   831  			serverArgs.LeaseManagerConfig = base.NewLeaseManagerConfig()
   832  			// The LeaseJitterFraction is zero so leases will have
   833  			// monotonically increasing expiration. This prevents two leases
   834  			// from having the same expiration due to randomness, as the
   835  			// leases are checked for having a different expiration.
   836  			serverArgs.LeaseManagerConfig.TableDescriptorLeaseJitterFraction = 0.0
   837  
   838  			s, _, _ := serverutils.StartServer(
   839  				t, serverArgs)
   840  			defer s.Stopper().Stop(context.Background())
   841  			leaseManager := s.LeaseManager().(*Manager)
   842  
   843  			acquireResultChan := make(chan Result)
   844  
   845  			// Start two routines to acquire and release.
   846  			preblock.Add(2)
   847  			go acquireBlock(ctx, leaseManager, acquireResultChan)
   848  			if test.isSecondCallAcquireFreshest {
   849  				go func(ctx context.Context, m *Manager, acquireChan chan Result) {
   850  					if err := m.AcquireFreshestFromStore(ctx, descID); err != nil {
   851  						acquireChan <- Result{err: err, exp: hlc.Timestamp{}, table: nil}
   852  						return
   853  					}
   854  					table, e, err := m.Acquire(ctx, s.Clock().Now(), descID)
   855  					acquireChan <- Result{err: err, exp: e, table: table}
   856  				}(ctx, leaseManager, acquireResultChan)
   857  
   858  			} else {
   859  				go acquireBlock(ctx, leaseManager, acquireResultChan)
   860  			}
   861  
   862  			// Wait until both routines arrive.
   863  			preblock.Wait()
   864  
   865  			// Allow the acquisition to finish. By delaying it until now, we guarantee
   866  			// both routines will receive the same lease.
   867  			acquisitionBlock <- struct{}{}
   868  
   869  			// Allow the first routine to finish acquisition. In the case where both
   870  			// routines are calling Acquire(), first refers to whichever routine
   871  			// continues, order does not matter.
   872  			blockChan <- struct{}{}
   873  			// Wait for the first routine's results.
   874  			result1 := <-acquireResultChan
   875  			if result1.err != nil {
   876  				t.Fatal(result1.err)
   877  			}
   878  
   879  			// Release the lease. This also causes it to get removed as the
   880  			// knob RemoveOnceDereferenced is set.
   881  			tracker := removalTracker.TrackRemoval(result1.table)
   882  			if err := leaseManager.Release(result1.table); err != nil {
   883  				t.Fatal(err)
   884  			}
   885  			// Wait until the lease is removed.
   886  			if err := tracker.WaitForRemoval(); err != nil {
   887  				t.Fatal(err)
   888  			}
   889  
   890  			// Allow the second routine to proceed.
   891  			if test.isSecondCallAcquireFreshest {
   892  				freshestBlockChan <- struct{}{}
   893  			} else {
   894  				blockChan <- struct{}{}
   895  			}
   896  
   897  			// Allow all future acquisitions to complete.
   898  			close(acquisitionBlock)
   899  
   900  			// Get the acquisition results of the second routine.
   901  			result2 := <-acquireResultChan
   902  			if result2.err != nil {
   903  				t.Fatal(result2.err)
   904  			}
   905  
   906  			if result1.table == result2.table && result1.exp == result2.exp {
   907  				t.Fatalf("Expected the leases to be different. TableDescriptor pointers are equal and both the same expiration")
   908  			}
   909  			if count := atomic.LoadInt32(&leasesAcquiredCount); count != 2 {
   910  				t.Fatalf("Expected to acquire 2 leases, instead got %d", count)
   911  			}
   912  		})
   913  	}
   914  }