func (c *FSM) State() *Store {
	c.stateLock.RLock()
	defer c.stateLock.RUnlock()
	return c.state
}
State is used to return a handle to the current state
package fsm
import (
	"fmt"
	"io"
	"os"
	"strings"
	"sync"
	memdb "github.com/hashicorp/go-memdb"
	"github.com/hashicorp/raft"
	opentracing "github.com/opentracing/opentracing-go"
	"github.com/travisjeffery/jocko/jocko/structs"
	"github.com/travisjeffery/jocko/jocko/util"
	"github.com/travisjeffery/jocko/log"
	"github.com/ugorji/go/codec"
)
var (
	fsmVerboseLogs bool
)
type command func(buf []byte, index uint64) interface{}
type unboundCommand func(c *FSM, buf []byte, index uint64) interface{}
var commands map[structs.MessageType]unboundCommand
func registerCommand(msg structs.MessageType, fn unboundCommand) {
	if commands == nil {
		commands = make(map[structs.MessageType]unboundCommand)
	}
	if commands[msg] != nil {
		panic(fmt.Errorf("Message %d is already registered", msg))
	}
	commands[msg] = fn
}
type NodeID int32
type Tracer opentracing.Tracer
type FSM struct {
	apply     map[structs.MessageType]command
	stateLock sync.RWMutex
	state     *Store
	tracer    opentracing.Tracer
	nodeID    NodeID
}
func New(args ...interface{}) (*FSM, error) {
	var nodeID NodeID
	var tracer Tracer
	for _, arg := range args {
		switch a := arg.(type) {
		case NodeID:
			nodeID = a
		case Tracer:
			tracer = a
		}
	}
	store, err := NewStore(tracer, nodeID)
	if err != nil {
		return nil, err
	}
	fsm := &FSM{
		apply:  make(map[structs.MessageType]command),
		state:  store,
		tracer: tracer,
		nodeID: nodeID,
	}
	for msg, fn := range commands {
		thisFn := fn
		fsm.apply[msg] = func(buf []byte, index uint64) interface{} {
			return thisFn(fsm, buf, index)
		}
	}
	return fsm, nil
}