func start(me, other *mock_state.MockState, test *testing.T) *performer { // i need to create a tmp folder // start a action // then have it transition to different states. // overwrite the builtin config options config.Conf = config.Config{ PGPort: 4567, DataDir: os.TempDir() + "/postgres/", StatusDir: os.TempDir() + "/postgres/", SyncCommand: "true", SystemUser: config.SystemUser(), } perform := NewPerformer(me, other, config.Conf) // ignore all errors that come across this way go func() { <-perform.err }() err := perform.Initialize() if err != nil { test.Log(err) test.FailNow() } if err := config.ConfigureHBAConf("127.0.0.1"); err != nil { test.Log(err) test.FailNow() } if err := config.ConfigurePGConf("127.0.0.1", config.Conf.PGPort); err != nil { test.Log(err) test.FailNow() } err = perform.Start() if err != nil { test.Log(err) test.FailNow() } return perform }
func main() { if len(os.Args) != 2 { fmt.Println("Missing required config file!") fmt.Println("Please, run yoke with configuration file as argument (e.g. $ yoke /etc/yoke/yoke.ini)") os.Exit(1) } config.Init(os.Args[1]) config.ConfigurePGConf("0.0.0.0", config.Conf.PGPort) store, err := scribble.New(config.Conf.StatusDir, config.Log) if err != nil { config.Log.Fatal("Scribble did not setup correctly: %v", err) os.Exit(1) } location := fmt.Sprintf("%v:%d", config.Conf.AdvertiseIp, config.Conf.AdvertisePort) me, err := state.NewLocalState(config.Conf.Role, location, config.Conf.DataDir, store) if err != nil { config.Log.Fatal("Failed to set local state: %v", err) os.Exit(1) } me.ExposeRPCEndpoint("tcp", location) var other state.State var host string switch config.Conf.Role { case "primary": location := config.Conf.Secondary other = state.NewRemoteState("tcp", location, time.Second) host, _, err = net.SplitHostPort(location) if err != nil { config.Log.Fatal("Failed to split host:port for primary node: %v", err) os.Exit(1) } case "secondary": location := config.Conf.Primary other = state.NewRemoteState("tcp", location, time.Second) host, _, err = net.SplitHostPort(location) if err != nil { config.Log.Fatal("Failed to split host:port for secondary node: %v", err) os.Exit(1) } default: // nothing as the monitor does not need to monitor anything // the monitor just acts as a secondary mode of communication in network // splits } mon := state.NewRemoteState("tcp", config.Conf.Monitor, time.Second) var perform monitor.Performer finished := make(chan error) if other != nil { perform = monitor.NewPerformer(me, other, config.Conf) if err := perform.Initialize(); err != nil { config.Log.Fatal("Failed to initialize database: %v", err) os.Exit(1) } if err := config.ConfigureHBAConf(host); err != nil { config.Log.Fatal("Failed to configure pg_hba.conf file: %v", err) os.Exit(1) } if err := config.ConfigurePGConf("0.0.0.0", config.Conf.PGPort); err != nil { config.Log.Fatal("Failed to configure postgresql.conf file: %v", err) os.Exit(1) } if err := perform.Start(); err != nil { config.Log.Fatal("Failed to start postgres: %v", err) os.Exit(1) } go func() { decide := monitor.NewDecider(me, other, mon, perform) decide.Loop(time.Second * 2) }() go func() { err := perform.Loop() if err != nil { finished <- err } // how do I stop the decide loop? close(finished) }() } // signal Handle signals := make(chan os.Signal, 1) signal.Notify(signals, syscall.SIGINT, syscall.SIGTERM, os.Kill, syscall.SIGQUIT, syscall.SIGALRM) // Block until a signal is received. for { select { case err := <-finished: if err != nil { config.Log.Fatal("The performer is finished, something triggered a stop: %v", err) os.Exit(1) } config.Log.Info("the database was shut down") return case signal := <-signals: switch signal { case syscall.SIGINT, os.Kill, syscall.SIGQUIT, syscall.SIGTERM: config.Log.Info("shutting down") if perform != nil { // stop the database, then wait for it to be stopped config.Log.Info("shutting down the database") perform.Stop() perform = nil config.Log.Info("waiting for the database") } else { return } case syscall.SIGALRM: config.Log.Info("Printing Stack Trace") stacktrace := make([]byte, 8192) length := runtime.Stack(stacktrace, true) fmt.Println(string(stacktrace[:length])) } } } }