diff --git a/storage/buffer_test.go b/storage/buffer_test.go index c1f34cb91c..52f7a7176a 100644 --- a/storage/buffer_test.go +++ b/storage/buffer_test.go @@ -5,7 +5,7 @@ import ( "sort" "testing" - "github.com/fabxc/tsdb/labels" + "github.com/prometheus/prometheus/pkg/labels" "github.com/stretchr/testify/require" ) diff --git a/vendor/github.com/fabxc/tsdb/chunks/bstream.go b/vendor/github.com/fabxc/tsdb/chunks/bstream.go deleted file mode 100644 index 25fadb26d2..0000000000 --- a/vendor/github.com/fabxc/tsdb/chunks/bstream.go +++ /dev/null @@ -1,169 +0,0 @@ -package chunks - -import "io" - -// bstream is a stream of bits -type bstream struct { - stream []byte // the data stream - count uint8 // how many bits are valid in current byte -} - -func newBReader(b []byte) *bstream { - return &bstream{stream: b, count: 8} -} - -func newBWriter(size int) *bstream { - return &bstream{stream: make([]byte, 0, size), count: 0} -} - -func (b *bstream) clone() *bstream { - d := make([]byte, len(b.stream)) - copy(d, b.stream) - return &bstream{stream: d, count: b.count} -} - -func (b *bstream) bytes() []byte { - return b.stream -} - -type bit bool - -const ( - zero bit = false - one bit = true -) - -func (b *bstream) writeBit(bit bit) { - if b.count == 0 { - b.stream = append(b.stream, 0) - b.count = 8 - } - - i := len(b.stream) - 1 - - if bit { - b.stream[i] |= 1 << (b.count - 1) - } - - b.count-- -} - -func (b *bstream) writeByte(byt byte) { - if b.count == 0 { - b.stream = append(b.stream, 0) - b.count = 8 - } - - i := len(b.stream) - 1 - - // fill up b.b with b.count bits from byt - b.stream[i] |= byt >> (8 - b.count) - - b.stream = append(b.stream, 0) - i++ - b.stream[i] = byt << b.count -} - -func (b *bstream) writeBits(u uint64, nbits int) { - u <<= (64 - uint(nbits)) - for nbits >= 8 { - byt := byte(u >> 56) - b.writeByte(byt) - u <<= 8 - nbits -= 8 - } - - for nbits > 0 { - b.writeBit((u >> 63) == 1) - u <<= 1 - nbits-- - } -} - -func (b *bstream) readBit() (bit, error) { - if len(b.stream) == 0 { - return false, io.EOF - } - - if b.count == 0 { - b.stream = b.stream[1:] - - if len(b.stream) == 0 { - return false, io.EOF - } - b.count = 8 - } - - d := (b.stream[0] << (8 - b.count)) & 0x80 - b.count-- - return d != 0, nil -} - -func (b *bstream) ReadByte() (byte, error) { - return b.readByte() -} - -func (b *bstream) readByte() (byte, error) { - if len(b.stream) == 0 { - return 0, io.EOF - } - - if b.count == 0 { - b.stream = b.stream[1:] - - if len(b.stream) == 0 { - return 0, io.EOF - } - return b.stream[0], nil - } - - if b.count == 8 { - b.count = 0 - return b.stream[0], nil - } - - byt := b.stream[0] << (8 - b.count) - b.stream = b.stream[1:] - - if len(b.stream) == 0 { - return 0, io.EOF - } - - // We just advanced the stream and can assume the shift to be 0. - byt |= b.stream[0] >> b.count - - return byt, nil -} - -func (b *bstream) readBits(nbits int) (uint64, error) { - var u uint64 - - for nbits >= 8 { - byt, err := b.readByte() - if err != nil { - return 0, err - } - - u = (u << 8) | uint64(byt) - nbits -= 8 - } - - if nbits == 0 { - return u, nil - } - - if nbits > int(b.count) { - u = (u << uint(b.count)) | uint64((b.stream[0]<<(8-b.count))>>(8-b.count)) - nbits -= int(b.count) - b.stream = b.stream[1:] - - if len(b.stream) == 0 { - return 0, io.EOF - } - b.count = 8 - } - - u = (u << uint(nbits)) | uint64((b.stream[0]<<(8-b.count))>>(8-uint(nbits))) - b.count -= uint8(nbits) - return u, nil -} diff --git a/vendor/github.com/fabxc/tsdb/chunks/chunk.go b/vendor/github.com/fabxc/tsdb/chunks/chunk.go deleted file mode 100644 index 6bff827357..0000000000 --- a/vendor/github.com/fabxc/tsdb/chunks/chunk.go +++ /dev/null @@ -1,57 +0,0 @@ -package chunks - -import ( - "encoding/binary" - "fmt" -) - -// Encoding is the identifier for a chunk encoding -type Encoding uint8 - -func (e Encoding) String() string { - switch e { - case EncNone: - return "none" - case EncXOR: - return "XOR" - } - return "" -} - -// The different available chunk encodings. -const ( - EncNone Encoding = iota - EncXOR -) - -// Chunk holds a sequence of sample pairs that can be iterated over and appended to. -type Chunk interface { - Bytes() []byte - Encoding() Encoding - Appender() (Appender, error) - Iterator() Iterator -} - -// FromData returns a chunk from a byte slice of chunk data. -func FromData(e Encoding, d []byte) (Chunk, error) { - switch e { - case EncXOR: - return &XORChunk{ - b: &bstream{count: 0, stream: d}, - num: binary.BigEndian.Uint16(d), - }, nil - } - return nil, fmt.Errorf("unknown chunk encoding: %d", e) -} - -// Appender adds sample pairs to a chunk. -type Appender interface { - Append(int64, float64) -} - -// Iterator is a simple iterator that can only get the next value. -type Iterator interface { - At() (int64, float64) - Err() error - Next() bool -} diff --git a/vendor/github.com/fabxc/tsdb/chunks/xor.go b/vendor/github.com/fabxc/tsdb/chunks/xor.go deleted file mode 100644 index 8acdda6ee0..0000000000 --- a/vendor/github.com/fabxc/tsdb/chunks/xor.go +++ /dev/null @@ -1,341 +0,0 @@ -package chunks - -import ( - "encoding/binary" - "math" - - bits "github.com/dgryski/go-bits" -) - -// XORChunk holds XOR encoded sample data. -type XORChunk struct { - b *bstream - num uint16 -} - -// NewXORChunk returns a new chunk with XOR encoding of the given size. -func NewXORChunk() *XORChunk { - b := make([]byte, 2, 128) - return &XORChunk{b: &bstream{stream: b, count: 0}} -} - -func (c *XORChunk) Encoding() Encoding { - return EncXOR -} - -// Bytes returns the underlying byte slice of the chunk. -func (c *XORChunk) Bytes() []byte { - return c.b.bytes() -} - -// Appender implements the Chunk interface. -func (c *XORChunk) Appender() (Appender, error) { - it := c.iterator() - - // To get an appender we must know the state it would have if we had - // appended all existing data from scratch. - // We iterate through the end and populate via the iterator's state. - for it.Next() { - } - if err := it.Err(); err != nil { - return nil, err - } - - a := &xorAppender{ - c: c, - b: c.b, - t: it.t, - v: it.val, - tDelta: it.tDelta, - leading: it.leading, - trailing: it.trailing, - } - if binary.BigEndian.Uint16(a.b.bytes()) == 0 { - a.leading = 0xff - } - return a, nil -} - -func (c *XORChunk) iterator() *xorIterator { - // Should iterators guarantee to act on a copy of the data so it doesn't lock append? - // When using striped locks to guard access to chunks, probably yes. - // Could only copy data if the chunk is not completed yet. - return &xorIterator{ - br: newBReader(c.b.bytes()[2:]), - numTotal: binary.BigEndian.Uint16(c.b.bytes()), - } -} - -// Iterator implements the Chunk interface. -func (c *XORChunk) Iterator() Iterator { - return c.iterator() -} - -type xorAppender struct { - c *XORChunk - b *bstream - - t int64 - v float64 - tDelta uint64 - - leading uint8 - trailing uint8 -} - -func (a *xorAppender) Append(t int64, v float64) { - var tDelta uint64 - num := binary.BigEndian.Uint16(a.b.bytes()) - - if num == 0 { - buf := make([]byte, binary.MaxVarintLen64) - for _, b := range buf[:binary.PutVarint(buf, t)] { - a.b.writeByte(b) - } - a.b.writeBits(math.Float64bits(v), 64) - - } else if num == 1 { - tDelta = uint64(t - a.t) - - buf := make([]byte, binary.MaxVarintLen64) - for _, b := range buf[:binary.PutUvarint(buf, tDelta)] { - a.b.writeByte(b) - } - - a.writeVDelta(v) - - } else { - tDelta = uint64(t - a.t) - dod := int64(tDelta - a.tDelta) - - // Gorilla has a max resolution of seconds, Prometheus milliseconds. - // Thus we use higher value range steps with larger bit size. - switch { - case dod == 0: - a.b.writeBit(zero) - case bitRange(dod, 14): - a.b.writeBits(0x02, 2) // '10' - a.b.writeBits(uint64(dod), 14) - case bitRange(dod, 17): - a.b.writeBits(0x06, 3) // '110' - a.b.writeBits(uint64(dod), 17) - case bitRange(dod, 20): - a.b.writeBits(0x0e, 4) // '1110' - a.b.writeBits(uint64(dod), 20) - default: - a.b.writeBits(0x0f, 4) // '1111' - a.b.writeBits(uint64(dod), 64) - } - - a.writeVDelta(v) - } - - a.t = t - a.v = v - binary.BigEndian.PutUint16(a.b.bytes(), num+1) - a.tDelta = tDelta -} - -func bitRange(x int64, nbits uint8) bool { - return -((1<<(nbits-1))-1) <= x && x <= 1<<(nbits-1) -} - -func (a *xorAppender) writeVDelta(v float64) { - vDelta := math.Float64bits(v) ^ math.Float64bits(a.v) - - if vDelta == 0 { - a.b.writeBit(zero) - return - } - a.b.writeBit(one) - - leading := uint8(bits.Clz(vDelta)) - trailing := uint8(bits.Ctz(vDelta)) - - // Clamp number of leading zeros to avoid overflow when encoding. - if leading >= 32 { - leading = 31 - } - - if a.leading != 0xff && leading >= a.leading && trailing >= a.trailing { - a.b.writeBit(zero) - a.b.writeBits(vDelta>>a.trailing, 64-int(a.leading)-int(a.trailing)) - } else { - a.leading, a.trailing = leading, trailing - - a.b.writeBit(one) - a.b.writeBits(uint64(leading), 5) - - // Note that if leading == trailing == 0, then sigbits == 64. But that value doesn't actually fit into the 6 bits we have. - // Luckily, we never need to encode 0 significant bits, since that would put us in the other case (vdelta == 0). - // So instead we write out a 0 and adjust it back to 64 on unpacking. - sigbits := 64 - leading - trailing - a.b.writeBits(uint64(sigbits), 6) - a.b.writeBits(vDelta>>trailing, int(sigbits)) - } -} - -type xorIterator struct { - br *bstream - numTotal uint16 - numRead uint16 - - t int64 - val float64 - - leading uint8 - trailing uint8 - - tDelta uint64 - err error -} - -func (it *xorIterator) At() (int64, float64) { - return it.t, it.val -} - -func (it *xorIterator) Err() error { - return it.err -} - -func (it *xorIterator) Next() bool { - if it.err != nil || it.numRead == it.numTotal { - return false - } - - if it.numRead == 0 { - t, err := binary.ReadVarint(it.br) - if err != nil { - it.err = err - return false - } - v, err := it.br.readBits(64) - if err != nil { - it.err = err - return false - } - it.t = int64(t) - it.val = math.Float64frombits(v) - - it.numRead++ - return true - } - if it.numRead == 1 { - tDelta, err := binary.ReadUvarint(it.br) - if err != nil { - it.err = err - return false - } - it.tDelta = tDelta - it.t = it.t + int64(it.tDelta) - - return it.readValue() - } - - var d byte - // read delta-of-delta - for i := 0; i < 4; i++ { - d <<= 1 - bit, err := it.br.readBit() - if err != nil { - it.err = err - return false - } - if bit == zero { - break - } - d |= 1 - } - var sz uint8 - var dod int64 - switch d { - case 0x00: - // dod == 0 - case 0x02: - sz = 14 - case 0x06: - sz = 17 - case 0x0e: - sz = 20 - case 0x0f: - bits, err := it.br.readBits(64) - if err != nil { - it.err = err - return false - } - - dod = int64(bits) - } - - if sz != 0 { - bits, err := it.br.readBits(int(sz)) - if err != nil { - it.err = err - return false - } - if bits > (1 << (sz - 1)) { - // or something - bits = bits - (1 << sz) - } - dod = int64(bits) - } - - it.tDelta = uint64(int64(it.tDelta) + dod) - it.t = it.t + int64(it.tDelta) - - return it.readValue() -} - -func (it *xorIterator) readValue() bool { - bit, err := it.br.readBit() - if err != nil { - it.err = err - return false - } - - if bit == zero { - // it.val = it.val - } else { - bit, err := it.br.readBit() - if err != nil { - it.err = err - return false - } - if bit == zero { - // reuse leading/trailing zero bits - // it.leading, it.trailing = it.leading, it.trailing - } else { - bits, err := it.br.readBits(5) - if err != nil { - it.err = err - return false - } - it.leading = uint8(bits) - - bits, err = it.br.readBits(6) - if err != nil { - it.err = err - return false - } - mbits := uint8(bits) - // 0 significant bits here means we overflowed and we actually need 64; see comment in encoder - if mbits == 0 { - mbits = 64 - } - it.trailing = 64 - it.leading - mbits - } - - mbits := int(64 - it.leading - it.trailing) - bits, err := it.br.readBits(mbits) - if err != nil { - it.err = err - return false - } - vbits := math.Float64bits(it.val) - vbits ^= (bits << it.trailing) - it.val = math.Float64frombits(vbits) - } - - it.numRead++ - return true -} diff --git a/vendor/github.com/fabxc/tsdb/labels/labels.go b/vendor/github.com/fabxc/tsdb/labels/labels.go deleted file mode 100644 index 0b79bc2e93..0000000000 --- a/vendor/github.com/fabxc/tsdb/labels/labels.go +++ /dev/null @@ -1,143 +0,0 @@ -package labels - -import ( - "bytes" - "sort" - "strconv" - "strings" - - "github.com/cespare/xxhash" -) - -const sep = '\xff' - -// Label is a key/value pair of strings. -type Label struct { - Name, Value string -} - -// Labels is a sorted set of labels. Order has to be guaranteed upon -// instantiation. -type Labels []Label - -func (ls Labels) Len() int { return len(ls) } -func (ls Labels) Swap(i, j int) { ls[i], ls[j] = ls[j], ls[i] } -func (ls Labels) Less(i, j int) bool { return ls[i].Name < ls[j].Name } - -func (ls Labels) String() string { - var b bytes.Buffer - - b.WriteByte('{') - for i, l := range ls { - if i > 0 { - b.WriteByte(',') - } - b.WriteString(l.Name) - b.WriteByte('=') - b.WriteString(strconv.Quote(l.Value)) - } - b.WriteByte('}') - - return b.String() -} - -// Hash returns a hash value for the label set. -func (ls Labels) Hash() uint64 { - b := make([]byte, 0, 1024) - - for _, v := range ls { - b = append(b, v.Name...) - b = append(b, sep) - b = append(b, v.Value...) - b = append(b, sep) - } - return xxhash.Sum64(b) -} - -// Get returns the value for the label with the given name. -// Returns an empty string if the label doesn't exist. -func (ls Labels) Get(name string) string { - for _, l := range ls { - if l.Name == name { - return l.Value - } - } - return "" -} - -// Equals returns whether the two label sets are equal. -func (ls Labels) Equals(o Labels) bool { - if len(ls) != len(o) { - return false - } - for i, l := range ls { - if l.Name != o[i].Name || l.Value != o[i].Value { - return false - } - } - return true -} - -// Map returns a string map of the labels. -func (ls Labels) Map() map[string]string { - m := make(map[string]string, len(ls)) - for _, l := range ls { - m[l.Name] = l.Value - } - return m -} - -// New returns a sorted Labels from the given labels. -// The caller has to guarantee that all label names are unique. -func New(ls ...Label) Labels { - set := make(Labels, 0, len(ls)) - for _, l := range ls { - set = append(set, l) - } - sort.Sort(set) - - return set -} - -// FromMap returns new sorted Labels from the given map. -func FromMap(m map[string]string) Labels { - l := make([]Label, 0, len(m)) - for k, v := range m { - l = append(l, Label{Name: k, Value: v}) - } - return New(l...) -} - -// FromStrings creates new labels from pairs of strings. -func FromStrings(ss ...string) Labels { - if len(ss)%2 != 0 { - panic("invalid number of strings") - } - var res Labels - for i := 0; i < len(ss); i += 2 { - res = append(res, Label{Name: ss[i], Value: ss[i+1]}) - } - - sort.Sort(res) - return res -} - -// Compare compares the two label sets. -// The result will be 0 if a==b, <0 if a < b, and >0 if a > b. -func Compare(a, b Labels) int { - l := len(a) - if len(b) < l { - l = len(b) - } - - for i := 0; i < l; i++ { - if d := strings.Compare(a[i].Name, b[i].Name); d != 0 { - return d - } - if d := strings.Compare(a[i].Value, b[i].Value); d != 0 { - return d - } - } - // If all labels so far were in common, the set with fewer labels comes first. - return len(a) - len(b) -} diff --git a/vendor/github.com/fabxc/tsdb/labels/selector.go b/vendor/github.com/fabxc/tsdb/labels/selector.go deleted file mode 100644 index 0bcf5380c9..0000000000 --- a/vendor/github.com/fabxc/tsdb/labels/selector.go +++ /dev/null @@ -1,66 +0,0 @@ -package labels - -import "regexp" - -// Selector holds constraints for matching against a label set. -type Selector []Matcher - -// Matches returns whether the labels satisfy all matchers. -func (s Selector) Matches(labels Labels) bool { - for _, m := range s { - if v := labels.Get(m.Name()); !m.Matches(v) { - return false - } - } - return true -} - -// Matcher specifies a constraint for the value of a label. -type Matcher interface { - // Name returns the label name the matcher should apply to. - Name() string - // Matches checks whether a value fulfills the constraints. - Matches(v string) bool -} - -type EqualMatcher struct { - name, value string -} - -func (m *EqualMatcher) Name() string { return m.name } -func (m *EqualMatcher) Matches(v string) bool { return v == m.value } - -// NewEqualMatcher returns a new matcher matching an exact label value. -func NewEqualMatcher(name, value string) Matcher { - return &EqualMatcher{name: name, value: value} -} - -type regexpMatcher struct { - name string - re *regexp.Regexp -} - -func (m *regexpMatcher) Name() string { return m.name } -func (m *regexpMatcher) Matches(v string) bool { return m.re.MatchString(v) } - -// NewRegexpMatcher returns a new matcher verifying that a value matches -// the regular expression pattern. -func NewRegexpMatcher(name, pattern string) (Matcher, error) { - re, err := regexp.Compile(pattern) - if err != nil { - return nil, err - } - return ®expMatcher{name: name, re: re}, nil -} - -// notMatcher inverts the matching result for a matcher. -type notMatcher struct { - Matcher -} - -func (m *notMatcher) Matches(v string) bool { return !m.Matcher.Matches(v) } - -// Not inverts the matcher's matching result. -func Not(m Matcher) Matcher { - return ¬Matcher{m} -} diff --git a/vendor/golang.org/x/time/LICENSE b/vendor/golang.org/x/time/LICENSE deleted file mode 100644 index 6a66aea5ea..0000000000 --- a/vendor/golang.org/x/time/LICENSE +++ /dev/null @@ -1,27 +0,0 @@ -Copyright (c) 2009 The Go Authors. All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - * Redistributions of source code must retain the above copyright -notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above -copyright notice, this list of conditions and the following disclaimer -in the documentation and/or other materials provided with the -distribution. - * Neither the name of Google Inc. nor the names of its -contributors may be used to endorse or promote products derived from -this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/golang.org/x/time/PATENTS b/vendor/golang.org/x/time/PATENTS deleted file mode 100644 index 733099041f..0000000000 --- a/vendor/golang.org/x/time/PATENTS +++ /dev/null @@ -1,22 +0,0 @@ -Additional IP Rights Grant (Patents) - -"This implementation" means the copyrightable works distributed by -Google as part of the Go project. - -Google hereby grants to You a perpetual, worldwide, non-exclusive, -no-charge, royalty-free, irrevocable (except as stated in this section) -patent license to make, have made, use, offer to sell, sell, import, -transfer and otherwise run, modify and propagate the contents of this -implementation of Go, where such license applies only to those patent -claims, both currently owned or controlled by Google and acquired in -the future, licensable by Google that are necessarily infringed by this -implementation of Go. This grant does not include claims that would be -infringed only as a consequence of further modification of this -implementation. If you or your agent or exclusive licensee institute or -order or agree to the institution of patent litigation against any -entity (including a cross-claim or counterclaim in a lawsuit) alleging -that this implementation of Go or any code incorporated within this -implementation of Go constitutes direct or contributory patent -infringement, or inducement of patent infringement, then any patent -rights granted to you under this License for this implementation of Go -shall terminate as of the date such litigation is filed. diff --git a/vendor/golang.org/x/time/rate/rate.go b/vendor/golang.org/x/time/rate/rate.go deleted file mode 100644 index 938feaffe9..0000000000 --- a/vendor/golang.org/x/time/rate/rate.go +++ /dev/null @@ -1,371 +0,0 @@ -// Copyright 2015 The 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 rate provides a rate limiter. -package rate - -import ( - "fmt" - "math" - "sync" - "time" - - "golang.org/x/net/context" -) - -// Limit defines the maximum frequency of some events. -// Limit is represented as number of events per second. -// A zero Limit allows no events. -type Limit float64 - -// Inf is the infinite rate limit; it allows all events (even if burst is zero). -const Inf = Limit(math.MaxFloat64) - -// Every converts a minimum time interval between events to a Limit. -func Every(interval time.Duration) Limit { - if interval <= 0 { - return Inf - } - return 1 / Limit(interval.Seconds()) -} - -// A Limiter controls how frequently events are allowed to happen. -// It implements a "token bucket" of size b, initially full and refilled -// at rate r tokens per second. -// Informally, in any large enough time interval, the Limiter limits the -// rate to r tokens per second, with a maximum burst size of b events. -// As a special case, if r == Inf (the infinite rate), b is ignored. -// See https://en.wikipedia.org/wiki/Token_bucket for more about token buckets. -// -// The zero value is a valid Limiter, but it will reject all events. -// Use NewLimiter to create non-zero Limiters. -// -// Limiter has three main methods, Allow, Reserve, and Wait. -// Most callers should use Wait. -// -// Each of the three methods consumes a single token. -// They differ in their behavior when no token is available. -// If no token is available, Allow returns false. -// If no token is available, Reserve returns a reservation for a future token -// and the amount of time the caller must wait before using it. -// If no token is available, Wait blocks until one can be obtained -// or its associated context.Context is canceled. -// -// The methods AllowN, ReserveN, and WaitN consume n tokens. -type Limiter struct { - limit Limit - burst int - - mu sync.Mutex - tokens float64 - // last is the last time the limiter's tokens field was updated - last time.Time - // lastEvent is the latest time of a rate-limited event (past or future) - lastEvent time.Time -} - -// Limit returns the maximum overall event rate. -func (lim *Limiter) Limit() Limit { - lim.mu.Lock() - defer lim.mu.Unlock() - return lim.limit -} - -// Burst returns the maximum burst size. Burst is the maximum number of tokens -// that can be consumed in a single call to Allow, Reserve, or Wait, so higher -// Burst values allow more events to happen at once. -// A zero Burst allows no events, unless limit == Inf. -func (lim *Limiter) Burst() int { - return lim.burst -} - -// NewLimiter returns a new Limiter that allows events up to rate r and permits -// bursts of at most b tokens. -func NewLimiter(r Limit, b int) *Limiter { - return &Limiter{ - limit: r, - burst: b, - } -} - -// Allow is shorthand for AllowN(time.Now(), 1). -func (lim *Limiter) Allow() bool { - return lim.AllowN(time.Now(), 1) -} - -// AllowN reports whether n events may happen at time now. -// Use this method if you intend to drop / skip events that exceed the rate limit. -// Otherwise use Reserve or Wait. -func (lim *Limiter) AllowN(now time.Time, n int) bool { - return lim.reserveN(now, n, 0).ok -} - -// A Reservation holds information about events that are permitted by a Limiter to happen after a delay. -// A Reservation may be canceled, which may enable the Limiter to permit additional events. -type Reservation struct { - ok bool - lim *Limiter - tokens int - timeToAct time.Time - // This is the Limit at reservation time, it can change later. - limit Limit -} - -// OK returns whether the limiter can provide the requested number of tokens -// within the maximum wait time. If OK is false, Delay returns InfDuration, and -// Cancel does nothing. -func (r *Reservation) OK() bool { - return r.ok -} - -// Delay is shorthand for DelayFrom(time.Now()). -func (r *Reservation) Delay() time.Duration { - return r.DelayFrom(time.Now()) -} - -// InfDuration is the duration returned by Delay when a Reservation is not OK. -const InfDuration = time.Duration(1<<63 - 1) - -// DelayFrom returns the duration for which the reservation holder must wait -// before taking the reserved action. Zero duration means act immediately. -// InfDuration means the limiter cannot grant the tokens requested in this -// Reservation within the maximum wait time. -func (r *Reservation) DelayFrom(now time.Time) time.Duration { - if !r.ok { - return InfDuration - } - delay := r.timeToAct.Sub(now) - if delay < 0 { - return 0 - } - return delay -} - -// Cancel is shorthand for CancelAt(time.Now()). -func (r *Reservation) Cancel() { - r.CancelAt(time.Now()) - return -} - -// CancelAt indicates that the reservation holder will not perform the reserved action -// and reverses the effects of this Reservation on the rate limit as much as possible, -// considering that other reservations may have already been made. -func (r *Reservation) CancelAt(now time.Time) { - if !r.ok { - return - } - - r.lim.mu.Lock() - defer r.lim.mu.Unlock() - - if r.lim.limit == Inf || r.tokens == 0 || r.timeToAct.Before(now) { - return - } - - // calculate tokens to restore - // The duration between lim.lastEvent and r.timeToAct tells us how many tokens were reserved - // after r was obtained. These tokens should not be restored. - restoreTokens := float64(r.tokens) - r.limit.tokensFromDuration(r.lim.lastEvent.Sub(r.timeToAct)) - if restoreTokens <= 0 { - return - } - // advance time to now - now, _, tokens := r.lim.advance(now) - // calculate new number of tokens - tokens += restoreTokens - if burst := float64(r.lim.burst); tokens > burst { - tokens = burst - } - // update state - r.lim.last = now - r.lim.tokens = tokens - if r.timeToAct == r.lim.lastEvent { - prevEvent := r.timeToAct.Add(r.limit.durationFromTokens(float64(-r.tokens))) - if !prevEvent.Before(now) { - r.lim.lastEvent = prevEvent - } - } - - return -} - -// Reserve is shorthand for ReserveN(time.Now(), 1). -func (lim *Limiter) Reserve() *Reservation { - return lim.ReserveN(time.Now(), 1) -} - -// ReserveN returns a Reservation that indicates how long the caller must wait before n events happen. -// The Limiter takes this Reservation into account when allowing future events. -// ReserveN returns false if n exceeds the Limiter's burst size. -// Usage example: -// r := lim.ReserveN(time.Now(), 1) -// if !r.OK() { -// // Not allowed to act! Did you remember to set lim.burst to be > 0 ? -// return -// } -// time.Sleep(r.Delay()) -// Act() -// Use this method if you wish to wait and slow down in accordance with the rate limit without dropping events. -// If you need to respect a deadline or cancel the delay, use Wait instead. -// To drop or skip events exceeding rate limit, use Allow instead. -func (lim *Limiter) ReserveN(now time.Time, n int) *Reservation { - r := lim.reserveN(now, n, InfDuration) - return &r -} - -// Wait is shorthand for WaitN(ctx, 1). -func (lim *Limiter) Wait(ctx context.Context) (err error) { - return lim.WaitN(ctx, 1) -} - -// WaitN blocks until lim permits n events to happen. -// It returns an error if n exceeds the Limiter's burst size, the Context is -// canceled, or the expected wait time exceeds the Context's Deadline. -// The burst limit is ignored if the rate limit is Inf. -func (lim *Limiter) WaitN(ctx context.Context, n int) (err error) { - if n > lim.burst && lim.limit != Inf { - return fmt.Errorf("rate: Wait(n=%d) exceeds limiter's burst %d", n, lim.burst) - } - // Check if ctx is already cancelled - select { - case <-ctx.Done(): - return ctx.Err() - default: - } - // Determine wait limit - now := time.Now() - waitLimit := InfDuration - if deadline, ok := ctx.Deadline(); ok { - waitLimit = deadline.Sub(now) - } - // Reserve - r := lim.reserveN(now, n, waitLimit) - if !r.ok { - return fmt.Errorf("rate: Wait(n=%d) would exceed context deadline", n) - } - // Wait - t := time.NewTimer(r.DelayFrom(now)) - defer t.Stop() - select { - case <-t.C: - // We can proceed. - return nil - case <-ctx.Done(): - // Context was canceled before we could proceed. Cancel the - // reservation, which may permit other events to proceed sooner. - r.Cancel() - return ctx.Err() - } -} - -// SetLimit is shorthand for SetLimitAt(time.Now(), newLimit). -func (lim *Limiter) SetLimit(newLimit Limit) { - lim.SetLimitAt(time.Now(), newLimit) -} - -// SetLimitAt sets a new Limit for the limiter. The new Limit, and Burst, may be violated -// or underutilized by those which reserved (using Reserve or Wait) but did not yet act -// before SetLimitAt was called. -func (lim *Limiter) SetLimitAt(now time.Time, newLimit Limit) { - lim.mu.Lock() - defer lim.mu.Unlock() - - now, _, tokens := lim.advance(now) - - lim.last = now - lim.tokens = tokens - lim.limit = newLimit -} - -// reserveN is a helper method for AllowN, ReserveN, and WaitN. -// maxFutureReserve specifies the maximum reservation wait duration allowed. -// reserveN returns Reservation, not *Reservation, to avoid allocation in AllowN and WaitN. -func (lim *Limiter) reserveN(now time.Time, n int, maxFutureReserve time.Duration) Reservation { - lim.mu.Lock() - - if lim.limit == Inf { - lim.mu.Unlock() - return Reservation{ - ok: true, - lim: lim, - tokens: n, - timeToAct: now, - } - } - - now, last, tokens := lim.advance(now) - - // Calculate the remaining number of tokens resulting from the request. - tokens -= float64(n) - - // Calculate the wait duration - var waitDuration time.Duration - if tokens < 0 { - waitDuration = lim.limit.durationFromTokens(-tokens) - } - - // Decide result - ok := n <= lim.burst && waitDuration <= maxFutureReserve - - // Prepare reservation - r := Reservation{ - ok: ok, - lim: lim, - limit: lim.limit, - } - if ok { - r.tokens = n - r.timeToAct = now.Add(waitDuration) - } - - // Update state - if ok { - lim.last = now - lim.tokens = tokens - lim.lastEvent = r.timeToAct - } else { - lim.last = last - } - - lim.mu.Unlock() - return r -} - -// advance calculates and returns an updated state for lim resulting from the passage of time. -// lim is not changed. -func (lim *Limiter) advance(now time.Time) (newNow time.Time, newLast time.Time, newTokens float64) { - last := lim.last - if now.Before(last) { - last = now - } - - // Avoid making delta overflow below when last is very old. - maxElapsed := lim.limit.durationFromTokens(float64(lim.burst) - lim.tokens) - elapsed := now.Sub(last) - if elapsed > maxElapsed { - elapsed = maxElapsed - } - - // Calculate the new number of tokens, due to time that passed. - delta := lim.limit.tokensFromDuration(elapsed) - tokens := lim.tokens + delta - if burst := float64(lim.burst); tokens > burst { - tokens = burst - } - - return now, last, tokens -} - -// durationFromTokens is a unit conversion function from the number of tokens to the duration -// of time it takes to accumulate them at a rate of limit tokens per second. -func (limit Limit) durationFromTokens(tokens float64) time.Duration { - seconds := tokens / float64(limit) - return time.Nanosecond * time.Duration(1e9*seconds) -} - -// tokensFromDuration is a unit conversion function from a time duration to the number of tokens -// which could be accumulated during that duration at a rate of limit tokens per second. -func (limit Limit) tokensFromDuration(d time.Duration) float64 { - return d.Seconds() * float64(limit) -} diff --git a/vendor/vendor.json b/vendor/vendor.json index 51cba62d66..4ef91e4a52 100644 --- a/vendor/vendor.json +++ b/vendor/vendor.json @@ -361,18 +361,6 @@ "revision": "c589d0c9f0d81640c518354c7bcae77d99820aa3", "revisionTime": "2016-09-30T00:14:02Z" }, - { - "checksumSHA1": "uVzWuLvF646YjiKomsc2CR1ua58=", - "path": "github.com/fabxc/tsdb/chunks", - "revision": "ca1bc920b795cfc670002e7643471b0277e79a9b", - "revisionTime": "2017-03-08T15:54:13Z" - }, - { - "checksumSHA1": "0Nl+7XBhC+XLpkgkWc6cEtW37aE=", - "path": "github.com/fabxc/tsdb/labels", - "revision": "ca1bc920b795cfc670002e7643471b0277e79a9b", - "revisionTime": "2017-03-08T15:54:13Z" - }, { "checksumSHA1": "ww7LVo7jNJ1o6sfRcromEHKyY+o=", "origin": "k8s.io/client-go/1.5/vendor/github.com/ghodss/yaml", @@ -882,12 +870,6 @@ "revision": "c589d0c9f0d81640c518354c7bcae77d99820aa3", "revisionTime": "2016-09-30T00:14:02Z" }, - { - "checksumSHA1": "eFQDEix/mGnhwnFu/Hq63zMfrX8=", - "path": "golang.org/x/time/rate", - "revision": "f51c12702a4d776e4c1fa9b0fabab841babae631", - "revisionTime": "2016-10-28T04:02:39Z" - }, { "checksumSHA1": "AjdmRXf0fiy6Bec9mNlsGsmZi1k=", "path": "google.golang.org/api/compute/v1",