github.com/m3db/m3@v1.5.1-0.20231129193456-75a402aa583b/src/x/ident/types.go (about) 1 // Copyright (c) 2016 Uber Technologies, Inc. 2 // 3 // Permission is hereby granted, free of charge, to any person obtaining a copy 4 // of this software and associated documentation files (the "Software"), to deal 5 // in the Software without restriction, including without limitation the rights 6 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 // copies of the Software, and to permit persons to whom the Software is 8 // furnished to do so, subject to the following conditions: 9 // 10 // The above copyright notice and this permission notice shall be included in 11 // all copies or substantial portions of the Software. 12 // 13 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 // THE SOFTWARE. 20 21 // Package ident provides utilities for working with identifiers. 22 package ident 23 24 import ( 25 "fmt" 26 27 "github.com/m3db/m3/src/m3ninx/doc" 28 "github.com/m3db/m3/src/x/checked" 29 "github.com/m3db/m3/src/x/context" 30 ) 31 32 // ID represents an immutable identifier to allow use of byte slice pooling 33 // for the contents of the ID. 34 type ID interface { 35 fmt.Stringer 36 37 // Bytes returns the underlying byte slice of the bytes ID unpacked from 38 // any checked bytes container, callers cannot safely hold a ref to these 39 // bytes. 40 Bytes() []byte 41 42 // Equal returns whether the ID is equal to a given ID. 43 Equal(value ID) bool 44 45 // NoFinalize makes calls to finalize a no-op, this is useful when you 46 // would like to share a type with another sub-system that should is not 47 // allowed to finalize the resource as the resource is kept indefinitely 48 // until garbage collected (i.e. longly lived). 49 NoFinalize() 50 51 // IsNoFinalize returns whether finalize is a no-op or not, this is useful 52 // when you know you can use an ID without having to worry to take a copy. 53 IsNoFinalize() bool 54 55 // Finalize releases all resources held by the ID, unless NoFinalize has 56 // been called previously in which case this is a no-op. 57 Finalize() 58 } 59 60 // TagName represents the name of a timeseries tag. 61 type TagName ID 62 63 // TagValue represents the value of a timeseries tag. 64 type TagValue ID 65 66 // Tag represents a timeseries tag. 67 type Tag struct { 68 Name TagName 69 Value TagValue 70 noFinalize bool 71 } 72 73 // NoFinalize makes calls to finalize a no-op, this is useful when you 74 // would like to share a type with another sub-system that should is not 75 // allowed to finalize the resource as the resource is kept indefinitely 76 // until garbage collected (i.e. longly lived). 77 func (t *Tag) NoFinalize() { 78 t.noFinalize = true 79 t.Name.NoFinalize() 80 t.Value.NoFinalize() 81 } 82 83 // Finalize releases all resources held by the Tag, unless NoFinalize has 84 // been called previously in which case this is a no-op. 85 func (t *Tag) Finalize() { 86 if t.noFinalize { 87 return 88 } 89 if t.Name != nil { 90 t.Name.Finalize() 91 t.Name = nil 92 } 93 if t.Value != nil { 94 t.Value.Finalize() 95 t.Value = nil 96 } 97 } 98 99 // Equal returns whether the two tags are equal. 100 func (t Tag) Equal(value Tag) bool { 101 return t.Name.Equal(value.Name) && t.Value.Equal(value.Value) 102 } 103 104 // Pool represents an automatic pool of `ident` objects. 105 type Pool interface { 106 // GetBinaryID will create a new binary ID and take reference to the bytes. 107 // When the context closes the ID will be finalized and so too will 108 // the bytes, i.e. it will take ownership of the bytes. 109 GetBinaryID(c context.Context, data checked.Bytes) ID 110 111 // BinaryID will create a new binary ID and take a reference to the bytes. 112 BinaryID(data checked.Bytes) ID 113 114 // GetBinaryTag will create a new binary Tag and take reference to the bytes. 115 // When the context closes, the Tag will be finalized and so too will 116 // the bytes, i.e. it will take ownership of the bytes. 117 GetBinaryTag(c context.Context, name, value checked.Bytes) Tag 118 119 // BinaryTag will create a new binary Tag and take a reference to the provided bytes. 120 BinaryTag(name, value checked.Bytes) Tag 121 122 // GetStringID will create a new string ID and create a bytes copy of the 123 // string. When the context closes the ID will be finalized. 124 GetStringID(c context.Context, id string) ID 125 126 // StringID will create a new string ID and create a bytes copy of the 127 // string. 128 StringID(data string) ID 129 130 // GetStringTag will create a new string Tag and create a bytes copy of the 131 // string. When the context closes the ID will be finalized. 132 GetStringTag(c context.Context, name, value string) Tag 133 134 // StringTag will create a new string Tag and create a bytes copy of the 135 // string. 136 StringTag(name, value string) Tag 137 138 // Tags will create a new array of tags and return it. 139 Tags() Tags 140 141 // GetTagsIterator will create a tag iterator and return it. When the context 142 // closes the tags array and any tags contained will be finalized. 143 GetTagsIterator(c context.Context) TagsIterator 144 145 // TagsIterator will create a tag iterator and return it. 146 TagsIterator() TagsIterator 147 148 // Put an ID back in the pool. 149 Put(id ID) 150 151 // PutTag puts a tag back in the pool. 152 PutTag(tag Tag) 153 154 // PutTags puts a set of tags back in the pool. 155 PutTags(tags Tags) 156 157 // PutTagsIterator puts a tags iterator back in the pool. 158 PutTagsIterator(iter TagsIterator) 159 160 // Clone replicates a given ID into a pooled ID. 161 Clone(id ID) ID 162 163 // CloneTag replicates a given Tag into a pooled Tag. 164 CloneTag(tag Tag) Tag 165 166 // CloneTags replicates a given set of Tags into a pooled Tags. 167 CloneTags(tags Tags) Tags 168 } 169 170 // Iterator represents an iterator over `ID` instances. It is not thread-safe. 171 type Iterator interface { 172 // Next returns a bool indicating the presence of the next ID instance. 173 Next() bool 174 175 // Current returns the current ID instance. 176 Current() ID 177 178 // CurrentIndex returns the current index at. 179 CurrentIndex() int 180 181 // Close releases any resources held by the iterator. 182 Close() 183 184 // Err returns any errors encountered during iteration. 185 Err() error 186 187 // Len returns the number of elements. 188 Len() int 189 190 // Remaining returns the number of elements remaining to be iterated over. 191 Remaining() int 192 193 // Dupe returns an independent duplicate of the iterator. 194 Duplicate() Iterator 195 } 196 197 // TagIterator represents an iterator over `Tag` instances. It is not thread-safe. 198 type TagIterator interface { 199 // Next returns a bool indicating the presence of the next Tag instance. 200 Next() bool 201 202 // Current returns the current Tag instance. 203 Current() Tag 204 205 // CurrentIndex returns the current index at. 206 CurrentIndex() int 207 208 // Err returns any errors encountered during iteration. 209 Err() error 210 211 // Close releases any resources held by the iterator. 212 Close() 213 214 // Len returns the number of elements. 215 Len() int 216 217 // Remaining returns the number of elements remaining to be iterated over. 218 Remaining() int 219 220 // Duplicate returns an independent duplicate of the iterator. 221 Duplicate() TagIterator 222 223 // Rewind resets the tag iterator to the initial position. 224 Rewind() 225 } 226 227 // TagsIterator represents a TagIterator that can be reset with a Tags 228 // collection type. It is not thread-safe. 229 type TagsIterator interface { 230 TagIterator 231 232 // Reset allows the tag iterator to be reused with a new set of tags. 233 Reset(tags Tags) 234 235 // ResetFields allows tag iterator to be reused from a set of fields. 236 ResetFields(fields []doc.Field) 237 } 238 239 // Tags is a collection of Tag instances that can be pooled. 240 type Tags struct { 241 values []Tag 242 pool Pool 243 noFinalize bool 244 } 245 246 // NewTags returns a new set of tags. 247 func NewTags(values ...Tag) Tags { 248 return Tags{values: values} 249 } 250 251 // Reset resets the tags for reuse. 252 func (t *Tags) Reset(values []Tag) { 253 t.values = values 254 } 255 256 // Values returns the tags values. 257 func (t Tags) Values() []Tag { 258 return t.values 259 } 260 261 // Append will append a tag. 262 func (t *Tags) Append(tag Tag) { 263 t.values = append(t.values, tag) 264 } 265 266 // NoFinalize makes calls to finalize a no-op, this is useful when you 267 // would like to share a type with another sub-system that should is not 268 // allowed to finalize the resource as the resource is kept indefinitely 269 // until garbage collected (i.e. longly lived). 270 func (t *Tags) NoFinalize() { 271 t.noFinalize = true 272 for _, tag := range t.values { 273 tag.NoFinalize() 274 } 275 } 276 277 // Finalize finalizes all Tags, unless NoFinalize has been called previously 278 // in which case this is a no-op. 279 func (t *Tags) Finalize() { 280 if t.noFinalize { 281 return 282 } 283 284 values := t.values 285 t.values = nil 286 287 for i := range values { 288 values[i].Finalize() 289 } 290 291 if t.pool == nil { 292 return 293 } 294 295 t.pool.PutTags(Tags{values: values}) 296 } 297 298 // Equal returns a bool indicating if the tags are equal. It requires 299 // the two slices are ordered the same. 300 func (t Tags) Equal(other Tags) bool { 301 if len(t.Values()) != len(other.Values()) { 302 return false 303 } 304 for i := 0; i < len(t.Values()); i++ { 305 equal := t.values[i].Name.Equal(other.values[i].Name) && 306 t.values[i].Value.Equal(other.values[i].Value) 307 if !equal { 308 return false 309 } 310 } 311 return true 312 }