// NewStorePool creates a StorePool and registers the store updating callback // with gossip. func NewStorePool( ambient log.AmbientContext, g *gossip.Gossip, clock *hlc.Clock, rpcContext *rpc.Context, timeUntilStoreDead time.Duration, stopper *stop.Stopper, deterministic bool, ) *StorePool { sp := &StorePool{ AmbientContext: ambient, clock: clock, timeUntilStoreDead: timeUntilStoreDead, rpcContext: rpcContext, failedReservationsTimeout: envutil.EnvOrDefaultDuration("COCKROACH_FAILED_RESERVATION_TIMEOUT", defaultFailedReservationsTimeout), declinedReservationsTimeout: envutil.EnvOrDefaultDuration("COCKROACH_DECLINED_RESERVATION_TIMEOUT", defaultDeclinedReservationsTimeout), resolver: GossipAddressResolver(g), deterministic: deterministic, } sp.mu.storeDetails = make(map[roachpb.StoreID]*storeDetail) heap.Init(&sp.mu.queue) sp.mu.nodeLocalities = make(map[roachpb.NodeID]roachpb.Locality) storeRegex := gossip.MakePrefixPattern(gossip.KeyStorePrefix) g.RegisterCallback(storeRegex, sp.storeGossipUpdate) deadReplicasRegex := gossip.MakePrefixPattern(gossip.KeyDeadReplicasPrefix) g.RegisterCallback(deadReplicasRegex, sp.deadReplicasGossipUpdate) sp.start(stopper) return sp }
func initFakeTime() { if offset := envutil.EnvOrDefaultDuration("COCKROACH_SIMULATED_OFFSET", 0); offset == 0 { nowFunc = time.Now } else { nowFunc = func() time.Time { return time.Now().Add(offset) } } }
func (r *RocksDB) open() error { var ver storageVersion if len(r.dir) != 0 { log.Infof(context.TODO(), "opening rocksdb instance at %q", r.dir) // Check the version number. var err error if ver, err = getVersion(r.dir); err != nil { return err } if ver < versionMinimum || ver > versionCurrent { // Instead of an error, we should call a migration if possible when // one is needed immediately following the DBOpen call. return fmt.Errorf("incompatible rocksdb data version, current:%d, on disk:%d, minimum:%d", versionCurrent, ver, versionMinimum) } } else { if log.V(2) { log.Infof(context.TODO(), "opening in memory rocksdb instance") } // In memory dbs are always current. ver = versionCurrent } blockSize := envutil.EnvOrDefaultBytes("COCKROACH_ROCKSDB_BLOCK_SIZE", defaultBlockSize) walTTL := envutil.EnvOrDefaultDuration("COCKROACH_ROCKSDB_WAL_TTL", 0).Seconds() status := C.DBOpen(&r.rdb, goToCSlice([]byte(r.dir)), C.DBOptions{ cache: r.cache.cache, block_size: C.uint64_t(blockSize), wal_ttl_seconds: C.uint64_t(walTTL), allow_os_buffer: C.bool(true), logging_enabled: C.bool(log.V(3)), num_cpu: C.int(runtime.NumCPU()), max_open_files: C.int(r.maxOpenFiles), }) if err := statusToError(status); err != nil { return errors.Errorf("could not open rocksdb instance: %s", err) } // Update or add the version file if needed. if ver < versionCurrent { if err := writeVersionFile(r.dir); err != nil { return err } } // Start a goroutine that will finish when the underlying handle // is deallocated. This is used to check a leak in tests. go func() { <-r.deallocated }() return nil }
// readEnvironmentVariables populates all context values that are environment // variable based. Note that this only happens when initializing a node and not // when NewContext is called. func (cfg *Config) readEnvironmentVariables() { // cockroach-linearizable cfg.Linearizable = envutil.EnvOrDefaultBool("COCKROACH_LINEARIZABLE", cfg.Linearizable) cfg.ConsistencyCheckPanicOnFailure = envutil.EnvOrDefaultBool("COCKROACH_CONSISTENCY_CHECK_PANIC_ON_FAILURE", cfg.ConsistencyCheckPanicOnFailure) cfg.MaxOffset = envutil.EnvOrDefaultDuration("COCKROACH_MAX_OFFSET", cfg.MaxOffset) cfg.MetricsSampleInterval = envutil.EnvOrDefaultDuration("COCKROACH_METRICS_SAMPLE_INTERVAL", cfg.MetricsSampleInterval) cfg.ScanInterval = envutil.EnvOrDefaultDuration("COCKROACH_SCAN_INTERVAL", cfg.ScanInterval) cfg.ScanMaxIdleTime = envutil.EnvOrDefaultDuration("COCKROACH_SCAN_MAX_IDLE_TIME", cfg.ScanMaxIdleTime) cfg.TimeUntilStoreDead = envutil.EnvOrDefaultDuration("COCKROACH_TIME_UNTIL_STORE_DEAD", cfg.TimeUntilStoreDead) cfg.ConsistencyCheckInterval = envutil.EnvOrDefaultDuration("COCKROACH_CONSISTENCY_CHECK_INTERVAL", cfg.ConsistencyCheckInterval) }
// startGossip loops on a periodic ticker to gossip node-related // information. Starts a goroutine to loop until the node is closed. func (n *Node) startGossip(stopper *stop.Stopper) { stopper.RunWorker(func() { ctx := n.AnnotateCtx(context.Background()) // This should always return immediately and acts as a sanity check that we // don't try to gossip before we're connected. select { case <-n.storeCfg.Gossip.Connected: default: panic(fmt.Sprintf("%s: not connected to gossip", n)) } // Verify we've already gossiped our node descriptor. if _, err := n.storeCfg.Gossip.GetNodeDescriptor(n.Descriptor.NodeID); err != nil { panic(err) } gossipStoresInterval := envutil.EnvOrDefaultDuration("COCKROACH_GOSSIP_STORES_INTERVAL", gossip.DefaultGossipStoresInterval) statusTicker := time.NewTicker(gossipStatusInterval) storesTicker := time.NewTicker(gossipStoresInterval) nodeTicker := time.NewTicker(gossipNodeDescriptorInterval) defer storesTicker.Stop() defer nodeTicker.Stop() n.gossipStores(ctx) // one-off run before going to sleep for { select { case <-statusTicker.C: n.storeCfg.Gossip.LogStatus() case <-storesTicker.C: n.gossipStores(ctx) case <-nodeTicker.C: if err := n.storeCfg.Gossip.SetNodeDescriptor(&n.Descriptor); err != nil { log.Warningf(ctx, "couldn't gossip descriptor for node %d: %s", n.Descriptor.NodeID, err) } case <-stopper.ShouldStop(): return } } }) }
) // Gossip metrics counter names. var ( MetaConnectionsIncomingGauge = metric.Metadata{Name: "gossip.connections.incoming"} MetaConnectionsOutgoingGauge = metric.Metadata{Name: "gossip.connections.outgoing"} MetaConnectionsRefusedRates = metric.Metadata{Name: "gossip.connections.refused"} MetaInfosSentRates = metric.Metadata{Name: "gossip.infos.sent"} MetaInfosReceivedRates = metric.Metadata{Name: "gossip.infos.received"} MetaBytesSentRates = metric.Metadata{Name: "gossip.bytes.sent"} MetaBytesReceivedRates = metric.Metadata{Name: "gossip.bytes.received"} ) var ( // GossipStoresInterval is the interval for gossipping storage-related info. GossipStoresInterval = envutil.EnvOrDefaultDuration("COCKROACH_GOSSIP_STORES_INTERVAL", defaultGossipStoresInterval) ) // Storage is an interface which allows the gossip instance // to read and write bootstrapping data to persistent storage // between instantiations. type Storage interface { // ReadBootstrapInfo fetches the bootstrap data from the persistent // store into the provided bootstrap protobuf. Returns nil or an // error on failure. ReadBootstrapInfo(*BootstrapInfo) error // WriteBootstrapInfo stores the provided bootstrap data to the // persistent store. Returns nil or an error on failure. WriteBootstrapInfo(*BootstrapInfo) error }
"github.com/cockroachdb/cockroach/pkg/util/log" "github.com/cockroachdb/cockroach/pkg/util/retry" "github.com/cockroachdb/cockroach/pkg/util/timeutil" "github.com/cockroachdb/cockroach/pkg/util/tracing" basictracer "github.com/opentracing/basictracer-go" opentracing "github.com/opentracing/opentracing-go" "github.com/pkg/errors" ) // COCKROACH_TRACE_SQL=duration can be used to log SQL transactions that take // longer than duration to complete. For example, COCKROACH_TRACE_SQL=1s will // log the trace for any transaction that takes 1s or longer. To log traces for // all transactions use COCKROACH_TRACE_SQL=1ns. Note that any positive // duration will enable tracing and will slow down all execution because traces // are gathered for all transactions even if they are not output. var traceSQLDuration = envutil.EnvOrDefaultDuration("COCKROACH_TRACE_SQL", 0) var traceSQL = traceSQLDuration > 0 // COCKROACH_TRACE_7881 can be used to trace all SQL transactions, in the hope // that we'll catch #7881 and dump the current trace for debugging. var traceSQLFor7881 = envutil.EnvOrDefaultBool("COCKROACH_TRACE_7881", false) // span baggage key used for marking a span const keyFor7881Sample = "found#7881" // Session contains the state of a SQL client connection. // Create instances using NewSession(). type Session struct { Database string // SearchPath is a list of databases that will be searched for a table name // before the database. Currently, this is used only for SELECTs.