func (s *MetaStore) GetGtidSet(flavor string, key string) (gomysql.GTIDSet, error) {
	flavorKey := path.Join(flavor, key)
	value, err := s.Get(utils.StringToBytes(flavorKey))
	if err != nil {
		return nil, err
	}
	if value == nil {
		gitSet := new(gomysql.MysqlGTIDSet)
		gitSet.Sets = make(map[string]*gomysql.UUIDSet)
		return gitSet, nil
	}
	gtids, err := gomysql.DecodeMysqlGTIDSet(value)
	if err != nil {
		return nil, err
	}
	return gtids, nil
}
GetGtidSet get gtid set
package storage
import (
	"encoding/binary"
	"path"
	"encoding/json"
	"bytes"
	"strings"
	"strconv"
	"fmt"
	bolt "github.com/coreos/bbolt"
	pb "github.com/coreos/etcd/raft/raftpb"
	"github.com/flike/kingbus/log"
	"github.com/flike/kingbus/utils"
	gomysql "github.com/siddontang/go-mysql/mysql"
)
const (
	MetadataFile = "kingbus_meta.db"
	BucketName = "kingbus_meta_bucket"
)
type MetaStore struct {
	DB         *bolt.DB
	Dir        string
	BucketName []byte
}
func NewMetaStore(dir string) (*MetaStore, error) {
	if len(dir) == 0 {
		return nil, ErrArgsIllegal
	}
	dbFilePath := path.Join(dir, MetadataFile)
	db, err := bolt.Open(dbFilePath, 0600, nil)
	if err != nil {
		log.Log.Errorf("[stable_bolt.go-NewBoltDBStore]:bolt Open error,err:%s,dbpath:%s", err.Error(), dbFilePath)
		return nil, err
	}
	s := &MetaStore{
		Dir:        dir,
		DB:         db,
		BucketName: []byte(BucketName),
	}
	err = s.init()
	if err != nil {
		s.Close2()
		return nil, err
	}
	return s, nil
}
func (s *MetaStore) init() error {
	return s.DB.Update(func(tx *bolt.Tx) error {
		_, err := tx.CreateBucketIfNotExists(s.BucketName)
		if err != nil {
			log.Log.Errorf("CreateBucketIfNotExists error:error=%s,BucketName=%s",
				err.Error(), string(s.BucketName))
			return err
		}
		log.Log.Debugf("create bucket:%s success", BucketName)
		return nil
	})
}
func (s *MetaStore) Get(key []byte) ([]byte, error) {
	if len(key) == 0 {
		return nil, ErrKeyIsNil
	}
	var data []byte
	err := s.DB.View(func(tx *bolt.Tx) error {
		bucket := tx.Bucket(s.BucketName)
		val := bucket.Get(key)
		if val != nil {
			data = make([]byte, len(val))
			copy(data, val)
		}
		return nil
	})
	if err != nil {
		return nil, err
	}
	return data, nil
}
func (s *MetaStore) Set(key []byte, value []byte) error {
	return s.DB.Update(func(tx *bolt.Tx) error {
		b := tx.Bucket(s.BucketName)
		err := b.Put(key, value)
		if err != nil {
			log.Log.Errorf("MetaStore Set error,err:%s,key:%s", err.Error(), string(key))
			return err
		}
		return nil
	})
}
func (s *MetaStore) Delete(key []byte) error {
	return s.DB.Update(func(tx *bolt.Tx) error {
		b := tx.Bucket(s.BucketName)
		err := b.Delete(key)
		if err != nil {
			log.Log.Errorf("MetaStore Delete error,err:%s,key:%s", err.Error(), string(key))
			return err
		}
		return nil
	})
}
func (s *MetaStore) InitialState() (pb.HardState, pb.ConfState, error) {
	var hs pb.HardState
	var cs pb.ConfState
	hsValue, err := s.Get(utils.StringToBytes(HardStateKey))
	if err != nil {
		return pb.HardState{}, pb.ConfState{}, err
	}
	if hsValue != nil {
		err = json.Unmarshal(hsValue, &hs)
		if err != nil {
			log.Log.Errorf("MetaStore:initialState json Unmarshal error,err:%s,hsKey:%s,hsValue:%s",
				err.Error(), HardStateKey, utils.BytesToString(hsValue))
			return pb.HardState{}, pb.ConfState{}, err
		}
	}
	csValue, err := s.Get(utils.StringToBytes(ConfStateKey))
	if err != nil {
		return pb.HardState{}, pb.ConfState{}, err
	}
	if csValue != nil {
		err = json.Unmarshal(csValue, &cs)
		if err != nil {
			log.Log.Errorf("MetaStore:initialState json Unmarshal error,err:%s,csKey:%s,csValue:%s",
				err.Error(), ConfStateKey, utils.BytesToString(csValue))
			return pb.HardState{}, pb.ConfState{}, err
		}
	}
	return hs, cs, nil
}
func (s *MetaStore) SaveHardState(st pb.HardState) error {
	value, err := json.Marshal(st)
	if err != nil {
		log.Log.Errorf("MetaStore:saveHardState error,err:%s,HardState:%v", err.Error(), st)
		return err
	}
	err = s.Set(utils.StringToBytes(HardStateKey), value)
	if err != nil {
		log.Log.Errorf("MetaStore:saveHardState error,err:%s,key:%s,value:%s",
			err.Error(), HardStateKey, utils.BytesToString(value))
		return err
	}
	return nil
}
func (s *MetaStore) SetGtidSet(flavor string, key string, gtidSet gomysql.GTIDSet) error {
	flavorKey := path.Join(flavor, key)
	value := gtidSet.Encode()
	err := s.Set(utils.StringToBytes(flavorKey), value)
	if err != nil {
		log.Log.Errorf("MetaStore:SetGtidSet error,err:%s,key:%s,value:%s",
			err, key, gtidSet.String())
		return err
	}
	return nil
}
func (s *MetaStore) SetBinlogProgress(appliedIndex uint64, executedGtidSet gomysql.GTIDSet) error {
	gtidsKey := utils.StringToBytes(path.Join(gomysql.MySQLFlavor, ExecutedGtidSetKey))
	gtidsValue := executedGtidSet.Encode()
	appliedIndexKey := utils.StringToBytes(AppliedIndexKey)
	appliedIndexValue := make([]byte, 8)
	binary.BigEndian.PutUint64(appliedIndexValue, appliedIndex)
	return s.DB.Update(func(tx *bolt.Tx) error {
		b := tx.Bucket(s.BucketName)
		err := b.Put(gtidsKey, gtidsValue)
		if err != nil {
			log.Log.Errorf("MetaStore SetBinlogProgress error,err:%s,key:%s", err.Error(), string(gtidsKey))
			return err
		}
		err = b.Put(appliedIndexKey, appliedIndexValue)
		if err != nil {
			log.Log.Errorf("MetaStore SetBinlogProgress error,err:%s,key:%s", err.Error(), string(appliedIndexKey))
			return err
		}
		return nil
	})
}