Exemple #1
0
func TestLocal(test *testing.T) {
	ctrl := gomock.NewController(test)
	defer ctrl.Finish()

	store := mock_state.NewMockStore(ctrl)

	store.EXPECT().Read("states", "something", gomock.Any()).Return(fakeErr).Times(2)
	store.EXPECT().Write("states", "something", gomock.Any()).Return(fakeErr)

	out, err := state.NewLocalState("something", "wherever", "//here", store)
	if err == nil {
		test.Log("should have gotten an error", out, err)
		test.FailNow()
	}

	store.EXPECT().Write("states", "something", gomock.Any()).Return(nil)
	local, err := state.NewLocalState("something", "wherever", "//here", store)
	if err != nil {
		test.Log(err)
		test.FailNow()
	}

	testState(local, store, test)

	// now for specific tests to local
	store.EXPECT().Write("states", "something", gomock.Any())
	err = local.SetDBRole("testing")
	if err != nil {
		test.Log(err)
		test.FailNow()
	}

	dbRole, err := local.GetDBRole()
	if err != nil {
		test.Log(err)
		test.FailNow()
	}
	if dbRole != "testing" {
		test.Log("wrong dbrole was returned")
		test.Fail()
	}

	if local.Location() != "wherever" {
		test.Log("wrong location was returned")
		test.Fail()
	}
}
Exemple #2
0
func TestRpc(test *testing.T) {
	ctrl := gomock.NewController(test)
	defer ctrl.Finish()

	store := mock_state.NewMockStore(ctrl)

	store.EXPECT().Read("states", "something", gomock.Any()).Return(fakeErr)
	store.EXPECT().Write("states", "something", gomock.Any()).Return(nil)
	local, err := state.NewLocalState("something", "wherever", "//here", store)
	if err != nil {
		test.Log(err)
		test.FailNow()
	}

	_, err = local.ExposeRPCEndpoint("tcp", "127.0.0.1:1234")
	if err != nil {
		test.Log(err)
		test.FailNow()
	}
	// I don't know why this causes the tests to fail
	// defer listen.Close()

	client := state.NewRemoteState("tcp", "127.0.0.1:1234", time.Second)

	testState(client, store, test)

	// now for tests specific to remote states

	err = client.SetDBRole("testing")
	if err == nil {
		test.Log("should not have been able to update the db state from remote")
		test.Fail()
	}

	if client.Location() != "127.0.0.1:1234" {
		test.Log("wrong location was returned")
		test.Fail()
	}
}
Exemple #3
0
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]))
			}
		}
	}
}
Exemple #4
0
func TestBounce(test *testing.T) {
	ctrl := gomock.NewController(test)
	defer ctrl.Finish()

	store := mock_state.NewMockStore(ctrl)

	store.EXPECT().Read("states", "here", gomock.Any()).Return(fakeErr)
	store.EXPECT().Write("states", "here", gomock.Any()).Return(nil)
	local, err := state.NewLocalState("here", "right here", "//other", store)
	if err != nil {
		test.Log(err)
		test.FailNow()
	}

	listen, err := local.ExposeRPCEndpoint("tcp", "127.0.0.1:2345")
	if err != nil {
		test.Log(err)
		test.FailNow()
	}
	defer listen.Close()

	store.EXPECT().Read("states", "something", gomock.Any()).Return(fakeErr)
	store.EXPECT().Write("states", "something", gomock.Any()).Return(nil)
	remote, err := state.NewLocalState("something", "wherever", "//here", store)
	if err != nil {
		test.Log(err)
		test.FailNow()
	}

	testState(remote, store, test)
	test.Logf("now for the remote")

	// this needs to be reset
	remote.SetSynced(false)

	listen1, err := remote.ExposeRPCEndpoint("tcp", "127.0.0.1:3456")
	if err != nil {
		test.Log(err)
		test.FailNow()
	}
	defer listen1.Close()

	client := state.NewRemoteState("tcp", "127.0.0.1:2345", time.Second)

	bounced := client.Bounce("127.0.0.1:3456")

	testState(bounced, store, test)

	// now for tests specific to remote states

	err = bounced.SetDBRole("testing")
	if err == nil {
		test.Log("should not have been able to update the db state from remote")
		test.Fail()
	}

	if bounced.Location() != "127.0.0.1:3456" {
		test.Log("wrong location was returned")
		test.Fail()
	}
}