github.com/janelia-flyem/dvid@v1.0.0/datatype/labelsz/keys.go (about) 1 /* 2 This file supports keyspaces for the labelsz data type. 3 */ 4 5 package labelsz 6 7 import ( 8 "encoding/binary" 9 "fmt" 10 "math" 11 12 "github.com/janelia-flyem/dvid/datastore" 13 "github.com/janelia-flyem/dvid/datatype/annotation" 14 "github.com/janelia-flyem/dvid/storage" 15 ) 16 17 const ( 18 // keyUnknown should never be used and is a check for corrupt or incorrectly set keys 19 keyUnknown storage.TKeyClass = iota 20 21 // reserved type-specific key for metadata 22 keyProperties = datastore.PropertyTKeyClass 23 24 // key is index type + size + label 25 keyTypeSizeLabel = 97 26 27 // key is index type + label, with value equal to size, necessary to delete old indices. 28 keyTypeLabel = 98 29 ) 30 31 // DescribeTKeyClass returns a string explanation of what a particular TKeyClass 32 // is used for. Implements the datastore.TKeyClassDescriber interface. 33 func (d *Data) DescribeTKeyClass(tkc storage.TKeyClass) string { 34 switch tkc { 35 case keyTypeLabel: 36 return "labelsz index type + label key" 37 case keyTypeSizeLabel: 38 return "labelsz index type + size + label key" 39 default: 40 } 41 return "unknown labelsz key" 42 } 43 44 const ( 45 UnknownIndex IndexType = iota 46 PostSyn // Post-synaptic element 47 PreSyn // Pre-synaptic element 48 Gap // Gap junction 49 Note // A note or bookmark with some description 50 AllSyn // PostSyn, PreSyn, or Gap 51 Voxels // Number of voxels 52 ) 53 54 // IndexType gives the type of index. 55 type IndexType uint8 56 57 func (i IndexType) String() string { 58 switch i { 59 case PostSyn: 60 return "PostSyn" 61 case PreSyn: 62 return "PreSyn" 63 case Gap: 64 return "Gap" 65 case Note: 66 return "Note" 67 case AllSyn: 68 return "AllSyn" 69 case Voxels: 70 return "Voxels" 71 default: 72 return "Unknown IndexType" 73 } 74 } 75 76 // StringToIndexType converts a string to an IndexType 77 func StringToIndexType(s string) IndexType { 78 switch s { 79 case "PostSyn": 80 return PostSyn 81 case "PreSyn": 82 return PreSyn 83 case "Gap": 84 return Gap 85 case "Note": 86 return Note 87 case "AllSyn": 88 return AllSyn 89 case "Voxels": 90 return Voxels 91 default: 92 return UnknownIndex 93 } 94 } 95 96 func elementToIndexType(e annotation.ElementType) (i IndexType) { 97 switch e { 98 case annotation.PostSyn: 99 i = PostSyn 100 case annotation.PreSyn: 101 i = PreSyn 102 case annotation.Gap: 103 i = Gap 104 case annotation.Note: 105 i = Note 106 default: 107 i = UnknownIndex 108 } 109 return 110 } 111 112 // can be used as map index and holds serialized (IndexType, Label) 113 type indexedLabel string 114 115 func (il indexedLabel) String() string { 116 i := IndexType(il[0]) 117 labelBytes := []byte(il[1:]) 118 label := binary.BigEndian.Uint64(labelBytes) 119 return fmt.Sprintf("[label %d, index %s]", label, i.String()) 120 } 121 122 func toIndexedLabel(e annotation.ElementPos) indexedLabel { 123 return newIndexedLabel(elementToIndexType(e.Kind), e.Label) 124 } 125 126 func newIndexedLabel(i IndexType, label uint64) indexedLabel { 127 buf := make([]byte, 9) 128 buf[0] = byte(i) 129 binary.BigEndian.PutUint64(buf[1:], label) 130 return indexedLabel(buf) 131 } 132 133 func decodeIndexedLabel(il indexedLabel) (i IndexType, label uint64, err error) { 134 if len(il) != 9 { 135 err = fmt.Errorf("indexed label %v is supposed to be 9 bytes but is %d bytes", il, len(il)) 136 return 137 } 138 i = IndexType(il[0]) 139 labelBytes := []byte(il[1:]) 140 label = binary.BigEndian.Uint64(labelBytes) 141 return 142 } 143 144 // NewTypeSizeLabelTKey returns a type-specific key for the (index type, size, label) tuple. 145 func NewTypeSizeLabelTKey(i IndexType, sz uint32, label uint64) storage.TKey { 146 // Since we want biggest -> smallest sort and initially only have forward range queries, 147 // modify size to make smallest <-> largest. 148 rsz := math.MaxUint32 - sz 149 150 buf := make([]byte, 8+1+4) 151 buf[0] = byte(i) 152 binary.BigEndian.PutUint32(buf[1:5], rsz) 153 binary.BigEndian.PutUint64(buf[5:], label) 154 return storage.NewTKey(keyTypeSizeLabel, buf) 155 } 156 157 // DecodeTypeSizeLabelTKey decodes a type-specific key into a (index type, size, label) tuple. 158 func DecodeTypeSizeLabelTKey(tk storage.TKey) (i IndexType, sz uint32, label uint64, err error) { 159 var ibytes []byte 160 ibytes, err = tk.ClassBytes(keyTypeSizeLabel) 161 if err != nil { 162 return 163 } 164 if len(ibytes) != 13 { 165 err = fmt.Errorf("labelsz element size type-specific key is wrong size: expected 13, got %d bytes", len(ibytes)) 166 return 167 } 168 i = IndexType(ibytes[0]) 169 sz = math.MaxUint32 - binary.BigEndian.Uint32(ibytes[1:5]) 170 label = binary.BigEndian.Uint64(ibytes[5:]) 171 return 172 } 173 174 // NewTypeLabelTKey returns a type-specific key for the (index type, label) tuple. 175 func NewTypeLabelTKey(i IndexType, label uint64) storage.TKey { 176 buf := make([]byte, 1+8) 177 buf[0] = byte(i) 178 binary.BigEndian.PutUint64(buf[1:], label) 179 return storage.NewTKey(keyTypeLabel, buf) 180 } 181 182 // DecodeTypeLabelTKey decodes a type-specific key into a (index type, label) tuple. 183 func DecodeTypeLabelTKey(tk storage.TKey) (i IndexType, label uint64, err error) { 184 var ibytes []byte 185 ibytes, err = tk.ClassBytes(keyTypeLabel) 186 if err != nil { 187 return 188 } 189 if len(ibytes) != 9 { 190 err = fmt.Errorf("labelsz label size type-specific key is wrong size: expected 9, got %d bytes", len(ibytes)) 191 return 192 } 193 i = IndexType(ibytes[0]) 194 label = binary.BigEndian.Uint64(ibytes[1:]) 195 return 196 }