github.com/outcaste-io/ristretto@v0.2.3/z/z.go (about) 1 /* 2 * Copyright 2019 Dgraph Labs, Inc. and Contributors 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package z 18 19 import ( 20 "context" 21 "fmt" 22 "os" 23 "sync" 24 25 "github.com/cespare/xxhash/v2" 26 ) 27 28 // TODO: Figure out a way to re-use memhash for the second uint64 hash, we 29 // already know that appending bytes isn't reliable for generating a 30 // second hash (see Ristretto PR #88). 31 // 32 // We also know that while the Go runtime has a runtime memhash128 33 // function, it's not possible to use it to generate [2]uint64 or 34 // anything resembling a 128bit hash, even though that's exactly what 35 // we need in this situation. 36 func KeyToHash(key interface{}) (uint64, uint64) { 37 if key == nil { 38 return 0, 0 39 } 40 switch k := key.(type) { 41 case uint64: 42 return k, 0 43 case string: 44 return MemHashString(k), xxhash.Sum64String(k) 45 case []byte: 46 return MemHash(k), xxhash.Sum64(k) 47 case byte: 48 return uint64(k), 0 49 case int: 50 return uint64(k), 0 51 case int32: 52 return uint64(k), 0 53 case uint32: 54 return uint64(k), 0 55 case int64: 56 return uint64(k), 0 57 default: 58 panic("Key type not supported") 59 } 60 } 61 62 var ( 63 dummyCloserChan <-chan struct{} 64 tmpDir string 65 ) 66 67 // Closer holds the two things we need to close a goroutine and wait for it to 68 // finish: a chan to tell the goroutine to shut down, and a WaitGroup with 69 // which to wait for it to finish shutting down. 70 type Closer struct { 71 waiting sync.WaitGroup 72 73 ctx context.Context 74 cancel context.CancelFunc 75 } 76 77 // SetTmpDir sets the temporary directory for the temporary buffers. 78 func SetTmpDir(dir string) { 79 tmpDir = dir 80 } 81 82 // NewCloser constructs a new Closer, with an initial count on the WaitGroup. 83 func NewCloser(initial int) *Closer { 84 ret := &Closer{} 85 ret.ctx, ret.cancel = context.WithCancel(context.Background()) 86 ret.waiting.Add(initial) 87 return ret 88 } 89 90 // AddRunning Add()'s delta to the WaitGroup. 91 func (lc *Closer) AddRunning(delta int) { 92 lc.waiting.Add(delta) 93 } 94 95 // Ctx can be used to get a context, which would automatically get cancelled when Signal is called. 96 func (lc *Closer) Ctx() context.Context { 97 if lc == nil { 98 return context.Background() 99 } 100 return lc.ctx 101 } 102 103 // Signal signals the HasBeenClosed signal. 104 func (lc *Closer) Signal() { 105 // Todo(ibrahim): Change Signal to return error on next badger breaking change. 106 lc.cancel() 107 } 108 109 // HasBeenClosed gets signaled when Signal() is called. 110 func (lc *Closer) HasBeenClosed() <-chan struct{} { 111 if lc == nil { 112 return dummyCloserChan 113 } 114 return lc.ctx.Done() 115 } 116 117 // Done calls Done() on the WaitGroup. 118 func (lc *Closer) Done() { 119 if lc == nil { 120 return 121 } 122 lc.waiting.Done() 123 } 124 125 // Wait waits on the WaitGroup. (It waits for NewCloser's initial value, AddRunning, and Done 126 // calls to balance out.) 127 func (lc *Closer) Wait() { 128 lc.waiting.Wait() 129 } 130 131 // SignalAndWait calls Signal(), then Wait(). 132 func (lc *Closer) SignalAndWait() { 133 lc.Signal() 134 lc.Wait() 135 } 136 137 // ZeroOut zeroes out all the bytes in the range [start, end). 138 func ZeroOut(dst []byte, start, end int) { 139 if start < 0 || start >= len(dst) { 140 return // BAD 141 } 142 if end >= len(dst) { 143 end = len(dst) 144 } 145 if end-start <= 0 { 146 return 147 } 148 Memclr(dst[start:end]) 149 // b := dst[start:end] 150 // for i := range b { 151 // b[i] = 0x0 152 // } 153 } 154 155 func fatal(args ...interface{}) { 156 defer os.Exit(1) 157 panic(fmt.Sprint(args...)) 158 } 159 160 func fatalf(format string, args ...interface{}) { 161 defer os.Exit(1) 162 panic(fmt.Sprintf(format, args...)) 163 }