vitess.io/vitess@v0.16.2/go/test/endtoend/recovery/pitr/binlog_server.go (about)

     1  /*
     2  Copyright 2020 The Vitess Authors.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package pitr
    18  
    19  import (
    20  	"fmt"
    21  	"os"
    22  	"os/exec"
    23  	"path"
    24  	"strings"
    25  	"syscall"
    26  	"time"
    27  
    28  	"vitess.io/vitess/go/vt/log"
    29  )
    30  
    31  const (
    32  	binlogExecutableName = "rippled"
    33  	binlogDataDir        = "binlog_dir"
    34  	binlogUser           = "ripple"
    35  	binlogPassword       = "ripplepassword"
    36  	binlogPasswordHash   = "D4CDF66E273494CEA9592162BEBB6D62D94C4168"
    37  )
    38  
    39  type binLogServer struct {
    40  	hostname       string
    41  	port           int
    42  	username       string
    43  	password       string
    44  	passwordHash   string
    45  	dataDirectory  string
    46  	executablePath string
    47  
    48  	proc *exec.Cmd
    49  	exit chan error
    50  }
    51  
    52  type mysqlSource struct {
    53  	hostname string
    54  	port     int
    55  	username string
    56  	password string
    57  }
    58  
    59  // newBinlogServer returns an instance of binlog server
    60  func newBinlogServer(hostname string, port int) (*binLogServer, error) {
    61  	dataDir := path.Join(os.Getenv("VTDATAROOT"), fmt.Sprintf("%s_%d", binlogDataDir, port))
    62  	fmt.Println(dataDir)
    63  	if _, err := os.Stat(dataDir); os.IsNotExist(err) {
    64  		err := os.Mkdir(dataDir, 0700)
    65  		if err != nil {
    66  			log.Error(err)
    67  			return nil, err
    68  		}
    69  	}
    70  	return &binLogServer{
    71  		executablePath: path.Join(os.Getenv("EXTRA_BIN"), binlogExecutableName),
    72  		dataDirectory:  dataDir,
    73  		username:       binlogUser,
    74  		password:       binlogPassword,
    75  		passwordHash:   binlogPasswordHash,
    76  		hostname:       hostname,
    77  		port:           port,
    78  	}, nil
    79  }
    80  
    81  // start starts the binlog server points to running mysql port
    82  func (bs *binLogServer) start(source mysqlSource) error {
    83  	bs.proc = exec.Command(
    84  		bs.executablePath,
    85  		fmt.Sprintf("-ripple_datadir=%s", bs.dataDirectory),
    86  		fmt.Sprintf("-ripple_server_password_hash=%s", bs.passwordHash),
    87  		fmt.Sprintf("-ripple_master_address=%s", source.hostname),
    88  		fmt.Sprintf("-ripple_master_port=%d", source.port),
    89  		fmt.Sprintf("-ripple_master_user=%s", source.username),
    90  		fmt.Sprintf("-ripple_server_ports=%d", bs.port),
    91  	)
    92  	if source.password != "" {
    93  		bs.proc.Args = append(bs.proc.Args, fmt.Sprintf("-ripple_master_password=%s", source.password))
    94  	}
    95  
    96  	errFile, _ := os.Create(path.Join(bs.dataDirectory, "log.txt"))
    97  	bs.proc.Stderr = errFile
    98  
    99  	bs.proc.Env = append(bs.proc.Env, os.Environ()...)
   100  
   101  	log.Infof("Running binlog server with command: %v", strings.Join(bs.proc.Args, " "))
   102  
   103  	err := bs.proc.Start()
   104  	if err != nil {
   105  		return err
   106  	}
   107  	bs.exit = make(chan error)
   108  	go func() {
   109  		if bs.proc != nil {
   110  			bs.exit <- bs.proc.Wait()
   111  		}
   112  	}()
   113  	return nil
   114  }
   115  
   116  func (bs *binLogServer) stop() error {
   117  	if bs.proc == nil || bs.exit == nil {
   118  		return nil
   119  	}
   120  	// Attempt graceful shutdown with SIGTERM first
   121  	bs.proc.Process.Signal(syscall.SIGTERM)
   122  
   123  	select {
   124  	case err := <-bs.exit:
   125  		bs.proc = nil
   126  		return err
   127  
   128  	case <-time.After(10 * time.Second):
   129  		bs.proc.Process.Kill()
   130  		bs.proc = nil
   131  		return <-bs.exit
   132  	}
   133  }