func (i *Partition) MeasurementExists(name []byte) (bool, error) {
	fs, err := i.RetainFileSet()
	if err != nil {
		return false, err
	}
	defer fs.Release()
	m := fs.Measurement(name)
	return m != nil && !m.Deleted(), nil
}
MeasurementExists returns true if a measurement exists.
package tsi1
import (
	"encoding/json"
	"errors"
	"fmt"
	"io/ioutil"
	"os"
	"path/filepath"
	"regexp"
	"strconv"
	"strings"
	"sync"
	"time"
	"github.com/influxdata/influxdb/logger"
	"github.com/influxdata/influxdb/models"
	"github.com/influxdata/influxdb/pkg/bytesutil"
	"github.com/influxdata/influxdb/pkg/estimator"
	"github.com/influxdata/influxdb/tsdb"
	"github.com/influxdata/influxql"
	"go.uber.org/zap"
)
const Version = 1
const (
	LogFileExt   = ".tsl"
	IndexFileExt = ".tsi"
	CompactingExt = ".compacting"
)
const ManifestFileName = "MANIFEST"
type Partition struct {
	mu     sync.RWMutex
	opened bool
	sfile         *tsdb.SeriesFile  
	activeLogFile *LogFile          
	fileSet       *FileSet          
	seq           int               
	seriesIDSet *tsdb.SeriesIDSet
	levels          []CompactionLevel  
	levelCompacting []bool             
	once    sync.Once
	closing chan struct{}  
	wg      sync.WaitGroup
	fieldset *tsdb.MeasurementFieldSet
	Database string
	path string
	id   string  
	MaxLogFileSize int64
	compactionInterrupt chan struct{}
	compactionsDisabled int
	logger *zap.Logger
	manifestSize int64
	version int
}
func NewPartition(sfile *tsdb.SeriesFile, path string) *Partition {
	return &Partition{
		closing:     make(chan struct{}),
		path:        path,
		sfile:       sfile,
		seriesIDSet: tsdb.NewSeriesIDSet(),
		MaxLogFileSize: tsdb.DefaultMaxIndexLogFileSize,
		compactionInterrupt: make(chan struct{}),
		logger:  zap.NewNop(),
		version: Version,
	}
}
var ErrIncompatibleVersion = errors.New("incompatible tsi1 index MANIFEST")
func (i *Partition) Open() error {
	i.mu.Lock()
	defer i.mu.Unlock()
	i.closing = make(chan struct{})
	if i.opened {
		return errors.New("index partition already open")
	}
	i.id = filepath.Base(i.path)
	_, err := strconv.Atoi(i.id)
	if err != nil {
		return err
	}
	if err := os.MkdirAll(i.path, 0777); err != nil {
		return err
	}
	m, manifestSize, err := ReadManifestFile(filepath.Join(i.path, ManifestFileName))
	if os.IsNotExist(err) {
		m = NewManifest(i.ManifestPath())
	} else if err != nil {
		return err
	}
	i.manifestSize = manifestSize
	if err := m.Validate(); err != nil {
		return err
	}
	i.levels = make([]CompactionLevel, len(m.Levels))
	copy(i.levels, m.Levels)
	i.levelCompacting = make([]bool, len(i.levels))
	var files []File
	for _, filename := range m.Files {
		switch filepath.Ext(filename) {
		case LogFileExt:
			f, err := i.openLogFile(filepath.Join(i.path, filename))
			if err != nil {
				return err
			}
			files = append(files, f)
			sz, _ := f.Stat()
			if i.activeLogFile == nil && sz < i.MaxLogFileSize {
				i.activeLogFile = f
			}
		case IndexFileExt:
			f, err := i.openIndexFile(filepath.Join(i.path, filename))
			if err != nil {
				return err
			}
			files = append(files, f)
		}
	}
	fs, err := NewFileSet(i.Database, i.levels, i.sfile, files)
	if err != nil {
		return err
	}
	i.fileSet = fs
	i.seq = i.fileSet.MaxID()
	if err := i.deleteNonManifestFiles(m); err != nil {
		return err
	}
	if i.activeLogFile == nil {
		if err := i.prependActiveLogFile(); err != nil {
			return err
		}
	}
	if err := i.buildSeriesSet(); err != nil {
		return err
	}
	i.opened = true
	i.compact()
	return nil
}
func (i *Partition) openLogFile(path string) (*LogFile, error) {
	f := NewLogFile(i.sfile, path)
	if err := f.Open(); err != nil {
		return nil, err
	}
	return f, nil
}
func (i *Partition) openIndexFile(path string) (*IndexFile, error) {
	f := NewIndexFile(i.sfile)
	f.SetPath(path)
	if err := f.Open(); err != nil {
		return nil, err
	}
	return f, nil
}
func (i *Partition) deleteNonManifestFiles(m *Manifest) error {
	dir, err := os.Open(i.path)
	if err != nil {
		return err
	}
	defer dir.Close()
	fis, err := dir.Readdir(-1)
	if err != nil {
		return err
	}
	for _, fi := range fis {
		filename := filepath.Base(fi.Name())
		if filename == ManifestFileName || m.HasFile(filename) {
			continue
		}
		if err := os.RemoveAll(filename); err != nil {
			return err
		}
	}
	return nil
}
func (p *Partition) buildSeriesSet() error {
	fs := p.retainFileSet()
	defer fs.Release()
	p.seriesIDSet = tsdb.NewSeriesIDSet()
	for i := len(fs.files) - 1; i >= 0; i-- {
		f := fs.files[i]
		ts, err := f.TombstoneSeriesIDSet()
		if err != nil {
			return err
		}
		p.seriesIDSet.Diff(ts)
		ss, err := f.SeriesIDSet()
		if err != nil {
			return err
		}
		p.seriesIDSet.Merge(ss)
	}
	return nil
}
func (i *Partition) Wait() {
	i.wg.Wait()
}
func (i *Partition) Close() error {
	i.once.Do(func() {
		close(i.closing)
		close(i.compactionInterrupt)
	})
	i.wg.Wait()
	i.mu.Lock()
	defer i.mu.Unlock()
	for _, f := range i.fileSet.files {
		f.Close()
	}
	i.fileSet.files = nil
	return nil
}
func (p *Partition) isClosing() bool {
	select {
	case <-p.closing:
		return true
	default:
		return false
	}
}
func (i *Partition) Path() string { return i.path }
func (i *Partition) SeriesFile() *tsdb.SeriesFile { return i.sfile }
func (i *Partition) NextSequence() int {
	i.mu.Lock()
	defer i.mu.Unlock()
	return i.nextSequence()
}
func (i *Partition) nextSequence() int {
	i.seq++
	return i.seq
}
func (i *Partition) ManifestPath() string {
	return filepath.Join(i.path, ManifestFileName)
}
func (i *Partition) Manifest() *Manifest {
	m := &Manifest{
		Levels:  i.levels,
		Files:   make([]string, len(i.fileSet.files)),
		Version: i.version,
		path:    i.ManifestPath(),
	}
	for j, f := range i.fileSet.files {
		m.Files[j] = filepath.Base(f.Path())
	}
	return m
}
func (i *Partition) WithLogger(logger *zap.Logger) {
	i.logger = logger.With(zap.String("index", "tsi"))
}
func (i *Partition) SetFieldSet(fs *tsdb.MeasurementFieldSet) {
	i.mu.Lock()
	i.fieldset = fs
	i.mu.Unlock()
}
func (i *Partition) FieldSet() *tsdb.MeasurementFieldSet {
	i.mu.Lock()
	fs := i.fieldset
	i.mu.Unlock()
	return fs
}
func (i *Partition) RetainFileSet() (*FileSet, error) {
	select {
	case <-i.closing:
		return nil, errors.New("index is closing")
	default:
		i.mu.RLock()
		defer i.mu.RUnlock()
		return i.retainFileSet(), nil
	}
}
func (i *Partition) retainFileSet() *FileSet {
	fs := i.fileSet
	fs.Retain()
	return fs
}
func (i *Partition) FileN() int { return len(i.fileSet.files) }
func (i *Partition) prependActiveLogFile() error {
	f, err := i.openLogFile(filepath.Join(i.path, FormatLogFileName(i.nextSequence())))
	if err != nil {
		return err
	}
	i.activeLogFile = f
	i.fileSet = i.fileSet.PrependLogFile(f)
	manifestSize, err := i.Manifest().Write()
	if err != nil {
		return err
	}
	i.manifestSize = manifestSize
	return nil
}
func (i *Partition) ForEachMeasurementName(fn func(name []byte) error) error {
	fs, err := i.RetainFileSet()
	if err != nil {
		return err
	}
	defer fs.Release()
	itr := fs.MeasurementIterator()
	if itr == nil {
		return nil
	}
	for e := itr.Next(); e != nil; e = itr.Next() {
		if err := fn(e.Name()); err != nil {
			return err
		}
	}
	return nil
}
func (p *Partition) MeasurementHasSeries(name []byte) (bool, error) {
	fs, err := p.RetainFileSet()
	if err != nil {
		return false, err
	}
	defer fs.Release()
	for _, f := range fs.files {
		if f.MeasurementHasSeries(p.seriesIDSet, name) {
			return true, nil
		}
	}
	return false, nil
}
func (i *Partition) MeasurementIterator() (tsdb.MeasurementIterator, error) {
	fs, err := i.RetainFileSet()
	if err != nil {
		return nil, err
	}
	itr := fs.MeasurementIterator()
	if itr == nil {
		fs.Release()
		return nil, nil
	}
	return newFileSetMeasurementIterator(fs, NewTSDBMeasurementIteratorAdapter(itr)), nil
}