Xiang Li 12 years ago
parent
commit
ef59a03fbb
11 changed files with 234 additions and 261 deletions
  1. 12 15
      command.go
  2. 10 19
      handlers.go
  3. 70 79
      raftd.go
  4. 29 31
      store/store.go
  5. 13 16
      store/store_test.go
  6. 4 5
      store/watcher.go
  7. 1 1
      store/watcher_test.go
  8. 17 12
      trans_handler.go
  9. 6 6
      web/conn.go
  10. 40 40
      web/hub.go
  11. 32 37
      web/web.go

+ 12 - 15
command.go

@@ -1,4 +1,5 @@
 package main
+
 //------------------------------------------------------------------------------
 //
 // Commands
@@ -6,11 +7,11 @@ package main
 //------------------------------------------------------------------------------
 
 import (
+	"encoding/json"
 	"github.com/benbjohnson/go-raft"
 	"github.com/xiangli-cmu/raft-etcd/store"
-	"encoding/json"
 	"time"
-	)
+)
 
 // A command represents an action to be taken on the replicated state machine.
 type Command interface {
@@ -20,8 +21,8 @@ type Command interface {
 
 // Set command
 type SetCommand struct {
-	Key string `json:"key"`
-	Value string `json:"value"`
+	Key        string    `json:"key"`
+	Value      string    `json:"value"`
 	ExpireTime time.Time `json:"expireTime"`
 }
 
@@ -40,7 +41,6 @@ func (c *SetCommand) GeneratePath() string {
 	return "set/" + c.Key
 }
 
-
 // Get command
 type GetCommand struct {
 	Key string `json:"key"`
@@ -52,12 +52,12 @@ func (c *GetCommand) CommandName() string {
 }
 
 // Set the value of key to value
-func (c *GetCommand) Apply(server *raft.Server) ([]byte, error){
+func (c *GetCommand) Apply(server *raft.Server) ([]byte, error) {
 	res := store.Get(c.Key)
 	return json.Marshal(res)
 }
 
-func (c *GetCommand) GeneratePath() string{
+func (c *GetCommand) GeneratePath() string {
 	return "get/" + c.Key
 }
 
@@ -71,8 +71,8 @@ func (c *DeleteCommand) CommandName() string {
 	return "delete"
 }
 
-// Delete the key 
-func (c *DeleteCommand) Apply(server *raft.Server) ([]byte, error){
+// Delete the key
+func (c *DeleteCommand) Apply(server *raft.Server) ([]byte, error) {
 	return store.Delete(c.Key)
 }
 
@@ -86,14 +86,14 @@ func (c *WatchCommand) CommandName() string {
 	return "watch"
 }
 
-func (c *WatchCommand) Apply(server *raft.Server) ([]byte, error){
+func (c *WatchCommand) Apply(server *raft.Server) ([]byte, error) {
 	ch := make(chan store.Response)
 
 	// add to the watchers list
-	store.AddWatcher(c.Key, ch)	
+	store.AddWatcher(c.Key, ch)
 
 	// wait for the notification for any changing
-	res := <- ch
+	res := <-ch
 
 	return json.Marshal(res)
 }
@@ -112,6 +112,3 @@ func (c *JoinCommand) Apply(server *raft.Server) ([]byte, error) {
 	// no result will be returned
 	return nil, err
 }
-
-
-

+ 10 - 19
handlers.go

@@ -1,17 +1,16 @@
 package main
 
 import (
+	"encoding/json"
 	"github.com/benbjohnson/go-raft"
 	"net/http"
-	"encoding/json"
 	//"fmt"
 	"io/ioutil"
 	//"bytes"
-	"time"
-	"strings"
 	"strconv"
-	)
-
+	"strings"
+	"time"
+)
 
 //--------------------------------------
 // HTTP Handlers
@@ -73,9 +72,8 @@ func SnapshotHttpHandler(w http.ResponseWriter, req *http.Request) {
 	w.WriteHeader(http.StatusInternalServerError)
 }
 
-
 func JoinHttpHandler(w http.ResponseWriter, req *http.Request) {
-	
+
 	command := &JoinCommand{}
 
 	if err := decodeJsonRequest(req, command); err == nil {
@@ -87,7 +85,6 @@ func JoinHttpHandler(w http.ResponseWriter, req *http.Request) {
 	}
 }
 
-
 func SetHttpHandler(w http.ResponseWriter, req *http.Request) {
 	key := req.URL.Path[len("/set/"):]
 
@@ -96,7 +93,7 @@ func SetHttpHandler(w http.ResponseWriter, req *http.Request) {
 	if err != nil {
 		warn("raftd: Unable to read: %v", err)
 		w.WriteHeader(http.StatusInternalServerError)
-		return 
+		return
 	}
 
 	debug("[recv] POST http://%v/set/%s [%s]", server.Name(), key, content)
@@ -112,11 +109,11 @@ func SetHttpHandler(w http.ResponseWriter, req *http.Request) {
 		if err != nil {
 			warn("raftd: Bad duration: %v", err)
 			w.WriteHeader(http.StatusInternalServerError)
-			return 
+			return
 		}
 		command.ExpireTime = time.Now().Add(time.Second * (time.Duration)(duration))
 	} else {
-		command.ExpireTime = time.Unix(0,0)
+		command.ExpireTime = time.Unix(0, 0)
 	}
 
 	excute(command, &w)
@@ -134,7 +131,6 @@ func DeleteHttpHandler(w http.ResponseWriter, req *http.Request) {
 	excute(command, &w)
 }
 
-
 func excute(c Command, w *http.ResponseWriter) {
 	if server.State() == "leader" {
 		if body, err := server.Do(c); err != nil {
@@ -152,11 +148,11 @@ func excute(c Command, w *http.ResponseWriter) {
 		(*w).Write([]byte(server.Leader()))
 		return
 	}
-	
+
 	(*w).WriteHeader(http.StatusInternalServerError)
 
 	return
-} 
+}
 
 func MasterHttpHandler(w http.ResponseWriter, req *http.Request) {
 	w.WriteHeader(http.StatusOK)
@@ -202,8 +198,3 @@ func WatchHttpHandler(w http.ResponseWriter, req *http.Request) {
 	}
 
 }
-
-
-
-
-

+ 70 - 79
raftd.go

@@ -2,23 +2,23 @@ package main
 
 import (
 	"bytes"
+	"crypto/tls"
+	"crypto/x509"
 	"encoding/json"
 	"encoding/pem"
 	"flag"
 	"fmt"
 	"github.com/benbjohnson/go-raft"
-	"log"
+	"github.com/xiangli-cmu/raft-etcd/store"
+	"github.com/xiangli-cmu/raft-etcd/web"
 	"io"
 	"io/ioutil"
+	"log"
 	"net/http"
-	"strings"
 	"os"
-	"time"
 	"strconv"
-	"crypto/tls"
-	"crypto/x509"
-	"github.com/xiangli-cmu/raft-etcd/web"
-	"github.com/xiangli-cmu/raft-etcd/store"
+	"strings"
+	"time"
 )
 
 //------------------------------------------------------------------------------
@@ -27,7 +27,6 @@ import (
 //
 //------------------------------------------------------------------------------
 
-
 var verbose bool
 var leaderHost string
 var address string
@@ -45,15 +44,16 @@ func init() {
 	flag.StringVar(&certFile, "cert", "", "the cert file of the server")
 	flag.StringVar(&keyFile, "key", "", "the key file of the server")
 }
+
 // CONSTANTS
-const (	
+const (
 	HTTP = iota
 	HTTPS
 	HTTPSANDVERIFY
 )
 
 const (
-	ELECTIONTIMTOUT = 3 * time.Second
+	ELECTIONTIMTOUT  = 3 * time.Second
 	HEARTBEATTIMEOUT = 1 * time.Second
 )
 
@@ -65,7 +65,7 @@ const (
 
 type Info struct {
 	Host string `json:"host"`
-	Port int `json:"port"`
+	Port int    `json:"port"`
 }
 
 //------------------------------------------------------------------------------
@@ -79,7 +79,6 @@ var logger *log.Logger
 
 var storeMsg chan string
 
-
 //------------------------------------------------------------------------------
 //
 // Functions
@@ -100,7 +99,7 @@ func main() {
 	raft.RegisterCommand(&SetCommand{})
 	raft.RegisterCommand(&GetCommand{})
 	raft.RegisterCommand(&DeleteCommand{})
-	
+
 	// Use the present working directory if a directory was not passed in.
 	var path string
 	if flag.NArg() == 0 {
@@ -118,7 +117,7 @@ func main() {
 	name := fmt.Sprintf("%s:%d", info.Host, info.Port)
 
 	fmt.Printf("Name: %s\n\n", name)
-	
+
 	// secrity type
 	st := securityType()
 
@@ -126,7 +125,7 @@ func main() {
 		panic("ERROR type")
 	}
 
-    t := createTranHandler(st)
+	t := createTranHandler(st)
 
 	// Setup new raft server.
 	s := store.GetStore()
@@ -159,7 +158,7 @@ func main() {
 			server.Do(command)
 			debug("%s start as a leader", server.Name())
 
-		// start as a fellower in a existing cluster
+			// start as a fellower in a existing cluster
 		} else {
 			server.StartElectionTimeout()
 			server.StartFollower()
@@ -171,7 +170,7 @@ func main() {
 			fmt.Println("success join")
 		}
 
-	// rejoin the previous cluster
+		// rejoin the previous cluster
 	} else {
 		server.StartElectionTimeout()
 		server.StartFollower()
@@ -181,15 +180,14 @@ func main() {
 	// open the snapshot
 	go server.Snapshot()
 
+	if webPort != -1 {
+		// start web
+		s.SetMessager(&storeMsg)
+		go webHelper()
+		go web.Start(server, webPort)
+	}
 
-    if webPort != -1 {
-    	// start web
-    	s.SetMessager(&storeMsg)
-    	go webHelper()
-    	go web.Start(server, webPort)
-    } 
-
-    startTransport(info.Port, st)
+	startTransport(info.Port, st)
 
 }
 
@@ -216,12 +214,12 @@ func createTranHandler(st int) transHandler {
 		}
 
 		tr := &http.Transport{
-			TLSClientConfig:   &tls.Config{
-				Certificates: []tls.Certificate{tlsCert},
+			TLSClientConfig: &tls.Config{
+				Certificates:       []tls.Certificate{tlsCert},
 				InsecureSkipVerify: true,
-				},
-				DisableCompression: true,
-			}
+			},
+			DisableCompression: true,
+		}
 
 		t.client = &http.Client{Transport: tr}
 		return t
@@ -231,36 +229,35 @@ func createTranHandler(st int) transHandler {
 	return transHandler{}
 }
 
-func startTransport(port int, st int) {	
+func startTransport(port int, st int) {
 
 	// internal commands
-    http.HandleFunc("/join", JoinHttpHandler)
-    http.HandleFunc("/vote", VoteHttpHandler)
-    http.HandleFunc("/log", GetLogHttpHandler)
-    http.HandleFunc("/log/append", AppendEntriesHttpHandler)
-    http.HandleFunc("/snapshot", SnapshotHttpHandler)
-
-    // external commands
-    http.HandleFunc("/set/", SetHttpHandler)
-    http.HandleFunc("/get/", GetHttpHandler)
-    http.HandleFunc("/delete/", DeleteHttpHandler)
-    http.HandleFunc("/watch/", WatchHttpHandler)
-    http.HandleFunc("/master", MasterHttpHandler)
+	http.HandleFunc("/join", JoinHttpHandler)
+	http.HandleFunc("/vote", VoteHttpHandler)
+	http.HandleFunc("/log", GetLogHttpHandler)
+	http.HandleFunc("/log/append", AppendEntriesHttpHandler)
+	http.HandleFunc("/snapshot", SnapshotHttpHandler)
+
+	// external commands
+	http.HandleFunc("/set/", SetHttpHandler)
+	http.HandleFunc("/get/", GetHttpHandler)
+	http.HandleFunc("/delete/", DeleteHttpHandler)
+	http.HandleFunc("/watch/", WatchHttpHandler)
+	http.HandleFunc("/master", MasterHttpHandler)
 
-    switch st {
+	switch st {
 
-    case HTTP:
-    	log.Fatal(http.ListenAndServe(fmt.Sprintf(":%d", port), nil))
+	case HTTP:
+		log.Fatal(http.ListenAndServe(fmt.Sprintf(":%d", port), nil))
 
-    case HTTPS:
-    	http.ListenAndServeTLS(fmt.Sprintf(":%d", port), certFile, keyFile, nil)
+	case HTTPS:
+		http.ListenAndServeTLS(fmt.Sprintf(":%d", port), certFile, keyFile, nil)
 
-    case HTTPSANDVERIFY:
-    	pemByte, _ := ioutil.ReadFile(CAFile)
+	case HTTPSANDVERIFY:
+		pemByte, _ := ioutil.ReadFile(CAFile)
 
 		block, pemByte := pem.Decode(pemByte)
 
-
 		cert, err := x509.ParseCertificate(block.Bytes)
 
 		if err != nil {
@@ -274,16 +271,16 @@ func startTransport(port int, st int) {
 		server := &http.Server{
 			TLSConfig: &tls.Config{
 				ClientAuth: tls.RequireAndVerifyClientCert,
-				ClientCAs: certPool,
-				},
-			Addr:fmt.Sprintf(":%d", port),
+				ClientCAs:  certPool,
+			},
+			Addr: fmt.Sprintf(":%d", port),
 		}
 		err = server.ListenAndServeTLS(certFile, keyFile)
 
 		if err != nil {
 			log.Fatal(err)
 		}
-    }
+	}
 
 }
 
@@ -291,8 +288,8 @@ func startTransport(port int, st int) {
 // Config
 //--------------------------------------
 
-func securityType() int{
-	if keyFile == "" && certFile == "" && CAFile == ""{
+func securityType() int {
+	if keyFile == "" && certFile == "" && CAFile == "" {
 
 		return HTTP
 
@@ -310,7 +307,6 @@ func securityType() int{
 	return -1
 }
 
-
 func getInfo(path string) *Info {
 	info := &Info{}
 
@@ -325,10 +321,10 @@ func getInfo(path string) *Info {
 			}
 		}
 		file.Close()
-	
-	// Otherwise ask user for info and write it to file.
+
+		// Otherwise ask user for info and write it to file.
 	} else {
-		
+
 		if address == "" {
 			fatal("Please give the address of the local machine")
 		}
@@ -341,9 +337,9 @@ func getInfo(path string) *Info {
 
 		info.Host = input[0]
 		info.Host = strings.TrimSpace(info.Host)
-		
+
 		info.Port, err = strconv.Atoi(input[1])
-		
+
 		if err != nil {
 			fatal("Wrong port %s", address)
 		}
@@ -355,11 +351,10 @@ func getInfo(path string) *Info {
 			fatal("Unable to write info to file: %v", err)
 		}
 	}
-	
+
 	return info
 }
 
-
 //--------------------------------------
 // Handlers
 //--------------------------------------
@@ -367,15 +362,14 @@ func getInfo(path string) *Info {
 // Send join requests to the leader.
 func Join(s *raft.Server, serverName string) error {
 	var b bytes.Buffer
-	
+
 	command := &JoinCommand{}
 	command.Name = s.Name()
 
 	json.NewEncoder(&b).Encode(command)
-	
 
 	// t must be ok
-	t,_ := server.Transporter().(transHandler)
+	t, _ := server.Transporter().(transHandler)
 	debug("Send Join Request to %s", serverName)
 	resp, err := Post(&t, fmt.Sprintf("%s/join", serverName), &b)
 
@@ -399,6 +393,7 @@ func Join(s *raft.Server, serverName string) error {
 	}
 	return fmt.Errorf("Unable to join: %v", err)
 }
+
 //--------------------------------------
 // Web Helper
 //--------------------------------------
@@ -410,7 +405,6 @@ func webHelper() {
 	}
 }
 
-
 //--------------------------------------
 // HTTP Utilities
 //--------------------------------------
@@ -434,13 +428,13 @@ func encodeJsonResponse(w http.ResponseWriter, status int, data interface{}) {
 	}
 }
 
-func Post(t *transHandler, path string, body io.Reader) (*http.Response, error){
+func Post(t *transHandler, path string, body io.Reader) (*http.Response, error) {
 
 	if t.client != nil {
-		resp, err := t.client.Post("https://" + path, "application/json", body)
+		resp, err := t.client.Post("https://"+path, "application/json", body)
 		return resp, err
 	} else {
-		resp, err := http.Post("http://" + path, "application/json", body)
+		resp, err := http.Post("http://"+path, "application/json", body)
 		return resp, err
 	}
 }
@@ -461,22 +455,19 @@ func Get(t *transHandler, path string) (*http.Response, error) {
 
 func debug(msg string, v ...interface{}) {
 	if verbose {
-		logger.Printf("DEBUG " + msg + "\n", v...)
+		logger.Printf("DEBUG "+msg+"\n", v...)
 	}
 }
 
 func info(msg string, v ...interface{}) {
-	logger.Printf("INFO  " + msg + "\n", v...)
+	logger.Printf("INFO  "+msg+"\n", v...)
 }
 
 func warn(msg string, v ...interface{}) {
-	logger.Printf("Alpaca Server: WARN  " + msg + "\n", v...)
+	logger.Printf("Alpaca Server: WARN  "+msg+"\n", v...)
 }
 
 func fatal(msg string, v ...interface{}) {
-	logger.Printf("FATAL " + msg + "\n", v...)
+	logger.Printf("FATAL "+msg+"\n", v...)
 	os.Exit(1)
 }
-
-
-

+ 29 - 31
store/store.go

@@ -1,11 +1,11 @@
 package store
 
 import (
-	"path"
 	"encoding/json"
-	"time"
 	"fmt"
-	)
+	"path"
+	"time"
+)
 
 // global store
 var s *Store
@@ -13,26 +13,24 @@ var s *Store
 // CONSTANTS
 const (
 	ERROR = -1 + iota
-	SET 
+	SET
 	DELETE
 	GET
 )
 
-
-var PERMANENT = time.Unix(0,0)
+var PERMANENT = time.Unix(0, 0)
 
 type Store struct {
 	// use the build-in hash map as the key-value store structure
-	Nodes map[string]Node  `json:"nodes"`
+	Nodes map[string]Node `json:"nodes"`
 
 	// the string channel to send messages to the outside world
 	// now we use it to send changes to the hub of the web service
 	messager *chan string
 }
 
-
 type Node struct {
-	Value string	`json:"value"`
+	Value string `json:"value"`
 
 	// if the node is a permanent one the ExprieTime will be Unix(0,0)
 	// Otherwise after the expireTime, the node will be deleted
@@ -43,14 +41,14 @@ type Node struct {
 }
 
 type Response struct {
-	Action	 int    `json:"action"`
+	Action   int    `json:"action"`
 	Key      string `json:"key"`
 	OldValue string `json:"oldValue"`
 	NewValue string `json:"newValue"`
 
 	// if the key existed before the action, this field should be true
 	// if the key did not exist before the action, this field should be false
-	Exist 	 bool `json:"exist"`
+	Exist bool `json:"exist"`
 
 	Expiration time.Time `json:"expiration"`
 }
@@ -61,7 +59,7 @@ func init() {
 }
 
 // make a new stroe
-func createStore() *Store{
+func createStore() *Store {
 	s := new(Store)
 	s.Nodes = make(map[string]Node)
 	return s
@@ -73,11 +71,11 @@ func GetStore() *Store {
 }
 
 // set the messager of the store
-func (s *Store)SetMessager(messager *chan string) {
+func (s *Store) SetMessager(messager *chan string) {
 	s.messager = messager
-}	
+}
 
-// set the key to value, return the old value if the key exists 
+// set the key to value, return the old value if the key exists
 func Set(key string, value string, expireTime time.Time) ([]byte, error) {
 
 	key = path.Clean(key)
@@ -97,11 +95,11 @@ func Set(key string, value string, expireTime time.Time) ([]byte, error) {
 	node, ok := s.Nodes[key]
 
 	if ok {
-		// if node is not permanent before 
+		// if node is not permanent before
 		// update its expireTime
 		if !node.ExpireTime.Equal(PERMANENT) {
 
-				node.update <- expireTime
+			node.update <- expireTime
 
 		} else {
 			// if we want the permanent node to have expire time
@@ -115,7 +113,7 @@ func Set(key string, value string, expireTime time.Time) ([]byte, error) {
 		// update the information of the node
 		node.ExpireTime = expireTime
 		node.Value = value
-		
+
 		resp := Response{SET, key, node.Value, value, true, expireTime}
 
 		msg, err := json.Marshal(resp)
@@ -123,14 +121,14 @@ func Set(key string, value string, expireTime time.Time) ([]byte, error) {
 		notify(resp)
 
 		// send to the messager
-		if (s.messager != nil && err == nil) {
+		if s.messager != nil && err == nil {
 
 			*s.messager <- string(msg)
-		} 
+		}
 
 		return msg, err
 
-	// add new node
+		// add new node
 	} else {
 
 		update := make(chan time.Time)
@@ -149,10 +147,10 @@ func Set(key string, value string, expireTime time.Time) ([]byte, error) {
 		notify(resp)
 
 		// notify the web interface
-		if (s.messager != nil && err == nil) {
+		if s.messager != nil && err == nil {
 
 			*s.messager <- string(msg)
-		} 
+		}
 
 		return msg, err
 	}
@@ -180,10 +178,10 @@ func expire(key string, update chan time.Time, expireTime time.Time) {
 				notify(resp)
 
 				// notify the messager
-				if (s.messager != nil && err == nil) {
+				if s.messager != nil && err == nil {
 
 					*s.messager <- string(msg)
-				} 
+				}
 
 				return
 
@@ -191,7 +189,7 @@ func expire(key string, update chan time.Time, expireTime time.Time) {
 
 		case updateTime := <-update:
 			//update duration
-			// if the node become a permanent one, the go routine is 
+			// if the node become a permanent one, the go routine is
 			// not needed
 			if updateTime.Equal(PERMANENT) {
 				return
@@ -242,10 +240,10 @@ func Delete(key string) ([]byte, error) {
 		notify(resp)
 
 		// notify the messager
-		if (s.messager != nil && err == nil) {
+		if s.messager != nil && err == nil {
 
 			*s.messager <- string(msg)
-		} 
+		}
 
 		return msg, err
 
@@ -256,7 +254,7 @@ func Delete(key string) ([]byte, error) {
 }
 
 // save the current state of the storage system
-func (s *Store)Save() ([]byte, error) {
+func (s *Store) Save() ([]byte, error) {
 	b, err := json.Marshal(s)
 	if err != nil {
 		fmt.Println(err)
@@ -266,7 +264,7 @@ func (s *Store)Save() ([]byte, error) {
 }
 
 // recovery the state of the stroage system from a previous state
-func (s *Store)Recovery(state []byte) error {
+func (s *Store) Recovery(state []byte) error {
 	err := json.Unmarshal(state, s)
 
 	// clean the expired nodes
@@ -277,7 +275,7 @@ func (s *Store)Recovery(state []byte) error {
 
 // clean all expired keys
 func clean() {
-	for key, node := range s.Nodes{
+	for key, node := range s.Nodes {
 
 		if node.ExpireTime.Equal(PERMANENT) {
 			continue

+ 13 - 16
store/store_test.go

@@ -1,9 +1,9 @@
 package store
 
 import (
+	"fmt"
 	"testing"
 	"time"
-	"fmt"
 )
 
 func TestStoreGet(t *testing.T) {
@@ -53,7 +53,6 @@ func TestStoreGet(t *testing.T) {
 // 		t.Fatalf("Get expired value")
 // 	}
 
-
 // 	s.Delete("foo")
 
 // }
@@ -63,8 +62,8 @@ func TestExpire(t *testing.T) {
 	fmt.Println("TEST EXPIRE")
 
 	// test expire
-	Set("foo", "bar", time.Now().Add(time.Second * 1))
-	time.Sleep(2*time.Second)
+	Set("foo", "bar", time.Now().Add(time.Second*1))
+	time.Sleep(2 * time.Second)
 
 	res := Get("foo")
 
@@ -73,7 +72,7 @@ func TestExpire(t *testing.T) {
 	}
 
 	//test change expire time
-	Set("foo", "bar", time.Now().Add(time.Second * 10))
+	Set("foo", "bar", time.Now().Add(time.Second*10))
 
 	res = Get("foo")
 
@@ -81,7 +80,7 @@ func TestExpire(t *testing.T) {
 		t.Fatalf("Cannot get Value")
 	}
 
-	Set("foo", "barbar", time.Now().Add(time.Second * 1))
+	Set("foo", "barbar", time.Now().Add(time.Second*1))
 
 	time.Sleep(2 * time.Second)
 
@@ -91,13 +90,12 @@ func TestExpire(t *testing.T) {
 		t.Fatalf("Got expired value")
 	}
 
-
 	// test change expire to stable
-	Set("foo", "bar", time.Now().Add(time.Second * 1))
+	Set("foo", "bar", time.Now().Add(time.Second*1))
 
-	Set("foo", "bar", time.Unix(0,0))
+	Set("foo", "bar", time.Unix(0, 0))
 
-	time.Sleep(2*time.Second)
+	time.Sleep(2 * time.Second)
 
 	res = s.Get("foo")
 
@@ -105,22 +103,21 @@ func TestExpire(t *testing.T) {
 		t.Fatalf("Cannot get Value")
 	}
 
-	// test stable to expire 
-	s.Set("foo", "bar", time.Now().Add(time.Second * 1))
-	time.Sleep(2*time.Second)
+	// test stable to expire
+	s.Set("foo", "bar", time.Now().Add(time.Second*1))
+	time.Sleep(2 * time.Second)
 	res = s.Get("foo")
 
 	if res.Exist {
 		t.Fatalf("Got expired value")
 	}
 
-	// test set older node 
-	s.Set("foo", "bar", time.Now().Add(-time.Second * 1))
+	// test set older node
+	s.Set("foo", "bar", time.Now().Add(-time.Second*1))
 	res = s.Get("foo")
 
 	if res.Exist {
 		t.Fatalf("Got expired value")
 	}
 
-
 }

+ 4 - 5
store/watcher.go

@@ -3,9 +3,9 @@ package store
 import (
 	"path"
 	"strings"
-	//"fmt"
-	)
 
+//"fmt"
+)
 
 type Watchers struct {
 	chanMap map[string][]chan Response
@@ -14,7 +14,6 @@ type Watchers struct {
 // global watcher
 var w *Watchers
 
-
 // init the global watcher
 func init() {
 	w = createWatcher()
@@ -66,7 +65,7 @@ func notify(resp Response) error {
 			for _, c := range chans {
 				c <- resp
 			}
-			
+
 			// we have notified all the watchers at this path
 			// delete the map
 			delete(w.chanMap, currPath)
@@ -75,4 +74,4 @@ func notify(resp Response) error {
 	}
 
 	return nil
-}
+}

+ 1 - 1
store/watcher_test.go

@@ -1,8 +1,8 @@
 package store
 
 import (
-	"testing"
 	"fmt"
+	"testing"
 	"time"
 )
 

+ 17 - 12
trans_handler.go

@@ -1,16 +1,16 @@
 package main
 
-import(
-	"encoding/json"
-	"github.com/benbjohnson/go-raft"
+import (
 	"bytes"
-	"net/http"
+	"encoding/json"
 	"fmt"
+	"github.com/benbjohnson/go-raft"
 	"io"
+	"net/http"
 )
 
 type transHandler struct {
-	name string
+	name   string
 	client *http.Client
 }
 
@@ -19,7 +19,9 @@ func (t transHandler) SendAppendEntriesRequest(server *raft.Server, peer *raft.P
 	var aersp *raft.AppendEntriesResponse
 	var b bytes.Buffer
 	json.NewEncoder(&b).Encode(req)
-	
+
+	debug("Send LogEntries to %s ", peer.Name())
+
 	resp, err := Post(&t, fmt.Sprintf("%s/log/append", peer.Name()), &b)
 
 	if resp != nil {
@@ -28,7 +30,7 @@ func (t transHandler) SendAppendEntriesRequest(server *raft.Server, peer *raft.P
 		if err = json.NewDecoder(resp.Body).Decode(&aersp); err == nil || err == io.EOF {
 			return aersp, nil
 		}
-		
+
 	}
 	return aersp, fmt.Errorf("raftd: Unable to append entries: %v", err)
 }
@@ -39,6 +41,8 @@ func (t transHandler) SendVoteRequest(server *raft.Server, peer *raft.Peer, req
 	var b bytes.Buffer
 	json.NewEncoder(&b).Encode(req)
 
+	debug("Send Vote to %s", peer.Name())
+
 	resp, err := Post(&t, fmt.Sprintf("%s/vote", peer.Name()), &b)
 
 	if resp != nil {
@@ -47,9 +51,9 @@ func (t transHandler) SendVoteRequest(server *raft.Server, peer *raft.Peer, req
 		if err = json.NewDecoder(resp.Body).Decode(&rvrsp); err == nil || err == io.EOF {
 			return rvrsp, nil
 		}
-		
+
 	}
-	return rvrsp, fmt.Errorf("raftd: Unable to request vote: %v", err)
+	return rvrsp, fmt.Errorf("Unable to request vote: %v", err)
 }
 
 // Sends SnapshotRequest RPCs to a peer when the server is the candidate.
@@ -58,7 +62,8 @@ func (t transHandler) SendSnapshotRequest(server *raft.Server, peer *raft.Peer,
 	var b bytes.Buffer
 	json.NewEncoder(&b).Encode(req)
 
-	debug("[send] POST %s/snapshot [%d %d]", peer.Name(), req.LastTerm, req.LastIndex)
+	debug("Send Snapshot to %s [Last Term: %d, LastIndex %d]", peer.Name(),
+		req.LastTerm, req.LastIndex)
 
 	resp, err := Post(&t, fmt.Sprintf("%s/snapshot", peer.Name()), &b)
 
@@ -70,5 +75,5 @@ func (t transHandler) SendSnapshotRequest(server *raft.Server, peer *raft.Peer,
 			return aersp, nil
 		}
 	}
-	return aersp, fmt.Errorf("raftd: Unable to send snapshot: %v", err)
-}
+	return aersp, fmt.Errorf("Unable to send snapshot: %v", err)
+}

+ 6 - 6
web/conn.go

@@ -1,17 +1,17 @@
 package web
- 
+
 import (
 	"code.google.com/p/go.net/websocket"
 )
- 
+
 type connection struct {
 	// The websocket connection.
 	ws *websocket.Conn
- 
+
 	// Buffered channel of outbound messages.
 	send chan string
 }
- 
+
 func (c *connection) writer() {
 	for message := range c.send {
 		err := websocket.Message.Send(c.ws, message)
@@ -21,10 +21,10 @@ func (c *connection) writer() {
 	}
 	c.ws.Close()
 }
- 
+
 func wsHandler(ws *websocket.Conn) {
 	c := &connection{send: make(chan string, 256), ws: ws}
 	h.register <- c
 	defer func() { h.unregister <- c }()
 	c.writer()
-}
+}

+ 40 - 40
web/hub.go

@@ -1,61 +1,61 @@
 package web
 
 type hub struct {
-    // status
-    open    bool
+	// status
+	open bool
 
-    // Registered connections.
-    connections map[*connection]bool
+	// Registered connections.
+	connections map[*connection]bool
 
-    // Inbound messages from the connections.
-    broadcast chan string
+	// Inbound messages from the connections.
+	broadcast chan string
 
-    // Register requests from the connections.
-    register chan *connection
+	// Register requests from the connections.
+	register chan *connection
 
-    // Unregister requests from connections.
-    unregister chan *connection
+	// Unregister requests from connections.
+	unregister chan *connection
 }
 
 var h = hub{
-    open:   false,
-    broadcast:   make(chan string),
-    register:    make(chan *connection),
-    unregister:  make(chan *connection),
-    connections: make(map[*connection]bool),
+	open:        false,
+	broadcast:   make(chan string),
+	register:    make(chan *connection),
+	unregister:  make(chan *connection),
+	connections: make(map[*connection]bool),
 }
 
-func Hub() *hub{
-    return &h
+func Hub() *hub {
+	return &h
 }
 
 func HubOpen() bool {
-    return h.open
+	return h.open
 }
 
 func (h *hub) run() {
-    h.open = true
-    for {
-        select {
-        case c := <-h.register:
-            h.connections[c] = true
-        case c := <-h.unregister:
-            delete(h.connections, c)
-            close(c.send)
-        case m := <-h.broadcast:
-            for c := range h.connections {
-                select {
-                case c.send <- m:
-                default:
-                    delete(h.connections, c)
-                    close(c.send)
-                    go c.ws.Close()
-                }
-            }
-        }
-    }
+	h.open = true
+	for {
+		select {
+		case c := <-h.register:
+			h.connections[c] = true
+		case c := <-h.unregister:
+			delete(h.connections, c)
+			close(c.send)
+		case m := <-h.broadcast:
+			for c := range h.connections {
+				select {
+				case c.send <- m:
+				default:
+					delete(h.connections, c)
+					close(c.send)
+					go c.ws.Close()
+				}
+			}
+		}
+	}
 }
 
 func (h *hub) Send(msg string) {
-    h.broadcast <- msg
-}
+	h.broadcast <- msg
+}

+ 32 - 37
web/web.go

@@ -1,42 +1,41 @@
 package web
 
 import (
-    "fmt"
-    "net/http"
-    "github.com/xiangli-cmu/raft-etcd/store"
-    "github.com/benbjohnson/go-raft"
-    "time"
-    "code.google.com/p/go.net/websocket"
-    "html/template"
+	"code.google.com/p/go.net/websocket"
+	"fmt"
+	"github.com/benbjohnson/go-raft"
+	"github.com/xiangli-cmu/raft-etcd/store"
+	"html/template"
+	"net/http"
+	"time"
 )
 
 var s *raft.Server
 
 type MainPage struct {
-    Leader string
-    Address string
+	Leader  string
+	Address string
 }
 
 func handler(w http.ResponseWriter, r *http.Request) {
-    fmt.Fprintf(w, "Leader:\n%s\n", s.Leader())
-    fmt.Fprintf(w, "Peers:\n")
+	fmt.Fprintf(w, "Leader:\n%s\n", s.Leader())
+	fmt.Fprintf(w, "Peers:\n")
 
-    for peerName, _ := range s.Peers() {
-        fmt.Fprintf(w, "%s\n", peerName)
-    }
+	for peerName, _ := range s.Peers() {
+		fmt.Fprintf(w, "%s\n", peerName)
+	}
 
+	fmt.Fprintf(w, "Data\n")
 
-    fmt.Fprintf(w, "Data\n")
+	s := store.GetStore()
 
-    s := store.GetStore()
-
-    for key, node := range s.Nodes {
-        if node.ExpireTime.Equal(time.Unix(0,0)) {
-            fmt.Fprintf(w, "%s %s\n", key, node.Value)
-        } else {
-            fmt.Fprintf(w, "%s %s %s\n", key, node.Value, node.ExpireTime)
-        }
-    }
+	for key, node := range s.Nodes {
+		if node.ExpireTime.Equal(time.Unix(0, 0)) {
+			fmt.Fprintf(w, "%s %s\n", key, node.Value)
+		} else {
+			fmt.Fprintf(w, "%s %s %s\n", key, node.Value, node.ExpireTime)
+		}
+	}
 
 }
 
@@ -44,24 +43,20 @@ var mainTempl = template.Must(template.ParseFiles("home.html"))
 
 func mainHandler(c http.ResponseWriter, req *http.Request) {
 
-    p := &MainPage{Leader: s.Leader(),
-        Address: s.Name(),}
+	p := &MainPage{Leader: s.Leader(),
+		Address: s.Name()}
 
-    mainTempl.Execute(c, p)
+	mainTempl.Execute(c, p)
 }
 
-
 func Start(server *raft.Server, port int) {
 	s = server
 
-    go h.run()
-    http.HandleFunc("/", mainHandler)
-    http.Handle("/ws", websocket.Handler(wsHandler))
+	go h.run()
+	http.HandleFunc("/", mainHandler)
+	http.Handle("/ws", websocket.Handler(wsHandler))
 
-    //http.HandleFunc("/", handler)
-    fmt.Println("web listening at port ", port)
-    http.ListenAndServe(fmt.Sprintf(":%v", port), nil)
+	//http.HandleFunc("/", handler)
+	fmt.Println("web listening at port ", port)
+	http.ListenAndServe(fmt.Sprintf(":%v", port), nil)
 }
-
-
-