mirror of
https://github.com/opencloud-eu/opencloud.git
synced 2026-08-04 03:44:55 -04:00
build(deps): bump github.com/prometheus/client_golang
Bumps [github.com/prometheus/client_golang](https://github.com/prometheus/client_golang) from 1.23.2 to 1.24.1. - [Release notes](https://github.com/prometheus/client_golang/releases) - [Changelog](https://github.com/prometheus/client_golang/blob/v1.24.1/CHANGELOG.md) - [Commits](https://github.com/prometheus/client_golang/compare/v1.23.2...v1.24.1) --- updated-dependencies: - dependency-name: github.com/prometheus/client_golang dependency-version: 1.24.1 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com>
This commit is contained in:
committed by
Ralf Haferkamp
parent
639e3657cd
commit
7c2cb14a80
8
go.mod
8
go.mod
@@ -69,7 +69,7 @@ require (
|
||||
github.com/orcaman/concurrent-map v1.0.0
|
||||
github.com/pkg/errors v0.9.1
|
||||
github.com/pkg/xattr v0.4.12
|
||||
github.com/prometheus/client_golang v1.23.2
|
||||
github.com/prometheus/client_golang v1.24.1
|
||||
github.com/r3labs/sse/v2 v2.10.0
|
||||
github.com/riandyrn/otelchi v0.12.3
|
||||
github.com/rogpeppe/go-internal v1.15.0
|
||||
@@ -255,7 +255,7 @@ require (
|
||||
github.com/json-iterator/go v1.1.12 // indirect
|
||||
github.com/juliangruber/go-intersect v1.1.0 // indirect
|
||||
github.com/kevinburke/ssh_config v1.2.0 // indirect
|
||||
github.com/klauspost/compress v1.18.6 // indirect
|
||||
github.com/klauspost/compress v1.19.1 // indirect
|
||||
github.com/klauspost/cpuid/v2 v2.3.0 // indirect
|
||||
github.com/klauspost/crc32 v1.3.0 // indirect
|
||||
github.com/kovidgoyal/go-parallel v1.1.1 // indirect
|
||||
@@ -325,8 +325,8 @@ require (
|
||||
github.com/pquerna/cachecontrol v0.2.0 // indirect
|
||||
github.com/prometheus/alertmanager v0.33.1 // indirect
|
||||
github.com/prometheus/client_model v0.6.2 // indirect
|
||||
github.com/prometheus/common v0.67.5 // indirect
|
||||
github.com/prometheus/procfs v0.20.1 // indirect
|
||||
github.com/prometheus/common v0.70.1 // indirect
|
||||
github.com/prometheus/procfs v0.21.1 // indirect
|
||||
github.com/prometheus/statsd_exporter v0.22.8 // indirect
|
||||
github.com/rcrowley/go-metrics v0.0.0-20250401214520-65e299d6c5c9 // indirect
|
||||
github.com/rs/xid v1.6.0 // indirect
|
||||
|
||||
16
go.sum
16
go.sum
@@ -715,8 +715,8 @@ github.com/kevinburke/ssh_config v1.2.0/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF
|
||||
github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
|
||||
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
|
||||
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
||||
github.com/klauspost/compress v1.18.6 h1:2jupLlAwFm95+YDR+NwD2MEfFO9d4z4Prjl1XXDjuao=
|
||||
github.com/klauspost/compress v1.18.6/go.mod h1:cwPg85FWrGar70rWktvGQj8/hthj3wpl0PGDogxkrSQ=
|
||||
github.com/klauspost/compress v1.19.1 h1:VsB4HPswih7mmZ8WleSFQ75c/Ui1M4trX5oAsJnhSlk=
|
||||
github.com/klauspost/compress v1.19.1/go.mod h1:cwPg85FWrGar70rWktvGQj8/hthj3wpl0PGDogxkrSQ=
|
||||
github.com/klauspost/cpuid/v2 v2.0.1/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
|
||||
github.com/klauspost/cpuid/v2 v2.3.0 h1:S4CRMLnYUhGeDFDqkGriYKdfoFlDnMtqTiI/sFzhA9Y=
|
||||
github.com/klauspost/cpuid/v2 v2.3.0/go.mod h1:hqwkgyIinND0mEev00jJYCxPNVRVXFQeu1XKlok6oO0=
|
||||
@@ -1016,8 +1016,8 @@ github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqr
|
||||
github.com/prometheus/client_golang v1.12.1/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY=
|
||||
github.com/prometheus/client_golang v1.12.2/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY=
|
||||
github.com/prometheus/client_golang v1.13.0/go.mod h1:vTeo+zgvILHsnnj/39Ou/1fPN5nJFOEMgftOUOmlvYQ=
|
||||
github.com/prometheus/client_golang v1.23.2 h1:Je96obch5RDVy3FDMndoUsjAhG5Edi49h0RJWRi/o0o=
|
||||
github.com/prometheus/client_golang v1.23.2/go.mod h1:Tb1a6LWHB3/SPIzCoaDXI4I8UHKeFTEQ1YCr+0Gyqmg=
|
||||
github.com/prometheus/client_golang v1.24.1 h1:JnJkREXzWxUdCuPFpIWZiPispT9xVV59uiuyR2bPlnU=
|
||||
github.com/prometheus/client_golang v1.24.1/go.mod h1:F+oSRECHg4sse5ucfYpYDeIv/hu68Zo0uoHKetWnzcE=
|
||||
github.com/prometheus/client_model v0.0.0-20170216185247-6f3806018612/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
|
||||
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
|
||||
github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
|
||||
@@ -1037,8 +1037,8 @@ github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9
|
||||
github.com/prometheus/common v0.32.1/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls=
|
||||
github.com/prometheus/common v0.35.0/go.mod h1:phzohg0JFMnBEFGxTDbfu3QyL5GI8gTQJFhYO5B3mfA=
|
||||
github.com/prometheus/common v0.37.0/go.mod h1:phzohg0JFMnBEFGxTDbfu3QyL5GI8gTQJFhYO5B3mfA=
|
||||
github.com/prometheus/common v0.67.5 h1:pIgK94WWlQt1WLwAC5j2ynLaBRDiinoAb86HZHTUGI4=
|
||||
github.com/prometheus/common v0.67.5/go.mod h1:SjE/0MzDEEAyrdr5Gqc6G+sXI67maCxzaT3A2+HqjUw=
|
||||
github.com/prometheus/common v0.70.1 h1:1HvjP4D5oL3t8RsPlwxA9onvvStjtIHYE5XuuwOi/PY=
|
||||
github.com/prometheus/common v0.70.1/go.mod h1:VdFUQDMZK3VLkurFUVhia6uys/0suUp86TJz5qbJRhc=
|
||||
github.com/prometheus/procfs v0.0.0-20170703101242-e645f4e5aaa8/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
|
||||
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
|
||||
github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
|
||||
@@ -1049,8 +1049,8 @@ github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4O
|
||||
github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA=
|
||||
github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA=
|
||||
github.com/prometheus/procfs v0.8.0/go.mod h1:z7EfXMXOkbkqb9IINtpCn86r/to3BnA0uaxHdg830/4=
|
||||
github.com/prometheus/procfs v0.20.1 h1:XwbrGOIplXW/AU3YhIhLODXMJYyC1isLFfYCsTEycfc=
|
||||
github.com/prometheus/procfs v0.20.1/go.mod h1:o9EMBZGRyvDrSPH1RqdxhojkuXstoe4UlK79eF5TGGo=
|
||||
github.com/prometheus/procfs v0.21.1 h1:GljZCt+zSTS+NZq88cyQ1LjZ+RCHp3uVuabBWA5+OJI=
|
||||
github.com/prometheus/procfs v0.21.1/go.mod h1:aB55Cww9pdSJVHk0hUf0inxWyyjPogFIjmHKYgMKmtY=
|
||||
github.com/prometheus/statsd_exporter v0.22.7/go.mod h1:N/TevpjkIh9ccs6nuzY3jQn9dFqnUakOjnEuMPJJJnI=
|
||||
github.com/prometheus/statsd_exporter v0.22.8 h1:Qo2D9ZzaQG+id9i5NYNGmbf1aa/KxKbB9aKfMS+Yib0=
|
||||
github.com/prometheus/statsd_exporter v0.22.8/go.mod h1:/DzwbTEaFTE0Ojz5PqcSk6+PFHOPWGxdXVr6yC8eFOM=
|
||||
|
||||
12
vendor/github.com/klauspost/compress/README.md
generated
vendored
12
vendor/github.com/klauspost/compress/README.md
generated
vendored
@@ -27,6 +27,18 @@ Use the links above for more information on each.
|
||||
|
||||
# changelog
|
||||
|
||||
* Jul 1st, 2026 [1.19.0](https://github.com/klauspost/compress/releases/tag/v1.19.0)
|
||||
* zstd: Add true concurrent stream encodingin https://github.com/klauspost/compress/pull/1136
|
||||
* zstd: arm64 decoder asm by @lizthegrey in https://github.com/klauspost/compress/pull/1160
|
||||
* flate: Add inflate checkpoints in https://github.com/klauspost/compress/pull/1154
|
||||
* zstd: avoid unused BuildDict encoder allocation by @snissn in https://github.com/klauspost/compress/pull/1147
|
||||
* snappy/s2: Limit length of varint in `decodedLen` by @eustas in https://github.com/klauspost/compress/pull/1148
|
||||
* gzhttp: match qvalue parameter case-insensitively (RFC 7231) by @z9z in https://github.com/klauspost/compress/pull/1149
|
||||
* zip: add NameDecoder callback for legacy encoding rewrite by @SAY-5 in https://github.com/klauspost/compress/pull/1150
|
||||
* huff0: Allow building tables from histogram in https://github.com/klauspost/compress/pull/1155
|
||||
* huff0: Allow building table from oversized histogram in https://github.com/klauspost/compress/pull/1156
|
||||
* s2sx: Clean symlink targets in https://github.com/klauspost/compress/pull/1163
|
||||
|
||||
* Feb 9th, 2026 [1.18.4](https://github.com/klauspost/compress/releases/tag/v1.18.4)
|
||||
* gzhttp: Add zstandard to server handler wrapper https://github.com/klauspost/compress/pull/1121
|
||||
* zstd: Add ResetWithOptions to encoder/decoder https://github.com/klauspost/compress/pull/1122
|
||||
|
||||
24
vendor/github.com/klauspost/compress/flate/dict_decoder.go
generated
vendored
24
vendor/github.com/klauspost/compress/flate/dict_decoder.go
generated
vendored
@@ -28,9 +28,10 @@ type dictDecoder struct {
|
||||
hist []byte // Sliding window history
|
||||
|
||||
// Invariant: 0 <= rdPos <= wrPos <= len(hist)
|
||||
wrPos int // Current output position in buffer
|
||||
rdPos int // Have emitted hist[:rdPos] already
|
||||
full bool // Has a full window length been written yet?
|
||||
wrPos int // Current output position in buffer
|
||||
rdPos int // Have emitted hist[:rdPos] already
|
||||
flushed int64 // Total bytes returned by readFlush since init
|
||||
full bool // Has a full window length been written yet?
|
||||
}
|
||||
|
||||
// init initializes dictDecoder to have a sliding window dictionary of the given
|
||||
@@ -167,11 +168,22 @@ loop:
|
||||
return dstPos - dstBase
|
||||
}
|
||||
|
||||
// appendWindow appends the current sliding window (up to len(hist) most recent
|
||||
// bytes, oldest first) to dst.
|
||||
func (dd *dictDecoder) appendWindow(dst []byte) []byte {
|
||||
if dd.full {
|
||||
dst = append(dst, dd.hist[dd.wrPos:]...)
|
||||
return append(dst, dd.hist[:dd.wrPos]...)
|
||||
}
|
||||
return append(dst, dd.hist[:dd.wrPos]...)
|
||||
}
|
||||
|
||||
// readFlush returns a slice of the historical buffer that is ready to be
|
||||
// emitted to the user. The data returned by readFlush must be fully consumed
|
||||
// before calling any other dictDecoder methods.
|
||||
func (dd *dictDecoder) readFlush() []byte {
|
||||
toRead := dd.hist[dd.rdPos:dd.wrPos]
|
||||
dd.flushed += int64(len(toRead))
|
||||
dd.rdPos = dd.wrPos
|
||||
if dd.wrPos == len(dd.hist) {
|
||||
dd.wrPos, dd.rdPos = 0, 0
|
||||
@@ -179,3 +191,9 @@ func (dd *dictDecoder) readFlush() []byte {
|
||||
}
|
||||
return toRead
|
||||
}
|
||||
|
||||
// decoded reports the total number of bytes written into the dictionary since
|
||||
// init (i.e. excluding any preset dict bytes).
|
||||
func (dd *dictDecoder) decoded() int64 {
|
||||
return dd.flushed + int64(dd.wrPos-dd.rdPos)
|
||||
}
|
||||
|
||||
92
vendor/github.com/klauspost/compress/flate/inflate.go
generated
vendored
92
vendor/github.com/klauspost/compress/flate/inflate.go
generated
vendored
@@ -342,6 +342,11 @@ type decompressor struct {
|
||||
final bool
|
||||
|
||||
flushMode flushMode
|
||||
cb func(InflateCheckpoint)
|
||||
cp InflateCheckpoint
|
||||
hasCP bool // WithResumeFrom was supplied
|
||||
uncOffset int64 // baseline uncompressed offset (from a resume checkpoint)
|
||||
cpBuf []byte
|
||||
}
|
||||
|
||||
func (f *decompressor) nextBlock() {
|
||||
@@ -676,6 +681,18 @@ func (f *decompressor) finishBlock() {
|
||||
f.toRead = f.dict.readFlush()
|
||||
}
|
||||
|
||||
if f.cb != nil {
|
||||
bitPos := f.roffset*8 - int64(f.nb)
|
||||
f.cpBuf = f.dict.appendWindow(f.cpBuf[:0])
|
||||
f.cb(InflateCheckpoint{
|
||||
UncompressedOffset: f.uncOffset + f.dict.decoded(),
|
||||
CompressedOffset: bitPos / 8,
|
||||
Final: f.final,
|
||||
BitOffset: uint8(bitPos & 7),
|
||||
Window: f.cpBuf,
|
||||
})
|
||||
}
|
||||
|
||||
f.step = nextBlock
|
||||
}
|
||||
|
||||
@@ -806,6 +823,45 @@ func (f *decompressor) Reset(r io.Reader, dict []byte) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// ResetCP will adjust the input to the provided checkpoint.
|
||||
// It is assumed the input stream is forwarded to cp.CompressedOffset.
|
||||
func (f *decompressor) ResetCP(r io.Reader, cp InflateCheckpoint) error {
|
||||
*f = decompressor{
|
||||
r: makeReader(r),
|
||||
bits: f.bits,
|
||||
codebits: f.codebits,
|
||||
h1: f.h1,
|
||||
h2: f.h2,
|
||||
dict: f.dict,
|
||||
step: nextBlock,
|
||||
cpBuf: f.cpBuf,
|
||||
}
|
||||
return f.applyCP(cp)
|
||||
}
|
||||
|
||||
// applyCP seeds the decompressor state from a resume checkpoint:
|
||||
// loads the sliding window, sets the absolute compressed/uncompressed
|
||||
// offsets, and skips cp.BitOffset bits into the first input byte so
|
||||
// the next decode aligns with the start of a deflate block.
|
||||
func (f *decompressor) applyCP(cp InflateCheckpoint) error {
|
||||
f.dict.init(maxMatchOffset, cp.Window)
|
||||
f.roffset = cp.CompressedOffset
|
||||
f.uncOffset = cp.UncompressedOffset
|
||||
f.final = cp.Final
|
||||
f.b = 0
|
||||
f.nb = 0
|
||||
if cp.BitOffset > 0 {
|
||||
c, err := f.r.ReadByte()
|
||||
if err != nil {
|
||||
return noEOF(err)
|
||||
}
|
||||
f.roffset++
|
||||
f.b = uint32(c) >> cp.BitOffset
|
||||
f.nb = 8 - uint(cp.BitOffset)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type ReaderOpt func(*decompressor)
|
||||
|
||||
// WithPartialBlock tells decompressor to return after each block,
|
||||
@@ -823,6 +879,36 @@ func WithDict(dict []byte) ReaderOpt {
|
||||
}
|
||||
}
|
||||
|
||||
// InflateCheckpoint provides a resumable checkpoint for inflate.
|
||||
type InflateCheckpoint struct {
|
||||
UncompressedOffset int64 // Byte offset in the decompressed stream
|
||||
CompressedOffset int64 // Byte offset in the compressed stream
|
||||
Final bool // True if this is the final block
|
||||
BitOffset uint8 // 0-7 bits
|
||||
Window []byte // 32KB sliding window dictionary
|
||||
}
|
||||
|
||||
// WithEobCallback will call the provided function after each block
|
||||
// with the current gzip checkpoint.
|
||||
// After returning the provided window can no longer be referenced.
|
||||
// The callback will not be triggered after a block is marked "final".
|
||||
// The callback is not retained after Reset.
|
||||
func WithEobCallback(cb func(InflateCheckpoint)) ReaderOpt {
|
||||
return func(f *decompressor) {
|
||||
f.cb = cb
|
||||
}
|
||||
}
|
||||
|
||||
// WithResumeFrom will adjust the input to the provided checkpoint.
|
||||
// It is assumed the input stream is forwarded to the provided offset.
|
||||
// The checkpoint is removed when Reset is called.
|
||||
func WithResumeFrom(cp InflateCheckpoint) ReaderOpt {
|
||||
return func(f *decompressor) {
|
||||
f.cp = cp
|
||||
f.hasCP = true
|
||||
}
|
||||
}
|
||||
|
||||
// NewReaderOpts returns new reader with provided options
|
||||
func NewReaderOpts(r io.Reader, opts ...ReaderOpt) io.ReadCloser {
|
||||
fixedHuffmanDecoderInit()
|
||||
@@ -838,6 +924,12 @@ func NewReaderOpts(r io.Reader, opts ...ReaderOpt) io.ReadCloser {
|
||||
opt(&f)
|
||||
}
|
||||
|
||||
if f.hasCP {
|
||||
if err := f.applyCP(f.cp); err != nil {
|
||||
f.err = err
|
||||
}
|
||||
}
|
||||
|
||||
return &f
|
||||
}
|
||||
|
||||
|
||||
116
vendor/github.com/klauspost/compress/flate/inflate_gen.go
generated
vendored
116
vendor/github.com/klauspost/compress/flate/inflate_gen.go
generated
vendored
@@ -10,6 +10,15 @@ import (
|
||||
"strings"
|
||||
)
|
||||
|
||||
func peekBufio(fr *bufio.Reader) ([]byte, error) {
|
||||
if fr.Buffered() == 0 {
|
||||
if _, err := fr.Peek(1); err != nil && fr.Buffered() == 0 {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return fr.Peek(fr.Buffered())
|
||||
}
|
||||
|
||||
// Decode a single Huffman block from f.
|
||||
// hl and hd are the Huffman states for the lit/length values
|
||||
// and the distance values, respectively. If hd == nil, using the
|
||||
@@ -527,6 +536,8 @@ func (f *decompressor) huffmanBufioReader() {
|
||||
// but is smart enough to keep local variables in registers, so use nb and b,
|
||||
// inline call to moreBits and reassign b,nb back to f on return.
|
||||
fnb, fb, dict := f.nb, f.b, &f.dict
|
||||
pbuf, _ := fr.Peek(fr.Buffered())
|
||||
pos := 0
|
||||
|
||||
switch f.stepState {
|
||||
case stateInit:
|
||||
@@ -548,12 +559,19 @@ readLiteral:
|
||||
n := uint(f.hl.maxRead)
|
||||
for {
|
||||
for fnb < n {
|
||||
c, err := fr.ReadByte()
|
||||
if err != nil {
|
||||
f.b, f.nb = fb, fnb
|
||||
f.err = noEOF(err)
|
||||
return
|
||||
if pos >= len(pbuf) {
|
||||
fr.Discard(pos)
|
||||
var err error
|
||||
pbuf, err = peekBufio(fr)
|
||||
pos = 0
|
||||
if len(pbuf) == 0 {
|
||||
f.b, f.nb = fb, fnb
|
||||
f.err = noEOF(err)
|
||||
return
|
||||
}
|
||||
}
|
||||
c := pbuf[pos]
|
||||
pos++
|
||||
f.roffset++
|
||||
fb |= uint32(c) << (fnb & regSizeMaskUint32)
|
||||
fnb += 8
|
||||
@@ -566,6 +584,7 @@ readLiteral:
|
||||
}
|
||||
if n <= fnb {
|
||||
if n == 0 {
|
||||
fr.Discard(pos)
|
||||
f.b, f.nb = fb, fnb
|
||||
if debugDecode {
|
||||
fmt.Println("huffsym: n==0")
|
||||
@@ -586,6 +605,7 @@ readLiteral:
|
||||
case v < 256:
|
||||
dict.writeByte(byte(v))
|
||||
if dict.availWrite() == 0 {
|
||||
fr.Discard(pos)
|
||||
f.toRead = dict.readFlush()
|
||||
f.step = huffmanBufioReader
|
||||
f.stepState = stateInit
|
||||
@@ -594,6 +614,7 @@ readLiteral:
|
||||
}
|
||||
goto readLiteral
|
||||
case v == 256:
|
||||
fr.Discard(pos)
|
||||
f.b, f.nb = fb, fnb
|
||||
f.finishBlock()
|
||||
return
|
||||
@@ -605,15 +626,22 @@ readLiteral:
|
||||
length = int(val.length) + 3
|
||||
n := uint(val.extra)
|
||||
for fnb < n {
|
||||
c, err := fr.ReadByte()
|
||||
if err != nil {
|
||||
f.b, f.nb = fb, fnb
|
||||
if debugDecode {
|
||||
fmt.Println("morebits n>0:", err)
|
||||
if pos >= len(pbuf) {
|
||||
fr.Discard(pos)
|
||||
var err error
|
||||
pbuf, err = peekBufio(fr)
|
||||
pos = 0
|
||||
if len(pbuf) == 0 {
|
||||
f.b, f.nb = fb, fnb
|
||||
if debugDecode {
|
||||
fmt.Println("morebits n>0:", err)
|
||||
}
|
||||
f.err = err
|
||||
return
|
||||
}
|
||||
f.err = err
|
||||
return
|
||||
}
|
||||
c := pbuf[pos]
|
||||
pos++
|
||||
f.roffset++
|
||||
fb |= uint32(c) << (fnb & regSizeMaskUint32)
|
||||
fnb += 8
|
||||
@@ -622,6 +650,7 @@ readLiteral:
|
||||
fb >>= n & regSizeMaskUint32
|
||||
fnb -= n
|
||||
default:
|
||||
fr.Discard(pos)
|
||||
if debugDecode {
|
||||
fmt.Println(v, ">= maxNumLit")
|
||||
}
|
||||
@@ -633,15 +662,22 @@ readLiteral:
|
||||
var dist uint32
|
||||
if f.hd == nil {
|
||||
for fnb < 5 {
|
||||
c, err := fr.ReadByte()
|
||||
if err != nil {
|
||||
f.b, f.nb = fb, fnb
|
||||
if debugDecode {
|
||||
fmt.Println("morebits f.nb<5:", err)
|
||||
if pos >= len(pbuf) {
|
||||
fr.Discard(pos)
|
||||
var err error
|
||||
pbuf, err = peekBufio(fr)
|
||||
pos = 0
|
||||
if len(pbuf) == 0 {
|
||||
f.b, f.nb = fb, fnb
|
||||
if debugDecode {
|
||||
fmt.Println("morebits f.nb<5:", err)
|
||||
}
|
||||
f.err = err
|
||||
return
|
||||
}
|
||||
f.err = err
|
||||
return
|
||||
}
|
||||
c := pbuf[pos]
|
||||
pos++
|
||||
f.roffset++
|
||||
fb |= uint32(c) << (fnb & regSizeMaskUint32)
|
||||
fnb += 8
|
||||
@@ -660,12 +696,19 @@ readLiteral:
|
||||
// inline call to moreBits and reassign b,nb back to f on return.
|
||||
for {
|
||||
for fnb < n {
|
||||
c, err := fr.ReadByte()
|
||||
if err != nil {
|
||||
f.b, f.nb = fb, fnb
|
||||
f.err = noEOF(err)
|
||||
return
|
||||
if pos >= len(pbuf) {
|
||||
fr.Discard(pos)
|
||||
var err error
|
||||
pbuf, err = peekBufio(fr)
|
||||
pos = 0
|
||||
if len(pbuf) == 0 {
|
||||
f.b, f.nb = fb, fnb
|
||||
f.err = noEOF(err)
|
||||
return
|
||||
}
|
||||
}
|
||||
c := pbuf[pos]
|
||||
pos++
|
||||
f.roffset++
|
||||
fb |= uint32(c) << (fnb & regSizeMaskUint32)
|
||||
fnb += 8
|
||||
@@ -678,6 +721,7 @@ readLiteral:
|
||||
}
|
||||
if n <= fnb {
|
||||
if n == 0 {
|
||||
fr.Discard(pos)
|
||||
f.b, f.nb = fb, fnb
|
||||
if debugDecode {
|
||||
fmt.Println("huffsym: n==0")
|
||||
@@ -701,15 +745,22 @@ readLiteral:
|
||||
// have 1 bit in bottom of dist, need nb more.
|
||||
extra := (dist & 1) << (nb & regSizeMaskUint32)
|
||||
for fnb < nb {
|
||||
c, err := fr.ReadByte()
|
||||
if err != nil {
|
||||
f.b, f.nb = fb, fnb
|
||||
if debugDecode {
|
||||
fmt.Println("morebits f.nb<nb:", err)
|
||||
if pos >= len(pbuf) {
|
||||
fr.Discard(pos)
|
||||
var err error
|
||||
pbuf, err = peekBufio(fr)
|
||||
pos = 0
|
||||
if len(pbuf) == 0 {
|
||||
f.b, f.nb = fb, fnb
|
||||
if debugDecode {
|
||||
fmt.Println("morebits f.nb<nb:", err)
|
||||
}
|
||||
f.err = err
|
||||
return
|
||||
}
|
||||
f.err = err
|
||||
return
|
||||
}
|
||||
c := pbuf[pos]
|
||||
pos++
|
||||
f.roffset++
|
||||
fb |= uint32(c) << (fnb & regSizeMaskUint32)
|
||||
fnb += 8
|
||||
@@ -720,6 +771,7 @@ readLiteral:
|
||||
dist = 1<<((nb+1)®SizeMaskUint32) + 1 + extra
|
||||
// slower: dist = bitMask32[nb+1] + 2 + extra
|
||||
default:
|
||||
fr.Discard(pos)
|
||||
f.b, f.nb = fb, fnb
|
||||
if debugDecode {
|
||||
fmt.Println("dist too big:", dist, maxNumDist)
|
||||
@@ -730,6 +782,7 @@ readLiteral:
|
||||
|
||||
// No check on length; encoding can be prescient.
|
||||
if dist > uint32(dict.histSize()) {
|
||||
fr.Discard(pos)
|
||||
f.b, f.nb = fb, fnb
|
||||
if debugDecode {
|
||||
fmt.Println("dist > dict.histSize():", dist, dict.histSize())
|
||||
@@ -752,6 +805,7 @@ copyHistory:
|
||||
f.copyLen -= cnt
|
||||
|
||||
if dict.availWrite() == 0 || f.copyLen > 0 {
|
||||
fr.Discard(pos)
|
||||
f.toRead = dict.readFlush()
|
||||
f.step = huffmanBufioReader // We need to continue this work
|
||||
f.stepState = stateDict
|
||||
|
||||
168
vendor/github.com/klauspost/compress/huff0/build_table.go
generated
vendored
Normal file
168
vendor/github.com/klauspost/compress/huff0/build_table.go
generated
vendored
Normal file
@@ -0,0 +1,168 @@
|
||||
package huff0
|
||||
|
||||
import "errors"
|
||||
|
||||
// BuildCTable builds a Huffman compression table from a precomputed symbol
|
||||
// histogram and installs it as the previous (reuse) table on s.
|
||||
//
|
||||
// After this call:
|
||||
// - EstimateSize/CanUseTable can probe the table against other histograms.
|
||||
// - Compress1X/Compress4X with Reuse = ReusePolicyMust will encode without
|
||||
// emitting a new table header.
|
||||
// - TransferCTable can hand the table to a sibling Scratch.
|
||||
//
|
||||
// count[i] is the number of occurrences of symbol i. The histogram must have
|
||||
// at least 2 distinct non-zero symbols; ErrUseRLE is returned for a single
|
||||
// symbol and an error is returned for an empty histogram.
|
||||
func (s *Scratch) BuildCTable(count *[256]uint32) error {
|
||||
if s == nil {
|
||||
return errors.New("huff0: BuildCTable on nil Scratch")
|
||||
}
|
||||
if count == nil {
|
||||
return errors.New("huff0: nil count passed to BuildCTable")
|
||||
}
|
||||
var err error
|
||||
s, err = s.prepare(nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
s.count = *count
|
||||
var total, maxCount int
|
||||
var symLen uint16
|
||||
for i, v := range s.count {
|
||||
total += int(v)
|
||||
if int(v) > maxCount {
|
||||
maxCount = int(v)
|
||||
}
|
||||
if v != 0 {
|
||||
symLen = uint16(i) + 1
|
||||
}
|
||||
}
|
||||
if total == 0 {
|
||||
return errors.New("huff0: empty histogram")
|
||||
}
|
||||
if symLen < 2 || maxCount == total {
|
||||
return ErrUseRLE
|
||||
}
|
||||
// huff0's internal rank table assumes total ≤ BlockSizeMax (it uses
|
||||
// highBit32(count+1) + 1 as a rank index into a fixed-size array).
|
||||
// Histograms summed across multiple blocks can exceed that; scale the
|
||||
// counts down preserving the distribution. Non-zero entries round up so
|
||||
// rare symbols stay representable.
|
||||
if total > BlockSizeMax {
|
||||
shift := uint(0)
|
||||
for total>>shift > BlockSizeMax {
|
||||
shift++
|
||||
}
|
||||
round := uint32(1<<shift) - 1
|
||||
var newTotal, newMax int
|
||||
for i, v := range s.count {
|
||||
if v == 0 {
|
||||
continue
|
||||
}
|
||||
scaled := (v + round) >> shift
|
||||
if scaled == 0 {
|
||||
scaled = 1
|
||||
}
|
||||
s.count[i] = scaled
|
||||
newTotal += int(scaled)
|
||||
if int(scaled) > newMax {
|
||||
newMax = int(scaled)
|
||||
}
|
||||
}
|
||||
total = newTotal
|
||||
maxCount = newMax
|
||||
if maxCount == total {
|
||||
return ErrUseRLE
|
||||
}
|
||||
}
|
||||
s.symbolLen = symLen
|
||||
s.maxCount = maxCount
|
||||
s.srcLen = total
|
||||
if err := s.buildCTable(); err != nil {
|
||||
return err
|
||||
}
|
||||
if cap(s.prevTable) < len(s.cTable) {
|
||||
s.prevTable = make(cTable, 0, maxSymbolValue+1)
|
||||
}
|
||||
s.prevTable = s.prevTable[:len(s.cTable)]
|
||||
copy(s.prevTable, s.cTable)
|
||||
s.prevTableLog = s.actualTableLog
|
||||
// Force the next Compress* to recount from real input.
|
||||
s.clearCount = true
|
||||
s.maxCount = 0
|
||||
return nil
|
||||
}
|
||||
|
||||
// EstimateSize returns an estimated compressed payload size in bytes for the
|
||||
// supplied histogram using the table currently stored in prevTable. It returns
|
||||
// -1 when the table cannot encode every non-zero symbol of hist (i.e. when
|
||||
// CanUseTable would return false). The estimate excludes the table header.
|
||||
func (s *Scratch) EstimateSize(hist *[256]uint32) int {
|
||||
if s == nil || hist == nil || len(s.prevTable) == 0 {
|
||||
return -1
|
||||
}
|
||||
pt := s.prevTable
|
||||
nbBits := uint32(7)
|
||||
for i, v := range hist {
|
||||
if v == 0 {
|
||||
continue
|
||||
}
|
||||
if i >= len(pt) || pt[i].nBits == 0 {
|
||||
return -1
|
||||
}
|
||||
nbBits += uint32(pt[i].nBits) * v
|
||||
}
|
||||
return int(nbBits >> 3)
|
||||
}
|
||||
|
||||
// CanUseTable reports whether the table in prevTable can encode every
|
||||
// non-zero symbol present in hist.
|
||||
func (s *Scratch) CanUseTable(hist *[256]uint32) bool {
|
||||
if s == nil || hist == nil || len(s.prevTable) == 0 {
|
||||
return false
|
||||
}
|
||||
pt := s.prevTable
|
||||
for i, v := range hist {
|
||||
if v == 0 {
|
||||
continue
|
||||
}
|
||||
if i >= len(pt) || pt[i].nBits == 0 {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// AppendTable serializes the table currently stored in prevTable (e.g. as
|
||||
// installed by BuildCTable or carried over from a previous Compress call)
|
||||
// into a self-delimiting zstd-style header and appends it to dst. The
|
||||
// returned slice can be parsed back by ReadTable.
|
||||
func (s *Scratch) AppendTable(dst []byte) ([]byte, error) {
|
||||
if s == nil || len(s.prevTable) == 0 {
|
||||
return dst, errors.New("huff0: AppendTable with empty table")
|
||||
}
|
||||
// cTable.write reads s.actualTableLog, s.symbolLen, s.huffWeight, s.fse
|
||||
// and writes into s.Out. Save/restore Out so we don't disturb in-flight
|
||||
// compression buffers.
|
||||
saveOut := s.Out
|
||||
saveTL := s.actualTableLog
|
||||
saveSL := s.symbolLen
|
||||
if s.fse == nil {
|
||||
// Lazily init in case AppendTable is called on a fresh Scratch.
|
||||
if _, err := s.prepare(nil); err != nil {
|
||||
return dst, err
|
||||
}
|
||||
saveOut = s.Out
|
||||
}
|
||||
s.Out = s.Out[:0]
|
||||
s.actualTableLog = s.prevTableLog
|
||||
s.symbolLen = uint16(len(s.prevTable))
|
||||
if err := s.prevTable.write(s); err != nil {
|
||||
s.Out, s.actualTableLog, s.symbolLen = saveOut, saveTL, saveSL
|
||||
return dst, err
|
||||
}
|
||||
dst = append(dst, s.Out...)
|
||||
s.Out, s.actualTableLog, s.symbolLen = saveOut, saveTL, saveSL
|
||||
return dst, nil
|
||||
}
|
||||
2
vendor/github.com/klauspost/compress/internal/snapref/decode.go
generated
vendored
2
vendor/github.com/klauspost/compress/internal/snapref/decode.go
generated
vendored
@@ -31,7 +31,7 @@ func DecodedLen(src []byte) (int, error) {
|
||||
// that the length header occupied.
|
||||
func decodedLen(src []byte) (blockLen, headerLen int, err error) {
|
||||
v, n := binary.Uvarint(src)
|
||||
if n <= 0 || v > 0xffffffff {
|
||||
if n <= 0 || n > 5 || v > 0xffffffff {
|
||||
return 0, 0, ErrCorrupt
|
||||
}
|
||||
|
||||
|
||||
2
vendor/github.com/klauspost/compress/s2/decode.go
generated
vendored
2
vendor/github.com/klauspost/compress/s2/decode.go
generated
vendored
@@ -35,7 +35,7 @@ func DecodedLen(src []byte) (int, error) {
|
||||
// that the length header occupied.
|
||||
func decodedLen(src []byte) (blockLen, headerLen int, err error) {
|
||||
v, n := binary.Uvarint(src)
|
||||
if n <= 0 || v > 0xffffffff {
|
||||
if n <= 0 || n > 5 || v > 0xffffffff {
|
||||
return 0, 0, ErrCorrupt
|
||||
}
|
||||
|
||||
|
||||
6
vendor/github.com/klauspost/compress/s2/dict.go
generated
vendored
6
vendor/github.com/klauspost/compress/s2/dict.go
generated
vendored
@@ -56,10 +56,12 @@ func NewDict(dict []byte) *Dict {
|
||||
if len(dict) < MinDictSize || len(dict) > MaxDictSize {
|
||||
return nil
|
||||
}
|
||||
d.repeat = int(r)
|
||||
if d.repeat > len(dict) {
|
||||
// Compare as uint64: int(r) would wrap negative for r > MaxInt64,
|
||||
// slipping past the bounds check and causing an OOB read in encode.
|
||||
if r > uint64(len(dict)) {
|
||||
return nil
|
||||
}
|
||||
d.repeat = int(r)
|
||||
return &d
|
||||
}
|
||||
|
||||
|
||||
2
vendor/github.com/klauspost/compress/s2/encode_all.go
generated
vendored
2
vendor/github.com/klauspost/compress/s2/encode_all.go
generated
vendored
@@ -981,7 +981,7 @@ searchDict:
|
||||
cv = load64(src, s)
|
||||
continue
|
||||
}
|
||||
} else if uint32(cv>>(checkRep*8)) == load32(src, s-repeat+checkRep) {
|
||||
} else if repeat > 0 && uint32(cv>>(checkRep*8)) == load32(src, s-repeat+checkRep) {
|
||||
base := s + checkRep
|
||||
// Extend back
|
||||
for i := base - repeat; base > nextEmit && i > 0 && src[i-1] == src[base-1]; {
|
||||
|
||||
6
vendor/github.com/klauspost/compress/s2/hashtable_pool.go
generated
vendored
6
vendor/github.com/klauspost/compress/s2/hashtable_pool.go
generated
vendored
@@ -25,7 +25,7 @@ type betterTables struct {
|
||||
sTable [betterShortTableSize]uint32
|
||||
}
|
||||
|
||||
var betterTablePool = sync.Pool{New: func() interface{} { return &betterTables{} }}
|
||||
var betterTablePool = sync.Pool{New: func() any { return &betterTables{} }}
|
||||
|
||||
// betterSnappyTables holds better-snappy compression hash tables.
|
||||
type betterSnappyTables struct {
|
||||
@@ -33,7 +33,7 @@ type betterSnappyTables struct {
|
||||
sTable [betterShortTableSize]uint32
|
||||
}
|
||||
|
||||
var betterSnappyTablePool = sync.Pool{New: func() interface{} { return &betterSnappyTables{} }}
|
||||
var betterSnappyTablePool = sync.Pool{New: func() any { return &betterSnappyTables{} }}
|
||||
|
||||
// bestTables holds best compression hash tables.
|
||||
type bestTables struct {
|
||||
@@ -41,7 +41,7 @@ type bestTables struct {
|
||||
sTable [bestShortTableSize]uint64
|
||||
}
|
||||
|
||||
var bestTablePool = sync.Pool{New: func() interface{} { return &bestTables{} }}
|
||||
var bestTablePool = sync.Pool{New: func() any { return &bestTables{} }}
|
||||
|
||||
// getBetterTables gets a zeroed betterTables from the pool.
|
||||
func getBetterTables() *betterTables {
|
||||
|
||||
19
vendor/github.com/klauspost/compress/s2/reader.go
generated
vendored
19
vendor/github.com/klauspost/compress/s2/reader.go
generated
vendored
@@ -216,13 +216,18 @@ func (r *Reader) skippable(tmp []byte, n int, allowEOF bool, id uint8) (ok bool)
|
||||
return r.err == nil
|
||||
}
|
||||
if rs, ok := r.r.(io.ReadSeeker); ok {
|
||||
_, err := rs.Seek(int64(n), io.SeekCurrent)
|
||||
if err == nil {
|
||||
return true
|
||||
}
|
||||
if err == io.ErrUnexpectedEOF || (r.err == io.EOF && !allowEOF) {
|
||||
r.err = ErrCorrupt
|
||||
return false
|
||||
if cur, err := rs.Seek(0, io.SeekCurrent); err == nil {
|
||||
if end, err := rs.Seek(0, io.SeekEnd); err == nil {
|
||||
if cur+int64(n) <= end {
|
||||
if _, err := rs.Seek(cur+int64(n), io.SeekStart); err == nil {
|
||||
return true
|
||||
}
|
||||
}
|
||||
if _, err := rs.Seek(cur, io.SeekStart); err != nil {
|
||||
r.err = ErrCorrupt
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
for n > 0 {
|
||||
|
||||
130
vendor/github.com/klauspost/compress/snappy/decode_strict.go
generated
vendored
Normal file
130
vendor/github.com/klauspost/compress/snappy/decode_strict.go
generated
vendored
Normal file
@@ -0,0 +1,130 @@
|
||||
// Copyright 2011 The Snappy-Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package snappy
|
||||
|
||||
import "encoding/binary"
|
||||
|
||||
// DecodeStrict returns the decoded form of src, like Decode.
|
||||
//
|
||||
// Unlike Decode, which delegates to the s2 decoder and accepts the s2
|
||||
// "repeat last offset" extension (a copy whose encoded offset is 0),
|
||||
// DecodeStrict uses a strict standard-Snappy block decoder. Offset 0 is not
|
||||
// valid in the standard Snappy block format, so such a copy is rejected with
|
||||
// ErrCorrupt. This makes DecodeStrict match github.com/golang/snappy and the
|
||||
// C++ reference decoder, at the cost of being slower than Decode.
|
||||
//
|
||||
// The returned slice may be a sub-slice of dst if dst was large enough to
|
||||
// hold the entire decoded block. Otherwise, a newly allocated slice will be
|
||||
// returned.
|
||||
//
|
||||
// The dst and src must not overlap. It is valid to pass a nil dst.
|
||||
//
|
||||
// DecodeStrict handles the Snappy block format, not the Snappy stream format.
|
||||
func DecodeStrict(dst, src []byte) ([]byte, error) {
|
||||
v, n := binary.Uvarint(src)
|
||||
if n <= 0 || n > 5 || v > 0xffffffff {
|
||||
return nil, ErrCorrupt
|
||||
}
|
||||
const wordSize = 32 << (^uint(0) >> 32 & 1)
|
||||
if wordSize == 32 && v > 0x7fffffff {
|
||||
return nil, ErrTooLarge
|
||||
}
|
||||
dLen := int(v)
|
||||
if dLen <= cap(dst) {
|
||||
dst = dst[:dLen]
|
||||
} else {
|
||||
dst = make([]byte, dLen)
|
||||
}
|
||||
if decodeStrict(dst, src[n:]) != 0 {
|
||||
return nil, ErrCorrupt
|
||||
}
|
||||
return dst, nil
|
||||
}
|
||||
|
||||
func decodeStrict(dst, src []byte) int {
|
||||
var d, s, offset, length int
|
||||
for s < len(src) {
|
||||
switch src[s] & 0x03 {
|
||||
case 0x00:
|
||||
x := uint32(src[s] >> 2)
|
||||
switch {
|
||||
case x < 60:
|
||||
s++
|
||||
case x == 60:
|
||||
s += 2
|
||||
if uint(s) > uint(len(src)) {
|
||||
return 1
|
||||
}
|
||||
x = uint32(src[s-1])
|
||||
case x == 61:
|
||||
s += 3
|
||||
if uint(s) > uint(len(src)) {
|
||||
return 1
|
||||
}
|
||||
x = uint32(src[s-2]) | uint32(src[s-1])<<8
|
||||
case x == 62:
|
||||
s += 4
|
||||
if uint(s) > uint(len(src)) {
|
||||
return 1
|
||||
}
|
||||
x = uint32(src[s-3]) | uint32(src[s-2])<<8 | uint32(src[s-1])<<16
|
||||
case x == 63:
|
||||
s += 5
|
||||
if uint(s) > uint(len(src)) {
|
||||
return 1
|
||||
}
|
||||
x = uint32(src[s-4]) | uint32(src[s-3])<<8 | uint32(src[s-2])<<16 | uint32(src[s-1])<<24
|
||||
}
|
||||
length = int(x) + 1
|
||||
if length <= 0 || length > len(dst)-d || length > len(src)-s {
|
||||
return 1
|
||||
}
|
||||
copy(dst[d:], src[s:s+length])
|
||||
d += length
|
||||
s += length
|
||||
continue
|
||||
case 0x01:
|
||||
s += 2
|
||||
if uint(s) > uint(len(src)) {
|
||||
return 1
|
||||
}
|
||||
length = 4 + int(src[s-2])>>2&0x7
|
||||
offset = int(uint32(src[s-2])&0xe0<<3 | uint32(src[s-1]))
|
||||
case 0x02:
|
||||
s += 3
|
||||
if uint(s) > uint(len(src)) {
|
||||
return 1
|
||||
}
|
||||
length = 1 + int(src[s-3])>>2
|
||||
offset = int(uint32(src[s-2]) | uint32(src[s-1])<<8)
|
||||
case 0x03:
|
||||
s += 5
|
||||
if uint(s) > uint(len(src)) {
|
||||
return 1
|
||||
}
|
||||
length = 1 + int(src[s-5])>>2
|
||||
offset = int(uint32(src[s-4]) | uint32(src[s-3])<<8 | uint32(src[s-2])<<16 | uint32(src[s-1])<<24)
|
||||
}
|
||||
if offset <= 0 || d < offset || length > len(dst)-d {
|
||||
return 1
|
||||
}
|
||||
if offset >= length {
|
||||
copy(dst[d:d+length], dst[d-offset:])
|
||||
d += length
|
||||
continue
|
||||
}
|
||||
a := dst[d : d+length]
|
||||
b := dst[d-offset:]
|
||||
b = b[:len(a)]
|
||||
for i := range a {
|
||||
a[i] = b[i]
|
||||
}
|
||||
d += length
|
||||
}
|
||||
if d != len(dst) {
|
||||
return 1
|
||||
}
|
||||
return 0
|
||||
}
|
||||
37
vendor/github.com/klauspost/compress/zstd/README.md
generated
vendored
37
vendor/github.com/klauspost/compress/zstd/README.md
generated
vendored
@@ -75,14 +75,47 @@ The above is fine for big encodes. However, whenever possible try to *reuse* the
|
||||
To reuse the encoder, you can use the `Reset(io.Writer)` function to change to another output.
|
||||
This will allow the encoder to reuse all resources and avoid wasteful allocations.
|
||||
|
||||
Currently stream encoding has 'light' concurrency, meaning up to 2 goroutines can be working on part
|
||||
of a stream. This is independent of the `WithEncoderConcurrency(n)`, but that is likely to change
|
||||
By default, stream encoding has 'light' concurrency, meaning up to 2 goroutines can be working on part
|
||||
of a stream. This is independent of the `WithEncoderConcurrency(n)`, but that is likely to change
|
||||
in the future. So if you want to limit concurrency for future updates, specify the concurrency
|
||||
you would like.
|
||||
|
||||
If you would like stream encoding to be done without spawning async goroutines, use `WithEncoderConcurrency(1)`
|
||||
which will compress input as each block is completed, blocking on writes until each has completed.
|
||||
|
||||
#### Parallel Stream Compression
|
||||
|
||||
For maximum throughput on large streams, use `WithConcurrentBlocks(true)` together with
|
||||
`WithEncoderConcurrency(n)` where n is the number of CPU cores you want to use.
|
||||
This splits the input into large sections (jobs) that are compressed simultaneously by multiple goroutines,
|
||||
similar to how the C zstd library does multithreaded compression.
|
||||
|
||||
```Go
|
||||
enc, err := zstd.NewWriter(out,
|
||||
zstd.WithEncoderLevel(zstd.SpeedDefault),
|
||||
zstd.WithEncoderConcurrency(runtime.GOMAXPROCS(0)),
|
||||
zstd.WithConcurrentBlocks(true),
|
||||
)
|
||||
```
|
||||
|
||||
Each non-first job receives an overlap prefix from the previous job for match context,
|
||||
so compression ratio is only marginally affected. Output is flushed in order,
|
||||
producing a valid single-frame zstd stream.
|
||||
|
||||
Benchmark on 1.8GB GOB stream (AMD Ryzen 9 9950X):
|
||||
|
||||
| Level | 1 thread | 4 threads | 16 threads | 1T ratio | 16T ratio |
|
||||
|---------|:----------:|:------------------:|:-------------------:|:--------:|:---------:|
|
||||
| fastest | 783 MB/s | 2950 MB/s (3.8×) | 6939 MB/s (8.9×) | 12.24% | 12.26% |
|
||||
| default | 728 MB/s | 2533 MB/s (3.5×) | 5340 MB/s (7.3×) | 10.67% | 10.68% |
|
||||
| better | 434 MB/s | 1105 MB/s (2.5×) | 2206 MB/s (5.1×) | 9.14% | 9.21% |
|
||||
| best | 129 MB/s | 367 MB/s (2.8×) | 884 MB/s (6.8×) | 8.48% | 8.63% |
|
||||
|
||||
Notes:
|
||||
* Not compatible with dictionary encoding.
|
||||
* `Flush()` dispatches the current partial job, so latency-sensitive callers can force output.
|
||||
* `EncodeAll` is unaffected — it uses its own concurrency via the encoder pool.
|
||||
|
||||
You can specify your desired compression level using `WithEncoderLevel()` option. Currently only pre-defined
|
||||
compression settings can be specified.
|
||||
|
||||
|
||||
3
vendor/github.com/klauspost/compress/zstd/dict.go
generated
vendored
3
vendor/github.com/klauspost/compress/zstd/dict.go
generated
vendored
@@ -230,7 +230,7 @@ func BuildDict(o BuildDictOptions) ([]byte, error) {
|
||||
}
|
||||
block := blockEnc{lowMem: false}
|
||||
block.init()
|
||||
enc := encoder(&bestFastEncoder{fastBase: fastBase{maxMatchOff: int32(maxMatchLen), bufferReset: math.MaxInt32 - int32(maxMatchLen*2), lowMem: false}})
|
||||
var enc encoder
|
||||
if o.Level != 0 {
|
||||
eOpts := encoderOptions{
|
||||
level: o.Level,
|
||||
@@ -242,6 +242,7 @@ func BuildDict(o BuildDictOptions) ([]byte, error) {
|
||||
enc = eOpts.encoder()
|
||||
} else {
|
||||
o.Level = SpeedBestCompression
|
||||
enc = encoder(&bestFastEncoder{fastBase: fastBase{maxMatchOff: int32(maxMatchLen), bufferReset: math.MaxInt32 - int32(maxMatchLen*2), lowMem: false}})
|
||||
}
|
||||
var (
|
||||
remain [256]int
|
||||
|
||||
28
vendor/github.com/klauspost/compress/zstd/enc_base.go
generated
vendored
28
vendor/github.com/klauspost/compress/zstd/enc_base.go
generated
vendored
@@ -128,6 +128,34 @@ func (e *fastBase) matchlen(s, t int32, src []byte) int32 {
|
||||
return int32(matchLen(src[s:], src[t:]))
|
||||
}
|
||||
|
||||
// resetBasePrefix resets the encoder state and loads prefix as initial history.
|
||||
// This is used for parallel job encoding where non-first jobs need overlap context.
|
||||
// Rep offsets are set to defaults [1,4,8] (invalidated, matching C behavior).
|
||||
func (e *fastBase) resetBasePrefix(prefix []byte) {
|
||||
if e.blk == nil {
|
||||
e.blk = &blockEnc{lowMem: e.lowMem}
|
||||
e.blk.init()
|
||||
} else {
|
||||
e.blk.reset(nil)
|
||||
}
|
||||
e.blk.initNewEncode()
|
||||
if e.crc == nil {
|
||||
e.crc = xxhash.New()
|
||||
} else {
|
||||
e.crc.Reset()
|
||||
}
|
||||
e.blk.dictLitEnc = nil
|
||||
e.ensureHist(len(prefix) + maxCompressedBlockSize)
|
||||
// Bump cur so old table entries fall outside the window.
|
||||
// When cur >= bufferReset, leave it; the first Encode call
|
||||
// will shift/clear tables, preserving valid prefix entries.
|
||||
if e.cur < e.bufferReset {
|
||||
e.cur += e.maxMatchOff + int32(len(e.hist))
|
||||
}
|
||||
e.hist = e.hist[:0]
|
||||
e.hist = append(e.hist, prefix...)
|
||||
}
|
||||
|
||||
// Reset the encoding table.
|
||||
func (e *fastBase) resetBase(d *dict, singleBlock bool) {
|
||||
if e.blk == nil {
|
||||
|
||||
15
vendor/github.com/klauspost/compress/zstd/enc_best.go
generated
vendored
15
vendor/github.com/klauspost/compress/zstd/enc_best.go
generated
vendored
@@ -551,3 +551,18 @@ func (e *bestFastEncoder) Reset(d *dict, singleBlock bool) {
|
||||
// Reset table to initial state
|
||||
copy(e.table[:], e.dictTable)
|
||||
}
|
||||
|
||||
func (e *bestFastEncoder) ResetPrefix(prefix []byte) {
|
||||
e.resetBasePrefix(prefix)
|
||||
if len(prefix) < 8 {
|
||||
return
|
||||
}
|
||||
end := e.cur + int32(len(prefix)) - 8
|
||||
for i := e.cur; i < end; i++ {
|
||||
cv := load6432(prefix, i-e.cur)
|
||||
h := hashLen(cv, bestLongTableBits, bestLongLen)
|
||||
e.longTable[h] = prevEntry{offset: i, prev: e.longTable[h].offset}
|
||||
h0 := hashLen(cv, bestShortTableBits, bestShortLen)
|
||||
e.table[h0] = prevEntry{offset: i, prev: e.table[h0].offset}
|
||||
}
|
||||
}
|
||||
|
||||
18
vendor/github.com/klauspost/compress/zstd/enc_better.go
generated
vendored
18
vendor/github.com/klauspost/compress/zstd/enc_better.go
generated
vendored
@@ -1096,6 +1096,20 @@ func (e *betterFastEncoder) Reset(d *dict, singleBlock bool) {
|
||||
}
|
||||
}
|
||||
|
||||
func (e *betterFastEncoder) ResetPrefix(prefix []byte) {
|
||||
e.resetBasePrefix(prefix)
|
||||
if len(prefix) < 8 {
|
||||
return
|
||||
}
|
||||
end := e.cur + int32(len(prefix)) - 8
|
||||
for i := e.cur; i < end; i += 2 {
|
||||
cv := load6432(prefix, i-e.cur)
|
||||
h := hashLen(cv, betterLongTableBits, betterLongLen)
|
||||
e.longTable[h] = prevEntry{offset: i, prev: e.longTable[h].offset}
|
||||
e.table[hashLen(cv>>8, betterShortTableBits, betterShortLen)] = tableEntry{val: uint32(cv >> 8), offset: i + 1}
|
||||
}
|
||||
}
|
||||
|
||||
// ResetDict will reset and set a dictionary if not nil
|
||||
func (e *betterFastEncoderDict) Reset(d *dict, singleBlock bool) {
|
||||
e.resetBase(d, singleBlock)
|
||||
@@ -1229,6 +1243,10 @@ func (e *betterFastEncoderDict) Reset(d *dict, singleBlock bool) {
|
||||
e.allDirty = false
|
||||
}
|
||||
|
||||
func (e *betterFastEncoderDict) ResetPrefix([]byte) {
|
||||
panic("ResetPrefix not supported for dict encoders")
|
||||
}
|
||||
|
||||
func (e *betterFastEncoderDict) markLongShardDirty(entryNum uint32) {
|
||||
e.longTableShardDirty[entryNum/betterLongTableShardSize] = true
|
||||
}
|
||||
|
||||
16
vendor/github.com/klauspost/compress/zstd/enc_dfast.go
generated
vendored
16
vendor/github.com/klauspost/compress/zstd/enc_dfast.go
generated
vendored
@@ -1037,6 +1037,18 @@ func (e *doubleFastEncoder) Reset(d *dict, singleBlock bool) {
|
||||
}
|
||||
}
|
||||
|
||||
func (e *doubleFastEncoder) ResetPrefix(prefix []byte) {
|
||||
e.fastEncoder.ResetPrefix(prefix)
|
||||
if len(prefix) < 8 {
|
||||
return
|
||||
}
|
||||
end := e.cur + int32(len(prefix)) - 8
|
||||
for i := e.cur + 1; i < end; i += 2 {
|
||||
cv := load6432(prefix, i-e.cur)
|
||||
e.longTable[hashLen(cv, dFastLongTableBits, dFastLongLen)] = tableEntry{val: uint32(cv), offset: i}
|
||||
}
|
||||
}
|
||||
|
||||
// ResetDict will reset and set a dictionary if not nil
|
||||
func (e *doubleFastEncoderDict) Reset(d *dict, singleBlock bool) {
|
||||
allDirty := e.allDirty
|
||||
@@ -1102,6 +1114,10 @@ func (e *doubleFastEncoderDict) Reset(d *dict, singleBlock bool) {
|
||||
}
|
||||
}
|
||||
|
||||
func (e *doubleFastEncoderDict) ResetPrefix([]byte) {
|
||||
panic("ResetPrefix not supported for dict encoders")
|
||||
}
|
||||
|
||||
func (e *doubleFastEncoderDict) markLongShardDirty(entryNum uint32) {
|
||||
e.longTableShardDirty[entryNum/dLongTableShardSize] = true
|
||||
}
|
||||
|
||||
17
vendor/github.com/klauspost/compress/zstd/enc_fast.go
generated
vendored
17
vendor/github.com/klauspost/compress/zstd/enc_fast.go
generated
vendored
@@ -797,6 +797,19 @@ func (e *fastEncoder) Reset(d *dict, singleBlock bool) {
|
||||
}
|
||||
}
|
||||
|
||||
func (e *fastEncoder) ResetPrefix(prefix []byte) {
|
||||
e.resetBasePrefix(prefix)
|
||||
if len(prefix) < 8 {
|
||||
return
|
||||
}
|
||||
end := e.cur + int32(len(prefix)) - 8
|
||||
// Index every 4th
|
||||
for i := e.cur + 1; i < end; i += 4 {
|
||||
cv := load6432(prefix, i-e.cur)
|
||||
e.table[hashLen(cv, tableBits, tableFastHashLen)] = tableEntry{val: uint32(cv), offset: i}
|
||||
}
|
||||
}
|
||||
|
||||
// ResetDict will reset and set a dictionary if not nil
|
||||
func (e *fastEncoderDict) Reset(d *dict, singleBlock bool) {
|
||||
e.resetBase(d, singleBlock)
|
||||
@@ -866,6 +879,10 @@ func (e *fastEncoderDict) Reset(d *dict, singleBlock bool) {
|
||||
e.allDirty = false
|
||||
}
|
||||
|
||||
func (e *fastEncoderDict) ResetPrefix([]byte) {
|
||||
panic("ResetPrefix not supported for dict encoders")
|
||||
}
|
||||
|
||||
func (e *fastEncoderDict) markAllShardsDirty() {
|
||||
e.allDirty = true
|
||||
}
|
||||
|
||||
352
vendor/github.com/klauspost/compress/zstd/enc_jobs.go
generated
vendored
Normal file
352
vendor/github.com/klauspost/compress/zstd/enc_jobs.go
generated
vendored
Normal file
@@ -0,0 +1,352 @@
|
||||
// Copyright 2019+ Klaus Post. All rights reserved.
|
||||
// License information can be found in the LICENSE file.
|
||||
// Based on work by Yann Collet, released under BSD License.
|
||||
|
||||
package zstd
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
rdebug "runtime/debug"
|
||||
"sync"
|
||||
)
|
||||
|
||||
type encJob struct {
|
||||
prefix []byte // overlap from previous job (nil for first)
|
||||
input []byte // job's own input data (swapped from filling)
|
||||
last bool // last block of last job gets last=true
|
||||
output []byte // compressed blocks (filled by worker)
|
||||
err error // encoding error
|
||||
done chan struct{} // closed when complete
|
||||
}
|
||||
|
||||
type jobState struct {
|
||||
jobSize int
|
||||
overlapSize int
|
||||
filling []byte // accumulates input up to jobSize
|
||||
nextPrefix []byte // overlap prefix prepared for the next dispatched job
|
||||
|
||||
jobSeq int // next job sequence number
|
||||
|
||||
jobCh chan *encJob // dispatch to workers
|
||||
resultCh chan *encJob // ordered results to flusher
|
||||
|
||||
workerWg sync.WaitGroup
|
||||
flusherWg sync.WaitGroup
|
||||
|
||||
mu sync.Mutex
|
||||
flushedSeq int // last flushed sequence number
|
||||
cond *sync.Cond
|
||||
|
||||
flusherErr error
|
||||
started bool
|
||||
|
||||
inputPool sync.Pool // *[]byte buffers of jobSize cap
|
||||
outputPool sync.Pool // *[]byte buffers for compressed output
|
||||
overlapPool sync.Pool // *[]byte buffers for overlap prefixes
|
||||
}
|
||||
|
||||
func (e *Encoder) startJobWorkers() {
|
||||
js := &e.state.jobs
|
||||
n := e.o.concurrent
|
||||
js.jobCh = make(chan *encJob, n)
|
||||
js.resultCh = make(chan *encJob, n)
|
||||
js.flushedSeq = 0
|
||||
js.cond = sync.NewCond(&js.mu)
|
||||
|
||||
// Workers borrow encoders from the shared e.encoders pool per-job.
|
||||
// Ensure the pool is initialized before any worker tries to borrow.
|
||||
e.init.Do(e.initialize)
|
||||
|
||||
for range n {
|
||||
js.workerWg.Add(1)
|
||||
go e.jobWorker()
|
||||
}
|
||||
js.flusherWg.Add(1)
|
||||
go e.jobFlusher()
|
||||
js.started = true
|
||||
}
|
||||
|
||||
func (e *Encoder) jobWorker() {
|
||||
js := &e.state.jobs
|
||||
defer js.workerWg.Done()
|
||||
for job := range js.jobCh {
|
||||
enc := <-e.encoders
|
||||
e.compressJob(enc, job)
|
||||
e.encoders <- enc
|
||||
close(job.done)
|
||||
}
|
||||
}
|
||||
|
||||
func (e *Encoder) compressJob(enc encoder, job *encJob) {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
job.err = fmt.Errorf("panic in parallel job: %v", r)
|
||||
rdebug.PrintStack()
|
||||
}
|
||||
}()
|
||||
|
||||
if len(job.prefix) > 0 {
|
||||
enc.ResetPrefix(job.prefix)
|
||||
} else {
|
||||
enc.Reset(nil, false)
|
||||
}
|
||||
|
||||
data := job.input
|
||||
if len(data) == 0 && job.last {
|
||||
blk := enc.Block()
|
||||
blk.reset(nil)
|
||||
blk.last = true
|
||||
blk.encodeRaw(nil)
|
||||
job.output = append(job.output, blk.output...)
|
||||
return
|
||||
}
|
||||
|
||||
blk := enc.Block()
|
||||
for len(data) > 0 {
|
||||
todo := data
|
||||
if len(todo) > e.o.blockSize {
|
||||
todo = todo[:e.o.blockSize]
|
||||
}
|
||||
data = data[len(todo):]
|
||||
|
||||
blk.pushOffsets()
|
||||
enc.Encode(blk, todo)
|
||||
blk.last = len(data) == 0 && job.last
|
||||
|
||||
err := blk.encode(todo, e.o.noEntropy, !e.o.allLitEntropy)
|
||||
if err != nil {
|
||||
job.err = err
|
||||
return
|
||||
}
|
||||
job.output = append(job.output, blk.output...)
|
||||
blk.reset(nil)
|
||||
}
|
||||
}
|
||||
|
||||
func (js *jobState) getInputBuf(size int) []byte {
|
||||
if v := js.inputPool.Get(); v != nil {
|
||||
bp := v.(*[]byte)
|
||||
b := *bp
|
||||
if cap(b) >= size {
|
||||
return b[:0]
|
||||
}
|
||||
}
|
||||
return make([]byte, 0, size)
|
||||
}
|
||||
|
||||
func (js *jobState) putInputBuf(b []byte) {
|
||||
if cap(b) > 0 {
|
||||
b = b[:0]
|
||||
js.inputPool.Put(&b)
|
||||
}
|
||||
}
|
||||
|
||||
func (js *jobState) getOutputBuf(size int) []byte {
|
||||
if v := js.outputPool.Get(); v != nil {
|
||||
bp := v.(*[]byte)
|
||||
b := *bp
|
||||
if cap(b) >= size {
|
||||
return b[:0]
|
||||
}
|
||||
}
|
||||
return make([]byte, 0, size)
|
||||
}
|
||||
|
||||
func (js *jobState) putOutputBuf(b []byte) {
|
||||
if cap(b) > 0 {
|
||||
b = b[:0]
|
||||
js.outputPool.Put(&b)
|
||||
}
|
||||
}
|
||||
|
||||
func (js *jobState) getOverlapBuf(size int) []byte {
|
||||
if v := js.overlapPool.Get(); v != nil {
|
||||
bp := v.(*[]byte)
|
||||
b := *bp
|
||||
if cap(b) >= size {
|
||||
return b[:size]
|
||||
}
|
||||
}
|
||||
return make([]byte, size)
|
||||
}
|
||||
|
||||
func (js *jobState) putOverlapBuf(b []byte) {
|
||||
if cap(b) > 0 {
|
||||
b = b[:0]
|
||||
js.overlapPool.Put(&b)
|
||||
}
|
||||
}
|
||||
|
||||
func (e *Encoder) jobFlusher() {
|
||||
js := &e.state.jobs
|
||||
defer js.flusherWg.Done()
|
||||
for job := range js.resultCh {
|
||||
<-job.done
|
||||
// Worker has fully exited compressJob, so the prefix is no longer
|
||||
// in use. Return it to the pool regardless of outcome.
|
||||
if job.prefix != nil {
|
||||
js.putOverlapBuf(job.prefix)
|
||||
job.prefix = nil
|
||||
}
|
||||
if job.err != nil {
|
||||
js.mu.Lock()
|
||||
js.flusherErr = job.err
|
||||
js.cond.Broadcast()
|
||||
js.mu.Unlock()
|
||||
for range js.resultCh {
|
||||
}
|
||||
return
|
||||
}
|
||||
if len(job.output) > 0 {
|
||||
_, err := e.state.w.Write(job.output)
|
||||
if err != nil {
|
||||
js.mu.Lock()
|
||||
js.flusherErr = err
|
||||
js.cond.Broadcast()
|
||||
js.mu.Unlock()
|
||||
for range js.resultCh {
|
||||
}
|
||||
return
|
||||
}
|
||||
e.state.nWritten += int64(len(job.output))
|
||||
}
|
||||
// Return buffers to pools.
|
||||
js.putInputBuf(job.input)
|
||||
js.putOutputBuf(job.output)
|
||||
job.input = nil
|
||||
job.output = nil
|
||||
|
||||
js.mu.Lock()
|
||||
js.flushedSeq++
|
||||
js.cond.Broadcast()
|
||||
js.mu.Unlock()
|
||||
}
|
||||
}
|
||||
|
||||
func (e *Encoder) shutdownJobWorkers() {
|
||||
js := &e.state.jobs
|
||||
if !js.started {
|
||||
return
|
||||
}
|
||||
close(js.jobCh)
|
||||
js.workerWg.Wait()
|
||||
close(js.resultCh)
|
||||
js.flusherWg.Wait()
|
||||
js.started = false
|
||||
}
|
||||
|
||||
// waitAllJobs blocks until all dispatched jobs have been flushed.
|
||||
func (e *Encoder) waitAllJobs() {
|
||||
js := &e.state.jobs
|
||||
if !js.started {
|
||||
return
|
||||
}
|
||||
js.mu.Lock()
|
||||
for js.flushedSeq < js.jobSeq && js.flusherErr == nil {
|
||||
js.cond.Wait()
|
||||
}
|
||||
js.mu.Unlock()
|
||||
}
|
||||
|
||||
func (e *Encoder) dispatchJob(final bool) error {
|
||||
s := &e.state
|
||||
js := &s.jobs
|
||||
|
||||
js.mu.Lock()
|
||||
fErr := js.flusherErr
|
||||
js.mu.Unlock()
|
||||
if fErr != nil {
|
||||
return fErr
|
||||
}
|
||||
|
||||
if !s.headerWritten {
|
||||
// Single-block optimization: fall through to encodeAll path.
|
||||
if final && len(js.filling) > 0 && len(js.filling) <= e.o.blockSize {
|
||||
s.current = e.encodeAll(s.encoder, js.filling, s.current[:0])
|
||||
var n2 int
|
||||
n2, s.err = s.w.Write(s.current)
|
||||
if s.err != nil {
|
||||
return s.err
|
||||
}
|
||||
s.nWritten += int64(n2)
|
||||
s.nInput += int64(len(js.filling))
|
||||
s.current = s.current[:0]
|
||||
js.filling = js.filling[:0]
|
||||
s.headerWritten = true
|
||||
s.fullFrameWritten = true
|
||||
s.eofWritten = true
|
||||
return nil
|
||||
}
|
||||
if final && len(js.filling) == 0 && !e.o.fullZero {
|
||||
s.headerWritten = true
|
||||
s.fullFrameWritten = true
|
||||
s.eofWritten = true
|
||||
return nil
|
||||
}
|
||||
|
||||
var tmp [maxHeaderSize]byte
|
||||
fh := frameHeader{
|
||||
ContentSize: uint64(s.frameContentSize),
|
||||
WindowSize: uint32(s.encoder.WindowSize(s.frameContentSize)),
|
||||
SingleSegment: false,
|
||||
Checksum: e.o.crc,
|
||||
DictID: 0,
|
||||
}
|
||||
dst := fh.appendTo(tmp[:0])
|
||||
var n2 int
|
||||
n2, s.err = s.w.Write(dst)
|
||||
if s.err != nil {
|
||||
return s.err
|
||||
}
|
||||
s.nWritten += int64(n2)
|
||||
s.headerWritten = true
|
||||
}
|
||||
|
||||
if len(js.filling) == 0 && !final {
|
||||
return nil
|
||||
}
|
||||
|
||||
if !js.started {
|
||||
e.startJobWorkers()
|
||||
}
|
||||
|
||||
// Estimate output size for pooled buffer.
|
||||
outputEst := max(len(js.filling)/2, 512)
|
||||
|
||||
job := &encJob{
|
||||
last: final,
|
||||
done: make(chan struct{}),
|
||||
output: js.getOutputBuf(outputEst),
|
||||
}
|
||||
|
||||
// Each job owns its prefix slice; the flusher returns it to the pool
|
||||
// after <-job.done, so workers and dispatch never share a buffer.
|
||||
if js.nextPrefix != nil {
|
||||
job.prefix = js.nextPrefix
|
||||
js.nextPrefix = nil
|
||||
}
|
||||
|
||||
// Build the next job's prefix from the tail of this job's input.
|
||||
if !final && len(js.filling) > 0 {
|
||||
overlapLen := min(js.overlapSize, len(js.filling))
|
||||
np := js.getOverlapBuf(overlapLen)
|
||||
copy(np, js.filling[len(js.filling)-overlapLen:])
|
||||
js.nextPrefix = np
|
||||
}
|
||||
|
||||
// Swap filling buffer into job — zero-copy for the input data.
|
||||
job.input = js.filling
|
||||
js.filling = js.getInputBuf(js.jobSize)
|
||||
|
||||
s.nInput += int64(len(job.input))
|
||||
js.jobSeq++
|
||||
|
||||
if final {
|
||||
s.eofWritten = true
|
||||
}
|
||||
|
||||
js.resultCh <- job
|
||||
js.jobCh <- job
|
||||
|
||||
return nil
|
||||
}
|
||||
210
vendor/github.com/klauspost/compress/zstd/encoder.go
generated
vendored
210
vendor/github.com/klauspost/compress/zstd/encoder.go
generated
vendored
@@ -38,6 +38,7 @@ type encoder interface {
|
||||
WindowSize(size int64) int32
|
||||
UseBlock(*blockEnc)
|
||||
Reset(d *dict, singleBlock bool)
|
||||
ResetPrefix(prefix []byte)
|
||||
}
|
||||
|
||||
type encoderState struct {
|
||||
@@ -60,6 +61,9 @@ type encoderState struct {
|
||||
wg sync.WaitGroup
|
||||
// This waitgroup indicates we have a block encoding/writing.
|
||||
wWg sync.WaitGroup
|
||||
|
||||
// Parallel job state (used when concurrentBlocks is enabled).
|
||||
jobs jobState
|
||||
}
|
||||
|
||||
// NewWriter will create a new Zstandard encoder.
|
||||
@@ -74,6 +78,9 @@ func NewWriter(w io.Writer, opts ...EOption) (*Encoder, error) {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
if e.o.concurrentBlocks && (e.o.dict != nil || e.o.concurrent <= 1) {
|
||||
e.o.concurrentBlocks = false
|
||||
}
|
||||
if w != nil {
|
||||
e.Reset(w)
|
||||
}
|
||||
@@ -95,12 +102,31 @@ func (e *Encoder) initialize() {
|
||||
// as a new, independent stream.
|
||||
func (e *Encoder) Reset(w io.Writer) {
|
||||
s := &e.state
|
||||
|
||||
if e.o.concurrentBlocks {
|
||||
e.shutdownJobWorkers()
|
||||
js := &s.jobs
|
||||
js.jobSize = e.o.jobSize()
|
||||
js.overlapSize = e.o.overlapSize()
|
||||
// js.filling is allocated lazily on first Write/ReadFrom so callers
|
||||
// that only use EncodeAll don't pay the (up to ~32 MB) jobSize cost.
|
||||
js.filling = js.filling[:0]
|
||||
if js.nextPrefix != nil {
|
||||
js.putOverlapBuf(js.nextPrefix)
|
||||
js.nextPrefix = nil
|
||||
}
|
||||
js.jobSeq = 0
|
||||
js.flushedSeq = 0
|
||||
js.flusherErr = nil
|
||||
js.started = false
|
||||
}
|
||||
|
||||
s.wg.Wait()
|
||||
s.wWg.Wait()
|
||||
if cap(s.filling) == 0 {
|
||||
s.filling = make([]byte, 0, e.o.blockSize)
|
||||
}
|
||||
if e.o.concurrent > 1 {
|
||||
if e.o.concurrent > 1 && !e.o.concurrentBlocks {
|
||||
if cap(s.current) == 0 {
|
||||
s.current = make([]byte, 0, e.o.blockSize)
|
||||
}
|
||||
@@ -145,6 +171,9 @@ func (e *Encoder) ResetWithOptions(w io.Writer, opts ...EOption) error {
|
||||
}
|
||||
}
|
||||
hasDict := e.o.dict != nil
|
||||
if e.o.concurrentBlocks && hasDict {
|
||||
e.o.concurrentBlocks = false
|
||||
}
|
||||
if hadDict != hasDict {
|
||||
// Dict presence changed — encoder type must be recreated.
|
||||
e.state.encoder = nil
|
||||
@@ -176,6 +205,49 @@ func (e *Encoder) Write(p []byte) (n int, err error) {
|
||||
if s.eofWritten {
|
||||
return 0, ErrEncoderClosed
|
||||
}
|
||||
if e.o.concurrentBlocks {
|
||||
return e.writeJobs(p)
|
||||
}
|
||||
return e.writeBlocks(p)
|
||||
}
|
||||
|
||||
func (e *Encoder) writeJobs(p []byte) (n int, err error) {
|
||||
s := &e.state
|
||||
js := &s.jobs
|
||||
jobSize := js.jobSize
|
||||
if cap(js.filling) == 0 && len(p) > 0 {
|
||||
js.filling = make([]byte, 0, jobSize)
|
||||
}
|
||||
for len(p) > 0 {
|
||||
if len(p)+len(js.filling) < jobSize {
|
||||
if e.o.crc {
|
||||
_, _ = s.encoder.CRC().Write(p)
|
||||
}
|
||||
js.filling = append(js.filling, p...)
|
||||
return n + len(p), nil
|
||||
}
|
||||
add := p
|
||||
if len(p)+len(js.filling) > jobSize {
|
||||
add = add[:jobSize-len(js.filling)]
|
||||
}
|
||||
if e.o.crc {
|
||||
_, _ = s.encoder.CRC().Write(add)
|
||||
}
|
||||
js.filling = append(js.filling, add...)
|
||||
p = p[len(add):]
|
||||
n += len(add)
|
||||
if len(js.filling) < jobSize {
|
||||
return n, nil
|
||||
}
|
||||
if err := e.dispatchJob(false); err != nil {
|
||||
return n, err
|
||||
}
|
||||
}
|
||||
return n, nil
|
||||
}
|
||||
|
||||
func (e *Encoder) writeBlocks(p []byte) (n int, err error) {
|
||||
s := &e.state
|
||||
for len(p) > 0 {
|
||||
if len(p)+len(s.filling) < e.o.blockSize {
|
||||
if e.o.crc {
|
||||
@@ -374,6 +446,10 @@ func (e *Encoder) ReadFrom(r io.Reader) (n int64, err error) {
|
||||
println("Using ReadFrom")
|
||||
}
|
||||
|
||||
if e.o.concurrentBlocks {
|
||||
return e.readFromJobs(r)
|
||||
}
|
||||
|
||||
// Flush any current writes.
|
||||
if len(e.state.filling) > 0 {
|
||||
if err := e.nextBlock(false); err != nil {
|
||||
@@ -387,7 +463,6 @@ func (e *Encoder) ReadFrom(r io.Reader) (n int64, err error) {
|
||||
if e.o.crc {
|
||||
_, _ = e.state.encoder.CRC().Write(src[:n2])
|
||||
}
|
||||
// src is now the unfilled part...
|
||||
src = src[n2:]
|
||||
n += int64(n2)
|
||||
switch err {
|
||||
@@ -420,15 +495,63 @@ func (e *Encoder) ReadFrom(r io.Reader) (n int64, err error) {
|
||||
}
|
||||
}
|
||||
|
||||
func (e *Encoder) readFromJobs(r io.Reader) (n int64, err error) {
|
||||
js := &e.state.jobs
|
||||
jobSize := js.jobSize
|
||||
|
||||
// Flush any current filling.
|
||||
if len(js.filling) > 0 {
|
||||
if err := e.dispatchJob(false); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
}
|
||||
|
||||
if cap(js.filling) < jobSize {
|
||||
js.filling = make([]byte, 0, jobSize)
|
||||
}
|
||||
js.filling = js.filling[:jobSize]
|
||||
src := js.filling
|
||||
for {
|
||||
n2, err := r.Read(src)
|
||||
if e.o.crc {
|
||||
_, _ = e.state.encoder.CRC().Write(src[:n2])
|
||||
}
|
||||
src = src[n2:]
|
||||
n += int64(n2)
|
||||
switch err {
|
||||
case io.EOF:
|
||||
js.filling = js.filling[:len(js.filling)-len(src)]
|
||||
return n, nil
|
||||
case nil:
|
||||
default:
|
||||
e.state.err = err
|
||||
return n, err
|
||||
}
|
||||
if len(src) > 0 {
|
||||
continue
|
||||
}
|
||||
if err = e.dispatchJob(false); err != nil {
|
||||
return n, err
|
||||
}
|
||||
if cap(js.filling) < jobSize {
|
||||
js.filling = make([]byte, 0, jobSize)
|
||||
}
|
||||
js.filling = js.filling[:jobSize]
|
||||
src = js.filling
|
||||
}
|
||||
}
|
||||
|
||||
// Flush will send the currently written data to output
|
||||
// and block until everything has been written.
|
||||
// This should only be used on rare occasions where pushing the currently queued data is critical.
|
||||
func (e *Encoder) Flush() error {
|
||||
s := &e.state
|
||||
if e.o.concurrentBlocks {
|
||||
return e.flushJobs()
|
||||
}
|
||||
if len(s.filling) > 0 {
|
||||
err := e.nextBlock(false)
|
||||
if err != nil {
|
||||
// Ignore Flush after Close.
|
||||
if errors.Is(s.err, ErrEncoderClosed) {
|
||||
return nil
|
||||
}
|
||||
@@ -438,7 +561,6 @@ func (e *Encoder) Flush() error {
|
||||
s.wg.Wait()
|
||||
s.wWg.Wait()
|
||||
if s.err != nil {
|
||||
// Ignore Flush after Close.
|
||||
if errors.Is(s.err, ErrEncoderClosed) {
|
||||
return nil
|
||||
}
|
||||
@@ -447,6 +569,20 @@ func (e *Encoder) Flush() error {
|
||||
return s.writeErr
|
||||
}
|
||||
|
||||
func (e *Encoder) flushJobs() error {
|
||||
js := &e.state.jobs
|
||||
if len(js.filling) > 0 {
|
||||
if err := e.dispatchJob(false); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
e.waitAllJobs()
|
||||
js.mu.Lock()
|
||||
fErr := js.flusherErr
|
||||
js.mu.Unlock()
|
||||
return fErr
|
||||
}
|
||||
|
||||
// Close will flush the final output and close the stream.
|
||||
// The function will block until everything has been written.
|
||||
// The Encoder can still be re-used after calling this.
|
||||
@@ -455,12 +591,16 @@ func (e *Encoder) Close() error {
|
||||
if s.encoder == nil {
|
||||
return nil
|
||||
}
|
||||
if e.o.concurrentBlocks {
|
||||
return e.closeJobs()
|
||||
}
|
||||
if s.w == nil {
|
||||
if len(s.filling) == 0 && !s.headerWritten && !s.eofWritten && s.nInput == 0 {
|
||||
return nil
|
||||
}
|
||||
return errors.New("zstd: encoder has no writer")
|
||||
}
|
||||
|
||||
err := e.nextBlock(true)
|
||||
if err != nil {
|
||||
if errors.Is(s.err, ErrEncoderClosed) {
|
||||
@@ -511,6 +651,68 @@ func (e *Encoder) Close() error {
|
||||
return s.err
|
||||
}
|
||||
|
||||
func (e *Encoder) closeJobs() error {
|
||||
s := &e.state
|
||||
js := &s.jobs
|
||||
|
||||
if errors.Is(s.err, ErrEncoderClosed) {
|
||||
return nil
|
||||
}
|
||||
|
||||
if s.w == nil {
|
||||
if len(js.filling) == 0 && !s.headerWritten && !s.eofWritten && s.nInput == 0 {
|
||||
return nil
|
||||
}
|
||||
return errors.New("zstd: encoder has no writer")
|
||||
}
|
||||
|
||||
if err := e.dispatchJob(true); err != nil {
|
||||
e.shutdownJobWorkers()
|
||||
if errors.Is(s.err, ErrEncoderClosed) {
|
||||
return nil
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
if s.frameContentSize > 0 && s.nInput != s.frameContentSize {
|
||||
e.shutdownJobWorkers()
|
||||
return fmt.Errorf("frame content size %d given, but %d bytes was written", s.frameContentSize, s.nInput)
|
||||
}
|
||||
|
||||
if s.fullFrameWritten {
|
||||
e.shutdownJobWorkers()
|
||||
s.err = ErrEncoderClosed
|
||||
return nil
|
||||
}
|
||||
|
||||
e.shutdownJobWorkers()
|
||||
if js.flusherErr != nil {
|
||||
return js.flusherErr
|
||||
}
|
||||
|
||||
// Write CRC
|
||||
if e.o.crc {
|
||||
var tmp [4]byte
|
||||
_, s.err = s.w.Write(s.encoder.AppendCRC(tmp[:0]))
|
||||
s.nWritten += 4
|
||||
}
|
||||
|
||||
// Add padding
|
||||
if s.err == nil && e.o.pad > 0 {
|
||||
add := calcSkippableFrame(s.nWritten, int64(e.o.pad))
|
||||
frame, err := skippableFrame(js.filling[:0], add, rand.Reader)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, s.err = s.w.Write(frame)
|
||||
}
|
||||
if s.err == nil {
|
||||
s.err = ErrEncoderClosed
|
||||
return nil
|
||||
}
|
||||
return s.err
|
||||
}
|
||||
|
||||
// EncodeAll will encode all input in src and append it to dst.
|
||||
// This function can be called concurrently, but each call will only run on a single goroutine.
|
||||
// If empty input is given, nothing is returned, unless WithZeroFrames is specified.
|
||||
|
||||
69
vendor/github.com/klauspost/compress/zstd/encoder_options.go
generated
vendored
69
vendor/github.com/klauspost/compress/zstd/encoder_options.go
generated
vendored
@@ -14,22 +14,23 @@ type EOption func(*encoderOptions) error
|
||||
|
||||
// options retains accumulated state of multiple options.
|
||||
type encoderOptions struct {
|
||||
resetOpt bool
|
||||
concurrent int
|
||||
level EncoderLevel
|
||||
single *bool
|
||||
pad int
|
||||
blockSize int
|
||||
windowSize int
|
||||
crc bool
|
||||
fullZero bool
|
||||
noEntropy bool
|
||||
allLitEntropy bool
|
||||
customWindow bool
|
||||
customALEntropy bool
|
||||
customBlockSize bool
|
||||
lowMem bool
|
||||
dict *dict
|
||||
resetOpt bool
|
||||
concurrent int
|
||||
level EncoderLevel
|
||||
single *bool
|
||||
pad int
|
||||
blockSize int
|
||||
windowSize int
|
||||
crc bool
|
||||
fullZero bool
|
||||
noEntropy bool
|
||||
allLitEntropy bool
|
||||
customWindow bool
|
||||
customALEntropy bool
|
||||
customBlockSize bool
|
||||
lowMem bool
|
||||
dict *dict
|
||||
concurrentBlocks bool
|
||||
}
|
||||
|
||||
func (o *encoderOptions) setDefault() {
|
||||
@@ -333,6 +334,42 @@ func WithLowerEncoderMem(b bool) EOption {
|
||||
}
|
||||
}
|
||||
|
||||
// WithConcurrentBlocks enables job-based parallel compression for streams.
|
||||
// When enabled and concurrent > 1, input is split into large sections (jobs)
|
||||
// that are compressed simultaneously by multiple goroutines.
|
||||
// Each non-first job receives an overlap prefix from the previous job for match context.
|
||||
// Output is flushed in order, producing a valid single-frame zstd stream.
|
||||
//
|
||||
// Currently disabled when used with dictionary encoding.
|
||||
// Cannot be changed with ResetWithOptions.
|
||||
func WithConcurrentBlocks(b bool) EOption {
|
||||
return func(o *encoderOptions) error {
|
||||
if o.resetOpt && b != o.concurrentBlocks {
|
||||
return errors.New("WithConcurrentBlocks cannot be changed on Reset")
|
||||
}
|
||||
o.concurrentBlocks = b
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// jobSize returns the input section size per parallel job.
|
||||
func (o *encoderOptions) jobSize() int {
|
||||
s := max(o.windowSize*4, 512<<10)
|
||||
return s
|
||||
}
|
||||
|
||||
// overlapSize returns the overlap prefix size for parallel jobs.
|
||||
func (o *encoderOptions) overlapSize() int {
|
||||
switch o.level {
|
||||
case SpeedBestCompression:
|
||||
return o.windowSize / 2
|
||||
case SpeedBetterCompression:
|
||||
return o.windowSize / 4
|
||||
default:
|
||||
return o.windowSize / 8
|
||||
}
|
||||
}
|
||||
|
||||
// WithEncoderDict allows to register a dictionary that will be used for the encode.
|
||||
//
|
||||
// The slice dict must be in the [dictionary format] produced by
|
||||
|
||||
2
vendor/github.com/klauspost/compress/zstd/fse_decoder_amd64.s
generated
vendored
2
vendor/github.com/klauspost/compress/zstd/fse_decoder_amd64.s
generated
vendored
@@ -1,4 +1,4 @@
|
||||
// Code generated by command: go run gen_fse.go -out ../fse_decoder_amd64.s -pkg=zstd. DO NOT EDIT.
|
||||
// Code generated by command: go run gen_fse.go -out ../fse_decoder.s -arch amd64,arm64 -pkg=zstd. DO NOT EDIT.
|
||||
|
||||
//go:build !appengine && !noasm && gc && !noasm
|
||||
|
||||
|
||||
153
vendor/github.com/klauspost/compress/zstd/fse_decoder_arm64.s
generated
vendored
Normal file
153
vendor/github.com/klauspost/compress/zstd/fse_decoder_arm64.s
generated
vendored
Normal file
@@ -0,0 +1,153 @@
|
||||
// Code generated by command: go run gen_fse.go -out ../fse_decoder.s -arch amd64,arm64 -pkg=zstd. DO NOT EDIT.
|
||||
// EXPERIMENTAL arm64 output lowered from an amd64 avo program.
|
||||
|
||||
//go:build arm64 && !appengine && !noasm && gc && !noasm
|
||||
|
||||
// func buildDtable_asm(s *fseDecoder, ctx *buildDtableAsmContext) int
|
||||
TEXT ·buildDtable_asm(SB), $0-24
|
||||
MOVD ctx+8(FP), R1
|
||||
MOVD s+0(FP), R6
|
||||
|
||||
// Load values
|
||||
MOVBU 4098(R6), R2
|
||||
MOVD $0, R0
|
||||
MOVD $1, R16
|
||||
LSL R2, R16, R16
|
||||
ORR R16, R0, R0
|
||||
MOVD (R1), R3
|
||||
MOVD 16(R1), R5
|
||||
SUB $1, R0, R7
|
||||
MOVD 8(R1), R1
|
||||
MOVHU 4096(R6), R6
|
||||
|
||||
// End load values
|
||||
// Init, lay down lowprob symbols
|
||||
MOVD $0, R8
|
||||
JMP init_main_loop_condition
|
||||
|
||||
init_main_loop:
|
||||
ADD R8<<1, R1, R15
|
||||
MOVH (R15), R9
|
||||
AND $0xffff, R9, R15
|
||||
MOVD $-1, R16
|
||||
AND $0xffff, R16, R16
|
||||
CMP R16, R15
|
||||
BNE do_not_update_high_threshold
|
||||
ADD R7<<3, R5, R15
|
||||
MOVB R8, 1(R15)
|
||||
SUB $1, R7, R7
|
||||
MOVD $0x0000000000000001, R9
|
||||
|
||||
do_not_update_high_threshold:
|
||||
ADD R8<<1, R3, R15
|
||||
MOVH R9, (R15)
|
||||
ADD $1, R8, R8
|
||||
|
||||
init_main_loop_condition:
|
||||
CMP R6, R8
|
||||
BLT init_main_loop
|
||||
|
||||
// Spread symbols
|
||||
// Calculate table step
|
||||
MOVD R0, R8
|
||||
LSR $0x01, R8, R8
|
||||
MOVD R0, R9
|
||||
LSR $0x03, R9, R9
|
||||
ADD R9, R8, R8
|
||||
ADD $3, R8, R8
|
||||
|
||||
// Fill add bits values
|
||||
SUB $1, R0, R9
|
||||
MOVD $0, R10
|
||||
MOVD $0, R11
|
||||
JMP spread_main_loop_condition
|
||||
|
||||
spread_main_loop:
|
||||
MOVD $0, R12
|
||||
ADD R11<<1, R1, R15
|
||||
MOVH (R15), R13
|
||||
JMP spread_inner_loop_condition
|
||||
|
||||
spread_inner_loop:
|
||||
ADD R10<<3, R5, R15
|
||||
MOVB R11, 1(R15)
|
||||
|
||||
adjust_position:
|
||||
ADD R8, R10, R10
|
||||
AND R9, R10, R10
|
||||
CMP R7, R10
|
||||
BGT adjust_position
|
||||
ADD $1, R12, R12
|
||||
|
||||
spread_inner_loop_condition:
|
||||
CMP R13, R12
|
||||
BLT spread_inner_loop
|
||||
ADD $1, R11, R11
|
||||
|
||||
spread_main_loop_condition:
|
||||
CMP R6, R11
|
||||
BLT spread_main_loop
|
||||
TST R10, R10
|
||||
BEQ spread_check_ok
|
||||
MOVD ctx+8(FP), R0
|
||||
MOVD R10, 24(R0)
|
||||
MOVD $+1, R16
|
||||
MOVD R16, ret+16(FP)
|
||||
RET
|
||||
|
||||
spread_check_ok:
|
||||
// Build Decoding table
|
||||
MOVD $0, R6
|
||||
|
||||
build_table_main_table:
|
||||
ADD R6<<3, R5, R15
|
||||
MOVBU 1(R15), R1
|
||||
ADD R1<<1, R3, R15
|
||||
MOVHU (R15), R7
|
||||
ADD $1, R7, R8
|
||||
ADD R1<<1, R3, R15
|
||||
MOVH R8, (R15)
|
||||
MOVD R7, R8
|
||||
CLZ R8, R16
|
||||
MOVD $63, R8
|
||||
SUB R16, R8, R8
|
||||
MOVD R2, R1
|
||||
SUB R8, R1, R1
|
||||
LSL R1, R7, R7
|
||||
SUB R0, R7, R7
|
||||
ADD R6<<3, R5, R15
|
||||
MOVB R1, (R15)
|
||||
ADD R6<<3, R5, R15
|
||||
MOVH R7, 2(R15)
|
||||
CMP R0, R7
|
||||
BLE build_table_check1_ok
|
||||
MOVD ctx+8(FP), R1
|
||||
MOVD R7, 24(R1)
|
||||
MOVD R0, 32(R1)
|
||||
MOVD $+2, R16
|
||||
MOVD R16, ret+16(FP)
|
||||
RET
|
||||
|
||||
build_table_check1_ok:
|
||||
AND $0xff, R1, R15
|
||||
AND $0xff, R1, R16
|
||||
TST R16, R15
|
||||
BNE build_table_check2_ok
|
||||
AND $0xffff, R7, R15
|
||||
AND $0xffff, R6, R16
|
||||
CMP R16, R15
|
||||
BNE build_table_check2_ok
|
||||
MOVD ctx+8(FP), R0
|
||||
MOVD R7, 24(R0)
|
||||
MOVD R6, 32(R0)
|
||||
MOVD $+3, R16
|
||||
MOVD R16, ret+16(FP)
|
||||
RET
|
||||
|
||||
build_table_check2_ok:
|
||||
ADD $1, R6, R6
|
||||
CMP R0, R6
|
||||
BLT build_table_main_table
|
||||
MOVD $+0, R16
|
||||
MOVD R16, ret+16(FP)
|
||||
RET
|
||||
@@ -1,4 +1,4 @@
|
||||
//go:build amd64 && !appengine && !noasm && gc
|
||||
//go:build (amd64 || arm64) && !appengine && !noasm && gc
|
||||
|
||||
package zstd
|
||||
|
||||
@@ -6,6 +6,10 @@ import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
// buildDtable_asm is generated by _generate/gen_fse.go and lowered to each
|
||||
// architecture (amd64 by goasm, arm64 by the avo arm64 lowering printer). The
|
||||
// Go side is identical across architectures, so it lives here.
|
||||
|
||||
type buildDtableAsmContext struct {
|
||||
// inputs
|
||||
stateTable *uint16
|
||||
@@ -18,7 +22,7 @@ type buildDtableAsmContext struct {
|
||||
errParam2 uint64
|
||||
}
|
||||
|
||||
// buildDtable_asm is an x86 assembly implementation of fseDecoder.buildDtable.
|
||||
// buildDtable_asm is an assembly implementation of fseDecoder.buildDtable.
|
||||
// Function returns non-zero exit code on error.
|
||||
//
|
||||
//go:noescape
|
||||
2
vendor/github.com/klauspost/compress/zstd/fse_decoder_generic.go
generated
vendored
2
vendor/github.com/klauspost/compress/zstd/fse_decoder_generic.go
generated
vendored
@@ -1,4 +1,4 @@
|
||||
//go:build !amd64 || appengine || !gc || noasm
|
||||
//go:build (!amd64 && !arm64) || appengine || !gc || noasm
|
||||
|
||||
package zstd
|
||||
|
||||
|
||||
384
vendor/github.com/klauspost/compress/zstd/seqdec_amd64.go
generated
vendored
384
vendor/github.com/klauspost/compress/zstd/seqdec_amd64.go
generated
vendored
@@ -3,30 +3,47 @@
|
||||
package zstd
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
|
||||
"github.com/klauspost/compress/internal/cpuinfo"
|
||||
)
|
||||
|
||||
type decodeSyncAsmContext struct {
|
||||
llTable []decSymbol
|
||||
mlTable []decSymbol
|
||||
ofTable []decSymbol
|
||||
llState uint64
|
||||
mlState uint64
|
||||
ofState uint64
|
||||
iteration int
|
||||
litRemain int
|
||||
out []byte
|
||||
outPosition int
|
||||
literals []byte
|
||||
litPosition int
|
||||
history []byte
|
||||
windowSize int
|
||||
ll int // set on error (not for all errors, please refer to _generate/gen.go)
|
||||
ml int // set on error (not for all errors, please refer to _generate/gen.go)
|
||||
mo int // set on error (not for all errors, please refer to _generate/gen.go)
|
||||
// The shared decode/decodeSync/executeSimple wrappers and context structs live
|
||||
// in seqdec_asm.go; this file only declares the amd64 asm routines and the
|
||||
// dispatch helpers that pick the BMI2 / non-BMI2 (and 56-bit / safe) variant.
|
||||
|
||||
// sequenceDecs_decode implements the main loop of sequenceDecs in x86 asm.
|
||||
//
|
||||
// Please refer to seqdec_generic.go for the reference implementation.
|
||||
//
|
||||
//go:noescape
|
||||
func sequenceDecs_decode_amd64(s *sequenceDecs, br *bitReader, ctx *decodeAsmContext) int
|
||||
|
||||
// sequenceDecs_decode_56_amd64 implements the main loop of sequenceDecs in x86 asm.
|
||||
//
|
||||
//go:noescape
|
||||
func sequenceDecs_decode_56_amd64(s *sequenceDecs, br *bitReader, ctx *decodeAsmContext) int
|
||||
|
||||
// sequenceDecs_decode_bmi2 implements the main loop of sequenceDecs in x86 asm with BMI2 extensions.
|
||||
//
|
||||
//go:noescape
|
||||
func sequenceDecs_decode_bmi2(s *sequenceDecs, br *bitReader, ctx *decodeAsmContext) int
|
||||
|
||||
// sequenceDecs_decode_56_bmi2 implements the main loop of sequenceDecs in x86 asm with BMI2 extensions.
|
||||
//
|
||||
//go:noescape
|
||||
func sequenceDecs_decode_56_bmi2(s *sequenceDecs, br *bitReader, ctx *decodeAsmContext) int
|
||||
|
||||
// decodeAsm runs the sequenceDecs decode loop, choosing the BMI2 / 56-bit variant.
|
||||
func decodeAsm(s *sequenceDecs, br *bitReader, ctx *decodeAsmContext, lte56bits bool) int {
|
||||
if cpuinfo.HasBMI2() {
|
||||
if lte56bits {
|
||||
return sequenceDecs_decode_56_bmi2(s, br, ctx)
|
||||
}
|
||||
return sequenceDecs_decode_bmi2(s, br, ctx)
|
||||
}
|
||||
if lte56bits {
|
||||
return sequenceDecs_decode_56_amd64(s, br, ctx)
|
||||
}
|
||||
return sequenceDecs_decode_amd64(s, br, ctx)
|
||||
}
|
||||
|
||||
// sequenceDecs_decodeSync_amd64 implements the main loop of sequenceDecs.decodeSync in x86 asm.
|
||||
@@ -51,273 +68,18 @@ func sequenceDecs_decodeSync_safe_amd64(s *sequenceDecs, br *bitReader, ctx *dec
|
||||
//go:noescape
|
||||
func sequenceDecs_decodeSync_safe_bmi2(s *sequenceDecs, br *bitReader, ctx *decodeSyncAsmContext) int
|
||||
|
||||
// decode sequences from the stream with the provided history but without a dictionary.
|
||||
func (s *sequenceDecs) decodeSyncSimple(hist []byte) (bool, error) {
|
||||
if len(s.dict) > 0 {
|
||||
return false, nil
|
||||
}
|
||||
if s.maxSyncLen == 0 && cap(s.out)-len(s.out) < maxCompressedBlockSize {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
// FIXME: Using unsafe memory copies leads to rare, random crashes
|
||||
// with fuzz testing. It is therefore disabled for now.
|
||||
const useSafe = true
|
||||
/*
|
||||
useSafe := false
|
||||
if s.maxSyncLen == 0 && cap(s.out)-len(s.out) < maxCompressedBlockSizeAlloc {
|
||||
useSafe = true
|
||||
}
|
||||
if s.maxSyncLen > 0 && cap(s.out)-len(s.out)-compressedBlockOverAlloc < int(s.maxSyncLen) {
|
||||
useSafe = true
|
||||
}
|
||||
if cap(s.literals) < len(s.literals)+compressedBlockOverAlloc {
|
||||
useSafe = true
|
||||
}
|
||||
*/
|
||||
|
||||
br := s.br
|
||||
|
||||
maxBlockSize := min(s.windowSize, maxCompressedBlockSize)
|
||||
|
||||
ctx := decodeSyncAsmContext{
|
||||
llTable: s.litLengths.fse.dt[:maxTablesize],
|
||||
mlTable: s.matchLengths.fse.dt[:maxTablesize],
|
||||
ofTable: s.offsets.fse.dt[:maxTablesize],
|
||||
llState: uint64(s.litLengths.state.state),
|
||||
mlState: uint64(s.matchLengths.state.state),
|
||||
ofState: uint64(s.offsets.state.state),
|
||||
iteration: s.nSeqs - 1,
|
||||
litRemain: len(s.literals),
|
||||
out: s.out,
|
||||
outPosition: len(s.out),
|
||||
literals: s.literals,
|
||||
windowSize: s.windowSize,
|
||||
history: hist,
|
||||
}
|
||||
|
||||
s.seqSize = 0
|
||||
startSize := len(s.out)
|
||||
|
||||
var errCode int
|
||||
// decodeSyncAsm runs the decodeSync loop, choosing the BMI2 / safe variant.
|
||||
func decodeSyncAsm(s *sequenceDecs, br *bitReader, ctx *decodeSyncAsmContext, safe bool) int {
|
||||
if cpuinfo.HasBMI2() {
|
||||
if useSafe {
|
||||
errCode = sequenceDecs_decodeSync_safe_bmi2(s, br, &ctx)
|
||||
} else {
|
||||
errCode = sequenceDecs_decodeSync_bmi2(s, br, &ctx)
|
||||
}
|
||||
} else {
|
||||
if useSafe {
|
||||
errCode = sequenceDecs_decodeSync_safe_amd64(s, br, &ctx)
|
||||
} else {
|
||||
errCode = sequenceDecs_decodeSync_amd64(s, br, &ctx)
|
||||
if safe {
|
||||
return sequenceDecs_decodeSync_safe_bmi2(s, br, ctx)
|
||||
}
|
||||
return sequenceDecs_decodeSync_bmi2(s, br, ctx)
|
||||
}
|
||||
switch errCode {
|
||||
case noError:
|
||||
break
|
||||
|
||||
case errorMatchLenOfsMismatch:
|
||||
return true, fmt.Errorf("zero matchoff and matchlen (%d) > 0", ctx.ml)
|
||||
|
||||
case errorMatchLenTooBig:
|
||||
return true, fmt.Errorf("match len (%d) bigger than max allowed length", ctx.ml)
|
||||
|
||||
case errorMatchOffTooBig:
|
||||
return true, fmt.Errorf("match offset (%d) bigger than current history (%d)",
|
||||
ctx.mo, ctx.outPosition+len(hist)-startSize)
|
||||
|
||||
case errorNotEnoughLiterals:
|
||||
return true, fmt.Errorf("unexpected literal count, want %d bytes, but only %d is available",
|
||||
ctx.ll, ctx.litRemain+ctx.ll)
|
||||
|
||||
case errorOverread:
|
||||
return true, io.ErrUnexpectedEOF
|
||||
|
||||
case errorNotEnoughSpace:
|
||||
size := ctx.outPosition + ctx.ll + ctx.ml
|
||||
if debugDecoder {
|
||||
println("msl:", s.maxSyncLen, "cap", cap(s.out), "bef:", startSize, "sz:", size-startSize, "mbs:", maxBlockSize, "outsz:", cap(s.out)-startSize)
|
||||
}
|
||||
return true, fmt.Errorf("output bigger than max block size (%d)", maxBlockSize)
|
||||
|
||||
default:
|
||||
return true, fmt.Errorf("sequenceDecs_decode returned erroneous code %d", errCode)
|
||||
if safe {
|
||||
return sequenceDecs_decodeSync_safe_amd64(s, br, ctx)
|
||||
}
|
||||
|
||||
s.seqSize += ctx.litRemain
|
||||
if s.seqSize > maxBlockSize {
|
||||
return true, fmt.Errorf("output bigger than max block size (%d)", maxBlockSize)
|
||||
}
|
||||
err := br.close()
|
||||
if err != nil {
|
||||
printf("Closing sequences: %v, %+v\n", err, *br)
|
||||
return true, err
|
||||
}
|
||||
|
||||
s.literals = s.literals[ctx.litPosition:]
|
||||
t := ctx.outPosition
|
||||
s.out = s.out[:t]
|
||||
|
||||
// Add final literals
|
||||
s.out = append(s.out, s.literals...)
|
||||
if debugDecoder {
|
||||
t += len(s.literals)
|
||||
if t != len(s.out) {
|
||||
panic(fmt.Errorf("length mismatch, want %d, got %d", len(s.out), t))
|
||||
}
|
||||
}
|
||||
|
||||
return true, nil
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------------
|
||||
|
||||
type decodeAsmContext struct {
|
||||
llTable []decSymbol
|
||||
mlTable []decSymbol
|
||||
ofTable []decSymbol
|
||||
llState uint64
|
||||
mlState uint64
|
||||
ofState uint64
|
||||
iteration int
|
||||
seqs []seqVals
|
||||
litRemain int
|
||||
}
|
||||
|
||||
const noError = 0
|
||||
|
||||
// error reported when mo == 0 && ml > 0
|
||||
const errorMatchLenOfsMismatch = 1
|
||||
|
||||
// error reported when ml > maxMatchLen
|
||||
const errorMatchLenTooBig = 2
|
||||
|
||||
// error reported when mo > available history or mo > s.windowSize
|
||||
const errorMatchOffTooBig = 3
|
||||
|
||||
// error reported when the sum of literal lengths exeeceds the literal buffer size
|
||||
const errorNotEnoughLiterals = 4
|
||||
|
||||
// error reported when capacity of `out` is too small
|
||||
const errorNotEnoughSpace = 5
|
||||
|
||||
// error reported when bits are overread.
|
||||
const errorOverread = 6
|
||||
|
||||
// sequenceDecs_decode implements the main loop of sequenceDecs in x86 asm.
|
||||
//
|
||||
// Please refer to seqdec_generic.go for the reference implementation.
|
||||
//
|
||||
//go:noescape
|
||||
func sequenceDecs_decode_amd64(s *sequenceDecs, br *bitReader, ctx *decodeAsmContext) int
|
||||
|
||||
// sequenceDecs_decode implements the main loop of sequenceDecs in x86 asm.
|
||||
//
|
||||
// Please refer to seqdec_generic.go for the reference implementation.
|
||||
//
|
||||
//go:noescape
|
||||
func sequenceDecs_decode_56_amd64(s *sequenceDecs, br *bitReader, ctx *decodeAsmContext) int
|
||||
|
||||
// sequenceDecs_decode implements the main loop of sequenceDecs in x86 asm with BMI2 extensions.
|
||||
//
|
||||
//go:noescape
|
||||
func sequenceDecs_decode_bmi2(s *sequenceDecs, br *bitReader, ctx *decodeAsmContext) int
|
||||
|
||||
// sequenceDecs_decode implements the main loop of sequenceDecs in x86 asm with BMI2 extensions.
|
||||
//
|
||||
//go:noescape
|
||||
func sequenceDecs_decode_56_bmi2(s *sequenceDecs, br *bitReader, ctx *decodeAsmContext) int
|
||||
|
||||
// decode sequences from the stream without the provided history.
|
||||
func (s *sequenceDecs) decode(seqs []seqVals) error {
|
||||
br := s.br
|
||||
|
||||
maxBlockSize := min(s.windowSize, maxCompressedBlockSize)
|
||||
|
||||
ctx := decodeAsmContext{
|
||||
llTable: s.litLengths.fse.dt[:maxTablesize],
|
||||
mlTable: s.matchLengths.fse.dt[:maxTablesize],
|
||||
ofTable: s.offsets.fse.dt[:maxTablesize],
|
||||
llState: uint64(s.litLengths.state.state),
|
||||
mlState: uint64(s.matchLengths.state.state),
|
||||
ofState: uint64(s.offsets.state.state),
|
||||
seqs: seqs,
|
||||
iteration: len(seqs) - 1,
|
||||
litRemain: len(s.literals),
|
||||
}
|
||||
|
||||
if debugDecoder {
|
||||
println("decode: decoding", len(seqs), "sequences", br.remain(), "bits remain on stream")
|
||||
}
|
||||
|
||||
s.seqSize = 0
|
||||
lte56bits := s.maxBits+s.offsets.fse.actualTableLog+s.matchLengths.fse.actualTableLog+s.litLengths.fse.actualTableLog <= 56
|
||||
var errCode int
|
||||
if cpuinfo.HasBMI2() {
|
||||
if lte56bits {
|
||||
errCode = sequenceDecs_decode_56_bmi2(s, br, &ctx)
|
||||
} else {
|
||||
errCode = sequenceDecs_decode_bmi2(s, br, &ctx)
|
||||
}
|
||||
} else {
|
||||
if lte56bits {
|
||||
errCode = sequenceDecs_decode_56_amd64(s, br, &ctx)
|
||||
} else {
|
||||
errCode = sequenceDecs_decode_amd64(s, br, &ctx)
|
||||
}
|
||||
}
|
||||
if errCode != 0 {
|
||||
i := len(seqs) - ctx.iteration - 1
|
||||
switch errCode {
|
||||
case errorMatchLenOfsMismatch:
|
||||
ml := ctx.seqs[i].ml
|
||||
return fmt.Errorf("zero matchoff and matchlen (%d) > 0", ml)
|
||||
|
||||
case errorMatchLenTooBig:
|
||||
ml := ctx.seqs[i].ml
|
||||
return fmt.Errorf("match len (%d) bigger than max allowed length", ml)
|
||||
|
||||
case errorNotEnoughLiterals:
|
||||
ll := ctx.seqs[i].ll
|
||||
return fmt.Errorf("unexpected literal count, want %d bytes, but only %d is available", ll, ctx.litRemain+ll)
|
||||
case errorOverread:
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
|
||||
return fmt.Errorf("sequenceDecs_decode_amd64 returned erroneous code %d", errCode)
|
||||
}
|
||||
|
||||
if ctx.litRemain < 0 {
|
||||
return fmt.Errorf("literal count is too big: total available %d, total requested %d",
|
||||
len(s.literals), len(s.literals)-ctx.litRemain)
|
||||
}
|
||||
|
||||
s.seqSize += ctx.litRemain
|
||||
if s.seqSize > maxBlockSize {
|
||||
return fmt.Errorf("output bigger than max block size (%d)", maxBlockSize)
|
||||
}
|
||||
if debugDecoder {
|
||||
println("decode: ", br.remain(), "bits remain on stream. code:", errCode)
|
||||
}
|
||||
err := br.close()
|
||||
if err != nil {
|
||||
printf("Closing sequences: %v, %+v\n", err, *br)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------------
|
||||
|
||||
type executeAsmContext struct {
|
||||
seqs []seqVals
|
||||
seqIndex int
|
||||
out []byte
|
||||
history []byte
|
||||
literals []byte
|
||||
outPosition int
|
||||
litPosition int
|
||||
windowSize int
|
||||
return sequenceDecs_decodeSync_amd64(s, br, ctx)
|
||||
}
|
||||
|
||||
// sequenceDecs_executeSimple_amd64 implements the main loop of sequenceDecs.executeSimple in x86 asm.
|
||||
@@ -334,54 +96,10 @@ func sequenceDecs_executeSimple_amd64(ctx *executeAsmContext) bool
|
||||
//go:noescape
|
||||
func sequenceDecs_executeSimple_safe_amd64(ctx *executeAsmContext) bool
|
||||
|
||||
// executeSimple handles cases when dictionary is not used.
|
||||
func (s *sequenceDecs) executeSimple(seqs []seqVals, hist []byte) error {
|
||||
// Ensure we have enough output size...
|
||||
if len(s.out)+s.seqSize+compressedBlockOverAlloc > cap(s.out) {
|
||||
addBytes := s.seqSize + len(s.out) + compressedBlockOverAlloc
|
||||
s.out = append(s.out, make([]byte, addBytes)...)
|
||||
s.out = s.out[:len(s.out)-addBytes]
|
||||
// executeSimpleAsm runs the executeSimple loop, choosing the safe variant.
|
||||
func executeSimpleAsm(ctx *executeAsmContext, safe bool) bool {
|
||||
if safe {
|
||||
return sequenceDecs_executeSimple_safe_amd64(ctx)
|
||||
}
|
||||
|
||||
if debugDecoder {
|
||||
printf("Execute %d seqs with literals: %d into %d bytes\n", len(seqs), len(s.literals), s.seqSize)
|
||||
}
|
||||
|
||||
var t = len(s.out)
|
||||
out := s.out[:t+s.seqSize]
|
||||
|
||||
ctx := executeAsmContext{
|
||||
seqs: seqs,
|
||||
seqIndex: 0,
|
||||
out: out,
|
||||
history: hist,
|
||||
outPosition: t,
|
||||
litPosition: 0,
|
||||
literals: s.literals,
|
||||
windowSize: s.windowSize,
|
||||
}
|
||||
var ok bool
|
||||
if cap(s.literals) < len(s.literals)+compressedBlockOverAlloc {
|
||||
ok = sequenceDecs_executeSimple_safe_amd64(&ctx)
|
||||
} else {
|
||||
ok = sequenceDecs_executeSimple_amd64(&ctx)
|
||||
}
|
||||
if !ok {
|
||||
return fmt.Errorf("match offset (%d) bigger than current history (%d)",
|
||||
seqs[ctx.seqIndex].mo, ctx.outPosition+len(hist))
|
||||
}
|
||||
s.literals = s.literals[ctx.litPosition:]
|
||||
t = ctx.outPosition
|
||||
|
||||
// Add final literals
|
||||
copy(out[t:], s.literals)
|
||||
if debugDecoder {
|
||||
t += len(s.literals)
|
||||
if t != len(out) {
|
||||
panic(fmt.Errorf("length mismatch, want %d, got %d, ss: %d", len(out), t, s.seqSize))
|
||||
}
|
||||
}
|
||||
s.out = out
|
||||
|
||||
return nil
|
||||
return sequenceDecs_executeSimple_amd64(ctx)
|
||||
}
|
||||
|
||||
2
vendor/github.com/klauspost/compress/zstd/seqdec_amd64.s
generated
vendored
2
vendor/github.com/klauspost/compress/zstd/seqdec_amd64.s
generated
vendored
@@ -1,4 +1,4 @@
|
||||
// Code generated by command: go run gen.go -out ../seqdec_amd64.s -pkg=zstd. DO NOT EDIT.
|
||||
// Code generated by command: go run gen.go -out ../seqdec.s -arch amd64,arm64 -pkg=zstd. DO NOT EDIT.
|
||||
|
||||
//go:build !appengine && !noasm && gc && !noasm
|
||||
|
||||
|
||||
70
vendor/github.com/klauspost/compress/zstd/seqdec_arm64.go
generated
vendored
Normal file
70
vendor/github.com/klauspost/compress/zstd/seqdec_arm64.go
generated
vendored
Normal file
@@ -0,0 +1,70 @@
|
||||
//go:build arm64 && !appengine && !noasm && gc
|
||||
|
||||
package zstd
|
||||
|
||||
// The shared decode/decodeSync/executeSimple wrappers and context structs live
|
||||
// in seqdec_asm.go; this file only declares the arm64 asm routines (generated
|
||||
// by the avo arm64 lowering printer) and the dispatch helpers. arm64 has no
|
||||
// BMI2, so each helper selects only between the 56-bit / safe variants.
|
||||
|
||||
// sequenceDecs_decode_arm64 implements the main loop of sequenceDecs in arm64 asm.
|
||||
//
|
||||
// Please refer to seqdec_generic.go for the reference implementation.
|
||||
//
|
||||
//go:noescape
|
||||
func sequenceDecs_decode_arm64(s *sequenceDecs, br *bitReader, ctx *decodeAsmContext) int
|
||||
|
||||
// sequenceDecs_decode_56_arm64 implements the main loop of sequenceDecs in arm64 asm.
|
||||
//
|
||||
//go:noescape
|
||||
func sequenceDecs_decode_56_arm64(s *sequenceDecs, br *bitReader, ctx *decodeAsmContext) int
|
||||
|
||||
// decodeAsm runs the sequenceDecs decode loop, choosing the 56-bit variant.
|
||||
func decodeAsm(s *sequenceDecs, br *bitReader, ctx *decodeAsmContext, lte56bits bool) int {
|
||||
if lte56bits {
|
||||
return sequenceDecs_decode_56_arm64(s, br, ctx)
|
||||
}
|
||||
return sequenceDecs_decode_arm64(s, br, ctx)
|
||||
}
|
||||
|
||||
// sequenceDecs_decodeSync_arm64 implements the main loop of sequenceDecs.decodeSync in arm64 asm.
|
||||
//
|
||||
// Please refer to seqdec_generic.go for the reference implementation.
|
||||
//
|
||||
//go:noescape
|
||||
func sequenceDecs_decodeSync_arm64(s *sequenceDecs, br *bitReader, ctx *decodeSyncAsmContext) int
|
||||
|
||||
// sequenceDecs_decodeSync_safe_arm64 does the same as above, but does not write more than output buffer.
|
||||
//
|
||||
//go:noescape
|
||||
func sequenceDecs_decodeSync_safe_arm64(s *sequenceDecs, br *bitReader, ctx *decodeSyncAsmContext) int
|
||||
|
||||
// decodeSyncAsm runs the decodeSync loop, choosing the safe variant.
|
||||
func decodeSyncAsm(s *sequenceDecs, br *bitReader, ctx *decodeSyncAsmContext, safe bool) int {
|
||||
if safe {
|
||||
return sequenceDecs_decodeSync_safe_arm64(s, br, ctx)
|
||||
}
|
||||
return sequenceDecs_decodeSync_arm64(s, br, ctx)
|
||||
}
|
||||
|
||||
// sequenceDecs_executeSimple_arm64 implements the main loop of sequenceDecs.executeSimple in arm64 asm.
|
||||
//
|
||||
// Returns false if a match offset is too big.
|
||||
//
|
||||
// Please refer to seqdec_generic.go for the reference implementation.
|
||||
//
|
||||
//go:noescape
|
||||
func sequenceDecs_executeSimple_arm64(ctx *executeAsmContext) bool
|
||||
|
||||
// Same as above, but with safe memcopies
|
||||
//
|
||||
//go:noescape
|
||||
func sequenceDecs_executeSimple_safe_arm64(ctx *executeAsmContext) bool
|
||||
|
||||
// executeSimpleAsm runs the executeSimple loop, choosing the safe variant.
|
||||
func executeSimpleAsm(ctx *executeAsmContext, safe bool) bool {
|
||||
if safe {
|
||||
return sequenceDecs_executeSimple_safe_arm64(ctx)
|
||||
}
|
||||
return sequenceDecs_executeSimple_arm64(ctx)
|
||||
}
|
||||
2705
vendor/github.com/klauspost/compress/zstd/seqdec_arm64.s
generated
vendored
Normal file
2705
vendor/github.com/klauspost/compress/zstd/seqdec_arm64.s
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
289
vendor/github.com/klauspost/compress/zstd/seqdec_asm.go
generated
vendored
Normal file
289
vendor/github.com/klauspost/compress/zstd/seqdec_asm.go
generated
vendored
Normal file
@@ -0,0 +1,289 @@
|
||||
//go:build (amd64 || arm64) && !appengine && !noasm && gc
|
||||
|
||||
package zstd
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
)
|
||||
|
||||
// This file holds the parts of the assembly sequence decoder that are identical
|
||||
// across architectures: the context structs exchanged with the asm, the error
|
||||
// codes, and the decode/decodeSync/executeSimple wrappers. Each architecture
|
||||
// supplies the small dispatch helpers (decodeAsm, decodeSyncAsm,
|
||||
// executeSimpleAsm) that select the concrete asm routine — amd64 also chooses a
|
||||
// BMI2 variant, arm64 has a single implementation.
|
||||
|
||||
type decodeSyncAsmContext struct {
|
||||
llTable []decSymbol
|
||||
mlTable []decSymbol
|
||||
ofTable []decSymbol
|
||||
llState uint64
|
||||
mlState uint64
|
||||
ofState uint64
|
||||
iteration int
|
||||
litRemain int
|
||||
out []byte
|
||||
outPosition int
|
||||
literals []byte
|
||||
litPosition int
|
||||
history []byte
|
||||
windowSize int
|
||||
ll int // set on error (not for all errors, please refer to _generate/gen.go)
|
||||
ml int // set on error (not for all errors, please refer to _generate/gen.go)
|
||||
mo int // set on error (not for all errors, please refer to _generate/gen.go)
|
||||
}
|
||||
|
||||
type decodeAsmContext struct {
|
||||
llTable []decSymbol
|
||||
mlTable []decSymbol
|
||||
ofTable []decSymbol
|
||||
llState uint64
|
||||
mlState uint64
|
||||
ofState uint64
|
||||
iteration int
|
||||
seqs []seqVals
|
||||
litRemain int
|
||||
}
|
||||
|
||||
type executeAsmContext struct {
|
||||
seqs []seqVals
|
||||
seqIndex int
|
||||
out []byte
|
||||
history []byte
|
||||
literals []byte
|
||||
outPosition int
|
||||
litPosition int
|
||||
windowSize int
|
||||
}
|
||||
|
||||
const noError = 0
|
||||
|
||||
// error reported when mo == 0 && ml > 0
|
||||
const errorMatchLenOfsMismatch = 1
|
||||
|
||||
// error reported when ml > maxMatchLen
|
||||
const errorMatchLenTooBig = 2
|
||||
|
||||
// error reported when mo > available history or mo > s.windowSize
|
||||
const errorMatchOffTooBig = 3
|
||||
|
||||
// error reported when the sum of literal lengths exeeceds the literal buffer size
|
||||
const errorNotEnoughLiterals = 4
|
||||
|
||||
// error reported when capacity of `out` is too small
|
||||
const errorNotEnoughSpace = 5
|
||||
|
||||
// error reported when bits are overread.
|
||||
const errorOverread = 6
|
||||
|
||||
// decode sequences from the stream with the provided history but without a dictionary.
|
||||
func (s *sequenceDecs) decodeSyncSimple(hist []byte) (bool, error) {
|
||||
if len(s.dict) > 0 {
|
||||
return false, nil
|
||||
}
|
||||
if s.maxSyncLen == 0 && cap(s.out)-len(s.out) < maxCompressedBlockSize {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
// FIXME: Using unsafe memory copies leads to rare, random crashes
|
||||
// with fuzz testing. It is therefore disabled for now.
|
||||
const useSafe = true
|
||||
|
||||
br := s.br
|
||||
|
||||
maxBlockSize := min(s.windowSize, maxCompressedBlockSize)
|
||||
|
||||
ctx := decodeSyncAsmContext{
|
||||
llTable: s.litLengths.fse.dt[:maxTablesize],
|
||||
mlTable: s.matchLengths.fse.dt[:maxTablesize],
|
||||
ofTable: s.offsets.fse.dt[:maxTablesize],
|
||||
llState: uint64(s.litLengths.state.state),
|
||||
mlState: uint64(s.matchLengths.state.state),
|
||||
ofState: uint64(s.offsets.state.state),
|
||||
iteration: s.nSeqs - 1,
|
||||
litRemain: len(s.literals),
|
||||
out: s.out,
|
||||
outPosition: len(s.out),
|
||||
literals: s.literals,
|
||||
windowSize: s.windowSize,
|
||||
history: hist,
|
||||
}
|
||||
|
||||
s.seqSize = 0
|
||||
startSize := len(s.out)
|
||||
|
||||
errCode := decodeSyncAsm(s, br, &ctx, useSafe)
|
||||
switch errCode {
|
||||
case noError:
|
||||
break
|
||||
|
||||
case errorMatchLenOfsMismatch:
|
||||
return true, fmt.Errorf("zero matchoff and matchlen (%d) > 0", ctx.ml)
|
||||
|
||||
case errorMatchLenTooBig:
|
||||
return true, fmt.Errorf("match len (%d) bigger than max allowed length", ctx.ml)
|
||||
|
||||
case errorMatchOffTooBig:
|
||||
return true, fmt.Errorf("match offset (%d) bigger than current history (%d)",
|
||||
ctx.mo, ctx.outPosition+len(hist)-startSize)
|
||||
|
||||
case errorNotEnoughLiterals:
|
||||
return true, fmt.Errorf("unexpected literal count, want %d bytes, but only %d is available",
|
||||
ctx.ll, ctx.litRemain+ctx.ll)
|
||||
|
||||
case errorOverread:
|
||||
return true, io.ErrUnexpectedEOF
|
||||
|
||||
case errorNotEnoughSpace:
|
||||
size := ctx.outPosition + ctx.ll + ctx.ml
|
||||
if debugDecoder {
|
||||
println("msl:", s.maxSyncLen, "cap", cap(s.out), "bef:", startSize, "sz:", size-startSize, "mbs:", maxBlockSize, "outsz:", cap(s.out)-startSize)
|
||||
}
|
||||
return true, fmt.Errorf("output bigger than max block size (%d)", maxBlockSize)
|
||||
|
||||
default:
|
||||
return true, fmt.Errorf("sequenceDecs_decode returned erroneous code %d", errCode)
|
||||
}
|
||||
|
||||
s.seqSize += ctx.litRemain
|
||||
if s.seqSize > maxBlockSize {
|
||||
return true, fmt.Errorf("output bigger than max block size (%d)", maxBlockSize)
|
||||
}
|
||||
err := br.close()
|
||||
if err != nil {
|
||||
printf("Closing sequences: %v, %+v\n", err, *br)
|
||||
return true, err
|
||||
}
|
||||
|
||||
s.literals = s.literals[ctx.litPosition:]
|
||||
t := ctx.outPosition
|
||||
s.out = s.out[:t]
|
||||
|
||||
// Add final literals
|
||||
s.out = append(s.out, s.literals...)
|
||||
if debugDecoder {
|
||||
t += len(s.literals)
|
||||
if t != len(s.out) {
|
||||
panic(fmt.Errorf("length mismatch, want %d, got %d", len(s.out), t))
|
||||
}
|
||||
}
|
||||
|
||||
return true, nil
|
||||
}
|
||||
|
||||
// decode sequences from the stream without the provided history.
|
||||
func (s *sequenceDecs) decode(seqs []seqVals) error {
|
||||
br := s.br
|
||||
|
||||
maxBlockSize := min(s.windowSize, maxCompressedBlockSize)
|
||||
|
||||
ctx := decodeAsmContext{
|
||||
llTable: s.litLengths.fse.dt[:maxTablesize],
|
||||
mlTable: s.matchLengths.fse.dt[:maxTablesize],
|
||||
ofTable: s.offsets.fse.dt[:maxTablesize],
|
||||
llState: uint64(s.litLengths.state.state),
|
||||
mlState: uint64(s.matchLengths.state.state),
|
||||
ofState: uint64(s.offsets.state.state),
|
||||
seqs: seqs,
|
||||
iteration: len(seqs) - 1,
|
||||
litRemain: len(s.literals),
|
||||
}
|
||||
|
||||
if debugDecoder {
|
||||
println("decode: decoding", len(seqs), "sequences", br.remain(), "bits remain on stream")
|
||||
}
|
||||
|
||||
s.seqSize = 0
|
||||
lte56bits := s.maxBits+s.offsets.fse.actualTableLog+s.matchLengths.fse.actualTableLog+s.litLengths.fse.actualTableLog <= 56
|
||||
errCode := decodeAsm(s, br, &ctx, lte56bits)
|
||||
if errCode != 0 {
|
||||
i := len(seqs) - ctx.iteration - 1
|
||||
switch errCode {
|
||||
case errorMatchLenOfsMismatch:
|
||||
ml := ctx.seqs[i].ml
|
||||
return fmt.Errorf("zero matchoff and matchlen (%d) > 0", ml)
|
||||
|
||||
case errorMatchLenTooBig:
|
||||
ml := ctx.seqs[i].ml
|
||||
return fmt.Errorf("match len (%d) bigger than max allowed length", ml)
|
||||
|
||||
case errorNotEnoughLiterals:
|
||||
ll := ctx.seqs[i].ll
|
||||
return fmt.Errorf("unexpected literal count, want %d bytes, but only %d is available", ll, ctx.litRemain+ll)
|
||||
case errorOverread:
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
|
||||
return fmt.Errorf("sequenceDecs_decode_amd64 returned erroneous code %d", errCode)
|
||||
}
|
||||
|
||||
if ctx.litRemain < 0 {
|
||||
return fmt.Errorf("literal count is too big: total available %d, total requested %d",
|
||||
len(s.literals), len(s.literals)-ctx.litRemain)
|
||||
}
|
||||
|
||||
s.seqSize += ctx.litRemain
|
||||
if s.seqSize > maxBlockSize {
|
||||
return fmt.Errorf("output bigger than max block size (%d)", maxBlockSize)
|
||||
}
|
||||
if debugDecoder {
|
||||
println("decode: ", br.remain(), "bits remain on stream. code:", errCode)
|
||||
}
|
||||
err := br.close()
|
||||
if err != nil {
|
||||
printf("Closing sequences: %v, %+v\n", err, *br)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
// executeSimple handles cases when dictionary is not used.
|
||||
func (s *sequenceDecs) executeSimple(seqs []seqVals, hist []byte) error {
|
||||
// Ensure we have enough output size...
|
||||
if len(s.out)+s.seqSize+compressedBlockOverAlloc > cap(s.out) {
|
||||
addBytes := s.seqSize + len(s.out) + compressedBlockOverAlloc
|
||||
s.out = append(s.out, make([]byte, addBytes)...)
|
||||
s.out = s.out[:len(s.out)-addBytes]
|
||||
}
|
||||
|
||||
if debugDecoder {
|
||||
printf("Execute %d seqs with literals: %d into %d bytes\n", len(seqs), len(s.literals), s.seqSize)
|
||||
}
|
||||
|
||||
var t = len(s.out)
|
||||
out := s.out[:t+s.seqSize]
|
||||
|
||||
ctx := executeAsmContext{
|
||||
seqs: seqs,
|
||||
seqIndex: 0,
|
||||
out: out,
|
||||
history: hist,
|
||||
outPosition: t,
|
||||
litPosition: 0,
|
||||
literals: s.literals,
|
||||
windowSize: s.windowSize,
|
||||
}
|
||||
// useSafe avoids overwriting the output buffer when the literals slice has
|
||||
// not been allocated with the required over-allocation slack.
|
||||
useSafe := cap(s.literals) < len(s.literals)+compressedBlockOverAlloc
|
||||
|
||||
ok := executeSimpleAsm(&ctx, useSafe)
|
||||
if !ok {
|
||||
return fmt.Errorf("match offset (%d) bigger than current history (%d)",
|
||||
seqs[ctx.seqIndex].mo, ctx.outPosition+len(hist))
|
||||
}
|
||||
s.literals = s.literals[ctx.litPosition:]
|
||||
t = ctx.outPosition
|
||||
|
||||
// Add final literals
|
||||
copy(out[t:], s.literals)
|
||||
if debugDecoder {
|
||||
t += len(s.literals)
|
||||
if t != len(out) {
|
||||
panic(fmt.Errorf("length mismatch, want %d, got %d, ss: %d", len(out), t, s.seqSize))
|
||||
}
|
||||
}
|
||||
s.out = out
|
||||
|
||||
return nil
|
||||
}
|
||||
2
vendor/github.com/klauspost/compress/zstd/seqdec_generic.go
generated
vendored
2
vendor/github.com/klauspost/compress/zstd/seqdec_generic.go
generated
vendored
@@ -1,4 +1,4 @@
|
||||
//go:build !amd64 || appengine || !gc || noasm
|
||||
//go:build (!amd64 && !arm64) || appengine || !gc || noasm
|
||||
|
||||
package zstd
|
||||
|
||||
|
||||
7
vendor/github.com/klauspost/compress/zstd/snappy.go
generated
vendored
7
vendor/github.com/klauspost/compress/zstd/snappy.go
generated
vendored
@@ -334,9 +334,10 @@ func decodeSnappy(blk *blockEnc, src []byte) error {
|
||||
|
||||
return errUnsupportedLiteralLength
|
||||
}
|
||||
//if length > snappyMaxBlockSize-d || uint32(length) > len(src)-s {
|
||||
// return ErrSnappyCorrupt
|
||||
//}
|
||||
if length > len(src)-s {
|
||||
println("length > len(src)-s", length, len(src)-s)
|
||||
return ErrSnappyCorrupt
|
||||
}
|
||||
|
||||
blk.literals = append(blk.literals, src[s:s+length]...)
|
||||
//println(length, "litLen")
|
||||
|
||||
@@ -90,7 +90,7 @@ loop:
|
||||
s = skipSpace(s[1:])
|
||||
}
|
||||
}
|
||||
return
|
||||
return specs
|
||||
}
|
||||
|
||||
func skipSpace(s string) (rest string) {
|
||||
|
||||
11
vendor/github.com/prometheus/client_golang/prometheus/counter.go
generated
vendored
11
vendor/github.com/prometheus/client_golang/prometheus/counter.go
generated
vendored
@@ -85,11 +85,12 @@ type CounterVecOpts struct {
|
||||
// Both internal tracking values are added up in the Write method. This has to
|
||||
// be taken into account when it comes to precision and overflow behavior.
|
||||
func NewCounter(opts CounterOpts) Counter {
|
||||
desc := NewDesc(
|
||||
desc := V2.NewDesc(
|
||||
BuildFQName(opts.Namespace, opts.Subsystem, opts.Name),
|
||||
opts.Help,
|
||||
nil,
|
||||
UnconstrainedLabels(nil),
|
||||
opts.ConstLabels,
|
||||
WithUnit(opts.Unit),
|
||||
)
|
||||
if opts.now == nil {
|
||||
opts.now = time.Now
|
||||
@@ -205,6 +206,7 @@ func (v2) NewCounterVec(opts CounterVecOpts) *CounterVec {
|
||||
opts.Help,
|
||||
opts.VariableLabels,
|
||||
opts.ConstLabels,
|
||||
WithUnit(opts.Unit),
|
||||
)
|
||||
if opts.now == nil {
|
||||
opts.now = time.Now
|
||||
@@ -349,10 +351,11 @@ type CounterFunc interface {
|
||||
//
|
||||
// Check out the ExampleGaugeFunc examples for the similar GaugeFunc.
|
||||
func NewCounterFunc(opts CounterOpts, function func() float64) CounterFunc {
|
||||
return newValueFunc(NewDesc(
|
||||
return newValueFunc(V2.NewDesc(
|
||||
BuildFQName(opts.Namespace, opts.Subsystem, opts.Name),
|
||||
opts.Help,
|
||||
nil,
|
||||
UnconstrainedLabels(nil),
|
||||
opts.ConstLabels,
|
||||
WithUnit(opts.Unit),
|
||||
), CounterValue, function)
|
||||
}
|
||||
|
||||
37
vendor/github.com/prometheus/client_golang/prometheus/desc.go
generated
vendored
37
vendor/github.com/prometheus/client_golang/prometheus/desc.go
generated
vendored
@@ -47,6 +47,8 @@ type Desc struct {
|
||||
fqName string
|
||||
// help provides some helpful information about this metric.
|
||||
help string
|
||||
// unit provides the unit of this metric.
|
||||
unit string
|
||||
// constLabelPairs contains precalculated DTO label pairs based on
|
||||
// the constant labels.
|
||||
constLabelPairs []*dto.LabelPair
|
||||
@@ -66,6 +68,16 @@ type Desc struct {
|
||||
err error
|
||||
}
|
||||
|
||||
// DescOpt allows setting optional fields for NewDesc.
|
||||
type DescOpt func(*Desc)
|
||||
|
||||
// WithUnit sets the unit for a Desc.
|
||||
func WithUnit(unit string) DescOpt {
|
||||
return func(d *Desc) {
|
||||
d.unit = unit
|
||||
}
|
||||
}
|
||||
|
||||
// NewDesc allocates and initializes a new Desc. Errors are recorded in the Desc
|
||||
// and will be reported on registration time. variableLabels and constLabels can
|
||||
// be nil if no such labels should be set. fqName must not be empty.
|
||||
@@ -89,14 +101,17 @@ func NewDesc(fqName, help string, variableLabels []string, constLabels Labels) *
|
||||
//
|
||||
// For constLabels, the label values are constant. Therefore, they are fully
|
||||
// specified in the Desc. See the Collector example for a usage pattern.
|
||||
func (v2) NewDesc(fqName, help string, variableLabels ConstrainableLabels, constLabels Labels) *Desc {
|
||||
func (v2) NewDesc(fqName, help string, variableLabels ConstrainableLabels, constLabels Labels, opts ...DescOpt) *Desc {
|
||||
d := &Desc{
|
||||
fqName: fqName,
|
||||
help: help,
|
||||
variableLabels: variableLabels.compile(),
|
||||
}
|
||||
//nolint:staticcheck // TODO: Don't use deprecated model.NameValidationScheme.
|
||||
if !model.NameValidationScheme.IsValidMetricName(fqName) {
|
||||
|
||||
for _, opt := range opts {
|
||||
opt(d)
|
||||
}
|
||||
if !model.UTF8Validation.IsValidMetricName(fqName) {
|
||||
d.err = fmt.Errorf("%q is not a valid metric name", fqName)
|
||||
return d
|
||||
}
|
||||
@@ -150,11 +165,13 @@ func (v2) NewDesc(fqName, help string, variableLabels ConstrainableLabels, const
|
||||
d.id = xxh.Sum64()
|
||||
// Sort labelNames so that order doesn't matter for the hash.
|
||||
sort.Strings(labelNames)
|
||||
// Now hash together (in this order) the help string and the sorted
|
||||
// Now hash together (in this order) the help string, the unit string and the sorted
|
||||
// label names.
|
||||
xxh.Reset()
|
||||
xxh.WriteString(help)
|
||||
xxh.Write(separatorByteSlice)
|
||||
xxh.WriteString(d.unit)
|
||||
xxh.Write(separatorByteSlice)
|
||||
for _, labelName := range labelNames {
|
||||
xxh.WriteString(labelName)
|
||||
xxh.Write(separatorByteSlice)
|
||||
@@ -182,6 +199,15 @@ func NewInvalidDesc(err error) *Desc {
|
||||
}
|
||||
}
|
||||
|
||||
// Err returns an error that occurred during construction, if any.
|
||||
//
|
||||
// Calling this method is optional. It can be used to detect construction
|
||||
// errors early, before invoking other methods on the Desc. If an error is
|
||||
// present, later operations may not behave as expected.
|
||||
func (d *Desc) Err() error {
|
||||
return d.err
|
||||
}
|
||||
|
||||
func (d *Desc) String() string {
|
||||
lpStrings := make([]string, 0, len(d.constLabelPairs))
|
||||
for _, lp := range d.constLabelPairs {
|
||||
@@ -202,9 +228,10 @@ func (d *Desc) String() string {
|
||||
}
|
||||
}
|
||||
return fmt.Sprintf(
|
||||
"Desc{fqName: %q, help: %q, constLabels: {%s}, variableLabels: {%s}}",
|
||||
"Desc{fqName: %q, help: %q, unit: %q, constLabels: {%s}, variableLabels: {%s}}",
|
||||
d.fqName,
|
||||
d.help,
|
||||
d.unit,
|
||||
strings.Join(lpStrings, ","),
|
||||
strings.Join(vlStrings, ","),
|
||||
)
|
||||
|
||||
8
vendor/github.com/prometheus/client_golang/prometheus/expvar_collector.go
generated
vendored
8
vendor/github.com/prometheus/client_golang/prometheus/expvar_collector.go
generated
vendored
@@ -47,14 +47,14 @@ func (e *expvarCollector) Collect(ch chan<- Metric) {
|
||||
if expVar == nil {
|
||||
continue
|
||||
}
|
||||
var v interface{}
|
||||
var v any
|
||||
labels := make([]string, len(desc.variableLabels.names))
|
||||
if err := json.Unmarshal([]byte(expVar.String()), &v); err != nil {
|
||||
ch <- NewInvalidMetric(desc, err)
|
||||
continue
|
||||
}
|
||||
var processValue func(v interface{}, i int)
|
||||
processValue = func(v interface{}, i int) {
|
||||
var processValue func(v any, i int)
|
||||
processValue = func(v any, i int) {
|
||||
if i >= len(labels) {
|
||||
copiedLabels := append(make([]string, 0, len(labels)), labels...)
|
||||
switch v := v.(type) {
|
||||
@@ -72,7 +72,7 @@ func (e *expvarCollector) Collect(ch chan<- Metric) {
|
||||
ch <- m
|
||||
return
|
||||
}
|
||||
vm, ok := v.(map[string]interface{})
|
||||
vm, ok := v.(map[string]any)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
|
||||
11
vendor/github.com/prometheus/client_golang/prometheus/gauge.go
generated
vendored
11
vendor/github.com/prometheus/client_golang/prometheus/gauge.go
generated
vendored
@@ -76,11 +76,12 @@ type GaugeVecOpts struct {
|
||||
// scenarios for Gauges and Counters, where the former tends to be Set-heavy and
|
||||
// the latter Inc-heavy.
|
||||
func NewGauge(opts GaugeOpts) Gauge {
|
||||
desc := NewDesc(
|
||||
desc := V2.NewDesc(
|
||||
BuildFQName(opts.Namespace, opts.Subsystem, opts.Name),
|
||||
opts.Help,
|
||||
nil,
|
||||
UnconstrainedLabels(nil),
|
||||
opts.ConstLabels,
|
||||
WithUnit(opts.Unit),
|
||||
)
|
||||
result := &gauge{desc: desc, labelPairs: desc.constLabelPairs}
|
||||
result.init(result) // Init self-collection.
|
||||
@@ -163,6 +164,7 @@ func (v2) NewGaugeVec(opts GaugeVecOpts) *GaugeVec {
|
||||
opts.Help,
|
||||
opts.VariableLabels,
|
||||
opts.ConstLabels,
|
||||
WithUnit(opts.Unit),
|
||||
)
|
||||
return &GaugeVec{
|
||||
MetricVec: NewMetricVec(desc, func(lvs ...string) Metric {
|
||||
@@ -302,10 +304,11 @@ type GaugeFunc interface {
|
||||
// value of 1. Example:
|
||||
// https://github.com/prometheus/common/blob/8558a5b7db3c84fa38b4766966059a7bd5bfa2ee/version/info.go#L36-L56
|
||||
func NewGaugeFunc(opts GaugeOpts, function func() float64) GaugeFunc {
|
||||
return newValueFunc(NewDesc(
|
||||
return newValueFunc(V2.NewDesc(
|
||||
BuildFQName(opts.Namespace, opts.Subsystem, opts.Name),
|
||||
opts.Help,
|
||||
nil,
|
||||
UnconstrainedLabels(nil),
|
||||
opts.ConstLabels,
|
||||
WithUnit(opts.Unit),
|
||||
), GaugeValue, function)
|
||||
}
|
||||
|
||||
122
vendor/github.com/prometheus/client_golang/prometheus/go_collector_go116.go
generated
vendored
122
vendor/github.com/prometheus/client_golang/prometheus/go_collector_go116.go
generated
vendored
@@ -1,122 +0,0 @@
|
||||
// Copyright 2021 The Prometheus Authors
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
//go:build !go1.17
|
||||
// +build !go1.17
|
||||
|
||||
package prometheus
|
||||
|
||||
import (
|
||||
"runtime"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
type goCollector struct {
|
||||
base baseGoCollector
|
||||
|
||||
// ms... are memstats related.
|
||||
msLast *runtime.MemStats // Previously collected memstats.
|
||||
msLastTimestamp time.Time
|
||||
msMtx sync.Mutex // Protects msLast and msLastTimestamp.
|
||||
msMetrics memStatsMetrics
|
||||
msRead func(*runtime.MemStats) // For mocking in tests.
|
||||
msMaxWait time.Duration // Wait time for fresh memstats.
|
||||
msMaxAge time.Duration // Maximum allowed age of old memstats.
|
||||
}
|
||||
|
||||
// NewGoCollector is the obsolete version of collectors.NewGoCollector.
|
||||
// See there for documentation.
|
||||
//
|
||||
// Deprecated: Use collectors.NewGoCollector instead.
|
||||
func NewGoCollector() Collector {
|
||||
msMetrics := goRuntimeMemStats()
|
||||
msMetrics = append(msMetrics, struct {
|
||||
desc *Desc
|
||||
eval func(*runtime.MemStats) float64
|
||||
valType ValueType
|
||||
}{
|
||||
// This metric is omitted in Go1.17+, see https://github.com/prometheus/client_golang/issues/842#issuecomment-861812034
|
||||
desc: NewDesc(
|
||||
memstatNamespace("gc_cpu_fraction"),
|
||||
"The fraction of this program's available CPU time used by the GC since the program started.",
|
||||
nil, nil,
|
||||
),
|
||||
eval: func(ms *runtime.MemStats) float64 { return ms.GCCPUFraction },
|
||||
valType: GaugeValue,
|
||||
})
|
||||
return &goCollector{
|
||||
base: newBaseGoCollector(),
|
||||
msLast: &runtime.MemStats{},
|
||||
msRead: runtime.ReadMemStats,
|
||||
msMaxWait: time.Second,
|
||||
msMaxAge: 5 * time.Minute,
|
||||
msMetrics: msMetrics,
|
||||
}
|
||||
}
|
||||
|
||||
// Describe returns all descriptions of the collector.
|
||||
func (c *goCollector) Describe(ch chan<- *Desc) {
|
||||
c.base.Describe(ch)
|
||||
for _, i := range c.msMetrics {
|
||||
ch <- i.desc
|
||||
}
|
||||
}
|
||||
|
||||
// Collect returns the current state of all metrics of the collector.
|
||||
func (c *goCollector) Collect(ch chan<- Metric) {
|
||||
var (
|
||||
ms = &runtime.MemStats{}
|
||||
done = make(chan struct{})
|
||||
)
|
||||
// Start reading memstats first as it might take a while.
|
||||
go func() {
|
||||
c.msRead(ms)
|
||||
c.msMtx.Lock()
|
||||
c.msLast = ms
|
||||
c.msLastTimestamp = time.Now()
|
||||
c.msMtx.Unlock()
|
||||
close(done)
|
||||
}()
|
||||
|
||||
// Collect base non-memory metrics.
|
||||
c.base.Collect(ch)
|
||||
|
||||
timer := time.NewTimer(c.msMaxWait)
|
||||
select {
|
||||
case <-done: // Our own ReadMemStats succeeded in time. Use it.
|
||||
timer.Stop() // Important for high collection frequencies to not pile up timers.
|
||||
c.msCollect(ch, ms)
|
||||
return
|
||||
case <-timer.C: // Time out, use last memstats if possible. Continue below.
|
||||
}
|
||||
c.msMtx.Lock()
|
||||
if time.Since(c.msLastTimestamp) < c.msMaxAge {
|
||||
// Last memstats are recent enough. Collect from them under the lock.
|
||||
c.msCollect(ch, c.msLast)
|
||||
c.msMtx.Unlock()
|
||||
return
|
||||
}
|
||||
// If we are here, the last memstats are too old or don't exist. We have
|
||||
// to wait until our own ReadMemStats finally completes. For that to
|
||||
// happen, we have to release the lock.
|
||||
c.msMtx.Unlock()
|
||||
<-done
|
||||
c.msCollect(ch, ms)
|
||||
}
|
||||
|
||||
func (c *goCollector) msCollect(ch chan<- Metric, ms *runtime.MemStats) {
|
||||
for _, i := range c.msMetrics {
|
||||
ch <- MustNewConstMetric(i.desc, i.valType, i.eval(ms))
|
||||
}
|
||||
}
|
||||
20
vendor/github.com/prometheus/client_golang/prometheus/go_collector_latest.go
generated
vendored
20
vendor/github.com/prometheus/client_golang/prometheus/go_collector_latest.go
generated
vendored
@@ -98,7 +98,7 @@ type goCollector struct {
|
||||
// snapshot is always produced by Collect.
|
||||
mu sync.Mutex
|
||||
|
||||
// Contains all samples that has to retrieved from runtime/metrics (not all of them will be exposed).
|
||||
// Contains all samples that have to be retrieved from runtime/metrics (not all of them will be exposed).
|
||||
sampleBuf []metrics.Sample
|
||||
// sampleMap allows lookup for MemStats metrics and runtime/metrics histograms for exact sums.
|
||||
sampleMap map[string]*metrics.Sample
|
||||
@@ -210,16 +210,26 @@ func NewGoCollector(opts ...func(o *internal.GoCollectorOptions)) Collector {
|
||||
sampleBuf = append(sampleBuf, metrics.Sample{Name: d.Name})
|
||||
sampleMap[d.Name] = &sampleBuf[len(sampleBuf)-1]
|
||||
|
||||
// Extract unit from the runtime/metrics name (e.g., "/gc/heap/allocs:bytes" -> "bytes")
|
||||
// and sanitize to match Prometheus naming conventions (e.g., "cpu-seconds" -> "cpu_seconds")
|
||||
var unit string
|
||||
if idx := strings.IndexRune(d.Name, ':'); idx >= 0 {
|
||||
unit = d.Name[idx+1:]
|
||||
unit = strings.ReplaceAll(unit, "-", "_")
|
||||
unit = strings.ReplaceAll(unit, "*", "_")
|
||||
unit = strings.ReplaceAll(unit, "/", "_per_")
|
||||
}
|
||||
|
||||
var m collectorMetric
|
||||
if d.Kind == metrics.KindFloat64Histogram {
|
||||
_, hasSum := opt.RuntimeMetricSumForHist[d.Name]
|
||||
unit := d.Name[strings.IndexRune(d.Name, ':')+1:]
|
||||
m = newBatchHistogram(
|
||||
NewDesc(
|
||||
V2.NewDesc(
|
||||
BuildFQName(namespace, subsystem, name),
|
||||
help,
|
||||
UnconstrainedLabels(nil),
|
||||
nil,
|
||||
nil,
|
||||
WithUnit(unit),
|
||||
),
|
||||
internal.RuntimeMetricsBucketsForUnit(bucketsMap[d.Name], unit),
|
||||
hasSum,
|
||||
@@ -230,6 +240,7 @@ func NewGoCollector(opts ...func(o *internal.GoCollectorOptions)) Collector {
|
||||
Subsystem: subsystem,
|
||||
Name: name,
|
||||
Help: help,
|
||||
Unit: unit,
|
||||
},
|
||||
)
|
||||
} else {
|
||||
@@ -238,6 +249,7 @@ func NewGoCollector(opts ...func(o *internal.GoCollectorOptions)) Collector {
|
||||
Subsystem: subsystem,
|
||||
Name: name,
|
||||
Help: help,
|
||||
Unit: unit,
|
||||
})
|
||||
}
|
||||
metricSet = append(metricSet, m)
|
||||
|
||||
29
vendor/github.com/prometheus/client_golang/prometheus/histogram.go
generated
vendored
29
vendor/github.com/prometheus/client_golang/prometheus/histogram.go
generated
vendored
@@ -378,6 +378,9 @@ type HistogramOpts struct {
|
||||
// string.
|
||||
Help string
|
||||
|
||||
// Unit provides the unit of this Histogram.
|
||||
Unit string
|
||||
|
||||
// ConstLabels are used to attach fixed labels to this metric. Metrics
|
||||
// with the same fully-qualified name must have the same label names in
|
||||
// their ConstLabels.
|
||||
@@ -522,11 +525,12 @@ type HistogramVecOpts struct {
|
||||
// for each bucket.
|
||||
func NewHistogram(opts HistogramOpts) Histogram {
|
||||
return newHistogram(
|
||||
NewDesc(
|
||||
V2.NewDesc(
|
||||
BuildFQName(opts.Namespace, opts.Subsystem, opts.Name),
|
||||
opts.Help,
|
||||
nil,
|
||||
UnconstrainedLabels(nil),
|
||||
opts.ConstLabels,
|
||||
WithUnit(opts.Unit),
|
||||
),
|
||||
opts,
|
||||
)
|
||||
@@ -966,7 +970,7 @@ func (h *histogram) maybeReset(
|
||||
// We are using the possibly mocked h.now() rather than
|
||||
// time.Since(h.lastResetTime) to enable testing.
|
||||
if h.nativeHistogramMinResetDuration == 0 || // No reset configured.
|
||||
h.resetScheduled || // Do not interefere if a reset is already scheduled.
|
||||
h.resetScheduled || // Do not interfere if a reset is already scheduled.
|
||||
h.now().Sub(h.lastResetTime) < h.nativeHistogramMinResetDuration {
|
||||
return false
|
||||
}
|
||||
@@ -1053,8 +1057,8 @@ func (h *histogram) maybeWidenZeroBucket(hot, cold *histogramCounts) bool {
|
||||
atomic.StoreUint64(&cold.nativeHistogramZeroThresholdBits, math.Float64bits(newZeroThreshold))
|
||||
// ...and then merge the newly deleted buckets into the wider zero
|
||||
// bucket.
|
||||
mergeAndDeleteOrAddAndReset := func(hotBuckets, coldBuckets *sync.Map) func(k, v interface{}) bool {
|
||||
return func(k, v interface{}) bool {
|
||||
mergeAndDeleteOrAddAndReset := func(hotBuckets, coldBuckets *sync.Map) func(k, v any) bool {
|
||||
return func(k, v any) bool {
|
||||
key := k.(int)
|
||||
bucket := v.(*int64)
|
||||
if key == smallestKey {
|
||||
@@ -1107,8 +1111,8 @@ func (h *histogram) doubleBucketWidth(hot, cold *histogramCounts) {
|
||||
// ...adjust the schema in the cold counts, too...
|
||||
atomic.StoreInt32(&cold.nativeHistogramSchema, coldSchema)
|
||||
// ...and then merge the cold buckets into the wider hot buckets.
|
||||
merge := func(hotBuckets *sync.Map) func(k, v interface{}) bool {
|
||||
return func(k, v interface{}) bool {
|
||||
merge := func(hotBuckets *sync.Map) func(k, v any) bool {
|
||||
return func(k, v any) bool {
|
||||
key := k.(int)
|
||||
bucket := v.(*int64)
|
||||
// Adjust key to match the bucket to merge into.
|
||||
@@ -1190,6 +1194,7 @@ func (v2) NewHistogramVec(opts HistogramVecOpts) *HistogramVec {
|
||||
opts.Help,
|
||||
opts.VariableLabels,
|
||||
opts.ConstLabels,
|
||||
WithUnit(opts.Unit),
|
||||
)
|
||||
return &HistogramVec{
|
||||
MetricVec: NewMetricVec(desc, func(lvs ...string) Metric {
|
||||
@@ -1476,7 +1481,7 @@ func pickSchema(bucketFactor float64) int32 {
|
||||
|
||||
func makeBuckets(buckets *sync.Map) ([]*dto.BucketSpan, []int64) {
|
||||
var ii []int
|
||||
buckets.Range(func(k, v interface{}) bool {
|
||||
buckets.Range(func(k, v any) bool {
|
||||
ii = append(ii, k.(int))
|
||||
return true
|
||||
})
|
||||
@@ -1553,8 +1558,8 @@ func addToBucket(buckets *sync.Map, key int, increment int64) bool {
|
||||
// according to the buckets ranged through. It then resets all buckets ranged
|
||||
// through to 0 (but leaves them in place so that they don't need to get
|
||||
// recreated on the next scrape).
|
||||
func addAndReset(hotBuckets *sync.Map, bucketNumber *uint32) func(k, v interface{}) bool {
|
||||
return func(k, v interface{}) bool {
|
||||
func addAndReset(hotBuckets *sync.Map, bucketNumber *uint32) func(k, v any) bool {
|
||||
return func(k, v any) bool {
|
||||
bucket := v.(*int64)
|
||||
if addToBucket(hotBuckets, k.(int), atomic.LoadInt64(bucket)) {
|
||||
atomic.AddUint32(bucketNumber, 1)
|
||||
@@ -1565,7 +1570,7 @@ func addAndReset(hotBuckets *sync.Map, bucketNumber *uint32) func(k, v interface
|
||||
}
|
||||
|
||||
func deleteSyncMap(m *sync.Map) {
|
||||
m.Range(func(k, v interface{}) bool {
|
||||
m.Range(func(k, v any) bool {
|
||||
m.Delete(k)
|
||||
return true
|
||||
})
|
||||
@@ -1573,7 +1578,7 @@ func deleteSyncMap(m *sync.Map) {
|
||||
|
||||
func findSmallestKey(m *sync.Map) int {
|
||||
result := math.MaxInt32
|
||||
m.Range(func(k, v interface{}) bool {
|
||||
m.Range(func(k, v any) bool {
|
||||
key := k.(int)
|
||||
if key < result {
|
||||
result = key
|
||||
|
||||
4
vendor/github.com/prometheus/client_golang/prometheus/internal/difflib.go
generated
vendored
4
vendor/github.com/prometheus/client_golang/prometheus/internal/difflib.go
generated
vendored
@@ -78,7 +78,7 @@ type OpCode struct {
|
||||
// notion, pairing up elements that appear uniquely in each sequence.
|
||||
// That, and the method here, appear to yield more intuitive difference
|
||||
// reports than does diff. This method appears to be the least vulnerable
|
||||
// to synching up on blocks of "junk lines", though (like blank lines in
|
||||
// to syncing up on blocks of "junk lines", though (like blank lines in
|
||||
// ordinary text files, or maybe "<P>" lines in HTML files). That may be
|
||||
// because this is the only method of the 3 that has a *concept* of
|
||||
// "junk" <wink>.
|
||||
@@ -567,7 +567,7 @@ type UnifiedDiff struct {
|
||||
func WriteUnifiedDiff(writer io.Writer, diff UnifiedDiff) error {
|
||||
buf := bufio.NewWriter(writer)
|
||||
defer buf.Flush()
|
||||
wf := func(format string, args ...interface{}) error {
|
||||
wf := func(format string, args ...any) error {
|
||||
_, err := fmt.Fprintf(buf, format, args...)
|
||||
return err
|
||||
}
|
||||
|
||||
3
vendor/github.com/prometheus/client_golang/prometheus/labels.go
generated
vendored
3
vendor/github.com/prometheus/client_golang/prometheus/labels.go
generated
vendored
@@ -184,6 +184,5 @@ func validateLabelValues(vals []string, expectedNumberOfValues int) error {
|
||||
}
|
||||
|
||||
func checkLabelName(l string) bool {
|
||||
//nolint:staticcheck // TODO: Don't use deprecated model.NameValidationScheme.
|
||||
return model.NameValidationScheme.IsValidLabelName(l) && !strings.HasPrefix(l, reservedLabelPrefix)
|
||||
return model.UTF8Validation.IsValidLabelName(l) && !strings.HasPrefix(l, reservedLabelPrefix)
|
||||
}
|
||||
|
||||
3
vendor/github.com/prometheus/client_golang/prometheus/metric.go
generated
vendored
3
vendor/github.com/prometheus/client_golang/prometheus/metric.go
generated
vendored
@@ -81,6 +81,9 @@ type Opts struct {
|
||||
// string.
|
||||
Help string
|
||||
|
||||
// Unit provides the unit of this metric as per https://prometheus.io/docs/specs/om
|
||||
Unit string
|
||||
|
||||
// ConstLabels are used to attach fixed labels to this metric. Metrics
|
||||
// with the same fully-qualified name must have the same label names in
|
||||
// their ConstLabels.
|
||||
|
||||
13
vendor/github.com/prometheus/client_golang/prometheus/process_collector_darwin.go
generated
vendored
13
vendor/github.com/prometheus/client_golang/prometheus/process_collector_darwin.go
generated
vendored
@@ -72,7 +72,13 @@ func getOpenFileCount() (float64, error) {
|
||||
}
|
||||
|
||||
func (c *processCollector) processCollect(ch chan<- Metric) {
|
||||
if procs, err := unix.SysctlKinfoProcSlice("kern.proc.pid", os.Getpid()); err == nil {
|
||||
pid, err := c.pidFn()
|
||||
if err != nil {
|
||||
c.reportError(ch, nil, err)
|
||||
return
|
||||
}
|
||||
|
||||
if procs, err := unix.SysctlKinfoProcSlice("kern.proc.pid", pid); err == nil {
|
||||
if len(procs) == 1 {
|
||||
startTime := float64(procs[0].Proc.P_starttime.Nano() / 1e9)
|
||||
ch <- MustNewConstMetric(c.startTime, GaugeValue, startTime)
|
||||
@@ -84,6 +90,11 @@ func (c *processCollector) processCollect(ch chan<- Metric) {
|
||||
c.reportError(ch, c.startTime, err)
|
||||
}
|
||||
|
||||
if pid != os.Getpid() {
|
||||
c.reportError(ch, nil, fmt.Errorf("collecting metrics for pid %d is not supported on darwin: process metrics collection is limited to the current process (pid %d)", pid, os.Getpid()))
|
||||
return
|
||||
}
|
||||
|
||||
// The proc structure returned by kern.proc.pid above has an Rusage member,
|
||||
// but it is not filled in, so it needs to be fetched by getrusage(2). For
|
||||
// that call, the UTime, STime, and Maxrss members are filled out, but not
|
||||
|
||||
19
vendor/github.com/prometheus/client_golang/prometheus/process_collector_windows.go
generated
vendored
19
vendor/github.com/prometheus/client_golang/prometheus/process_collector_windows.go
generated
vendored
@@ -30,6 +30,10 @@ var (
|
||||
|
||||
procGetProcessMemoryInfo = modpsapi.NewProc("GetProcessMemoryInfo")
|
||||
procGetProcessHandleCount = modkernel32.NewProc("GetProcessHandleCount")
|
||||
|
||||
openProcess = windows.OpenProcess
|
||||
closeHandle = windows.CloseHandle
|
||||
getProcessTimes = windows.GetProcessTimes
|
||||
)
|
||||
|
||||
type processMemoryCounters struct {
|
||||
@@ -79,10 +83,21 @@ func getProcessHandleCount(handle windows.Handle) (uint32, error) {
|
||||
}
|
||||
|
||||
func (c *processCollector) processCollect(ch chan<- Metric) {
|
||||
h := windows.CurrentProcess()
|
||||
pid, err := c.pidFn()
|
||||
if err != nil {
|
||||
c.reportError(ch, nil, err)
|
||||
return
|
||||
}
|
||||
|
||||
h, err := openProcess(windows.PROCESS_QUERY_INFORMATION|windows.PROCESS_VM_READ, false, uint32(pid))
|
||||
if err != nil {
|
||||
c.reportError(ch, nil, err)
|
||||
return
|
||||
}
|
||||
defer closeHandle(h)
|
||||
|
||||
var startTime, exitTime, kernelTime, userTime windows.Filetime
|
||||
err := windows.GetProcessTimes(h, &startTime, &exitTime, &kernelTime, &userTime)
|
||||
err = getProcessTimes(h, &startTime, &exitTime, &kernelTime, &userTime)
|
||||
if err != nil {
|
||||
c.reportError(ch, nil, err)
|
||||
return
|
||||
|
||||
197
vendor/github.com/prometheus/client_golang/prometheus/promhttp/http.go
generated
vendored
197
vendor/github.com/prometheus/client_golang/prometheus/promhttp/http.go
generated
vendored
@@ -37,10 +37,12 @@ import (
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"slices"
|
||||
"strconv"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
dto "github.com/prometheus/client_model/go"
|
||||
"github.com/prometheus/common/expfmt"
|
||||
|
||||
"github.com/prometheus/client_golang/internal/github.com/golang/gddo/httputil"
|
||||
@@ -74,11 +76,118 @@ func defaultCompressionFormats() []Compression {
|
||||
}
|
||||
|
||||
var gzipPool = sync.Pool{
|
||||
New: func() interface{} {
|
||||
New: func() any {
|
||||
return gzip.NewWriter(nil)
|
||||
},
|
||||
}
|
||||
|
||||
// coalescingGatherer wraps a TransactionalGatherer to deduplicate concurrent
|
||||
// Gather calls. When a Gather is already in flight, new callers join the
|
||||
// existing cycle and receive the same result once it completes. The underlying
|
||||
// done function is called exactly once, when the last joined caller releases.
|
||||
//
|
||||
// This prevents goroutine pile-up when the scrape rate is faster than the
|
||||
// time collectors need to produce metrics.
|
||||
type coalescingGatherer struct {
|
||||
g prometheus.TransactionalGatherer
|
||||
mu sync.Mutex
|
||||
cycle *gatherCycle
|
||||
}
|
||||
|
||||
// gatherCycle tracks a single in-flight Gather and all HTTP handlers sharing it.
|
||||
type gatherCycle struct {
|
||||
ready chan struct{} // closed when Gather completes; happens-before reads of mfs/err/done
|
||||
mfs []*dto.MetricFamily // canonical result, set before ready is closed; callers get a slices.Clone, the element values stay shared and must not be mutated
|
||||
err error // set before ready is closed
|
||||
done func() // underlying done callback; set before ready is closed
|
||||
refs int // number of handlers using this cycle; protected by coalescingGatherer.mu
|
||||
}
|
||||
|
||||
var _ prometheus.TransactionalGatherer = (*coalescingGatherer)(nil) // compile-time interface check
|
||||
|
||||
// errGatherPanicked is returned to callers that joined an in-flight coalesced
|
||||
// Gather whose underlying gatherer panicked. See the panic guard in Gather for
|
||||
// why joiners receive this error instead of the panic itself.
|
||||
var errGatherPanicked = errors.New("coalesced gather panicked")
|
||||
|
||||
func (c *coalescingGatherer) Gather() ([]*dto.MetricFamily, func(), error) {
|
||||
c.mu.Lock()
|
||||
if cy := c.cycle; cy != nil {
|
||||
// c.cycle is non-nil while Gather runs or handlers are still consuming its results.
|
||||
cy.refs++
|
||||
c.mu.Unlock()
|
||||
<-cy.ready
|
||||
// Each caller gets its own slice header so it can filter or reorder
|
||||
// without racing other callers sharing this cycle. The *dto.MetricFamily
|
||||
// values remain shared and must not be mutated in place.
|
||||
return slices.Clone(cy.mfs), c.releaseFunc(cy), cy.err
|
||||
}
|
||||
cy := &gatherCycle{
|
||||
ready: make(chan struct{}),
|
||||
done: func() {},
|
||||
refs: 1,
|
||||
}
|
||||
c.cycle = cy
|
||||
c.mu.Unlock()
|
||||
|
||||
// Guard against a panic in c.g.Gather. The common case, a panicking
|
||||
// Collector, never reaches here: Registry.Gather recovers Collector panics
|
||||
// and returns them as an error. This guard only covers the rare case where
|
||||
// the wrapped gatherer itself panics.
|
||||
//
|
||||
// We deliberately do not recover: the leader's panic propagates and is
|
||||
// handled by net/http exactly as it would be without coalescing. We only
|
||||
// set cy.err before closing cy.ready so joiners waiting on <-cy.ready fail
|
||||
// with that error instead of silently returning an empty, successful
|
||||
// response, and we clear c.cycle so the next Gather starts a fresh cycle.
|
||||
//
|
||||
// The leader never runs its own releaseFunc on this path, so its ref is
|
||||
// not decremented; that is harmless because the cycle is detached (c.cycle
|
||||
// = nil) and cy.done is still the no-op set at construction (c.g.Gather
|
||||
// panicked before assigning a real done). If cy.done is ever made non-nil
|
||||
// before c.g.Gather runs, this path would need to release it.
|
||||
panicked := true
|
||||
defer func() {
|
||||
if panicked {
|
||||
c.mu.Lock()
|
||||
if c.cycle == cy {
|
||||
c.cycle = nil
|
||||
}
|
||||
c.mu.Unlock()
|
||||
cy.err = errGatherPanicked // set before close: happens-before joiners' reads
|
||||
close(cy.ready)
|
||||
}
|
||||
}()
|
||||
cy.mfs, cy.done, cy.err = c.g.Gather()
|
||||
panicked = false
|
||||
close(cy.ready) // happens-before joiners' reads of cy.mfs/err/done
|
||||
|
||||
// Clone here too so cy.mfs stays the write-once canonical slice: joiners
|
||||
// read it concurrently via slices.Clone, so the leader must not hand out
|
||||
// (and potentially reorder) the same backing array.
|
||||
return slices.Clone(cy.mfs), c.releaseFunc(cy), cy.err
|
||||
}
|
||||
|
||||
// releaseFunc returns the done callback for one caller sharing cy.
|
||||
// When the last caller releases, the underlying done is invoked and the
|
||||
// cycle is cleared so the next Gather starts fresh.
|
||||
func (c *coalescingGatherer) releaseFunc(cy *gatherCycle) func() {
|
||||
return func() {
|
||||
c.mu.Lock()
|
||||
cy.refs--
|
||||
if cy.refs > 0 {
|
||||
c.mu.Unlock()
|
||||
return
|
||||
}
|
||||
// Last caller.
|
||||
if c.cycle == cy {
|
||||
c.cycle = nil
|
||||
}
|
||||
c.mu.Unlock()
|
||||
cy.done() // called outside the lock to avoid holding it during done
|
||||
}
|
||||
}
|
||||
|
||||
// Handler returns an http.Handler for the prometheus.DefaultGatherer, using
|
||||
// default HandlerOpts, i.e. it reports the first error as an HTTP error, it has
|
||||
// no error logging, and it applies compression if requested by the client.
|
||||
@@ -89,6 +198,10 @@ var gzipPool = sync.Pool{
|
||||
// metrics used for instrumentation will be shared between them, providing
|
||||
// global scrape counts.
|
||||
//
|
||||
// The handler supports filtering metrics by name using the `name[]` query parameter.
|
||||
// Multiple metric names can be specified by providing the parameter multiple times.
|
||||
// When no name[] parameters are provided, all metrics are returned.
|
||||
//
|
||||
// This function is meant to cover the bulk of basic use cases. If you are doing
|
||||
// anything that requires more customization (including using a non-default
|
||||
// Gatherer, different instrumentation, and non-default HandlerOpts), use the
|
||||
@@ -105,6 +218,10 @@ func Handler() http.Handler {
|
||||
// Gatherers, with non-default HandlerOpts, and/or with custom (or no)
|
||||
// instrumentation. Use the InstrumentMetricHandler function to apply the same
|
||||
// kind of instrumentation as it is used by the Handler function.
|
||||
//
|
||||
// The handler supports filtering metrics by name using the `name[]` query parameter.
|
||||
// Multiple metric names can be specified by providing the parameter multiple times.
|
||||
// When no name[] parameters are provided, all metrics are returned.
|
||||
func HandlerFor(reg prometheus.Gatherer, opts HandlerOpts) http.Handler {
|
||||
return HandlerForTransactional(prometheus.ToTransactionalGatherer(reg), opts)
|
||||
}
|
||||
@@ -112,7 +229,15 @@ func HandlerFor(reg prometheus.Gatherer, opts HandlerOpts) http.Handler {
|
||||
// HandlerForTransactional is like HandlerFor, but it uses transactional gather, which
|
||||
// can safely change in-place returned *dto.MetricFamily before call to `Gather` and after
|
||||
// call to `done` of that `Gather`.
|
||||
//
|
||||
// The handler supports filtering metrics by name using the `name[]` query parameter.
|
||||
// Multiple metric names can be specified by providing the parameter multiple times.
|
||||
// When no name[] parameters are provided, all metrics are returned.
|
||||
func HandlerForTransactional(reg prometheus.TransactionalGatherer, opts HandlerOpts) http.Handler {
|
||||
if opts.CoalesceGather {
|
||||
reg = &coalescingGatherer{g: reg}
|
||||
}
|
||||
|
||||
var (
|
||||
inFlightSem chan struct{}
|
||||
errCnt = prometheus.NewCounterVec(
|
||||
@@ -214,12 +339,14 @@ func HandlerForTransactional(reg prometheus.TransactionalGatherer, opts HandlerO
|
||||
rsp.Header().Set(contentEncodingHeader, encodingHeader)
|
||||
}
|
||||
|
||||
var enc expfmt.Encoder
|
||||
var (
|
||||
enc expfmt.Encoder
|
||||
encOpts []expfmt.EncoderOption
|
||||
)
|
||||
if opts.EnableOpenMetricsTextCreatedSamples {
|
||||
enc = expfmt.NewEncoder(w, contentType, expfmt.WithCreatedLines())
|
||||
} else {
|
||||
enc = expfmt.NewEncoder(w, contentType)
|
||||
encOpts = append(encOpts, expfmt.WithCreatedLines())
|
||||
}
|
||||
enc = expfmt.NewEncoder(w, contentType, encOpts...)
|
||||
|
||||
// handleError handles the error according to opts.ErrorHandling
|
||||
// and returns true if we have to abort after the handling.
|
||||
@@ -245,7 +372,24 @@ func HandlerForTransactional(reg prometheus.TransactionalGatherer, opts HandlerO
|
||||
return false
|
||||
}
|
||||
|
||||
// Build metric name filter set from query params (if any). The URL
|
||||
// can be nil on hand-constructed requests.
|
||||
var metricFilter map[string]struct{}
|
||||
if req.URL != nil {
|
||||
if metricNames := req.URL.Query()["name[]"]; len(metricNames) > 0 {
|
||||
metricFilter = make(map[string]struct{}, len(metricNames))
|
||||
for _, name := range metricNames {
|
||||
metricFilter[name] = struct{}{}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for _, mf := range mfs {
|
||||
if metricFilter != nil {
|
||||
if _, ok := metricFilter[mf.GetName()]; !ok {
|
||||
continue
|
||||
}
|
||||
}
|
||||
if handleError(enc.Encode(mf)) {
|
||||
return
|
||||
}
|
||||
@@ -353,7 +497,7 @@ const (
|
||||
// log.Logger from the standard library implements this interface, and it is
|
||||
// easy to implement by custom loggers, if they don't do so already anyway.
|
||||
type Logger interface {
|
||||
Println(v ...interface{})
|
||||
Println(v ...any)
|
||||
}
|
||||
|
||||
// HandlerOpts specifies options how to serve metrics via an http.Handler. The
|
||||
@@ -400,6 +544,40 @@ type HandlerOpts struct {
|
||||
// Service Unavailable and a suitable message in the body. If
|
||||
// MaxRequestsInFlight is 0 or negative, no limit is applied.
|
||||
MaxRequestsInFlight int
|
||||
// CoalesceGather, if true, deduplicates concurrent Gather calls so that
|
||||
// only one collection runs at a time. Additional requests that arrive
|
||||
// while a Gather is in flight will receive the same result once it
|
||||
// completes. This prevents goroutine pile-up when the scrape rate is
|
||||
// faster than the time collectors need to produce metrics.
|
||||
//
|
||||
// When enabled, concurrent scrapers share a single metric snapshot per
|
||||
// collection cycle. Each request receives its own copy of the returned
|
||||
// slice, so filtering or reordering it (for example via name[] query
|
||||
// parameters) is safe. The pointed-to MetricFamily values are still
|
||||
// shared: the built-in handler only reads them, so this is safe in
|
||||
// practice, but a custom TransactionalGatherer that mutates the returned
|
||||
// families in place after Gather returns must not use this option.
|
||||
//
|
||||
// Because the snapshot is shared, a request that arrives while a cycle is
|
||||
// in flight receives that cycle's result even though collection began
|
||||
// before the request; two scrapers joined to one cycle observe the same
|
||||
// timestamps rather than independently gathered data.
|
||||
//
|
||||
// Consider using CoalesceGather together with Timeout. Timeout bounds the
|
||||
// client-facing response time and keeps at most one collection running at
|
||||
// a time, but it does not cancel the underlying Gather: a joined request
|
||||
// that times out still holds a MaxRequestsInFlight slot until the shared
|
||||
// collection completes.
|
||||
//
|
||||
// Panic handling: a panicking Collector is already turned into an error by
|
||||
// the registry, so joiners receive that error like any other. In the rare
|
||||
// case where the wrapped gatherer itself panics, the panicking request's
|
||||
// panic propagates as usual (handled by net/http), while requests that
|
||||
// joined the same cycle receive an error rather than an empty response.
|
||||
//
|
||||
// NOTE: This option is experimental and may change or be removed in a
|
||||
// future release.
|
||||
CoalesceGather bool
|
||||
// If handling a request takes longer than Timeout, it is responded to
|
||||
// with 503 ServiceUnavailable and a suitable Message. No timeout is
|
||||
// applied if Timeout is 0 or negative. Note that with the current
|
||||
@@ -407,8 +585,9 @@ type HandlerOpts struct {
|
||||
// described above (and even that only if sending of the body hasn't
|
||||
// started yet), while the bulk work of gathering all the metrics keeps
|
||||
// running in the background (with the eventual result to be thrown
|
||||
// away). Until the implementation is improved, it is recommended to
|
||||
// implement a separate timeout in potentially slow Collectors.
|
||||
// away). When CoalesceGather is enabled, only one such background Gather
|
||||
// can be in flight at a time. It is also recommended to implement a
|
||||
// separate timeout in potentially slow Collectors.
|
||||
Timeout time.Duration
|
||||
// If true, the experimental OpenMetrics encoding is added to the
|
||||
// possible options during content negotiation. Note that Prometheus
|
||||
@@ -460,7 +639,7 @@ func httpError(rsp http.ResponseWriter, err error) {
|
||||
|
||||
// negotiateEncodingWriter reads the Accept-Encoding header from a request and
|
||||
// selects the right compression based on an allow-list of supported
|
||||
// compressions. It returns a writer implementing the compression and an the
|
||||
// compressions. It returns a writer implementing the compression and the
|
||||
// correct value that the caller can set in the response header.
|
||||
func negotiateEncodingWriter(r *http.Request, rw io.Writer, compressions []string) (_ io.Writer, encodingHeaderValue string, closeWriter func(), _ error) {
|
||||
if len(compressions) == 0 {
|
||||
|
||||
12
vendor/github.com/prometheus/client_golang/prometheus/promhttp/instrument_client.go
generated
vendored
12
vendor/github.com/prometheus/client_golang/prometheus/promhttp/instrument_client.go
generated
vendored
@@ -75,10 +75,10 @@ func InstrumentRoundTripperCounter(counter *prometheus.CounterVec, next http.Rou
|
||||
resp, err := next.RoundTrip(r)
|
||||
if err == nil {
|
||||
l := labels(code, method, r.Method, resp.StatusCode, rtOpts.extraMethods...)
|
||||
for label, resolve := range rtOpts.extraLabelsFromCtx {
|
||||
l[label] = resolve(resp.Request.Context())
|
||||
for label, resolve := range rtOpts.extraLabelsFromRequest {
|
||||
l[label] = resolve(resp.Request)
|
||||
}
|
||||
addWithExemplar(counter.With(l), 1, rtOpts.getExemplarFn(r.Context()))
|
||||
addWithExemplar(counter.With(l), 1, rtOpts.getExemplarFn(r))
|
||||
}
|
||||
return resp, err
|
||||
}
|
||||
@@ -119,10 +119,10 @@ func InstrumentRoundTripperDuration(obs prometheus.ObserverVec, next http.RoundT
|
||||
resp, err := next.RoundTrip(r)
|
||||
if err == nil {
|
||||
l := labels(code, method, r.Method, resp.StatusCode, rtOpts.extraMethods...)
|
||||
for label, resolve := range rtOpts.extraLabelsFromCtx {
|
||||
l[label] = resolve(resp.Request.Context())
|
||||
for label, resolve := range rtOpts.extraLabelsFromRequest {
|
||||
l[label] = resolve(resp.Request)
|
||||
}
|
||||
observeWithExemplar(obs.With(l), time.Since(start).Seconds(), rtOpts.getExemplarFn(r.Context()))
|
||||
observeWithExemplar(obs.With(l), time.Since(start).Seconds(), rtOpts.getExemplarFn(r))
|
||||
}
|
||||
return resp, err
|
||||
}
|
||||
|
||||
88
vendor/github.com/prometheus/client_golang/prometheus/promhttp/instrument_server.go
generated
vendored
88
vendor/github.com/prometheus/client_golang/prometheus/promhttp/instrument_server.go
generated
vendored
@@ -28,24 +28,36 @@ import (
|
||||
// magicString is used for the hacky label test in checkLabels. Remove once fixed.
|
||||
const magicString = "zZgWfBxLqvG8kc8IMv3POi2Bb0tZI3vAnBx+gBaFi9FyPzB/CzKUer1yufDa"
|
||||
|
||||
// observeWithExemplar is a wrapper for [prometheus.ExemplarAdder.ExemplarObserver],
|
||||
// which falls back to [prometheus.Observer.Observe] if no labels are provided.
|
||||
// observeWithExemplar records val on obs. If labels is non-nil and obs
|
||||
// implements [prometheus.ExemplarObserver], the exemplar is attached via
|
||||
// ObserveWithExemplar; otherwise the exemplar is dropped and the value is
|
||||
// recorded with a plain [prometheus.Observer.Observe]. This mirrors the
|
||||
// safe-cast pattern in [prometheus.Timer.ObserveDurationWithExemplar] and
|
||||
// ensures we never panic when callers pass an ObserverVec backed by a
|
||||
// summary, which cannot carry exemplars in the Prometheus exposition format.
|
||||
func observeWithExemplar(obs prometheus.Observer, val float64, labels map[string]string) {
|
||||
if labels == nil {
|
||||
obs.Observe(val)
|
||||
return
|
||||
if labels != nil {
|
||||
if eo, ok := obs.(prometheus.ExemplarObserver); ok {
|
||||
eo.ObserveWithExemplar(val, labels)
|
||||
return
|
||||
}
|
||||
}
|
||||
obs.(prometheus.ExemplarObserver).ObserveWithExemplar(val, labels)
|
||||
obs.Observe(val)
|
||||
}
|
||||
|
||||
// addWithExemplar is a wrapper for [prometheus.ExemplarAdder.AddWithExemplar],
|
||||
// which falls back to [prometheus.Counter.Add] if no labels are provided.
|
||||
func addWithExemplar(obs prometheus.Counter, val float64, labels map[string]string) {
|
||||
if labels == nil {
|
||||
obs.Add(val)
|
||||
return
|
||||
// addWithExemplar records val on c. If labels is non-nil and c implements
|
||||
// [prometheus.ExemplarAdder], the exemplar is attached via AddWithExemplar;
|
||||
// otherwise the exemplar is dropped and the value is recorded with a plain
|
||||
// [prometheus.Counter.Add]. The safe-cast keeps the helper robust against
|
||||
// custom Counter implementations that do not advertise exemplar support.
|
||||
func addWithExemplar(c prometheus.Counter, val float64, labels map[string]string) {
|
||||
if labels != nil {
|
||||
if ea, ok := c.(prometheus.ExemplarAdder); ok {
|
||||
ea.AddWithExemplar(val, labels)
|
||||
return
|
||||
}
|
||||
}
|
||||
obs.(prometheus.ExemplarAdder).AddWithExemplar(val, labels)
|
||||
c.Add(val)
|
||||
}
|
||||
|
||||
// InstrumentHandlerInFlight is a middleware that wraps the provided
|
||||
@@ -97,10 +109,10 @@ func InstrumentHandlerDuration(obs prometheus.ObserverVec, next http.Handler, op
|
||||
next.ServeHTTP(d, r)
|
||||
|
||||
l := labels(code, method, r.Method, d.Status(), hOpts.extraMethods...)
|
||||
for label, resolve := range hOpts.extraLabelsFromCtx {
|
||||
l[label] = resolve(r.Context())
|
||||
for label, resolve := range hOpts.extraLabelsFromRequest {
|
||||
l[label] = resolve(r)
|
||||
}
|
||||
observeWithExemplar(obs.With(l), time.Since(now).Seconds(), hOpts.getExemplarFn(r.Context()))
|
||||
observeWithExemplar(obs.With(l), time.Since(now).Seconds(), hOpts.getExemplarFn(r))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -108,10 +120,10 @@ func InstrumentHandlerDuration(obs prometheus.ObserverVec, next http.Handler, op
|
||||
now := time.Now()
|
||||
next.ServeHTTP(w, r)
|
||||
l := labels(code, method, r.Method, 0, hOpts.extraMethods...)
|
||||
for label, resolve := range hOpts.extraLabelsFromCtx {
|
||||
l[label] = resolve(r.Context())
|
||||
for label, resolve := range hOpts.extraLabelsFromRequest {
|
||||
l[label] = resolve(r)
|
||||
}
|
||||
observeWithExemplar(obs.With(l), time.Since(now).Seconds(), hOpts.getExemplarFn(r.Context()))
|
||||
observeWithExemplar(obs.With(l), time.Since(now).Seconds(), hOpts.getExemplarFn(r))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -147,10 +159,10 @@ func InstrumentHandlerCounter(counter *prometheus.CounterVec, next http.Handler,
|
||||
next.ServeHTTP(d, r)
|
||||
|
||||
l := labels(code, method, r.Method, d.Status(), hOpts.extraMethods...)
|
||||
for label, resolve := range hOpts.extraLabelsFromCtx {
|
||||
l[label] = resolve(r.Context())
|
||||
for label, resolve := range hOpts.extraLabelsFromRequest {
|
||||
l[label] = resolve(r)
|
||||
}
|
||||
addWithExemplar(counter.With(l), 1, hOpts.getExemplarFn(r.Context()))
|
||||
addWithExemplar(counter.With(l), 1, hOpts.getExemplarFn(r))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -158,10 +170,10 @@ func InstrumentHandlerCounter(counter *prometheus.CounterVec, next http.Handler,
|
||||
next.ServeHTTP(w, r)
|
||||
|
||||
l := labels(code, method, r.Method, 0, hOpts.extraMethods...)
|
||||
for label, resolve := range hOpts.extraLabelsFromCtx {
|
||||
l[label] = resolve(r.Context())
|
||||
for label, resolve := range hOpts.extraLabelsFromRequest {
|
||||
l[label] = resolve(r)
|
||||
}
|
||||
addWithExemplar(counter.With(l), 1, hOpts.getExemplarFn(r.Context()))
|
||||
addWithExemplar(counter.With(l), 1, hOpts.getExemplarFn(r))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -200,10 +212,10 @@ func InstrumentHandlerTimeToWriteHeader(obs prometheus.ObserverVec, next http.Ha
|
||||
now := time.Now()
|
||||
d := newDelegator(w, func(status int) {
|
||||
l := labels(code, method, r.Method, status, hOpts.extraMethods...)
|
||||
for label, resolve := range hOpts.extraLabelsFromCtx {
|
||||
l[label] = resolve(r.Context())
|
||||
for label, resolve := range hOpts.extraLabelsFromRequest {
|
||||
l[label] = resolve(r)
|
||||
}
|
||||
observeWithExemplar(obs.With(l), time.Since(now).Seconds(), hOpts.getExemplarFn(r.Context()))
|
||||
observeWithExemplar(obs.With(l), time.Since(now).Seconds(), hOpts.getExemplarFn(r))
|
||||
})
|
||||
next.ServeHTTP(d, r)
|
||||
}
|
||||
@@ -244,10 +256,10 @@ func InstrumentHandlerRequestSize(obs prometheus.ObserverVec, next http.Handler,
|
||||
size := computeApproximateRequestSize(r)
|
||||
|
||||
l := labels(code, method, r.Method, d.Status(), hOpts.extraMethods...)
|
||||
for label, resolve := range hOpts.extraLabelsFromCtx {
|
||||
l[label] = resolve(r.Context())
|
||||
for label, resolve := range hOpts.extraLabelsFromRequest {
|
||||
l[label] = resolve(r)
|
||||
}
|
||||
observeWithExemplar(obs.With(l), float64(size), hOpts.getExemplarFn(r.Context()))
|
||||
observeWithExemplar(obs.With(l), float64(size), hOpts.getExemplarFn(r))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -256,10 +268,10 @@ func InstrumentHandlerRequestSize(obs prometheus.ObserverVec, next http.Handler,
|
||||
size := computeApproximateRequestSize(r)
|
||||
|
||||
l := labels(code, method, r.Method, 0, hOpts.extraMethods...)
|
||||
for label, resolve := range hOpts.extraLabelsFromCtx {
|
||||
l[label] = resolve(r.Context())
|
||||
for label, resolve := range hOpts.extraLabelsFromRequest {
|
||||
l[label] = resolve(r)
|
||||
}
|
||||
observeWithExemplar(obs.With(l), float64(size), hOpts.getExemplarFn(r.Context()))
|
||||
observeWithExemplar(obs.With(l), float64(size), hOpts.getExemplarFn(r))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -296,10 +308,10 @@ func InstrumentHandlerResponseSize(obs prometheus.ObserverVec, next http.Handler
|
||||
next.ServeHTTP(d, r)
|
||||
|
||||
l := labels(code, method, r.Method, d.Status(), hOpts.extraMethods...)
|
||||
for label, resolve := range hOpts.extraLabelsFromCtx {
|
||||
l[label] = resolve(r.Context())
|
||||
for label, resolve := range hOpts.extraLabelsFromRequest {
|
||||
l[label] = resolve(r)
|
||||
}
|
||||
observeWithExemplar(obs.With(l), float64(d.Written()), hOpts.getExemplarFn(r.Context()))
|
||||
observeWithExemplar(obs.With(l), float64(d.Written()), hOpts.getExemplarFn(r))
|
||||
})
|
||||
}
|
||||
|
||||
@@ -366,7 +378,7 @@ func checkLabels(c prometheus.Collector) (code, method bool) {
|
||||
panic("metric partitioned with non-supported labels")
|
||||
}
|
||||
}
|
||||
return
|
||||
return code, method
|
||||
}
|
||||
|
||||
func isLabelCurried(c prometheus.Collector, label string) bool {
|
||||
|
||||
42
vendor/github.com/prometheus/client_golang/prometheus/promhttp/option.go
generated
vendored
42
vendor/github.com/prometheus/client_golang/prometheus/promhttp/option.go
generated
vendored
@@ -15,6 +15,7 @@ package promhttp
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/http"
|
||||
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
)
|
||||
@@ -24,28 +25,31 @@ type Option interface {
|
||||
apply(*options)
|
||||
}
|
||||
|
||||
// LabelValueFromRequest is used to compute the label value from request.
|
||||
type LabelValueFromRequest func(request *http.Request) string
|
||||
|
||||
// LabelValueFromCtx are used to compute the label value from request context.
|
||||
// Context can be filled with values from request through middleware.
|
||||
type LabelValueFromCtx func(ctx context.Context) string
|
||||
|
||||
// options store options for both a handler or round tripper.
|
||||
type options struct {
|
||||
extraMethods []string
|
||||
getExemplarFn func(requestCtx context.Context) prometheus.Labels
|
||||
extraLabelsFromCtx map[string]LabelValueFromCtx
|
||||
extraMethods []string
|
||||
getExemplarFn func(req *http.Request) prometheus.Labels
|
||||
extraLabelsFromRequest map[string]LabelValueFromRequest
|
||||
}
|
||||
|
||||
func defaultOptions() *options {
|
||||
return &options{
|
||||
getExemplarFn: func(ctx context.Context) prometheus.Labels { return nil },
|
||||
extraLabelsFromCtx: map[string]LabelValueFromCtx{},
|
||||
getExemplarFn: func(req *http.Request) prometheus.Labels { return nil },
|
||||
extraLabelsFromRequest: map[string]LabelValueFromRequest{},
|
||||
}
|
||||
}
|
||||
|
||||
func (o *options) emptyDynamicLabels() prometheus.Labels {
|
||||
labels := prometheus.Labels{}
|
||||
|
||||
for label := range o.extraLabelsFromCtx {
|
||||
for label := range o.extraLabelsFromRequest {
|
||||
labels[label] = ""
|
||||
}
|
||||
|
||||
@@ -66,12 +70,30 @@ func WithExtraMethods(methods ...string) Option {
|
||||
})
|
||||
}
|
||||
|
||||
// WithExemplarFromContext allows to inject function that will get exemplar from context that will be put to counter and histogram metrics.
|
||||
// WithExemplarFromRequest allows you to inject a function that will get exemplar from request that will be put to counter and histogram metrics.
|
||||
// If the function returns nil labels or the metric does not support exemplars, no exemplar will be added (noop), but
|
||||
// metric will continue to observe/increment.
|
||||
func WithExemplarFromRequest(getExemplarFn func(req *http.Request) prometheus.Labels) Option {
|
||||
return optionApplyFunc(func(o *options) {
|
||||
o.getExemplarFn = getExemplarFn
|
||||
})
|
||||
}
|
||||
|
||||
// WithExemplarFromContext allows you to inject a function that will get exemplar from context that will be put to counter and histogram metrics.
|
||||
// If the function returns nil labels or the metric does not support exemplars, no exemplar will be added (noop), but
|
||||
// metric will continue to observe/increment.
|
||||
func WithExemplarFromContext(getExemplarFn func(requestCtx context.Context) prometheus.Labels) Option {
|
||||
return optionApplyFunc(func(o *options) {
|
||||
o.getExemplarFn = getExemplarFn
|
||||
o.getExemplarFn = func(req *http.Request) prometheus.Labels {
|
||||
return getExemplarFn(req.Context())
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// WithLabelFromRequest registers a label for dynamic resolution with access to the request.
|
||||
func WithLabelFromRequest(name string, valueFn LabelValueFromRequest) Option {
|
||||
return optionApplyFunc(func(o *options) {
|
||||
o.extraLabelsFromRequest[name] = valueFn
|
||||
})
|
||||
}
|
||||
|
||||
@@ -79,6 +101,8 @@ func WithExemplarFromContext(getExemplarFn func(requestCtx context.Context) prom
|
||||
// See the example for ExampleInstrumentHandlerWithLabelResolver for example usage
|
||||
func WithLabelFromCtx(name string, valueFn LabelValueFromCtx) Option {
|
||||
return optionApplyFunc(func(o *options) {
|
||||
o.extraLabelsFromCtx[name] = valueFn
|
||||
o.extraLabelsFromRequest[name] = func(req *http.Request) string {
|
||||
return valueFn(req.Context())
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
63
vendor/github.com/prometheus/client_golang/prometheus/registry.go
generated
vendored
63
vendor/github.com/prometheus/client_golang/prometheus/registry.go
generated
vendored
@@ -214,6 +214,19 @@ func (err AlreadyRegisteredError) Error() string {
|
||||
// by a Gatherer to report multiple errors during MetricFamily gathering.
|
||||
type MultiError []error
|
||||
|
||||
// SafeMultiError is a thread-safe wrapper around MultiError using a mutex.
|
||||
type SafeMultiError struct {
|
||||
mu sync.Mutex
|
||||
errs MultiError
|
||||
}
|
||||
|
||||
// Appends the provided error to the contained MultiError in a thread-safe way.
|
||||
func (s *SafeMultiError) Append(err error) {
|
||||
s.mu.Lock()
|
||||
s.errs.Append(err)
|
||||
s.mu.Unlock()
|
||||
}
|
||||
|
||||
// Error formats the contained errors as a bullet point list, preceded by the
|
||||
// total number of errors. Note that this results in a multi-line string.
|
||||
func (errs MultiError) Error() string {
|
||||
@@ -408,6 +421,16 @@ func (r *Registry) MustRegister(cs ...Collector) {
|
||||
}
|
||||
}
|
||||
|
||||
// MustGather implements Gatherer.
|
||||
// Wraps around Gather and panics if Gather fails for any reason.
|
||||
func (r *Registry) MustGather() []*dto.MetricFamily {
|
||||
mfs, err := r.Gather()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return mfs
|
||||
}
|
||||
|
||||
// Gather implements Gatherer.
|
||||
func (r *Registry) Gather() ([]*dto.MetricFamily, error) {
|
||||
r.mtx.RLock()
|
||||
@@ -423,7 +446,7 @@ func (r *Registry) Gather() ([]*dto.MetricFamily, error) {
|
||||
uncheckedMetricChan = make(chan Metric, capMetricChan)
|
||||
metricHashes = map[uint64]struct{}{}
|
||||
wg sync.WaitGroup
|
||||
errs MultiError // The collected errors to return in the end.
|
||||
safeErrs = &SafeMultiError{} // To collect errors in a threadsafe way
|
||||
registeredDescIDs map[uint64]struct{} // Only used for pedantic checks
|
||||
)
|
||||
|
||||
@@ -453,9 +476,9 @@ func (r *Registry) Gather() ([]*dto.MetricFamily, error) {
|
||||
for {
|
||||
select {
|
||||
case collector := <-checkedCollectors:
|
||||
collector.Collect(checkedMetricChan)
|
||||
safeErrs.Append((safeCollect(collector, checkedMetricChan)))
|
||||
case collector := <-uncheckedCollectors:
|
||||
collector.Collect(uncheckedMetricChan)
|
||||
safeErrs.Append(safeCollect(collector, uncheckedMetricChan))
|
||||
default:
|
||||
return
|
||||
}
|
||||
@@ -499,7 +522,7 @@ func (r *Registry) Gather() ([]*dto.MetricFamily, error) {
|
||||
cmc = nil
|
||||
break
|
||||
}
|
||||
errs.Append(processMetric(
|
||||
safeErrs.Append(processMetric(
|
||||
metric, metricFamiliesByName,
|
||||
metricHashes,
|
||||
registeredDescIDs,
|
||||
@@ -509,7 +532,7 @@ func (r *Registry) Gather() ([]*dto.MetricFamily, error) {
|
||||
umc = nil
|
||||
break
|
||||
}
|
||||
errs.Append(processMetric(
|
||||
safeErrs.Append(processMetric(
|
||||
metric, metricFamiliesByName,
|
||||
metricHashes,
|
||||
nil,
|
||||
@@ -526,7 +549,7 @@ func (r *Registry) Gather() ([]*dto.MetricFamily, error) {
|
||||
cmc = nil
|
||||
break
|
||||
}
|
||||
errs.Append(processMetric(
|
||||
safeErrs.Append(processMetric(
|
||||
metric, metricFamiliesByName,
|
||||
metricHashes,
|
||||
registeredDescIDs,
|
||||
@@ -536,7 +559,7 @@ func (r *Registry) Gather() ([]*dto.MetricFamily, error) {
|
||||
umc = nil
|
||||
break
|
||||
}
|
||||
errs.Append(processMetric(
|
||||
safeErrs.Append(processMetric(
|
||||
metric, metricFamiliesByName,
|
||||
metricHashes,
|
||||
nil,
|
||||
@@ -556,7 +579,8 @@ func (r *Registry) Gather() ([]*dto.MetricFamily, error) {
|
||||
break
|
||||
}
|
||||
}
|
||||
return internal.NormalizeMetricFamilies(metricFamiliesByName), errs.MaybeUnwrap()
|
||||
|
||||
return internal.NormalizeMetricFamilies(metricFamiliesByName), safeErrs.errs.MaybeUnwrap()
|
||||
}
|
||||
|
||||
// Describe implements Collector.
|
||||
@@ -571,6 +595,24 @@ func (r *Registry) Describe(ch chan<- *Desc) {
|
||||
}
|
||||
}
|
||||
|
||||
// Helper wrapper around Collector.Collect.
|
||||
// It tries to collect from the channel, recovers on panic and
|
||||
// if it has recovered from a panic, then it sends an InvalidMetric into
|
||||
// the channel with an InvalidDesc, and an error that includes a stack trace.
|
||||
func safeCollect(c Collector, ch chan<- Metric) (err error) {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
buf := make([]byte, 64<<10) // 64 KB
|
||||
n := runtime.Stack(buf, false)
|
||||
err = fmt.Errorf("prometheus collector panic recovered: type=%T: error=%v\nstack trace=%s", c, r, buf[:n])
|
||||
ch <- NewInvalidMetric(NewInvalidDesc(err), err)
|
||||
}
|
||||
}()
|
||||
c.Collect(ch)
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
// Collect implements Collector.
|
||||
func (r *Registry) Collect(ch chan<- Metric) {
|
||||
r.mtx.RLock()
|
||||
@@ -599,10 +641,12 @@ func WriteToTextfile(filename string, g Gatherer) error {
|
||||
|
||||
mfs, err := g.Gather()
|
||||
if err != nil {
|
||||
tmp.Close()
|
||||
return err
|
||||
}
|
||||
for _, mf := range mfs {
|
||||
if _, err := expfmt.MetricFamilyToText(tmp, mf); err != nil {
|
||||
tmp.Close()
|
||||
return err
|
||||
}
|
||||
}
|
||||
@@ -685,6 +729,9 @@ func processMetric(
|
||||
metricFamily = &dto.MetricFamily{}
|
||||
metricFamily.Name = proto.String(desc.fqName)
|
||||
metricFamily.Help = proto.String(desc.help)
|
||||
if desc.unit != "" {
|
||||
metricFamily.Unit = proto.String(desc.unit)
|
||||
}
|
||||
// TODO(beorn7): Simplify switch once Desc has type.
|
||||
switch {
|
||||
case dtoMetric.Gauge != nil:
|
||||
|
||||
9
vendor/github.com/prometheus/client_golang/prometheus/summary.go
generated
vendored
9
vendor/github.com/prometheus/client_golang/prometheus/summary.go
generated
vendored
@@ -101,6 +101,9 @@ type SummaryOpts struct {
|
||||
// string.
|
||||
Help string
|
||||
|
||||
// Unit provides the unit of this Summary.
|
||||
Unit string
|
||||
|
||||
// ConstLabels are used to attach fixed labels to this metric. Metrics
|
||||
// with the same fully-qualified name must have the same label names in
|
||||
// their ConstLabels.
|
||||
@@ -181,11 +184,12 @@ type SummaryVecOpts struct {
|
||||
// NewSummary creates a new Summary based on the provided SummaryOpts.
|
||||
func NewSummary(opts SummaryOpts) Summary {
|
||||
return newSummary(
|
||||
NewDesc(
|
||||
V2.NewDesc(
|
||||
BuildFQName(opts.Namespace, opts.Subsystem, opts.Name),
|
||||
opts.Help,
|
||||
nil,
|
||||
UnconstrainedLabels(nil),
|
||||
opts.ConstLabels,
|
||||
WithUnit(opts.Unit),
|
||||
),
|
||||
opts,
|
||||
)
|
||||
@@ -578,6 +582,7 @@ func (v2) NewSummaryVec(opts SummaryVecOpts) *SummaryVec {
|
||||
opts.Help,
|
||||
opts.VariableLabels,
|
||||
opts.ConstLabels,
|
||||
WithUnit(opts.Unit),
|
||||
)
|
||||
return &SummaryVec{
|
||||
MetricVec: NewMetricVec(desc, func(lvs ...string) Metric {
|
||||
|
||||
10
vendor/github.com/prometheus/client_golang/prometheus/timer.go
generated
vendored
10
vendor/github.com/prometheus/client_golang/prometheus/timer.go
generated
vendored
@@ -37,10 +37,10 @@ type Timer struct {
|
||||
// or
|
||||
//
|
||||
// func TimeMeWithExemplar() {
|
||||
// timer := NewTimer(myHistogram)
|
||||
// defer timer.ObserveDurationWithExemplar(exemplar)
|
||||
// // Do actual work.
|
||||
// }
|
||||
// timer := NewTimer(myHistogram)
|
||||
// defer timer.ObserveDurationWithExemplar(exemplar)
|
||||
// // Do actual work.
|
||||
// }
|
||||
func NewTimer(o Observer) *Timer {
|
||||
return &Timer{
|
||||
begin: time.Now(),
|
||||
@@ -66,7 +66,7 @@ func (t *Timer) ObserveDuration() time.Duration {
|
||||
|
||||
// ObserveDurationWithExemplar is like ObserveDuration, but it will also
|
||||
// observe exemplar with the duration unless exemplar is nil or provided Observer can't
|
||||
// be casted to ExemplarObserver.
|
||||
// be cast to ExemplarObserver.
|
||||
func (t *Timer) ObserveDurationWithExemplar(exemplar Labels) time.Duration {
|
||||
d := time.Since(t.begin)
|
||||
eo, ok := t.observer.(ExemplarObserver)
|
||||
|
||||
10
vendor/github.com/prometheus/client_golang/prometheus/vec.go
generated
vendored
10
vendor/github.com/prometheus/client_golang/prometheus/vec.go
generated
vendored
@@ -193,9 +193,11 @@ func (m *MetricVec) CurryWith(labels Labels) (*MetricVec, error) {
|
||||
//
|
||||
// Keeping the Metric for later use is possible (and should be considered if
|
||||
// performance is critical), but keep in mind that Reset, DeleteLabelValues and
|
||||
// Delete can be used to delete the Metric from the MetricVec. In that case, the
|
||||
// Metric will still exist, but it will not be exported anymore, even if a
|
||||
// Metric with the same label values is created later.
|
||||
// Delete can be used to delete the Metric from the MetricVec. In that case, if
|
||||
// you have previously kept a reference to that Metric, the Metric object still
|
||||
// exists and can be used, but it will not be exported anymore. If a Metric with
|
||||
// the same label values is created later, updates to the old Metric reference
|
||||
// will not be exported.
|
||||
//
|
||||
// An error is returned if the number of label values is not the same as the
|
||||
// number of variable labels in Desc (minus any curried labels).
|
||||
@@ -657,7 +659,7 @@ func inlineLabelValues(lvs []string, curry []curriedLabelValue) []string {
|
||||
}
|
||||
|
||||
var labelsPool = &sync.Pool{
|
||||
New: func() interface{} {
|
||||
New: func() any {
|
||||
return make(Labels)
|
||||
},
|
||||
}
|
||||
|
||||
5
vendor/github.com/prometheus/client_golang/prometheus/wrap.go
generated
vendored
5
vendor/github.com/prometheus/client_golang/prometheus/wrap.go
generated
vendored
@@ -230,6 +230,7 @@ func wrapDesc(desc *Desc, prefix string, labels Labels) *Desc {
|
||||
return &Desc{
|
||||
fqName: desc.fqName,
|
||||
help: desc.help,
|
||||
unit: desc.unit,
|
||||
variableLabels: desc.variableLabels,
|
||||
constLabelPairs: desc.constLabelPairs,
|
||||
err: fmt.Errorf("attempted wrapping with already existing label name %q", ln),
|
||||
@@ -238,8 +239,8 @@ func wrapDesc(desc *Desc, prefix string, labels Labels) *Desc {
|
||||
constLabels[ln] = lv
|
||||
}
|
||||
// NewDesc will do remaining validations.
|
||||
newDesc := V2.NewDesc(prefix+desc.fqName, desc.help, desc.variableLabels, constLabels)
|
||||
// Propagate errors if there was any. This will override any errer
|
||||
newDesc := V2.NewDesc(prefix+desc.fqName, desc.help, desc.variableLabels, constLabels, WithUnit(desc.unit))
|
||||
// Propagate errors if there was any. This will override any error
|
||||
// created by NewDesc above, i.e. earlier errors get precedence.
|
||||
if desc.err != nil {
|
||||
newDesc.err = desc.err
|
||||
|
||||
4
vendor/github.com/prometheus/common/expfmt/expfmt.go
generated
vendored
4
vendor/github.com/prometheus/common/expfmt/expfmt.go
generated
vendored
@@ -122,7 +122,7 @@ func NewOpenMetricsFormat(version string) (Format, error) {
|
||||
// removed.
|
||||
func (f Format) WithEscapingScheme(s model.EscapingScheme) Format {
|
||||
var terms []string
|
||||
for _, p := range strings.Split(string(f), ";") {
|
||||
for p := range strings.SplitSeq(string(f), ";") {
|
||||
toks := strings.Split(p, "=")
|
||||
if len(toks) != 2 {
|
||||
trimmed := strings.TrimSpace(p)
|
||||
@@ -194,7 +194,7 @@ func (f Format) FormatType() FormatType {
|
||||
// "escaping" term exists, that will be used. Otherwise, the global default will
|
||||
// be returned.
|
||||
func (f Format) ToEscapingScheme() model.EscapingScheme {
|
||||
for _, p := range strings.Split(string(f), ";") {
|
||||
for p := range strings.SplitSeq(string(f), ";") {
|
||||
toks := strings.Split(p, "=")
|
||||
if len(toks) != 2 {
|
||||
continue
|
||||
|
||||
26
vendor/github.com/prometheus/common/expfmt/openmetrics_create.go
generated
vendored
26
vendor/github.com/prometheus/common/expfmt/openmetrics_create.go
generated
vendored
@@ -30,7 +30,6 @@ import (
|
||||
|
||||
type encoderOption struct {
|
||||
withCreatedLines bool
|
||||
withUnit bool
|
||||
}
|
||||
|
||||
type EncoderOption func(*encoderOption)
|
||||
@@ -51,17 +50,6 @@ func WithCreatedLines() EncoderOption {
|
||||
}
|
||||
}
|
||||
|
||||
// WithUnit is an EncoderOption enabling a set unit to be written to the output
|
||||
// and to be added to the metric name, if it's not there already, as a suffix.
|
||||
// Without opting in this way, the unit will not be added to the metric name and,
|
||||
// on top of that, the unit will not be passed onto the output, even if it
|
||||
// were declared in the *dto.MetricFamily struct, i.e. even if in.Unit !=nil.
|
||||
func WithUnit() EncoderOption {
|
||||
return func(t *encoderOption) {
|
||||
t.withUnit = true
|
||||
}
|
||||
}
|
||||
|
||||
// MetricFamilyToOpenMetrics converts a MetricFamily proto message into the
|
||||
// OpenMetrics text format and writes the resulting lines to 'out'. It returns
|
||||
// the number of bytes written and any error encountered. The output will have
|
||||
@@ -99,15 +87,6 @@ func WithUnit() EncoderOption {
|
||||
// its type will be set to `unknown` in that case to avoid invalid OpenMetrics
|
||||
// output.
|
||||
//
|
||||
// - According to the OM specs, the `# UNIT` line is optional, but if populated,
|
||||
// the unit has to be present in the metric name as its suffix:
|
||||
// (see https://github.com/prometheus/OpenMetrics/blob/v1.0.0/specification/OpenMetrics.md#unit).
|
||||
// However, in order to accommodate any potential scenario where such a change in the
|
||||
// metric name is not desirable, the users are here given the choice of either explicitly
|
||||
// opt in, in case they wish for the unit to be included in the output AND in the metric name
|
||||
// as a suffix (see the description of the WithUnit function above),
|
||||
// or not to opt in, in case they don't want for any of that to happen.
|
||||
//
|
||||
// - No support for the following (optional) features: info type,
|
||||
// stateset type, gaugehistogram type.
|
||||
//
|
||||
@@ -151,9 +130,6 @@ func MetricFamilyToOpenMetrics(out io.Writer, in *dto.MetricFamily, options ...E
|
||||
if metricType == dto.MetricType_COUNTER && strings.HasSuffix(compliantName, "_total") {
|
||||
compliantName = name[:len(name)-6]
|
||||
}
|
||||
if toOM.withUnit && in.Unit != nil && !strings.HasSuffix(compliantName, "_"+*in.Unit) {
|
||||
compliantName = compliantName + "_" + *in.Unit
|
||||
}
|
||||
|
||||
// Comments, first HELP, then TYPE.
|
||||
if in.Help != nil {
|
||||
@@ -217,7 +193,7 @@ func MetricFamilyToOpenMetrics(out io.Writer, in *dto.MetricFamily, options ...E
|
||||
if err != nil {
|
||||
return written, err
|
||||
}
|
||||
if toOM.withUnit && in.Unit != nil {
|
||||
if in.Unit != nil {
|
||||
n, err = w.WriteString("# UNIT ")
|
||||
written += n
|
||||
if err != nil {
|
||||
|
||||
4
vendor/github.com/prometheus/common/expfmt/text_create.go
generated
vendored
4
vendor/github.com/prometheus/common/expfmt/text_create.go
generated
vendored
@@ -42,12 +42,12 @@ const (
|
||||
|
||||
var (
|
||||
bufPool = sync.Pool{
|
||||
New: func() interface{} {
|
||||
New: func() any {
|
||||
return bufio.NewWriter(io.Discard)
|
||||
},
|
||||
}
|
||||
numBufPool = sync.Pool{
|
||||
New: func() interface{} {
|
||||
New: func() any {
|
||||
b := make([]byte, 0, initialNumBufSize)
|
||||
return &b
|
||||
},
|
||||
|
||||
10
vendor/github.com/prometheus/common/expfmt/text_parse.go
generated
vendored
10
vendor/github.com/prometheus/common/expfmt/text_parse.go
generated
vendored
@@ -339,6 +339,16 @@ func (p *TextParser) startLabelName() stateFn {
|
||||
return nil // Unexpected end of input.
|
||||
}
|
||||
if p.currentByte == '}' {
|
||||
if p.currentMF == nil {
|
||||
// The closing brace was reached before any metric name was read,
|
||||
// e.g. for the input "{}". There is no metric to attach labels to,
|
||||
// so this is a malformed exposition. This mirrors the guard in
|
||||
// startLabelValue. currentMF (not currentMetric) is checked because
|
||||
// reset only clears currentMF between parses.
|
||||
p.parseError("invalid metric name")
|
||||
p.currentLabelPairs = nil
|
||||
return nil
|
||||
}
|
||||
p.currentMetric.Label = append(p.currentMetric.Label, p.currentLabelPairs...)
|
||||
p.currentLabelPairs = nil
|
||||
if p.skipBlankTab(); p.err != nil {
|
||||
|
||||
6
vendor/github.com/prometheus/common/helpers/templates/time.go
generated
vendored
6
vendor/github.com/prometheus/common/helpers/templates/time.go
generated
vendored
@@ -25,7 +25,7 @@ import (
|
||||
|
||||
var errNaNOrInf = errors.New("value is NaN or Inf")
|
||||
|
||||
func ConvertToFloat(i interface{}) (float64, error) {
|
||||
func ConvertToFloat(i any) (float64, error) {
|
||||
switch v := i.(type) {
|
||||
case float64:
|
||||
return v, nil
|
||||
@@ -58,7 +58,7 @@ func FloatToTime(v float64) (*time.Time, error) {
|
||||
return &t, nil
|
||||
}
|
||||
|
||||
func HumanizeDuration(i interface{}) (string, error) {
|
||||
func HumanizeDuration(i any) (string, error) {
|
||||
v, err := ConvertToFloat(i)
|
||||
if err != nil {
|
||||
return "", err
|
||||
@@ -105,7 +105,7 @@ func HumanizeDuration(i interface{}) (string, error) {
|
||||
return fmt.Sprintf("%.4g%ss", v, prefix), nil
|
||||
}
|
||||
|
||||
func HumanizeTimestamp(i interface{}) (string, error) {
|
||||
func HumanizeTimestamp(i any) (string, error) {
|
||||
v, err := ConvertToFloat(i)
|
||||
if err != nil {
|
||||
return "", err
|
||||
|
||||
2
vendor/github.com/prometheus/common/model/labels.go
generated
vendored
2
vendor/github.com/prometheus/common/model/labels.go
generated
vendored
@@ -124,7 +124,7 @@ func (ln LabelName) IsValidLegacy() bool {
|
||||
}
|
||||
|
||||
// UnmarshalYAML implements the yaml.Unmarshaler interface.
|
||||
func (ln *LabelName) UnmarshalYAML(unmarshal func(interface{}) error) error {
|
||||
func (ln *LabelName) UnmarshalYAML(unmarshal func(any) error) error {
|
||||
var s string
|
||||
if err := unmarshal(&s); err != nil {
|
||||
return err
|
||||
|
||||
13
vendor/github.com/prometheus/common/model/labelset.go
generated
vendored
13
vendor/github.com/prometheus/common/model/labelset.go
generated
vendored
@@ -16,6 +16,7 @@ package model
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"maps"
|
||||
"sort"
|
||||
)
|
||||
|
||||
@@ -107,9 +108,7 @@ func (ls LabelSet) Before(o LabelSet) bool {
|
||||
// Clone returns a copy of the label set.
|
||||
func (ls LabelSet) Clone() LabelSet {
|
||||
lsn := make(LabelSet, len(ls))
|
||||
for ln, lv := range ls {
|
||||
lsn[ln] = lv
|
||||
}
|
||||
maps.Copy(lsn, ls)
|
||||
return lsn
|
||||
}
|
||||
|
||||
@@ -117,13 +116,9 @@ func (ls LabelSet) Clone() LabelSet {
|
||||
func (ls LabelSet) Merge(other LabelSet) LabelSet {
|
||||
result := make(LabelSet, len(ls))
|
||||
|
||||
for k, v := range ls {
|
||||
result[k] = v
|
||||
}
|
||||
maps.Copy(result, ls)
|
||||
|
||||
for k, v := range other {
|
||||
result[k] = v
|
||||
}
|
||||
maps.Copy(result, other)
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
14
vendor/github.com/prometheus/common/model/metric.go
generated
vendored
14
vendor/github.com/prometheus/common/model/metric.go
generated
vendored
@@ -17,6 +17,7 @@ import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"maps"
|
||||
"regexp"
|
||||
"sort"
|
||||
"strconv"
|
||||
@@ -24,7 +25,6 @@ import (
|
||||
"unicode/utf8"
|
||||
|
||||
dto "github.com/prometheus/client_model/go"
|
||||
"go.yaml.in/yaml/v2"
|
||||
"google.golang.org/protobuf/proto"
|
||||
)
|
||||
|
||||
@@ -78,14 +78,6 @@ const (
|
||||
UTF8Validation
|
||||
)
|
||||
|
||||
var _ interface {
|
||||
yaml.Marshaler
|
||||
yaml.Unmarshaler
|
||||
json.Marshaler
|
||||
json.Unmarshaler
|
||||
fmt.Stringer
|
||||
} = new(ValidationScheme)
|
||||
|
||||
// String returns the string representation of s.
|
||||
func (s ValidationScheme) String() string {
|
||||
switch s {
|
||||
@@ -267,9 +259,7 @@ func (m Metric) Before(o Metric) bool {
|
||||
// Clone returns a copy of the Metric.
|
||||
func (m Metric) Clone() Metric {
|
||||
clone := make(Metric, len(m))
|
||||
for k, v := range m {
|
||||
clone[k] = v
|
||||
}
|
||||
maps.Copy(clone, m)
|
||||
return clone
|
||||
}
|
||||
|
||||
|
||||
44
vendor/github.com/prometheus/common/model/time.go
generated
vendored
44
vendor/github.com/prometheus/common/model/time.go
generated
vendored
@@ -123,44 +123,38 @@ func (t Time) MarshalJSON() ([]byte, error) {
|
||||
|
||||
// UnmarshalJSON implements the json.Unmarshaler interface.
|
||||
func (t *Time) UnmarshalJSON(b []byte) error {
|
||||
p := strings.Split(string(b), ".")
|
||||
switch len(p) {
|
||||
case 1:
|
||||
v, err := strconv.ParseInt(p[0], 10, 64)
|
||||
base, frac, found := strings.Cut(string(b), ".")
|
||||
if !found {
|
||||
v, err := strconv.ParseInt(base, 10, 64)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
*t = Time(v * second)
|
||||
|
||||
case 2:
|
||||
v, err := strconv.ParseInt(p[0], 10, 64)
|
||||
} else {
|
||||
v, err := strconv.ParseInt(base, 10, 64)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
v *= second
|
||||
|
||||
prec := dotPrecision - len(p[1])
|
||||
prec := dotPrecision - len(frac)
|
||||
if prec < 0 {
|
||||
p[1] = p[1][:dotPrecision]
|
||||
} else if prec > 0 {
|
||||
p[1] += strings.Repeat("0", prec)
|
||||
frac = frac[:dotPrecision]
|
||||
}
|
||||
|
||||
va, err := strconv.ParseInt(p[1], 10, 32)
|
||||
va, err := strconv.ParseInt(frac, 10, 32)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// If the value was something like -0.1 the negative is lost in the
|
||||
// parsing because of the leading zero, this ensures that we capture it.
|
||||
if len(p[0]) > 0 && p[0][0] == '-' && v+va > 0 {
|
||||
*t = Time(v+va) * -1
|
||||
} else {
|
||||
*t = Time(v + va)
|
||||
switch prec {
|
||||
case 1:
|
||||
va *= 10
|
||||
case 2:
|
||||
va *= 100
|
||||
}
|
||||
|
||||
default:
|
||||
return fmt.Errorf("invalid time %q", string(b))
|
||||
if len(base) > 0 && base[0] == '-' {
|
||||
va = -va
|
||||
}
|
||||
*t = Time(v*second + va)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -340,12 +334,12 @@ func (d *Duration) UnmarshalText(text []byte) error {
|
||||
}
|
||||
|
||||
// MarshalYAML implements the yaml.Marshaler interface.
|
||||
func (d Duration) MarshalYAML() (interface{}, error) {
|
||||
func (d Duration) MarshalYAML() (any, error) {
|
||||
return d.String(), nil
|
||||
}
|
||||
|
||||
// UnmarshalYAML implements the yaml.Unmarshaler interface.
|
||||
func (d *Duration) UnmarshalYAML(unmarshal func(interface{}) error) error {
|
||||
func (d *Duration) UnmarshalYAML(unmarshal func(any) error) error {
|
||||
var s string
|
||||
if err := unmarshal(&s); err != nil {
|
||||
return err
|
||||
|
||||
8
vendor/github.com/prometheus/common/model/value.go
generated
vendored
8
vendor/github.com/prometheus/common/model/value.go
generated
vendored
@@ -259,13 +259,13 @@ func (s Scalar) String() string {
|
||||
// MarshalJSON implements json.Marshaler.
|
||||
func (s Scalar) MarshalJSON() ([]byte, error) {
|
||||
v := strconv.FormatFloat(float64(s.Value), 'f', -1, 64)
|
||||
return json.Marshal([...]interface{}{s.Timestamp, v})
|
||||
return json.Marshal([...]any{s.Timestamp, v})
|
||||
}
|
||||
|
||||
// UnmarshalJSON implements json.Unmarshaler.
|
||||
func (s *Scalar) UnmarshalJSON(b []byte) error {
|
||||
var f string
|
||||
v := [...]interface{}{&s.Timestamp, &f}
|
||||
v := [...]any{&s.Timestamp, &f}
|
||||
|
||||
if err := json.Unmarshal(b, &v); err != nil {
|
||||
return err
|
||||
@@ -291,12 +291,12 @@ func (s *String) String() string {
|
||||
|
||||
// MarshalJSON implements json.Marshaler.
|
||||
func (s String) MarshalJSON() ([]byte, error) {
|
||||
return json.Marshal([]interface{}{s.Timestamp, s.Value})
|
||||
return json.Marshal([]any{s.Timestamp, s.Value})
|
||||
}
|
||||
|
||||
// UnmarshalJSON implements json.Unmarshaler.
|
||||
func (s *String) UnmarshalJSON(b []byte) error {
|
||||
v := [...]interface{}{&s.Timestamp, &s.Value}
|
||||
v := [...]any{&s.Timestamp, &s.Value}
|
||||
return json.Unmarshal(b, &v)
|
||||
}
|
||||
|
||||
|
||||
2
vendor/github.com/prometheus/common/model/value_float.go
generated
vendored
2
vendor/github.com/prometheus/common/model/value_float.go
generated
vendored
@@ -79,7 +79,7 @@ func (s SamplePair) MarshalJSON() ([]byte, error) {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return []byte(fmt.Sprintf("[%s,%s]", t, v)), nil
|
||||
return fmt.Appendf(nil, "[%s,%s]", t, v), nil
|
||||
}
|
||||
|
||||
// UnmarshalJSON implements json.Unmarshaler.
|
||||
|
||||
8
vendor/github.com/prometheus/common/model/value_histogram.go
generated
vendored
8
vendor/github.com/prometheus/common/model/value_histogram.go
generated
vendored
@@ -67,11 +67,11 @@ func (s HistogramBucket) MarshalJSON() ([]byte, error) {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return []byte(fmt.Sprintf("[%s,%s,%s,%s]", b, l, u, c)), nil
|
||||
return fmt.Appendf(nil, "[%s,%s,%s,%s]", b, l, u, c), nil
|
||||
}
|
||||
|
||||
func (s *HistogramBucket) UnmarshalJSON(buf []byte) error {
|
||||
tmp := []interface{}{&s.Boundaries, &s.Lower, &s.Upper, &s.Count}
|
||||
tmp := []any{&s.Boundaries, &s.Lower, &s.Upper, &s.Count}
|
||||
wantLen := len(tmp)
|
||||
if err := json.Unmarshal(buf, &tmp); err != nil {
|
||||
return err
|
||||
@@ -152,11 +152,11 @@ func (s SampleHistogramPair) MarshalJSON() ([]byte, error) {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return []byte(fmt.Sprintf("[%s,%s]", t, v)), nil
|
||||
return fmt.Appendf(nil, "[%s,%s]", t, v), nil
|
||||
}
|
||||
|
||||
func (s *SampleHistogramPair) UnmarshalJSON(buf []byte) error {
|
||||
tmp := []interface{}{&s.Timestamp, &s.Histogram}
|
||||
tmp := []any{&s.Timestamp, &s.Histogram}
|
||||
wantLen := len(tmp)
|
||||
if err := json.Unmarshal(buf, &tmp); err != nil {
|
||||
return err
|
||||
|
||||
2
vendor/github.com/prometheus/common/promslog/slog.go
generated
vendored
2
vendor/github.com/prometheus/common/promslog/slog.go
generated
vendored
@@ -61,7 +61,7 @@ func NewLevel() *Level {
|
||||
}
|
||||
}
|
||||
|
||||
func (l *Level) UnmarshalYAML(unmarshal func(interface{}) error) error {
|
||||
func (l *Level) UnmarshalYAML(unmarshal func(any) error) error {
|
||||
var s string
|
||||
type plain string
|
||||
if err := unmarshal((*plain)(&s)); err != nil {
|
||||
|
||||
84
vendor/github.com/prometheus/procfs/Makefile.common
generated
vendored
84
vendor/github.com/prometheus/procfs/Makefile.common
generated
vendored
@@ -55,13 +55,13 @@ ifneq ($(shell command -v gotestsum 2> /dev/null),)
|
||||
endif
|
||||
endif
|
||||
|
||||
PROMU_VERSION ?= 0.18.0
|
||||
PROMU_VERSION ?= 0.20.0
|
||||
PROMU_URL := https://github.com/prometheus/promu/releases/download/v$(PROMU_VERSION)/promu-$(PROMU_VERSION).$(GO_BUILD_PLATFORM).tar.gz
|
||||
|
||||
SKIP_GOLANGCI_LINT :=
|
||||
GOLANGCI_LINT :=
|
||||
GOLANGCI_LINT_OPTS ?=
|
||||
GOLANGCI_LINT_VERSION ?= v2.10.1
|
||||
GOLANGCI_LINT_VERSION ?= v2.11.4
|
||||
GOLANGCI_FMT_OPTS ?=
|
||||
# golangci-lint only supports linux, darwin and windows platforms on i386/amd64/arm64.
|
||||
# windows isn't included here because of the path separator being different.
|
||||
@@ -90,8 +90,8 @@ ifdef DOCKERFILE_PATH
|
||||
$(error DOCKERFILE_PATH is deprecated. Use DOCKERFILE_VARIANTS ?= $(DOCKERFILE_PATH) in the Makefile)
|
||||
endif
|
||||
|
||||
DOCKER_ARCHS ?= amd64
|
||||
DOCKERFILE_VARIANTS ?= Dockerfile $(wildcard Dockerfile.*)
|
||||
DOCKER_ARCHS ?= amd64 arm64 armv7 ppc64le riscv64 s390x
|
||||
DOCKERFILE_VARIANTS ?= $(wildcard Dockerfile Dockerfile.*)
|
||||
|
||||
# Function to extract variant from Dockerfile label.
|
||||
# Returns the variant name from io.prometheus.image.variant label, or "default" if not found.
|
||||
@@ -109,24 +109,6 @@ endif
|
||||
# Build variant:dockerfile pairs for shell iteration.
|
||||
DOCKERFILE_VARIANTS_WITH_NAMES := $(foreach df,$(DOCKERFILE_VARIANTS),$(call dockerfile_variant,$(df)):$(df))
|
||||
|
||||
# Shell helper to check whether a dockerfile/arch pair is excluded.
|
||||
define dockerfile_arch_is_excluded
|
||||
case " $(DOCKERFILE_ARCH_EXCLUSIONS) " in \
|
||||
*" $$dockerfile:$(1) "*) true ;; \
|
||||
*) false ;; \
|
||||
esac
|
||||
endef
|
||||
|
||||
# Shell helper to check whether a registry/arch pair is excluded.
|
||||
# Extracts registry from DOCKER_REPO (e.g., quay.io/prometheus -> quay.io)
|
||||
define registry_arch_is_excluded
|
||||
registry=$$(echo "$(DOCKER_REPO)" | cut -d'/' -f1); \
|
||||
case " $(DOCKER_REGISTRY_ARCH_EXCLUSIONS) " in \
|
||||
*" $$registry:$(1) "*) true ;; \
|
||||
*) false ;; \
|
||||
esac
|
||||
endef
|
||||
|
||||
BUILD_DOCKER_ARCHS = $(addprefix common-docker-,$(DOCKER_ARCHS))
|
||||
PUBLISH_DOCKER_ARCHS = $(addprefix common-docker-publish-,$(DOCKER_ARCHS))
|
||||
TAG_DOCKER_ARCHS = $(addprefix common-docker-tag-latest-,$(DOCKER_ARCHS))
|
||||
@@ -268,10 +250,6 @@ $(BUILD_DOCKER_ARCHS): common-docker-%:
|
||||
@for variant in $(DOCKERFILE_VARIANTS_WITH_NAMES); do \
|
||||
dockerfile=$${variant#*:}; \
|
||||
variant_name=$${variant%%:*}; \
|
||||
if $(call dockerfile_arch_is_excluded,$*); then \
|
||||
echo "Skipping $$variant_name variant for linux-$* (excluded by DOCKERFILE_ARCH_EXCLUSIONS)"; \
|
||||
continue; \
|
||||
fi; \
|
||||
distroless_arch="$*"; \
|
||||
if [ "$*" = "armv7" ]; then \
|
||||
distroless_arch="arm"; \
|
||||
@@ -306,14 +284,6 @@ $(PUBLISH_DOCKER_ARCHS): common-docker-publish-%:
|
||||
@for variant in $(DOCKERFILE_VARIANTS_WITH_NAMES); do \
|
||||
dockerfile=$${variant#*:}; \
|
||||
variant_name=$${variant%%:*}; \
|
||||
if $(call dockerfile_arch_is_excluded,$*); then \
|
||||
echo "Skipping push for $$variant_name variant on linux-$* (excluded by DOCKERFILE_ARCH_EXCLUSIONS)"; \
|
||||
continue; \
|
||||
fi; \
|
||||
if $(call registry_arch_is_excluded,$*); then \
|
||||
echo "Skipping push for $$variant_name variant on linux-$* to $(DOCKER_REPO) (excluded by DOCKER_REGISTRY_ARCH_EXCLUSIONS)"; \
|
||||
continue; \
|
||||
fi; \
|
||||
if [ "$$dockerfile" != "Dockerfile" ] || [ "$$variant_name" != "default" ]; then \
|
||||
echo "Pushing $$variant_name variant for linux-$*"; \
|
||||
docker push "$(DOCKER_REPO)/$(DOCKER_IMAGE_NAME)-linux-$*:$(SANITIZED_DOCKER_IMAGE_TAG)-$$variant_name"; \
|
||||
@@ -341,14 +311,6 @@ $(TAG_DOCKER_ARCHS): common-docker-tag-latest-%:
|
||||
@for variant in $(DOCKERFILE_VARIANTS_WITH_NAMES); do \
|
||||
dockerfile=$${variant#*:}; \
|
||||
variant_name=$${variant%%:*}; \
|
||||
if $(call dockerfile_arch_is_excluded,$*); then \
|
||||
echo "Skipping tag for $$variant_name variant on linux-$* (excluded by DOCKERFILE_ARCH_EXCLUSIONS)"; \
|
||||
continue; \
|
||||
fi; \
|
||||
if $(call registry_arch_is_excluded,$*); then \
|
||||
echo "Skipping tag for $$variant_name variant on linux-$* for $(DOCKER_REPO) (excluded by DOCKER_REGISTRY_ARCH_EXCLUSIONS)"; \
|
||||
continue; \
|
||||
fi; \
|
||||
if [ "$$dockerfile" != "Dockerfile" ] || [ "$$variant_name" != "default" ]; then \
|
||||
echo "Tagging $$variant_name variant for linux-$* as latest"; \
|
||||
docker tag "$(DOCKER_REPO)/$(DOCKER_IMAGE_NAME)-linux-$*:$(SANITIZED_DOCKER_IMAGE_TAG)-$$variant_name" "$(DOCKER_REPO)/$(DOCKER_IMAGE_NAME)-linux-$*:latest-$$variant_name"; \
|
||||
@@ -370,14 +332,6 @@ common-docker-manifest:
|
||||
echo "Creating manifest for $$variant_name variant"; \
|
||||
refs=""; \
|
||||
for arch in $(DOCKER_ARCHS); do \
|
||||
if $(call dockerfile_arch_is_excluded,$$arch); then \
|
||||
echo " Skipping $$arch for $$variant_name (excluded by DOCKERFILE_ARCH_EXCLUSIONS)"; \
|
||||
continue; \
|
||||
fi; \
|
||||
if $(call registry_arch_is_excluded,$$arch); then \
|
||||
echo " Skipping $$arch for $$variant_name on $(DOCKER_REPO) (excluded by DOCKER_REGISTRY_ARCH_EXCLUSIONS)"; \
|
||||
continue; \
|
||||
fi; \
|
||||
refs="$$refs $(DOCKER_REPO)/$(DOCKER_IMAGE_NAME)-linux-$$arch:$(SANITIZED_DOCKER_IMAGE_TAG)-$$variant_name"; \
|
||||
done; \
|
||||
if [ -z "$$refs" ]; then \
|
||||
@@ -391,14 +345,6 @@ common-docker-manifest:
|
||||
echo "Creating default variant ($$variant_name) manifest"; \
|
||||
refs=""; \
|
||||
for arch in $(DOCKER_ARCHS); do \
|
||||
if $(call dockerfile_arch_is_excluded,$$arch); then \
|
||||
echo " Skipping $$arch for default variant (excluded by DOCKERFILE_ARCH_EXCLUSIONS)"; \
|
||||
continue; \
|
||||
fi; \
|
||||
if $(call registry_arch_is_excluded,$$arch); then \
|
||||
echo " Skipping $$arch for default variant on $(DOCKER_REPO) (excluded by DOCKER_REGISTRY_ARCH_EXCLUSIONS)"; \
|
||||
continue; \
|
||||
fi; \
|
||||
refs="$$refs $(DOCKER_REPO)/$(DOCKER_IMAGE_NAME)-linux-$$arch:$(SANITIZED_DOCKER_IMAGE_TAG)"; \
|
||||
done; \
|
||||
if [ -z "$$refs" ]; then \
|
||||
@@ -413,14 +359,6 @@ common-docker-manifest:
|
||||
echo "Creating manifest for $$variant_name variant version tag"; \
|
||||
refs=""; \
|
||||
for arch in $(DOCKER_ARCHS); do \
|
||||
if $(call dockerfile_arch_is_excluded,$$arch); then \
|
||||
echo " Skipping $$arch for $$variant_name version tag (excluded by DOCKERFILE_ARCH_EXCLUSIONS)"; \
|
||||
continue; \
|
||||
fi; \
|
||||
if $(call registry_arch_is_excluded,$$arch); then \
|
||||
echo " Skipping $$arch for $$variant_name version tag on $(DOCKER_REPO) (excluded by DOCKER_REGISTRY_ARCH_EXCLUSIONS)"; \
|
||||
continue; \
|
||||
fi; \
|
||||
refs="$$refs $(DOCKER_REPO)/$(DOCKER_IMAGE_NAME)-linux-$$arch:v$(DOCKER_MAJOR_VERSION_TAG)-$$variant_name"; \
|
||||
done; \
|
||||
if [ -z "$$refs" ]; then \
|
||||
@@ -434,14 +372,6 @@ common-docker-manifest:
|
||||
echo "Creating default variant version tag manifest"; \
|
||||
refs=""; \
|
||||
for arch in $(DOCKER_ARCHS); do \
|
||||
if $(call dockerfile_arch_is_excluded,$$arch); then \
|
||||
echo " Skipping $$arch for default variant version tag (excluded by DOCKERFILE_ARCH_EXCLUSIONS)"; \
|
||||
continue; \
|
||||
fi; \
|
||||
if $(call registry_arch_is_excluded,$$arch); then \
|
||||
echo " Skipping $$arch for default variant version tag on $(DOCKER_REPO) (excluded by DOCKER_REGISTRY_ARCH_EXCLUSIONS)"; \
|
||||
continue; \
|
||||
fi; \
|
||||
refs="$$refs $(DOCKER_REPO)/$(DOCKER_IMAGE_NAME)-linux-$$arch:v$(DOCKER_MAJOR_VERSION_TAG)"; \
|
||||
done; \
|
||||
if [ -z "$$refs" ]; then \
|
||||
@@ -495,9 +425,3 @@ $(1)_precheck:
|
||||
exit 1; \
|
||||
fi
|
||||
endef
|
||||
|
||||
govulncheck: install-govulncheck
|
||||
govulncheck ./...
|
||||
|
||||
install-govulncheck:
|
||||
command -v govulncheck > /dev/null || go install golang.org/x/vuln/cmd/govulncheck@latest
|
||||
|
||||
2
vendor/github.com/prometheus/procfs/README.md
generated
vendored
2
vendor/github.com/prometheus/procfs/README.md
generated
vendored
@@ -7,7 +7,7 @@ metrics from the pseudo-filesystems /proc and /sys.
|
||||
backwards-incompatible ways without warnings. Use it at your own risk.
|
||||
|
||||
[](https://pkg.go.dev/github.com/prometheus/procfs)
|
||||
[](https://circleci.com/gh/prometheus/procfs/tree/master)
|
||||
[](https://github.com/prometheus/procfs/actions/workflows/ci.yml)
|
||||
[](https://goreportcard.com/report/github.com/prometheus/procfs)
|
||||
|
||||
## Usage
|
||||
|
||||
2
vendor/github.com/prometheus/procfs/SECURITY.md
generated
vendored
2
vendor/github.com/prometheus/procfs/SECURITY.md
generated
vendored
@@ -3,4 +3,4 @@
|
||||
The Prometheus security policy, including how to report vulnerabilities, can be
|
||||
found here:
|
||||
|
||||
<https://prometheus.io/docs/operating/security/>
|
||||
[https://prometheus.io/docs/operating/security/](https://prometheus.io/docs/operating/security/)
|
||||
|
||||
8
vendor/github.com/prometheus/procfs/crypto.go
generated
vendored
8
vendor/github.com/prometheus/procfs/crypto.go
generated
vendored
@@ -48,11 +48,13 @@ type Crypto struct {
|
||||
Walksize *uint64
|
||||
}
|
||||
|
||||
var cryptoFile = "crypto"
|
||||
|
||||
// Crypto parses an crypto-file (/proc/crypto) and returns a slice of
|
||||
// structs containing the relevant info. More information available here:
|
||||
// https://kernel.readthedocs.io/en/sphinx-samples/crypto-API.html
|
||||
func (fs FS) Crypto() ([]Crypto, error) {
|
||||
path := fs.proc.Path("crypto")
|
||||
path := fs.proc.Path(cryptoFile)
|
||||
b, err := util.ReadFileNoStat(path)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%w: Cannot read file %v: %w", ErrFileRead, b, err)
|
||||
@@ -82,6 +84,10 @@ func parseCrypto(r io.Reader) ([]Crypto, error) {
|
||||
continue
|
||||
}
|
||||
|
||||
if len(out) == 0 {
|
||||
return nil, fmt.Errorf("%w: parsed invalid line before name parsed: %q", ErrFileParse, text)
|
||||
}
|
||||
|
||||
kv := strings.Split(text, ":")
|
||||
if len(kv) != 2 {
|
||||
return nil, fmt.Errorf("%w: Cannot parse line: %q", ErrFileParse, text)
|
||||
|
||||
22
vendor/github.com/prometheus/procfs/mountinfo.go
generated
vendored
22
vendor/github.com/prometheus/procfs/mountinfo.go
generated
vendored
@@ -17,10 +17,10 @@ import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/prometheus/procfs/internal/util"
|
||||
)
|
||||
|
||||
// A MountInfo is a type that describes the details, options
|
||||
@@ -160,9 +160,19 @@ func mountOptionsParser(mountOptions string) map[string]string {
|
||||
return opts
|
||||
}
|
||||
|
||||
// readMountInfo reads a full mountinfo file (no 1 MiB cap, unlike util.ReadFileNoStat).
|
||||
func readMountInfo(path string) ([]byte, error) {
|
||||
f, err := os.Open(path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer f.Close()
|
||||
return io.ReadAll(f)
|
||||
}
|
||||
|
||||
// GetMounts retrieves mountinfo information from `/proc/self/mountinfo`.
|
||||
func GetMounts() ([]*MountInfo, error) {
|
||||
data, err := util.ReadFileNoStat("/proc/self/mountinfo")
|
||||
data, err := readMountInfo("/proc/self/mountinfo")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -171,7 +181,7 @@ func GetMounts() ([]*MountInfo, error) {
|
||||
|
||||
// GetProcMounts retrieves mountinfo information from a processes' `/proc/<pid>/mountinfo`.
|
||||
func GetProcMounts(pid int) ([]*MountInfo, error) {
|
||||
data, err := util.ReadFileNoStat(fmt.Sprintf("/proc/%d/mountinfo", pid))
|
||||
data, err := readMountInfo(fmt.Sprintf("/proc/%d/mountinfo", pid))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -180,7 +190,7 @@ func GetProcMounts(pid int) ([]*MountInfo, error) {
|
||||
|
||||
// GetMounts retrieves mountinfo information from `/proc/self/mountinfo`.
|
||||
func (fs FS) GetMounts() ([]*MountInfo, error) {
|
||||
data, err := util.ReadFileNoStat(fs.proc.Path("self/mountinfo"))
|
||||
data, err := readMountInfo(fs.proc.Path("self/mountinfo"))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -189,7 +199,7 @@ func (fs FS) GetMounts() ([]*MountInfo, error) {
|
||||
|
||||
// GetProcMounts retrieves mountinfo information from a processes' `/proc/<pid>/mountinfo`.
|
||||
func (fs FS) GetProcMounts(pid int) ([]*MountInfo, error) {
|
||||
data, err := util.ReadFileNoStat(fs.proc.Path(fmt.Sprintf("%d/mountinfo", pid)))
|
||||
data, err := readMountInfo(fs.proc.Path(fmt.Sprintf("%d/mountinfo", pid)))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
18
vendor/github.com/prometheus/procfs/net_wireless.go
generated
vendored
18
vendor/github.com/prometheus/procfs/net_wireless.go
generated
vendored
@@ -114,47 +114,47 @@ func parseWireless(r io.Reader) ([]*Wireless, error) {
|
||||
|
||||
qlink, err := strconv.Atoi(strings.TrimSuffix(stats[1], "."))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%w: parse Quality:link as integer %q: %w", ErrFileParse, qlink, err)
|
||||
return nil, fmt.Errorf("%w: parse Quality:link as integer %q: %w", ErrFileParse, stats[1], err)
|
||||
}
|
||||
|
||||
qlevel, err := strconv.Atoi(strings.TrimSuffix(stats[2], "."))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%w: Quality:level as integer %q: %w", ErrFileParse, qlevel, err)
|
||||
return nil, fmt.Errorf("%w: Quality:level as integer %q: %w", ErrFileParse, stats[2], err)
|
||||
}
|
||||
|
||||
qnoise, err := strconv.Atoi(strings.TrimSuffix(stats[3], "."))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%w: Quality:noise as integer %q: %w", ErrFileParse, qnoise, err)
|
||||
return nil, fmt.Errorf("%w: Quality:noise as integer %q: %w", ErrFileParse, stats[3], err)
|
||||
}
|
||||
|
||||
dnwid, err := strconv.Atoi(stats[4])
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%w: Discarded:nwid as integer %q: %w", ErrFileParse, dnwid, err)
|
||||
return nil, fmt.Errorf("%w: Discarded:nwid as integer %q: %w", ErrFileParse, stats[4], err)
|
||||
}
|
||||
|
||||
dcrypt, err := strconv.Atoi(stats[5])
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%w: Discarded:crypt as integer %q: %w", ErrFileParse, dcrypt, err)
|
||||
return nil, fmt.Errorf("%w: Discarded:crypt as integer %q: %w", ErrFileParse, stats[5], err)
|
||||
}
|
||||
|
||||
dfrag, err := strconv.Atoi(stats[6])
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%w: Discarded:frag as integer %q: %w", ErrFileParse, dfrag, err)
|
||||
return nil, fmt.Errorf("%w: Discarded:frag as integer %q: %w", ErrFileParse, stats[6], err)
|
||||
}
|
||||
|
||||
dretry, err := strconv.Atoi(stats[7])
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%w: Discarded:retry as integer %q: %w", ErrFileParse, dretry, err)
|
||||
return nil, fmt.Errorf("%w: Discarded:retry as integer %q: %w", ErrFileParse, stats[7], err)
|
||||
}
|
||||
|
||||
dmisc, err := strconv.Atoi(stats[8])
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%w: Discarded:misc as integer %q: %w", ErrFileParse, dmisc, err)
|
||||
return nil, fmt.Errorf("%w: Discarded:misc as integer %q: %w", ErrFileParse, stats[8], err)
|
||||
}
|
||||
|
||||
mbeacon, err := strconv.Atoi(stats[9])
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%w: Missed:beacon as integer %q: %w", ErrFileParse, mbeacon, err)
|
||||
return nil, fmt.Errorf("%w: Missed:beacon as integer %q: %w", ErrFileParse, stats[9], err)
|
||||
}
|
||||
|
||||
w := &Wireless{
|
||||
|
||||
2
vendor/github.com/prometheus/procfs/proc_cgroup.go
generated
vendored
2
vendor/github.com/prometheus/procfs/proc_cgroup.go
generated
vendored
@@ -60,7 +60,7 @@ func parseCgroupString(cgroupStr string) (*Cgroup, error) {
|
||||
}
|
||||
cgroup.HierarchyID, err = strconv.Atoi(fields[0])
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%w: hierarchy ID: %q", ErrFileParse, cgroup.HierarchyID)
|
||||
return nil, fmt.Errorf("%w: hierarchy ID: %q", ErrFileParse, fields[0])
|
||||
}
|
||||
if fields[1] != "" {
|
||||
ssNames := strings.Split(fields[1], ",")
|
||||
|
||||
12
vendor/modules.txt
vendored
12
vendor/modules.txt
vendored
@@ -844,7 +844,7 @@ github.com/justinas/alice
|
||||
# github.com/kevinburke/ssh_config v1.2.0
|
||||
## explicit
|
||||
github.com/kevinburke/ssh_config
|
||||
# github.com/klauspost/compress v1.18.6
|
||||
# github.com/klauspost/compress v1.19.1
|
||||
## explicit; go 1.24
|
||||
github.com/klauspost/compress
|
||||
github.com/klauspost/compress/flate
|
||||
@@ -1819,8 +1819,8 @@ github.com/prometheus/alertmanager/matcher/parse
|
||||
github.com/prometheus/alertmanager/pkg/labels
|
||||
github.com/prometheus/alertmanager/template
|
||||
github.com/prometheus/alertmanager/types
|
||||
# github.com/prometheus/client_golang v1.23.2
|
||||
## explicit; go 1.23.0
|
||||
# github.com/prometheus/client_golang v1.24.1
|
||||
## explicit; go 1.25.0
|
||||
github.com/prometheus/client_golang/internal/github.com/golang/gddo/httputil
|
||||
github.com/prometheus/client_golang/internal/github.com/golang/gddo/httputil/header
|
||||
github.com/prometheus/client_golang/prometheus
|
||||
@@ -1831,13 +1831,13 @@ github.com/prometheus/client_golang/prometheus/promhttp/internal
|
||||
# github.com/prometheus/client_model v0.6.2
|
||||
## explicit; go 1.22.0
|
||||
github.com/prometheus/client_model/go
|
||||
# github.com/prometheus/common v0.67.5
|
||||
## explicit; go 1.24.0
|
||||
# github.com/prometheus/common v0.70.1
|
||||
## explicit; go 1.25.0
|
||||
github.com/prometheus/common/expfmt
|
||||
github.com/prometheus/common/helpers/templates
|
||||
github.com/prometheus/common/model
|
||||
github.com/prometheus/common/promslog
|
||||
# github.com/prometheus/procfs v0.20.1
|
||||
# github.com/prometheus/procfs v0.21.1
|
||||
## explicit; go 1.25.0
|
||||
github.com/prometheus/procfs
|
||||
github.com/prometheus/procfs/internal/fs
|
||||
|
||||
Reference in New Issue
Block a user