mirror of
https://github.com/wavetermdev/waveterm.git
synced 2024-12-21 16:38:23 +01:00
update statediff algorithm for wavesrv / remote instances (#530)
* remote statemap from waveshell server (diff against initial state) * move ShellStatePtr from sstore to packet so it can be passed over the wire * add finalstatebaseptr to cmddone * much improved diff computation code on wavesrv side * fix displayname -- now using hash * add comments, change a couple msh.WriteToPtyBuffer calls to log.Printfs
This commit is contained in:
parent
5c85b2b786
commit
a1e4e807cc
@ -743,13 +743,14 @@ func MakeCmdFinalPacket(ck base.CommandKey) *CmdFinalPacketType {
|
||||
}
|
||||
|
||||
type CmdDonePacketType struct {
|
||||
Type string `json:"type"`
|
||||
Ts int64 `json:"ts"`
|
||||
CK base.CommandKey `json:"ck"`
|
||||
ExitCode int `json:"exitcode"`
|
||||
DurationMs int64 `json:"durationms"`
|
||||
FinalState *ShellState `json:"finalstate,omitempty"`
|
||||
FinalStateDiff *ShellStateDiff `json:"finalstatediff,omitempty"`
|
||||
Type string `json:"type"`
|
||||
Ts int64 `json:"ts"`
|
||||
CK base.CommandKey `json:"ck"`
|
||||
ExitCode int `json:"exitcode"`
|
||||
DurationMs int64 `json:"durationms"`
|
||||
FinalState *ShellState `json:"finalstate,omitempty"`
|
||||
FinalStateDiff *ShellStateDiff `json:"finalstatediff,omitempty"`
|
||||
FinalStateBasePtr *ShellStatePtr `json:"finalstatebaseptr,omitempty"`
|
||||
}
|
||||
|
||||
func (*CmdDonePacketType) GetType() string {
|
||||
@ -814,10 +815,10 @@ type RunPacketType struct {
|
||||
Type string `json:"type"`
|
||||
ReqId string `json:"reqid"`
|
||||
CK base.CommandKey `json:"ck"`
|
||||
ShellType string `json:"shelltype"` // new in v0.6.0 (either "bash" or "zsh") (set by remote.go)
|
||||
ShellType string `json:"shelltype"` // added in Wave v0.6.0 (either "bash" or "zsh") (set by remote.go)
|
||||
Command string `json:"command"`
|
||||
State *ShellState `json:"state,omitempty"`
|
||||
StateDiff *ShellStateDiff `json:"statediff,omitempty"`
|
||||
StatePtr *ShellStatePtr `json:"stateptr,omitempty"` // added in Wave v0.7.2
|
||||
StateComplete bool `json:"statecomplete,omitempty"` // set to true if state is complete (the default env should not be set)
|
||||
UsePty bool `json:"usepty,omitempty"`
|
||||
TermOpts *TermOpts `json:"termopts,omitempty"`
|
||||
|
@ -40,6 +40,18 @@ type ShellState struct {
|
||||
HashVal string `json:"-"`
|
||||
}
|
||||
|
||||
type ShellStatePtr struct {
|
||||
BaseHash string `json:"basehash"`
|
||||
DiffHashArr []string `json:"diffhasharr,omitempty"`
|
||||
}
|
||||
|
||||
func (ssptr *ShellStatePtr) IsEmpty() bool {
|
||||
if ssptr == nil || ssptr.BaseHash == "" {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (state ShellState) ApproximateSize() int64 {
|
||||
return int64(len(state.Version) + len(state.Cwd) + len(state.ShellVars) + len(state.Aliases) + len(state.Funcs) + len(state.Error))
|
||||
}
|
||||
|
@ -50,7 +50,6 @@ type MServer struct {
|
||||
Sender *packet.PacketSender
|
||||
ClientMap map[base.CommandKey]*shexec.ClientProc
|
||||
Debug bool
|
||||
StateMap *ShellStateMap
|
||||
WriteErrorCh chan bool // closed if there is a I/O write error
|
||||
WriteErrorChOnce *sync.Once
|
||||
Done bool
|
||||
@ -338,11 +337,6 @@ func (m *MServer) reinit(reqId string, shellType string) {
|
||||
m.Sender.SendErrorResponse(reqId, fmt.Errorf("error initializing shell: %w", err))
|
||||
return
|
||||
}
|
||||
err = m.StateMap.SetCurrentState(ssPk.State.GetShellType(), ssPk.State)
|
||||
if err != nil {
|
||||
m.Sender.SendErrorResponse(reqId, fmt.Errorf("error setting current state: %w", err))
|
||||
return
|
||||
}
|
||||
ssPk.RespId = reqId
|
||||
m.Sender.SendPacket(ssPk)
|
||||
}
|
||||
@ -710,7 +704,7 @@ func (m *MServer) ProcessRpcPacket(pk packet.RpcPacketType) {
|
||||
m.Sender.SendErrorResponse(reqId, fmt.Errorf("invalid rpc type '%s'", pk.GetType()))
|
||||
}
|
||||
|
||||
func (m *MServer) clientPacketCallback(shellType string, pk packet.PacketType) {
|
||||
func (m *MServer) clientPacketCallback(shellType string, pk packet.PacketType, runPk *packet.RunPacketType) {
|
||||
if pk.GetType() != packet.CmdDonePacketStr {
|
||||
return
|
||||
}
|
||||
@ -718,25 +712,22 @@ func (m *MServer) clientPacketCallback(shellType string, pk packet.PacketType) {
|
||||
if donePk.FinalState == nil {
|
||||
return
|
||||
}
|
||||
stateHash, curState := m.StateMap.GetCurrentState(shellType)
|
||||
if curState == nil {
|
||||
initialState := runPk.State
|
||||
if initialState == nil {
|
||||
return
|
||||
}
|
||||
sapi, err := shellapi.MakeShellApi(curState.GetShellType())
|
||||
initialStateHash := initialState.GetHashVal(false)
|
||||
sapi, err := shellapi.MakeShellApi(initialState.GetShellType())
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
diff, err := sapi.MakeShellStateDiff(curState, stateHash, donePk.FinalState)
|
||||
diff, err := sapi.MakeShellStateDiff(initialState, initialStateHash, donePk.FinalState)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
donePk.FinalState = nil
|
||||
donePk.FinalStateDiff = diff
|
||||
}
|
||||
|
||||
func (m *MServer) isShellInitialized(shellType string) bool {
|
||||
_, curState := m.StateMap.GetCurrentState(shellType)
|
||||
return curState != nil
|
||||
donePk.FinalStateBasePtr = runPk.StatePtr
|
||||
}
|
||||
|
||||
func (m *MServer) runCommand(runPacket *packet.RunPacketType) {
|
||||
@ -786,7 +777,7 @@ func (m *MServer) runCommand(runPacket *packet.RunPacketType) {
|
||||
}()
|
||||
shexec.SendRunPacketAndRunData(context.Background(), cproc.Input, runPacket)
|
||||
cproc.ProxySingleOutput(runPacket.CK, m.Sender, func(pk packet.PacketType) {
|
||||
m.clientPacketCallback(runPacket.ShellType, pk)
|
||||
m.clientPacketCallback(runPacket.ShellType, pk, runPacket)
|
||||
})
|
||||
}()
|
||||
}
|
||||
@ -849,7 +840,6 @@ func RunServer() (int, error) {
|
||||
server := &MServer{
|
||||
Lock: &sync.Mutex{},
|
||||
ClientMap: make(map[base.CommandKey]*shexec.ClientProc),
|
||||
StateMap: MakeShellStateMap(),
|
||||
Debug: debug,
|
||||
WriteErrorCh: make(chan bool),
|
||||
WriteErrorChOnce: &sync.Once{},
|
||||
|
@ -63,6 +63,9 @@ type ShellStateOutput struct {
|
||||
Error string
|
||||
}
|
||||
|
||||
// some timing info
|
||||
// MakeShellStateDiff takes ~1ms to run (even on a large diff)
|
||||
|
||||
type ShellApi interface {
|
||||
GetShellType() string
|
||||
MakeExitTrap(fdNum int) (string, []byte)
|
||||
|
@ -186,6 +186,9 @@ func readEncodedStringArray(buf *bytes.Buffer) ([]string, error) {
|
||||
|
||||
func (rtn *LineDiffType) Decode(diffBytes []byte) error {
|
||||
rtn.Clear()
|
||||
if len(diffBytes) == 0 {
|
||||
return nil
|
||||
}
|
||||
r := bytes.NewBuffer(diffBytes)
|
||||
version, err := binary.ReadUvarint(r)
|
||||
if err != nil {
|
||||
|
@ -29,7 +29,7 @@ func (diff *MapDiffType) Clear() {
|
||||
}
|
||||
|
||||
func (diff MapDiffType) Dump() {
|
||||
fmt.Printf("VAR-DIFF\n")
|
||||
fmt.Printf("VAR-DIFF +%d -%d\n", len(diff.ToAdd), len(diff.ToRemove))
|
||||
for name, val := range diff.ToAdd {
|
||||
fmt.Printf(" add[%s] %s\n", name, val)
|
||||
}
|
||||
@ -111,6 +111,9 @@ func (diff MapDiffType) Encode() []byte {
|
||||
|
||||
func (diff *MapDiffType) Decode(diffBytes []byte) error {
|
||||
diff.Clear()
|
||||
if len(diffBytes) == 0 {
|
||||
return nil
|
||||
}
|
||||
r := bytes.NewBuffer(diffBytes)
|
||||
version, err := binpack.UnpackUInt(r)
|
||||
if err != nil {
|
||||
|
@ -3862,7 +3862,7 @@ func doAsyncResetCommand(msh *remote.MShellProc, opts connectOptsType, cmd *ssto
|
||||
rtnErr = err
|
||||
return
|
||||
}
|
||||
newStatePtr := sstore.ShellStatePtr{
|
||||
newStatePtr := packet.ShellStatePtr{
|
||||
BaseHash: ssPk.State.GetHashVal(false),
|
||||
}
|
||||
if opts.Verbose && origStatePtr != nil {
|
||||
|
@ -12,6 +12,7 @@ import (
|
||||
"strings"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"github.com/wavetermdev/waveterm/waveshell/pkg/packet"
|
||||
"github.com/wavetermdev/waveterm/wavesrv/pkg/remote"
|
||||
"github.com/wavetermdev/waveterm/wavesrv/pkg/scpacket"
|
||||
"github.com/wavetermdev/waveterm/wavesrv/pkg/sstore"
|
||||
@ -42,7 +43,7 @@ type ResolvedRemote struct {
|
||||
RState remote.RemoteRuntimeState
|
||||
RemoteCopy *sstore.RemoteType
|
||||
ShellType string // default remote shell preference
|
||||
StatePtr *sstore.ShellStatePtr
|
||||
StatePtr *packet.ShellStatePtr
|
||||
FeState map[string]string
|
||||
}
|
||||
|
||||
@ -491,7 +492,7 @@ func ResolveRemoteFromPtr(ctx context.Context, rptr *sstore.RemotePtrType, sessi
|
||||
rtn.StatePtr = nil
|
||||
rtn.FeState = nil
|
||||
} else {
|
||||
rtn.StatePtr = &sstore.ShellStatePtr{BaseHash: ri.StateBaseHash, DiffHashArr: ri.StateDiffHashArr}
|
||||
rtn.StatePtr = &packet.ShellStatePtr{BaseHash: ri.StateBaseHash, DiffHashArr: ri.StateDiffHashArr}
|
||||
rtn.FeState = ri.FeState
|
||||
rtn.ShellType = ri.ShellType
|
||||
}
|
||||
|
@ -1886,7 +1886,7 @@ type RunCommandOpts struct {
|
||||
// optional, if not provided shellstate will look up state from remote instance
|
||||
// ReturnState cannot be used with StatePtr
|
||||
// this will also cause this command to bypass the pending state cmd logic
|
||||
StatePtr *sstore.ShellStatePtr
|
||||
StatePtr *packet.ShellStatePtr
|
||||
|
||||
// set to true to skip creating the pty file (for restarted commands)
|
||||
NoCreateCmdPtyFile bool
|
||||
@ -1920,6 +1920,9 @@ func RunCommand(ctx context.Context, rcOpts RunCommandOpts, runPacket *packet.Ru
|
||||
if rcOpts.StatePtr != nil && runPacket.ReturnState {
|
||||
return nil, nil, fmt.Errorf("RunCommand: cannot use ReturnState with StatePtr")
|
||||
}
|
||||
if runPacket.StatePtr != nil {
|
||||
return nil, nil, fmt.Errorf("runPacket.StatePtr should not be set, it is set in RunCommand")
|
||||
}
|
||||
|
||||
// pending state command logic
|
||||
// if we are currently running a command that can change the state, we need to wait for it to finish
|
||||
@ -1950,7 +1953,7 @@ func RunCommand(ctx context.Context, rcOpts RunCommandOpts, runPacket *packet.Ru
|
||||
}
|
||||
|
||||
// get current remote-instance state
|
||||
var statePtr *sstore.ShellStatePtr
|
||||
var statePtr *packet.ShellStatePtr
|
||||
if rcOpts.StatePtr != nil {
|
||||
statePtr = rcOpts.StatePtr
|
||||
} else {
|
||||
@ -1963,6 +1966,8 @@ func RunCommand(ctx context.Context, rcOpts RunCommandOpts, runPacket *packet.Ru
|
||||
return nil, nil, fmt.Errorf("cannot run command: no valid shell state found")
|
||||
}
|
||||
}
|
||||
// statePtr will not be nil
|
||||
runPacket.StatePtr = statePtr
|
||||
currentState, err := sstore.GetFullState(ctx, *statePtr)
|
||||
if err != nil || currentState == nil {
|
||||
return nil, nil, fmt.Errorf("cannot load current remote state: %w", err)
|
||||
@ -2216,31 +2221,95 @@ func (msh *MShellProc) notifyHangups_nolock() {
|
||||
msh.PendingStateCmds = make(map[pendingStateKey]base.CommandKey)
|
||||
}
|
||||
|
||||
// either fullstate or statediff will be set (not both) <- this is so the result is compatible with the sstore.UpdateRemoteState function
|
||||
// note that this function *does* touch the DB, if FinalStateDiff is set, will ensure that StateBase is written to DB
|
||||
func (msh *MShellProc) makeStatePtrFromFinalState(ctx context.Context, donePk *packet.CmdDonePacketType) (*sstore.ShellStatePtr, map[string]string, *packet.ShellState, *packet.ShellStateDiff, error) {
|
||||
func (msh *MShellProc) resolveFinalState(ctx context.Context, origState *packet.ShellState, origStatePtr *packet.ShellStatePtr, donePk *packet.CmdDonePacketType) (*packet.ShellState, error) {
|
||||
if donePk.FinalState != nil {
|
||||
if origStatePtr == nil {
|
||||
return nil, fmt.Errorf("command must have a stateptr to resolve final state")
|
||||
}
|
||||
finalState := stripScVarsFromState(donePk.FinalState)
|
||||
feState := sstore.FeStateFromShellState(finalState)
|
||||
statePtr := &sstore.ShellStatePtr{BaseHash: finalState.GetHashVal(false)}
|
||||
return statePtr, feState, finalState, nil, nil
|
||||
return finalState, nil
|
||||
}
|
||||
if donePk.FinalStateDiff != nil {
|
||||
if donePk.FinalStateBasePtr == nil {
|
||||
return nil, fmt.Errorf("invalid rtnstate, has diff but no baseptr")
|
||||
}
|
||||
stateDiff := stripScVarsFromStateDiff(donePk.FinalStateDiff)
|
||||
feState, err := msh.getFeStateFromDiff(stateDiff)
|
||||
if origStatePtr == donePk.FinalStateBasePtr {
|
||||
// this is the normal case. the stateptr from the run-packet should match the baseptr from the done-packet
|
||||
// this is also the most efficient, because we don't need to fetch the original state
|
||||
sapi, err := shellapi.MakeShellApi(origState.GetShellType())
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("cannot make shellapi from initial state: %w", err)
|
||||
}
|
||||
fullState, err := sapi.ApplyShellStateDiff(origState, stateDiff)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("cannot apply shell state diff: %w", err)
|
||||
}
|
||||
return fullState, nil
|
||||
}
|
||||
// this is strange (why is backend returning non-original stateptr?)
|
||||
// but here, we fetch the stateptr, and then apply the diff against that
|
||||
realOrigState, err := sstore.GetFullState(ctx, *donePk.FinalStateBasePtr)
|
||||
if err != nil {
|
||||
return nil, nil, nil, nil, err
|
||||
return nil, fmt.Errorf("cannot get original state for diff: %w", err)
|
||||
}
|
||||
fullState := msh.StateMap.GetStateByHash(stateDiff.GetShellType(), stateDiff.BaseHash)
|
||||
if fullState != nil {
|
||||
sstore.StoreStateBase(ctx, fullState)
|
||||
if realOrigState == nil {
|
||||
return nil, fmt.Errorf("cannot get original state for diff: not found")
|
||||
}
|
||||
diffHashArr := append(([]string)(nil), donePk.FinalStateDiff.DiffHashArr...)
|
||||
diffHashArr = append(diffHashArr, donePk.FinalStateDiff.GetHashVal(false))
|
||||
statePtr := &sstore.ShellStatePtr{BaseHash: donePk.FinalStateDiff.BaseHash, DiffHashArr: diffHashArr}
|
||||
return statePtr, feState, nil, stateDiff, nil
|
||||
sapi, err := shellapi.MakeShellApi(realOrigState.GetShellType())
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("cannot make shellapi from original state: %w", err)
|
||||
}
|
||||
fullState, err := sapi.ApplyShellStateDiff(realOrigState, stateDiff)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("cannot apply shell state diff: %w", err)
|
||||
}
|
||||
return fullState, nil
|
||||
}
|
||||
return nil, nil, nil, nil, nil
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// after this limit we'll switch to persisting the full state
|
||||
const NewStateDiffSizeThreshold = 30 * 1024
|
||||
|
||||
// will update the remote instance with the final state
|
||||
// this is complicated because we want to be as efficient as possible.
|
||||
// so we pull the current remote-instance state (just the baseptr). then we compute the diff.
|
||||
// then we check the size of the diff, and only persist the diff it is under some size threshold
|
||||
// also we check to see if the diff succeeds (it can fail if the shell or version changed).
|
||||
// in those cases we also update the RI with the full state
|
||||
func (msh *MShellProc) updateRIWithFinalState(ctx context.Context, rct *RunCmdType, newState *packet.ShellState) (*sstore.RemoteInstance, error) {
|
||||
curRIState, err := sstore.GetRemoteStatePtr(ctx, rct.SessionId, rct.ScreenId, rct.RemotePtr)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error trying to get current screen stateptr: %w", err)
|
||||
}
|
||||
feState := sstore.FeStateFromShellState(newState)
|
||||
if curRIState == nil {
|
||||
// no current state, so just persist the full state
|
||||
return sstore.UpdateRemoteState(ctx, rct.SessionId, rct.ScreenId, rct.RemotePtr, feState, newState, nil)
|
||||
}
|
||||
// pull the base (not the diff) state from the RI (right now we don't want to make multi-level diffs)
|
||||
riBaseState, err := sstore.GetStateBase(ctx, curRIState.BaseHash)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error trying to get statebase: %w", err)
|
||||
}
|
||||
sapi, err := shellapi.MakeShellApi(riBaseState.GetShellType())
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error trying to make shellapi: %w", err)
|
||||
}
|
||||
newStateDiff, err := sapi.MakeShellStateDiff(riBaseState, curRIState.BaseHash, newState)
|
||||
if err != nil {
|
||||
// if we can't make a diff, just persist the full state (this could happen if the shell type changes)
|
||||
return sstore.UpdateRemoteState(ctx, rct.SessionId, rct.ScreenId, rct.RemotePtr, feState, newState, nil)
|
||||
}
|
||||
// we have a diff, let's check the diff size first
|
||||
_, encodedDiff := newStateDiff.EncodeAndHash()
|
||||
if len(encodedDiff) > NewStateDiffSizeThreshold {
|
||||
// diff is too large, persist the full state
|
||||
return sstore.UpdateRemoteState(ctx, rct.SessionId, rct.ScreenId, rct.RemotePtr, feState, newState, nil)
|
||||
}
|
||||
// diff is small enough, persist the diff
|
||||
return sstore.UpdateRemoteState(ctx, rct.SessionId, rct.ScreenId, rct.RemotePtr, feState, nil, newStateDiff)
|
||||
}
|
||||
|
||||
func (msh *MShellProc) handleCmdDonePacket(rct *RunCmdType, donePk *packet.CmdDonePacketType) {
|
||||
@ -2261,12 +2330,12 @@ func (msh *MShellProc) handleCmdDonePacket(rct *RunCmdType, donePk *packet.CmdDo
|
||||
// only update DB for non-ephemeral commands
|
||||
err := sstore.UpdateCmdDoneInfo(ctx, update, donePk.CK, donePk, sstore.CmdStatusDone)
|
||||
if err != nil {
|
||||
msh.WriteToPtyBuffer("*error updating cmddone: %v\n", err)
|
||||
log.Printf("error updating cmddone info (in handleCmdDonePacket): %v\n", err)
|
||||
return
|
||||
}
|
||||
screen, err := sstore.UpdateScreenFocusForDoneCmd(ctx, donePk.CK.GetGroupId(), donePk.CK.GetCmdId())
|
||||
if err != nil {
|
||||
msh.WriteToPtyBuffer("*error trying to update screen focus type: %v\n", err)
|
||||
log.Printf("error trying to update screen focus type (in handleCmdDonePacket): %v\n", err)
|
||||
// fall-through (nothing to do)
|
||||
}
|
||||
if screen != nil {
|
||||
@ -2274,24 +2343,28 @@ func (msh *MShellProc) handleCmdDonePacket(rct *RunCmdType, donePk *packet.CmdDo
|
||||
}
|
||||
}
|
||||
// ephemeral commands *do* update the remote state
|
||||
if donePk.FinalState != nil || donePk.FinalStateDiff != nil {
|
||||
statePtr, feState, finalState, finalStateDiff, err := msh.makeStatePtrFromFinalState(ctx, donePk)
|
||||
// not all commands get a final state (only RtnState commands have this returned)
|
||||
// so in those cases finalState will be nil
|
||||
finalState, err := msh.resolveFinalState(ctx, rct.RunPacket.State, rct.RunPacket.StatePtr, donePk)
|
||||
if err != nil {
|
||||
log.Printf("error resolving final state for cmd: %v\n", err)
|
||||
// fallthrough
|
||||
}
|
||||
if finalState != nil {
|
||||
newRI, err := msh.updateRIWithFinalState(ctx, rct, finalState)
|
||||
if err != nil {
|
||||
msh.WriteToPtyBuffer("*error trying to read final command state: %v\n", err)
|
||||
log.Printf("error updating RI with final state (in handleCmdDonePacket): %v\n", err)
|
||||
// fallthrough
|
||||
}
|
||||
remoteInst, err := sstore.UpdateRemoteState(ctx, rct.SessionId, rct.ScreenId, rct.RemotePtr, feState, finalState, finalStateDiff)
|
||||
if err != nil {
|
||||
msh.WriteToPtyBuffer("*error trying to update remotestate: %v\n", err)
|
||||
// fall-through (nothing to do)
|
||||
}
|
||||
if remoteInst != nil {
|
||||
update.AddUpdate(sstore.MakeSessionUpdateForRemote(rct.SessionId, remoteInst))
|
||||
if newRI != nil {
|
||||
update.AddUpdate(sstore.MakeSessionUpdateForRemote(rct.SessionId, newRI))
|
||||
}
|
||||
// ephemeral commands *do not* update cmd state (there is no command)
|
||||
if statePtr != nil && !rct.Ephemeral {
|
||||
err = sstore.UpdateCmdRtnState(ctx, donePk.CK, *statePtr)
|
||||
if newRI != nil && !rct.Ephemeral {
|
||||
newRIStatePtr := packet.ShellStatePtr{BaseHash: newRI.StateBaseHash, DiffHashArr: newRI.StateDiffHashArr}
|
||||
err = sstore.UpdateCmdRtnState(ctx, donePk.CK, newRIStatePtr)
|
||||
if err != nil {
|
||||
msh.WriteToPtyBuffer("*error trying to update cmd rtnstate: %v\n", err)
|
||||
log.Printf("error trying to update cmd rtnstate: %v\n", err)
|
||||
// fall-through (nothing to do)
|
||||
}
|
||||
}
|
||||
@ -2605,7 +2678,7 @@ func (msh *MShellProc) getFullState(shellType string, stateDiff *packet.ShellSta
|
||||
}
|
||||
return newState, nil
|
||||
} else {
|
||||
fullState, err := sstore.GetFullState(context.Background(), sstore.ShellStatePtr{BaseHash: stateDiff.BaseHash, DiffHashArr: stateDiff.DiffHashArr})
|
||||
fullState, err := sstore.GetFullState(context.Background(), packet.ShellStatePtr{BaseHash: stateDiff.BaseHash, DiffHashArr: stateDiff.DiffHashArr})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -2632,7 +2705,7 @@ func (msh *MShellProc) getFeStateFromDiff(stateDiff *packet.ShellStateDiff) (map
|
||||
}
|
||||
return sstore.FeStateFromShellState(newState), nil
|
||||
} else {
|
||||
fullState, err := sstore.GetFullState(context.Background(), sstore.ShellStatePtr{BaseHash: stateDiff.BaseHash, DiffHashArr: stateDiff.DiffHashArr})
|
||||
fullState, err := sstore.GetFullState(context.Background(), packet.ShellStatePtr{BaseHash: stateDiff.BaseHash, DiffHashArr: stateDiff.DiffHashArr})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -35,10 +35,10 @@ func (rptr *RemotePtrType) GetDisplayName(baseDisplayName string) string {
|
||||
return name
|
||||
}
|
||||
if rptr.Name != "" {
|
||||
name = name + ":" + rptr.Name
|
||||
name = name + "#" + rptr.Name
|
||||
}
|
||||
if rptr.OwnerId != "" {
|
||||
name = "@" + rptr.OwnerId + ":" + name
|
||||
name = "@" + rptr.OwnerId + "#" + name
|
||||
}
|
||||
return name
|
||||
}
|
||||
|
@ -793,7 +793,7 @@ func UpdateCmdDoneInfo(ctx context.Context, update *scbus.ModelUpdatePacketType,
|
||||
return nil
|
||||
}
|
||||
|
||||
func UpdateCmdRtnState(ctx context.Context, ck base.CommandKey, statePtr ShellStatePtr) error {
|
||||
func UpdateCmdRtnState(ctx context.Context, ck base.CommandKey, statePtr packet.ShellStatePtr) error {
|
||||
if ck.IsEmpty() {
|
||||
return fmt.Errorf("cannot update cmdrtnstate, empty ck")
|
||||
}
|
||||
@ -1098,7 +1098,7 @@ func DeleteScreen(ctx context.Context, screenId string, sessionDel bool, update
|
||||
return update, nil
|
||||
}
|
||||
|
||||
func GetRemoteState(ctx context.Context, sessionId string, screenId string, remotePtr RemotePtrType) (*packet.ShellState, *ShellStatePtr, error) {
|
||||
func GetRemoteState(ctx context.Context, sessionId string, screenId string, remotePtr RemotePtrType) (*packet.ShellState, *packet.ShellStatePtr, error) {
|
||||
ssptr, err := GetRemoteStatePtr(ctx, sessionId, screenId, remotePtr)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
@ -1113,8 +1113,8 @@ func GetRemoteState(ctx context.Context, sessionId string, screenId string, remo
|
||||
return state, ssptr, err
|
||||
}
|
||||
|
||||
func GetRemoteStatePtr(ctx context.Context, sessionId string, screenId string, remotePtr RemotePtrType) (*ShellStatePtr, error) {
|
||||
var ssptr *ShellStatePtr
|
||||
func GetRemoteStatePtr(ctx context.Context, sessionId string, screenId string, remotePtr RemotePtrType) (*packet.ShellStatePtr, error) {
|
||||
var ssptr *packet.ShellStatePtr
|
||||
txErr := WithTx(ctx, func(tx *TxWrap) error {
|
||||
ri, err := GetRemoteInstance(tx.Context(), sessionId, screenId, remotePtr)
|
||||
if err != nil {
|
||||
@ -1123,7 +1123,7 @@ func GetRemoteStatePtr(ctx context.Context, sessionId string, screenId string, r
|
||||
if ri == nil {
|
||||
return nil
|
||||
}
|
||||
ssptr = &ShellStatePtr{ri.StateBaseHash, ri.StateDiffHashArr}
|
||||
ssptr = &packet.ShellStatePtr{ri.StateBaseHash, ri.StateDiffHashArr}
|
||||
return nil
|
||||
})
|
||||
if txErr != nil {
|
||||
@ -1836,7 +1836,7 @@ func GetStateBaseVersion(ctx context.Context, baseHash string) (string, error) {
|
||||
})
|
||||
}
|
||||
|
||||
func GetCurStateDiffFromPtr(ctx context.Context, ssPtr *ShellStatePtr) (*packet.ShellStateDiff, error) {
|
||||
func GetCurStateDiffFromPtr(ctx context.Context, ssPtr *packet.ShellStatePtr) (*packet.ShellStateDiff, error) {
|
||||
if ssPtr == nil {
|
||||
return nil, fmt.Errorf("cannot resolve state, empty stateptr")
|
||||
}
|
||||
@ -1894,7 +1894,7 @@ func GetStateDiff(ctx context.Context, diffHash string) (*packet.ShellStateDiff,
|
||||
}
|
||||
|
||||
// returns error when not found
|
||||
func GetFullState(ctx context.Context, ssPtr ShellStatePtr) (*packet.ShellState, error) {
|
||||
func GetFullState(ctx context.Context, ssPtr packet.ShellStatePtr) (*packet.ShellState, error) {
|
||||
var state *packet.ShellState
|
||||
if ssPtr.BaseHash == "" {
|
||||
return nil, fmt.Errorf("invalid empty basehash")
|
||||
|
@ -538,18 +538,6 @@ func (opts TermOpts) Value() (driver.Value, error) {
|
||||
return quickValueJson(opts)
|
||||
}
|
||||
|
||||
type ShellStatePtr struct {
|
||||
BaseHash string
|
||||
DiffHashArr []string
|
||||
}
|
||||
|
||||
func (ssptr *ShellStatePtr) IsEmpty() bool {
|
||||
if ssptr == nil || ssptr.BaseHash == "" {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
type RemoteInstance struct {
|
||||
RIId string `json:"riid"`
|
||||
Name string `json:"name"`
|
||||
@ -864,27 +852,27 @@ func (r *RemoteType) GetName() string {
|
||||
}
|
||||
|
||||
type CmdType struct {
|
||||
ScreenId string `json:"screenid"`
|
||||
LineId string `json:"lineid"`
|
||||
Remote RemotePtrType `json:"remote"`
|
||||
CmdStr string `json:"cmdstr"`
|
||||
RawCmdStr string `json:"rawcmdstr"`
|
||||
FeState map[string]string `json:"festate"`
|
||||
StatePtr ShellStatePtr `json:"state"`
|
||||
TermOpts TermOpts `json:"termopts"`
|
||||
OrigTermOpts TermOpts `json:"origtermopts"`
|
||||
Status string `json:"status"`
|
||||
CmdPid int `json:"cmdpid"`
|
||||
RemotePid int `json:"remotepid"`
|
||||
RestartTs int64 `json:"restartts,omitempty"`
|
||||
DoneTs int64 `json:"donets"`
|
||||
ExitCode int `json:"exitcode"`
|
||||
DurationMs int `json:"durationms"`
|
||||
RunOut []packet.PacketType `json:"runout,omitempty"`
|
||||
RtnState bool `json:"rtnstate,omitempty"`
|
||||
RtnStatePtr ShellStatePtr `json:"rtnstateptr,omitempty"`
|
||||
Remove bool `json:"remove,omitempty"` // not persisted to DB
|
||||
Restarted bool `json:"restarted,omitempty"` // not persisted to DB
|
||||
ScreenId string `json:"screenid"`
|
||||
LineId string `json:"lineid"`
|
||||
Remote RemotePtrType `json:"remote"`
|
||||
CmdStr string `json:"cmdstr"`
|
||||
RawCmdStr string `json:"rawcmdstr"`
|
||||
FeState map[string]string `json:"festate"`
|
||||
StatePtr packet.ShellStatePtr `json:"state"`
|
||||
TermOpts TermOpts `json:"termopts"`
|
||||
OrigTermOpts TermOpts `json:"origtermopts"`
|
||||
Status string `json:"status"`
|
||||
CmdPid int `json:"cmdpid"`
|
||||
RemotePid int `json:"remotepid"`
|
||||
RestartTs int64 `json:"restartts,omitempty"`
|
||||
DoneTs int64 `json:"donets"`
|
||||
ExitCode int `json:"exitcode"`
|
||||
DurationMs int `json:"durationms"`
|
||||
RunOut []packet.PacketType `json:"runout,omitempty"`
|
||||
RtnState bool `json:"rtnstate,omitempty"`
|
||||
RtnStatePtr packet.ShellStatePtr `json:"rtnstateptr,omitempty"`
|
||||
Remove bool `json:"remove,omitempty"` // not persisted to DB
|
||||
Restarted bool `json:"restarted,omitempty"` // not persisted to DB
|
||||
}
|
||||
|
||||
func (CmdType) GetType() string {
|
||||
|
Loading…
Reference in New Issue
Block a user