|
|
|
@ -454,8 +454,9 @@ func TestHeadDeleteSimple(t *testing.T) {
|
|
|
|
|
lblDefault := labels.Label{Name: "a", Value: "b"} |
|
|
|
|
|
|
|
|
|
cases := []struct { |
|
|
|
|
dranges tombstones.Intervals |
|
|
|
|
smplsExp []sample |
|
|
|
|
dranges tombstones.Intervals |
|
|
|
|
addSamples []sample // Samples to add after delete.
|
|
|
|
|
smplsExp []sample |
|
|
|
|
}{ |
|
|
|
|
{ |
|
|
|
|
dranges: tombstones.Intervals{{Mint: 0, Maxt: 3}}, |
|
|
|
@ -477,6 +478,18 @@ func TestHeadDeleteSimple(t *testing.T) {
|
|
|
|
|
dranges: tombstones.Intervals{{Mint: 0, Maxt: 9}}, |
|
|
|
|
smplsExp: buildSmpls([]int64{}), |
|
|
|
|
}, |
|
|
|
|
{ |
|
|
|
|
dranges: tombstones.Intervals{{Mint: 1, Maxt: 3}}, |
|
|
|
|
addSamples: buildSmpls([]int64{11, 13, 15}), |
|
|
|
|
smplsExp: buildSmpls([]int64{0, 4, 5, 6, 7, 8, 9, 11, 13, 15}), |
|
|
|
|
}, |
|
|
|
|
{ |
|
|
|
|
// After delete, the appended samples in the deleted range should be visible
|
|
|
|
|
// as the tombstones are clamped to head min/max time.
|
|
|
|
|
dranges: tombstones.Intervals{{Mint: 7, Maxt: 20}}, |
|
|
|
|
addSamples: buildSmpls([]int64{11, 13, 15}), |
|
|
|
|
smplsExp: buildSmpls([]int64{0, 1, 2, 3, 4, 5, 6, 11, 13, 15}), |
|
|
|
|
}, |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
for _, compress := range []bool{false, true} { |
|
|
|
@ -510,6 +523,15 @@ func TestHeadDeleteSimple(t *testing.T) {
|
|
|
|
|
testutil.Ok(t, head.Delete(r.Mint, r.Maxt, labels.MustNewMatcher(labels.MatchEqual, lblDefault.Name, lblDefault.Value))) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Add more samples.
|
|
|
|
|
app = head.Appender() |
|
|
|
|
for _, smpl := range c.addSamples { |
|
|
|
|
_, err = app.Add(labels.Labels{lblDefault}, smpl.t, smpl.v) |
|
|
|
|
testutil.Ok(t, err) |
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
testutil.Ok(t, app.Commit()) |
|
|
|
|
|
|
|
|
|
// Compare the samples for both heads - before and after the reload.
|
|
|
|
|
reloadedW, err := wal.New(nil, nil, w.Dir(), compress) // Use a new wal to ensure deleted samples are gone even after a reload.
|
|
|
|
|
testutil.Ok(t, err) |
|
|
|
@ -518,37 +540,6 @@ func TestHeadDeleteSimple(t *testing.T) {
|
|
|
|
|
testutil.Ok(t, err) |
|
|
|
|
defer reloadedHead.Close() |
|
|
|
|
testutil.Ok(t, reloadedHead.Init(0)) |
|
|
|
|
for _, h := range []*Head{head, reloadedHead} { |
|
|
|
|
indexr, err := h.Index() |
|
|
|
|
testutil.Ok(t, err) |
|
|
|
|
// Use an emptyTombstoneReader explicitly to get all the samples.
|
|
|
|
|
css, err := LookupChunkSeries(indexr, emptyTombstoneReader, labels.MustNewMatcher(labels.MatchEqual, lblDefault.Name, lblDefault.Value)) |
|
|
|
|
testutil.Ok(t, err) |
|
|
|
|
|
|
|
|
|
// Getting the actual samples.
|
|
|
|
|
actSamples := make([]sample, 0) |
|
|
|
|
for css.Next() { |
|
|
|
|
lblsAct, chkMetas, intv := css.At() |
|
|
|
|
testutil.Equals(t, labels.Labels{lblDefault}, lblsAct) |
|
|
|
|
testutil.Equals(t, 0, len(intv)) |
|
|
|
|
|
|
|
|
|
chunkr, err := h.Chunks() |
|
|
|
|
testutil.Ok(t, err) |
|
|
|
|
var ii chunkenc.Iterator |
|
|
|
|
for _, meta := range chkMetas { |
|
|
|
|
chk, err := chunkr.Chunk(meta.Ref) |
|
|
|
|
testutil.Ok(t, err) |
|
|
|
|
ii = chk.Iterator(ii) |
|
|
|
|
for ii.Next() { |
|
|
|
|
t, v := ii.At() |
|
|
|
|
actSamples = append(actSamples, sample{t: t, v: v}) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
testutil.Ok(t, css.Err()) |
|
|
|
|
testutil.Equals(t, c.smplsExp, actSamples) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Compare the query results for both heads - before and after the reload.
|
|
|
|
|
expSeriesSet := newMockSeriesSet([]Series{ |
|
|
|
@ -567,24 +558,6 @@ func TestHeadDeleteSimple(t *testing.T) {
|
|
|
|
|
actSeriesSet, err := q.Select(labels.MustNewMatcher(labels.MatchEqual, lblDefault.Name, lblDefault.Value)) |
|
|
|
|
testutil.Ok(t, err) |
|
|
|
|
|
|
|
|
|
lns, err := q.LabelNames() |
|
|
|
|
testutil.Ok(t, err) |
|
|
|
|
lvs, err := q.LabelValues(lblDefault.Name) |
|
|
|
|
testutil.Ok(t, err) |
|
|
|
|
// When all samples are deleted we expect that no labels should exist either.
|
|
|
|
|
if len(c.smplsExp) == 0 { |
|
|
|
|
testutil.Equals(t, 0, len(lns)) |
|
|
|
|
testutil.Equals(t, 0, len(lvs)) |
|
|
|
|
testutil.Assert(t, actSeriesSet.Next() == false, "") |
|
|
|
|
testutil.Ok(t, h.Close()) |
|
|
|
|
continue |
|
|
|
|
} else { |
|
|
|
|
testutil.Equals(t, 1, len(lns)) |
|
|
|
|
testutil.Equals(t, 1, len(lvs)) |
|
|
|
|
testutil.Equals(t, lblDefault.Name, lns[0]) |
|
|
|
|
testutil.Equals(t, lblDefault.Value, lvs[0]) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
for { |
|
|
|
|
eok, rok := expSeriesSet.Next(), actSeriesSet.Next() |
|
|
|
|
testutil.Equals(t, eok, rok) |
|
|
|
@ -625,12 +598,15 @@ func TestDeleteUntilCurMax(t *testing.T) {
|
|
|
|
|
testutil.Ok(t, app.Commit()) |
|
|
|
|
testutil.Ok(t, hb.Delete(0, 10000, labels.MustNewMatcher(labels.MatchEqual, "a", "b"))) |
|
|
|
|
|
|
|
|
|
// Test the series have been deleted.
|
|
|
|
|
// Test the series returns no samples. The series is cleared only after compaction.
|
|
|
|
|
q, err := NewBlockQuerier(hb, 0, 100000) |
|
|
|
|
testutil.Ok(t, err) |
|
|
|
|
res, err := q.Select(labels.MustNewMatcher(labels.MatchEqual, "a", "b")) |
|
|
|
|
testutil.Ok(t, err) |
|
|
|
|
testutil.Assert(t, !res.Next(), "series didn't get deleted") |
|
|
|
|
testutil.Assert(t, res.Next(), "series is not present") |
|
|
|
|
s := res.At() |
|
|
|
|
it := s.Iterator() |
|
|
|
|
testutil.Assert(t, !it.Next(), "expected no samples") |
|
|
|
|
|
|
|
|
|
// Add again and test for presence.
|
|
|
|
|
app = hb.Appender() |
|
|
|
@ -643,7 +619,7 @@ func TestDeleteUntilCurMax(t *testing.T) {
|
|
|
|
|
testutil.Ok(t, err) |
|
|
|
|
testutil.Assert(t, res.Next(), "series don't exist") |
|
|
|
|
exps := res.At() |
|
|
|
|
it := exps.Iterator() |
|
|
|
|
it = exps.Iterator() |
|
|
|
|
resSamples, err := expandSeriesIterator(it) |
|
|
|
|
testutil.Ok(t, err) |
|
|
|
|
testutil.Equals(t, []tsdbutil.Sample{sample{11, 1}}, resSamples) |
|
|
|
|