Skip to content

Commit 076d5fe

Browse files
authored
Implement GetAppend (#68)
1 parent 794a326 commit 076d5fe

File tree

2 files changed

+63
-2
lines changed

2 files changed

+63
-2
lines changed

db.go

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -215,6 +215,34 @@ func (db *DB) Get(key []byte) ([]byte, error) {
215215
return retValue, nil
216216
}
217217

218+
// GetAppend returns the value for the given key (appended into buffer) stored in the DB or nil if the key doesn't exist
219+
func (db *DB) GetAppend(key, buf []byte) ([]byte, error) {
220+
h := db.hash(key)
221+
db.metrics.Gets.Add(1)
222+
db.mu.RLock()
223+
defer db.mu.RUnlock()
224+
var retValue []byte
225+
err := db.index.get(h, func(sl slot) (bool, error) {
226+
if uint16(len(key)) != sl.keySize {
227+
return false, nil
228+
}
229+
slKey, value, err := db.datalog.readKeyValue(sl)
230+
if err != nil {
231+
return true, err
232+
}
233+
if bytes.Equal(key, slKey) {
234+
retValue = append(buf, value...)
235+
return true, nil
236+
}
237+
db.metrics.HashCollisions.Add(1)
238+
return false, nil
239+
})
240+
if err != nil {
241+
return nil, err
242+
}
243+
return retValue, nil
244+
}
245+
218246
// Has returns true if the DB contains the given key.
219247
func (db *DB) Has(key []byte) (bool, error) {
220248
h := db.hash(key)

db_test.go

Lines changed: 35 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,18 @@ func TestEmpty(t *testing.T) {
117117
}
118118

119119
func TestFull(t *testing.T) {
120+
fullTest(t, func(db *DB, key []byte) ([]byte, error) {
121+
return db.Get(key)
122+
})
123+
var buf []byte
124+
fullTest(t, func(db *DB, key []byte) ([]byte, error) {
125+
var err error
126+
buf, err = db.GetAppend(key, buf[:0])
127+
return buf, err
128+
})
129+
}
130+
131+
func fullTest(t *testing.T, getFunc func(db *DB, key []byte) ([]byte, error)) {
120132
opts := &Options{
121133
BackgroundSyncInterval: -1,
122134
FileSystem: testFS,
@@ -165,7 +177,7 @@ func TestFull(t *testing.T) {
165177
if has, err := db.Has([]byte{0, i}); has || err != nil {
166178
t.Fatal(has, err)
167179
}
168-
v, err := db.Get([]byte{i})
180+
v, err := getFunc(db, []byte{i})
169181
if err != nil {
170182
t.Fatal(err)
171183
}
@@ -418,10 +430,11 @@ func BenchmarkGet(b *testing.B) {
418430
db, err := createTestDB(nil)
419431
assert.Nil(b, err)
420432
k := []byte{1}
421-
if err := db.Put(k, k); err != nil {
433+
if err := db.Put(k, make([]byte, 1024)); err != nil {
422434
b.Fail()
423435
}
424436
b.ResetTimer()
437+
b.ReportAllocs()
425438
for i := 0; i < b.N; i++ {
426439
if _, err := db.Get(k); err != nil {
427440
b.Fatal()
@@ -430,6 +443,26 @@ func BenchmarkGet(b *testing.B) {
430443
assert.Nil(b, db.Close())
431444
}
432445

446+
func BenchmarkGetAppend(b *testing.B) {
447+
db, err := createTestDB(nil)
448+
assert.Nil(b, err)
449+
k := []byte{1}
450+
if err := db.Put(k, make([]byte, 1024)); err != nil {
451+
b.Fail()
452+
}
453+
b.ResetTimer()
454+
b.ReportAllocs()
455+
buf := make([]byte, 0, 1024)
456+
for i := 0; i < b.N; i++ {
457+
value, err := db.GetAppend(k, buf[:0])
458+
if err != nil {
459+
b.Fatal()
460+
}
461+
buf = value
462+
}
463+
assert.Nil(b, db.Close())
464+
}
465+
433466
func BenchmarkBucket_UnmarshalBinary(b *testing.B) {
434467
testBucket := bucket{
435468
slots: [slotsPerBucket]slot{},

0 commit comments

Comments
 (0)