Merge pull request #13055 from prometheus/beorn7/storage

storage: Fix mixed samples handling in sampleRing
This commit is contained in:
Björn Rabenstein 2023-10-31 17:10:24 +01:00 committed by GitHub
commit 96179fe06a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 57 additions and 1 deletions

View file

@ -284,7 +284,8 @@ func newSampleRing(delta int64, size int, typ chunkenc.ValueType) *sampleRing {
case chunkenc.ValFloatHistogram:
r.fhBuf = make([]fhSample, size)
default:
r.iBuf = make([]chunks.Sample, size)
// Do not initialize anything because the 1st sample will be
// added to one of the other bufs anyway.
}
return r
}
@ -294,6 +295,12 @@ func (r *sampleRing) reset() {
r.i = -1
r.f = 0
r.bufInUse = noBuf
// The first sample after the reset will always go to a specialized
// buffer. If we later need to change to the interface buffer, we'll
// copy from the specialized buffer to the interface buffer. For that to
// work properly, we have to reset the interface buffer here, too.
r.iBuf = r.iBuf[:0]
}
// Returns the current iterator. Invalidates previously returned iterators.
@ -441,6 +448,7 @@ func (r *sampleRing) add(s chunks.Sample) {
}
// The new sample isn't a fit for the already existing
// ones. Copy the latter into the interface buffer where needed.
// The interface buffer is assumed to be of length zero at this point.
switch r.bufInUse {
case fBuf:
for _, s := range r.fBuf {

View file

@ -90,6 +90,54 @@ func TestSampleRing(t *testing.T) {
}
}
func TestSampleRingMixed(t *testing.T) {
h1 := tsdbutil.GenerateTestHistogram(1)
h2 := tsdbutil.GenerateTestHistogram(2)
// With ValNone as the preferred type, nothing should be initialized.
r := newSampleRing(10, 2, chunkenc.ValNone)
require.Zero(t, len(r.fBuf))
require.Zero(t, len(r.hBuf))
require.Zero(t, len(r.fhBuf))
require.Zero(t, len(r.iBuf))
// But then mixed adds should work as expected.
r.addF(fSample{t: 1, f: 3.14})
r.addH(hSample{t: 2, h: h1})
it := r.iterator()
require.Equal(t, chunkenc.ValFloat, it.Next())
ts, f := it.At()
require.Equal(t, int64(1), ts)
require.Equal(t, 3.14, f)
require.Equal(t, chunkenc.ValHistogram, it.Next())
var h *histogram.Histogram
ts, h = it.AtHistogram()
require.Equal(t, int64(2), ts)
require.Equal(t, h1, h)
require.Equal(t, chunkenc.ValNone, it.Next())
r.reset()
it = r.iterator()
require.Equal(t, chunkenc.ValNone, it.Next())
r.addF(fSample{t: 3, f: 4.2})
r.addH(hSample{t: 4, h: h2})
it = r.iterator()
require.Equal(t, chunkenc.ValFloat, it.Next())
ts, f = it.At()
require.Equal(t, int64(3), ts)
require.Equal(t, 4.2, f)
require.Equal(t, chunkenc.ValHistogram, it.Next())
ts, h = it.AtHistogram()
require.Equal(t, int64(4), ts)
require.Equal(t, h2, h)
require.Equal(t, chunkenc.ValNone, it.Next())
}
func TestBufferedSeriesIterator(t *testing.T) {
var it *BufferedSeriesIterator