github.com/qorio/etcd@v0.1.2-0.20131003183127-5cc585af9618/util.go (about)

     1  package main
     2  
     3  import (
     4  	"encoding/json"
     5  	"fmt"
     6  	"io"
     7  	"net"
     8  	"net/http"
     9  	"net/url"
    10  	"os"
    11  	"os/signal"
    12  	"runtime/pprof"
    13  	"strconv"
    14  	"time"
    15  
    16  	"github.com/coreos/etcd/web"
    17  	"github.com/coreos/go-log/log"
    18  )
    19  
    20  //--------------------------------------
    21  // etcd http Helper
    22  //--------------------------------------
    23  
    24  // Convert string duration to time format
    25  func durationToExpireTime(strDuration string) (time.Time, error) {
    26  	if strDuration != "" {
    27  		duration, err := strconv.Atoi(strDuration)
    28  
    29  		if err != nil {
    30  			return time.Unix(0, 0), err
    31  		}
    32  		return time.Now().Add(time.Second * (time.Duration)(duration)), nil
    33  
    34  	} else {
    35  		return time.Unix(0, 0), nil
    36  	}
    37  }
    38  
    39  //--------------------------------------
    40  // Web Helper
    41  //--------------------------------------
    42  var storeMsg chan string
    43  
    44  // Help to send msg from store to webHub
    45  func webHelper() {
    46  	storeMsg = make(chan string)
    47  	etcdStore.SetMessager(storeMsg)
    48  	for {
    49  		// transfer the new msg to webHub
    50  		web.Hub().Send(<-storeMsg)
    51  	}
    52  }
    53  
    54  // startWebInterface starts web interface if webURL is not empty
    55  func startWebInterface() {
    56  	if argInfo.WebURL != "" {
    57  		// start web
    58  		go webHelper()
    59  		go web.Start(r.Server, argInfo.WebURL)
    60  	}
    61  }
    62  
    63  //--------------------------------------
    64  // HTTP Utilities
    65  //--------------------------------------
    66  
    67  func decodeJsonRequest(req *http.Request, data interface{}) error {
    68  	decoder := json.NewDecoder(req.Body)
    69  	if err := decoder.Decode(&data); err != nil && err != io.EOF {
    70  		warnf("Malformed json request: %v", err)
    71  		return fmt.Errorf("Malformed json request: %v", err)
    72  	}
    73  	return nil
    74  }
    75  
    76  func encodeJsonResponse(w http.ResponseWriter, status int, data interface{}) {
    77  	w.Header().Set("Content-Type", "application/json")
    78  	w.WriteHeader(status)
    79  
    80  	if data != nil {
    81  		encoder := json.NewEncoder(w)
    82  		encoder.Encode(data)
    83  	}
    84  }
    85  
    86  // sanitizeURL will cleanup a host string in the format hostname:port and
    87  // attach a schema.
    88  func sanitizeURL(host string, defaultScheme string) string {
    89  	// Blank URLs are fine input, just return it
    90  	if len(host) == 0 {
    91  		return host
    92  	}
    93  
    94  	p, err := url.Parse(host)
    95  	if err != nil {
    96  		fatal(err)
    97  	}
    98  
    99  	// Make sure the host is in Host:Port format
   100  	_, _, err = net.SplitHostPort(host)
   101  	if err != nil {
   102  		fatal(err)
   103  	}
   104  
   105  	p = &url.URL{Host: host, Scheme: defaultScheme}
   106  
   107  	return p.String()
   108  }
   109  
   110  // sanitizeListenHost cleans up the ListenHost parameter and appends a port
   111  // if necessary based on the advertised port.
   112  func sanitizeListenHost(listen string, advertised string) string {
   113  	aurl, err := url.Parse(advertised)
   114  	if err != nil {
   115  		fatal(err)
   116  	}
   117  
   118  	ahost, aport, err := net.SplitHostPort(aurl.Host)
   119  	if err != nil {
   120  		fatal(err)
   121  	}
   122  
   123  	// If the listen host isn't set use the advertised host
   124  	if listen == "" {
   125  		listen = ahost
   126  	}
   127  
   128  	return net.JoinHostPort(listen, aport)
   129  }
   130  
   131  func redirect(node string, etcd bool, w http.ResponseWriter, req *http.Request) {
   132  	var url string
   133  	path := req.URL.Path
   134  
   135  	if etcd {
   136  		etcdAddr, _ := nameToEtcdURL(node)
   137  		url = etcdAddr + path
   138  	} else {
   139  		raftAddr, _ := nameToRaftURL(node)
   140  		url = raftAddr + path
   141  	}
   142  
   143  	debugf("Redirect to %s", url)
   144  
   145  	http.Redirect(w, req, url, http.StatusTemporaryRedirect)
   146  }
   147  
   148  func check(err error) {
   149  	if err != nil {
   150  		fatal(err)
   151  	}
   152  }
   153  
   154  //--------------------------------------
   155  // Log
   156  //--------------------------------------
   157  
   158  var logger *log.Logger = log.New("etcd", false,
   159  	log.CombinedSink(os.Stdout, "[%s] %s %-9s | %s\n", []string{"prefix", "time", "priority", "message"}))
   160  
   161  func infof(format string, v ...interface{}) {
   162  	logger.Infof(format, v...)
   163  }
   164  
   165  func debugf(format string, v ...interface{}) {
   166  	if verbose {
   167  		logger.Debugf(format, v...)
   168  	}
   169  }
   170  
   171  func debug(v ...interface{}) {
   172  	if verbose {
   173  		logger.Debug(v...)
   174  	}
   175  }
   176  
   177  func warnf(format string, v ...interface{}) {
   178  	logger.Warningf(format, v...)
   179  }
   180  
   181  func warn(v ...interface{}) {
   182  	logger.Warning(v...)
   183  }
   184  
   185  func fatalf(format string, v ...interface{}) {
   186  	logger.Fatalf(format, v...)
   187  }
   188  
   189  func fatal(v ...interface{}) {
   190  	logger.Fatalln(v...)
   191  }
   192  
   193  //--------------------------------------
   194  // CPU profile
   195  //--------------------------------------
   196  func runCPUProfile() {
   197  
   198  	f, err := os.Create(cpuprofile)
   199  	if err != nil {
   200  		fatal(err)
   201  	}
   202  	pprof.StartCPUProfile(f)
   203  
   204  	c := make(chan os.Signal, 1)
   205  	signal.Notify(c, os.Interrupt)
   206  	go func() {
   207  		for sig := range c {
   208  			infof("captured %v, stopping profiler and exiting..", sig)
   209  			pprof.StopCPUProfile()
   210  			os.Exit(1)
   211  		}
   212  	}()
   213  }
   214  
   215  //--------------------------------------
   216  // Testing
   217  //--------------------------------------
   218  func directSet() {
   219  	c := make(chan bool, 1000)
   220  	for i := 0; i < 1000; i++ {
   221  		go send(c)
   222  	}
   223  
   224  	for i := 0; i < 1000; i++ {
   225  		<-c
   226  	}
   227  }
   228  
   229  func send(c chan bool) {
   230  	for i := 0; i < 10; i++ {
   231  		command := &SetCommand{}
   232  		command.Key = "foo"
   233  		command.Value = "bar"
   234  		command.ExpireTime = time.Unix(0, 0)
   235  		r.Do(command)
   236  	}
   237  	c <- true
   238  }