func (s *raftLog) LastIndex() (uint64, error) {
	it := s.db.NewIteratorCF(rocksdb.NewDefaultReadOptions(), s.cfHandles[logTable])
	defer it.Close()
	it.SeekToLast()
	if it.Valid() {
		slice := it.Key()
		defer slice.Free()
		key := make([]byte, slice.Size())
		copy(key, slice.Data())
		return util.BytesAsUint64(key), nil
	}
	return 0, nil
}
LastIndex returns the last known index from the Raft log.
package consensus
import (
	"errors"
	"github.com/bbva/qed/metrics"
	"github.com/bbva/qed/rocksdb"
	"github.com/bbva/qed/util"
	"github.com/hashicorp/go-msgpack/codec"
	"github.com/hashicorp/raft"
)
var (
	ErrKeyNotFound = errors.New("not found")
)
type table uint32
const (
	defaultTable table = iota
	stableTable
	logTable
)
func (t table) String() string {
	var s string
	switch t {
	case defaultTable:
		s = "default"
	case stableTable:
		s = "stable"
	case logTable:
		s = "log"
	}
	return s
}
type raftLog struct {
	db *rocksdb.DB
	codec *codec.MsgpackHandle
	stats *rocksdb.Statistics
	path string
	ro   *rocksdb.ReadOptions
	wo   *rocksdb.WriteOptions
	cfHandles rocksdb.ColumnFamilyHandles
	globalOpts *rocksdb.Options
	stableBbto *rocksdb.BlockBasedTableOptions
	stableOpts *rocksdb.Options
	logBbto *rocksdb.BlockBasedTableOptions
	logOpts *rocksdb.Options
	blockCache *rocksdb.Cache
	metrics *raftLogMetrics
}
type raftLogOptions struct {
	Path string
	NoSync bool
	EnableStatistics bool
}
func newRaftLog(path string) (*raftLog, error) {
	return newRaftLogOpts(raftLogOptions{
		Path:             path,
		NoSync:           true,
		EnableStatistics: true,
	})
}
func newRaftLogOpts(options raftLogOptions) (*raftLog, error) {
	cfNames := []string{defaultTable.String(), stableTable.String(), logTable.String()}
	defaultOpts := rocksdb.NewDefaultOptions()
	globalOpts := rocksdb.NewDefaultOptions()
	globalOpts.SetCreateIfMissing(true)
	globalOpts.SetCreateIfMissingColumnFamilies(true)
	blockCache := rocksdb.NewDefaultLRUCache(512 * 1024 * 1024)
	var stats *rocksdb.Statistics
	if options.EnableStatistics {
		stats = rocksdb.NewStatistics()
		globalOpts.SetStatistics(stats)
	}
	stableBbto := rocksdb.NewDefaultBlockBasedTableOptions()
	stableOpts := rocksdb.NewDefaultOptions()
	stableOpts.SetBlockBasedTableFactory(stableBbto)
	logBbto := rocksdb.NewDefaultBlockBasedTableOptions()
	logBbto.SetBlockSize(32 * 1024)
	logBbto.SetCacheIndexAndFilterBlocks(true)
	logBbto.SetBlockCache(blockCache)
	logOpts := rocksdb.NewDefaultOptions()
	logOpts.SetUseFsync(!options.NoSync)
	logOpts.SetCompression(rocksdb.NoCompression)
	logOpts.SetMaxSubCompactions(2)  
	logOpts.SetEnablePipelinedWrite(true)
	logOpts.SetWriteBufferSize(256 * 1024 * 1024)
	logOpts.SetMinWriteBufferNumberToMerge(2)
	logOpts.SetLevel0FileNumCompactionTrigger(8)
	logOpts.SetLevel0SlowdownWritesTrigger(17)
	logOpts.SetLevel0StopWritesTrigger(24)
	logOpts.SetMaxWriteBufferNumber(5)
	logOpts.SetNumLevels(7)
	logOpts.SetMaxBytesForLevelBase(4 * 1024 * 1024 * 1024)
	logOpts.SetMaxBytesForLevelMultiplier(2)
	logOpts.SetTargetFileSizeBase(256 * 1024 * 1024)
	logOpts.SetTargetFileSizeMultiplier(1)
	logOpts.SetMaxBackgroundCompactions(2)
	logOpts.SetMaxBackgroundFlushes(2)
	cfOpts := []*rocksdb.Options{defaultOpts, stableOpts, logOpts}
	db, cfHandles, err := rocksdb.OpenDBColumnFamilies(options.Path, globalOpts, cfNames, cfOpts)
	if err != nil {
		return nil, err
	}
	wo := rocksdb.NewDefaultWriteOptions()
	wo.SetSync(!options.NoSync)
	ro := rocksdb.NewDefaultReadOptions()
	ro.SetFillCache(false)
	store := &raftLog{
		db:         db,
		codec:      &codec.MsgpackHandle{},
		stats:      stats,
		path:       options.Path,
		cfHandles:  cfHandles,
		stableBbto: stableBbto,
		stableOpts: stableOpts,
		logBbto:    logBbto,
		logOpts:    logOpts,
		blockCache: blockCache,
		globalOpts: globalOpts,
		ro:         ro,
		wo:         wo,
	}
	if stats != nil {
		store.metrics = newRaftLogMetrics(store)
	}
	return store, nil
}
func (s *raftLog) Close() error {
	for _, cf := range s.cfHandles {
		cf.Destroy()
	}
	if s.db != nil {
		s.db.Close()
	}
	if s.stableBbto != nil {
		s.stableBbto.Destroy()
	}
	if s.stableOpts != nil {
		s.stableOpts.Destroy()
	}
	if s.blockCache != nil {
		s.blockCache.Destroy()
	}
	if s.logBbto != nil {
		s.logBbto.Destroy()
	}
	if s.logOpts != nil {
		s.logOpts.Destroy()
	}
	if s.stats != nil {
		s.stats.Destroy()
	}
	if s.wo != nil {
		s.wo.Destroy()
	}
	if s.ro != nil {
		s.ro.Destroy()
	}
	s.db = nil
	return nil
}
func (s *raftLog) FirstIndex() (uint64, error) {
	it := s.db.NewIteratorCF(rocksdb.NewDefaultReadOptions(), s.cfHandles[logTable])
	defer it.Close()
	it.SeekToFirst()
	if it.Valid() {
		slice := it.Key()
		defer slice.Free()
		key := make([]byte, slice.Size())
		copy(key, slice.Data())
		return util.BytesAsUint64(key), nil
	}
	return 0, nil
}