-
Notifications
You must be signed in to change notification settings - Fork 0
/
hashindex.go
90 lines (78 loc) · 1.85 KB
/
hashindex.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
package gomap
import (
"bytes"
"sync"
"unsafe"
"github.com/segmentio/fasthash/fnv1"
)
func (h *Hashmap) addKey(key []byte, slabOffset Key) {
hkey, newKey := h.getKeyOffsetToAdd(key)
(*h.Keys)[hkey] = slabOffset
if newKey {
*h.Count += 1
}
}
func (h *Hashmap) addBucket(key []byte, slabOffset Key) {
if h.checkResize() {
h.resize()
}
h.addKey(key, slabOffset)
}
func hash(key []byte) Hash {
return Hash(fnv1.HashBytes32(key))
}
func (h *Hashmap) getKeys() []Key {
tmpkeys := (*Key)(unsafe.Pointer(&h.hashMap[0]))
ret := unsafe.Slice(tmpkeys, h.Capacity)
return ret
}
func (h *Hashmap) getKeyOffsetToAdd(key []byte) (uint64, bool) {
myhash := hash(key)
hkey := uint64(myhash) % (h.Capacity)
for {
hkey = (hkey + 1) % h.Capacity
mybucket := (*h.Keys)[hkey]
if mybucket.slabOffset == 0 {
return hkey, true
}
if mybucket.hash == myhash {
item := h.unmarshalItemFromSlab(mybucket)
if bytes.Equal(item.Key, key) {
return hkey, false
}
}
}
}
func (h *Hashmap) addManyBuckets(items []Item, slabOffsets []Key) {
if h.checkResize() {
h.resize()
}
h.addManyKeys(items, slabOffsets)
}
func (h *Hashmap) addManyKeys(items []Item, slabOffsets []Key) {
var wg sync.WaitGroup
seenSet := NewSet()
extra_items := make([]Item, 0)
extra_slabOffsets := make([]Key, 0)
hkeys, totalNewKey := ConcurrentMap(items, h.getKeyOffsetToAdd)
for i, hkey := range hkeys {
alreadyExists := seenSet.Add(hkey)
if alreadyExists {
extra_items = append(extra_items, items[i])
extra_slabOffsets = append(extra_slabOffsets, slabOffsets[i])
totalNewKey -= 1
} else {
//todo put this in gothing
wg.Add(1)
go func(i int, hkey uint64) {
defer wg.Done()
(*h.Keys)[hkey] = slabOffsets[i]
}(i, hkey)
}
}
wg.Wait()
*h.Count += totalNewKey
for i, item := range extra_items {
h.addBucket(item.Key, extra_slabOffsets[i])
}
}