// NewFSMPath is used to construct a new FSM with a blank state func NewFSM(gc *state.TombstoneGC, logOutput io.Writer) (*consulFSM, error) { stateNew, err := state.NewStateStore(gc) if err != nil { return nil, err } fsm := &consulFSM{ logOutput: logOutput, logger: log.New(logOutput, "", log.LstdFlags), state: stateNew, gc: gc, } return fsm, nil }
func (c *consulFSM) Restore(old io.ReadCloser) error { defer old.Close() // Create a new state store stateNew, err := state.NewStateStore(c.gc) if err != nil { return err } c.state = stateNew // Set up a new restore transaction restore := c.state.Restore() defer restore.Abort() // Create a decoder dec := codec.NewDecoder(old, msgpackHandle) // Read in the header var header snapshotHeader if err := dec.Decode(&header); err != nil { return err } // Populate the new state msgType := make([]byte, 1) for { // Read the message type _, err := old.Read(msgType) if err == io.EOF { break } else if err != nil { return err } // Decode switch structs.MessageType(msgType[0]) { case structs.RegisterRequestType: var req structs.RegisterRequest if err := dec.Decode(&req); err != nil { return err } if err := restore.Registration(header.LastIndex, &req); err != nil { return err } case structs.KVSRequestType: var req structs.DirEntry if err := dec.Decode(&req); err != nil { return err } if err := restore.KVS(&req); err != nil { return err } case structs.TombstoneRequestType: var req structs.DirEntry if err := dec.Decode(&req); err != nil { return err } // For historical reasons, these are serialized in the // snapshots as KV entries. We want to keep the snapshot // format compatible with pre-0.6 versions for now. stone := &state.Tombstone{ Key: req.Key, Index: req.ModifyIndex, } if err := restore.Tombstone(stone); err != nil { return err } case structs.SessionRequestType: var req structs.Session if err := dec.Decode(&req); err != nil { return err } if err := restore.Session(&req); err != nil { return err } case structs.ACLRequestType: var req structs.ACL if err := dec.Decode(&req); err != nil { return err } if err := restore.ACL(&req); err != nil { return err } case structs.CoordinateBatchUpdateType: var req structs.Coordinates if err := dec.Decode(&req); err != nil { return err } if err := restore.Coordinates(header.LastIndex, req); err != nil { return err } case structs.PreparedQueryRequestType: var req structs.PreparedQuery if err := dec.Decode(&req); err != nil { return err } if err := restore.PreparedQuery(&req); err != nil { return err } default: return fmt.Errorf("Unrecognized msg type: %v", msgType) } } restore.Commit() return nil }