From 064c5bd7ee0b8cfba28707fba2f2bd3507d1c9d6 Mon Sep 17 00:00:00 2001 From: jc3wish <> Date: Sun, 25 Feb 2024 21:16:27 +0800 Subject: [PATCH 1/4] fixed output starrocks varchar(255) tansfer error bug https://github.com/brokercap/Bifrost/issues/266 --- plugin/mysql/src/transfer.go | 12 +- plugin/mysql/src/transfer_test.go | 183 ++++++++++++++++++++++++++++++ plugin/mysql/src/version.go | 4 +- 3 files changed, 193 insertions(+), 6 deletions(-) create mode 100644 plugin/mysql/src/transfer_test.go diff --git a/plugin/mysql/src/transfer.go b/plugin/mysql/src/transfer.go index 167658d4..9bb99b39 100644 --- a/plugin/mysql/src/transfer.go +++ b/plugin/mysql/src/transfer.go @@ -149,15 +149,15 @@ func (This *Conn) TransferToTypeByColumnType_Starrocks(columnType string, nullab toType = "VARCHAR(20)" case "int64": toType = "BIGINT(20)" - case "uint32", "uint24": + case "uint32": toType = "BIGINT(20)" - case "int32", "int24": + case "int32", "int24", "uint24": toType = "INT(11)" case "uint16": toType = "INT(11)" case "int16", "year(4)", "year(2)", "year": toType = "SMALLINT(6)" - case "uint8", "SMALLINT(uint8)": + case "uint8": toType = "SMALLINT(6)" case "int8", "bool": toType = "TINYINT(4)" @@ -227,7 +227,11 @@ func (This *Conn) TransferToTypeByColumnType_Starrocks(columnType string, nullab if lenStr == "" { toType = "VARCHAR(255)" } else { - toType = fmt.Sprintf("CHAR(%s)", lenStr) + if i == 0 { + toType = fmt.Sprintf("CHAR(%s)", lenStr) + } else { + toType = fmt.Sprintf("VARCHAR(%s)", lenStr) + } } break } diff --git a/plugin/mysql/src/transfer_test.go b/plugin/mysql/src/transfer_test.go new file mode 100644 index 00000000..fa23503b --- /dev/null +++ b/plugin/mysql/src/transfer_test.go @@ -0,0 +1,183 @@ +package src + +import ( + "testing" + + . "github.com/smartystreets/goconvey/convey" +) + +func TestTransferToTypeByColumnType_Starrocks(t *testing.T) { + type ColumnTypeStruct struct { + columnTypeList []string + nullable bool + destColumnType string + } + var caseList = []ColumnTypeStruct{ + { + columnTypeList: []string{"uint64"}, + nullable: false, + destColumnType: "VARCHAR(20)", + }, + { + columnTypeList: []string{"int64", "uint32"}, + nullable: false, + destColumnType: "BIGINT(20)", + }, + { + columnTypeList: []string{"int32", "uint24", "int24", "uint16"}, + nullable: false, + destColumnType: "INT(11)", + }, + { + columnTypeList: []string{"int16", "year(4)", "year(2)", "year", "uint8"}, + nullable: false, + destColumnType: "SMALLINT(6)", + }, + { + columnTypeList: []string{"int8", "bool"}, + nullable: false, + destColumnType: "TINYINT(4)", + }, + { + columnTypeList: []string{"float"}, + nullable: false, + destColumnType: "FLOAT", + }, + { + columnTypeList: []string{"double", "real"}, + nullable: false, + destColumnType: "DOUBLE", + }, + { + columnTypeList: []string{"decimal", "numeric"}, + nullable: false, + destColumnType: "DECIMAL", + }, + { + columnTypeList: []string{"decimal(9,2)"}, + nullable: false, + destColumnType: "Decimal(9,2)", + }, + { + columnTypeList: []string{"decimal(19,5)"}, + nullable: false, + destColumnType: "Decimal(19,5)", + }, + { + columnTypeList: []string{"decimal(38,2)"}, + nullable: false, + destColumnType: "Decimal(38,2)", + }, + { + columnTypeList: []string{"decimal(39,2)"}, + nullable: false, + destColumnType: "VARCHAR(78)", + }, + { + columnTypeList: []string{"decimal(88,2)"}, + nullable: false, + destColumnType: "VARCHAR(255)", + }, + { + columnTypeList: []string{"date", "Nullable(date)"}, + nullable: false, + destColumnType: "DATE", + }, + { + columnTypeList: []string{"json"}, + nullable: false, + destColumnType: "JSON", + }, + { + columnTypeList: []string{"time"}, + nullable: false, + destColumnType: "VARCHAR(10)", + }, + { + columnTypeList: []string{"enum"}, + nullable: false, + destColumnType: "VARCHAR(255)", + }, + { + columnTypeList: []string{"set"}, + nullable: false, + destColumnType: "VARCHAR(2048)", + }, + { + columnTypeList: []string{"string", "longblob", "longtext"}, + nullable: false, + destColumnType: "VARCHAR(163841)", + }, + { + columnTypeList: []string{"double(9,2)", "real(10,2)"}, + nullable: false, + destColumnType: "DOUBLE", + }, + { + columnTypeList: []string{"float(9,2)"}, + nullable: false, + destColumnType: "FLOAT", + }, + { + columnTypeList: []string{"bit"}, + nullable: false, + destColumnType: "BIGINT(20)", + }, + { + columnTypeList: []string{"timestamp(6)", "datetime(3)"}, + nullable: false, + destColumnType: "DATETIME", + }, + { + columnTypeList: []string{"time(6)", "time(1)"}, + nullable: false, + destColumnType: "VARCHAR(16)", + }, + { + columnTypeList: []string{"enum('a','b')"}, + nullable: false, + destColumnType: "VARCHAR(255)", + }, + { + columnTypeList: []string{"set('a','b')"}, + nullable: false, + destColumnType: "VARCHAR(2048)", + }, + { + columnTypeList: []string{"char(1)"}, + nullable: false, + destColumnType: "CHAR(1)", + }, + { + columnTypeList: []string{"char(255)"}, + nullable: false, + destColumnType: "CHAR(255)", + }, + { + columnTypeList: []string{"varchar(500)"}, + nullable: false, + destColumnType: "VARCHAR(500)", + }, + + { + columnTypeList: []string{"Nullable(varchar(500))"}, + nullable: false, + destColumnType: "VARCHAR(500)", + }, + { + columnTypeList: []string{"Nullable(int64)"}, + nullable: true, + destColumnType: "BIGINT(20) DEFAULT NULL", + }, + } + + c := &Conn{} + for _, caseInfo := range caseList { + for _, columnType := range caseInfo.columnTypeList { + Convey(caseInfo.destColumnType, t, func() { + toDestColumnType := c.TransferToTypeByColumnType_Starrocks(columnType, caseInfo.nullable) + So(toDestColumnType, ShouldEqual, caseInfo.destColumnType) + }) + } + } +} diff --git a/plugin/mysql/src/version.go b/plugin/mysql/src/version.go index 26d89730..9fe92f4d 100644 --- a/plugin/mysql/src/version.go +++ b/plugin/mysql/src/version.go @@ -1,4 +1,4 @@ package src -const VERSION = "v2.2.0" -const BIFROST_VERION = "v2.2.0" +const VERSION = "v2.3.5" +const BIFROST_VERION = "v2.3.4" From ec609d7ac9f574dc4b460d498d2e7353f183f2d8 Mon Sep 17 00:00:00 2001 From: jc3wish <> Date: Fri, 5 Apr 2024 12:05:58 +0800 Subject: [PATCH 2/4] record first boot time --- Bifrost.go | 108 +++++++++++++++--------------- admin/controller/index.go | 1 + admin/view/template/index.html | 9 ++- server/recovery_test.go | 33 +++++++--- server/server.go | 33 ++++++++++ server/server_save_recovery.go | 116 +++++++++++++++++---------------- server/server_test.go | 64 ++++++++++++++++++ 7 files changed, 243 insertions(+), 121 deletions(-) create mode 100644 server/server.go create mode 100644 server/server_test.go diff --git a/Bifrost.go b/Bifrost.go index c7cbbd4c..41320782 100755 --- a/Bifrost.go +++ b/Bifrost.go @@ -53,18 +53,19 @@ ___ ___ _ 纪念2022.08.28认识Monty并合影 ` -func printLogo(){ + +func printLogo() { var IpAndPort2 string //IpAndPort2 = strings.Replace(IpAndPort,"0.0.0.0","127.0.0.1",-1) if config.TLS { - IpAndPort2 = "https://"+config.Listen - }else{ - IpAndPort2 = "http://"+config.Listen + IpAndPort2 = "https://" + config.Listen + } else { + IpAndPort2 = "http://" + config.Listen } - logo = strings.Replace(logo,"{$version}",config.VERSION,-1) - logo = strings.Replace(logo,"{$Port}",IpAndPort2,-1) - logo = strings.Replace(logo,"{$Pid}",fmt.Sprint(os.Getpid()),-1) - logo = strings.Replace(logo,"{$system}",fmt.Sprint(runtime.GOARCH),-1) + logo = strings.Replace(logo, "{$version}", config.VERSION, -1) + logo = strings.Replace(logo, "{$Port}", IpAndPort2, -1) + logo = strings.Replace(logo, "{$Pid}", fmt.Sprint(os.Getpid()), -1) + logo = strings.Replace(logo, "{$system}", fmt.Sprint(runtime.GOARCH), -1) fmt.Println(logo) } @@ -80,33 +81,32 @@ Options: } func main() { - var BifrostConfigFile string var BifrostPid string var BifrostDataDir string var Version bool var Help bool defer func() { doSeverDbInfoFun() - if os.Getppid() == 1 && config.BifrostPidFile != ""{ + if os.Getppid() == 1 && config.BifrostPidFile != "" { os.Remove(config.BifrostPidFile) } - if err := recover();err != nil{ + if err := recover(); err != nil { log.Println(err) log.Println(string(debug.Stack())) return } }() - flag.StringVar(&BifrostConfigFile,"config", "", "-config") - flag.StringVar(&BifrostPid,"pid", "", "-pid") + flag.StringVar(&config.BifrostConfigFile, "config", "", "-config") + flag.StringVar(&BifrostPid, "pid", "", "-pid") flag.BoolVar(&BifrostDaemon, "d", false, "-d") - flag.StringVar(&BifrostDataDir,"data_dir", "", "-data_dir") + flag.StringVar(&BifrostDataDir, "data_dir", "", "-data_dir") flag.BoolVar(&Version, "v", false, "-v") flag.BoolVar(&Help, "h", false, "-h") flag.Usage = usage flag.Parse() - if Help{ + if Help { flag.Usage() os.Exit(0) } @@ -120,18 +120,18 @@ func main() { if os.Getppid() != 1 && runtime.GOOS != "windows" { // 因为有一些桌面系统,父进程开了子进程之后,父进程退出之后,并不是由 pid=1 的 systemd 进程接管,可能有些系统给每个桌面帐号重新分配了一下systemd 进程 // 这里每去判断 一下是不是 systemd 进程名,如果是的话,也认为是父进程被退出了 - cmdString := "ps -ef|grep "+strconv.Itoa(os.Getppid())+" | grep systemd|grep -v grep" - resultBytes,err := CmdShell(cmdString) - if err == nil && resultBytes != nil && string(resultBytes) != ""{ + cmdString := "ps -ef|grep " + strconv.Itoa(os.Getppid()) + " | grep systemd|grep -v grep" + resultBytes, err := CmdShell(cmdString) + if err == nil && resultBytes != nil && string(resultBytes) != "" { isDaemoProcess = true } - }else { + } else { isDaemoProcess = true } if !isDaemoProcess { - filePath,_:=filepath.Abs(os.Args[0]) //将命令行参数中执行文件路径转换成可用路径 - args:=append([]string{filePath},os.Args[1:]...) - os.StartProcess(filePath,args,&os.ProcAttr{Files:[]*os.File{os.Stdin,os.Stdout,os.Stderr}}) + filePath, _ := filepath.Abs(os.Args[0]) //将命令行参数中执行文件路径转换成可用路径 + args := append([]string{filePath}, os.Args[1:]...) + os.StartProcess(filePath, args, &os.ProcAttr{Files: []*os.File{os.Stdin, os.Stdout, os.Stderr}}) return } if config.BifrostPidFile == "" { @@ -139,18 +139,18 @@ func main() { } } - config.LoadConf(BifrostConfigFile) + config.LoadConf(config.BifrostConfigFile) if BifrostDataDir != "" { - config.SetConfigVal("Bifrostd","data_dir",BifrostDataDir) + config.SetConfigVal("Bifrostd", "data_dir", BifrostDataDir) } if BifrostPid != "" { - config.SetConfigVal("Bifrostd","pid",BifrostPid) + config.SetConfigVal("Bifrostd", "pid", BifrostPid) } config.InitParam() if !BifrostDaemon { printLogo() - }else{ + } else { printLogo() initLog() fmt.Printf("Please press the `Enter`\r") @@ -163,7 +163,7 @@ func main() { plugin.DoDynamicPlugin() server.InitStorage() - log.Println("Server started, Bifrost version",config.VERSION) + log.Println("Server started, Bifrost version", config.VERSION) doRecovery() @@ -171,41 +171,41 @@ func main() { ListenSignal() } -func initLog(){ - os.MkdirAll(config.BifrostLogDir,0700) +func initLog() { + os.MkdirAll(config.BifrostLogDir, 0700) t := time.Now().Format("2006-01-02") - LogFileName := config.BifrostLogDir+"/Bifrost_"+t+".log" + LogFileName := config.BifrostLogDir + "/Bifrost_" + t + ".log" f, err := os.OpenFile(LogFileName, os.O_CREATE|os.O_RDWR|os.O_APPEND, 0700) //打开文件 - if err != nil{ - log.Println("log init error:",err) + if err != nil { + log.Println("log init error:", err) } log.SetOutput(f) - fmt.Println("log input to",LogFileName) + fmt.Println("log input to", LogFileName) } -func WritePid(){ +func WritePid() { if config.BifrostPidFile == "" { return } var err error var pidFileFd *os.File pidFileFd, err = os.OpenFile(config.BifrostPidFile, os.O_CREATE|os.O_RDWR, 0700) //打开文件 - if err !=nil{ - log.Println("Open BifrostPid Error; File:",config.BifrostPidFile,"; Error:",err) + if err != nil { + log.Println("Open BifrostPid Error; File:", config.BifrostPidFile, "; Error:", err) os.Exit(1) return } defer pidFileFd.Close() pidContent, err2 := ioutil.ReadAll(pidFileFd) - if string(pidContent) != ""{ + if string(pidContent) != "" { ExitBool := true - cmdString := "ps -ef|grep "+string(pidContent)+" | grep "+filepath.Base(os.Args[0]+"|grep -v grep") - resultBytes,err := CmdShell(cmdString) + cmdString := "ps -ef|grep " + string(pidContent) + " | grep " + filepath.Base(os.Args[0]+"|grep -v grep") + resultBytes, err := CmdShell(cmdString) // err 不为 nil 则代表没有grep 到进程,可以认为有可能被 kill -9 等操作了 - if err != nil && resultBytes != nil{ + if err != nil && resultBytes != nil { ExitBool = false - }else{ - log.Println(cmdString," result:",string(resultBytes)," err:",err,) + } else { + log.Println(cmdString, " result:", string(resultBytes), " err:", err) } if ExitBool { log.Println("Birostd server quit without updating PID file ; File:", config.BifrostPidFile, "; Error:", err2) @@ -213,34 +213,34 @@ func WritePid(){ } } os.Truncate(config.BifrostPidFile, 0) - pidFileFd.Seek(0,0) - io.WriteString(pidFileFd,fmt.Sprint(os.Getpid())) + pidFileFd.Seek(0, 0) + io.WriteString(pidFileFd, fmt.Sprint(os.Getpid())) } -func CmdShell(cmdString string)([]byte,error){ +func CmdShell(cmdString string) ([]byte, error) { switch runtime.GOOS { - case "linux","darwin","freebsd": + case "linux", "darwin", "freebsd": cmd := exec.Command("/bin/bash", "-c", cmdString) return cmd.Output() break default: break } - return nil,fmt.Errorf(runtime.GOOS+" not supported") + return nil, fmt.Errorf(runtime.GOOS + " not supported") } -func doSaveDbInfo(){ - if os.Getppid() != 1 && BifrostDaemon{ +func doSaveDbInfo() { + if os.Getppid() != 1 && BifrostDaemon { return } server.DoSaveSnapshotData() } -func doRecovery(){ +func doRecovery() { server.DoRecoverySnapshotData() } -func doSeverDbInfoFun() { +func doSeverDbInfoFun() { log.Println("save db server info data start... ") defer func() { if err := recover(); err != nil { @@ -260,15 +260,15 @@ func doSeverDbInfoFun() { log.Println("save db server info data success! ") } -func ListenSignal(){ +func ListenSignal() { signals := make(chan os.Signal, 1) signal.Notify(signals, syscall.SIGHUP, syscall.SIGTERM, syscall.SIGINT) for sig := range signals { - if sig == nil{ + if sig == nil { continue } doSeverDbInfoFun() - if config.BifrostPidFile != ""{ + if config.BifrostPidFile != "" { os.Remove(config.BifrostPidFile) } os.Exit(0) diff --git a/admin/controller/index.go b/admin/controller/index.go index 94314b7d..ffd4121e 100644 --- a/admin/controller/index.go +++ b/admin/controller/index.go @@ -43,6 +43,7 @@ type IndexController struct { // 首页 func (c *IndexController) Index() { c.SetTitle("Index") + c.SetData("ServerStartTime", server.GetServerStartTime().Format("2006-01-02")) c.AddAdminTemplate("index.html", "header.html", "footer.html") } diff --git a/admin/view/template/index.html b/admin/view/template/index.html index f4998484..32a7c62d 100644 --- a/admin/view/template/index.html +++ b/admin/view/template/index.html @@ -355,7 +355,7 @@