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
}
Close closes the index.
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()
}