// Addr returns the address for the key, used to lookup the range containing // the key. In the normal case, this is simply the key's value. However, for // local keys, such as transaction records, range-spanning binary tree node // pointers, the address is the inner encoded key, with the local key prefix // and the suffix and optional detail removed. This address unwrapping is // performed repeatedly in the case of doubly-local keys. In this way, local // keys address to the same range as non-local keys, but are stored separately // so that they don't collide with user-space or global system keys. // // However, not all local keys are addressable in the global map. Only range // local keys incorporating a range key (start key or transaction key) are // addressable (e.g. range metadata and txn records). Range local keys // incorporating the Range ID are not (e.g. abort cache entries, and range // stats). func Addr(k roachpb.Key) (roachpb.RKey, error) { if !bytes.HasPrefix(k, localPrefix) { return roachpb.RKey(k), nil } for { if bytes.HasPrefix(k, localStorePrefix) { return nil, errors.Errorf("store-local key %q is not addressable", k) } if bytes.HasPrefix(k, LocalRangeIDPrefix) { return nil, errors.Errorf("local range ID key %q is not addressable", k) } if !bytes.HasPrefix(k, LocalRangePrefix) { return nil, errors.Errorf("local key %q malformed; should contain prefix %q", k, LocalRangePrefix) } k = k[len(LocalRangePrefix):] var err error // Decode the encoded key, throw away the suffix and detail. if _, k, err = encoding.DecodeBytesAscending(k, nil); err != nil { return nil, err } if !bytes.HasPrefix(k, localPrefix) { break } } return roachpb.RKey(k), nil }
// DecodeDataKey decodes a time series key into its components. func DecodeDataKey(key roachpb.Key) (string, string, Resolution, int64, error) { // Detect and remove prefix. remainder := key if !bytes.HasPrefix(remainder, keyDataPrefix) { return "", "", 0, 0, util.Errorf("malformed time series data key %v: improper prefix", key) } remainder = remainder[len(keyDataPrefix):] // Decode series name. remainder, name, err := encoding.DecodeBytesAscending(remainder, nil) if err != nil { return "", "", 0, 0, err } // Decode resolution. remainder, resolutionInt, err := encoding.DecodeVarintAscending(remainder) if err != nil { return "", "", 0, 0, err } resolution := Resolution(resolutionInt) // Decode timestamp. remainder, timeslot, err := encoding.DecodeVarintAscending(remainder) if err != nil { return "", "", 0, 0, err } timestamp := timeslot * resolution.KeyDuration() // The remaining bytes are the source. source := remainder return string(name), string(source), resolution, timestamp, nil }
func sequenceCacheKeyPrint(key roachpb.Key) string { b, id, err := encoding.DecodeBytesAscending([]byte(key), nil) if err != nil { return fmt.Sprintf("/%q/err:%v", key, err) } txnID, err := uuid.FromBytes(id) if err != nil { return fmt.Sprintf("/%q/err:%v", key, err) } if len(b) == 0 { return fmt.Sprintf("/%q", txnID) } b, epoch, err := encoding.DecodeUint32Descending(b) if err != nil { return fmt.Sprintf("/%q/err:%v", txnID, err) } _, seq, err := encoding.DecodeUint32Descending(b) if err != nil { return fmt.Sprintf("/%q/epoch:%d/err:%v", txnID, epoch, err) } return fmt.Sprintf("/%q/epoch:%d/seq:%d", txnID, epoch, seq) }
// DecodeAbortCacheKey decodes the provided abort cache entry, // returning the transaction ID. func DecodeAbortCacheKey(key roachpb.Key, dest []byte) (*uuid.UUID, error) { // TODO(tschottdorf): redundant check. if !bytes.HasPrefix(key, LocalRangeIDPrefix) { return nil, util.Errorf("key %s does not have %s prefix", key, LocalRangeIDPrefix) } // Cut the prefix, the Range ID, and the infix specifier. b := key[len(LocalRangeIDPrefix):] b, _, err := encoding.DecodeUvarintAscending(b) if err != nil { return nil, err } b = b[1:] if !bytes.HasPrefix(b, LocalAbortCacheSuffix) { return nil, util.Errorf("key %s does not contain the abort cache suffix %s", key, LocalAbortCacheSuffix) } // Cut the abort cache suffix. b = b[len(LocalAbortCacheSuffix):] // Decode the id. b, idBytes, err := encoding.DecodeBytesAscending(b, dest) if err != nil { return nil, err } if len(b) > 0 { return nil, util.Errorf("key %q has leftover bytes after decode: %s; indicates corrupt key", key, b) } txnID, err := uuid.FromBytes(idBytes) return txnID, err }
func abortCacheKeyPrint(key roachpb.Key) string { _, id, err := encoding.DecodeBytesAscending([]byte(key), nil) if err != nil { return fmt.Sprintf("/%q/err:%v", key, err) } txnID, err := uuid.FromBytes(id) if err != nil { return fmt.Sprintf("/%q/err:%v", key, err) } return fmt.Sprintf("/%q", txnID) }
// DecodeRangeKey decodes the range key into range start key, // suffix and optional detail (may be nil). func DecodeRangeKey(key roachpb.Key) (startKey, suffix, detail roachpb.Key, err error) { if !bytes.HasPrefix(key, LocalRangePrefix) { return nil, nil, nil, errors.Errorf("key %q does not have %q prefix", key, LocalRangePrefix) } // Cut the prefix and the Range ID. b := key[len(LocalRangePrefix):] b, startKey, err = encoding.DecodeBytesAscending(b, nil) if err != nil { return nil, nil, nil, err } if len(b) < localSuffixLength { return nil, nil, nil, errors.Errorf("key %q does not have suffix of length %d", key, localSuffixLength) } // Cut the suffix. suffix = b[:localSuffixLength] detail = b[localSuffixLength:] return }
// DecodeAbortCacheKey decodes the provided abort cache entry, // returning the transaction ID. func DecodeAbortCacheKey(key roachpb.Key, dest []byte) (*uuid.UUID, error) { _, _, suffix, detail, err := DecodeRangeIDKey(key) if err != nil { return nil, err } if !bytes.Equal(suffix, LocalAbortCacheSuffix) { return nil, errors.Errorf("key %s does not contain the abort cache suffix %s", key, LocalAbortCacheSuffix) } // Decode the id. detail, idBytes, err := encoding.DecodeBytesAscending(detail, dest) if err != nil { return nil, err } if len(detail) > 0 { return nil, errors.Errorf("key %q has leftover bytes after decode: %s; indicates corrupt key", key, detail) } txnID, err := uuid.FromBytes(idBytes) return txnID, err }
// Addr returns the address for the key, used to lookup the range containing // the key. In the normal case, this is simply the key's value. However, for // local keys, such as transaction records, range-spanning binary tree node // pointers, the address is the trailing suffix of the key, with the local key // prefix removed. In this way, local keys address to the same range as // non-local keys, but are stored separately so that they don't collide with // user-space or global system keys. // // However, not all local keys are addressable in the global map. Only range // local keys incorporating a range key (start key or transaction key) are // addressable (e.g. range metadata and txn records). Range local keys // incorporating the Range ID are not (e.g. sequence cache entries, and range // stats). // // TODO(pmattis): Should KeyAddress return an error when the key is malformed? func Addr(k roachpb.Key) roachpb.RKey { if k == nil { return nil } if !bytes.HasPrefix(k, localPrefix) { return roachpb.RKey(k) } if bytes.HasPrefix(k, LocalRangePrefix) { k = k[len(LocalRangePrefix):] _, k, err := encoding.DecodeBytesAscending(k, nil) if err != nil { panic(err) } return roachpb.RKey(k) } log.Fatalf("local key %q malformed; should contain prefix %q", k, LocalRangePrefix) return nil }
func decodeSequenceCacheKey(key roachpb.Key, dest []byte) (*uuid.UUID, uint32, uint32, error) { // TODO(tschottdorf): redundant check. if !bytes.HasPrefix(key, keys.LocalRangeIDPrefix) { return nil, 0, 0, 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.DecodeUvarintAscending(b) if err != nil { return nil, 0, 0, err } if !bytes.HasPrefix(b, keys.LocalSequenceCacheSuffix) { return nil, 0, 0, util.Errorf("key %s does not contain the sequence cache suffix %s", key, keys.LocalSequenceCacheSuffix) } // Cut the sequence cache suffix. b = b[len(keys.LocalSequenceCacheSuffix):] // Decode the id. b, idBytes, err := encoding.DecodeBytesAscending(b, dest) if err != nil { return nil, 0, 0, err } // Decode the epoch. b, epoch, err := encoding.DecodeUint32Descending(b) if err != nil { return nil, 0, 0, err } // Decode the sequence number. b, seq, err := encoding.DecodeUint32Descending(b) if err != nil { return nil, 0, 0, err } if len(b) > 0 { return nil, 0, 0, util.Errorf("key %q has leftover bytes after decode: %s; indicates corrupt key", key, b) } txnID, err := uuid.FromBytes(idBytes) return txnID, epoch, seq, err }
// decodeDataKeySuffix decodes a time series key into its components. func decodeDataKeySuffix(key roachpb.Key) (string, string, Resolution, int64, error) { // Decode series name. remainder, name, err := encoding.DecodeBytesAscending(key, nil) if err != nil { return "", "", 0, 0, err } // Decode resolution. remainder, resolutionInt, err := encoding.DecodeVarintAscending(remainder) if err != nil { return "", "", 0, 0, err } resolution := Resolution(resolutionInt) // Decode timestamp. remainder, timeslot, err := encoding.DecodeVarintAscending(remainder) if err != nil { return "", "", 0, 0, err } timestamp := timeslot * resolution.KeyDuration() // The remaining bytes are the source. source := remainder return string(name), string(source), resolution, timestamp, nil }
// DecodeTableKey decodes a table key/value. func DecodeTableKey( a *DatumAlloc, valType parser.Datum, key []byte, dir encoding.Direction, ) (parser.Datum, []byte, error) { if (dir != encoding.Ascending) && (dir != encoding.Descending) { return nil, nil, util.Errorf("invalid direction: %d", dir) } var isNull bool if key, isNull = encoding.DecodeIfNull(key); isNull { return parser.DNull, key, nil } var rkey []byte var err error switch valType.(type) { case *parser.DBool: var i int64 if dir == encoding.Ascending { rkey, i, err = encoding.DecodeVarintAscending(key) } else { rkey, i, err = encoding.DecodeVarintDescending(key) } // No need to chunk allocate DBool as MakeDBool returns either // parser.DBoolTrue or parser.DBoolFalse. return parser.MakeDBool(parser.DBool(i != 0)), rkey, err case *parser.DInt: var i int64 if dir == encoding.Ascending { rkey, i, err = encoding.DecodeVarintAscending(key) } else { rkey, i, err = encoding.DecodeVarintDescending(key) } return a.NewDInt(parser.DInt(i)), rkey, err case *parser.DFloat: var f float64 if dir == encoding.Ascending { rkey, f, err = encoding.DecodeFloatAscending(key) } else { rkey, f, err = encoding.DecodeFloatDescending(key) } return a.NewDFloat(parser.DFloat(f)), rkey, err case *parser.DDecimal: var d *inf.Dec if dir == encoding.Ascending { rkey, d, err = encoding.DecodeDecimalAscending(key, nil) } else { rkey, d, err = encoding.DecodeDecimalDescending(key, nil) } dd := a.NewDDecimal(parser.DDecimal{}) dd.Set(d) return dd, rkey, err case *parser.DString: var r string if dir == encoding.Ascending { rkey, r, err = encoding.DecodeUnsafeStringAscending(key, nil) } else { rkey, r, err = encoding.DecodeUnsafeStringDescending(key, nil) } return a.NewDString(parser.DString(r)), rkey, err case *parser.DBytes: var r []byte if dir == encoding.Ascending { rkey, r, err = encoding.DecodeBytesAscending(key, nil) } else { rkey, r, err = encoding.DecodeBytesDescending(key, nil) } return a.NewDBytes(parser.DBytes(r)), rkey, err case *parser.DDate: var t int64 if dir == encoding.Ascending { rkey, t, err = encoding.DecodeVarintAscending(key) } else { rkey, t, err = encoding.DecodeVarintDescending(key) } return a.NewDDate(parser.DDate(t)), rkey, err case *parser.DTimestamp: var t time.Time if dir == encoding.Ascending { rkey, t, err = encoding.DecodeTimeAscending(key) } else { rkey, t, err = encoding.DecodeTimeDescending(key) } return a.NewDTimestamp(parser.DTimestamp{Time: t}), rkey, err case *parser.DTimestampTZ: var t time.Time if dir == encoding.Ascending { rkey, t, err = encoding.DecodeTimeAscending(key) } else { rkey, t, err = encoding.DecodeTimeDescending(key) } return a.NewDTimestampTZ(parser.DTimestampTZ{Time: t}), rkey, err case *parser.DInterval: var d duration.Duration if dir == encoding.Ascending { rkey, d, err = encoding.DecodeDurationAscending(key) } else { rkey, d, err = encoding.DecodeDurationDescending(key) } return a.NewDInterval(parser.DInterval{Duration: d}), rkey, err default: return nil, nil, util.Errorf("TODO(pmattis): decoded index key: %s", valType.Type()) } }
func decodeTableKey(valType parser.Datum, key []byte, dir encoding.Direction) ( parser.Datum, []byte, error) { if (dir != encoding.Ascending) && (dir != encoding.Descending) { return nil, nil, util.Errorf("invalid direction: %d", dir) } var isNull bool if key, isNull = encoding.DecodeIfNull(key); isNull { return parser.DNull, key, nil } var rkey []byte var err error switch valType.(type) { case parser.DBool: var i int64 if dir == encoding.Ascending { rkey, i, err = encoding.DecodeVarintAscending(key) } else { rkey, i, err = encoding.DecodeVarintDescending(key) } return parser.DBool(i != 0), rkey, err case parser.DInt: var i int64 if dir == encoding.Ascending { rkey, i, err = encoding.DecodeVarintAscending(key) } else { rkey, i, err = encoding.DecodeVarintDescending(key) } return parser.DInt(i), rkey, err case parser.DFloat: var f float64 if dir == encoding.Ascending { rkey, f, err = encoding.DecodeFloatAscending(key, nil) } else { rkey, f, err = encoding.DecodeFloatDescending(key, nil) } return parser.DFloat(f), rkey, err case *parser.DDecimal: var d *inf.Dec if dir == encoding.Ascending { rkey, d, err = encoding.DecodeDecimalAscending(key, nil) } else { rkey, d, err = encoding.DecodeDecimalDescending(key, nil) } dd := &parser.DDecimal{} dd.Set(d) return dd, rkey, err case parser.DString: var r string if dir == encoding.Ascending { rkey, r, err = encoding.DecodeStringAscending(key, nil) } else { rkey, r, err = encoding.DecodeStringDescending(key, nil) } return parser.DString(r), rkey, err case parser.DBytes: var r []byte if dir == encoding.Ascending { rkey, r, err = encoding.DecodeBytesAscending(key, nil) } else { rkey, r, err = encoding.DecodeBytesDescending(key, nil) } return parser.DBytes(r), rkey, err case parser.DDate: var t int64 if dir == encoding.Ascending { rkey, t, err = encoding.DecodeVarintAscending(key) } else { rkey, t, err = encoding.DecodeVarintDescending(key) } return parser.DDate(t), rkey, err case parser.DTimestamp: var t time.Time if dir == encoding.Ascending { rkey, t, err = encoding.DecodeTimeAscending(key) } else { rkey, t, err = encoding.DecodeTimeDescending(key) } return parser.DTimestamp{Time: t}, rkey, err case parser.DInterval: var d int64 if dir == encoding.Ascending { rkey, d, err = encoding.DecodeVarintAscending(key) } else { rkey, d, err = encoding.DecodeVarintDescending(key) } return parser.DInterval{Duration: time.Duration(d)}, rkey, err default: return nil, nil, util.Errorf("TODO(pmattis): decoded index key: %s", valType.Type()) } }