github.com/janelia-flyem/dvid@v1.0.0/datatype/labelarray/keys.go (about) 1 /* 2 This file supports keyspaces for label block data types. 3 */ 4 5 package labelarray 6 7 import ( 8 "encoding/binary" 9 "fmt" 10 11 "github.com/janelia-flyem/dvid/datastore" 12 "github.com/janelia-flyem/dvid/dvid" 13 "github.com/janelia-flyem/dvid/storage" 14 ) 15 16 const ( 17 // keyUnknown should never be used and is a check for corrupt or incorrectly set keys 18 keyUnknown storage.TKeyClass = 0 19 20 // reserved type-specific key for metadata 21 keyProperties = datastore.PropertyTKeyClass 22 23 // key = scale + block coord 24 keyLabelBlock = 186 25 26 // key = label. value = labels.LabelMeta 27 keyLabelIndex = 187 28 29 // Used to store max label on commit for each version of the instance. 30 keyLabelMax = 237 31 32 // Stores the single repo-wide max label for the instance. Used for new labels on split. 33 keyRepoLabelMax = 238 34 ) 35 36 // DescribeTKeyClass returns a string explanation of what a particular TKeyClass 37 // is used for. Implements the datastore.TKeyClassDescriber interface. 38 func (d *Data) DescribeTKeyClass(tkc storage.TKeyClass) string { 39 switch tkc { 40 case keyLabelBlock: 41 return "labelarray scale + block coord key" 42 case keyLabelIndex: 43 return "labelarray label index key" 44 case keyLabelMax: 45 return "labelarray label max key" 46 case keyRepoLabelMax: 47 return "labelarray repo label max key" 48 default: 49 } 50 return "unknown labelarray key" 51 } 52 53 var ( 54 maxLabelTKey = storage.NewTKey(keyLabelMax, nil) 55 maxRepoLabelTKey = storage.NewTKey(keyRepoLabelMax, nil) 56 ) 57 58 // NewBlockTKey returns a TKey for a label block, which is a slice suitable for 59 // lexicographical ordering on zyx coordinates. 60 func NewBlockTKey(scale uint8, idx dvid.Index) storage.TKey { 61 izyx := idx.(*dvid.IndexZYX) 62 return NewBlockTKeyByCoord(scale, izyx.ToIZYXString()) 63 } 64 65 // NewBlockTKeyByCoord returns a TKey for a block coord in string format. 66 func NewBlockTKeyByCoord(scale uint8, izyx dvid.IZYXString) storage.TKey { 67 buf := make([]byte, 13) 68 buf[0] = byte(scale) 69 copy(buf[1:], []byte(izyx)) 70 return storage.NewTKey(keyLabelBlock, buf) 71 } 72 73 // DecodeBlockTKey returns a spatial index from a label block key. 74 // TODO: Extend this when necessary to allow any form of spatial indexing like CZYX. 75 func DecodeBlockTKey(tk storage.TKey) (scale uint8, idx *dvid.IndexZYX, err error) { 76 ibytes, err := tk.ClassBytes(keyLabelBlock) 77 if err != nil { 78 return 0, nil, err 79 } 80 if len(ibytes) != 13 { 81 err = fmt.Errorf("bad labelarray block key of %d bytes: %v", len(ibytes), ibytes) 82 return 83 } 84 scale = uint8(ibytes[0]) 85 idx = new(dvid.IndexZYX) 86 if err = idx.IndexFromBytes(ibytes[1:]); err != nil { 87 err = fmt.Errorf("Cannot recover ZYX index from image block key %v: %v\n", tk, err) 88 } 89 return 90 } 91 92 // NewLabelIndexTKey returns a TKey corresponding to a label. Value will hold block coords that contain the label. 93 func NewLabelIndexTKey(label uint64) storage.TKey { 94 buf := make([]byte, 8) 95 binary.BigEndian.PutUint64(buf, label) 96 return storage.NewTKey(keyLabelIndex, buf) 97 } 98 99 // DecodeLabelIndexTKey parses a TKey and returns the corresponding label. 100 func DecodeLabelIndexTKey(tk storage.TKey) (label uint64, err error) { 101 ibytes, err := tk.ClassBytes(keyLabelIndex) 102 if err != nil { 103 return 104 } 105 label = binary.BigEndian.Uint64(ibytes[0:8]) 106 return 107 }