func ReadSeriesKeyFromSegments(a []*SeriesSegment, offset int64) []byte {
	segmentID, pos := SplitSeriesOffset(offset)
	segment := FindSegment(a, segmentID)
	if segment == nil {
		return nil
	}
	buf := segment.Slice(pos)
	key, _ := ReadSeriesKey(buf)
	return key
}
ReadSeriesKeyFromSegments returns a series key from an offset within a set of segments.
package tsdb
import (
	"bufio"
	"bytes"
	"encoding/binary"
	"errors"
	"fmt"
	"io"
	"os"
	"regexp"
	"strconv"
	"github.com/influxdata/influxdb/pkg/mmap"
)
const (
	SeriesSegmentVersion = 1
	SeriesSegmentMagic   = "SSEG"
	SeriesSegmentHeaderSize = 4 + 1  
)
const (
	SeriesEntryFlagSize   = 1
	SeriesEntryHeaderSize = 1 + 8  
	SeriesEntryInsertFlag    = 0x01
	SeriesEntryTombstoneFlag = 0x02
)
var (
	ErrInvalidSeriesSegment        = errors.New("invalid series segment")
	ErrInvalidSeriesSegmentVersion = errors.New("invalid series segment version")
	ErrSeriesSegmentNotWritable    = errors.New("series segment not writable")
)
type SeriesSegment struct {
	id   uint16
	path string
	data []byte         
	file *os.File       
	w    *bufio.Writer  
	size uint32         
}
func NewSeriesSegment(id uint16, path string) *SeriesSegment {
	return &SeriesSegment{
		id:   id,
		path: path,
	}
}
func CreateSeriesSegment(id uint16, path string) (*SeriesSegment, error) {
	f, err := os.Create(path + ".initializing")
	if err != nil {
		return nil, err
	}
	defer f.Close()
	hdr := NewSeriesSegmentHeader()
	if _, err := hdr.WriteTo(f); err != nil {
		return nil, err
	} else if err := f.Truncate(int64(SeriesSegmentSize(id))); err != nil {
		return nil, err
	} else if err := f.Close(); err != nil {
		return nil, err
	}
	if err := os.Rename(f.Name(), path); err != nil {
		return nil, err
	}
	segment := NewSeriesSegment(id, path)
	if err := segment.Open(); err != nil {
		return nil, err
	}
	return segment, nil
}
func (s *SeriesSegment) Open() error {
	if err := func() (err error) {
		if s.data, err = mmap.Map(s.path, int64(SeriesSegmentSize(s.id))); err != nil {
			return err
		}
		hdr, err := ReadSeriesSegmentHeader(s.data)
		if err != nil {
			return err
		} else if hdr.Version != SeriesSegmentVersion {
			return ErrInvalidSeriesSegmentVersion
		}
		return nil
	}(); err != nil {
		s.Close()
		return err
	}
	return nil
}
func (s *SeriesSegment) InitForWrite() (err error) {
	for s.size = uint32(SeriesSegmentHeaderSize); s.size < uint32(len(s.data)); {
		flag, _, _, sz := ReadSeriesEntry(s.data[s.size:])
		if flag == 0 {
			break
		}
		s.size += uint32(sz)
	}
	if s.file, err = os.OpenFile(s.path, os.O_WRONLY|os.O_CREATE, 0666); err != nil {
		return err
	} else if _, err := s.file.Seek(int64(s.size), io.SeekStart); err != nil {
		return err
	}
	s.w = bufio.NewWriterSize(s.file, 32*1024)
	return nil
}
func (s *SeriesSegment) Close() (err error) {
	if e := s.CloseForWrite(); e != nil && err == nil {
		err = e
	}
	if s.data != nil {
		if e := mmap.Unmap(s.data); e != nil && err == nil {
			err = e
		}
		s.data = nil
	}
	return err
}
func (s *SeriesSegment) CloseForWrite() (err error) {
	if s.w != nil {
		if e := s.w.Flush(); e != nil && err == nil {
			err = e
		}
		s.w = nil
	}
	if s.file != nil {
		if e := s.file.Close(); e != nil && err == nil {
			err = e
		}
		s.file = nil
	}
	return err
}
func (s *SeriesSegment) ID() uint16 { return s.id }
func (s *SeriesSegment) Size() int64 { return int64(s.size) }
func (s *SeriesSegment) Slice(pos uint32) []byte { return s.data[pos:] }
func (s *SeriesSegment) WriteLogEntry(data []byte) (offset int64, err error) {
	if !s.CanWrite(data) {
		return 0, ErrSeriesSegmentNotWritable
	}
	offset = JoinSeriesOffset(s.id, s.size)
	if _, err := s.w.Write(data); err != nil {
		return 0, err
	}
	s.size += uint32(len(data))
	return offset, nil
}
func (s *SeriesSegment) CanWrite(data []byte) bool {
	return s.w != nil && s.size+uint32(len(data)) <= SeriesSegmentSize(s.id)
}
func (s *SeriesSegment) Flush() error {
	if s.w == nil {
		return nil
	}
	return s.w.Flush()
}
func (s *SeriesSegment) AppendSeriesIDs(a []uint64) []uint64 {
	s.ForEachEntry(func(flag uint8, id uint64, _ int64, _ []byte) error {
		if flag == SeriesEntryInsertFlag {
			a = append(a, id)
		}
		return nil
	})
	return a
}
func (s *SeriesSegment) MaxSeriesID() uint64 {
	var max uint64
	s.ForEachEntry(func(flag uint8, id uint64, _ int64, _ []byte) error {
		if flag == SeriesEntryInsertFlag && id > max {
			max = id
		}
		return nil
	})
	return max
}
func (s *SeriesSegment) ForEachEntry(fn func(flag uint8, id uint64, offset int64, key []byte) error) error {
	for pos := uint32(SeriesSegmentHeaderSize); pos < uint32(len(s.data)); {
		flag, id, key, sz := ReadSeriesEntry(s.data[pos:])
		if flag == 0 {
			break
		}
		offset := JoinSeriesOffset(s.id, pos)
		if err := fn(flag, id, offset, key); err != nil {
			return err
		}
		pos += uint32(sz)
	}
	return nil
}
func (s *SeriesSegment) Clone() *SeriesSegment {
	return &SeriesSegment{
		id:   s.id,
		path: s.path,
		data: s.data,
		size: s.size,
	}
}
func CloneSeriesSegments(a []*SeriesSegment) []*SeriesSegment {
	other := make([]*SeriesSegment, len(a))
	for i := range a {
		other[i] = a[i].Clone()
	}
	return other
}
func FindSegment(a []*SeriesSegment, id uint16) *SeriesSegment {
	for _, segment := range a {
		if segment.id == id {
			return segment
		}
	}
	return nil
}