// getDescriptorFromTargetList examines a TargetList and fetches the // appropriate descriptor. // TODO(marc): support multiple targets. func (p *planner) getDescriptorFromTargetList(targets parser.TargetList) (descriptorProto, error) { if targets.Databases != nil { if len(targets.Databases) == 0 { return nil, errNoDatabase } else if len(targets.Databases) != 1 { return nil, util.Errorf("TODO(marc): multiple targets not implemented") } descriptor, err := p.getDatabaseDesc(targets.Databases[0]) if err != nil { return nil, err } return descriptor, nil } if targets.Tables == nil { return nil, util.Errorf("no targets speciied") } if len(targets.Tables) == 0 { return nil, errNoTable } else if len(targets.Tables) != 1 { return nil, util.Errorf("TODO(marc): multiple targets not implemented") } descriptor, err := p.getTableDesc(targets.Tables[0]) if err != nil { return nil, err } return descriptor, nil }
// BootstrapCluster bootstraps a multiple stores using the provided engines and // cluster ID. The first bootstrapped store contains a single range spanning // all keys. Initial range lookup metadata is populated for the range. // // Returns a KV client for unittest purposes. Caller should close the returned // client. func BootstrapCluster(clusterID string, engines []engine.Engine, stopper *stop.Stopper) (*client.DB, error) { ctx := storage.StoreContext{} ctx.ScanInterval = 10 * time.Minute ctx.Clock = hlc.NewClock(hlc.UnixNano) // Create a KV DB with a local sender. lSender := kv.NewLocalSender() sender := kv.NewTxnCoordSender(lSender, ctx.Clock, false, nil, stopper) ctx.DB = client.NewDB(sender) ctx.Transport = multiraft.NewLocalRPCTransport(stopper) for i, eng := range engines { sIdent := roachpb.StoreIdent{ ClusterID: clusterID, NodeID: 1, StoreID: roachpb.StoreID(i + 1), } // The bootstrapping store will not connect to other nodes so its // StoreConfig doesn't really matter. s := storage.NewStore(ctx, eng, &roachpb.NodeDescriptor{NodeID: 1}) // Verify the store isn't already part of a cluster. if len(s.Ident.ClusterID) > 0 { 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, stopper); err != nil { return nil, err } // Create first range, writing directly to engine. Note this does // not create the range, just its data. Only do this if this is the // first store. if i == 0 { // TODO(marc): this is better than having storage/ import sql, but still // not great. Find a better place to keep those. initialValues := sql.GetInitialSystemValues() if err := s.BootstrapRange(initialValues); err != nil { return nil, err } } if err := s.Start(stopper); err != nil { return nil, err } lSender.AddStore(s) // Initialize node and store ids. Only initialize the node once. if i == 0 { if nodeID, err := allocateNodeID(ctx.DB); nodeID != sIdent.NodeID || err != nil { return nil, util.Errorf("expected to initialize node id allocator to %d, got %d: %s", sIdent.NodeID, nodeID, err) } } if storeID, err := allocateStoreIDs(sIdent.NodeID, 1, ctx.DB); storeID != sIdent.StoreID || err != nil { return nil, util.Errorf("expected to initialize store id allocator to %d, got %d: %s", sIdent.StoreID, storeID, err) } } return ctx.DB, nil }
func parseOptions(data []byte) (sql.SessionArgs, error) { args := sql.SessionArgs{} buf := readBuffer{msg: data} for { key, err := buf.getString() if err != nil { return sql.SessionArgs{}, util.Errorf("error reading option key: %s", err) } if len(key) == 0 { break } value, err := buf.getString() if err != nil { return sql.SessionArgs{}, util.Errorf("error reading option value: %s", err) } switch key { case "database": args.Database = value case "user": args.User = value default: if log.V(1) { log.Warningf("unrecognized configuration parameter %q", key) } } } return args, nil }
// GetServerTLSConfig returns the context server TLS config, initializing it if needed. // If Insecure is true, return a nil config, otherwise load a config based // on the Certs directory. Fails if Insecure=false and Certs="". func (ctx *Context) GetServerTLSConfig() (*tls.Config, error) { // Early out. if ctx.Insecure { return nil, nil } ctx.tlsConfigMu.Lock() defer ctx.tlsConfigMu.Unlock() if ctx.serverTLSConfig != nil { return ctx.serverTLSConfig, nil } if ctx.Certs == "" { return nil, util.Errorf("--insecure=false, but --certs is empty. We need a certs directory") } if log.V(1) { log.Infof("setting up TLS from certificates directory: %s", ctx.Certs) } cfg, err := security.LoadServerTLSConfig(ctx.Certs, ctx.User) if err != nil { return nil, util.Errorf("error setting up server TLS config: %s", err) } ctx.serverTLSConfig = cfg return ctx.serverTLSConfig, nil }
// verifyPermissions verifies that the requesting user (header.User) // has permission to read/write (capabilities depend on method // name). In the event that multiple permission configs apply to the // key range implicated by the command, the lowest common denominator // for permission. For example, if a scan crosses two permission // configs, both configs must allow read permissions or the entire // scan will fail. func (db *DistDB) verifyPermissions(method string, header *storage.RequestHeader) error { // Get permissions map from gossip. permMap, err := db.gossip.GetInfo(gossip.KeyConfigPermission) if err != nil { return err } if permMap == nil { return util.Errorf("perm configs not available; cannot execute %s", method) } // Visit PermConfig(s) which apply to the method's key range. // - For each, verify each PermConfig allows reads or writes as method requires. end := header.EndKey if end == nil { end = header.Key } return permMap.(storage.PrefixConfigMap).VisitPrefixes( header.Key, end, func(start, end storage.Key, config interface{}) error { perm := config.(*storage.PermConfig) if storage.NeedReadPerm(method) && !perm.CanRead(header.User) { return util.Errorf("user %q cannot read range %q-%q; permissions: %+v", header.User, string(start), string(end), perm) } if storage.NeedWritePerm(method) && !perm.CanWrite(header.User) { return util.Errorf("user %q cannot read range %q-%q; permissions: %+v", header.User, string(start), string(end), perm) } return nil }) }
// CopyFrom copies all the cached results from the originRangeID // response cache into this one. Note that the cache will not be // locked while copying is in progress. Failures decoding individual // cache entries return an error. The copy is done directly using the // engine instead of interpreting values through MVCC for efficiency. func (rc *ResponseCache) CopyFrom(e engine.Engine, originRangeID proto.RangeID) error { prefix := keys.ResponseCacheKey(originRangeID, nil) // response cache prefix start := engine.MVCCEncodeKey(prefix) end := engine.MVCCEncodeKey(prefix.PrefixEnd()) return e.Iterate(start, end, func(kv proto.RawKeyValue) (bool, error) { // Decode the key into a cmd, skipping on error. Otherwise, // write it to the corresponding key in the new cache. cmdID, err := rc.decodeResponseCacheKey(kv.Key) if err != nil { return false, util.Errorf("could not decode a response cache key %s: %s", proto.Key(kv.Key), err) } key := keys.ResponseCacheKey(rc.rangeID, &cmdID) encKey := engine.MVCCEncodeKey(key) // Decode the value, update the checksum and re-encode. meta := &engine.MVCCMetadata{} if err := gogoproto.Unmarshal(kv.Value, meta); err != nil { return false, util.Errorf("could not decode response cache value %s [% x]: %s", proto.Key(kv.Key), kv.Value, err) } meta.Value.Checksum = nil meta.Value.InitChecksum(key) _, _, err = engine.PutProto(e, encKey, meta) return false, err }) }
func copySeqCache(e engine.Engine, srcID, dstID roachpb.RangeID, keyMin, keyMax engine.MVCCKey) error { var scratch [64]byte return e.Iterate(keyMin, keyMax, func(kv engine.MVCCKeyValue) (bool, error) { // Decode the key into a cmd, skipping on error. Otherwise, // write it to the corresponding key in the new cache. id, epoch, seq, err := decodeSequenceCacheMVCCKey(kv.Key, scratch[:0]) if err != nil { return false, util.Errorf("could not decode a sequence cache key %s: %s", kv.Key, err) } key := keys.SequenceCacheKey(dstID, id, epoch, seq) encKey := engine.MakeMVCCMetadataKey(key) // Decode the value, update the checksum and re-encode. meta := &engine.MVCCMetadata{} if err := proto.Unmarshal(kv.Value, meta); err != nil { return false, util.Errorf("could not decode sequence cache value %s [% x]: %s", kv.Key, kv.Value, err) } value := meta.Value() value.ClearChecksum() value.InitChecksum(key) meta.RawBytes = value.RawBytes _, _, err = engine.PutProto(e, encKey, meta) return false, err }) }
// DecodeFloatAscending returns the remaining byte slice after decoding and the decoded // float64 from buf. func DecodeFloatAscending(buf []byte) ([]byte, float64, error) { if PeekType(buf) != Float { return buf, 0, util.Errorf("did not find marker") } switch buf[0] { case floatNaN, floatNaNDesc: return buf[1:], math.NaN(), nil case floatNeg: b, u, err := DecodeUint64Ascending(buf[1:]) if err != nil { return b, 0, err } u = ^u return b, math.Float64frombits(u), nil case floatZero: return buf[1:], 0, nil case floatPos: b, u, err := DecodeUint64Ascending(buf[1:]) if err != nil { return b, 0, err } return b, math.Float64frombits(u), nil default: return nil, 0, util.Errorf("unknown prefix of the encoded byte slice: %q", buf) } }
func (c *v3Conn) parseOptions(data []byte) error { buf := readBuffer{msg: data} for { key, err := buf.getString() if err != nil { return util.Errorf("error reading option key: %s", err) } if len(key) == 0 { return nil } value, err := buf.getString() if err != nil { return util.Errorf("error reading option value: %s", err) } switch key { case "database": c.opts.database = value case "user": c.opts.user = value default: if log.V(1) { log.Warningf("unrecognized configuration parameter %q", key) } } } }
// PeekLength returns the length of the encoded value at the start of b. Note: // if this function succeeds, it's not a guarantee that decoding the value will // succeed. func PeekLength(b []byte) (int, error) { if len(b) == 0 { return 0, util.Errorf("empty slice") } m := b[0] switch m { case encodedNull, encodedNullDesc, encodedNotNull, encodedNotNullDesc, floatNaN, floatNaNDesc, floatZero, decimalZero: return 1, nil case bytesMarker: return getBytesLength(b, ascendingEscapes) case bytesDescMarker: return getBytesLength(b, descendingEscapes) case timeMarker: return GetMultiVarintLen(b, 2) case durationBigNegMarker, durationMarker, durationBigPosMarker: return GetMultiVarintLen(b, 3) case floatNeg, floatPos: // the marker is followed by 8 bytes if len(b) < 9 { return 0, util.Errorf("slice too short for float (%d)", len(b)) } return 9, nil } if m >= IntMin && m <= IntMax { return getVarintLen(b) } if m >= decimalNaN && m <= decimalNaNDesc { return getDecimalLen(b) } return 0, util.Errorf("unknown tag %d", m) }
func (lt *localRPCTransport) getClient(id roachpb.StoreID) (*netrpc.Client, error) { lt.mu.Lock() defer lt.mu.Unlock() select { case <-lt.closed: return nil, util.Errorf("transport is closed") default: } client, ok := lt.clients[id] if ok { return client, nil } srvWithAddr, ok := lt.servers[id] if !ok { return nil, util.Errorf("unknown peer %v", id) } address := srvWithAddr.addr.String() // If this wasn't test code we wouldn't want to call Dial while holding the lock. conn, err := codec.TLSDialHTTP("tcp", address, base.NetworkTimeout, nil) if err != nil { return nil, err } client = netrpc.NewClientWithCodec(codec.NewClientCodec(conn)) lt.clients[id] = client return client, err }
func decodeBytesInternal(b []byte, r []byte, e escapes, expectMarker bool) ([]byte, []byte, error) { if expectMarker { if len(b) == 0 || b[0] != e.marker { return nil, nil, util.Errorf("did not find marker %#x in buffer %#x", e.marker, b) } b = b[1:] } for { i := bytes.IndexByte(b, e.escape) if i == -1 { return nil, nil, util.Errorf("did not find terminator %#x in buffer %#x", e.escape, b) } if i+1 >= len(b) { return nil, nil, util.Errorf("malformed escape in buffer %#x", b) } v := b[i+1] if v == e.escapedTerm { if r == nil { r = b[:i] } else { r = append(r, b[:i]...) } return b[i+2:], r, nil } if v != e.escaped00 { return nil, nil, util.Errorf("unknown escape sequence: %#x %#x", e.escape, v) } r = append(r, b[:i]...) r = append(r, e.escapedFF) b = b[i+2:] } }
// DecodeVarintAscending decodes a value encoded by EncodeVaringAscending. func DecodeVarintAscending(b []byte) ([]byte, int64, error) { if len(b) == 0 { return nil, 0, util.Errorf("insufficient bytes to decode uvarint value") } length := int(b[0]) - intZero if length < 0 { length = -length remB := b[1:] if len(remB) < length { return nil, 0, util.Errorf("insufficient bytes to decode uvarint value: %s", remB) } var v int64 // Use the ones-complement of each encoded byte in order to build // up a positive number, then take the ones-complement again to // arrive at our negative value. for _, t := range remB[:length] { v = (v << 8) | int64(^t) } return remB[length:], ^v, nil } remB, v, err := DecodeUvarintAscending(b) if err != nil { return remB, 0, err } if v > math.MaxInt64 { return nil, 0, util.Errorf("varint %d overflows int64", v) } return remB, int64(v), nil }
// TestReplicateRange verifies basic replication functionality by creating two stores // and a range, replicating the range to the second store, and reading its data there. func TestReplicateRange(t *testing.T) { defer leaktest.AfterTest(t) mtc := multiTestContext{} mtc.Start(t, 2) defer mtc.Stop() // Issue a command on the first node before replicating. incArgs, incResp := incrementArgs([]byte("a"), 5, 1, mtc.stores[0].StoreID()) if err := mtc.stores[0].ExecuteCmd(context.Background(), proto.Call{Args: incArgs, Reply: incResp}); err != nil { t.Fatal(err) } rng, err := mtc.stores[0].GetRange(1) if err != nil { t.Fatal(err) } if err := rng.ChangeReplicas(proto.ADD_REPLICA, proto.Replica{ NodeID: mtc.stores[1].Ident.NodeID, StoreID: mtc.stores[1].Ident.StoreID, }); err != nil { t.Fatal(err) } // Verify no intent remains on range descriptor key. key := keys.RangeDescriptorKey(rng.Desc().StartKey) desc := proto.RangeDescriptor{} if ok, err := engine.MVCCGetProto(mtc.stores[0].Engine(), key, mtc.stores[0].Clock().Now(), true, nil, &desc); !ok || err != nil { t.Fatalf("fetching range descriptor yielded %t, %s", ok, err) } // Verify that in time, no intents remain on meta addressing // keys, and that range descriptor on the meta records is correct. util.SucceedsWithin(t, 1*time.Second, func() error { meta2 := keys.RangeMetaKey(proto.KeyMax) meta1 := keys.RangeMetaKey(meta2) for _, key := range []proto.Key{meta2, meta1} { metaDesc := proto.RangeDescriptor{} if ok, err := engine.MVCCGetProto(mtc.stores[0].Engine(), key, mtc.stores[0].Clock().Now(), true, nil, &metaDesc); !ok || err != nil { return util.Errorf("failed to resolve %s", key) } if !reflect.DeepEqual(metaDesc, desc) { return util.Errorf("descs not equal: %+v != %+v", metaDesc, desc) } } return nil }) // Verify that the same data is available on the replica. util.SucceedsWithin(t, 1*time.Second, func() error { getArgs, getResp := getArgs([]byte("a"), 1, mtc.stores[1].StoreID()) getArgs.ReadConsistency = proto.INCONSISTENT if err := mtc.stores[1].ExecuteCmd(context.Background(), proto.Call{Args: getArgs, Reply: getResp}); err != nil { return util.Errorf("failed to read data") } if v := mustGetInteger(getResp.Value); v != 5 { return util.Errorf("failed to read correct data: %d", v) } return nil }) }
// getColumnSchema unpacks the struct field into name and cockroach- // specific schema directives via the struct field tag. func getColumnSchema(sf reflect.StructField) (*Column, error) { schemaType, err := getSchemaType(sf) if err != nil { return nil, err } c := &Column{ Name: sf.Name, Type: schemaType, } cr := sf.Tag.Get("roach") for i, spec := range strings.Split(cr, ",") { keyValueSplit := strings.SplitN(spec, "=", 2) if len(keyValueSplit) == 1 { keyValueSplit = append(keyValueSplit, "") } key, value := keyValueSplit[0], keyValueSplit[1] if i == 0 { if len(value) > 0 { return nil, util.Errorf("roach tag for field %s must begin with column key, a short (1-3) character designation related to column name: %s", c.Name, spec) } c.Key = key } else { if err := setColumnOption(c, key, value); err != nil { return nil, err } } } if c.Key == "" { return nil, util.Errorf("roach tag must include a column key") } return c, nil }
// initEngine parses the engine specification according to the // dataDirRE regexp and instantiates an engine of correct type. func initEngine(spec string) (storage.Engine, error) { // Error if regexp doesn't match. matches := dataDirRE.FindStringSubmatch(spec) if matches == nil || len(matches) != 3 { return nil, util.Errorf("invalid engine specification %q", spec) } var engine storage.Engine var err error if matches[1] == "mem" { size, err := strconv.ParseInt(matches[2], 10, 64) if err != nil { return nil, util.Errorf("unable to init in-memory storage %q", spec) } engine = storage.NewInMem(size) } else { var typ storage.DiskType switch matches[2] { case "hdd": typ = storage.HDD case "ssd": typ = storage.SSD default: return nil, util.Errorf("unhandled disk type %q", matches[1]) } engine, err = storage.NewRocksDB(typ, matches[2]) if err != nil { return nil, util.Errorf("unable to init rocksdb with data dir %q", matches[2]) } } return engine, nil }
// post posts the call using the HTTP client. The call's method is // appended to KVDBEndpoint and set as the URL path. The call's arguments // are protobuf-serialized and written as the POST body. The content // type is set to application/x-protobuf. // // On success, the response body is unmarshalled into call.Reply. func (s *HTTPSender) post(call *Call) (*http.Response, error) { // Marshal the args into a request body. body, err := gogoproto.Marshal(call.Args) if err != nil { return nil, err } url := fmt.Sprintf("%s://%s%s%s", KVDBScheme, s.server, KVDBEndpoint, call.Method) req, err := http.NewRequest("POST", url, bytes.NewReader(body)) if err != nil { return nil, util.Errorf("unable to create request: %s", err) } req.Header.Add("Content-Type", "application/x-protobuf") req.Header.Add("Accept", "application/x-protobuf") resp, err := s.client.Do(req) if resp == nil { return nil, &httpSendError{util.Errorf("http client was closed: %s", err)} } defer resp.Body.Close() if err != nil { return nil, &httpSendError{err} } b, err := ioutil.ReadAll(resp.Body) if err != nil { return nil, &httpSendError{err} } if resp.StatusCode != 200 { return resp, errors.New(resp.Status) } if err := gogoproto.Unmarshal(b, call.Reply); err != nil { log.Errorf("request completed, but unable to unmarshal response from server: %s; body=%q", err, b) return nil, &httpSendError{err} } return resp, nil }
// RunCreateNodeCert is the entry-point from the command-line interface // to generate node certs and keys: // - node.server.{crt,key}: server cert with list of dns/ip addresses // - node.client.{crt,key}: client cert with "node" as the Common Name. // We intentionally generate distinct keys for each cert. func RunCreateNodeCert(certsDir string, keySize int, hosts []string) error { if certsDir == "" { return util.Errorf("no certs directory specified, use --certs") } if len(hosts) == 0 { return util.Errorf("no hosts specified. Need at least one") } caCert, caKey, err := loadCACertAndKey(certsDir) if err != nil { return err } // Generate certificates and keys. serverCert, serverKey, err := GenerateServerCert(caCert, caKey, keySize, hosts) if err != nil { return util.Errorf("error creating node server certificate and key: %s", err) } clientCert, clientKey, err := GenerateClientCert(caCert, caKey, keySize, NodeUser) if err != nil { return util.Errorf("error creating node client certificate and key: %s", err) } // TODO(marc): we fail if files already exist. At this point, we're checking four // different files, and should really make this more atomic (or at least check for existence first). err = writeCertificateAndKey(certsDir, NodeUser+".server", serverCert, serverKey) if err != nil { return err } return writeCertificateAndKey(certsDir, NodeUser+".client", clientCert, clientKey) }
// getLeaseForGossip tries to obtain a leader lease. Only one of the replicas // should gossip; the bool returned indicates whether it's us. func (r *Range) getLeaseForGossip(ctx context.Context) (bool, error) { // If no Gossip available (some tests) or range too fresh, noop. if r.rm.Gossip() == nil || !r.isInitialized() { return false, util.Errorf("no gossip or range not initialized") } var hasLease bool var err error if !r.rm.Stopper().RunTask(func() { timestamp := r.rm.Clock().Now() // Check for or obtain the lease, if none active. err = r.redirectOnOrAcquireLeaderLease(tracer.FromCtx(ctx), timestamp) hasLease = err == nil if err != nil { switch e := err.(type) { // NotLeaderError means there is an active lease, leaseRejectedError // means we tried to get one but someone beat us to it. case *proto.NotLeaderError, *proto.LeaseRejectedError: err = nil default: // Any other error is worth being logged visibly. log.Warningc(ctx, "could not acquire lease for range gossip: %s", e) } } }) { err = util.Errorf("node is stopping") } return hasLease, err }
// initStores initializes the Stores map from ID to Store. Stores are // added to the local sender if already bootstrapped. A bootstrapped // Store has a valid ident with cluster, node and Store IDs set. If // the Store doesn't yet have a valid ident, it's added to the // bootstraps list for initialization once the cluster and node IDs // have been determined. func (n *Node) initStores(engines []engine.Engine, stopper *stop.Stopper) error { bootstraps := list.New() if len(engines) == 0 { return util.Errorf("no engines") } for _, e := range engines { s := storage.NewStore(n.ctx, e, &n.Descriptor) // Initialize each store in turn, handling un-bootstrapped errors by // adding the store to the bootstraps list. if err := s.Start(stopper); err != nil { if _, ok := err.(*storage.NotBootstrappedError); ok { log.Infof("store %s not bootstrapped", s) bootstraps.PushBack(s) continue } return util.Errorf("failed to start store: %s", err) } if s.Ident.ClusterID == "" || s.Ident.NodeID == 0 { return util.Errorf("unidentified store: %s", s) } capacity, err := s.Capacity() if err != nil { return util.Errorf("could not query store capacity: %s", err) } log.Infof("initialized store %s: %+v", s, capacity) n.stores.AddStore(s) } // Verify all initialized stores agree on cluster and node IDs. if err := n.validateStores(); err != nil { return err } // Set the stores map as the gossip persistent storage, so that // gossip can bootstrap using the most recently persisted set of // node addresses. if err := n.ctx.Gossip.SetStorage(n.stores); err != nil { return fmt.Errorf("failed to initialize the gossip interface: %s", err) } // Connect gossip before starting bootstrap. For new nodes, connecting // to the gossip network is necessary to get the cluster ID. n.connectGossip() // If no NodeID has been assigned yet, allocate a new node ID by // supplying 0 to initNodeID. if n.Descriptor.NodeID == 0 { n.initNodeID(0) } // Bootstrap any uninitialized stores asynchronously. if bootstraps.Len() > 0 { stopper.RunAsyncTask(func() { n.bootstrapStores(bootstraps, stopper) }) } return nil }
// addInfo adds or updates an info in the infos map. // // Returns nil if info was added; error otherwise. func (is *infoStore) addInfo(key string, i *Info) error { if i.NodeID == 0 { panic("gossip info's NodeID is 0") } // Only replace an existing info if new timestamp is greater, or if // timestamps are equal, but new hops is smaller. if existingInfo, ok := is.Infos[key]; ok { iNanos := i.Value.Timestamp.WallTime existingNanos := existingInfo.Value.Timestamp.WallTime if iNanos < existingNanos || (iNanos == existingNanos && i.Hops >= existingInfo.Hops) { return util.Errorf("info %+v older than current info %+v", i, existingInfo) } } if i.OrigStamp == 0 { i.Value.InitChecksum([]byte(key)) i.OrigStamp = monotonicUnixNano() if hws := is.highWaterStamps[int32(i.NodeID)]; hws >= i.OrigStamp { panic(util.Errorf("high water stamp %d >= %d", hws, i.OrigStamp)) } } // Update info map. is.Infos[key] = i // Update the high water timestamps. if i.NodeID != 0 { if is.highWaterStamps[int32(i.NodeID)] < i.OrigStamp { is.highWaterStamps[int32(i.NodeID)] = i.OrigStamp } } is.processCallbacks(key, i.Value) return nil }
func (lt *localRPCTransport) getClient(id proto.RaftNodeID) (*rpc.Client, error) { lt.mu.Lock() defer lt.mu.Unlock() select { case <-lt.closed: return nil, util.Errorf("transport is closed") default: } client, ok := lt.clients[id] if ok { return client, nil } listener, ok := lt.listeners[id] if !ok { return nil, util.Errorf("unknown peer %v", id) } address := listener.Addr().String() // If this wasn't test code we wouldn't want to call Dial while holding the lock. client, err := rpc.Dial("tcp", address) if err != nil { return nil, err } lt.clients[id] = client return client, err }
// RunCommitters lists stargazers by commits to subscribed repos, from // most prolific committer to least. func RunCommitters(c *fetch.Context, sg []*fetch.Stargazer, rs map[string]*fetch.Repo) error { log.Infof("running committers analysis") // Open file and prepare. f, err := createFile(c, "committers.csv") if err != nil { return util.Errorf("failed to create file: %s", err) } defer f.Close() w := csv.NewWriter(f) if err := w.Write([]string{"Login", "Email", "Commits", "Additions", "Deletions"}); err != nil { return util.Errorf("failed to write to CSV: %s", err) } // Sort the stargazers. slice := Contributors(sg) sort.Sort(slice) // Now accumulate by days. for _, s := range slice { c, a, d := s.TotalCommits() if c == 0 { break } if err := w.Write([]string{s.Login, s.Email, strconv.Itoa(c), strconv.Itoa(a), strconv.Itoa(d)}); err != nil { return util.Errorf("failed to write to CSV: %s", err) } } w.Flush() log.Infof("wrote committers analysis to %s", f.Name()) return nil }
func (rc *ResponseCache) decodeResponseCacheKey(encKey engine.MVCCKey) ([]byte, error) { key, _, isValue, err := engine.MVCCDecodeKey(encKey) if err != nil { return nil, err } if isValue { return nil, util.Errorf("key %s is not a raw MVCC value", encKey) } if !bytes.HasPrefix(key, keys.LocalRangeIDPrefix) { return nil, util.Errorf("key %s does not have %s prefix", key, keys.LocalRangeIDPrefix) } // Cut the prefix and the Range ID. b := key[len(keys.LocalRangeIDPrefix):] b, _, err = encoding.DecodeUvarint(b) if err != nil { return nil, err } if !bytes.HasPrefix(b, keys.LocalResponseCacheSuffix) { return nil, util.Errorf("key %s does not contain the response cache suffix %s", key, keys.LocalResponseCacheSuffix) } // Cut the response cache suffix. b = b[len(keys.LocalResponseCacheSuffix):] // Decode the family. b, fm, err := encoding.DecodeBytes(b, nil) if err != nil { return nil, err } if len(b) > 0 { return nil, util.Errorf("key %s has leftover bytes after decode: %s; indicates corrupt key", encKey, b) } return fm, nil }
// sendRPC sends one or more RPCs to replicas from the supplied // storage.Replica slice. First, replicas which have gossipped // addresses are corraled and then sent via rpc.Send, with requirement // that one RPC to a server must succeed. func (db *DistDB) sendRPC(replicas []storage.Replica, method string, args, replyChanI interface{}) error { if len(replicas) == 0 { return util.Errorf("%s: replicas set is empty", method) } // Build a map from replica address (if gossipped) to args struct // with replica set in header. argsMap := map[net.Addr]interface{}{} for _, replica := range replicas { addr, err := db.nodeIDToAddr(replica.NodeID) if err != nil { glog.V(1).Infof("node %d address is not gossipped", replica.NodeID) continue } // Copy the args value and set the replica in the header. argsVal := reflect.New(reflect.TypeOf(args).Elem()) reflect.Indirect(argsVal).Set(reflect.Indirect(reflect.ValueOf(args))) reflect.Indirect(argsVal).FieldByName("Replica").Set(reflect.ValueOf(replica)) argsMap[addr] = argsVal.Interface() } if len(argsMap) == 0 { return noNodeAddrsAvailErr{util.Errorf("%s: no replica node addresses available via gossip", method)} } rpcOpts := rpc.Options{ N: 1, SendNextTimeout: defaultSendNextTimeout, Timeout: defaultRPCTimeout, } return rpc.Send(argsMap, method, replyChanI, rpcOpts) }
// CopyInto copies all the cached results from this response cache // into the destRangeID response cache. Failures decoding individual // cache entries return an error. func (rc *ResponseCache) CopyInto(e engine.Engine, destRangeID roachpb.RangeID) error { start := engine.MVCCEncodeKey( keys.ResponseCacheKey(rc.rangeID, roachpb.KeyMin)) end := engine.MVCCEncodeKey( keys.ResponseCacheKey(rc.rangeID, roachpb.KeyMax)) return e.Iterate(start, end, func(kv engine.MVCCKeyValue) (bool, error) { // Decode the key into a cmd, skipping on error. Otherwise, // write it to the corresponding key in the new cache. family, err := rc.decodeResponseCacheKey(kv.Key) if err != nil { return false, util.Errorf("could not decode a response cache key %s: %s", roachpb.Key(kv.Key), err) } key := keys.ResponseCacheKey(destRangeID, family) encKey := engine.MVCCEncodeKey(key) // Decode the value, update the checksum and re-encode. meta := &engine.MVCCMetadata{} if err := proto.Unmarshal(kv.Value, meta); err != nil { return false, util.Errorf("could not decode response cache value %s [% x]: %s", roachpb.Key(kv.Key), kv.Value, err) } meta.Value.Checksum = nil meta.Value.InitChecksum(key) _, _, err = engine.PutProto(e, encKey, meta) return false, err }) }
// 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 (rc *ResponseCache) decodeResponseCacheKey(encKey proto.EncodedKey) (proto.ClientCmdID, error) { ret := proto.ClientCmdID{} key, _, isValue := engine.MVCCDecodeKey(encKey) if isValue { return ret, util.Errorf("key %s is not a raw MVCC value", encKey) } if !bytes.HasPrefix(key, keys.LocalRangeIDPrefix) { return ret, util.Errorf("key %s does not have %s prefix", key, keys.LocalRangeIDPrefix) } // Cut the prefix and the Raft ID. b := key[len(keys.LocalRangeIDPrefix):] b, _ = encoding.DecodeUvarint(b) if !bytes.HasPrefix(b, keys.LocalResponseCacheSuffix) { return ret, util.Errorf("key %s does not contain the response cache suffix %s", key, keys.LocalResponseCacheSuffix) } // Cut the response cache suffix. b = b[len(keys.LocalResponseCacheSuffix):] // Now, decode the command ID. b, wt := encoding.DecodeUvarint(b) b, rd := encoding.DecodeUint64(b) if len(b) > 0 { return ret, util.Errorf("key %s has leftover bytes after decode: %s; indicates corrupt key", encKey, b) } ret.WallTime = int64(wt) ret.Random = int64(rd) return ret, nil }
// getTruncatableIndexes returns the total number of stale raft log entries that // can be truncated and the oldest index that cannot be pruned. func getTruncatableIndexes(r *Replica) (uint64, uint64, error) { rangeID := r.Desc().RangeID raftStatus := r.store.RaftStatus(rangeID) if raftStatus == nil { return 0, 0, util.Errorf("the raft group doesn't exist for range %d", rangeID) } // Is this the raft leader? if raftStatus.RaftState != raft.StateLeader { return 0, 0, nil } // Find the oldest index still in use by the range. oldestIndex := raftStatus.Applied for _, progress := range raftStatus.Progress { if progress.Match < oldestIndex { oldestIndex = progress.Match } } firstIndex, err := r.FirstIndex() if err != nil { return 0, 0, util.Errorf("error retrieving first index for range %d: %s", rangeID, err) } if oldestIndex < firstIndex { return 0, 0, util.Errorf("raft log's oldest index is less than the first index for range %d", rangeID) } // Return the number of truncatable indexes. return oldestIndex - firstIndex, oldestIndex, nil }
// ConditionalPut sets the value for a specified key only if // the expected value matches. If not, the return value contains // the actual value. func (r *Range) ConditionalPut(args *proto.ConditionalPutRequest, reply *proto.ConditionalPutResponse) { // Handle check for non-existence of key. val, err := r.engine.Get(args.Key) if err != nil { reply.SetGoError(err) return } if args.ExpValue.Bytes == nil && val != nil { reply.SetGoError(util.Errorf("key %q already exists", args.Key)) return } else if args.ExpValue.Bytes != nil { // Handle check for existence when there is no key. if val == nil { reply.SetGoError(util.Errorf("key %q does not exist", args.Key)) return } else if !bytes.Equal(args.ExpValue.Bytes, val) { // TODO(Jiang-Ming): provide the correct timestamp once switch to use MVCC reply.ActualValue = &proto.Value{Bytes: val} reply.SetGoError(util.Errorf("key %q does not match existing", args.Key)) return } } reply.SetGoError(r.internalPut(args.Key, args.Value)) }