diff --git a/db.go b/db.go index ae05fd385..66bd6679a 100644 --- a/db.go +++ b/db.go @@ -521,7 +521,7 @@ func (a *dbAppender) Add(lset labels.Labels, t int64, v float64) (uint64, error) } a.samples++ // Store last byte of sequence number in 3rd byte of reference. - return ref | (uint64(h.meta.Sequence^0xff) << 40), nil + return ref | (uint64(h.meta.Sequence&0xff) << 40), nil } func (a *dbAppender) AddFast(ref uint64, t int64, v float64) error { @@ -534,7 +534,7 @@ func (a *dbAppender) AddFast(ref uint64, t int64, v float64) error { return err } // If the last byte of the sequence does not add up, the reference is not valid. - if uint64(h.meta.Sequence^0xff) != gen { + if uint64(h.meta.Sequence&0xff) != gen { return ErrNotFound } if err := h.app.AddFast(ref, t, v); err != nil { diff --git a/db_test.go b/db_test.go index 9539101c2..f3b2dca2a 100644 --- a/db_test.go +++ b/db_test.go @@ -98,3 +98,34 @@ func TestDataNotAvailableAfterRollback(t *testing.T) { require.NoError(t, err) require.Equal(t, seriesSet, map[string][]sample{}) } + +func TestDBAppenderAddRef(t *testing.T) { + tmpdir, _ := ioutil.TempDir("", "test") + defer os.RemoveAll(tmpdir) + + db, err := Open(tmpdir, nil, nil, nil) + require.NoError(t, err) + defer db.Close() + + app := db.Appender() + defer app.Rollback() + + ref, err := app.Add(labels.FromStrings("a", "b"), 0, 0) + require.NoError(t, err) + + // Head sequence number should be in 3rd MSB and be greater than 0. + gen := (ref << 16) >> 56 + require.True(t, gen > 1) + + // Reference must be valid to add another sample. + err = app.AddFast(ref, 1, 1) + require.NoError(t, err) + + // AddFast for the same timestamp must fail if the generation in the reference + // doesn't add up. + refBad := ref | ((gen + 1) << 4) + err = app.AddFast(refBad, 1, 1) + require.Error(t, err) + + require.Equal(t, 2, app.(*dbAppender).samples) +}