90 lines
2.9 KiB
Go
90 lines
2.9 KiB
Go
package local
|
|
|
|
import (
|
|
"io"
|
|
|
|
clientmodel "github.com/prometheus/client_golang/model"
|
|
|
|
"github.com/prometheus/prometheus/storage/metric"
|
|
)
|
|
|
|
// chunks is just a chunk slice. No methods are defined for this named type.
|
|
// TODO: Perhaps we should remove it? It might avoid errors if it's
|
|
// syntactically clear that we are dealing with a vanilly slice and not some
|
|
// kind of more complex collection.
|
|
type chunks []chunk
|
|
|
|
// chunk is the interface for all chunks. Chunks are generally not
|
|
// goroutine-safe.
|
|
type chunk interface {
|
|
// add adds a SamplePair to the chunks, performs any necessary
|
|
// re-encoding, and adds any necessary overflow chunks. It returns the
|
|
// new version of the original chunk, followed by overflow chunks, if
|
|
// any. The first chunk returned might be the same as the original one
|
|
// or a newly allocated version. In any case, take the returned chunk as
|
|
// the relevant one and discard the orginal chunk.
|
|
add(*metric.SamplePair) chunks
|
|
clone() chunk
|
|
firstTime() clientmodel.Timestamp
|
|
lastTime() clientmodel.Timestamp
|
|
newIterator() chunkIterator
|
|
marshal(io.Writer) error
|
|
unmarshal(io.Reader) error
|
|
// values returns a channel, from which all sample values in the chunk
|
|
// can be received in order. The channel is closed after the last
|
|
// one. It is generally not safe to mutate the chunk while the channel
|
|
// is still open.
|
|
values() <-chan *metric.SamplePair
|
|
}
|
|
|
|
// A chunkIterator enables efficient access to the content of a chunk. It is
|
|
// generally not safe to use a chunkIterator concurrently with or after chunk
|
|
// mutation.
|
|
type chunkIterator interface {
|
|
// Gets the two values that are immediately adjacent to a given time. In
|
|
// case a value exist at precisely the given time, only that single
|
|
// value is returned. Only the first or last value is returned (as a
|
|
// single value), if the given time is before or after the first or last
|
|
// value, respectively.
|
|
getValueAtTime(clientmodel.Timestamp) metric.Values
|
|
// Gets all values contained within a given interval.
|
|
getRangeValues(metric.Interval) metric.Values
|
|
// Whether a given timestamp is contained between first and last value
|
|
// in the chunk.
|
|
contains(clientmodel.Timestamp) bool
|
|
}
|
|
|
|
func transcodeAndAdd(dst chunk, src chunk, s *metric.SamplePair) chunks {
|
|
numTranscodes.Inc()
|
|
|
|
head := dst
|
|
body := chunks{}
|
|
for v := range src.values() {
|
|
newChunks := head.add(v)
|
|
body = append(body, newChunks[:len(newChunks)-1]...)
|
|
head = newChunks[len(newChunks)-1]
|
|
}
|
|
newChunks := head.add(s)
|
|
body = append(body, newChunks[:len(newChunks)-1]...)
|
|
head = newChunks[len(newChunks)-1]
|
|
return append(body, head)
|
|
}
|
|
|
|
func chunkType(c chunk) byte {
|
|
switch c.(type) {
|
|
case *deltaEncodedChunk:
|
|
return 0
|
|
default:
|
|
panic("unknown chunk type")
|
|
}
|
|
}
|
|
|
|
func chunkForType(chunkType byte) chunk {
|
|
switch chunkType {
|
|
case 0:
|
|
return newDeltaEncodedChunk(d1, d0, true)
|
|
default:
|
|
panic("unknown chunk type")
|
|
}
|
|
}
|