Skip to content

Commit bb70e15

Browse files
committed
db: remove getIterAlloc from Iterator
A call to DB.Get returns a io.Closer that must be called once the caller is finished with the returned value. Previously the *pebble.Iterator type provided the io.Closer implementation, so the *pebble.Iterator required a pointer to the containing getIterAlloc allocation for recycling. This commit inverts the relationship, adding a Close method to getIterAlloc, returning the *getIterAlloc as the io.Closer and allowing the removal of the getIterAlloc field from the Iterator. This new organization is more straightforward.
1 parent 8c784ec commit bb70e15

File tree

2 files changed

+29
-22
lines changed

2 files changed

+29
-22
lines changed

get.go

Lines changed: 26 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,22 @@ type getIterAlloc struct {
3535
get getIter
3636
}
3737

38+
// Close closes the contained iterator and recycles the alloc.
39+
//
40+
// During a successful call to DB.Get, *getIterAlloc is returned to the caller
41+
// as the io.Closer.
42+
func (g *getIterAlloc) Close() error {
43+
err := g.dbi.Close()
44+
keyBuf := g.keyBuf
45+
if cap(g.dbi.keyBuf) < maxKeyBufCacheSize && cap(g.dbi.keyBuf) > cap(keyBuf) {
46+
keyBuf = g.dbi.keyBuf
47+
}
48+
*g = getIterAlloc{}
49+
g.keyBuf = keyBuf
50+
getIterAllocPool.Put(g)
51+
return err
52+
}
53+
3854
var getIterAllocPool = sync.Pool{
3955
New: func() interface{} {
4056
return &getIterAlloc{}
@@ -95,31 +111,30 @@ func (d *DB) getInternal(key []byte, b *Batch, s *Snapshot) ([]byte, io.Closer,
95111
i := &buf.dbi
96112
pointIter := get
97113
*i = Iterator{
98-
ctx: context.Background(),
99-
getIterAlloc: buf,
100-
iter: pointIter,
101-
pointIter: pointIter,
102-
merge: d.merge,
103-
comparer: *d.opts.Comparer,
104-
readState: readState,
105-
keyBuf: buf.keyBuf,
114+
ctx: context.Background(),
115+
iter: pointIter,
116+
pointIter: pointIter,
117+
merge: d.merge,
118+
comparer: *d.opts.Comparer,
119+
readState: readState,
120+
keyBuf: buf.keyBuf,
106121
}
107122
// Set up a blob value fetcher to use for retrieving values from blob files.
108123
i.blobValueFetcher.Init(&readState.current.BlobFiles, d.fileCache, block.NoReadEnv)
109124
get.iiopts.blobValueFetcher = &i.blobValueFetcher
110125

111126
if !i.First() {
112-
err := i.Close()
127+
err := buf.Close()
113128
if err != nil {
114129
return nil, nil, err
115130
}
116131
return nil, nil, ErrNotFound
117132
}
118133
val, err := i.ValueAndErr()
119134
if err != nil {
120-
return nil, nil, errors.CombineErrors(err, i.Close())
135+
return nil, nil, errors.CombineErrors(err, buf.Close())
121136
}
122-
return val, i, nil
137+
return val, buf, nil
123138
}
124139

125140
// getIter is an internal iterator used to perform gets. It iterates through

iterator.go

Lines changed: 3 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -241,7 +241,6 @@ type Iterator struct {
241241
// called. In that case, it is explicitly set to nil.
242242
iterKV *base.InternalKV
243243
alloc *iterAlloc
244-
getIterAlloc *getIterAlloc
245244
prefixOrFullSeekKey []byte
246245
readSampling readSampling
247246
stats IteratorStats
@@ -2452,17 +2451,10 @@ func (i *Iterator) Close() error {
24522451
alloc.merging.heap.items = mergingIterHeapItems
24532452

24542453
iterAllocPool.Put(alloc)
2455-
} else if alloc := i.getIterAlloc; alloc != nil {
2456-
if cap(i.keyBuf) >= maxKeyBufCacheSize {
2457-
alloc.keyBuf = nil
2458-
} else {
2459-
alloc.keyBuf = i.keyBuf
2460-
}
2461-
*alloc = getIterAlloc{
2462-
keyBuf: alloc.keyBuf,
2463-
}
2464-
getIterAllocPool.Put(alloc)
24652454
}
2455+
// NB: When the Iterator is used as a part of a Get(), Close() is called by
2456+
// getIterAlloc.Close which handles recycling the appropriate structure and
2457+
// fields.
24662458
return err
24672459
}
24682460

0 commit comments

Comments
 (0)