Пример #1
0
// This is the only user-facing function, and accordingly the body is
// a raw string rather than JSON.
func (s *Server) sqlHandler(w http.ResponseWriter, req *http.Request) {
	state := s.cluster.State()
	if state != "primary" {
		http.Error(w, "Only the primary can service queries, but this is a "+state, http.StatusBadRequest)
		return
	}

	query, err := ioutil.ReadAll(req.Body)
	if err != nil {
		log.Printf("Couldn't read body: %s", err)
		http.Error(w, err.Error(), http.StatusBadRequest)
	}

	log.Debugf("[%s] Received query: %#v", s.cluster.State(), string(query))
	resp, err := s.execute(query)
	if err != nil {
		http.Error(w, err.Error(), http.StatusBadRequest)
	}

	r := &Replicate{
		Self:  s.cluster.self,
		Query: query,
	}
	for _, member := range s.cluster.members {
		b := util.JSONEncode(r)
		_, err := s.client.SafePost(member.ConnectionString, "/replicate", b)
		if err != nil {
			log.Printf("Couldn't replicate query to %v: %s", member, err)
		}
	}

	log.Debugf("[%s] Returning response to %#v: %#v", s.cluster.State(), string(query), string(resp))
	w.Write(resp)
}
Пример #2
0
func (s *Server) forwardQueryToLeader(query *sql.Query) {
	if s.raftServer.Leader() == s.name {
		// I am the leader, don't send it
		return
	}

	cs, err := s.GetLeaderCS()

	if err != nil {
		//log.Printf("Can't find leader to forward query")
		// Can't find leader
		return
	}

	var buffer bytes.Buffer
	compress := gzip.NewWriter(&buffer)

	err = EncodeObjToResponse(compress, query)

	compress.Close()

	if err != nil {
		log.Printf("Can't encode object to forward")
	}

	_, err = s.client.SafePost(cs, "/forward", "application/json", &buffer)

	if err != nil {
		log.Printf("Failed to forward query")
	}

}
Пример #3
0
// This is the only user-facing function, and accordingly the body is
// a raw string rather than JSON.
func (s *Server) sqlHandler(w http.ResponseWriter, req *http.Request) {
	query, err := ioutil.ReadAll(req.Body)
	if err != nil {
		log.Printf("Couldn't read body: %s", err)
		http.Error(w, err.Error(), http.StatusBadRequest)
		return
	}

	log.Debugf("[%s] Received query: %#v", s.raftServer.State(), string(query))

	// Execute the command against the Raft server.
	leader := s.raftServer.Leader()
	for leader == "" {
		time.Sleep(50 * time.Millisecond)
		leader = s.raftServer.Leader()
	}
	if s.name != leader {
		my_partial_name := strings.TrimSuffix(strings.TrimPrefix(s.name, ".-"), ".sock")
		leader_partial_name := strings.TrimSuffix(strings.TrimPrefix(leader, ".-"), ".sock")
		redirect_url := "http://" + strings.Replace(req.Host, my_partial_name, leader_partial_name, -1) + "/forward?query=" + encodeQuery(query)
		log.Printf("Redirecting to %s", redirect_url)
		http.Redirect(w, req, redirect_url, 302)
		return
	}

	resp, err := s.raftServer.Do(NewSqlCommand(string(query)))
	if err != nil {
		http.Error(w, err.Error(), http.StatusBadRequest)
		return
	}
	resp_frd := resp.([]byte)
	log.Debugf("[%s] Returning response to %#v: %#v", s.raftServer.State(), string(query), string(resp_frd))
	w.Write(resp_frd)
}
Пример #4
0
// Join an existing cluster
func (s *Server) Join(primary string) error {

	command := &raft.DefaultJoinCommand{
		Name:             s.raftServer.Name(),
		ConnectionString: s.connectionString(),
	}

	var b bytes.Buffer
	json.NewEncoder(&b).Encode(command)

	cs, err := transport.Encode(primary)
	if err != nil {
		return err
	}

	log.Printf("Server %v with cs=%v is trying to join %v on %s/join", s.raftServer.Name(), s.connectionString(), primary, cs)

	for {
		_, err := s.client.SafePost(cs, "/join", &b)
		if err != nil {
			log.Printf("Unable to join cluster: %s", err)
			time.Sleep(1 * time.Second)
			continue
		}
		return nil
	}
}
Пример #5
0
// This is the only user-facing function, and accordingly the body is
// a raw string rather than JSON.
func (s *Server) sqlHandler(w http.ResponseWriter, req *http.Request) {
	if s.block {
		time.Sleep(1000000 * time.Second)
	}

	query, err := ioutil.ReadAll(req.Body)
	if err != nil {
		log.Printf("Couldn't read body: %s", err)
		http.Error(w, err.Error(), http.StatusBadRequest)
	}

	if s.leader != s.listen {

		cs, errLeader := transport.Encode(s.leader)

		if errLeader != nil {
			http.Error(w, "Only the primary can service queries, but this is a secondary", http.StatusBadRequest)
			log.Printf("Leader ain't present?: %s", errLeader)
			return
		}

		//_, errLeaderHealthCheck := s.client.SafeGet(cs, "/healthcheck")

		//if errLeaderHealthCheck != nil {
		//    http.Error(w, "Primary is down", http.StatusBadRequest)
		//    return
		//}

		body, errLResp := s.client.SafePost(cs, "/sql", bytes.NewBufferString(string(query)))
		if errLResp != nil {
			s.block = true
			http.Error(w, "Can't forward request to primary, gotta block now", http.StatusBadRequest)
			return
			//	        log.Printf("Didn't get reply from leader: %s", errLResp)
		}

		formatted := fmt.Sprintf("%s", body)
		resp := []byte(formatted)

		w.Write(resp)
		return

	} else {

		log.Debugf("Primary Received query: %#v", string(query))
		resp, err := s.execute(query)
		if err != nil {
			http.Error(w, err.Error(), http.StatusBadRequest)
		}

		w.Write(resp)
		return
	}
}
Пример #6
0
func (s *Server) forwardHandler(w http.ResponseWriter, req *http.Request) {
	log.Printf("############################# forward: Initiating forward loop")
	h, ok := w.(http.Hijacker)
	if !ok {
		log.Printf("########################## forward: Failed to hijack connection for forwarding. Aborting")
		return
	}
	netConn, rw, err := h.Hijack()
	if err != nil {
		log.Printf("######################### forward: Failed to hijack connection for forwarding: %v Aborting", err)
		return
	}
	defer netConn.Close()
	reader := json.NewDecoder(rw)
	writer := json.NewEncoder(rw)
	log.Printf("############################ forward: Forward loop initiated")
	for {
		cmd := <-s.execCommand
		log.Printf("############ Received command to forward: %v", cmd.Data)
		err := writer.Encode(&cmd.Data)
		if err != nil {
			log.Printf("######################### forward: Writer cannot encode command: %v Stopping loop", err)
			return
		}
		reply := &raft.ExecuteCommandReply{}
		err = reader.Decode(reply)
		if err != nil {
			log.Printf("############################ forward: Reader cannot decode command reply: %v Stopping loop", err)
			return
		}
		log.Printf("############# Received reply via forward: %v", reply)
		cmd.Reply <- reply
	}
}
Пример #7
0
func (c *Cluster) PerformFailover() {
	state := c.State()
	if state != "secondary" {
		log.Fatalf("Trying to fail over even though my state is %s", state)
	}

	c.primary = c.members[0]
	c.members = c.members[1:]

	if c.State() == "primary" {
		log.Printf("I am the the primary now.")
	} else {
		log.Printf("Promoted %s to primary. My time will come one day.", c.primary.Name)
	}
}
Пример #8
0
// Server handlers
func (s *Server) joinHandler(w http.ResponseWriter, req *http.Request) {
	command := &raft.DefaultJoinCommand{}

	if err := json.NewDecoder(req.Body).Decode(&command); err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}

	log.Printf("Handling join request: %#v", command)

	if _, err := s.raftServer.Do(command); err != nil {
		log.Printf("Server was unable to join %v with err=%v", command, err)
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
}
Пример #9
0
func (s *Server) healthCheckPeer(peer *raft.Peer) {
	for {
		delay := HEALTH_CHECK_DELAY
		if s.raftServer.Leader() == s.name {
			delay = LEADER_HEALTH_CHECK_DELAY
		}

		// Endlessly
		response, err := s.client.SafeGet(peer.ConnectionString, "/healthcheck")

		if err != nil {
			continue
		}

		healthResponse := &HealthCheckResponse{}

		// if err := json.NewDecoder(response).Decode(&healthResponse); err != nil {
		// 	log.Fatal(err)
		// 	return
		// }
		err = DecodeResponseToObj(response, &healthResponse)
		if err != nil {
			log.Printf("healthCheckPeer Error: %v", err.Error())
			continue
		}

		s.mergeQueue(healthResponse.Outstanding)

		time.Sleep(delay)
	}
}
Пример #10
0
// Join an existing cluster
func (s *Server) Join(primary string) error {
	join := &Join{Self: s.cluster.self}
	b := util.JSONEncode(join)

	cs, err := transport.Encode(primary)
	if err != nil {
		return err
	}

	for {
		body, err := s.client.SafePost(cs, "/join", b)
		if err != nil {
			log.Printf("Unable to join cluster: %s", err)
			time.Sleep(1 * time.Second)
			continue
		}

		resp := &JoinResponse{}
		if err = util.JSONDecode(body, &resp); err != nil {
			return err
		}

		s.cluster.Join(resp.Self, resp.Members)
		return nil
	}
}
Пример #11
0
// This is the only user-facing function, and accordingly the body is
// a raw string rather than JSON.
func (s *Server) sqlHandler(w http.ResponseWriter, req *http.Request) {
	state := s.cluster.State()
	query, err := ioutil.ReadAll(req.Body)

	if state != "primary" {
		log.Printf("I AM NOT THE PRIMARY, NEED TO FORWARD THIS REQUEST TO MASTER")
		//cs, err := transport.Encode(primary)
		response, err := s.client.SafePost(s.cluster.primary.ConnectionString, "/sql", bytes.NewReader(query))
		if response == nil || err != nil {
			http.Error(w, "", http.StatusBadRequest)
			return
		} else {
			r, _ := ioutil.ReadAll(response)
			w.Write(r)
		}
		//http.Error(w, "Only the primary can service queries, but this is a "+state, http.StatusBadRequest)
		return
	}

	if err != nil {
		log.Printf("Couldn't read body: %s", err)
		http.Error(w, "", http.StatusBadRequest)
	}

	log.Debugf("[%s] Received query: %#v", s.cluster.State(), string(query))
	resp, err := s.execute(query)
	if err != nil {
		http.Error(w, "", http.StatusBadRequest)
	}

	//r := &Replicate{
	//Self:  s.cluster.self,
	//Query: query,
	//}
	//for _, member := range s.cluster.members {
	//b := util.JSONEncode(r)
	//_, err := s.client.SafePost(member.ConnectionString, "/replicate", b)
	//if err != nil {
	//log.Printf("Couldn't replicate query to %v: %s", member, err)
	//}
	//}

	log.Debugf("[%s] Returning response to %#v: %#v", s.cluster.State(), string(query), string(resp))
	w.Write(resp)
}
Пример #12
0
// Server handlers
func (s *Server) joinHandler(w http.ResponseWriter, req *http.Request) {
	log.Printf("handling /join %v", req)
	j := &raft.DefaultJoinCommand{}

	if err := util.JSONDecode(req.Body, j); err != nil {
		log.Printf("Invalid join request: %s", err)
		return
	}

	go func() {
		log.Printf("Handling join request: %#v", j)

		// Add node to the cluster
		if _, err := s.raftServer.Do(j); err != nil {
			return
		}
	}()
}
Пример #13
0
// This is the only user-facing function, and accordingly the body is
// a raw string rather than JSON.
func (s *Server) sqlHandler(w http.ResponseWriter, req *http.Request) {

	query, err := ioutil.ReadAll(req.Body)
	if err != nil {
		log.Printf("Couldn't read body: %s", err)
		http.Error(w, err.Error(), http.StatusBadRequest)
		return
	}
	log.Printf("[%s]Received query: %#v", string(s.raftServer.State()), string(query))

	if s.raftServer.State() != "leader" {
		if s.raftServer.Leader() == "" {
			w.WriteHeader(http.StatusBadRequest)
			return
		}
		leader, _ := transport.Encode(s.raftServer.Leader())
		log.Printf("Relaying query to leader: %v", s.raftServer.Leader())
		relayResp, err := s.client.SafePost(leader, "/sql", bytes.NewReader(query))
		if err != nil {
			http.Error(w, "Only the primary can service queries, relaying failed", http.StatusBadRequest)
			return
		}
		//buf := new(bytes.Buffer)
		//buf.ReadFrom(relayResp)
		w.Write(relayResp.(*bytes.Buffer).Bytes())
		return
	}

	// Execute the command against the Raft server.
	resp, err := s.raftServer.Do(command.NewWriteCommand(string(query)))
	if err != nil {
		log.Printf("Current leader: %#v resp=%v err=%v", string(s.raftServer.Leader()), resp, err)
		http.Error(w, err.Error(), http.StatusBadRequest)
		return
	}

	if formatted, ok := resp.(string); ok {
		log.Printf("Returning response to %#v: %#v", string(query), resp)
		w.Write([]byte(formatted))
	} else {
		w.WriteHeader(http.StatusBadRequest)
	}
}
Пример #14
0
func (s *Server) healthcheckPrimary() bool {
	_, err := s.client.SafeGet(s.cluster.primary.ConnectionString, "/healthcheck")

	if err != nil {
		log.Printf("The primary appears to be down: %s", err)
		return false
	} else {
		return true
	}
}
Пример #15
0
func (s *Server) healthcheckHandler(w http.ResponseWriter, req *http.Request) {
	response := &HealthCheckResponse{
		Outstanding: s.outstanding.GetAll(),
	}

	err := EncodeObjToResponse(w, response)

	if err != nil {
		log.Printf("healthCheckHandler ERror : %v", err.Error())
	}
}
Пример #16
0
func (c *Cluster) AddMember(identity ServerAddress) error {
	state := c.State()
	if state != "primary" {
		return errors.New("Can only join to a primary, but you're talking to a " + state)
	}

	log.Printf("Adding new cluster member %v", identity)
	c.members = append(c.members, identity)

	return nil
}
Пример #17
0
func (s *Server) replicationHandler(w http.ResponseWriter, req *http.Request) {
	r := &Replicate{}
	if err := util.JSONDecode(req.Body, r); err != nil {
		log.Printf("Invalid replication request: %s", err)
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}

	log.Printf("Handling replication request from %v", r.Self)

	_, err := s.execute(r.Query)
	if err != nil {
		http.Error(w, err.Error(), http.StatusBadRequest)
	}

	resp := &ReplicateResponse{
		s.cluster.self,
	}
	b := util.JSONEncode(resp)
	w.Write(b.Bytes())
}
Пример #18
0
// Server handlers
func (s *Server) joinHandler(w http.ResponseWriter, req *http.Request) {
	command := &raft.DefaultJoinCommand{}

	if err := json.NewDecoder(req.Body).Decode(&command); err != nil {
		log.Printf("Invalid join request: %s", err)
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}

	result, err := s.raftServer.Do(command)
	if err != nil {
		log.Printf("Unable to handle join: %s", err)
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}

	if b, ok := result.([]byte); ok {
		log.Printf(string(b))
        w.WriteHeader(http.StatusOK)
        w.Write(b)
	}
}
Пример #19
0
// Server handlers
func (s *Server) joinHandler(w http.ResponseWriter, req *http.Request) {
	j := &Join{}
	if err := util.JSONDecode(req.Body, j); err != nil {
		log.Printf("Invalid join request: %s", err)
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}

	log.Printf("Handling join request: %#v", j)

	// Add node to the cluster
	if err := s.cluster.AddMember(j.Self); err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
	}

	// Respond with the current cluster description
	resp := &JoinResponse{
		s.cluster.self,
		s.cluster.members,
	}
	b := util.JSONEncode(resp)
	w.Write(b.Bytes())
}
Пример #20
0
// Join an existing cluster
func (s *Server) Join(primary string) error {
	command := &raft.DefaultJoinCommand{
		Name:             s.raftServer.Name(),
		ConnectionString: s.connectionString,
	}

	b := util.JSONEncode(command)
	log.Printf("Joining Cluster: %s", primary)
	cs, err := transport.Encode(primary)
	if err != nil {
		return err
	}

	for i := 0; i < 5; i += 1 {
		log.Printf("Join -> %s Command: %s", cs, command)
		_, err = s.client.SafePost(cs, "/join", b)
		if err != nil {
			log.Printf("Unable to join cluster: %s", err)
		} else {
			break
		}
	}
	return err
}
Пример #21
0
func (sql *SQL) Execute(tag string, command string) (*Output, error) {
	// TODO: make sure I can catch non-lock issuez
	sql.mutex.Lock()
	defer sql.mutex.Unlock()

	defer func() { sql.sequenceNumber += 1 }()
	if tag == "primary" || log.Verbose() {
		log.Printf("[%s] [%d] Executing %#v", tag, sql.sequenceNumber, command)
	}

	subprocess := exec.Command("sqlite3", sql.path)
	subprocess.Stdin = strings.NewReader(command + ";")

	var stdout, stderr bytes.Buffer
	subprocess.Stdout = &stdout
	subprocess.Stderr = &stderr

	if err := subprocess.Start(); err != nil {
		log.Panic(err)
	}

	var o, e []byte

	if err := subprocess.Wait(); err != nil {
		exitstatus := getExitstatus(err)
		switch true {
		case exitstatus < 0:
			log.Panic(err)
		case exitstatus == 1:
			fallthrough
		case exitstatus == 2:
			o = stderr.Bytes()
			e = nil
		}
	} else {
		o = stdout.Bytes()
		e = stderr.Bytes()
	}

	output := &Output{
		Stdout:         o,
		Stderr:         e,
		SequenceNumber: sql.sequenceNumber,
	}

	return output, nil
}
Пример #22
0
// Creates a new server.
func New(path, listen string) (*Server, error) {
	cs, err := transport.Encode(listen)
	if err != nil {
		return nil, err
	}
	log.Printf("My connection string is %s", cs)

	sqlPath := filepath.Join(path, "storage.sql")
	util.EnsureAbsent(sqlPath)

	s := &Server{
		path:              path,
		name:              strings.Replace(listen, "/", "-", -1),
		listen:            listen,
		connection_string: cs,
		sql:               sql.NewSQL(sqlPath),
		router:            mux.NewRouter(),
		client:            transport.NewClient(),
	}

	return s, nil
}
Пример #23
0
// Creates a new server.
func New(path, listen string) (*Server, error) {

	cs, err := transport.Encode(listen)
	if err != nil {
		return nil, err
	}

	log.Printf("Starting server at" + cs)

	sqlPath := filepath.Join(path, "storage.sql")
	util.EnsureAbsent(sqlPath)

	s := &Server{
		path:   path,
		listen: listen,
		sql:    sql.NewSQL(sqlPath),
		router: mux.NewRouter(),
		client: transport.NewClient(),
		block:  false,
	}

	return s, nil
}
Пример #24
0
// Join an existing cluster
func (s *Server) Join(primary string) error {
	cs, err := transport.Encode(primary)
	if err != nil {
		return err
	}

    command := &raft.DefaultJoinCommand{
            Name:             s.raftServer.Name(),
            ConnectionString: s.connectionString(),
    }

    for {
		b := util.JSONEncode(command)
	    _, err = s.client.SafePost(cs, "/join", b)
	    if err != nil {
			log.Printf("Unable to join cluster: %s", err)
			time.Sleep(1 * time.Second)
			continue
	    }
	    return nil
	}

    return nil
}
Пример #25
0
func main() {
	//defer profile.Start(profile.CPUProfile).Stop()

	var raftdebug, verbose bool
	var listen, join, directory string

	flag.BoolVar(&verbose, "v", false, "Enable debug output")
	flag.BoolVar(&raftdebug, "r", false, "Enable raft debugging")
	flag.StringVar(&listen, "l", "127.0.0.1:4000", "Socket to listen on (Unix or TCP)")
	flag.StringVar(&join, "join", "", "Cluster to join")
	flag.StringVar(&directory, "d", "", "Storage directory")

	dir := filepath.Dir(os.Args[0])
	base := "./" + filepath.Base(os.Args[0])
	flag.Usage = func() {
		fmt.Fprintf(os.Stderr, `Usage: %s [options]

SQLCluster is a highly-available SQL store. It accepts commands over
HTTP, and returns the output of commands together with a
SequenceNumber which indicates the ordering in which requests are
being applied. (SequenceNumber is useful for validation, and can
otherwise be ignored.)

Run a cluster as follows:

  cd %s
  %s -d /tmp/sqlcluster/node0 &
  %s -d /tmp/sqlcluster/node1 -l 127.0.0.1:4001 --join 127.0.0.1:4000 &
  %s -d /tmp/sqlcluster/node2 -l 127.0.0.1:4002 --join 127.0.0.1:4000

You can then issue queries using your favorite HTTP client.

  curl 127.0.0.1:4000/sql -d 'CREATE TABLE hello (world int)'
  curl 127.0.0.1:4000/sql -d 'INSERT INTO hello (world) VALUES (1), (2)'
  curl 127.0.0.1:4000/sql -d 'SELECT * FROM hello'

This should return the following sequence of outputs:
  - SequenceNumber: 0

  - SequenceNumber: 1

  - SequenceNumber: 2
    1
    2

By default, SQLCluster will listen on a TCP port. However, if you
specify a listen address that begins with a / or ., that will be
interpeted as Unix path for SQLCluster to listen on. (Note that
Octopus runs using Unix sockets only, but it will probably be more
convient for you to develop using TCP.)

OPTIONS:
`, os.Args[0], dir, base, base, base)
		flag.PrintDefaults()
	}

	flag.Parse()

	if flag.NArg() != 0 {
		flag.Usage()
		os.Exit(1)
	}

	log.SetVerbose(verbose)

	if directory == "" {
		var err error
		directory, err = ioutil.TempDir("/tmp", "node")
		if err != nil {
			log.Fatalf("Could not create temporary base directory: %s", err)
		}
		defer os.RemoveAll(directory)

		log.Printf("Storing state in tmpdir %s", directory)
	} else {
		if err := os.MkdirAll(directory, os.ModeDir|0755); err != nil {
			log.Fatalf("Error while creating storage directory: %s", err)
		}
	}

	log.Printf("Changing directory to %s", directory)
	if err := os.Chdir(directory); err != nil {
		log.Fatalf("Error while changing to storage directory: %s", err)
	}

	// Make sure we don't leave stranded sqlclusters lying around
	go func() {
		for {
			time.Sleep(2 * time.Second)
			if os.Getppid() == 1 {
				log.Fatal("Parent process exited; terminating")
			}
		}
	}()

	runtime.GOMAXPROCS(4)

	rand.Seed(time.Now().UnixNano())
	raft.RegisterCommand(&server.WriteCommand{})
	if raftdebug {
		raft.SetLogLevel(raft.Debug)
	}
	//		raft.SetLogLevel(raft.Trace)

	// Start the server
	go func() {
		s, err := server.New(directory, listen)
		if err != nil {
			log.Fatal(err)
		}

		if err := s.ListenAndServe(join); err != nil {
			log.Fatal(err)
		}
	}()

	// Exit cleanly so we can remove the tmpdir
	sigchan := make(chan os.Signal)
	signal.Notify(sigchan, syscall.SIGINT, syscall.SIGTERM)
	<-sigchan
}
Пример #26
0
// This is the only user-facing function, and accordingly the body is
// a raw string rather than JSON.
func (s *Server) sqlHandler(w http.ResponseWriter, req *http.Request) {
	// Assign id
	s.mutex.Lock()

	var id string;
	var forwarded bool;
	id = req.URL.Query().Get("id")
	resChannel := make(chan string)
	if id == "" {
		// This is a client talking to us, assign a unique id
		id = fmt.Sprintf("%s-%d", s.connectionString(), s.counter)
		s.counter += 1


		forwarded = false
		s.sql.AddClientRecord(id,resChannel);

		log.Printf("Received request %s",id)
	} else {
		// This is a forwarded request
		forwarded = true

		if val, ok := s.received[id]; ok && val {
			s.mutex.Unlock()
			return
		}

		log.Printf("Received forwarded request %s",id)
		s.received[id]=true
        w.WriteHeader(http.StatusOK)
	}
	s.mutex.Unlock()

	// Read body
	query, err := ioutil.ReadAll(req.Body)
	if err != nil {
		log.Printf("Couldn't read body: %s", err)
		http.Error(w, err.Error(), http.StatusBadRequest)
	}

	// Forward if we are not the leader
	go func() {
		var count int = 0
		delay  := 50 * time.Millisecond
	    for {
	    	count += 1
	    	if count > 1 {
	    		log.Printf("Retry count for %s is %d",id,count)
	     	   	time.Sleep(delay)     	 
	     	   	if (delay < 200*time.Millisecond) { delay *= 2 } 
		    }

			// Redirect if we are not the leader
			if !s.IsLeader() {
				// Find leader and make sure we do not redirect back to us
				target := s.LeaderConnectionString()
				if (target == "") { continue }
				if (target == s.name) { continue }

				// Redirect
				for {
					res, err := s.client.RawPost(target, fmt.Sprintf("/sql?id=%s",id), bytes.NewBuffer(query))
					if err == nil && res.StatusCode == 200 { break }
		     	   	time.Sleep(50 * time.Millisecond)
		     	   	//if (delay < 200*time.Millisecond) { delay *= 2 } 
				}
				s.mutex.Lock()
				s.received[id] = false
				s.mutex.Unlock()
				break
			} else {
			    _, err := s.raftServer.Do(NewWriteCommand(id,string(query)))

			    // Retry on error
		    	if err != nil { continue; }
		    	break
			}
	    }
    }()

    // Respond if we orignally received the request from the client on this ndoe
    if !forwarded {
		response := <- resChannel
		log.Printf("Responding for id %s",id)
		w.Write([]byte(response))
    }
}
Пример #27
0
// Starts the server.
func (s *Server) ListenAndServe(leader string) error {
	var err error

    log.Printf("Initializing Raft Server: %s", s.path)
             
    // Initialize and start Raft server.
    transporter := raft.NewHTTPTransporter("/raft")
    transporter.Transport.Dial = transport.UnixDialer
    s.raftServer, err = raft.NewServer(s.name, s.path, transporter, nil, s.sql, "")
    if err != nil {
            log.Fatal(err)
    }
    transporter.Install(s.raftServer, s)


    s.raftServer.Start()
	s.raftServer.SetHeartbeatTimeout(1 * time.Millisecond)
	s.raftServer.SetElectionTimeout(500 * time.Millisecond)
	fn := func(e raft.Event) {
		log.Printf("%s %v -> %v\n", e.Type(), e.PrevValue(), e.Value())
	}
    s.raftServer.AddEventListener(raft.StateChangeEventType, fn)
    s.raftServer.AddEventListener(raft.LeaderChangeEventType, fn)
    s.raftServer.AddEventListener(raft.TermChangeEventType, fn)


    if leader != "" {
            // Join to leader if specified.

            log.Println("Attempting to join leader:", leader)

            if !s.raftServer.IsLogEmpty() {
                    log.Fatal("Cannot join with an existing log")
            }
             //time.Sleep(1 * time.Second)

            if err := s.Join(leader); err != nil {
            	log.Println("Join failed")
                log.Fatal(err)
            }
            log.Printf("Node %s joined leader %s" , s.connectionString(), leader)

    } else if s.raftServer.IsLogEmpty() {
            // Initialize the server by joining itself.

            log.Println("Initializing new cluster")

			cs, err := transport.Encode(s.listen)
			if err != nil {
				return err
			}

            _, err = s.raftServer.Do(&raft.DefaultJoinCommand{
                    Name:             s.raftServer.Name(),
                    ConnectionString: cs,
            })
            if err != nil {
                    log.Fatal(err)
            }

    } else {
            log.Println("Recovered from log")
    }

    log.Println("Initializing HTTP server")

	// Initialize and start HTTP server.
	s.httpServer = &http.Server{
		Handler: s.router,
	}

	s.router.HandleFunc("/sql", s.sqlHandler).Methods("POST")
	s.router.HandleFunc("/join", s.joinHandler).Methods("POST")

	// Start Unix transport
	l, err := transport.Listen(s.listen)
	if err != nil {
		log.Fatal(err)
	}
	return s.httpServer.Serve(l)
}
Пример #28
0
func Listen(addr string) (net.Listener, error) {
	network := Network(addr)
	log.Printf("Listening on %s: %s", network, addr)
	return net.Listen(network, addr)
}
Пример #29
0
func (c *Cluster) Init() {
	log.Printf("Initializing cluster and promoting self to primary")
	c.primary = c.self
	c.members = make([]ServerAddress, 0)
}
Пример #30
0
func (c *Cluster) Join(primary ServerAddress, members []ServerAddress) {
	log.Printf("Joining existing cluster: primary %v, members %v", primary, members)
	c.primary = primary
	c.members = members
}