-
Notifications
You must be signed in to change notification settings - Fork 36
/
bytekey.go
166 lines (145 loc) · 4.76 KB
/
bytekey.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
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
package offheap
import (
"fmt"
xxh64 "github.com/glycerine/xxhash-64"
)
// ByteKeyHashTable shows how to specialize HashTable to
// handle the []byte type as a key. At present, given the current
// definition of Key_t (you should redefine Key_t if needed -- see offheap.go),
// only the first 64 bytes are used in the hash of the key.
type ByteKeyHashTable HashTable
// xxHasher64 provides hashing for the byte-key (BK) interface to the hash table
//
// We use the 64-bit implementation of XXHash for speed.
// see
// https://github.com/OneOfOne/xxhash (github.com/glycerine/xxhash-64 version-locks)
// http://fastcompression.blogspot.com/2014/07/xxhash-wider-64-bits.html
//
var xxHasher64 = xxh64.New64()
// NewByteKeyHashTable produces a new ByteKeyHashTable, one specialized for
// handling []byte as keys.
func NewByteKeyHashTable(initialSize int64) *ByteKeyHashTable {
return (*ByteKeyHashTable)(NewHashTable(initialSize))
}
// InsertBK is the insert function for []byte keys. By default only len(Key_t) bytes are used in the key.
func (t *ByteKeyHashTable) InsertBK(bytekey []byte, value interface{}) bool {
xxHasher64.Reset()
min := minimum(len(Key_t{}), len(bytekey))
_, err := xxHasher64.Write(bytekey[:min])
if err != nil {
panic(err)
}
hashkey := xxHasher64.Sum64()
cell, ok := (*HashTable)(t).Insert(hashkey)
copy(cell.ByteKey[:], bytekey)
cell.SetValue(value)
return ok
}
func minimum(a, b int) int {
if a < b {
return a
}
return b
}
// LookupBK is the lookup function for []byte keys. By default only len(Key_t) bytes are used in the key.
func (t *ByteKeyHashTable) LookupBK(bytekey []byte) (Val_t, bool) {
xxHasher64.Reset()
min := minimum(len(Key_t{}), len(bytekey))
_, err := xxHasher64.Write(bytekey[:min])
if err != nil {
panic(err)
}
hashkey := xxHasher64.Sum64()
cell := (*HashTable)(t).Lookup(hashkey)
if cell == nil {
return Val_t{}, false
}
return cell.Value, true
}
// DeleteBK removes an entry with a []byte key. By default only len(Key_t) bytes are used in the key.
func (t *ByteKeyHashTable) DeleteBK(bytekey []byte) bool {
xxHasher64.Reset()
min := minimum(len(Key_t{}), len(bytekey))
_, err := xxHasher64.Write(bytekey[:min])
if err != nil {
panic(err)
}
hashkey := xxHasher64.Sum64()
cell := (*HashTable)(t).Lookup(hashkey)
if cell == nil {
return false
}
(*HashTable)(t).DeleteCell(cell)
return true
}
// StringHashTable shows how to specialize HashTable to
// handle strings as keys. At present, given the current
// definition of Key_t (you should redefine Key_t if needed -- see offheap.go),
// only the first 64 bytes are used in the hash of the key.
type StringHashTable HashTable
// NewStringHashTable produces a new StringHashTable, one specialized for
// handling keys of type string.
func NewStringHashTable(initialSize int64) *StringHashTable {
return (*StringHashTable)(NewHashTable(initialSize))
}
// InsertStringKey inserts a value with a key that is a string.
func (t *StringHashTable) InsertStringKey(strkey string, value interface{}) bool {
xxHasher64.Reset()
min := minimum(len(Key_t{}), len(strkey))
var bytekey Key_t
copy(bytekey[:], []byte(strkey))
_, err := xxHasher64.Write(bytekey[:min])
if err != nil {
panic(err)
}
hashkey := xxHasher64.Sum64()
cell, ok := (*HashTable)(t).Insert(hashkey)
cell.ByteKey = bytekey
cell.SetValue(value)
//fmt.Printf("assigned value : '%v' to key: '%v', with strkey: '%v'\n", value, hashkey, strkey)
return ok
}
// LookupStringKey looks up a value based on a key that is a string.
func (t *StringHashTable) LookupStringKey(strkey string) (Val_t, bool) {
xxHasher64.Reset()
min := minimum(len(Key_t{}), len(strkey))
var bytekey Key_t
copy(bytekey[:], []byte(strkey))
_, err := xxHasher64.Write(bytekey[:min])
if err != nil {
panic(err)
}
hashkey := xxHasher64.Sum64()
cell := (*HashTable)(t).Lookup(hashkey)
if cell == nil {
return Val_t{}, false
}
return cell.Value, true
}
// DeleteStringKey deletes the cell (if there is one) that has
// been previously inserted with the given strkey string key.
func (t *StringHashTable) DeleteStringKey(strkey string) bool {
xxHasher64.Reset()
min := minimum(len(Key_t{}), len(strkey))
var bytekey Key_t
copy(bytekey[:], []byte(strkey))
_, err := xxHasher64.Write(bytekey[:min])
if err != nil {
panic(err)
}
hashkey := xxHasher64.Sum64()
cell := (*HashTable)(t).Lookup(hashkey)
if cell == nil {
return false
}
(*HashTable)(t).DeleteCell(cell)
return true
}
// DumpStringKey provides a diagnostic printout of the
// contents of a hashtable that is using strings as keys.
func (t *StringHashTable) DumpStringKey() {
fmt.Printf(" DumpStringKey(): (table ArraySize: %d\n", t.ArraySize)
for it := (*HashTable)(t).NewIterator(); it.Cur != nil; it.Next() {
fmt.Printf(" '%v' -> %v\n", string(it.Cur.ByteKey[:]), it.Cur.Value)
}
}