func checkKeyCount(t *testing.T, kvDB *client.DB, prefix roachpb.Key, numKeys int) { if kvs, err := kvDB.Scan(context.TODO(), prefix, prefix.PrefixEnd(), 0); err != nil { t.Fatal(err) } else if l := numKeys; len(kvs) != l { t.Fatalf("expected %d key value pairs, but got %d", l, len(kvs)) } }
// getRangeKeys returns the end keys of all ranges. func getRangeKeys(db *client.DB) ([]roachpb.Key, error) { rows, err := db.Scan(context.TODO(), keys.Meta2Prefix, keys.MetaMax, 0) if err != nil { return nil, err } ret := make([]roachpb.Key, len(rows), len(rows)) for i := 0; i < len(rows); i++ { ret[i] = bytes.TrimPrefix(rows[i].Key, keys.Meta2Prefix) } return ret, nil }
// WaitForInitialSplits waits for the expected number of initial ranges to be // populated in the meta2 table. If the expected range count is not reached // within a configured timeout, an error is returned. func WaitForInitialSplits(db *client.DB) error { expectedRanges := ExpectedInitialRangeCount() return util.RetryForDuration(initialSplitsTimeout, func() error { // Scan all keys in the Meta2Prefix; we only need a count. rows, err := db.Scan(context.TODO(), keys.Meta2Prefix, keys.MetaMax, 0) if err != nil { return err } if a, e := len(rows), expectedRanges; a != e { return errors.Errorf("had %d ranges at startup, expected %d", a, e) } return nil }) }
// Run a particular schema change and run some OLTP operations in parallel, as // soon as the schema change starts executing its backfill. func runSchemaChangeWithOperations( t *testing.T, sqlDB *gosql.DB, kvDB *client.DB, schemaChange string, maxValue int, keyMultiple int, backfillNotification chan bool, ) { tableDesc := sqlbase.GetTableDescriptor(kvDB, "t", "test") // Run the schema change in a separate goroutine. var wg sync.WaitGroup wg.Add(1) go func() { start := timeutil.Now() // Start schema change that eventually runs a backfill. if _, err := sqlDB.Exec(schemaChange); err != nil { t.Error(err) } t.Logf("schema change %s took %v", schemaChange, timeutil.Since(start)) wg.Done() }() // Wait until the schema change backfill starts. <-backfillNotification // Run a variety of operations during the backfill. // Grabbing a schema change lease on the table will fail, disallowing // another schema change from being simultaneously executed. sc := csql.NewSchemaChangerForTesting(tableDesc.ID, 0, 0, *kvDB, nil) if l, err := sc.AcquireLease(); err == nil { t.Fatalf("schema change lease acquisition on table %d succeeded: %v", tableDesc.ID, l) } // Update some rows. var updatedKeys []int for i := 0; i < 10; i++ { k := rand.Intn(maxValue) v := maxValue + i + 1 if _, err := sqlDB.Exec(`UPDATE t.test SET v = $1 WHERE k = $2`, v, k); err != nil { t.Error(err) } updatedKeys = append(updatedKeys, k) } // Reupdate updated values back to what they were before. for _, k := range updatedKeys { if _, err := sqlDB.Exec(`UPDATE t.test SET v = $1 WHERE k = $2`, maxValue-k, k); err != nil { t.Error(err) } } // Delete some rows. deleteStartKey := rand.Intn(maxValue - 10) for i := 0; i < 10; i++ { if _, err := sqlDB.Exec(`DELETE FROM t.test WHERE k = $1`, deleteStartKey+i); err != nil { t.Error(err) } } // Reinsert deleted rows. for i := 0; i < 10; i++ { k := deleteStartKey + i if _, err := sqlDB.Exec(`INSERT INTO t.test VALUES($1, $2)`, k, maxValue-k); err != nil { t.Error(err) } } // Insert some new rows. numInserts := 10 for i := 0; i < numInserts; i++ { k := maxValue + i + 1 if _, err := sqlDB.Exec(`INSERT INTO t.test VALUES($1, $1)`, k); err != nil { t.Error(err) } } wg.Wait() // for schema change to complete. // Verify the number of keys left behind in the table to validate schema // change operations. tablePrefix := roachpb.Key(keys.MakeTablePrefix(uint32(tableDesc.ID))) tableEnd := tablePrefix.PrefixEnd() if kvs, err := kvDB.Scan(context.TODO(), tablePrefix, tableEnd, 0); err != nil { t.Fatal(err) } else if e := keyMultiple * (maxValue + numInserts + 1); len(kvs) != e { for _, kv := range kvs { t.Errorf("key %s, value %s", kv.Key, kv.Value) } t.Fatalf("expected %d key value pairs, but got %d", e, len(kvs)) } // Delete the rows inserted. for i := 0; i < numInserts; i++ { if _, err := sqlDB.Exec(`DELETE FROM t.test WHERE k = $1`, maxValue+i+1); err != nil { t.Error(err) } } }