parent
fe67d2f16a
commit
67f0ca8f0e
@ -1,98 +0,0 @@ |
||||
// Copyright 2017 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.
|
||||
|
||||
package tsdb |
||||
|
||||
import ( |
||||
"math/rand" |
||||
"testing" |
||||
|
||||
"github.com/pkg/errors" |
||||
"github.com/prometheus/tsdb/chunks" |
||||
"github.com/prometheus/tsdb/testutil" |
||||
) |
||||
|
||||
type mockChunkReader map[uint64]chunks.Chunk |
||||
|
||||
func (cr mockChunkReader) Chunk(ref uint64) (chunks.Chunk, error) { |
||||
chk, ok := cr[ref] |
||||
if ok { |
||||
return chk, nil |
||||
} |
||||
|
||||
return nil, errors.New("Chunk with ref not found") |
||||
} |
||||
|
||||
func (cr mockChunkReader) Close() error { |
||||
return nil |
||||
} |
||||
|
||||
func TestDeletedIterator(t *testing.T) { |
||||
chk := chunks.NewXORChunk() |
||||
app, err := chk.Appender() |
||||
testutil.Ok(t, err) |
||||
// Insert random stuff from (0, 1000).
|
||||
act := make([]sample, 1000) |
||||
for i := 0; i < 1000; i++ { |
||||
act[i].t = int64(i) |
||||
act[i].v = rand.Float64() |
||||
app.Append(act[i].t, act[i].v) |
||||
} |
||||
|
||||
cases := []struct { |
||||
r Intervals |
||||
}{ |
||||
{r: Intervals{{1, 20}}}, |
||||
{r: Intervals{{1, 10}, {12, 20}, {21, 23}, {25, 30}}}, |
||||
{r: Intervals{{1, 10}, {12, 20}, {20, 30}}}, |
||||
{r: Intervals{{1, 10}, {12, 23}, {25, 30}}}, |
||||
{r: Intervals{{1, 23}, {12, 20}, {25, 30}}}, |
||||
{r: Intervals{{1, 23}, {12, 20}, {25, 3000}}}, |
||||
{r: Intervals{{0, 2000}}}, |
||||
{r: Intervals{{500, 2000}}}, |
||||
{r: Intervals{{0, 200}}}, |
||||
{r: Intervals{{1000, 20000}}}, |
||||
} |
||||
|
||||
for _, c := range cases { |
||||
i := int64(-1) |
||||
it := &deletedIterator{it: chk.Iterator(), intervals: c.r[:]} |
||||
ranges := c.r[:] |
||||
for it.Next() { |
||||
i++ |
||||
for _, tr := range ranges { |
||||
if tr.inBounds(i) { |
||||
i = tr.Maxt + 1 |
||||
ranges = ranges[1:] |
||||
} |
||||
} |
||||
|
||||
testutil.Assert(t, i < 1000 == true, "") |
||||
|
||||
ts, v := it.At() |
||||
testutil.Equals(t, act[i].t, ts) |
||||
testutil.Equals(t, act[i].v, v) |
||||
} |
||||
// There has been an extra call to Next().
|
||||
i++ |
||||
for _, tr := range ranges { |
||||
if tr.inBounds(i) { |
||||
i = tr.Maxt + 1 |
||||
ranges = ranges[1:] |
||||
} |
||||
} |
||||
|
||||
testutil.Assert(t, i < 1000 == false, "") |
||||
testutil.Ok(t, it.Err()) |
||||
} |
||||
} |
||||
@ -0,0 +1,48 @@ |
||||
package fileutil |
||||
|
||||
import ( |
||||
"os" |
||||
|
||||
"github.com/pkg/errors" |
||||
) |
||||
|
||||
type MmapFile struct { |
||||
f *os.File |
||||
b []byte |
||||
} |
||||
|
||||
func OpenMmapFile(path string) (*MmapFile, error) { |
||||
f, err := os.Open(path) |
||||
if err != nil { |
||||
return nil, errors.Wrap(err, "try lock file") |
||||
} |
||||
info, err := f.Stat() |
||||
if err != nil { |
||||
return nil, errors.Wrap(err, "stat") |
||||
} |
||||
|
||||
b, err := mmap(f, int(info.Size())) |
||||
if err != nil { |
||||
return nil, errors.Wrap(err, "mmap") |
||||
} |
||||
|
||||
return &MmapFile{f: f, b: b}, nil |
||||
} |
||||
|
||||
func (f *MmapFile) Close() error { |
||||
err0 := munmap(f.b) |
||||
err1 := f.f.Close() |
||||
|
||||
if err0 != nil { |
||||
return err0 |
||||
} |
||||
return err1 |
||||
} |
||||
|
||||
func (f *MmapFile) File() *os.File { |
||||
return f.f |
||||
} |
||||
|
||||
func (f *MmapFile) Bytes() []byte { |
||||
return f.b |
||||
} |
||||
@ -0,0 +1,179 @@ |
||||
package index |
||||
|
||||
import ( |
||||
"encoding/binary" |
||||
"hash" |
||||
"hash/crc32" |
||||
"unsafe" |
||||
) |
||||
|
||||
// enbuf is a helper type to populate a byte slice with various types.
|
||||
type encbuf struct { |
||||
b []byte |
||||
c [binary.MaxVarintLen64]byte |
||||
} |
||||
|
||||
func (e *encbuf) reset() { e.b = e.b[:0] } |
||||
func (e *encbuf) get() []byte { return e.b } |
||||
func (e *encbuf) len() int { return len(e.b) } |
||||
|
||||
func (e *encbuf) putString(s string) { e.b = append(e.b, s...) } |
||||
func (e *encbuf) putBytes(b []byte) { e.b = append(e.b, b...) } |
||||
func (e *encbuf) putByte(c byte) { e.b = append(e.b, c) } |
||||
|
||||
func (e *encbuf) putBE32int(x int) { e.putBE32(uint32(x)) } |
||||
func (e *encbuf) putBE64int(x int) { e.putBE64(uint64(x)) } |
||||
func (e *encbuf) putBE64int64(x int64) { e.putBE64(uint64(x)) } |
||||
func (e *encbuf) putUvarint32(x uint32) { e.putUvarint64(uint64(x)) } |
||||
func (e *encbuf) putUvarint(x int) { e.putUvarint64(uint64(x)) } |
||||
|
||||
func (e *encbuf) putBE32(x uint32) { |
||||
binary.BigEndian.PutUint32(e.c[:], x) |
||||
e.b = append(e.b, e.c[:4]...) |
||||
} |
||||
|
||||
func (e *encbuf) putBE64(x uint64) { |
||||
binary.BigEndian.PutUint64(e.c[:], x) |
||||
e.b = append(e.b, e.c[:8]...) |
||||
} |
||||
|
||||
func (e *encbuf) putUvarint64(x uint64) { |
||||
n := binary.PutUvarint(e.c[:], x) |
||||
e.b = append(e.b, e.c[:n]...) |
||||
} |
||||
|
||||
func (e *encbuf) putVarint64(x int64) { |
||||
n := binary.PutVarint(e.c[:], x) |
||||
e.b = append(e.b, e.c[:n]...) |
||||
} |
||||
|
||||
// putVarintStr writes a string to the buffer prefixed by its varint length (in bytes!).
|
||||
func (e *encbuf) putUvarintStr(s string) { |
||||
b := *(*[]byte)(unsafe.Pointer(&s)) |
||||
e.putUvarint(len(b)) |
||||
e.putString(s) |
||||
} |
||||
|
||||
// putHash appends a hash over the buffers current contents to the buffer.
|
||||
func (e *encbuf) putHash(h hash.Hash) { |
||||
h.Reset() |
||||
_, err := h.Write(e.b) |
||||
if err != nil { |
||||
panic(err) // The CRC32 implementation does not error
|
||||
} |
||||
e.b = h.Sum(e.b) |
||||
} |
||||
|
||||
// decbuf provides safe methods to extract data from a byte slice. It does all
|
||||
// necessary bounds checking and advancing of the byte slice.
|
||||
// Several datums can be extracted without checking for errors. However, before using
|
||||
// any datum, the err() method must be checked.
|
||||
type decbuf struct { |
||||
b []byte |
||||
e error |
||||
} |
||||
|
||||
func (d *decbuf) uvarint() int { return int(d.uvarint64()) } |
||||
func (d *decbuf) uvarint32() uint32 { return uint32(d.uvarint64()) } |
||||
func (d *decbuf) be32int() int { return int(d.be32()) } |
||||
func (d *decbuf) be64int64() int64 { return int64(d.be64()) } |
||||
|
||||
// crc32 returns a CRC32 checksum over the remaining bytes.
|
||||
func (d *decbuf) crc32() uint32 { |
||||
return crc32.Checksum(d.b, castagnoliTable) |
||||
} |
||||
|
||||
func (d *decbuf) uvarintStr() string { |
||||
l := d.uvarint64() |
||||
if d.e != nil { |
||||
return "" |
||||
} |
||||
if len(d.b) < int(l) { |
||||
d.e = errInvalidSize |
||||
return "" |
||||
} |
||||
s := string(d.b[:l]) |
||||
d.b = d.b[l:] |
||||
return s |
||||
} |
||||
|
||||
func (d *decbuf) varint64() int64 { |
||||
if d.e != nil { |
||||
return 0 |
||||
} |
||||
x, n := binary.Varint(d.b) |
||||
if n < 1 { |
||||
d.e = errInvalidSize |
||||
return 0 |
||||
} |
||||
d.b = d.b[n:] |
||||
return x |
||||
} |
||||
|
||||
func (d *decbuf) uvarint64() uint64 { |
||||
if d.e != nil { |
||||
return 0 |
||||
} |
||||
x, n := binary.Uvarint(d.b) |
||||
if n < 1 { |
||||
d.e = errInvalidSize |
||||
return 0 |
||||
} |
||||
d.b = d.b[n:] |
||||
return x |
||||
} |
||||
|
||||
func (d *decbuf) be64() uint64 { |
||||
if d.e != nil { |
||||
return 0 |
||||
} |
||||
if len(d.b) < 4 { |
||||
d.e = errInvalidSize |
||||
return 0 |
||||
} |
||||
x := binary.BigEndian.Uint64(d.b) |
||||
d.b = d.b[8:] |
||||
return x |
||||
} |
||||
|
||||
func (d *decbuf) be32() uint32 { |
||||
if d.e != nil { |
||||
return 0 |
||||
} |
||||
if len(d.b) < 4 { |
||||
d.e = errInvalidSize |
||||
return 0 |
||||
} |
||||
x := binary.BigEndian.Uint32(d.b) |
||||
d.b = d.b[4:] |
||||
return x |
||||
} |
||||
|
||||
func (d *decbuf) byte() byte { |
||||
if d.e != nil { |
||||
return 0 |
||||
} |
||||
if len(d.b) < 1 { |
||||
d.e = errInvalidSize |
||||
return 0 |
||||
} |
||||
x := d.b[0] |
||||
d.b = d.b[1:] |
||||
return x |
||||
} |
||||
|
||||
func (d *decbuf) decbuf(l int) decbuf { |
||||
if d.e != nil { |
||||
return decbuf{e: d.e} |
||||
} |
||||
if l > len(d.b) { |
||||
return decbuf{e: errInvalidSize} |
||||
} |
||||
r := decbuf{b: d.b[:l]} |
||||
d.b = d.b[l:] |
||||
return r |
||||
} |
||||
|
||||
func (d *decbuf) err() error { return d.e } |
||||
func (d *decbuf) len() int { return len(d.b) } |
||||
func (d *decbuf) get() []byte { return d.b } |
||||
Loading…
Reference in new issue