func setAppliedIndex( ctx context.Context, eng engine.ReadWriter, ms *enginepb.MVCCStats, rangeID roachpb.RangeID, appliedIndex, leaseAppliedIndex uint64, ) error { var value roachpb.Value value.SetInt(int64(appliedIndex)) if err := engine.MVCCPut(ctx, eng, ms, keys.RaftAppliedIndexKey(rangeID), hlc.ZeroTimestamp, value, nil /* txn */); err != nil { return err } value.SetInt(int64(leaseAppliedIndex)) return engine.MVCCPut(ctx, eng, ms, keys.LeaseAppliedIndexKey(rangeID), hlc.ZeroTimestamp, value, nil /* txn */) }
// setLastIndex persists a new last index. func setLastIndex(eng engine.Engine, rangeID roachpb.RangeID, lastIndex uint64) error { var value roachpb.Value value.SetInt(int64(lastIndex)) return engine.MVCCPut(eng, nil, keys.RaftLastIndexKey(rangeID), roachpb.ZeroTimestamp, value, nil /* txn */) }
func setLastIndex(eng engine.ReadWriter, rangeID roachpb.RangeID, lastIndex uint64) error { var value roachpb.Value value.SetInt(int64(lastIndex)) return engine.MVCCPut(context.Background(), eng, nil, keys.RaftLastIndexKey(rangeID), hlc.ZeroTimestamp, value, nil /* txn */) }
// GetInitialValues returns the set of initial K/V values which should be added to // a bootstrapping CockroachDB cluster in order to create the tables contained // in the schema. func (ms MetadataSchema) GetInitialValues() []roachpb.KeyValue { var ret []roachpb.KeyValue // Save the ID generator value, which will generate descriptor IDs for user // objects. value := roachpb.Value{} value.SetInt(int64(keys.MaxReservedDescID + 1)) ret = append(ret, roachpb.KeyValue{ Key: keys.DescIDGenerator, Value: value, }) // addDescriptor generates the needed KeyValue objects to install a // descriptor on a new cluster. addDescriptor := func(parentID ID, desc descriptorProto) { // Create name metadata key. value := roachpb.Value{} value.SetInt(int64(desc.GetID())) ret = append(ret, roachpb.KeyValue{ Key: MakeNameMetadataKey(parentID, desc.GetName()), Value: value, }) // Create descriptor metadata key. value = roachpb.Value{} wrappedDesc := wrapDescriptor(desc) if err := value.SetProto(wrappedDesc); err != nil { log.Fatalf("could not marshal %v", desc) } ret = append(ret, roachpb.KeyValue{ Key: MakeDescMetadataKey(desc.GetID()), Value: value, }) } // Generate initial values for system databases and tables, which have // static descriptors that were generated elsewhere. for _, sysObj := range ms.descs { addDescriptor(sysObj.parentID, sysObj.desc) } for _, tbl := range ms.tables { dbID := ID(keys.SystemDatabaseID) desc := createTableDescriptor(tbl.id, dbID, tbl.definition, tbl.privileges) addDescriptor(dbID, &desc) } // Other key/value generation that doesn't fit into databases and // tables. This can be used to add initial entries to a table. ret = append(ret, ms.otherKV...) // Sort returned key values; this is valuable because it matches the way the // objects would be sorted if read from the engine. sort.Sort(roachpb.KeyValueByKey(ret)) return ret }
// setAppliedIndex persists a new applied index. func setAppliedIndex(eng engine.Engine, ms *engine.MVCCStats, rangeID roachpb.RangeID, appliedIndex uint64) error { var value roachpb.Value value.SetInt(int64(appliedIndex)) return engine.MVCCPut(eng, ms, keys.RaftAppliedIndexKey(rangeID), roachpb.ZeroTimestamp, value, nil /* txn */) }
// GetInitialSystemValues returns a list of key/value pairs. // They are written at cluster bootstrap time (see storage/node.go:BootstrapCLuster). func GetInitialSystemValues() []roachpb.KeyValue { systemData := []struct { parentID ID desc descriptorProto }{ {keys.RootNamespaceID, &SystemDB}, {SystemDB.ID, &NamespaceTable}, {SystemDB.ID, &DescriptorTable}, {SystemDB.ID, &LeaseTable}, {SystemDB.ID, &UsersTable}, {SystemDB.ID, &ZonesTable}, } // Initial kv pairs: // - ID generator // - 2 per table/database numEntries := 1 + len(systemData)*2 ret := make([]roachpb.KeyValue, numEntries, numEntries) i := 0 // Descriptor ID generator. value := roachpb.Value{} value.SetInt(int64(keys.MaxReservedDescID + 1)) ret[i] = roachpb.KeyValue{ Key: keys.DescIDGenerator, Value: value, } i++ // System database and tables. for _, d := range systemData { value = roachpb.Value{} value.SetInt(int64(d.desc.GetID())) ret[i] = roachpb.KeyValue{ Key: MakeNameMetadataKey(d.parentID, d.desc.GetName()), Value: value, } i++ value = roachpb.Value{} desc := wrapDescriptor(d.desc) if err := value.SetProto(desc); err != nil { log.Fatalf("could not marshal %v", desc) } ret[i] = roachpb.KeyValue{ Key: MakeDescMetadataKey(d.desc.GetID()), Value: value, } i++ } return ret }
// PutSequence writes a sequence number for the specified family. func (rc *ResponseCache) PutSequence(e engine.Engine, family []byte, sequence int64, err error) error { if sequence <= 0 || len(family) == 0 { return errEmptyID } if !rc.shouldCacheError(err) { return nil } // Write the response value to the engine. key := keys.ResponseCacheKey(rc.rangeID, family) var v roachpb.Value v.SetInt(sequence) return engine.MVCCPut(e, nil /* ms */, key, roachpb.ZeroTimestamp, v, nil /* txn */) }
// marshalValue returns a roachpb.Value initialized from the source // interface{}, returning an error if the types are not compatible. func marshalValue(v interface{}) (roachpb.Value, error) { var r roachpb.Value // Handle a few common types via a type switch. switch t := v.(type) { case *roachpb.Value: return *t, nil case nil: return r, nil case bool: i := int64(0) if t { i = 1 } r.SetInt(i) return r, nil case string: r.SetBytes([]byte(t)) return r, nil case []byte: r.SetBytes(t) return r, nil case inf.Dec: err := r.SetDecimal(&t) return r, err case roachpb.Key: r.SetBytes([]byte(t)) return r, nil case time.Time: r.SetTime(t) return r, nil case duration.Duration: err := r.SetDuration(t) return r, err case proto.Message: err := r.SetProto(t) return r, err } // Handle all of the Go primitive types besides struct and pointers. This // switch also handles types based on a primitive type (e.g. "type MyInt // int"). switch v := reflect.ValueOf(v); v.Kind() { case reflect.Bool: i := int64(0) if v.Bool() { i = 1 } r.SetInt(i) return r, nil case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: r.SetInt(v.Int()) return r, nil case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: r.SetInt(int64(v.Uint())) return r, nil case reflect.Float32, reflect.Float64: r.SetFloat(v.Float()) return r, nil case reflect.String: r.SetBytes([]byte(v.String())) return r, nil } return r, fmt.Errorf("unable to marshal %T: %v", v, v) }
// MarshalColumnValue returns a Go primitive value equivalent of val, of the // type expected by col. If val's type is incompatible with col, or if // col's type is not yet implemented, an error is returned. func MarshalColumnValue(col ColumnDescriptor, val parser.Datum) (roachpb.Value, error) { var r roachpb.Value if val == parser.DNull { return r, nil } switch col.Type.Kind { case ColumnType_BOOL: if v, ok := val.(*parser.DBool); ok { if *v { r.SetInt(1) } else { r.SetInt(0) } return r, nil } case ColumnType_INT: if v, ok := val.(*parser.DInt); ok { r.SetInt(int64(*v)) return r, nil } case ColumnType_FLOAT: if v, ok := val.(*parser.DFloat); ok { r.SetFloat(float64(*v)) return r, nil } case ColumnType_DECIMAL: if v, ok := val.(*parser.DDecimal); ok { err := r.SetDecimal(&v.Dec) return r, err } case ColumnType_STRING: if v, ok := val.(*parser.DString); ok { r.SetString(string(*v)) return r, nil } case ColumnType_BYTES: if v, ok := val.(*parser.DBytes); ok { r.SetString(string(*v)) return r, nil } if v, ok := val.(*parser.DString); ok { r.SetString(string(*v)) return r, nil } case ColumnType_DATE: if v, ok := val.(*parser.DDate); ok { r.SetInt(int64(*v)) return r, nil } case ColumnType_TIMESTAMP: if v, ok := val.(*parser.DTimestamp); ok { r.SetTime(v.Time) return r, nil } case ColumnType_TIMESTAMPTZ: if v, ok := val.(*parser.DTimestampTZ); ok { r.SetTime(v.Time) return r, nil } case ColumnType_INTERVAL: if v, ok := val.(*parser.DInterval); ok { err := r.SetDuration(v.Duration) return r, err } default: return r, util.Errorf("unsupported column type: %s", col.Type.Kind) } return r, fmt.Errorf("value type %s doesn't match type %s of column %q", val.Type(), col.Type.Kind, col.Name) }
// GetInitialValues returns the set of initial K/V values which should be added to // a bootstrapping CockroachDB cluster in order to create the tables contained // in the schema. func (ms MetadataSchema) GetInitialValues() []roachpb.KeyValue { var ret []roachpb.KeyValue // Save the ID generator value, which will generate descriptor IDs for user // objects. value := roachpb.Value{} value.SetInt(int64(keys.MaxReservedDescID + 1)) ret = append(ret, roachpb.KeyValue{ Key: keys.DescIDGenerator, Value: value, }) // addDescriptor generates the needed KeyValue objects to install a // descriptor on a new cluster. addDescriptor := func(parentID ID, desc descriptorProto) { // Create name metadata key. value := roachpb.Value{} value.SetInt(int64(desc.GetID())) ret = append(ret, roachpb.KeyValue{ Key: MakeNameMetadataKey(parentID, desc.GetName()), Value: value, }) // Create descriptor metadata key. value = roachpb.Value{} wrappedDesc := wrapDescriptor(desc) if err := value.SetProto(wrappedDesc); err != nil { log.Fatalf("could not marshal %v", desc) } ret = append(ret, roachpb.KeyValue{ Key: MakeDescMetadataKey(desc.GetID()), Value: value, }) } // Generate initial values for system databases and tables, which have // static descriptors that were generated elsewhere. for _, sysObj := range ms.systemObjects { addDescriptor(sysObj.parentID, sysObj.desc) } // Descriptor IDs for non-system databases and objects will be generated // sequentially within the non-system reserved range. initialDescID := keys.MaxSystemDescID + 1 nextID := func() ID { next := initialDescID initialDescID++ return ID(next) } // Generate initial values for non-system metadata tables, which do not need // well-known IDs. for _, db := range ms.databases { dbID := nextID() addDescriptor(keys.RootNamespaceID, &DatabaseDescriptor{ Name: db.name, ID: dbID, Privileges: db.privileges, }) for _, tbl := range db.tables { desc := createTableDescriptor(nextID(), dbID, tbl.definition, tbl.privileges) addDescriptor(dbID, &desc) } } // Sort returned key values; this is valuable because it matches the way the // objects would be sorted if read from the engine. sort.Sort(roachpb.KeyValueByKey(ret)) return ret }