@@ -101,10 +101,17 @@ type TestServer interface {
101
101
// BaseDir returns directory StoreOnDiskOpt writes to if used.
102
102
BaseDir () string
103
103
104
- WaitForNode (numNode int ) error
104
+ // WaitForInitFinishForNode waits until a node has completed
105
+ // initialization and is available to connect to and query on.
106
+ WaitForInitFinishForNode (numNode int ) error
107
+ // StartNode runs the "cockroach start" command for the node.
105
108
StartNode (i int ) error
109
+ // StopNode kills the node's process.
106
110
StopNode (i int ) error
111
+ // UpgradeNode stops the node, then starts the node on the with the
112
+ // binary specified at "upgradeBinaryPath".
107
113
UpgradeNode (i int ) error
114
+ // PGURLForNode returns the PGUrl for the node.
108
115
PGURLForNode (nodeNum int ) * url.URL
109
116
}
110
117
@@ -117,24 +124,29 @@ type pgURLChan struct {
117
124
orig url.URL
118
125
}
119
126
127
+ // nodeInfo contains the info to start a node and the state of the node.
128
+ type nodeInfo struct {
129
+ startCmd * exec.Cmd
130
+ startCmdArgs []string
131
+ listeningURLFile string
132
+ state int
133
+ }
134
+
120
135
// testServerImpl is a TestServer implementation.
121
136
type testServerImpl struct {
122
- mu sync.RWMutex
123
- version * version.Version
124
- serverArgs testServerArgs
125
- state int
126
- nodeStates []int
127
- baseDir string
128
- pgURL []pgURLChan
129
- cmd []* exec.Cmd
130
- cmdArgs [][]string
131
- initCmd * exec.Cmd
132
- initCmdArgs []string
133
- stdout string
134
- stderr string
135
- stdoutBuf logWriter
136
- stderrBuf logWriter
137
- listeningURLFile []string
137
+ mu sync.RWMutex
138
+ version * version.Version
139
+ serverArgs testServerArgs
140
+ serverState int
141
+ baseDir string
142
+ pgURL []pgURLChan
143
+ initCmd * exec.Cmd
144
+ initCmdArgs []string
145
+ stdout string
146
+ stderr string
147
+ stdoutBuf logWriter
148
+ stderrBuf logWriter
149
+ nodes []nodeInfo
138
150
139
151
// curTenantID is used to allocate tenant IDs. Refer to NewTenantServer for
140
152
// more information.
@@ -291,7 +303,7 @@ func StopDownloadInMiddleOpt() TestServerOpt {
291
303
}
292
304
}
293
305
294
- func ThreeNode () TestServerOpt {
306
+ func ThreeNodeOpt () TestServerOpt {
295
307
return func (args * testServerArgs ) {
296
308
args .numNodes = 3
297
309
}
@@ -376,11 +388,6 @@ func NewTestServer(opts ...TestServerOpt) (TestServer, error) {
376
388
return nil , fmt .Errorf ("%s: %w" , testserverMessagePrefix , err )
377
389
}
378
390
379
- listeningURLFile := make ([]string , serverArgs .numNodes )
380
- for i := 0 ; i < serverArgs .numNodes ; i ++ {
381
- listeningURLFile [i ] = filepath .Join (baseDir , fmt .Sprintf ("listen-url%d" , i ))
382
- }
383
-
384
391
secureOpt := "--insecure"
385
392
if serverArgs .secure {
386
393
// Create certificates.
@@ -436,40 +443,44 @@ func NewTestServer(opts ...TestServerOpt) (TestServer, error) {
436
443
storeArg = fmt .Sprintf ("--store=type=mem,size=%.2f" , serverArgs .storeMemSize )
437
444
}
438
445
439
- args := make ([][] string , serverArgs .numNodes )
446
+ nodes := make ([]nodeInfo , serverArgs .numNodes )
440
447
var initArgs []string
441
- if serverArgs .numNodes <= 1 {
442
- args [0 ] = []string {
443
- serverArgs .cockroachBinary ,
444
- startCmd ,
445
- "--logtostderr" ,
446
- secureOpt ,
447
- "--host=localhost" ,
448
- "--port=0" ,
449
- "--http-port=" + strconv .Itoa (serverArgs .httpPort ),
450
- storeArg ,
451
- "--listening-url-file=" + listeningURLFile [0 ],
452
- }
453
- } else {
454
- for i := 0 ; i < serverArgs .numNodes ; i ++ {
455
- args [i ] = []string {
448
+ for i := 0 ; i < serverArgs .numNodes ; i ++ {
449
+ nodes [i ].state = stateNew
450
+ nodes [i ].listeningURLFile = filepath .Join (baseDir , fmt .Sprintf ("listen-url%d" , i ))
451
+ if serverArgs .numNodes > 1 {
452
+ nodes [i ].startCmdArgs = []string {
456
453
serverArgs .cockroachBinary ,
457
454
startCmd ,
458
455
secureOpt ,
459
456
storeArg + strconv .Itoa (i ),
460
457
fmt .Sprintf ("--listen-addr=localhost:%d" , 26257 + i ),
461
458
fmt .Sprintf ("--http-addr=localhost:%d" , 8080 + i ),
462
- "--listening-url-file=" + listeningURLFile [i ],
459
+ "--listening-url-file=" + nodes [i ]. listeningURLFile ,
463
460
fmt .Sprintf ("--join=localhost:%d,localhost:%d,localhost:%d" , 26257 , 26258 , 26259 ),
464
461
}
462
+ } else {
463
+ nodes [0 ].startCmdArgs = []string {
464
+ serverArgs .cockroachBinary ,
465
+ startCmd ,
466
+ "--logtostderr" ,
467
+ secureOpt ,
468
+ "--host=localhost" ,
469
+ "--port=0" ,
470
+ "--http-port=" + strconv .Itoa (serverArgs .httpPort ),
471
+ storeArg ,
472
+ "--listening-url-file=" + nodes [i ].listeningURLFile ,
473
+ }
465
474
}
475
+ }
466
476
467
- initArgs = []string {
468
- serverArgs .cockroachBinary ,
469
- "init" ,
470
- secureOpt ,
471
- "--host=localhost:26259" ,
472
- }
477
+ // We only need initArgs if we're creating a testserver
478
+ // with multiple nodes.
479
+ initArgs = []string {
480
+ serverArgs .cockroachBinary ,
481
+ "init" ,
482
+ secureOpt ,
483
+ "--host=localhost:26259" ,
473
484
}
474
485
475
486
states := make ([]int , serverArgs .numNodes )
@@ -478,18 +489,15 @@ func NewTestServer(opts ...TestServerOpt) (TestServer, error) {
478
489
}
479
490
480
491
ts := & testServerImpl {
481
- serverArgs : * serverArgs ,
482
- version : v ,
483
- state : stateNew ,
484
- nodeStates : states ,
485
- baseDir : baseDir ,
486
- cmdArgs : args ,
487
- cmd : make ([]* exec.Cmd , serverArgs .numNodes ),
488
- initCmdArgs : initArgs ,
489
- stdout : filepath .Join (logDir , "cockroach.stdout" ),
490
- stderr : filepath .Join (logDir , "cockroach.stderr" ),
491
- listeningURLFile : listeningURLFile ,
492
- curTenantID : firstTenantID ,
492
+ serverArgs : * serverArgs ,
493
+ version : v ,
494
+ serverState : stateNew ,
495
+ baseDir : baseDir ,
496
+ initCmdArgs : initArgs ,
497
+ stdout : filepath .Join (logDir , "cockroach.stdout" ),
498
+ stderr : filepath .Join (logDir , "cockroach.stderr" ),
499
+ curTenantID : firstTenantID ,
500
+ nodes : nodes ,
493
501
}
494
502
ts .pgURL = make ([]pgURLChan , serverArgs .numNodes )
495
503
@@ -546,7 +554,7 @@ func (ts *testServerImpl) setPGURLForNode(nodeNum int, u *url.URL) {
546
554
close (ts .pgURL [nodeNum ].set )
547
555
}
548
556
549
- func (ts * testServerImpl ) WaitForNode (nodeNum int ) error {
557
+ func (ts * testServerImpl ) WaitForInitFinishForNode (nodeNum int ) error {
550
558
db , err := sql .Open ("postgres" , ts .PGURLForNode (nodeNum ).String ())
551
559
defer func () {
552
560
_ = db .Close ()
@@ -558,29 +566,29 @@ func (ts *testServerImpl) WaitForNode(nodeNum int) error {
558
566
if _ , err = db .Query ("SHOW DATABASES" ); err == nil {
559
567
return err
560
568
}
561
- log .Printf ("%s: WaitForNode %d: Trying again after error: %v" , testserverMessagePrefix , nodeNum , err )
569
+ log .Printf ("%s: WaitForInitFinishForNode %d: Trying again after error: %v" , testserverMessagePrefix , nodeNum , err )
562
570
time .Sleep (time .Millisecond * 100 )
563
571
}
564
572
return nil
565
573
}
566
574
567
575
// WaitForInit retries until a connection is successfully established.
568
576
func (ts * testServerImpl ) WaitForInit () error {
569
- return ts .WaitForNode (0 )
577
+ return ts .WaitForInitFinishForNode (0 )
570
578
}
571
579
572
580
func (ts * testServerImpl ) pollListeningURLFile (nodeNum int ) error {
573
581
var data []byte
574
582
for {
575
583
ts .mu .RLock ()
576
- state := ts .nodeStates [nodeNum ]
584
+ state := ts .nodes [nodeNum ]. state
577
585
ts .mu .RUnlock ()
578
586
if state != stateRunning {
579
587
return fmt .Errorf ("server stopped or crashed before listening URL file was available" )
580
588
}
581
589
582
590
var err error
583
- data , err = ioutil .ReadFile (ts .listeningURLFile [nodeNum ])
591
+ data , err = ioutil .ReadFile (ts .nodes [nodeNum ]. listeningURLFile )
584
592
if err == nil {
585
593
break
586
594
} else if ! os .IsNotExist (err ) {
@@ -624,9 +632,9 @@ func (ts *testServerImpl) pollListeningURLFile(nodeNum int) error {
624
632
// to restart a testserver, but use NewTestServer().
625
633
func (ts * testServerImpl ) Start () error {
626
634
ts .mu .Lock ()
627
- if ts .state != stateNew {
635
+ if ts .serverState != stateNew {
628
636
ts .mu .Unlock ()
629
- switch ts .state {
637
+ switch ts .serverState {
630
638
case stateRunning :
631
639
return nil // No-op if server is already running.
632
640
case stateStopped , stateFailed :
@@ -636,7 +644,7 @@ func (ts *testServerImpl) Start() error {
636
644
"Please use NewTestServer()" )
637
645
}
638
646
}
639
- ts .state = stateRunning
647
+ ts .serverState = stateRunning
640
648
ts .mu .Unlock ()
641
649
642
650
for i := 0 ; i < ts .serverArgs .numNodes ; i ++ {
@@ -662,18 +670,18 @@ func (ts *testServerImpl) Stop() {
662
670
ts .mu .RLock ()
663
671
defer ts .mu .RUnlock ()
664
672
665
- if ts .state == stateNew {
673
+ if ts .serverState == stateNew {
666
674
log .Fatalf ("%s: Stop() called, but Start() was never called" , testserverMessagePrefix )
667
675
}
668
- if ts .state == stateFailed {
676
+ if ts .serverState == stateFailed {
669
677
log .Fatalf ("%s: Stop() called, but process exited unexpectedly. Stdout:\n %s\n Stderr:\n %s\n " ,
670
678
testserverMessagePrefix ,
671
679
ts .Stdout (),
672
680
ts .Stderr ())
673
681
return
674
682
}
675
683
676
- if ts .state != stateStopped {
684
+ if ts .serverState != stateStopped {
677
685
if p := ts .proxyProcess ; p != nil {
678
686
_ = p .Kill ()
679
687
}
@@ -686,16 +694,15 @@ func (ts *testServerImpl) Stop() {
686
694
log .Printf ("%s: failed to close stderr: %v" , testserverMessagePrefix , closeErr )
687
695
}
688
696
689
- for _ , cmd := range ts .cmd {
697
+ ts .serverState = stateStopped
698
+ for _ , node := range ts .nodes {
699
+ cmd := node .startCmd
690
700
if cmd .Process != nil {
691
701
_ = cmd .Process .Kill ()
692
702
}
693
- }
694
703
695
- ts .state = stateStopped
696
- for _ , nodeState := range ts .nodeStates {
697
- if nodeState != stateStopped {
698
- ts .state = stateFailed
704
+ if node .state != stateStopped {
705
+ ts .serverState = stateFailed
699
706
}
700
707
}
701
708
0 commit comments