This repository has been archived by the owner on Jul 19, 2023. It is now read-only.
/
chunk.go
102 lines (82 loc) 路 2.32 KB
/
chunk.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
package index
import (
"sort"
"github.com/prometheus/common/model"
)
// Meta holds information about a chunk of data.
type ChunkMeta struct {
Checksum uint32
MinTime, MaxTime int64
// Bytes stored, rounded to nearest KB
KB uint32
SeriesIndex uint32
}
func (c ChunkMeta) From() model.Time { return model.Time(c.MinTime) }
func (c ChunkMeta) Through() model.Time { return model.Time(c.MaxTime) }
func (c ChunkMeta) Bounds() (model.Time, model.Time) { return c.From(), c.Through() }
type ChunkMetas []ChunkMeta
func (c ChunkMetas) Len() int { return len(c) }
func (c ChunkMetas) Swap(i, j int) { c[i], c[j] = c[j], c[i] }
func (c ChunkMetas) Bounds() (mint, maxt model.Time) {
ln := len(c)
if ln == 0 {
return
}
mint, maxt = model.Time(c[0].MinTime), model.Time(c[ln-1].MaxTime)
// even when sorted, we need to check all chunks for maxt
// since we sort by (min, max, checksum). Therefore
// check mint here as well to ensure this works on unordered ChunkMetas too
for _, chk := range c {
from, through := chk.Bounds()
if mint > from {
mint = from
}
if maxt < through {
maxt = through
}
}
return
}
// Sort by (MinTime, MaxTime, Checksum)
func (c ChunkMetas) Less(i, j int) bool {
a, b := c[i], c[j]
if a.MinTime != b.MinTime {
return a.MinTime < b.MinTime
}
if a.MaxTime != b.MaxTime {
return a.MaxTime < b.MaxTime
}
return a.Checksum < b.Checksum
}
// Finalize sorts and dedupes
// TODO(owen-d): can we remove the need for this by ensuring we only push
// in order and without duplicates?
func (c ChunkMetas) Finalize() ChunkMetas {
sort.Sort(c)
if len(c) == 0 {
return c
}
res := ChunkMetasPool.Get()
lastDuplicate := -1
prior := c[0]
// minimize reslicing costs due to duplicates
for i := 1; i < len(c); i++ {
x := c[i]
if x.MinTime == prior.MinTime && x.MaxTime == prior.MaxTime && x.Checksum == prior.Checksum {
res = append(res, c[lastDuplicate+1:i]...)
lastDuplicate = i
}
prior = x
}
// no duplicates were found, short circuit
// by returning unmodified underlying slice
if len(res) == 0 {
ChunkMetasPool.Put(res) // release unused slice to pool
return c
}
// otherwise, append any remaining values
res = append(res, c[lastDuplicate+1:]...)
// release self to pool; res will be returned instead
ChunkMetasPool.Put(c)
return res
}