@@ -2,19 +2,31 @@ package cmd
2
2
3
3
import (
4
4
"errors"
5
+ "fmt"
6
+ "log"
5
7
"os"
6
8
"os/exec"
9
+ "path/filepath"
7
10
"time"
8
11
12
+ "github.com/jedib0t/go-pretty/v6/table"
13
+ "github.com/jedib0t/go-pretty/v6/text"
9
14
"github.com/spf13/cobra"
10
15
"github.com/tarantool/tt/cli/cmdcontext"
11
16
"github.com/tarantool/tt/cli/modules"
17
+ "github.com/tarantool/tt/cli/process_utils"
12
18
tcmCmd "github.com/tarantool/tt/cli/tcm"
13
19
"github.com/tarantool/tt/cli/util"
20
+ libwatchdog "github.com/tarantool/tt/lib/watchdog"
14
21
)
15
22
16
23
var tcmCtx = tcmCmd.TcmCtx {}
17
24
25
+ const (
26
+ tcmPidFile = "tcmPidFile.pid"
27
+ watchdogPidFile = "watchdogPidFile.pid"
28
+ )
29
+
18
30
func newTcmStartCmd () * cobra.Command {
19
31
var tcmCmd = & cobra.Command {
20
32
Use : "start" ,
@@ -26,7 +38,6 @@ func newTcmStartCmd() *cobra.Command {
26
38
cmdCtx .CommandName = cmd .Name ()
27
39
err := modules .RunCmd (& cmdCtx , cmd .CommandPath (), & modulesInfo , internalStartTcm , args )
28
40
util .HandleCmdErr (cmd , err )
29
-
30
41
},
31
42
}
32
43
tcmCmd .Flags ().StringVar (& tcmCtx .Executable , "path" , "" , "the path to the tcm binary file" )
@@ -35,40 +46,73 @@ func newTcmStartCmd() *cobra.Command {
35
46
return tcmCmd
36
47
}
37
48
49
+ func newTcmStatusCmd () * cobra.Command {
50
+ var tcmCmd = & cobra.Command {
51
+ Use : "status" ,
52
+ Short : "Status tcm application" ,
53
+ Long : `Status to the tcm.
54
+ tt tcm status` ,
55
+ Run : func (cmd * cobra.Command , args []string ) {
56
+ cmdCtx .CommandName = cmd .Name ()
57
+ err := modules .RunCmd (& cmdCtx , cmd .CommandPath (), & modulesInfo , internalTcmStatus , args )
58
+ util .HandleCmdErr (cmd , err )
59
+ },
60
+ }
61
+ return tcmCmd
62
+ }
63
+
64
+ func newTcmStopCmd () * cobra.Command {
65
+ var tcmCmd = & cobra.Command {
66
+ Use : "stop" ,
67
+ Short : "Stop tcm application" ,
68
+ Long : `Stop to the tcm. tt tcm stop` ,
69
+ Run : func (cmd * cobra.Command , args []string ) {
70
+ cmdCtx .CommandName = cmd .Name ()
71
+ err := modules .RunCmd (& cmdCtx , cmd .CommandPath (), & modulesInfo , internalTcmStop , args )
72
+ util .HandleCmdErr (cmd , err )
73
+ },
74
+ }
75
+ return tcmCmd
76
+ }
77
+
38
78
func NewTcmCmd () * cobra.Command {
39
79
var tcmCmd = & cobra.Command {
40
80
Use : "tcm" ,
41
81
Short : "Manage tcm application" ,
42
82
}
43
83
tcmCmd .AddCommand (
44
84
newTcmStartCmd (),
85
+ newTcmStatusCmd (),
86
+ newTcmStopCmd (),
45
87
)
46
88
return tcmCmd
47
89
}
48
90
49
91
func startTcmInteractive () error {
50
92
tcmApp := exec .Command (tcmCtx .Executable )
51
93
52
- tcmApp .Stdout = os .Stdout
53
- tcmApp .Stderr = os .Stderr
54
-
55
- if err := tcmApp .Run (); err != nil {
94
+ if err := tcmApp .Start (); err != nil {
56
95
return err
57
96
}
58
97
59
- return nil
60
- }
98
+ if tcmApp == nil || tcmApp .Process == nil {
99
+ return errors .New ("process is not running" )
100
+ }
61
101
62
- func startTcmUnderWatchDog () error {
63
- wd , err := tcmCmd .NewWatchdog (5 * time .Second )
102
+ err := process_utils .CreatePIDFile (tcmPidFile , tcmApp .Process .Pid )
64
103
if err != nil {
65
104
return err
66
105
}
67
106
107
+ log .Printf ("(INFO): Interactive process PID %d written to %s\n " , tcmApp .Process .Pid , tcmPidFile )
108
+ return nil
109
+ }
110
+
111
+ func startTcmUnderWatchDog () error {
112
+ wd := libwatchdog .NewWatchdog (tcmPidFile , watchdogPidFile , 5 * time .Second )
68
113
if err := wd .Start (tcmCtx .Executable ); err != nil {
69
114
return err
70
115
}
71
-
72
116
return nil
73
117
}
74
118
@@ -87,11 +131,61 @@ func internalStartTcm(cmdCtx *cmdcontext.CmdCtx, args []string) error {
87
131
if err := startTcmInteractive (); err != nil {
88
132
return err
89
133
}
134
+ } else {
135
+ if err := startTcmUnderWatchDog (); err != nil {
136
+ return err
137
+ }
90
138
}
91
139
92
- if err := startTcmUnderWatchDog (); err != nil {
140
+ return nil
141
+ }
142
+
143
+ func internalTcmStatus (cmdCtx * cmdcontext.CmdCtx , args []string ) error {
144
+ pidAbsPath , err := filepath .Abs (tcmPidFile )
145
+ if err != nil {
93
146
return err
94
147
}
95
148
149
+ if _ , err := os .Stat (pidAbsPath ); err != nil {
150
+ return fmt .Errorf ("path does not exist: %v" , err )
151
+ }
152
+
153
+ ts := table .NewWriter ()
154
+ ts .SetOutputMirror (os .Stdout )
155
+
156
+ ts .AppendHeader (
157
+ table.Row {"APPLICATION" , "STATUS" , "PID" })
158
+
159
+ ts .SetColumnConfigs ([]table.ColumnConfig {
160
+ {Number : 1 , Align : text .AlignLeft , AlignHeader : text .AlignLeft },
161
+ {Number : 2 , Align : text .AlignLeft , AlignHeader : text .AlignLeft },
162
+ {Number : 3 , Align : text .AlignLeft , AlignHeader : text .AlignLeft },
163
+ {Number : 4 , Align : text .AlignLeft , AlignHeader : text .AlignLeft },
164
+ })
165
+
166
+ status := process_utils .ProcessStatus (pidAbsPath )
167
+
168
+ ts .AppendRows ([]table.Row {
169
+ {"TCM" , status .Status , status .PID },
170
+ })
171
+ ts .Render ()
172
+ return nil
173
+ }
174
+
175
+ func internalTcmStop (cmdCtx * cmdcontext.CmdCtx , args []string ) error {
176
+ if isExists , _ := process_utils .ExistsAndRecord (watchdogPidFile ); isExists {
177
+ _ , err := process_utils .StopProcess (watchdogPidFile )
178
+ if err != nil {
179
+ return err
180
+ }
181
+ log .Println ("Watchdog and TCM stoped" )
182
+ } else {
183
+ _ , err := process_utils .StopProcess (tcmPidFile )
184
+ if err != nil {
185
+ return err
186
+ }
187
+ log .Println ("TCM stoped" )
188
+ }
189
+
96
190
return nil
97
191
}
0 commit comments