func (f *IndexFile) TagKey(name, key []byte) TagKeyElem {
	tblk := f.tblks[string(name)]
	if tblk == nil {
		return nil
	}
	return tblk.TagKeyElem(key)
}
TagKey returns a tag key.
package tsi1
import (
	"bytes"
	"encoding/binary"
	"errors"
	"fmt"
	"io"
	"sync"
	"github.com/influxdata/influxdb/models"
	"github.com/influxdata/influxdb/pkg/estimator"
	"github.com/influxdata/influxdb/pkg/estimator/hll"
	"github.com/influxdata/influxdb/pkg/mmap"
	"github.com/influxdata/influxdb/tsdb"
)
const IndexFileVersion = 1
const FileSignature = "TSI1"
const (
	IndexFileVersionSize = 2
	IndexFileTrailerSize = IndexFileVersionSize +
		8 + 8 +  
		8 + 8 +  
		8 + 8 +  
		8 + 8 +  
		8 + 8 +  
		0
)
var (
	ErrInvalidIndexFile            = errors.New("invalid index file")
	ErrUnsupportedIndexFileVersion = errors.New("unsupported index file version")
)
type IndexFile struct {
	wg   sync.WaitGroup  
	data []byte
	sfile *tsdb.SeriesFile
	tblks map[string]*TagBlock  
	mblk  MeasurementBlock
	seriesIDSetData          []byte
	tombstoneSeriesIDSetData []byte
	sketch, tSketch estimator.Sketch
	level int
	id    int
	mu         sync.RWMutex
	compacting bool
	path string
}
func NewIndexFile(sfile *tsdb.SeriesFile) *IndexFile {
	return &IndexFile{
		sfile:   sfile,
		sketch:  hll.NewDefaultPlus(),
		tSketch: hll.NewDefaultPlus(),
	}
}
func (f *IndexFile) Open() error {
	defer func() {
		if err := recover(); err != nil {
			err = fmt.Errorf("[Index file: %s] %v", f.path, err)
			panic(err)
		}
	}()
	f.id, f.level = ParseFilename(f.Path())
	data, err := mmap.Map(f.Path(), 0)
	if err != nil {
		return err
	}
	return f.UnmarshalBinary(data)
}
func (f *IndexFile) Close() error {
	f.wg.Wait()
	f.sfile = nil
	f.tblks = nil
	f.mblk = MeasurementBlock{}
	return mmap.Unmap(f.data)
}
func (f *IndexFile) ID() int { return f.id }
func (f *IndexFile) Path() string { return f.path }
func (f *IndexFile) SetPath(path string) { f.path = path }
func (f *IndexFile) Level() int { return f.level }
func (f *IndexFile) Retain() { f.wg.Add(1) }
func (f *IndexFile) Release() { f.wg.Done() }
func (f *IndexFile) Size() int64 { return int64(len(f.data)) }
func (f *IndexFile) Compacting() bool {
	f.mu.RLock()
	v := f.compacting
	f.mu.RUnlock()
	return v
}
func (f *IndexFile) UnmarshalBinary(data []byte) error {
	if len(data) < len(FileSignature) {
		return io.ErrShortBuffer
	} else if !bytes.Equal(data[:len(FileSignature)], []byte(FileSignature)) {
		return ErrInvalidIndexFile
	}
	t, err := ReadIndexFileTrailer(data)
	if err != nil {
		return err
	}
	buf := data[t.SeriesSketch.Offset : t.SeriesSketch.Offset+t.SeriesSketch.Size]
	if err := f.sketch.UnmarshalBinary(buf); err != nil {
		return err
	}
	buf = data[t.TombstoneSeriesSketch.Offset : t.TombstoneSeriesSketch.Offset+t.TombstoneSeriesSketch.Size]
	if err := f.tSketch.UnmarshalBinary(buf); err != nil {
		return err
	}
	f.seriesIDSetData = data[t.SeriesIDSet.Offset : t.SeriesIDSet.Offset+t.SeriesIDSet.Size]
	f.tombstoneSeriesIDSetData = data[t.TombstoneSeriesIDSet.Offset : t.TombstoneSeriesIDSet.Offset+t.TombstoneSeriesIDSet.Size]
	buf = data[t.MeasurementBlock.Offset:]
	buf = buf[:t.MeasurementBlock.Size]
	if err := f.mblk.UnmarshalBinary(buf); err != nil {
		return err
	}
	f.tblks = make(map[string]*TagBlock)
	itr := f.mblk.Iterator()
	for m := itr.Next(); m != nil; m = itr.Next() {
		e := m.(*MeasurementBlockElem)
		buf := data[e.tagBlock.offset:]
		buf = buf[:e.tagBlock.size]
		var tblk TagBlock
		if err := tblk.UnmarshalBinary(buf); err != nil {
			return err
		}
		f.tblks[string(e.name)] = &tblk
	}
	f.data = data
	return nil
}
func (f *IndexFile) SeriesIDSet() (*tsdb.SeriesIDSet, error) {
	ss := tsdb.NewSeriesIDSet()
	if err := ss.UnmarshalBinary(f.seriesIDSetData); err != nil {
		return nil, err
	}
	return ss, nil
}
func (f *IndexFile) TombstoneSeriesIDSet() (*tsdb.SeriesIDSet, error) {
	ss := tsdb.NewSeriesIDSet()
	if err := ss.UnmarshalBinary(f.tombstoneSeriesIDSetData); err != nil {
		return nil, err
	}
	return ss, nil
}
func (f *IndexFile) Measurement(name []byte) MeasurementElem {
	e, ok := f.mblk.Elem(name)
	if !ok {
		return nil
	}
	return &e
}
func (f *IndexFile) MeasurementN() (n uint64) {
	mitr := f.mblk.Iterator()
	for me := mitr.Next(); me != nil; me = mitr.Next() {
		n++
	}
	return n
}
func (f *IndexFile) MeasurementHasSeries(ss *tsdb.SeriesIDSet, name []byte) (ok bool) {
	e, ok := f.mblk.Elem(name)
	if !ok {
		return false
	}
	var exists bool
	e.ForEachSeriesID(func(id uint64) error {
		if ss.Contains(id) {
			exists = true
			return errors.New("done")
		}
		return nil
	})
	return exists
}
func (f *IndexFile) TagValueIterator(name, key []byte) TagValueIterator {
	tblk := f.tblks[string(name)]
	if tblk == nil {
		return nil
	}
	ke := tblk.TagKeyElem(key)
	if ke == nil {
		return nil
	}
	return ke.TagValueIterator()
}
func (f *IndexFile) TagKeySeriesIDIterator(name, key []byte) tsdb.SeriesIDIterator {
	tblk := f.tblks[string(name)]
	if tblk == nil {
		return nil
	}
	ke := tblk.TagKeyElem(key)
	if ke == nil {
		return nil
	}
	vitr := ke.TagValueIterator()
	var itrs []tsdb.SeriesIDIterator
	for ve := vitr.Next(); ve != nil; ve = vitr.Next() {
		sitr := &rawSeriesIDIterator{data: ve.(*TagBlockValueElem).series.data}
		itrs = append(itrs, sitr)
	}
	return tsdb.MergeSeriesIDIterators(itrs...)
}
func (f *IndexFile) TagValueSeriesIDIterator(name, key, value []byte) tsdb.SeriesIDIterator {
	tblk := f.tblks[string(name)]
	if tblk == nil {
		return nil
	}
	n, data := tblk.TagValueSeriesData(key, value)
	if n == 0 {
		return nil
	}
	return &rawSeriesIDIterator{n: n, data: data}
}