func gossipForTest(t *testing.T) (*gossip.Gossip, *stop.Stopper) { stopper := stop.NewStopper() // Setup fake zone config handler. config.TestingSetupZoneConfigHook(stopper) rpcContext := rpc.NewContext(nil, nil, stopper) g := gossip.New(rpcContext, nil, stopper) // Have to call g.SetNodeID before call g.AddInfo g.SetNodeID(roachpb.NodeID(1)) // Put an empty system config into gossip. if err := g.AddInfoProto(gossip.KeySystemConfig, &config.SystemConfig{}, 0); err != nil { t.Fatal(err) } // Wait for SystemConfig. util.SucceedsSoon(t, func() error { if _, ok := g.GetSystemConfig(); !ok { return util.Errorf("expected system config to be set") } return nil }) return g, stopper }
// TestStoreRangeSplitWithMaxBytesUpdate tests a scenario where a new // zone config that updates the max bytes is set and triggers a range // split. func TestStoreRangeSplitWithMaxBytesUpdate(t *testing.T) { defer leaktest.AfterTest(t) store, stopper := createTestStore(t) config.TestingSetupZoneConfigHook(stopper) defer stopper.Stop() origRng := store.LookupReplica(roachpb.RKeyMin, nil) // Set max bytes. maxBytes := int64(1 << 16) config.TestingSetZoneConfig(1000, &config.ZoneConfig{RangeMaxBytes: maxBytes}) // Trigger gossip callback. if err := store.Gossip().AddInfoProto(gossip.KeySystemConfig, &config.SystemConfig{}, 0); err != nil { t.Fatal(err) } // Verify that the range is split and the new range has the correct max bytes. util.SucceedsWithin(t, time.Second, func() error { newRng := store.LookupReplica(keys.MakeTablePrefix(1000), nil) if newRng.Desc().RangeID == origRng.Desc().RangeID { return util.Errorf("expected new range created by split") } if newRng.GetMaxBytes() != maxBytes { return util.Errorf("expected %d max bytes for the new range, but got %d", maxBytes, newRng.GetMaxBytes()) } return nil }) }
func gossipForTest(t *testing.T) (*gossip.Gossip, *stop.Stopper) { stopper := stop.NewStopper() // Setup fake zone config handler. config.TestingSetupZoneConfigHook(stopper) rpcContext := rpc.NewContext(&base.Context{}, hlc.NewClock(hlc.UnixNano), stopper) g := gossip.New(rpcContext, gossip.TestBootstrap, stopper) // Have to call g.SetNodeID before call g.AddInfo g.SetNodeID(roachpb.NodeID(1)) // Put an empty system config into gossip. if err := g.AddInfoProto(gossip.KeySystemConfig, &config.SystemConfig{}, 0); err != nil { t.Fatal(err) } // Wait for SystemConfig. util.SucceedsSoon(t, func() error { if g.GetSystemConfig() == nil { return util.Errorf("expected non-nil system config") } return nil }) return g, stopper }
func gossipForTest(t *testing.T) (*gossip.Gossip, *stop.Stopper) { stopper := stop.NewStopper() // Setup fake zone config handler. config.TestingSetupZoneConfigHook(stopper) rpcContext := rpc.NewContext(&base.Context{}, hlc.NewClock(hlc.UnixNano), stopper) g := gossip.New(rpcContext, gossip.TestBootstrap) // Have to call g.SetNodeID before call g.AddInfo g.SetNodeID(roachpb.NodeID(1)) // Put an empty system config into gossip. if err := g.AddInfoProto(gossip.KeySystemConfig, &config.SystemConfig{}, 0); err != nil { t.Fatal(err) } // Wait for SystemConfig. if err := util.IsTrueWithin(func() bool { return g.GetSystemConfig() != nil }, 100*time.Millisecond); err != nil { t.Fatal(err) } return g, stopper }
// createTestStoreWithoutStart creates a test store using an in-memory // engine without starting the store. It returns the store, the store // clock's manual unix nanos time and a stopper. The caller is // responsible for stopping the stopper upon completion. func createTestStoreWithoutStart(t *testing.T) (*Store, *hlc.ManualClock, *stop.Stopper) { stopper := stop.NewStopper() // Setup fake zone config handler. config.TestingSetupZoneConfigHook(stopper) rpcContext := rpc.NewContext(&base.Context{}, hlc.NewClock(hlc.UnixNano), stopper) ctx := TestStoreContext ctx.Gossip = gossip.New(rpcContext, gossip.TestInterval, gossip.TestBootstrap) ctx.StorePool = NewStorePool(ctx.Gossip, TestTimeUntilStoreDeadOff, stopper) manual := hlc.NewManualClock(0) ctx.Clock = hlc.NewClock(manual.UnixNano) eng := engine.NewInMem(roachpb.Attributes{}, 10<<20, stopper) ctx.Transport = multiraft.NewLocalRPCTransport(stopper) stopper.AddCloser(ctx.Transport) sender := &testSender{} ctx.DB = client.NewDB(sender) store := NewStore(ctx, eng, &roachpb.NodeDescriptor{NodeID: 1}) sender.store = store if err := store.Bootstrap(roachpb.StoreIdent{NodeID: 1, StoreID: 1}, stopper); err != nil { t.Fatal(err) } if err := store.BootstrapRange(nil); err != nil { t.Fatal(err) } return store, manual, stopper }
// TestStoreZoneUpdateAndRangeSplit verifies that modifying the zone // configuration changes range max bytes and Range.maybeSplit() takes // max bytes into account when deciding whether to enqueue a range for // splitting. It further verifies that the range is in fact split on // exceeding zone's RangeMaxBytes. func TestStoreZoneUpdateAndRangeSplit(t *testing.T) { defer leaktest.AfterTest(t) t.Skip("#3762") store, stopper := createTestStore(t) config.TestingSetupZoneConfigHook(stopper) defer stopper.Stop() maxBytes := int64(1 << 16) // Set max bytes. descID := uint32(keys.MaxReservedDescID + 1) config.TestingSetZoneConfig(descID, &config.ZoneConfig{RangeMaxBytes: maxBytes}) // Trigger gossip callback. if err := store.Gossip().AddInfoProto(gossip.KeySystemConfig, &config.SystemConfig{}, 0); err != nil { t.Fatal(err) } // Wait for the range to be split along table boundaries. originalRange := store.LookupReplica(roachpb.RKey(keys.UserTableDataMin), nil) var rng *storage.Replica if err := util.IsTrueWithin(func() bool { rng = store.LookupReplica(keys.MakeTablePrefix(descID), nil) return rng.RangeID != originalRange.RangeID }, splitTimeout); err != nil { t.Fatalf("failed to notice range max bytes update: %s", err) } // Check range's max bytes settings. if rng.GetMaxBytes() != maxBytes { t.Fatalf("range max bytes mismatch, got: %d, expected: %d", rng.GetMaxBytes(), maxBytes) } // Make sure the second range goes to the end. if !roachpb.RKeyMax.Equal(rng.Desc().EndKey) { t.Fatalf("second range has split: %+v", rng.Desc()) } // Look in the range after prefix we're writing to. fillRange(store, rng.RangeID, keys.MakeTablePrefix(descID), maxBytes, t) // Verify that the range is in fact split (give it a few seconds for very // slow test machines). var newRng *storage.Replica util.SucceedsWithin(t, splitTimeout, func() error { newRng = store.LookupReplica(keys.MakeTablePrefix(descID+1), nil) if newRng.RangeID == rng.RangeID { return util.Errorf("range has not yet split") } return nil }) // Make sure the new range goes to the end. if !roachpb.RKeyMax.Equal(newRng.Desc().EndKey) { t.Fatalf("second range has split: %+v", rng.Desc()) } }
// TestRangeSplitsWithWritePressure sets the zone config max bytes for // a range to 256K and writes data until there are five ranges. func TestRangeSplitsWithWritePressure(t *testing.T) { defer leaktest.AfterTest(t)() // Override default zone config. cfg := config.DefaultZoneConfig() cfg.RangeMaxBytes = 1 << 18 defer config.TestingSetDefaultZoneConfig(cfg)() dbCtx := client.DefaultDBContext() dbCtx.TxnRetryOptions = retry.Options{ InitialBackoff: 1 * time.Millisecond, MaxBackoff: 10 * time.Millisecond, Multiplier: 2, } s, _ := createTestDBWithContext(t, dbCtx) // This is purely to silence log spam. config.TestingSetupZoneConfigHook(s.Stopper) defer s.Stop() // Start test writer write about a 32K/key so there aren't too many writes necessary to split 64K range. done := make(chan struct{}) var wg sync.WaitGroup wg.Add(1) go startTestWriter(s.DB, int64(0), 1<<15, &wg, nil, nil, done, t) // Check that we split 5 times in allotted time. util.SucceedsSoon(t, func() error { // Scan the txn records. rows, err := s.DB.Scan(keys.Meta2Prefix, keys.MetaMax, 0) if err != nil { return util.Errorf("failed to scan meta2 keys: %s", err) } if lr := len(rows); lr < 5 { return util.Errorf("expected >= 5 scans; got %d", lr) } return nil }) close(done) wg.Wait() // This write pressure test often causes splits while resolve // intents are in flight, causing them to fail with range key // mismatch errors. However, LocalSender should retry in these // cases. Check here via MVCC scan that there are no dangling write // intents. We do this using a SucceedsSoon construct to account // for timing of finishing the test writer and a possibly-ongoing // asynchronous split. util.SucceedsSoon(t, func() error { if _, _, err := engine.MVCCScan(context.Background(), s.Eng, keys.LocalMax, roachpb.KeyMax, 0, hlc.MaxTimestamp, true, nil); err != nil { return util.Errorf("failed to verify no dangling intents: %s", err) } return nil }) }
// TestStoreZoneUpdateAndRangeSplit verifies that modifying the zone // configuration changes range max bytes and Range.maybeSplit() takes // max bytes into account when deciding whether to enqueue a range for // splitting. It further verifies that the range is in fact split on // exceeding zone's RangeMaxBytes. func TestStoreZoneUpdateAndRangeSplit(t *testing.T) { defer leaktest.AfterTest(t) store, stopper := createTestStore(t) config.TestingSetupZoneConfigHook(stopper) defer stopper.Stop() maxBytes := int64(1 << 16) // Set max bytes. config.TestingSetZoneConfig(1000, &config.ZoneConfig{RangeMaxBytes: maxBytes}) // Trigger gossip callback. if err := store.Gossip().AddInfoProto(gossip.KeySystemConfig, &config.SystemConfig{}, 0); err != nil { t.Fatal(err) } // Wait for the range to be split along table boundaries. originalRange := store.LookupReplica(roachpb.RKeyMin, nil) var rng *storage.Replica if err := util.IsTrueWithin(func() bool { rng = store.LookupReplica(keys.MakeTablePrefix(1000), nil) return rng.Desc().RangeID != originalRange.Desc().RangeID }, 50*time.Millisecond); err != nil { t.Fatalf("failed to notice range max bytes update: %s", err) } // Check range's max bytes settings. if rng.GetMaxBytes() != maxBytes { t.Fatalf("range max bytes mismatch, got: %d, expected: %d", rng.GetMaxBytes(), maxBytes) } // Make sure the second range goes to the end. if !roachpb.RKeyMax.Equal(rng.Desc().EndKey) { t.Fatalf("second range has split: %+v", rng.Desc()) } // Look in the range after prefix we're writing to. fillRange(store, rng.Desc().RangeID, keys.MakeTablePrefix(1000), maxBytes, t) // Verify that the range is in fact split (give it a second for very slow test machines). var newRng *storage.Replica if err := util.IsTrueWithin(func() bool { newRng = store.LookupReplica(keys.MakeTablePrefix(2000), nil) return newRng.Desc().RangeID != rng.Desc().RangeID }, time.Second); err != nil { t.Errorf("expected range to split within 1s") } // Make sure the new range goes to the end. if !roachpb.RKeyMax.Equal(newRng.Desc().EndKey) { t.Fatalf("second range has split: %+v", rng.Desc()) } }
// TestStoreZoneUpdateAndRangeSplit verifies that modifying the zone // configuration changes range max bytes and Range.maybeSplit() takes // max bytes into account when deciding whether to enqueue a range for // splitting. It further verifies that the range is in fact split on // exceeding zone's RangeMaxBytes. func TestStoreZoneUpdateAndRangeSplit(t *testing.T) { defer leaktest.AfterTest(t)() store, stopper, _ := createTestStore(t) config.TestingSetupZoneConfigHook(stopper) defer stopper.Stop() maxBytes := int64(1 << 16) // Set max bytes. descID := uint32(keys.MaxReservedDescID + 1) config.TestingSetZoneConfig(descID, &config.ZoneConfig{RangeMaxBytes: maxBytes}) // Trigger gossip callback. if err := store.Gossip().AddInfoProto(gossip.KeySystemConfig, &config.SystemConfig{}, 0); err != nil { t.Fatal(err) } tableBoundary := keys.MakeTablePrefix(descID) { var rng *storage.Replica // Wait for the range to be split along table boundaries. expectedRSpan := roachpb.RSpan{Key: roachpb.RKey(tableBoundary), EndKey: roachpb.RKeyMax} util.SucceedsSoon(t, func() error { rng = store.LookupReplica(tableBoundary, nil) if actualRSpan := rng.Desc().RSpan(); !actualRSpan.Equal(expectedRSpan) { return util.Errorf("expected range %s to span %s", rng, expectedRSpan) } return nil }) // Check range's max bytes settings. if actualMaxBytes := rng.GetMaxBytes(); actualMaxBytes != maxBytes { t.Fatalf("range %s max bytes mismatch, got: %d, expected: %d", rng, actualMaxBytes, maxBytes) } // Look in the range after prefix we're writing to. fillRange(store, rng.RangeID, tableBoundary, maxBytes, t) } // Verify that the range is in fact split. util.SucceedsSoon(t, func() error { rng := store.LookupReplica(keys.MakeTablePrefix(descID+1), nil) rngDesc := rng.Desc() rngStart, rngEnd := rngDesc.StartKey, rngDesc.EndKey if rngStart.Equal(tableBoundary) || !rngEnd.Equal(roachpb.RKeyMax) { return util.Errorf("range %s has not yet split", rng) } return nil }) }
// TestRangeSplitsWithWritePressure sets the zone config max bytes for // a range to 256K and writes data until there are five ranges. func TestRangeSplitsWithWritePressure(t *testing.T) { defer leaktest.AfterTest(t) // Override default zone config. previousMaxBytes := config.DefaultZoneConfig.RangeMaxBytes config.DefaultZoneConfig.RangeMaxBytes = 1 << 18 defer func() { config.DefaultZoneConfig.RangeMaxBytes = previousMaxBytes }() s := createTestDB(t) // This is purely to silence log spam. config.TestingSetupZoneConfigHook(s.Stopper) defer s.Stop() setTestRetryOptions() // Start test writer write about a 32K/key so there aren't too many writes necessary to split 64K range. done := make(chan struct{}) var wg sync.WaitGroup wg.Add(1) go startTestWriter(s.DB, int64(0), 1<<15, &wg, nil, nil, done, t) // Check that we split 5 times in allotted time. if err := util.IsTrueWithin(func() bool { // Scan the txn records. rows, err := s.DB.Scan(keys.Meta2Prefix, keys.MetaMax, 0) if err != nil { t.Fatalf("failed to scan meta2 keys: %s", err) } return len(rows) >= 5 }, 6*time.Second); err != nil { t.Errorf("failed to split 5 times: %s", err) } close(done) wg.Wait() // This write pressure test often causes splits while resolve // intents are in flight, causing them to fail with range key // mismatch errors. However, LocalSender should retry in these // cases. Check here via MVCC scan that there are no dangling write // intents. We do this using an IsTrueWithin construct to account // for timing of finishing the test writer and a possibly-ongoing // asynchronous split. if err := util.IsTrueWithin(func() bool { if _, _, err := engine.MVCCScan(s.Eng, keys.LocalMax, roachpb.KeyMax, 0, roachpb.MaxTimestamp, true, nil); err != nil { log.Infof("mvcc scan should be clean: %s", err) return false } return true }, 500*time.Millisecond); err != nil { t.Error("failed to verify no dangling intents within 500ms") } }
func gossipForTest(t *testing.T) (*gossip.Gossip, *stop.Stopper) { stopper := stop.NewStopper() // Setup fake zone config handler. config.TestingSetupZoneConfigHook(stopper) rpcContext := rpc.NewContext(&base.Context{}, hlc.NewClock(hlc.UnixNano), stopper) g := gossip.New(rpcContext, gossip.TestInterval, gossip.TestBootstrap) // Put an empty system config into gossip. if err := g.AddInfoProto(gossip.KeySystemConfig, &config.SystemConfig{}, 0); err != nil { t.Fatal(err) } return g, stopper }