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 }