func (t *TSMReader) Key(index int, entries *[]IndexEntry) ([]byte, byte, []IndexEntry) {
	return t.index.Key(index, entries)
}
Key returns the key and the underlying entry at the numeric index.
package tsm1
import (
	"bytes"
	"encoding/binary"
	"fmt"
	"io"
	"math"
	"os"
	"runtime"
	"sort"
	"sync"
	"sync/atomic"
	"github.com/influxdata/influxdb/pkg/bytesutil"
)
var ErrFileInUse = fmt.Errorf("file still in use")
var nilOffset = []byte{255, 255, 255, 255}
type TSMReader struct {
	refs   int64
	refsWG sync.WaitGroup
	mu sync.RWMutex
	accessor blockAccessor
	index TSMIndex
	tombstoner *Tombstoner
	size int64
	lastModified int64
	deleteMu sync.Mutex
}
type TSMIndex interface {
	Delete(keys [][]byte)
	DeleteRange(keys [][]byte, minTime, maxTime int64)
	ContainsKey(key []byte) bool
	Contains(key []byte) bool
	ContainsValue(key []byte, timestamp int64) bool
	Entries(key []byte) []IndexEntry
	ReadEntries(key []byte, entries *[]IndexEntry) []IndexEntry
	Entry(key []byte, timestamp int64) *IndexEntry
	Key(index int, entries *[]IndexEntry) ([]byte, byte, []IndexEntry)
	KeyAt(index int) ([]byte, byte)
	KeyCount() int
	Seek(key []byte) int
	OverlapsTimeRange(min, max int64) bool
	OverlapsKeyRange(min, max []byte) bool
	Size() uint32
	TimeRange() (int64, int64)
	TombstoneRange(key []byte) []TimeRange
	KeyRange() ([]byte, []byte)
	Type(key []byte) (byte, error)
	UnmarshalBinary(b []byte) error
	Close() error
}
type BlockIterator struct {
	r *TSMReader
	i int
	n int
	key     []byte
	cache   []IndexEntry
	entries []IndexEntry
	err     error
	typ     byte
}
func (b *BlockIterator) PeekNext() []byte {
	if len(b.entries) > 1 {
		return b.key
	} else if b.n-b.i > 1 {
		key, _ := b.r.KeyAt(b.i + 1)
		return key
	}
	return nil
}
func (b *BlockIterator) Next() bool {
	if b.err != nil {
		return false
	}
	if b.n-b.i == 0 && len(b.entries) == 0 {
		return false
	}
	if len(b.entries) > 0 {
		b.entries = b.entries[1:]
		if len(b.entries) > 0 {
			return true
		}
	}
	if b.n-b.i > 0 {
		b.key, b.typ, b.entries = b.r.Key(b.i, &b.cache)
		b.i++
		if b.n != b.r.KeyCount() {
			b.err = fmt.Errorf("delete during iteration")
			return false
		}
		if len(b.entries) > 0 {
			return true
		}
	}
	return false
}
func (b *BlockIterator) Read() (key []byte, minTime int64, maxTime int64, typ byte, checksum uint32, buf []byte, err error) {
	if b.err != nil {
		return nil, 0, 0, 0, 0, nil, b.err
	}
	checksum, buf, err = b.r.ReadBytes(&b.entries[0], nil)
	if err != nil {
		return nil, 0, 0, 0, 0, nil, err
	}
	return b.key, b.entries[0].MinTime, b.entries[0].MaxTime, b.typ, checksum, buf, err
}
func (b *BlockIterator) Err() error {
	return b.err
}
type blockAccessor interface {
	init() (*indirectIndex, error)
	read(key []byte, timestamp int64) ([]Value, error)
	readAll(key []byte) ([]Value, error)
	readBlock(entry *IndexEntry, values []Value) ([]Value, error)
	readFloatBlock(entry *IndexEntry, values *[]FloatValue) ([]FloatValue, error)
	readIntegerBlock(entry *IndexEntry, values *[]IntegerValue) ([]IntegerValue, error)
	readUnsignedBlock(entry *IndexEntry, values *[]UnsignedValue) ([]UnsignedValue, error)
	readStringBlock(entry *IndexEntry, values *[]StringValue) ([]StringValue, error)
	readBooleanBlock(entry *IndexEntry, values *[]BooleanValue) ([]BooleanValue, error)
	readBytes(entry *IndexEntry, buf []byte) (uint32, []byte, error)
	rename(path string) error
	path() string
	close() error
	free() error
}
func NewTSMReader(f *os.File) (*TSMReader, error) {
	t := &TSMReader{}
	stat, err := f.Stat()
	if err != nil {
		return nil, err
	}
	t.size = stat.Size()
	t.lastModified = stat.ModTime().UnixNano()
	t.accessor = &mmapAccessor{
		f: f,
	}
	index, err := t.accessor.init()
	if err != nil {
		return nil, err
	}
	t.index = index
	t.tombstoner = &Tombstoner{Path: t.Path(), FilterFn: index.ContainsKey}
	if err := t.applyTombstones(); err != nil {
		return nil, err
	}
	return t, nil
}
func (t *TSMReader) applyTombstones() error {
	var cur, prev Tombstone
	batch := make([][]byte, 0, 4096)
	if err := t.tombstoner.Walk(func(ts Tombstone) error {
		cur = ts
		if len(batch) > 0 {
			if prev.Min != cur.Min || prev.Max != cur.Max {
				t.index.DeleteRange(batch, prev.Min, prev.Max)
				batch = batch[:0]
			}
		}
		n := len(batch)
		batch = batch[:n+1]
		if cap(batch[n]) < len(ts.Key) {
			batch[n] = make([]byte, len(ts.Key))
		} else {
			batch[n] = batch[n][:len(ts.Key)]
		}
		copy(batch[n], ts.Key)
		if len(batch) >= 4096 {
			t.index.DeleteRange(batch, prev.Min, prev.Max)
			batch = batch[:0]
		}
		prev = ts
		return nil
	}); err != nil {
		return fmt.Errorf("init: read tombstones: %v", err)
	}
	if len(batch) > 0 {
		t.index.DeleteRange(batch, cur.Min, cur.Max)
	}
	return nil
}
func (t *TSMReader) Free() error {
	t.mu.RLock()
	defer t.mu.RUnlock()
	return t.accessor.free()
}
func (t *TSMReader) Path() string {
	t.mu.RLock()
	p := t.accessor.path()
	t.mu.RUnlock()
	return p
}