|
|
|
|
@ -25,6 +25,7 @@ import ( |
|
|
|
|
"path/filepath" |
|
|
|
|
"sort" |
|
|
|
|
"strconv" |
|
|
|
|
"strings" |
|
|
|
|
"sync" |
|
|
|
|
"testing" |
|
|
|
|
"time" |
|
|
|
|
@ -2586,6 +2587,32 @@ func TestChunkSnapshot(t *testing.T) { |
|
|
|
|
require.Equal(t, expExemplars, actExemplars) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
var ( |
|
|
|
|
wlast, woffset int |
|
|
|
|
err error |
|
|
|
|
) |
|
|
|
|
|
|
|
|
|
closeHeadAndCheckSnapshot := func() { |
|
|
|
|
require.NoError(t, head.Close()) |
|
|
|
|
|
|
|
|
|
_, sidx, soffset, err := LastChunkSnapshot(head.opts.ChunkDirRoot) |
|
|
|
|
require.NoError(t, err) |
|
|
|
|
require.Equal(t, wlast, sidx) |
|
|
|
|
require.Equal(t, woffset, soffset) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
openHeadAndCheckReplay := func() { |
|
|
|
|
w, err := wal.NewSize(nil, nil, head.wal.Dir(), 32768, false) |
|
|
|
|
require.NoError(t, err) |
|
|
|
|
head, err = NewHead(nil, nil, w, head.opts, nil) |
|
|
|
|
require.NoError(t, err) |
|
|
|
|
require.NoError(t, head.Init(math.MinInt64)) |
|
|
|
|
|
|
|
|
|
checkSamples() |
|
|
|
|
checkTombstones() |
|
|
|
|
checkExemplars() |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
{ // Initial data that goes into snapshot.
|
|
|
|
|
// Add some initial samples with >=1 m-map chunk.
|
|
|
|
|
app := head.Appender(context.Background()) |
|
|
|
|
@ -2630,31 +2657,16 @@ func TestChunkSnapshot(t *testing.T) { |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// These references should be the ones used for the snapshot.
|
|
|
|
|
wlast, woffset, err := head.wal.LastSegmentAndOffset() |
|
|
|
|
wlast, woffset, err = head.wal.LastSegmentAndOffset() |
|
|
|
|
require.NoError(t, err) |
|
|
|
|
|
|
|
|
|
{ // Creating snapshot and verifying it.
|
|
|
|
|
{ |
|
|
|
|
// Creating snapshot and verifying it.
|
|
|
|
|
head.opts.EnableMemorySnapshotOnShutdown = true |
|
|
|
|
require.NoError(t, head.Close()) // This will create a snapshot.
|
|
|
|
|
|
|
|
|
|
_, sidx, soffset, err := LastChunkSnapshot(head.opts.ChunkDirRoot) |
|
|
|
|
require.NoError(t, err) |
|
|
|
|
require.Equal(t, wlast, sidx) |
|
|
|
|
require.Equal(t, woffset, soffset) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
{ // Test the replay of snapshot.
|
|
|
|
|
// Create new Head which should replay this snapshot.
|
|
|
|
|
w, err := wal.NewSize(nil, nil, head.wal.Dir(), 32768, false) |
|
|
|
|
require.NoError(t, err) |
|
|
|
|
head, err = NewHead(nil, nil, w, head.opts, nil) |
|
|
|
|
require.NoError(t, err) |
|
|
|
|
require.NoError(t, head.Init(math.MinInt64)) |
|
|
|
|
closeHeadAndCheckSnapshot() // This will create a snapshot.
|
|
|
|
|
|
|
|
|
|
// Test query for snapshot replay.
|
|
|
|
|
checkSamples() |
|
|
|
|
checkTombstones() |
|
|
|
|
checkExemplars() |
|
|
|
|
// Test the replay of snapshot.
|
|
|
|
|
openHeadAndCheckReplay() |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
{ // Additional data to only include in WAL and m-mapped chunks and not snapshot. This mimics having an old snapshot on disk.
|
|
|
|
|
@ -2700,30 +2712,42 @@ func TestChunkSnapshot(t *testing.T) { |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
{ // Close Head and verify that new snapshot was not created.
|
|
|
|
|
{ |
|
|
|
|
// Close Head and verify that new snapshot was not created.
|
|
|
|
|
head.opts.EnableMemorySnapshotOnShutdown = false |
|
|
|
|
require.NoError(t, head.Close()) // This should not create a snapshot.
|
|
|
|
|
closeHeadAndCheckSnapshot() // This should not create a snapshot.
|
|
|
|
|
|
|
|
|
|
_, sidx, soffset, err := LastChunkSnapshot(head.opts.ChunkDirRoot) |
|
|
|
|
require.NoError(t, err) |
|
|
|
|
require.Equal(t, wlast, sidx) |
|
|
|
|
require.Equal(t, woffset, soffset) |
|
|
|
|
// Test the replay of snapshot, m-map chunks, and WAL.
|
|
|
|
|
head.opts.EnableMemorySnapshotOnShutdown = true // Enabled to read from snapshot.
|
|
|
|
|
openHeadAndCheckReplay() |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
{ // Test the replay of snapshot, m-map chunks, and WAL.
|
|
|
|
|
// Create new Head to replay snapshot, m-map chunks, and WAL.
|
|
|
|
|
w, err := wal.NewSize(nil, nil, head.wal.Dir(), 32768, false) |
|
|
|
|
require.NoError(t, err) |
|
|
|
|
head.opts.EnableMemorySnapshotOnShutdown = true // Enabled to read from snapshot.
|
|
|
|
|
head, err = NewHead(nil, nil, w, head.opts, nil) |
|
|
|
|
// Creating another snapshot should delete the older snapshot and replay still works fine.
|
|
|
|
|
wlast, woffset, err = head.wal.LastSegmentAndOffset() |
|
|
|
|
require.NoError(t, err) |
|
|
|
|
|
|
|
|
|
{ |
|
|
|
|
// Close Head and verify that new snapshot was created.
|
|
|
|
|
closeHeadAndCheckSnapshot() |
|
|
|
|
|
|
|
|
|
// Verify that there is only 1 snapshot.
|
|
|
|
|
files, err := ioutil.ReadDir(head.opts.ChunkDirRoot) |
|
|
|
|
require.NoError(t, err) |
|
|
|
|
require.NoError(t, head.Init(math.MinInt64)) |
|
|
|
|
snapshots := 0 |
|
|
|
|
for i := len(files) - 1; i >= 0; i-- { |
|
|
|
|
fi := files[i] |
|
|
|
|
if strings.HasPrefix(fi.Name(), chunkSnapshotPrefix) { |
|
|
|
|
snapshots++ |
|
|
|
|
require.Equal(t, chunkSnapshotDir(wlast, woffset), fi.Name()) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
require.Equal(t, 1, snapshots) |
|
|
|
|
|
|
|
|
|
// Test query when data is replayed from snapshot, m-map chunks, and WAL.
|
|
|
|
|
checkSamples() |
|
|
|
|
checkTombstones() |
|
|
|
|
checkExemplars() |
|
|
|
|
// Test the replay of snapshot.
|
|
|
|
|
head.opts.EnableMemorySnapshotOnShutdown = true // Enabled to read from snapshot.
|
|
|
|
|
openHeadAndCheckReplay() |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func TestSnapshotError(t *testing.T) { |
|
|
|
|
|