Example #1
0
// createTestRange creates a range using a blocking engine. Returns
// the range clock's manual unix nanos time and the range.
func createTestRangeWithClock(t *testing.T) (*Range, *hlc.ManualClock, *blockingEngine) {
	manual := hlc.ManualClock(0)
	clock := hlc.NewHLClock(manual.UnixNano)
	engine := newBlockingEngine()
	rng := NewRange(RangeMetadata{}, clock, engine, nil, nil)
	rng.Start()
	return rng, &manual, engine
}
Example #2
0
// createTestRange creates a new range initialized to the full extent
// of the keyspace. The gossip instance is also returned for testing.
func createTestRange(engine engine.Engine, t *testing.T) (*Range, *gossip.Gossip) {
	rm := RangeMetadata{
		RangeID:         0,
		RangeDescriptor: testRangeDescriptor,
	}
	g := gossip.New()
	clock := hlc.NewHLClock(hlc.UnixNano)
	r := NewRange(rm, clock, engine, nil, g)
	r.Start()
	return r, g
}
Example #3
0
// createTestStore creates a test store using an in-memory
// engine. Returns the store clock's manual unix nanos time and the
// store. A single range from key "a" to key "z" is setup in the store
// with a default replica descriptor (i.e. StoreID = 0, RangeID = 1,
// etc.). The caller is responsible for closing the store on exit.
func createTestStore(t *testing.T) (*Store, *hlc.ManualClock) {
	manual := hlc.ManualClock(0)
	clock := hlc.NewHLClock(manual.UnixNano)
	engine := NewInMem(Attributes{}, 1<<20)
	store := NewStore(clock, engine, nil)
	replica := Replica{RangeID: 1}
	_, err := store.CreateRange(Key("a"), Key("z"), []Replica{replica})
	if err != nil {
		t.Fatal(err)
	}
	return store, &manual
}
// TestReadTimestampCacheLayeredIntervals verifies the maximum
// timestamp is chosen if previous reads have ranges which are
// layered over each other.
func TestReadTimestampCacheLayeredIntervals(t *testing.T) {
	manual := hlc.ManualClock(0)
	clock := hlc.NewHLClock(manual.UnixNano)
	clock.SetMaxDrift(maxClockSkew)
	rtc := NewReadTimestampCache(clock)
	manual = hlc.ManualClock(maxClockSkew.Nanoseconds() + 1)

	adTS := clock.Now()
	rtc.Add(engine.Key("a"), engine.Key("d"), adTS)

	beTS := clock.Now()
	rtc.Add(engine.Key("b"), engine.Key("e"), beTS)

	cTS := clock.Now()
	rtc.Add(engine.Key("c"), nil, cTS)

	// Try different sub ranges.
	if rtc.GetMax(engine.Key("a"), nil) != adTS {
		t.Error("expected \"a\" to have adTS timestamp")
	}
	if rtc.GetMax(engine.Key("b"), nil) != beTS {
		t.Error("expected \"b\" to have beTS timestamp")
	}
	if rtc.GetMax(engine.Key("c"), nil) != cTS {
		t.Error("expected \"b\" to have cTS timestamp")
	}
	if rtc.GetMax(engine.Key("d"), nil) != beTS {
		t.Error("expected \"d\" to have beTS timestamp")
	}
	if rtc.GetMax(engine.Key("a"), engine.Key("b")) != adTS {
		t.Error("expected \"a\"-\"b\" to have adTS timestamp")
	}
	if rtc.GetMax(engine.Key("a"), engine.Key("c")) != beTS {
		t.Error("expected \"a\"-\"c\" to have beTS timestamp")
	}
	if rtc.GetMax(engine.Key("a"), engine.Key("d")) != cTS {
		t.Error("expected \"a\"-\"d\" to have cTS timestamp")
	}
	if rtc.GetMax(engine.Key("b"), engine.Key("d")) != cTS {
		t.Error("expected \"b\"-\"d\" to have cTS timestamp")
	}
	if rtc.GetMax(engine.Key("c"), engine.Key("d")) != cTS {
		t.Error("expected \"c\"-\"d\" to have cTS timestamp")
	}
	if rtc.GetMax(engine.Key("c0"), engine.Key("d")) != beTS {
		t.Error("expected \"c0\"-\"d\" to have beTS timestamp")
	}
}
// TestReadTimestampCacheEviction verifies the eviction of
// read timestamp cache entries after minCacheWindow interval.
func TestReadTimestampCacheEviction(t *testing.T) {
	manual := hlc.ManualClock(0)
	clock := hlc.NewHLClock(manual.UnixNano)
	clock.SetMaxDrift(maxClockSkew)
	rtc := NewReadTimestampCache(clock)

	// Increment time to the maxClockSkew high water mark + 1.
	manual = hlc.ManualClock(maxClockSkew.Nanoseconds() + 1)
	aTS := clock.Now()
	rtc.Add(engine.Key("a"), nil, aTS)

	// Increment time by the minCacheWindow and add another key.
	manual = hlc.ManualClock(int64(manual) + minCacheWindow.Nanoseconds())
	rtc.Add(engine.Key("b"), nil, clock.Now())

	// Verify looking up key "c" returns the new high water mark ("a"'s timestamp).
	if rtc.GetMax(engine.Key("c"), nil) != aTS {
		t.Error("expected high water mark %+v, got %+v", aTS, rtc.GetMax(engine.Key("c"), nil))
	}
}
Example #6
0
// TestStoreInitAndBootstrap verifies store initialization and
// bootstrap.
func TestStoreInitAndBootstrap(t *testing.T) {
	manual := hlc.ManualClock(0)
	clock := hlc.NewHLClock(manual.UnixNano)
	engine := NewInMem(Attributes{}, 1<<20)
	store := NewStore(clock, engine, nil)
	defer store.Close()

	// Can't init as haven't bootstrapped.
	if err := store.Init(); err == nil {
		t.Error("expected failure init'ing un-bootstrapped store")
	}

	// Bootstrap with a fake ident.
	if err := store.Bootstrap(testIdent); err != nil {
		t.Errorf("error bootstrapping store: %v", err)
	}

	// Try to get 1st range--non-existent.
	if _, err := store.GetRange(1); err == nil {
		t.Error("expected error fetching non-existent range")
	}

	// Create range and fetch.
	if _, err := store.CreateRange(KeyMin, KeyMax, []Replica{}); err != nil {
		t.Errorf("failure to create first range: %v", err)
	}
	if _, err := store.GetRange(1); err != nil {
		t.Errorf("failure fetching 1st range: %v", err)
	}

	// Now, attempt to initialize a store with a now-bootstrapped engine.
	store = NewStore(clock, engine, nil)
	if err := store.Init(); err != nil {
		t.Errorf("failure initializing bootstrapped store: %v", err)
	}
	// 1st range should be available.
	if _, err := store.GetRange(1); err != nil {
		t.Errorf("failure fetching 1st range: %v", err)
	}
}
func TestReadTimestampCacheClear(t *testing.T) {
	manual := hlc.ManualClock(0)
	clock := hlc.NewHLClock(manual.UnixNano)
	clock.SetMaxDrift(maxClockSkew)
	rtc := NewReadTimestampCache(clock)

	// Increment time to the maxClockSkew high water mark + 1.
	manual = hlc.ManualClock(maxClockSkew.Nanoseconds() + 1)
	ts := clock.Now()
	rtc.Add(engine.Key("a"), nil, ts)

	// Clear the cache, which will reset the high water mark to
	// the current time + maxClockSkew.
	rtc.Clear()

	// Fetching any keys should give current time + maxClockSkew
	expTS := clock.Timestamp()
	expTS.WallTime += maxClockSkew.Nanoseconds()
	if rtc.GetMax(engine.Key("a"), nil) != expTS {
		t.Error("expected \"a\" to have cleared timestamp")
	}
}
Example #8
0
// TestBootstrapOfNonEmptyStore verifies bootstrap failure if engine
// is not empty.
func TestBootstrapOfNonEmptyStore(t *testing.T) {
	engine := NewInMem(Attributes{}, 1<<20)

	// Put some random garbage into the engine.
	if err := engine.put(Key("foo"), []byte("bar")); err != nil {
		t.Errorf("failure putting key foo into engine: %v", err)
	}
	manual := hlc.ManualClock(0)
	clock := hlc.NewHLClock(manual.UnixNano)
	store := NewStore(clock, engine, nil)
	defer store.Close()

	// Can't init as haven't bootstrapped.
	if err := store.Init(); err == nil {
		t.Error("expected failure init'ing un-bootstrapped store")
	}

	// Bootstrap should fail on non-empty engine.
	if err := store.Bootstrap(testIdent); err == nil {
		t.Error("expected bootstrap error on non-empty store")
	}
}
Example #9
0
// createTestNode creates an rpc server using the specified address,
// gossip instance, KV database and a node using the specified slice
// of engines. The server and node are returned. If gossipBS is not
// nil, the gossip bootstrap address is set to gossipBS.
func createTestNode(addr net.Addr, engines []engine.Engine, gossipBS net.Addr, t *testing.T) (
	*rpc.Server, *Node) {
	rpcServer := rpc.NewServer(addr)
	if err := rpcServer.Start(); err != nil {
		t.Fatal(err)
	}
	g := gossip.New()
	if gossipBS != nil {
		// Handle possibility of a :0 port specification.
		if gossipBS == addr {
			gossipBS = rpcServer.Addr()
		}
		g.SetBootstrap([]net.Addr{gossipBS})
		g.Start(rpcServer)
	}
	db := kv.NewDB(g)
	node := NewNode(db, g)
	clock := hlc.NewHLClock(hlc.UnixNano)
	if err := node.start(rpcServer, clock, engines, nil); err != nil {
		t.Fatal(err)
	}
	return rpcServer, node
}
Example #10
0
// runStart starts the cockroach node using -stores as the list of
// storage devices ("stores") on this machine and -gossip as the list
// of "well-known" hosts used to join this node to the cockroach
// cluster via the gossip network.
func runStart(cmd *commander.Command, args []string) {
	glog.Info("Starting cockroach cluster")
	s, err := newServer()
	if err != nil {
		glog.Errorf("Failed to start Cockroach server: %v", err)
		return
	}

	// Create a new hybrid-logical clock using the internal clock.
	clock := hlc.NewHLClock(hlc.UnixNano)
	clock.SetMaxDrift(*maxDrift)

	// Init engines from -stores.
	engines, err := initEngines(*stores)
	if err != nil {
		glog.Errorf("Failed to initialize engines from -stores=%q: %v", *stores, err)
		return
	}
	if len(engines) == 0 {
		glog.Errorf("No valid engines specified after initializing from -stores=%q", *stores)
		return
	}

	err = s.start(clock, engines, false)
	defer s.stop()
	if err != nil {
		glog.Errorf("Cockroach server exited with error: %v", err)
		return
	}

	c := make(chan os.Signal, 1)
	signal.Notify(c, os.Interrupt, os.Kill)

	// Block until one of the signals above is received.
	<-c
}
Example #11
0
func startServer() *server {
	serverTestOnce.Do(func() {
		s, err := newServer()
		if err != nil {
			glog.Fatal(err)
		}
		engines := []storage.Engine{storage.NewInMem(storage.Attributes{}, 1<<20)}
		if _, err := BootstrapCluster("cluster-1", engines[0]); err != nil {
			glog.Fatal(err)
		}
		clock := hlc.NewHLClock(hlc.UnixNano)
		err = s.start(clock, engines, true) // TODO(spencer): should shutdown server.
		if err != nil {
			glog.Fatalf("Could not start server: %s", err)
		}

		// Update the configuration variables to reflect the actual
		// sockets bound during this test.
		*httpAddr = (*s.httpListener).Addr().String()
		*rpcAddr = s.rpc.Addr().String()
		glog.Infof("Test server listening on http: %s, rpc: %s", *httpAddr, *rpcAddr)
	})
	return s
}
Example #12
0
// BootstrapCluster bootstraps a store using the provided engine and
// cluster ID. The bootstrapped store contains a single range spanning
// all keys. Initial range lookup metadata is populated for the range.
//
// Returns a direct-access kv.LocalDB for unittest purposes only.
func BootstrapCluster(clusterID string, eng engine.Engine) (
	*kv.LocalDB, error) {
	sIdent := storage.StoreIdent{
		ClusterID: clusterID,
		NodeID:    1,
		StoreID:   1,
	}
	clock := hlc.NewHLClock(hlc.UnixNano)
	now := clock.Now()
	s := storage.NewStore(clock, eng, nil)

	// Verify the store isn't already part of a cluster.
	if s.Ident.ClusterID != "" {
		return nil, util.Errorf("storage engine already belongs to a cluster (%s)", s.Ident.ClusterID)
	}

	// Bootstrap store to persist the store ident.
	if err := s.Bootstrap(sIdent); err != nil {
		return nil, err
	}

	if err := s.Init(); err != nil {
		return nil, err
	}

	// Create first range.
	replica := storage.Replica{
		NodeID:  1,
		StoreID: 1,
		RangeID: 1,
		Attrs:   engine.Attributes{},
	}
	rng, err := s.CreateRange(engine.KeyMin, engine.KeyMax, []storage.Replica{replica})
	if err != nil {
		return nil, err
	}
	if rng.Meta.RangeID != 1 {
		return nil, util.Errorf("expected range id of 1, got %d", rng.Meta.RangeID)
	}

	// Create a local DB to directly modify the new range.
	localDB := kv.NewLocalDB()
	localDB.AddStore(s)

	// Initialize range addressing records and default administrative configs.
	desc := storage.RangeDescriptor{
		StartKey: engine.KeyMin,
		Replicas: []storage.Replica{replica},
	}
	if err := kv.BootstrapRangeDescriptor(localDB, desc, now); err != nil {
		return nil, err
	}

	// Write default configs to local DB.
	if err := kv.BootstrapConfigs(localDB, now); err != nil {
		return nil, err
	}

	// Initialize node and store ids after the fact to account
	// for use of node ID = 1 and store ID = 1.
	if nodeID, err := allocateNodeID(localDB); nodeID != sIdent.NodeID || err != nil {
		return nil, util.Errorf("expected to intialize node id allocator to %d, got %d: %v",
			sIdent.NodeID, nodeID, err)
	}
	if storeID, err := allocateStoreIDs(sIdent.NodeID, 1, localDB); storeID != sIdent.StoreID || err != nil {
		return nil, util.Errorf("expected to intialize store id allocator to %d, got %d: %v",
			sIdent.StoreID, storeID, err)
	}

	return localDB, nil
}
func TestReadTimestampCache(t *testing.T) {
	manual := hlc.ManualClock(0)
	clock := hlc.NewHLClock(manual.UnixNano)
	clock.SetMaxDrift(maxClockSkew)
	rtc := NewReadTimestampCache(clock)

	// First simulate a read of just "a" at time 0.
	rtc.Add(engine.Key("a"), nil, clock.Now())
	// Verify GetMax returns the highWater mark which is maxClockSkew.
	if rtc.GetMax(engine.Key("a"), nil).WallTime != maxClockSkew.Nanoseconds() {
		t.Error("expected maxClockSkew for key \"a\"")
	}
	if rtc.GetMax(engine.Key("notincache"), nil).WallTime != maxClockSkew.Nanoseconds() {
		t.Error("expected maxClockSkew for key \"notincache\"")
	}

	// Advance the clock and verify same high water mark.
	manual = hlc.ManualClock(maxClockSkew.Nanoseconds() + 1)
	if rtc.GetMax(engine.Key("a"), nil).WallTime != maxClockSkew.Nanoseconds() {
		t.Error("expected maxClockSkew for key \"a\"")
	}
	if rtc.GetMax(engine.Key("notincache"), nil).WallTime != maxClockSkew.Nanoseconds() {
		t.Error("expected maxClockSkew for key \"notincache\"")
	}

	// Sim a read of "b"-"c" at time maxClockSkew + 1.
	ts := clock.Now()
	rtc.Add(engine.Key("b"), engine.Key("c"), ts)

	// Verify all permutations of direct and range access.
	if rtc.GetMax(engine.Key("b"), nil) != ts {
		t.Error("expected current time for key \"b\"; got %+v", rtc.GetMax(engine.Key("b"), nil))
	}
	if rtc.GetMax(engine.Key("bb"), nil) != ts {
		t.Error("expected current time for key \"bb\"")
	}
	if rtc.GetMax(engine.Key("c"), nil).WallTime != maxClockSkew.Nanoseconds() {
		t.Error("expected maxClockSkew for key \"c\"")
	}
	if rtc.GetMax(engine.Key("b"), engine.Key("c")) != ts {
		t.Error("expected current time for key \"b\"-\"c\"")
	}
	if rtc.GetMax(engine.Key("bb"), engine.Key("bz")) != ts {
		t.Error("expected current time for key \"bb\"-\"bz\"")
	}
	if rtc.GetMax(engine.Key("a"), engine.Key("b")).WallTime != maxClockSkew.Nanoseconds() {
		t.Error("expected maxClockSkew for key \"a\"-\"b\"")
	}
	if rtc.GetMax(engine.Key("a"), engine.Key("bb")) != ts {
		t.Error("expected current time for key \"a\"-\"bb\"")
	}
	if rtc.GetMax(engine.Key("a"), engine.Key("d")) != ts {
		t.Error("expected current time for key \"a\"-\"d\"")
	}
	if rtc.GetMax(engine.Key("bz"), engine.Key("c")) != ts {
		t.Error("expected current time for key \"bz\"-\"c\"")
	}
	if rtc.GetMax(engine.Key("bz"), engine.Key("d")) != ts {
		t.Error("expected current time for key \"bz\"-\"d\"")
	}
	if rtc.GetMax(engine.Key("c"), engine.Key("d")).WallTime != maxClockSkew.Nanoseconds() {
		t.Error("expected maxClockSkew for key \"c\"-\"d\"")
	}
}