github.com/m3db/m3@v1.5.0/src/m3ninx/index/segment/mem/postings_map_gen.go (about) 1 // Copyright (c) 2018 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 // This file was automatically generated by genny. 22 // Any changes will be lost if this file is regenerated. 23 // see https://github.com/mauricelam/genny 24 25 package mem 26 27 import ( 28 "github.com/m3db/m3/src/m3ninx/postings" 29 ) 30 31 // Copyright (c) 2018 Uber Technologies, Inc. 32 // 33 // Permission is hereby granted, free of charge, to any person obtaining a copy 34 // of this software and associated documentation files (the "Software"), to deal 35 // in the Software without restriction, including without limitation the rights 36 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 37 // copies of the Software, and to permit persons to whom the Software is 38 // furnished to do so, subject to the following conditions: 39 // 40 // The above copyright notice and this permission notice shall be included in 41 // all copies or substantial portions of the Software. 42 // 43 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 44 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 45 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 46 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 47 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 48 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 49 // THE SOFTWARE. 50 51 // postingsMapHash is the hash for a given map entry, this is public to support 52 // iterating over the map using a native Go for loop. 53 type postingsMapHash uint64 54 55 // postingsMapHashFn is the hash function to execute when hashing a key. 56 type postingsMapHashFn func([]byte) postingsMapHash 57 58 // postingsMapEqualsFn is the equals key function to execute when detecting equality of a key. 59 type postingsMapEqualsFn func([]byte, []byte) bool 60 61 // postingsMapCopyFn is the copy key function to execute when copying the key. 62 type postingsMapCopyFn func([]byte) []byte 63 64 // postingsMapFinalizeFn is the finalize key function to execute when finished with a key. 65 type postingsMapFinalizeFn func([]byte) 66 67 // postingsMap uses the genny package to provide a generic hash map that can be specialized 68 // by running the following command from this root of the repository: 69 // ``` 70 // make hashmap-gen pkg=outpkg key_type=Type value_type=Type out_dir=/tmp 71 // ``` 72 // Or if you would like to use bytes or ident.ID as keys you can use the 73 // partially specialized maps to generate your own maps as well: 74 // ``` 75 // make byteshashmap-gen pkg=outpkg value_type=Type out_dir=/tmp 76 // make idhashmap-gen pkg=outpkg value_type=Type out_dir=/tmp 77 // ``` 78 // This will output to stdout the generated source file to use for your map. 79 // It uses linear probing by incrementing the number of the hash created when 80 // hashing the identifier if there is a collision. 81 // postingsMap is a value type and not an interface to allow for less painful 82 // upgrades when adding/removing methods, it is not likely to need mocking so 83 // an interface would not be super useful either. 84 type postingsMap struct { 85 _postingsMapOptions 86 87 // lookup uses hash of the identifier for the key and the MapEntry value 88 // wraps the value type and the key (used to ensure lookup is correct 89 // when dealing with collisions), we use uint64 for the hash partially 90 // because lookups of maps with uint64 keys has a fast path for Go. 91 lookup map[postingsMapHash]postingsMapEntry 92 } 93 94 // _postingsMapOptions is a set of options used when creating an identifier map, it is kept 95 // private so that implementers of the generated map can specify their own options 96 // that partially fulfill these options. 97 type _postingsMapOptions struct { 98 // hash is the hash function to execute when hashing a key. 99 hash postingsMapHashFn 100 // equals is the equals key function to execute when detecting equality. 101 equals postingsMapEqualsFn 102 // copy is the copy key function to execute when copying the key. 103 copy postingsMapCopyFn 104 // finalize is the finalize key function to execute when finished with a 105 // key, this is optional to specify. 106 finalize postingsMapFinalizeFn 107 // initialSize is the initial size for the map, use zero to use Go's std map 108 // initial size and consequently is optional to specify. 109 initialSize int 110 } 111 112 // postingsMapEntry is an entry in the map, this is public to support iterating 113 // over the map using a native Go for loop. 114 type postingsMapEntry struct { 115 // key is used to check equality on lookups to resolve collisions 116 key _postingsMapKey 117 // value type stored 118 value postings.MutableList 119 } 120 121 type _postingsMapKey struct { 122 key []byte 123 finalize bool 124 } 125 126 // Key returns the map entry key. 127 func (e postingsMapEntry) Key() []byte { 128 return e.key.key 129 } 130 131 // Value returns the map entry value. 132 func (e postingsMapEntry) Value() postings.MutableList { 133 return e.value 134 } 135 136 // _postingsMapAlloc is a non-exported function so that when generating the source code 137 // for the map you can supply a public constructor that sets the correct 138 // hash, equals, copy, finalize options without users of the map needing to 139 // implement them themselves. 140 func _postingsMapAlloc(opts _postingsMapOptions) *postingsMap { 141 m := &postingsMap{_postingsMapOptions: opts} 142 m.Reallocate() 143 return m 144 } 145 146 func (m *postingsMap) newMapKey(k []byte, opts _postingsMapKeyOptions) _postingsMapKey { 147 key := _postingsMapKey{key: k, finalize: opts.finalizeKey} 148 if !opts.copyKey { 149 return key 150 } 151 152 key.key = m.copy(k) 153 return key 154 } 155 156 func (m *postingsMap) removeMapKey(hash postingsMapHash, key _postingsMapKey) { 157 delete(m.lookup, hash) 158 if key.finalize { 159 m.finalize(key.key) 160 } 161 } 162 163 // Get returns a value in the map for an identifier if found. 164 func (m *postingsMap) Get(k []byte) (postings.MutableList, bool) { 165 hash := m.hash(k) 166 for entry, ok := m.lookup[hash]; ok; entry, ok = m.lookup[hash] { 167 if m.equals(entry.key.key, k) { 168 return entry.value, true 169 } 170 // Linear probe to "next" to this entry (really a rehash) 171 hash++ 172 } 173 var empty postings.MutableList 174 return empty, false 175 } 176 177 // Set will set the value for an identifier. 178 func (m *postingsMap) Set(k []byte, v postings.MutableList) { 179 m.set(k, v, _postingsMapKeyOptions{ 180 copyKey: true, 181 finalizeKey: m.finalize != nil, 182 }) 183 } 184 185 // postingsMapSetUnsafeOptions is a set of options to use when setting a value with 186 // the SetUnsafe method. 187 type postingsMapSetUnsafeOptions struct { 188 NoCopyKey bool 189 NoFinalizeKey bool 190 } 191 192 // SetUnsafe will set the value for an identifier with unsafe options for how 193 // the map treats the key. 194 func (m *postingsMap) SetUnsafe(k []byte, v postings.MutableList, opts postingsMapSetUnsafeOptions) { 195 m.set(k, v, _postingsMapKeyOptions{ 196 copyKey: !opts.NoCopyKey, 197 finalizeKey: !opts.NoFinalizeKey, 198 }) 199 } 200 201 type _postingsMapKeyOptions struct { 202 copyKey bool 203 finalizeKey bool 204 } 205 206 func (m *postingsMap) set(k []byte, v postings.MutableList, opts _postingsMapKeyOptions) { 207 hash := m.hash(k) 208 for entry, ok := m.lookup[hash]; ok; entry, ok = m.lookup[hash] { 209 if m.equals(entry.key.key, k) { 210 m.lookup[hash] = postingsMapEntry{ 211 key: entry.key, 212 value: v, 213 } 214 return 215 } 216 // Linear probe to "next" to this entry (really a rehash) 217 hash++ 218 } 219 220 m.lookup[hash] = postingsMapEntry{ 221 key: m.newMapKey(k, opts), 222 value: v, 223 } 224 } 225 226 // Iter provides the underlying map to allow for using a native Go for loop 227 // to iterate the map, however callers should only ever read and not write 228 // the map. 229 func (m *postingsMap) Iter() map[postingsMapHash]postingsMapEntry { 230 return m.lookup 231 } 232 233 // Len returns the number of map entries in the map. 234 func (m *postingsMap) Len() int { 235 return len(m.lookup) 236 } 237 238 // Contains returns true if value exists for key, false otherwise, it is 239 // shorthand for a call to Get that doesn't return the value. 240 func (m *postingsMap) Contains(k []byte) bool { 241 _, ok := m.Get(k) 242 return ok 243 } 244 245 // Delete will remove a value set in the map for the specified key. 246 func (m *postingsMap) Delete(k []byte) { 247 hash := m.hash(k) 248 for entry, ok := m.lookup[hash]; ok; entry, ok = m.lookup[hash] { 249 if m.equals(entry.key.key, k) { 250 m.removeMapKey(hash, entry.key) 251 return 252 } 253 // Linear probe to "next" to this entry (really a rehash) 254 hash++ 255 } 256 } 257 258 // Reset will reset the map by simply deleting all keys to avoid 259 // allocating a new map. 260 func (m *postingsMap) Reset() { 261 for hash, entry := range m.lookup { 262 m.removeMapKey(hash, entry.key) 263 } 264 } 265 266 // Reallocate will avoid deleting all keys and reallocate a new 267 // map, this is useful if you believe you have a large map and 268 // will not need to grow back to a similar size. 269 func (m *postingsMap) Reallocate() { 270 if m.initialSize > 0 { 271 m.lookup = make(map[postingsMapHash]postingsMapEntry, m.initialSize) 272 } else { 273 m.lookup = make(map[postingsMapHash]postingsMapEntry) 274 } 275 }