Browse Source

Merge pull request #133 from xiangli-cmu/master

add killAllAndRecovery test
Xiang Li 12 years ago
parent
commit
e7caa1475e
5 changed files with 84 additions and 15 deletions
  1. 6 6
      command.go
  2. 66 3
      etcd_test.go
  3. 4 4
      name_url_map.go
  4. 1 1
      raft_server.go
  5. 7 1
      third_party/github.com/coreos/go-etcd/etcd/client.go

+ 6 - 6
command.go

@@ -118,17 +118,17 @@ func (c *WatchCommand) Apply(server *raft.Server) (interface{}, error) {
 // JoinCommand
 // JoinCommand
 type JoinCommand struct {
 type JoinCommand struct {
 	RaftVersion string `json:"raftVersion"`
 	RaftVersion string `json:"raftVersion"`
-	Name    string `json:"name"`
-	RaftURL string `json:"raftURL"`
-	EtcdURL string `json:"etcdURL"`
+	Name        string `json:"name"`
+	RaftURL     string `json:"raftURL"`
+	EtcdURL     string `json:"etcdURL"`
 }
 }
 
 
 func newJoinCommand() *JoinCommand {
 func newJoinCommand() *JoinCommand {
 	return &JoinCommand{
 	return &JoinCommand{
 		RaftVersion: r.version,
 		RaftVersion: r.version,
-		Name:    r.name,
-		RaftURL: r.url,
-		EtcdURL: e.url,
+		Name:        r.name,
+		RaftURL:     r.url,
+		EtcdURL:     e.url,
 	}
 	}
 }
 }
 
 

+ 66 - 3
etcd_test.go

@@ -78,7 +78,7 @@ func TestInternalVersionFail(t *testing.T) {
 
 
 	procAttr := new(os.ProcAttr)
 	procAttr := new(os.ProcAttr)
 	procAttr.Files = []*os.File{nil, os.Stdout, os.Stderr}
 	procAttr.Files = []*os.File{nil, os.Stdout, os.Stderr}
-	args := []string{"etcd", "-n=node1", "-f", "-d=/tmp/node1", "-vv", "-C="+fakeURL.Host}
+	args := []string{"etcd", "-n=node1", "-f", "-d=/tmp/node1", "-vv", "-C=" + fakeURL.Host}
 
 
 	process, err := os.StartProcess("etcd", args, procAttr)
 	process, err := os.StartProcess("etcd", args, procAttr)
 	if err != nil {
 	if err != nil {
@@ -102,7 +102,6 @@ func TestInternalVersionFail(t *testing.T) {
 	}
 	}
 }
 }
 
 
-
 // This test creates a single node and then set a value to it.
 // This test creates a single node and then set a value to it.
 // Then this test kills the node and restart it and tries to get the value again.
 // Then this test kills the node and restart it and tries to get the value again.
 func TestSingleNodeRecovery(t *testing.T) {
 func TestSingleNodeRecovery(t *testing.T) {
@@ -214,9 +213,73 @@ func TestSimpleMultiNodeTls(t *testing.T) {
 	templateTestSimpleMultiNode(t, true)
 	templateTestSimpleMultiNode(t, true)
 }
 }
 
 
+// Create a five nodes
+// Kill all the nodes and restart
+func TestMultiNodeKillAllAndRecovery(t *testing.T) {
+	procAttr := new(os.ProcAttr)
+	procAttr.Files = []*os.File{nil, os.Stdout, os.Stderr}
+
+	clusterSize := 5
+	argGroup, etcds, err := test.CreateCluster(clusterSize, procAttr, false)
+
+	if err != nil {
+		t.Fatal("cannot create cluster")
+	}
+
+	c := etcd.NewClient()
+
+	c.SyncCluster()
+
+	time.Sleep(time.Second)
+
+	// send 10 commands
+	for i := 0; i < 10; i++ {
+		// Test Set
+		_, err := c.Set("foo", "bar", 0)
+		if err != nil {
+			panic(err)
+		}
+	}
+
+	time.Sleep(time.Second)
+
+	// kill all
+	test.DestroyCluster(etcds)
+
+	time.Sleep(time.Second)
+
+	stop := make(chan bool)
+	leaderChan := make(chan string, 1)
+	all := make(chan bool, 1)
+
+	time.Sleep(time.Second)
+
+	for i := 0; i < clusterSize; i++ {
+		etcds[i], err = os.StartProcess("etcd", argGroup[i], procAttr)
+	}
+
+	go test.Monitor(clusterSize, 1, leaderChan, all, stop)
+
+	<-all
+	<-leaderChan
+
+	result, err := c.Set("foo", "bar", 0)
+
+	if err != nil {
+		panic(err)
+	}
+
+	if result.Index != 18 {
+		t.Fatalf("recovery failed! [%d/18]", result.Index)
+	}
+
+	// kill all
+	test.DestroyCluster(etcds)
+}
+
 // Create a five nodes
 // Create a five nodes
 // Randomly kill one of the node and keep on sending set command to the cluster
 // Randomly kill one of the node and keep on sending set command to the cluster
-func TestMultiNodeRecovery(t *testing.T) {
+func TestMultiNodeKillOne(t *testing.T) {
 	procAttr := new(os.ProcAttr)
 	procAttr := new(os.ProcAttr)
 	procAttr.Files = []*os.File{nil, os.Stdout, os.Stderr}
 	procAttr.Files = []*os.File{nil, os.Stdout, os.Stderr}
 
 

+ 4 - 4
name_url_map.go

@@ -8,8 +8,8 @@ import (
 // we map node name to url
 // we map node name to url
 type nodeInfo struct {
 type nodeInfo struct {
 	raftVersion string
 	raftVersion string
-	raftURL string
-	etcdURL string
+	raftURL     string
+	etcdURL     string
 }
 }
 
 
 var namesMap = make(map[string]*nodeInfo)
 var namesMap = make(map[string]*nodeInfo)
@@ -43,8 +43,8 @@ func nameToRaftURL(name string) (string, bool) {
 func addNameToURL(name string, version string, raftURL string, etcdURL string) {
 func addNameToURL(name string, version string, raftURL string, etcdURL string) {
 	namesMap[name] = &nodeInfo{
 	namesMap[name] = &nodeInfo{
 		raftVersion: raftVersion,
 		raftVersion: raftVersion,
-		raftURL: raftURL,
-		etcdURL: etcdURL,
+		raftURL:     raftURL,
+		etcdURL:     etcdURL,
 	}
 	}
 }
 }
 
 

+ 1 - 1
raft_server.go

@@ -4,10 +4,10 @@ import (
 	"bytes"
 	"bytes"
 	"crypto/tls"
 	"crypto/tls"
 	"encoding/json"
 	"encoding/json"
-	"io/ioutil"
 	"fmt"
 	"fmt"
 	etcdErr "github.com/coreos/etcd/error"
 	etcdErr "github.com/coreos/etcd/error"
 	"github.com/coreos/go-raft"
 	"github.com/coreos/go-raft"
+	"io/ioutil"
 	"net/http"
 	"net/http"
 	"net/url"
 	"net/url"
 	"time"
 	"time"

+ 7 - 1
third_party/github.com/coreos/go-etcd/etcd/client.go

@@ -170,7 +170,13 @@ func (c *Client) getHttpPath(s ...string) string {
 
 
 func (c *Client) updateLeader(httpPath string) {
 func (c *Client) updateLeader(httpPath string) {
 	u, _ := url.Parse(httpPath)
 	u, _ := url.Parse(httpPath)
-	leader := u.Host
+
+	var leader string
+	if u.Scheme == "" {
+		leader = "http://" + u.Host
+	} else {
+		leader = u.Scheme + "://" + u.Host
+	}
 
 
 	logger.Debugf("update.leader[%s,%s]", c.cluster.Leader, leader)
 	logger.Debugf("update.leader[%s,%s]", c.cluster.Leader, leader)
 	c.cluster.Leader = leader
 	c.cluster.Leader = leader