@@ -33,6 +33,14 @@ type StartOpts struct {
33
33
// InitScript is a Lua script for tarantool to run on start.
34
34
InitScript string
35
35
36
+ // ConfigFile is a path to a configuration file for a Tarantool instance.
37
+ // Required in pair with InstanceName.
38
+ ConfigFile string
39
+
40
+ // InstanceName is a name of an instance to run.
41
+ // Required in pair with ConfigFile.
42
+ InstanceName string
43
+
36
44
// Listen is box.cfg listen parameter for tarantool.
37
45
// Use this address to connect to tarantool after configuration.
38
46
// https://www.tarantool.io/en/doc/latest/reference/configuration/#cfg-basic-listen
@@ -77,6 +85,39 @@ type TarantoolInstance struct {
77
85
78
86
// Dialer to check that connection established.
79
87
Dialer tarantool.Dialer
88
+
89
+ done chan error
90
+ is_done bool
91
+ result error
92
+ is_stopping bool
93
+ }
94
+
95
+ // Status checks if Tarantool instance is still running.
96
+ // Return true if it is running, false if it is not.
97
+ // If instance was exit and error is nil - process completed success with zero status code.
98
+ func (t * TarantoolInstance ) Status () (bool , error ) {
99
+ if t .is_done {
100
+ return false , t .result
101
+ }
102
+
103
+ select {
104
+ case t .result = <- t .done :
105
+ t .is_done = true
106
+ return false , t .result
107
+ default :
108
+ return true , nil
109
+ }
110
+ }
111
+
112
+ func (t * TarantoolInstance ) checkDone () {
113
+ t .is_done = false
114
+ t .is_stopping = false
115
+ t .done = make (chan error , 1 )
116
+ t .done <- t .Cmd .Wait ()
117
+ if ! t .is_stopping {
118
+ _ , err := t .Status ()
119
+ log .Printf ("Tarantool was unexpected terminated: %s" , err )
120
+ }
80
121
}
81
122
82
123
func isReady (dialer tarantool.Dialer , opts * tarantool.Opts ) error {
@@ -108,7 +149,7 @@ var (
108
149
)
109
150
110
151
func init () {
111
- tarantoolVersionRegexp = regexp .MustCompile (`Tarantool (?: Enterprise )?(\d+)\.(\d+)\.(\d+).*` )
152
+ tarantoolVersionRegexp = regexp .MustCompile (`Tarantool (Enterprise )?(\d+)\.(\d+)\.(\d+).*` )
112
153
}
113
154
114
155
// atoiUint64 parses string to uint64.
@@ -145,15 +186,15 @@ func IsTarantoolVersionLess(majorMin uint64, minorMin uint64, patchMin uint64) (
145
186
return true , fmt .Errorf ("failed to parse output %q" , out )
146
187
}
147
188
148
- if major , err = atoiUint64 (parsed [1 ]); err != nil {
189
+ if major , err = atoiUint64 (parsed [2 ]); err != nil {
149
190
return true , fmt .Errorf ("failed to parse major from output %q: %w" , out , err )
150
191
}
151
192
152
- if minor , err = atoiUint64 (parsed [2 ]); err != nil {
193
+ if minor , err = atoiUint64 (parsed [3 ]); err != nil {
153
194
return true , fmt .Errorf ("failed to parse minor from output %q: %w" , out , err )
154
195
}
155
196
156
- if patch , err = atoiUint64 (parsed [3 ]); err != nil {
197
+ if patch , err = atoiUint64 (parsed [4 ]); err != nil {
157
198
return true , fmt .Errorf ("failed to parse patch from output %q: %w" , out , err )
158
199
}
159
200
@@ -166,6 +207,21 @@ func IsTarantoolVersionLess(majorMin uint64, minorMin uint64, patchMin uint64) (
166
207
}
167
208
}
168
209
210
+ // IsTarantoolEE checks if Tarantool is Enterprise edition.
211
+ func IsTarantoolEE () (bool , error ) {
212
+ out , err := exec .Command (getTarantoolExec (), "--version" ).Output ()
213
+ if err != nil {
214
+ return true , err
215
+ }
216
+
217
+ parsed := tarantoolVersionRegexp .FindStringSubmatch (string (out ))
218
+ if parsed == nil {
219
+ return true , fmt .Errorf ("failed to parse output %q" , out )
220
+ }
221
+
222
+ return parsed [1 ] != "" , nil
223
+ }
224
+
169
225
// RestartTarantool restarts a tarantool instance for tests
170
226
// with specifies parameters (refer to StartOpts)
171
227
// which were specified in inst parameter.
@@ -209,8 +265,16 @@ func StartTarantool(startOpts StartOpts) (TarantoolInstance, error) {
209
265
return inst , err
210
266
}
211
267
}
268
+ args := []string {}
212
269
213
- inst .Cmd = exec .Command (getTarantoolExec (), startOpts .InitScript )
270
+ if startOpts .InitScript != "" {
271
+ args = append (args , startOpts .InitScript )
272
+ }
273
+ if startOpts .ConfigFile != "" && startOpts .InstanceName != "" {
274
+ args = append (args , "--config" , startOpts .ConfigFile )
275
+ args = append (args , "--name" , startOpts .InstanceName )
276
+ }
277
+ inst .Cmd = exec .Command (getTarantoolExec (), args ... )
214
278
215
279
inst .Cmd .Env = append (
216
280
os .Environ (),
@@ -242,6 +306,8 @@ func StartTarantool(startOpts StartOpts) (TarantoolInstance, error) {
242
306
// see https://github.com/tarantool/go-tarantool/issues/136
243
307
time .Sleep (startOpts .WaitStart )
244
308
309
+ go inst .checkDone ()
310
+
245
311
opts := tarantool.Opts {
246
312
Timeout : 500 * time .Millisecond ,
247
313
SkipSchema : true ,
@@ -261,21 +327,40 @@ func StartTarantool(startOpts StartOpts) (TarantoolInstance, error) {
261
327
}
262
328
}
263
329
264
- return inst , err
330
+ working , err_st := inst .Status ()
331
+ if ! working || err_st != nil {
332
+ StopTarantool (inst )
333
+ return TarantoolInstance {}, fmt .Errorf ("unexpected terminated Tarantool: %w" , err_st )
334
+ }
335
+
336
+ if err != nil {
337
+ StopTarantool (inst )
338
+ return TarantoolInstance {}, fmt .Errorf ("failed to connect Tarantool: %w" , err )
339
+ }
340
+
341
+ return inst , nil
265
342
}
266
343
267
344
// StopTarantool stops a tarantool instance started
268
345
// with StartTarantool. Waits until any resources
269
346
// associated with the process is released. If something went wrong, fails.
270
347
func StopTarantool (inst TarantoolInstance ) {
348
+ log .Printf ("Stopping Tarantool instance" )
349
+ inst .is_stopping = true
271
350
if inst .Cmd != nil && inst .Cmd .Process != nil {
272
351
if err := inst .Cmd .Process .Kill (); err != nil {
273
- log .Fatalf ("Failed to kill tarantool (pid %d), got %s" , inst .Cmd .Process .Pid , err )
352
+ is_running , _ := inst .Status ()
353
+ if is_running {
354
+ log .Fatalf ("Failed to kill tarantool (pid %d), got %s" , inst .Cmd .Process .Pid , err )
355
+ }
274
356
}
275
357
276
358
// Wait releases any resources associated with the Process.
277
359
if _ , err := inst .Cmd .Process .Wait (); err != nil {
278
- log .Fatalf ("Failed to wait for Tarantool process to exit, got %s" , err )
360
+ is_running , _ := inst .Status ()
361
+ if is_running {
362
+ log .Fatalf ("Failed to wait for Tarantool process to exit, got %s" , err )
363
+ }
279
364
}
280
365
281
366
inst .Cmd .Process = nil
0 commit comments