Example #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)
}
Example #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")
	}

}
Example #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)
}
Example #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
	}
}
Example #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
	}
}
Example #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
	}
}
Example #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)
	}
}
Example #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
	}
}
Example #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)
	}
}
Example #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
	}
}
Example #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)
}
Example #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
		}
	}()
}
Example #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)
	}
}
Example #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
	}
}
Example #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())
	}
}
Example #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
}
Example #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())
}
Example #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)
	}
}
Example #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())
}
Example #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
}
Example #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
}
Example #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
}
Example #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
}
Example #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
}
Example #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
}
Example #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))
    }
}
Example #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)
}
Example #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)
}
Example #29
0
func (c *Cluster) Init() {
	log.Printf("Initializing cluster and promoting self to primary")
	c.primary = c.self
	c.members = make([]ServerAddress, 0)
}
Example #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
}