<commit_before>//
// Copyright © 2011-2017 Guy M. Allard
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//

package stompngo

import (
	"fmt"
	"strconv"
	"strings"
	"time"
)

/*
	Logical network reader.

	Read STOMP frames from the connection, create MessageData
	structures from the received data, and push the MessageData to the client.
*/
func (c *Connection) reader() {
readLoop:
	for {
		f, e := c.readFrame()
		c.log("RDR_RECEIVE_FRAME", f.Command, f.Headers, HexData(f.Body),
			"RDR_RECEIVE_ERR", e)
		if e != nil {
			f.Headers = append(f.Headers, "connection_read_error", e.Error())
			md := MessageData{Message(f), e}
			c.handleReadError(md)
			c.log("RDR_CONN_ERR", e)
			break readLoop
		}

		if f.Command == "" {
			continue readLoop
		}

		m := Message(f)
		c.mets.tfr += 1 // Total frames read
		// Headers already decoded
		c.mets.tbr += m.Size(false) // Total bytes read

		//*************************************************************************
		// Replacement START
		md := MessageData{m, e}
		switch f.Command {
		//
		case MESSAGE:
			sid, ok := f.Headers.Contains(HK_SUBSCRIPTION)
			if !ok { // This should *NEVER* happen
				panic(fmt.Sprintf("stompngo INTERNAL ERROR: command:<%s> headers:<%v>",
					f.Command, f.Headers))
			}
			c.subsLock.RLock()
			ps, sok := c.subs[sid] // This is a map of pointers .....
			//
			if !sok {
				// The sub can be gone under some timing conditions.  In that case
				// we log it of possible, and continue (hope for the best).
				c.log("RDR_NOSUB", sid, m.Command, m.Headers)
				goto csRUnlock
			}
			if ps.cs {
				// The sub can also already be closed under some conditions.
				// Again, we log that if possible, and continue
				c.log("RDR_CLSUB", sid, m.Command, m.Headers)
				goto csRUnlock
			}
			// Handle subscription draining
			switch ps.drav {
			case false:
				ps.md <- md
			default:
				ps.drmc++
				if ps.drmc > ps.dra {
					c.log("RDR_DROPM", ps.drmc, sid, m.Command,
						m.Headers, HexData(m.Body))
				} else {
					ps.md <- md
				}
			}
		csRUnlock:
			c.subsLock.RUnlock()
		//
		case ERROR:
			fallthrough
		//
		case RECEIPT:
			c.input <- md
		//
		default:
			panic(fmt.Sprintf("Broker SEVERE ERROR, not STOMP? command:<%s> headers:<%v>",
				f.Command, f.Headers))
		}
		// Replacement END
		//*************************************************************************

		select {
		case _ = <-c.ssdc:
			c.log("RDR_SHUTDOWN detected")
			break readLoop
		default:
		}
		c.log("RDR_RELOOP")
	}
	close(c.input)
	c.log("RDR_SHUTDOWN", time.Now())
}

/*
	Physical frame reader.

	This parses a single STOMP frame from data off of the wire, and
	returns a Frame, with a possible error.

	Note: this functionality could hang or exhibit other erroneous behavior
	if running against a non-compliant STOMP server.
*/
func (c *Connection) readFrame() (f Frame, e error) {
	f = Frame{"", Headers{}, NULLBUFF}

	// Read f.Command or line ends (maybe heartbeats)
	s, e := c.rdr.ReadString('\n')
	if s == "" {
		return f, e
	}
	if e != nil {
		return f, e
	}
	if c.hbd != nil {
		c.updateHBReads()
	}
	f.Command = s[0 : len(s)-1]
	if s == "\n" {
		return f, e
	}

	// Validate the command
	if _, ok := validCmds[f.Command]; !ok {
		return f, EINVBCMD
	}
	// Read f.Headers
	for {
		s, e := c.rdr.ReadString('\n')
		if e != nil {
			return f, e
		}
		if c.hbd != nil {
			c.updateHBReads()
		}
		if s == "\n" {
			break
		}
		s = s[0 : len(s)-1]
		p := strings.SplitN(s, ":", 2)
		if len(p) != 2 {
			return f, EUNKHDR
		}
		if c.Protocol() != SPL_10 {
			p[0] = decode(p[0])
			p[1] = decode(p[1])
		}
		f.Headers = append(f.Headers, p[0], p[1])
	}
	//
	e = checkHeaders(f.Headers, c.Protocol())
	if e != nil {
		return f, e
	}
	// Read f.Body
	if v, ok := f.Headers.Contains(HK_CONTENT_LENGTH); ok {
		l, e := strconv.Atoi(strings.TrimSpace(v))
		if e != nil {
			return f, e
		}
		if l == 0 {
			f.Body, e = readUntilNul(c.rdr)
		} else {
			f.Body, e = readBody(c.rdr, l)
		}
	} else {
		// content-length not present
		f.Body, e = readUntilNul(c.rdr)
	}
	if e != nil {
		return f, e
	}
	if c.hbd != nil {
		c.updateHBReads()
	}
	//
	return f, e
}

func (c *Connection) updateHBReads() {
	c.hbd.rdl.Lock()
	c.hbd.lr = time.Now().UnixNano() // Latest good read
	c.hbd.rdl.Unlock()
}
<commit_msg>Embellish unusual error message.<commit_after>//
// Copyright © 2011-2017 Guy M. Allard
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//

package stompngo

import (
	"encoding/hex"
	"fmt"
	"strconv"
	"strings"
	"time"
)

/*
	Logical network reader.

	Read STOMP frames from the connection, create MessageData
	structures from the received data, and push the MessageData to the client.
*/
func (c *Connection) reader() {
readLoop:
	for {
		f, e := c.readFrame()
		c.log("RDR_RECEIVE_FRAME", f.Command, f.Headers, HexData(f.Body),
			"RDR_RECEIVE_ERR", e)
		if e != nil {
			f.Headers = append(f.Headers, "connection_read_error", e.Error())
			md := MessageData{Message(f), e}
			c.handleReadError(md)
			c.log("RDR_CONN_ERR", e)
			break readLoop
		}

		if f.Command == "" {
			continue readLoop
		}

		m := Message(f)
		c.mets.tfr += 1 // Total frames read
		// Headers already decoded
		c.mets.tbr += m.Size(false) // Total bytes read

		//*************************************************************************
		// Replacement START
		md := MessageData{m, e}
		switch f.Command {
		//
		case MESSAGE:
			sid, ok := f.Headers.Contains(HK_SUBSCRIPTION)
			if !ok { // This should *NEVER* happen
				panic(fmt.Sprintf("stompngo INTERNAL ERROR: command:<%s> headers:<%v>",
					f.Command, f.Headers))
			}
			c.subsLock.RLock()
			ps, sok := c.subs[sid] // This is a map of pointers .....
			//
			if !sok {
				// The sub can be gone under some timing conditions.  In that case
				// we log it of possible, and continue (hope for the best).
				c.log("RDR_NOSUB", sid, m.Command, m.Headers)
				goto csRUnlock
			}
			if ps.cs {
				// The sub can also already be closed under some conditions.
				// Again, we log that if possible, and continue
				c.log("RDR_CLSUB", sid, m.Command, m.Headers)
				goto csRUnlock
			}
			// Handle subscription draining
			switch ps.drav {
			case false:
				ps.md <- md
			default:
				ps.drmc++
				if ps.drmc > ps.dra {
					c.log("RDR_DROPM", ps.drmc, sid, m.Command,
						m.Headers, HexData(m.Body))
				} else {
					ps.md <- md
				}
			}
		csRUnlock:
			c.subsLock.RUnlock()
		//
		case ERROR:
			fallthrough
		//
		case RECEIPT:
			c.input <- md
		//
		default:
			panic(fmt.Sprintf("Broker SEVERE ERROR, not STOMP? command:<%s> headers:<%v>",
				f.Command, f.Headers))
		}
		// Replacement END
		//*************************************************************************

		select {
		case _ = <-c.ssdc:
			c.log("RDR_SHUTDOWN detected")
			break readLoop
		default:
		}
		c.log("RDR_RELOOP")
	}
	close(c.input)
	c.log("RDR_SHUTDOWN", time.Now())
}

/*
	Physical frame reader.

	This parses a single STOMP frame from data off of the wire, and
	returns a Frame, with a possible error.

	Note: this functionality could hang or exhibit other erroneous behavior
	if running against a non-compliant STOMP server.
*/
func (c *Connection) readFrame() (f Frame, e error) {
	f = Frame{"", Headers{}, NULLBUFF}

	// Read f.Command or line ends (maybe heartbeats)
	s, e := c.rdr.ReadString('\n')
	if s == "" {
		return f, e
	}
	if e != nil {
		return f, e
	}
	if c.hbd != nil {
		c.updateHBReads()
	}
	f.Command = s[0 : len(s)-1]
	if s == "\n" {
		return f, e
	}

	// Validate the command
	if _, ok := validCmds[f.Command]; !ok {
		ev := fmt.Errorf("%s\n%s", EINVBCMD, hex.Dump([]byte(f.Command)))
		return f, ev
	}
	// Read f.Headers
	for {
		s, e := c.rdr.ReadString('\n')
		if e != nil {
			return f, e
		}
		if c.hbd != nil {
			c.updateHBReads()
		}
		if s == "\n" {
			break
		}
		s = s[0 : len(s)-1]
		p := strings.SplitN(s, ":", 2)
		if len(p) != 2 {
			return f, EUNKHDR
		}
		if c.Protocol() != SPL_10 {
			p[0] = decode(p[0])
			p[1] = decode(p[1])
		}
		f.Headers = append(f.Headers, p[0], p[1])
	}
	//
	e = checkHeaders(f.Headers, c.Protocol())
	if e != nil {
		return f, e
	}
	// Read f.Body
	if v, ok := f.Headers.Contains(HK_CONTENT_LENGTH); ok {
		l, e := strconv.Atoi(strings.TrimSpace(v))
		if e != nil {
			return f, e
		}
		if l == 0 {
			f.Body, e = readUntilNul(c.rdr)
		} else {
			f.Body, e = readBody(c.rdr, l)
		}
	} else {
		// content-length not present
		f.Body, e = readUntilNul(c.rdr)
	}
	if e != nil {
		return f, e
	}
	if c.hbd != nil {
		c.updateHBReads()
	}
	//
	return f, e
}

func (c *Connection) updateHBReads() {
	c.hbd.rdl.Lock()
	c.hbd.lr = time.Now().UnixNano() // Latest good read
	c.hbd.rdl.Unlock()
}
<|endoftext|>


<commit_before>package main

import (
	"log"
	"net/http"
	"strconv"

	"github.com/go-martini/martini"
	//"github.com/martini-contrib/gzip"
	"github.com/martini-contrib/oauth2"
	"github.com/martini-contrib/render"
	"github.com/martini-contrib/sessions"
)

func main() {
	m := martini.Classic()
	//m.Use(gzip.All())
	m.Use(render.Renderer(render.Options{
		Directory:       "templates",
		Layout:          "layout",
		Extensions:      []string{".tmpl", ".html"},
		HTMLContentType: "application/xhtml+xml",
	}))
	m.Use(sessions.Sessions("my_session", sessions.NewCookieStore([]byte("pollchatsecretkey"))))
	m.Use(oauth2.Google(&oauth2.Options{
		ClientId:     pollchat.clientId,
		ClientSecret: pollchat.clientSecret,
		RedirectURL:  "http://pollchat.co.uk/oauth2callback",
		Scopes:       []string{"https://www.googleapis.com/auth/drive"},
	}))
	// add an auth step here to redirect to /login if not authed
	m.Get("/", func(r render.Render, tokens oauth2.Tokens) {
		if tokens.IsExpired() {
			r.Redirect("/login")
		}
		type recent struct {
			Q   *Question
			Top string
		}
		questions := make([]*recent, 0) //questions = append(questions, question)
		if len(collection) > 5 {
			// take the top 5
			for last := len(collection); last > (len(collection) - 5); last-- {
				q := collection[last].question
				topres := ""
				currentTop := -1
				for _, res := range q.Responses {
					if res.Count > currentTop {
						currentTop = res.Count
						topres = res.Response
					}
				}
				ques := recent{collection[last].question, topres}
				questions = append(questions, &ques)
			}
		} else {
			for i := len(collection); i > 0; i-- {
				q := collection[i].question
				topres := ""
				currentTop := -1
				for _, res := range q.Responses {
					if res.Count > currentTop {
						currentTop = res.Count
						topres = res.Response
					}
				}
				ques := recent{collection[i].question, topres}
				questions = append(questions, &ques)
			}
		}
		log.Println(len(questions))
		if len(questions) != 0 {
			r.HTML(200, "indexwithrecentpolls", questions)
		} else {
			r.HTML(200, "index", nil)
		}

	})

	m.Get("/poll/:pollNumber", func(r render.Render, params martini.Params) {
		id, err := strconv.Atoi(params["pollNumber"])
		if err != nil {
			// should redirect here maybe 404?
			log.Println(err)
			r.Redirect("/")
		}
		if poll, ok := collection[id]; ok {
			r.HTML(200, "poll", poll.question)
		} else {
			// redirect maybe 404
			r.Redirect("/")
		}
	})

	// create a poll
	m.Post("/poll", func(req *http.Request, r render.Render, params martini.Params) {
		id := len(collection) + 1
		// parse form
		err := req.ParseForm()
		if err != nil {
			r.Redirect("/")
		}
		p := &Poll{
			broadcast:        make(chan Comment),
			register:         make(chan *connection),
			unregister:       make(chan *connection),
			connections:      make(map[*connection]bool),
			graphConnections: make(map[*connection]bool),
			graphRegister:    make(chan *connection),
			graphUnregister:  make(chan *connection),
			update:           make(chan int),
			question:         GenerateQuestion(id, req.PostForm.Get("pollquestion"), req.PostForm.Get("pollresponse1"), req.PostForm.Get("pollresponse2"), req.PostForm.Get("pollresponse3"), req.PostForm.Get("pollresponse4")),
		}
		go p.run()
		collection[id] = p
		r.Redirect("/poll/" + strconv.Itoa(id))
	})

	m.Post("/poll/:pollNumber/:response", func(params martini.Params) {
		id, err := strconv.Atoi(params["pollNumber"])
		if err != nil {
			log.Println(err)
		}
		// TODO: check the response and id
		collection[id].question.Responses[params["response"]].Count++
		// send an update to change the charts
		collection[id].update <- id
	})

	m.Get("/login", func(r render.Render) {
		r.HTML(200, "login", nil)
	})

	m.Get("/about", func(r render.Render) {
		r.HTML(200, "about", nil)
	})

	m.Get("/data/:id", serveWebsocket)

	m.Get("/graph/:id", serveGraphWs)

	m.Run()
}
<commit_msg>not found handling and oauth fix<commit_after>package main

import (
	"log"
	"net/http"
	"strconv"

	"github.com/go-martini/martini"
	//"github.com/martini-contrib/gzip"
	"github.com/martini-contrib/oauth2"
	"github.com/martini-contrib/render"
	"github.com/martini-contrib/sessions"
)

func main() {
	m := martini.Classic()
	//m.Use(gzip.All())
	m.Use(render.Renderer(render.Options{
		Directory:       "templates",
		Layout:          "layout",
		Extensions:      []string{".tmpl", ".html"},
		HTMLContentType: "application/xhtml+xml",
	}))
	m.Use(sessions.Sessions("my_session", sessions.NewCookieStore([]byte("pollchatsecretkey"))))
	m.Use(oauth2.Google(&oauth2.Options{
		ClientId:     pollchat.clientId,
		ClientSecret: pollchat.clientSecret,
		RedirectURL:  "http://pollchat.co.uk/oauth2callback",
		Scopes:       []string{"https://www.googleapis.com/auth/drive"},
	}))
	oauth2.PathLogin = "/oauth2login"
	// add an auth step here to redirect to /login if not authed
	m.Get("/", func(r render.Render, tokens oauth2.Tokens) {
		if tokens.IsExpired() {
			r.Redirect("/login")
		}
		type recent struct {
			Q   *Question
			Top string
		}
		questions := make([]*recent, 0) //questions = append(questions, question)
		if len(collection) > 5 {
			// take the top 5
			for last := len(collection); last > (len(collection) - 5); last-- {
				q := collection[last].question
				topres := ""
				currentTop := -1
				for _, res := range q.Responses {
					if res.Count > currentTop {
						currentTop = res.Count
						topres = res.Response
					}
				}
				ques := recent{collection[last].question, topres}
				questions = append(questions, &ques)
			}
		} else {
			for i := len(collection); i > 0; i-- {
				q := collection[i].question
				topres := ""
				currentTop := -1
				for _, res := range q.Responses {
					if res.Count > currentTop {
						currentTop = res.Count
						topres = res.Response
					}
				}
				ques := recent{collection[i].question, topres}
				questions = append(questions, &ques)
			}
		}
		log.Println(len(questions))
		if len(questions) != 0 {
			r.HTML(200, "indexwithrecentpolls", questions)
		} else {
			r.HTML(200, "index", nil)
		}

	})

	m.Get("/poll/:pollNumber", func(r render.Render, params martini.Params) {
		id, err := strconv.Atoi(params["pollNumber"])
		if err != nil {
			// should redirect here maybe 404?
			log.Println(err)
			r.Redirect("/")
		}
		if poll, ok := collection[id]; ok {
			r.HTML(200, "poll", poll.question)
		} else {
			// redirect maybe 404
			r.Redirect("/")
		}
	})

	// create a poll
	m.Post("/poll", func(req *http.Request, r render.Render, params martini.Params) {
		id := len(collection) + 1
		// parse form
		err := req.ParseForm()
		if err != nil {
			r.Redirect("/")
		}
		p := &Poll{
			broadcast:        make(chan Comment),
			register:         make(chan *connection),
			unregister:       make(chan *connection),
			connections:      make(map[*connection]bool),
			graphConnections: make(map[*connection]bool),
			graphRegister:    make(chan *connection),
			graphUnregister:  make(chan *connection),
			update:           make(chan int),
			question:         GenerateQuestion(id, req.PostForm.Get("pollquestion"), req.PostForm.Get("pollresponse1"), req.PostForm.Get("pollresponse2"), req.PostForm.Get("pollresponse3"), req.PostForm.Get("pollresponse4")),
		}
		go p.run()
		collection[id] = p
		r.Redirect("/poll/" + strconv.Itoa(id))
	})

	m.Post("/poll/:pollNumber/:response", func(params martini.Params) {
		id, err := strconv.Atoi(params["pollNumber"])
		if err != nil {
			log.Println(err)
		}
		// TODO: check the response and id
		collection[id].question.Responses[params["response"]].Count++
		// send an update to change the charts
		collection[id].update <- id
	})

	m.Get("/login", func(r render.Render) {
		r.HTML(200, "login", nil)
	})

	m.Get("/about", func(r render.Render) {
		r.HTML(200, "about", nil)
	})

	m.Get("/data/:id", serveWebsocket)

	m.Get("/graph/:id", serveGraphWs)

	m.NotFound(func(r render.Render) {
		r.HTML(200, "404", nil)
	})

	m.Run()
}
<|endoftext|>


<commit_before>package main

import (
	"cahbot/secrets"
	"cahbot/tgbotapi"
	"log"
)

func main() {
	bot, err := NewCAHBot(secrets.Token)
	if err != nil {
		log.Panic(err)
	}
	defer bot.db_conn.Close()

	// Remove when deployed
	bot.Debug = true

	log.Printf("Authorized on account %s", bot.Self.UserName)

	u := tgbotapi.NewUpdate(0)
	u.Timeout = 60

	err = bot.UpdatesChan(u)

	for update := range bot.Updates {
		go bot.HandleUpdate(&update)
	}
}
<commit_msg>Created go routine for cleaning up games that haven't been played in a while<commit_after>package main

import (
	"cahbot/secrets"
	"cahbot/tgbotapi"
	"log"
	"time"
)

func main() {
	bot, err := NewCAHBot(secrets.Token)
	if err != nil {
		log.Panic(err)
	}
	defer bot.db_conn.Close()

	// Remove when deployed
	bot.Debug = true

	log.Printf("Authorized on account %s", bot.Self.UserName)

	u := tgbotapi.NewUpdate(0)
	u.Timeout = 60

	err = bot.UpdatesChan(u)
	c := time.Tick(1 * time.Minute)
	go func() {
		for now := range c {
			log.Printf("%v %s\n", now, "This is when we would clean up the database.")
		}
	}()

	for update := range bot.Updates {
		go bot.HandleUpdate(&update)
	}
}
<|endoftext|>


<commit_before>package common

import (
	"bytes"
	"container/list"
	"fmt"
	"runtime"
	"strconv"
	"sync"
	"time"
)

type RollingAvg struct {
	size int
	nums *list.List
	sum  int
	Avg  int
}

func NewRollingAvg(size int) *RollingAvg {
	return &RollingAvg{
		size: size,
		nums: list.New(),
		sum:  0,
		Avg:  0,
	}
}

func (r *RollingAvg) Add(num int) {
	r.sum += num
	r.nums.PushFront(num)
	if r.nums.Len() > r.size {
		r.sum -= r.nums.Back().Value.(int)
		r.nums.Remove(r.nums.Back())
	}
	r.Avg = r.sum / r.nums.Len()
}

// process-global stats server

type msLatencyMsg struct {
	name string
	x    int64
}

type snapshotMsg struct {
	stats map[string]int64
	done  chan bool
}

var initOnce sync.Once
var statsChan chan interface{} = make(chan interface{}, 256)

func initTaskOnce() {
	initOnce.Do(func() {
		go statsTask()
	})
}

func statsTask() {
	msCounts := make(map[string]int64)
	msSums := make(map[string]int64)

	for raw := range statsChan {
		switch msg := raw.(type) {
		case *msLatencyMsg:
			msCounts[msg.name] += 1
			msSums[msg.name] += msg.x
		case *snapshotMsg:
			for k, cnt := range msCounts {
				msg.stats[k+".cnt"] = cnt
				msg.stats[k+".ms-avg"] = msSums[k] / cnt
			}
			msg.done <- true
		default:
			panic(fmt.Sprintf("unkown type: %T", msg))
		}
	}
}

func record(name string, x int64) {
	initTaskOnce()
	statsChan <- &msLatencyMsg{name, x}
}

func SnapshotStats() map[string]int64 {
	initTaskOnce()
	stats := make(map[string]int64)
	done := make(chan bool)
	statsChan <- &snapshotMsg{stats, done}
	<-done
	return stats
}

type Latency struct {
	name         string
	t0           time.Time
	Milliseconds int64
}

// record start time
func T0(name string) Latency {
	return Latency{
		name: name,
		t0:   time.Now(),
	}
}

// measure latency to end time, and record it
func (l Latency) T1() {
	l.Milliseconds = int64(time.Now().Sub(l.t0)) / 1000000
	if l.Milliseconds < 0 {
		panic("negative latency")
	}
	record(l.name, l.Milliseconds)

	// make sure we didn't double record
	var zero time.Time
	if l.t0 == zero {
		panic("double counted stat for " + l.name)
	}
	l.t0 = zero
}

// start measuring a sub latency
func (l Latency) T0(name string) Latency {
	return T0(l.name + "/" + name)
}

// https://blog.sgmansfield.com/2015/12/goroutine-ids/
//
// this is for debugging only (e.g., if we want to correlate a trace
// with a core dump
func GetGoroutineID() uint64 {
	b := make([]byte, 64)
	b = b[:runtime.Stack(b, false)]
	b = bytes.TrimPrefix(b, []byte("goroutine "))
	b = b[:bytes.IndexByte(b, ' ')]
	n, _ := strconv.ParseUint(string(b), 10, 64)
	return n
}

func Max(x int, y int) int {
	if x > y {
		return x
	} else {
		return y
	}
}

func Min(x int, y int) int {
	if x < y {
		return x
	} else {
		return y
	}
}
<commit_msg>Convert Latency to a pointer so that methods work on it (previously l.Milliseconds would always be 0 becaust l.T1() worked on a copy of l).<commit_after>package common

import (
	"bytes"
	"container/list"
	"fmt"
	"runtime"
	"strconv"
	"sync"
	"time"
)

type RollingAvg struct {
	size int
	nums *list.List
	sum  int
	Avg  int
}

func NewRollingAvg(size int) *RollingAvg {
	return &RollingAvg{
		size: size,
		nums: list.New(),
		sum:  0,
		Avg:  0,
	}
}

func (r *RollingAvg) Add(num int) {
	r.sum += num
	r.nums.PushFront(num)
	if r.nums.Len() > r.size {
		r.sum -= r.nums.Back().Value.(int)
		r.nums.Remove(r.nums.Back())
	}
	r.Avg = r.sum / r.nums.Len()
}

// process-global stats server

type msLatencyMsg struct {
	name string
	x    int64
}

type snapshotMsg struct {
	stats map[string]int64
	done  chan bool
}

var initOnce sync.Once
var statsChan chan interface{} = make(chan interface{}, 256)

func initTaskOnce() {
	initOnce.Do(func() {
		go statsTask()
	})
}

func statsTask() {
	msCounts := make(map[string]int64)
	msSums := make(map[string]int64)

	for raw := range statsChan {
		switch msg := raw.(type) {
		case *msLatencyMsg:
			msCounts[msg.name] += 1
			msSums[msg.name] += msg.x
		case *snapshotMsg:
			for k, cnt := range msCounts {
				msg.stats[k+".cnt"] = cnt
				msg.stats[k+".ms-avg"] = msSums[k] / cnt
			}
			msg.done <- true
		default:
			panic(fmt.Sprintf("unkown type: %T", msg))
		}
	}
}

func record(name string, x int64) {
	initTaskOnce()
	statsChan <- &msLatencyMsg{name, x}
}

func SnapshotStats() map[string]int64 {
	initTaskOnce()
	stats := make(map[string]int64)
	done := make(chan bool)
	statsChan <- &snapshotMsg{stats, done}
	<-done
	return stats
}

type Latency struct {
	name         string
	t0           time.Time
	Milliseconds int64
}

// record start time
func T0(name string) *Latency {
	return &Latency{
		name: name,
		t0:   time.Now(),
	}
}

// measure latency to end time, and record it
func (l *Latency) T1() {
	l.Milliseconds = int64(time.Now().Sub(l.t0)) / 1000000
	if l.Milliseconds < 0 {
		panic("negative latency")
	}
	record(l.name, l.Milliseconds)

	// make sure we didn't double record
	var zero time.Time
	if l.t0 == zero {
		panic("double counted stat for " + l.name)
	}
	l.t0 = zero
}

// start measuring a sub latency
func (l *Latency) T0(name string) *Latency {
	return T0(l.name + "/" + name)
}

// https://blog.sgmansfield.com/2015/12/goroutine-ids/
//
// this is for debugging only (e.g., if we want to correlate a trace
// with a core dump
func GetGoroutineID() uint64 {
	b := make([]byte, 64)
	b = b[:runtime.Stack(b, false)]
	b = bytes.TrimPrefix(b, []byte("goroutine "))
	b = b[:bytes.IndexByte(b, ' ')]
	n, _ := strconv.ParseUint(string(b), 10, 64)
	return n
}

func Max(x int, y int) int {
	if x > y {
		return x
	} else {
		return y
	}
}

func Min(x int, y int) int {
	if x < y {
		return x
	} else {
		return y
	}
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"github.com/codegangsta/negroni"
	"github.com/gorilla/mux"
	"github.com/luismesas/goPi/piface"
	"github.com/luismesas/goPi/spi"
	"github.com/unrolled/render"
	"net/http"
	"strconv"
	"time"
)

var progress int

func main() {
	// Render engine
	r := render.New(render.Options{
		Layout: "layout",
	})

	// Handlers
	router := mux.NewRouter()
	router.HandleFunc("/", func(w http.ResponseWriter, req *http.Request) {
		r.HTML(w, http.StatusOK, "home", progress)
	})
	router.HandleFunc("/about", func(w http.ResponseWriter, req *http.Request) {
		r.HTML(w, http.StatusOK, "about", nil)
	})
	router.HandleFunc("/start", func(w http.ResponseWriter, req *http.Request) {
		time := req.FormValue("time")
		stepsPerMinute, _ := strconv.Atoi(req.FormValue("steps"))
		var hours, minutes, seconds int
		fmt.Sscanf(time, "%d:%d:%d", &hours, &minutes, &seconds)
		fmt.Println(hours, minutes, seconds)
		go startLapse((hours*3600)+(minutes*60)+seconds, stepsPerMinute)
		r.HTML(w, http.StatusOK, "home", progress)
	}).Methods("POST")

	// HTTP Server
	n := negroni.Classic()
	n.UseHandler(router)
	n.Run(":3000")
}

func startLapse(seconds int, stepsPerMinute int) {
	go spin(stepsPerMinute)
	time.Sleep(time.Duration(int(time.Second) * seconds))
}

func spin(stepsPerMinute int) {
	var pauseTime float64
	pauseTime = float64(60) / float64(stepsPerMinute)
	pfd := piface.NewPiFaceDigital(spi.DEFAULT_HARDWARE_ADDR, spi.DEFAULT_BUS, spi.DEFAULT_CHIP)

	// initializes pifacedigital board
	err := pfd.InitBoard()
	if err != nil {
		fmt.Printf("Error on init board: %s", err)
		return
	}

	pfd.OutputPins[2].SetValue(0)
	for {
		pfd.OutputPins[2].Toggle()
		time.Sleep(time.Second / 10)
		pfd.OutputPins[2].Toggle()
		time.Sleep(time.Duration(float64(time.Second) * pauseTime))
	}
}

func testMotor() {
	// creates a new pifacedigital instance
	pfd := piface.NewPiFaceDigital(spi.DEFAULT_HARDWARE_ADDR, spi.DEFAULT_BUS, spi.DEFAULT_CHIP)

	// initializes pifacedigital board
	err := pfd.InitBoard()
	if err != nil {
		fmt.Printf("Error on init board: %s", err)
		return
	}
	pfd.OutputPins[0].Toggle()
	time.Sleep(time.Second / 10)
	pfd.OutputPins[0].Toggle()
}
<commit_msg>adder running var<commit_after>package main

import (
	"fmt"
	"github.com/codegangsta/negroni"
	"github.com/gorilla/mux"
	"github.com/luismesas/goPi/piface"
	"github.com/luismesas/goPi/spi"
	"github.com/unrolled/render"
	"net/http"
	"strconv"
	"time"
)

var progress int
var running bool

func main() {
	// Render engine
	r := render.New(render.Options{
		Layout: "layout",
	})

	// Handlers
	router := mux.NewRouter()
	router.HandleFunc("/", func(w http.ResponseWriter, req *http.Request) {
		r.HTML(w, http.StatusOK, "home", progress)
	})
	router.HandleFunc("/about", func(w http.ResponseWriter, req *http.Request) {
		r.HTML(w, http.StatusOK, "about", nil)
	})
	router.HandleFunc("/start", func(w http.ResponseWriter, req *http.Request) {
		time := req.FormValue("time")
		stepsPerMinute, _ := strconv.Atoi(req.FormValue("steps"))
		var hours, minutes, seconds int
		fmt.Sscanf(time, "%d:%d:%d", &hours, &minutes, &seconds)
		fmt.Println(hours, minutes, seconds)
		go startLapse((hours*3600)+(minutes*60)+seconds, stepsPerMinute)
		r.HTML(w, http.StatusOK, "home", progress)
	}).Methods("POST")

	// HTTP Server
	n := negroni.Classic()
	n.UseHandler(router)
	n.Run(":3000")
}

func startLapse(seconds int, stepsPerMinute int) {
	go spin(stepsPerMinute)
	time.Sleep(time.Duration(int(time.Second) * seconds))
	running = false
}

func spin(stepsPerMinute int) {
	var pauseTime float64
	pauseTime = float64(60) / float64(stepsPerMinute)
	pfd := piface.NewPiFaceDigital(spi.DEFAULT_HARDWARE_ADDR, spi.DEFAULT_BUS, spi.DEFAULT_CHIP)

	// initializes pifacedigital board
	err := pfd.InitBoard()
	if err != nil {
		fmt.Printf("Error on init board: %s", err)
		return
	}

	pfd.OutputPins[2].SetValue(0)
	running = true
	for running {
		pfd.OutputPins[2].Toggle()
		time.Sleep(time.Second / 10)
		pfd.OutputPins[2].Toggle()
		time.Sleep(time.Duration(float64(time.Second) * pauseTime))
	}
}

func testMotor() {
	// creates a new pifacedigital instance
	pfd := piface.NewPiFaceDigital(spi.DEFAULT_HARDWARE_ADDR, spi.DEFAULT_BUS, spi.DEFAULT_CHIP)

	// initializes pifacedigital board
	err := pfd.InitBoard()
	if err != nil {
		fmt.Printf("Error on init board: %s", err)
		return
	}
	pfd.OutputPins[0].Toggle()
	time.Sleep(time.Second / 10)
	pfd.OutputPins[0].Toggle()
}
<|endoftext|>


<commit_before>package main

import (
	"errors"
	"flag"
	"fmt"
	"os"
	"strconv"
	"strings"
	"text/tabwriter"
	"text/template"

	"koding/kites/kloud/api/sl"
	"koding/kites/kloud/utils/res"

	datatypes "github.com/maximilien/softlayer-go/data_types"
	"golang.org/x/net/context"
)

func init() {
	Resources.Register(vlanResource)
}

var vlanResource = &res.Resource{
	Name:        "vlan",
	Description: "Manage vlans.",
	Commands: map[string]res.Command{
		"list": new(vlanList),
		"edit": new(vlanEdit),
		"init": new(vlanInit),
	},
}

// vlanList implements a list command
type vlanList struct {
	template   string
	env        string
	datacenter string
	id         int
}

func (*vlanList) Name() string {
	return "list"
}

func (cmd *vlanList) RegisterFlags(f *flag.FlagSet) {
	f.StringVar(&cmd.template, "t", "", "Applies given text/template to slice of datacenters.")
	f.StringVar(&cmd.env, "env", "", "Koding environment of the VLAN.")
	f.StringVar(&cmd.datacenter, "dc", "", "Softlayer datacenter name of the VLAN.")
	f.IntVar(&cmd.id, "id", 0, "Prints VLAN given by the ID.")
}

func (cmd *vlanList) Run(ctx context.Context) error {
	f := &sl.Filter{
		ID:         cmd.id,
		Datacenter: cmd.datacenter,
	}
	if cmd.env != "" {
		f.Tags = sl.Tags{
			"koding-env": cmd.env,
		}
	}
	vlans, err := client.VlansByFilter(f)
	if err != nil {
		return err
	}
	switch {
	case cmd.template != "":
		t, err := template.New("list").Funcs(funcs).Parse(cmd.template)
		if err != nil {
			fmt.Fprintf(os.Stderr, "sl: failed to parse the filter: %s\n\n", err)
			break
		}
		return t.Execute(os.Stdout, vlans)
	}
	printVlans(vlans)
	return nil
}

func datacenter(v *sl.VLAN) string {
	if v.Subnet.Datacenter.Name != "" {
		return v.Subnet.Datacenter.Name
	}
	if len(v.Subnets) != 0 {
		return v.Subnets[0].Datacenter.Name
	}
	return ""
}

func printVlans(vlans sl.VLANs) {
	w := &tabwriter.Writer{}
	w.Init(os.Stdout, 0, 8, 0, '\t', 0)
	fmt.Fprintln(w, "ID\tInternal ID\tTotal\tAvailable\tInstances\tDatacenter\tTags")
	for _, v := range vlans {
		fmt.Fprintf(w, "%d\t%d\t%d\t%d\t%d\t%s\t%s\n", v.ID, v.InternalID, v.Subnet.Total,
			v.Subnet.Available, v.InstanceCount, datacenter(v), v.Tags)
	}
	w.Flush()
}

// vlanEdit implements an edit command
type vlanEdit struct {
	id   int
	tags string
}

func (*vlanEdit) Name() string {
	return "edit"
}

func (cmd *vlanEdit) RegisterFlags(f *flag.FlagSet) {
	f.IntVar(&cmd.id, "id", 0, "Vlan ID to set tags for.")
	f.StringVar(&cmd.tags, "tags", "", "Comma-separated key=value list of tags to set.")
}

func (cmd *vlanEdit) Valid() error {
	if cmd.id == 0 {
		return errors.New("empty value for -id flag")
	}
	return nil
}

func (cmd *vlanEdit) Run(ctx context.Context) error {
	if err := cmd.Valid(); err != nil {
		return err
	}

	tags := sl.NewTags(strings.Split(cmd.tags, ","))
	return client.VlanSetTags(cmd.id, tags)
}

// vlanInit implements the an init command
type vlanInit struct {
	id       int
	capacity int
	env      string
	guard    bool
}

func (*vlanInit) Name() string {
	return "init"
}

func (cmd *vlanInit) Valid() error {
	if cmd.id == 0 {
		return errors.New("empty value for -id flag")
	}
	if cmd.env == "" {
		return errors.New("empty value for -env flag")
	}
	return nil
}

func (cmd *vlanInit) RegisterFlags(f *flag.FlagSet) {
	f.IntVar(&cmd.id, "id", 0, "Vlan ID to init.")
	f.IntVar(&cmd.capacity, "cap", 0, "Vlan instance capacity.")
	f.StringVar(&cmd.env, "env", "", "Koding environment to init the Vlan for.")
	f.BoolVar(&cmd.guard, "guard", false, "Force creation of the vlanguard instance.")
}

func (cmd *vlanInit) Run(ctx context.Context) error {
	if err := cmd.Valid(); err != nil {
		return err
	}

	// TODO(rjeczalik): add sl.VlansByID
	vlans, err := client.VlansByFilter(&sl.Filter{ID: cmd.id})
	if err != nil {
		return err
	}
	if len(vlans) != 1 {
		return fmt.Errorf("want 1 vlan, got %d: %+v", len(vlans), vlans)
	}
	vlan := vlans[0]

	// If VLAN has one attached instance to it and the instance is removed,
	// the VLAN is removed as well. That's why we're adding dummy instance
	// to persist the VLAN as reference-counting is race-prone in
	// systems with eventual consistency.
	if vlan.InstanceCount == 0 || cmd.guard {
		// TODO(rjeczalik): add instance creation API

		keys, err := client.KeysByFilter(&sl.Filter{Label: "kloud"})
		if err != nil {
			return err
		}

		instance := datatypes.SoftLayer_Virtual_Guest_Template{
			Hostname:          "vlanguard",
			Domain:            "koding.io",
			StartCpus:         1,
			MaxMemory:         1024,
			HourlyBillingFlag: true,
			LocalDiskFlag:     true,
			Datacenter: datatypes.Datacenter{
				Name: vlan.Subnet.Datacenter.Name,
			},
			PrimaryBackendNetworkComponent: &datatypes.PrimaryBackendNetworkComponent{
				NetworkVlan: datatypes.NetworkVlan{
					Id: cmd.id,
				},
			},
			SshKeys: []datatypes.SshKey{{Id: keys[0].ID}},
			OperatingSystemReferenceCode: "UBUNTU_LATEST",
		}

		svc, err := client.GetSoftLayer_Virtual_Guest_Service()
		if err != nil {
			return err
		}

		fmt.Printf("Creating vlanguard instance for vlan id=%d... ", cmd.id)

		obj, err := svc.CreateObject(instance)
		if err != nil {
			return err
		}

		fmt.Printf("ok (id=%d)\n", obj.Id)
	}

	tags := vlan.Tags
	tags["koding-env"] = cmd.env
	if cmd.capacity > 0 {
		// Softlayer has no mean to discover VLAN capacity, as the subnets
		// are being added on demand. However the IBM guys said e.g.
		// the capacity for VLAN used for testing is 250 instances and
		// each VLAN shouldn't have more instances attached...
		tags["koding-vlan-cap"] = strconv.Itoa(cmd.capacity)
	}

	return client.VlanSetTags(vlan.ID, tags)
}
<commit_msg>scripts/sl: workaround for some vlans that have no primary subnet info<commit_after>package main

import (
	"errors"
	"flag"
	"fmt"
	"os"
	"strconv"
	"strings"
	"text/tabwriter"
	"text/template"

	"koding/kites/kloud/api/sl"
	"koding/kites/kloud/utils/res"

	datatypes "github.com/maximilien/softlayer-go/data_types"
	"golang.org/x/net/context"
)

func init() {
	Resources.Register(vlanResource)
}

var vlanResource = &res.Resource{
	Name:        "vlan",
	Description: "Manage vlans.",
	Commands: map[string]res.Command{
		"list": new(vlanList),
		"edit": new(vlanEdit),
		"init": new(vlanInit),
	},
}

// vlanList implements a list command
type vlanList struct {
	template   string
	env        string
	datacenter string
	id         int
}

func (*vlanList) Name() string {
	return "list"
}

func (cmd *vlanList) RegisterFlags(f *flag.FlagSet) {
	f.StringVar(&cmd.template, "t", "", "Applies given text/template to slice of datacenters.")
	f.StringVar(&cmd.env, "env", "", "Koding environment of the VLAN.")
	f.StringVar(&cmd.datacenter, "dc", "", "Softlayer datacenter name of the VLAN.")
	f.IntVar(&cmd.id, "id", 0, "Prints VLAN given by the ID.")
}

func (cmd *vlanList) Run(ctx context.Context) error {
	f := &sl.Filter{
		ID:         cmd.id,
		Datacenter: cmd.datacenter,
	}
	if cmd.env != "" {
		f.Tags = sl.Tags{
			"koding-env": cmd.env,
		}
	}
	vlans, err := client.VlansByFilter(f)
	if err != nil {
		return err
	}
	switch {
	case cmd.template != "":
		t, err := template.New("list").Funcs(funcs).Parse(cmd.template)
		if err != nil {
			fmt.Fprintf(os.Stderr, "sl: failed to parse the filter: %s\n\n", err)
			break
		}
		return t.Execute(os.Stdout, vlans)
	}
	printVlans(vlans)
	return nil
}

func datacenter(v *sl.VLAN) string {
	if v.Subnet.Datacenter.Name != "" {
		return v.Subnet.Datacenter.Name
	}
	if len(v.Subnets) != 0 {
		return v.Subnets[0].Datacenter.Name
	}
	return ""
}

func printVlans(vlans sl.VLANs) {
	w := &tabwriter.Writer{}
	w.Init(os.Stdout, 0, 8, 0, '\t', 0)
	fmt.Fprintln(w, "ID\tInternal ID\tTotal\tAvailable\tInstances\tDatacenter\tTags")
	for _, v := range vlans {
		fmt.Fprintf(w, "%d\t%d\t%d\t%d\t%d\t%s\t%s\n", v.ID, v.InternalID, v.Subnet.Total,
			v.Subnet.Available, v.InstanceCount, datacenter(v), v.Tags)
	}
	w.Flush()
}

// vlanEdit implements an edit command
type vlanEdit struct {
	id   int
	tags string
}

func (*vlanEdit) Name() string {
	return "edit"
}

func (cmd *vlanEdit) RegisterFlags(f *flag.FlagSet) {
	f.IntVar(&cmd.id, "id", 0, "Vlan ID to set tags for.")
	f.StringVar(&cmd.tags, "tags", "", "Comma-separated key=value list of tags to set.")
}

func (cmd *vlanEdit) Valid() error {
	if cmd.id == 0 {
		return errors.New("empty value for -id flag")
	}
	return nil
}

func (cmd *vlanEdit) Run(ctx context.Context) error {
	if err := cmd.Valid(); err != nil {
		return err
	}

	tags := sl.NewTags(strings.Split(cmd.tags, ","))
	return client.VlanSetTags(cmd.id, tags)
}

// vlanInit implements the an init command
type vlanInit struct {
	id       int
	capacity int
	env      string
	guard    bool
}

func (*vlanInit) Name() string {
	return "init"
}

func (cmd *vlanInit) Valid() error {
	if cmd.id == 0 {
		return errors.New("empty value for -id flag")
	}
	if cmd.env == "" {
		return errors.New("empty value for -env flag")
	}
	return nil
}

func (cmd *vlanInit) RegisterFlags(f *flag.FlagSet) {
	f.IntVar(&cmd.id, "id", 0, "Vlan ID to init.")
	f.IntVar(&cmd.capacity, "cap", 0, "Vlan instance capacity.")
	f.StringVar(&cmd.env, "env", "", "Koding environment to init the Vlan for.")
	f.BoolVar(&cmd.guard, "guard", false, "Force creation of the vlanguard instance.")
}

func (cmd *vlanInit) Run(ctx context.Context) error {
	if err := cmd.Valid(); err != nil {
		return err
	}

	// TODO(rjeczalik): add sl.VlansByID
	vlans, err := client.VlansByFilter(&sl.Filter{ID: cmd.id})
	if err != nil {
		return err
	}
	if len(vlans) != 1 {
		return fmt.Errorf("want 1 vlan, got %d: %+v", len(vlans), vlans)
	}
	vlan := vlans[0]

	// If VLAN has one attached instance to it and the instance is removed,
	// the VLAN is removed as well. That's why we're adding dummy instance
	// to persist the VLAN as reference-counting is race-prone in
	// systems with eventual consistency.
	if vlan.InstanceCount == 0 || cmd.guard {
		// TODO(rjeczalik): add instance creation API

		keys, err := client.KeysByFilter(&sl.Filter{Label: "kloud"})
		if err != nil {
			return err
		}

		datacenter := vlan.Subnet.Datacenter.Name

		// Some vlan has no primary subnet attached, we need to get
		// the datacenter name from first additional subnet.
		if datacenter == "" && len(vlan.Subnets) != 0 {
			datacenter = vlan.Subnets[0].Datacenter.Name
		}

		instance := datatypes.SoftLayer_Virtual_Guest_Template{
			Hostname:          "vlanguard",
			Domain:            "koding.io",
			StartCpus:         1,
			MaxMemory:         1024,
			HourlyBillingFlag: true,
			LocalDiskFlag:     true,
			Datacenter: datatypes.Datacenter{
				Name: datacenter,
			},
			PrimaryBackendNetworkComponent: &datatypes.PrimaryBackendNetworkComponent{
				NetworkVlan: datatypes.NetworkVlan{
					Id: cmd.id,
				},
			},
			SshKeys: []datatypes.SshKey{{Id: keys[0].ID}},
			OperatingSystemReferenceCode: "UBUNTU_LATEST",
		}

		svc, err := client.GetSoftLayer_Virtual_Guest_Service()
		if err != nil {
			return err
		}

		fmt.Printf("Creating vlanguard instance for vlan id=%d... ", cmd.id)

		obj, err := svc.CreateObject(instance)
		if err != nil {
			return err
		}

		fmt.Printf("ok (id=%d)\n", obj.Id)
	}

	tags := vlan.Tags
	tags["koding-env"] = cmd.env
	if cmd.capacity > 0 {
		// Softlayer has no mean to discover VLAN capacity, as the subnets
		// are being added on demand. However the IBM guys said e.g.
		// the capacity for VLAN used for testing is 250 instances and
		// each VLAN shouldn't have more instances attached...
		tags["koding-vlan-cap"] = strconv.Itoa(cmd.capacity)
	}

	return client.VlanSetTags(vlan.ID, tags)
}
<|endoftext|>


<commit_before>package main

import (
  "fmt"
  "net/http"
)

func main() {

}

func Router(w http.ResponseWriter, r *http.Request) {

}
<commit_msg>add code for port and http server<commit_after>package main

import (
  "fmt"
  "net/http"
  "os"
)

func main() {
  port := os.Getenv("PORT")
  if port == "" {
    port = "8080"
  }

  http.HandleFunc("/", Router)
  http.ListenAndServe(":"+port, nil)
}

func Router(w http.ResponseWriter, r *http.Request) {

}
<|endoftext|>


<commit_before>// package kodingkey provides functions for generating koding.key
// and heplers for conversions.
package kodingkey

import (
	"crypto/rand"
	"encoding/base64"
	"fmt"
	"io"
	"io/ioutil"
	"strings"
)

// Number of characters in a koding key whebn converted to string.
// Must be multiple of 8.
const StringLength = 64

// Length of the koding key when converted to []byte.
// We are using base64 conversion and it uses 6/8 of the ASCII table,
// that's the reason of this calculation.
const BytesLength = StringLength * 6 / 8

// KodingKey is a byte representation of a koding.key file
// generated by "kd register" command.
type KodingKey []byte

func NewKodingKey() (KodingKey, error) {
	key := make(KodingKey, BytesLength, BytesLength)

	if _, err := io.ReadFull(rand.Reader, key); err != nil {
		return nil, err
	}

	return key, nil
}

func FromString(s string) (KodingKey, error) {
	s = strings.TrimSpace(s)

	if len(s) != 64 {
		return nil, fmt.Errorf("Length of the koding key must be %s", StringLength)
	}

	return base64.URLEncoding.DecodeString(s)
}

func FromFile(path string) (KodingKey, error) {
	data, err := ioutil.ReadFile(path)
	if err != nil {
		return nil, err
	}

	return FromString(string(data))
}

func (k KodingKey) String() string {
	return base64.URLEncoding.EncodeToString(k)
}
<commit_msg>add Bytes32 method to KodingKey<commit_after>// package kodingkey provides functions for generating koding.key
// and heplers for conversions.
package kodingkey

import (
	"crypto/rand"
	"crypto/sha256"
	"encoding/base64"
	"errors"
	"io"
	"io/ioutil"
	"strings"
)

// Length of the koding key bytes.
// Must be multiple of 6 to not create padding in string representation.
const BytesLength = 48

// Number of characters in a koding key when converted to string.
// We are using base64 conversion and it uses 6/8 of the ASCII table,
// that's the reason of this calculation.
const StringLength = BytesLength * 8 / 6

var Encoding *base64.Encoding

func init() {
	Encoding = base64.URLEncoding
}

// KodingKey is a byte representation of a koding.key file
// generated by "kd register" command.
type KodingKey []byte

// NewKodingKey returns a new random generated KodingKey of length "BytesLength".
func NewKodingKey() (KodingKey, error) {
	key := make(KodingKey, BytesLength, BytesLength)

	if _, err := io.ReadFull(rand.Reader, key); err != nil {
		return nil, err
	}

	return key, nil
}

func FromString(s string) (KodingKey, error) {
	s = strings.TrimSpace(s)

	if len(s) == 0 {
		return nil, errors.New("Zero length Koding Key")
	}

	return Encoding.DecodeString(s)
}

func FromFile(path string) (KodingKey, error) {
	data, err := ioutil.ReadFile(path)
	if err != nil {
		return nil, err
	}

	return FromString(string(data))
}

func (k KodingKey) String() string {
	return Encoding.EncodeToString(k)
}

func (k KodingKey) Bytes32() []byte {
	h := sha256.New()
	h.Write(k)
	return h.Sum(nil)
}
<|endoftext|>


<commit_before>package main

import (
	"bytes"
	"encoding/json"
	"fmt"
	"net/http"
	"net/url"
	"os"
	"strings"
)

// Data struct for JIRA JSON parsing.
type Data struct {
	WebhookEvent string
	User         struct {
		Name        string
		AvatarUrls  map[string]string
		DisplayName string
	}
	Issue struct {
		Self   string
		Key    string
		Fields struct {
			Issuetype struct {
					  IconURL string
					  Name    string
			}
			Summary string
		}
	}
	Comment struct {
		Body string
	}
	Changelog struct {
		Items []struct {
			Field      string
			FromString string
			ToString   string
		}
	}
}

// Message structure for Mattermost JSON creation.
type Message struct {
	Text     string `json:"text"`
	Username string `json:"username"`
	IconURL  string `json:"icon_url"`
}

func getMessage(request *http.Request) []byte {
	// Parse JSON from JIRA
	decoder := json.NewDecoder(request.Body)
	var data Data
	decoder.Decode(&data)

	// Get JIRA URL from "issue" section in JSON
	u, _ := url.Parse(data.Issue.Self)

	// Select action
	var action, comment string
	switch data.WebhookEvent {
	case "jira:issue_created":
		action = "created"
	case "jira:issue_updated":
		action = "updated"
	case "jira:issue_deleted":
		action = "deleted"
	}

	//Process new comment
	if len(data.Comment.Body) > 0 {
		comment = fmt.Sprintf("\nComment:\n```\n%s\n```", data.Comment.Body)
	}

	// Process changelog
	var changelog string
	if len(data.Changelog.Items) > 0 {
		for _, item := range data.Changelog.Items {
			itemName := strings.ToUpper(string(item.Field[0])) + item.Field[1:]
			if item.FromString == "" {
				item.FromString = "None"
			}
			if itemName == "Description" {
				changelog += fmt.Sprintf(
					"\nNew Description:\n```\n%s\n```",
					item.ToString,
				)
			} else {
				changelog += fmt.Sprintf(
					"\n%s: ~~%s~~ %s",
					itemName,
					item.FromString,
					item.ToString,
				)
			}
		}
	}

	// Create message for Mattermost
	text := fmt.Sprintf(
		//Message format:
		//![user_icon](user_icon_link)[UserFirstName UserSecondName](user_link) commented task ![task_icon](task_icon link)[TSK-42](issue_link) "Test task"
		//Status: ~~Done~~ Finished
		//>Comment text
		"![user_icon](%s) [%s](%s://%s/secure/ViewProfile.jspa?name=%s) %s %s ![task_icon](%s) [%s](%s://%s/browse/%s) \"%s\"%s%s",
		data.User.AvatarUrls["16x16"],
		data.User.DisplayName,
		u.Scheme,
		u.Host,
		data.User.Name,
		action,
		strings.ToLower(data.Issue.Fields.Issuetype.Name),
		data.Issue.Fields.Issuetype.IconURL,
		data.Issue.Key,
		u.Scheme,
		u.Host,
		data.Issue.Key,
		data.Issue.Fields.Summary,
		changelog,
		comment,
	)

	message := Message{
		Text:     text,
		Username: "JIRA",
		IconURL:  "https://design.atlassian.com/images/brand/logo-02.png",
	}

	JSONMessage, _ := json.Marshal(message)

	return JSONMessage
}

func index(_ http.ResponseWriter, r *http.Request) {

	// Get mattermost URL
	mattermostHookURL := r.URL.Query().Get("mattermost_hook_url")

	if len(mattermostHookURL) > 0 {
		// Get message from JIRA JSON request
		message := getMessage(r)

		// Create http-client
		req, _ := http.NewRequest("POST", mattermostHookURL, bytes.NewBuffer(message))
		req.Header.Set("Content-Type", "application/json")

		// Send data to Mattermost
		client := &http.Client{}
		resp, err := client.Do(req)
		if err != nil {
			panic(err)
		}
		defer resp.Body.Close()
	}
}

func main() {

	port := os.Getenv("PORT")
	if port == "" {
		port = "5000"
	}
	http.HandleFunc("/", index)
	http.ListenAndServe(":"+port, nil)
}
<commit_msg>Update JIRA logo<commit_after>package main

import (
	"bytes"
	"encoding/json"
	"fmt"
	"net/http"
	"net/url"
	"os"
	"strings"
)

// Data struct for JIRA JSON parsing.
type Data struct {
	WebhookEvent string
	User         struct {
		Name        string
		AvatarUrls  map[string]string
		DisplayName string
	}
	Issue struct {
		Self   string
		Key    string
		Fields struct {
			Issuetype struct {
					  IconURL string
					  Name    string
			}
			Summary string
		}
	}
	Comment struct {
		Body string
	}
	Changelog struct {
		Items []struct {
			Field      string
			FromString string
			ToString   string
		}
	}
}

// Message structure for Mattermost JSON creation.
type Message struct {
	Text     string `json:"text"`
	Username string `json:"username"`
	IconURL  string `json:"icon_url"`
}

func getMessage(request *http.Request) []byte {
	// Parse JSON from JIRA
	decoder := json.NewDecoder(request.Body)
	var data Data
	decoder.Decode(&data)

	// Get JIRA URL from "issue" section in JSON
	u, _ := url.Parse(data.Issue.Self)

	// Select action
	var action, comment string
	switch data.WebhookEvent {
	case "jira:issue_created":
		action = "created"
	case "jira:issue_updated":
		action = "updated"
	case "jira:issue_deleted":
		action = "deleted"
	}

	//Process new comment
	if len(data.Comment.Body) > 0 {
		comment = fmt.Sprintf("\nComment:\n```\n%s\n```", data.Comment.Body)
	}

	// Process changelog
	var changelog string
	if len(data.Changelog.Items) > 0 {
		for _, item := range data.Changelog.Items {
			itemName := strings.ToUpper(string(item.Field[0])) + item.Field[1:]
			if item.FromString == "" {
				item.FromString = "None"
			}
			if itemName == "Description" {
				changelog += fmt.Sprintf(
					"\nNew Description:\n```\n%s\n```",
					item.ToString,
				)
			} else {
				changelog += fmt.Sprintf(
					"\n%s: ~~%s~~ %s",
					itemName,
					item.FromString,
					item.ToString,
				)
			}
		}
	}

	// Create message for Mattermost
	text := fmt.Sprintf(
		//Message format:
		//![user_icon](user_icon_link)[UserFirstName UserSecondName](user_link) commented task ![task_icon](task_icon link)[TSK-42](issue_link) "Test task"
		//Status: ~~Done~~ Finished
		//>Comment text
		"![user_icon](%s) [%s](%s://%s/secure/ViewProfile.jspa?name=%s) %s %s ![task_icon](%s) [%s](%s://%s/browse/%s) \"%s\"%s%s",
		data.User.AvatarUrls["16x16"],
		data.User.DisplayName,
		u.Scheme,
		u.Host,
		data.User.Name,
		action,
		strings.ToLower(data.Issue.Fields.Issuetype.Name),
		data.Issue.Fields.Issuetype.IconURL,
		data.Issue.Key,
		u.Scheme,
		u.Host,
		data.Issue.Key,
		data.Issue.Fields.Summary,
		changelog,
		comment,
	)

	message := Message{
		Text:     text,
		Username: "JIRA",
		IconURL:  "https://raw.githubusercontent.com/unco-games/mattermost-jira/master/logo-02.png",
	}

	JSONMessage, _ := json.Marshal(message)

	return JSONMessage
}

func index(_ http.ResponseWriter, r *http.Request) {

	// Get mattermost URL
	mattermostHookURL := r.URL.Query().Get("mattermost_hook_url")

	if len(mattermostHookURL) > 0 {
		// Get message from JIRA JSON request
		message := getMessage(r)

		// Create http-client
		req, _ := http.NewRequest("POST", mattermostHookURL, bytes.NewBuffer(message))
		req.Header.Set("Content-Type", "application/json")

		// Send data to Mattermost
		client := &http.Client{}
		resp, err := client.Do(req)
		if err != nil {
			panic(err)
		}
		defer resp.Body.Close()
	}
}

func main() {

	port := os.Getenv("PORT")
	if port == "" {
		port = "5000"
	}
	http.HandleFunc("/", index)
	http.ListenAndServe(":"+port, nil)
}
<|endoftext|>


<commit_before>/*
Copyright 2017 Google Inc.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package tabletmanager

import (
	"encoding/json"
	"flag"
	"fmt"
	"io/ioutil"
	"net/http"
	"net/url"
	"path"
	"strconv"
	"time"

	"vitess.io/vitess/go/vt/vterrors"

	"vitess.io/vitess/go/timer"
	"vitess.io/vitess/go/vt/log"
	topodatapb "vitess.io/vitess/go/vt/proto/topodata"
	"vitess.io/vitess/go/vt/topo/topoproto"
)

var (
	orcAddr     = flag.String("orc_api_url", "", "Address of Orchestrator's HTTP API (e.g. http://host:port/api/). Leave empty to disable Orchestrator integration.")
	orcTimeout  = flag.Duration("orc_timeout", 30*time.Second, "Timeout for calls to Orchestrator's HTTP API")
	orcInterval = flag.Duration("orc_discover_interval", 0, "How often to ping Orchestrator's HTTP API endpoint to tell it we exist. 0 means never.")
)

type orcClient struct {
	apiRoot    *url.URL
	httpClient *http.Client
}

// newOrcClient creates a client for the Orchestrator HTTP API.
// It should only be called after flags have been parsed.
func newOrcClient() (*orcClient, error) {
	if *orcAddr == "" {
		// Orchestrator integration is disabled.
		return nil, nil
	}
	apiRoot, err := url.Parse(*orcAddr)
	if err != nil {
		return nil, vterrors.Wrapf(err, "can't parse -orc_api_url flag value (%v)", *orcAddr)
	}
	return &orcClient{
		apiRoot:    apiRoot,
		httpClient: &http.Client{Timeout: *orcTimeout},
	}, nil
}

// DiscoverLoop periodically calls orc.discover() until process termination.
// The Tablet is read from the given agent each time before calling discover().
// Usually this will be launched as a background goroutine.
func (orc *orcClient) DiscoverLoop(agent *ActionAgent) {
	if *orcInterval == 0 {
		// 0 means never.
		return
	}
	log.Infof("Starting periodic Orchestrator self-registration: API URL = %v, interval = %v", *orcAddr, *orcInterval)

	// Randomly vary the interval by +/- 25% to reduce the potential for spikes.
	ticker := timer.NewRandTicker(*orcInterval, *orcInterval/4)

	// Remember whether we've most recently succeeded or failed.
	var lastErr error

	for {
		// Do the first attempt immediately.
		err := orc.Discover(agent.Tablet())

		// Only log if we're transitioning between success and failure states.
		if (err != nil) != (lastErr != nil) {
			if err != nil {
				log.Warningf("Orchestrator self-registration attempt failed: %v", err)
			} else {
				log.Infof("Orchestrator self-registration succeeded.")
			}
		}
		lastErr = err

		// Wait for the next tick.
		// The only way to stop the loop is to terminate the process.
		<-ticker.C
	}
}

// Discover executes a single attempt to self-register with Orchestrator.
func (orc *orcClient) Discover(tablet *topodatapb.Tablet) error {
	host, port, err := mysqlHostPort(tablet)
	if err != nil {
		return err
	}
	_, err = orc.apiGet("discover", host, port)
	return err
}

// BeginMaintenance tells Orchestrator not to touch the given tablet
// until we call EndMaintenance().
func (orc *orcClient) BeginMaintenance(tablet *topodatapb.Tablet, reason string) error {
	host, port, err := mysqlHostPort(tablet)
	if err != nil {
		return err
	}
	_, err = orc.apiGet("begin-maintenance", host, port, "vitess", reason)
	return err
}

// EndMaintenance tells Orchestrator to remove the maintenance block on the
// given tablet, which should have been placed there by BeginMaintenance().
func (orc *orcClient) EndMaintenance(tablet *topodatapb.Tablet) error {
	host, port, err := mysqlHostPort(tablet)
	if err != nil {
		return err
	}
	_, err = orc.apiGet("end-maintenance", host, port)
	return err
}

func (orc *orcClient) InActiveShardRecovery(tablet *topodatapb.Tablet) (bool, error) {
	alias := fmt.Sprintf("%v.%v", tablet.GetKeyspace(), tablet.GetShard())

	// TODO(zmagg): Replace this with simpler call to active-cluster-recovery
	// when call with alias parameter is supported.
	resp, err := orc.apiGet("audit-recovery", "alias", alias)

	if err != nil {
		return false, err
	}

	var r []map[string]interface{}

	if err := json.Unmarshal(resp, &r); err != nil {
		return false, err
	}

	// Orchestrator returns a 0-length response when it has no history of recovery on this cluster.
	if len(r) == 0 {
		return false, nil
	}

	active, ok := r[0]["IsActive"].(bool)

	if !ok {
		return false, fmt.Errorf("error parsing JSON response from Orchestrator")
	}
	return active, nil
}

func mysqlHostPort(tablet *topodatapb.Tablet) (host, port string, err error) {
	mysqlPort := int(topoproto.MysqlPort(tablet))
	if mysqlPort == 0 {
		return "", "", fmt.Errorf("MySQL port is unknown for tablet %v (mysqld may not be running yet)", topoproto.TabletAliasString(tablet.Alias))
	}
	return topoproto.MysqlHostname(tablet), strconv.Itoa(mysqlPort), nil
}

// apiGet calls the given Orchestrator API endpoint.
// The final, assembled path will be URL-escaped, but things like '/' inside a
// path part can still confuse the HTTP API. We can't do anything about that
// because Orchestrator's API chose to put variable values in path elements
// rather than query arguments.
func (orc *orcClient) apiGet(pathParts ...string) ([]byte, error) {
	// Append pathParts to a copy of the apiRoot URL.
	url := *orc.apiRoot
	fullPath := make([]string, 0, len(pathParts)+1)
	fullPath = append(fullPath, url.Path)
	fullPath = append(fullPath, pathParts...)
	url.Path = path.Join(fullPath...)

	// Note that url.String() will URL-escape the path we gave it above.
	resp, err := orc.httpClient.Get(url.String())
	if err != nil {
		return nil, err
	}
	defer resp.Body.Close()
	return ioutil.ReadAll(resp.Body)
}
<commit_msg>orchestrator: Add more detail to error messages.<commit_after>/*
Copyright 2017 Google Inc.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package tabletmanager

import (
	"encoding/json"
	"flag"
	"fmt"
	"io/ioutil"
	"net/http"
	"net/url"
	"path"
	"strconv"
	"time"

	"vitess.io/vitess/go/vt/vterrors"

	"vitess.io/vitess/go/timer"
	"vitess.io/vitess/go/vt/log"
	topodatapb "vitess.io/vitess/go/vt/proto/topodata"
	"vitess.io/vitess/go/vt/topo/topoproto"
)

var (
	orcAddr     = flag.String("orc_api_url", "", "Address of Orchestrator's HTTP API (e.g. http://host:port/api/). Leave empty to disable Orchestrator integration.")
	orcTimeout  = flag.Duration("orc_timeout", 30*time.Second, "Timeout for calls to Orchestrator's HTTP API")
	orcInterval = flag.Duration("orc_discover_interval", 0, "How often to ping Orchestrator's HTTP API endpoint to tell it we exist. 0 means never.")
)

type orcClient struct {
	apiRoot    *url.URL
	httpClient *http.Client
}

// newOrcClient creates a client for the Orchestrator HTTP API.
// It should only be called after flags have been parsed.
func newOrcClient() (*orcClient, error) {
	if *orcAddr == "" {
		// Orchestrator integration is disabled.
		return nil, nil
	}
	apiRoot, err := url.Parse(*orcAddr)
	if err != nil {
		return nil, vterrors.Wrapf(err, "can't parse -orc_api_url flag value (%v)", *orcAddr)
	}
	return &orcClient{
		apiRoot:    apiRoot,
		httpClient: &http.Client{Timeout: *orcTimeout},
	}, nil
}

// DiscoverLoop periodically calls orc.discover() until process termination.
// The Tablet is read from the given agent each time before calling discover().
// Usually this will be launched as a background goroutine.
func (orc *orcClient) DiscoverLoop(agent *ActionAgent) {
	if *orcInterval == 0 {
		// 0 means never.
		return
	}
	log.Infof("Starting periodic Orchestrator self-registration: API URL = %v, interval = %v", *orcAddr, *orcInterval)

	// Randomly vary the interval by +/- 25% to reduce the potential for spikes.
	ticker := timer.NewRandTicker(*orcInterval, *orcInterval/4)

	// Remember whether we've most recently succeeded or failed.
	var lastErr error

	for {
		// Do the first attempt immediately.
		err := orc.Discover(agent.Tablet())

		// Only log if we're transitioning between success and failure states.
		if (err != nil) != (lastErr != nil) {
			if err != nil {
				log.Warningf("Orchestrator self-registration attempt failed: %v", err)
			} else {
				log.Infof("Orchestrator self-registration succeeded.")
			}
		}
		lastErr = err

		// Wait for the next tick.
		// The only way to stop the loop is to terminate the process.
		<-ticker.C
	}
}

// Discover executes a single attempt to self-register with Orchestrator.
func (orc *orcClient) Discover(tablet *topodatapb.Tablet) error {
	host, port, err := mysqlHostPort(tablet)
	if err != nil {
		return err
	}
	_, err = orc.apiGet("discover", host, port)
	return err
}

// BeginMaintenance tells Orchestrator not to touch the given tablet
// until we call EndMaintenance().
func (orc *orcClient) BeginMaintenance(tablet *topodatapb.Tablet, reason string) error {
	host, port, err := mysqlHostPort(tablet)
	if err != nil {
		return err
	}
	_, err = orc.apiGet("begin-maintenance", host, port, "vitess", reason)
	return err
}

// EndMaintenance tells Orchestrator to remove the maintenance block on the
// given tablet, which should have been placed there by BeginMaintenance().
func (orc *orcClient) EndMaintenance(tablet *topodatapb.Tablet) error {
	host, port, err := mysqlHostPort(tablet)
	if err != nil {
		return err
	}
	_, err = orc.apiGet("end-maintenance", host, port)
	return err
}

func (orc *orcClient) InActiveShardRecovery(tablet *topodatapb.Tablet) (bool, error) {
	alias := fmt.Sprintf("%v.%v", tablet.GetKeyspace(), tablet.GetShard())

	// TODO(zmagg): Replace this with simpler call to active-cluster-recovery
	// when call with alias parameter is supported.
	resp, err := orc.apiGet("audit-recovery", "alias", alias)

	if err != nil {
		return false, fmt.Errorf("error calling Orchestrator API: %v", err)
	}

	var r []map[string]interface{}

	if err := json.Unmarshal(resp, &r); err != nil {
		return false, fmt.Errorf("error parsing JSON response from Orchestrator: %v; response: %q", err, string(resp))
	}

	// Orchestrator returns a 0-length response when it has no history of recovery on this cluster.
	if len(r) == 0 {
		return false, nil
	}

	active, ok := r[0]["IsActive"].(bool)

	if !ok {
		return false, fmt.Errorf("error parsing JSON response from Orchestrator")
	}
	return active, nil
}

func mysqlHostPort(tablet *topodatapb.Tablet) (host, port string, err error) {
	mysqlPort := int(topoproto.MysqlPort(tablet))
	if mysqlPort == 0 {
		return "", "", fmt.Errorf("MySQL port is unknown for tablet %v (mysqld may not be running yet)", topoproto.TabletAliasString(tablet.Alias))
	}
	return topoproto.MysqlHostname(tablet), strconv.Itoa(mysqlPort), nil
}

// apiGet calls the given Orchestrator API endpoint.
// The final, assembled path will be URL-escaped, but things like '/' inside a
// path part can still confuse the HTTP API. We can't do anything about that
// because Orchestrator's API chose to put variable values in path elements
// rather than query arguments.
func (orc *orcClient) apiGet(pathParts ...string) ([]byte, error) {
	// Append pathParts to a copy of the apiRoot URL.
	url := *orc.apiRoot
	fullPath := make([]string, 0, len(pathParts)+1)
	fullPath = append(fullPath, url.Path)
	fullPath = append(fullPath, pathParts...)
	url.Path = path.Join(fullPath...)

	// Note that url.String() will URL-escape the path we gave it above.
	resp, err := orc.httpClient.Get(url.String())
	if err != nil {
		return nil, err
	}
	defer resp.Body.Close()
	return ioutil.ReadAll(resp.Body)
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"github.com/howeyc/fsnotify"
	"log"
	"os"
	"os/exec"
	"regexp"
	"strings"
	"time"
)

var versionStr = "0.1.0"

func main() {
	var dirArgs = []string{}
	var cmdArgs = []string{}

	var hasDash bool = false
	for n := 1; n < len(os.Args); n++ {
		arg := os.Args[n]
		if arg == "--" {
			hasDash = true
			continue
		}
		tokens := strings.SplitN(arg, "=", 2)
		flag, value := "", ""
		switch len(tokens) {
		case 1:
			flag = tokens[0]
		case 2:
			flag = tokens[0]
			value = tokens[1]
		default:
			continue
		}

		// everything after the dash, should be the command arguments
		if !hasDash && flag[0] == '-' {
			option := options.Get(flag[1:])
			if option == nil {
				log.Fatal("Invalid option: '%v'\n", flag)
			} else {
				if _, ok := option.value.(string); ok {
					option.value = value
				} else {
					option.value = true
				}
			}
		} else {
			if !hasDash {
				if exists, _ := FileExists(arg); exists {
					dirArgs = append(dirArgs, arg)
				} else {
					log.Printf("Invalid path: '%v'", arg)
				}
			} else {
				cmdArgs = append(cmdArgs, arg)
			}
		}
	}

	if options.Bool("h") {
		fmt.Println("Usage: gomon [options] [dir] [-- command]")
		for _, option := range options {
			if _, ok := option.value.(string); ok {
				fmt.Printf("  -%s=%s: %s\n", option.flag, option.value, option.description)
			} else {
				fmt.Printf("  -%s: %s\n", option.flag, option.description)
			}
		}
		os.Exit(0)
	}
	if options.Bool("v") {
		fmt.Printf("gomon %s\n", versionStr)
		os.Exit(0)
	}

	if options.Bool("install-growl-icons") {
		installGrowlIcons()
		os.Exit(0)
	}

	var cmds = CommandSet{}
	var cmd = Command(cmdArgs)

	_ = cmds

	if len(cmd) == 0 {
		if options.Bool("t") {
			cmd = goCommands["test"]
		} else if options.Bool("i") {
			cmd = goCommands["install"]
		} else if options.Bool("f") {
			cmd = goCommands["fmt"]
		} else if options.Bool("r") {
			cmd = goCommands["run"]
		} else if options.Bool("b") {
			cmd = goCommands["build"]
		} else {
			// default behavior
			cmd = goCommands["build"]
		}
		if options.Bool("x") && len(cmd) > 0 {
			cmd = append(cmd, "-x")
		}
	}

	if len(cmd) == 0 {
		fmt.Println("No command specified")
		os.Exit(2)
	}

	if len(dirArgs) == 0 {
		var cwd, err = os.Getwd()
		if err != nil {
			fmt.Println(err)
			os.Exit(1)
		}
		dirArgs = []string{cwd}
	}

	fmt.Println("Watching", dirArgs, "for", cmd)

	watcher, err := fsnotify.NewWatcher()

	if err != nil {
		log.Fatal(err)
	}

	for _, dir := range dirArgs {
		subfolders := Subfolders(dir)
		for _, f := range subfolders {
			err = watcher.WatchFlags(f, fsnotify.FSN_ALL)
			if err != nil {
				log.Fatal(err)
			}
		}
	}

	var wasFailed bool = false
	var task *exec.Cmd

	runCommand := func(task *exec.Cmd) {
		var err error
		err = task.Start()
		if err != nil {
			log.Println(err)
			if options.Bool("growl") {
				notifyFail(options.String("gntp"), err.Error(), "")
			}
			failed("Failed!")
			wasFailed = true
			return
		}
		err = task.Wait()
		if err != nil {
			log.Println(err)
			if options.Bool("growl") {
				notifyFail(options.String("gntp"), err.Error(), "")
			}
			failed("Failed!")
			wasFailed = true
			return
		}

		// fixed
		if wasFailed {
			wasFailed = false
			if options.Bool("growl") {
				notifyFixed(options.String("gntp"), "Congratulations! It's fixed!", "")
			}
			success("Congratulations! It's fixed!")
		}
	}

	var fired bool = false
	for {
		select {
		case e := <-watcher.Event:
			matched, err := regexp.MatchString("\\.(go|c|h)$", e.Name)
			if err != nil {
				log.Println(err)
			}

			if !matched {
				if options.Bool("d") {
					log.Println("Ignore:", e)
				}
				continue
			}

			if options.Bool("d") {
				log.Println("Event:", e)
			} else {
				log.Println(e.Name)
			}

			if !fired {
				fired = true
				go func() {
					// duration to avoid to run commands frequency at once
					select {
					case <-time.After(100 * time.Millisecond):
						fired = false
						if task != nil && task.ProcessState != nil && !task.ProcessState.Exited() {
							fmt.Println("Stopping Task...")
							err := task.Process.Kill()
							if err != nil {
								log.Println(err)
							}
						}
						fmt.Println("Running Task:", cmd)
						task = exec.Command(cmd[0], cmd[1:]...)
						task.Stdout = os.Stdout
						task.Stderr = os.Stderr
						runCommand(task)
					}
				}()
			}

		case err := <-watcher.Error:
			log.Println("Error:", err)
		}
	}

	watcher.Close()
}
<commit_msg>Should be Fatalf<commit_after>package main

import (
	"fmt"
	"github.com/howeyc/fsnotify"
	"log"
	"os"
	"os/exec"
	"regexp"
	"strings"
	"time"
)

var versionStr = "0.1.0"

func main() {
	var dirArgs = []string{}
	var cmdArgs = []string{}

	var hasDash bool = false
	for n := 1; n < len(os.Args); n++ {
		arg := os.Args[n]
		if arg == "--" {
			hasDash = true
			continue
		}
		tokens := strings.SplitN(arg, "=", 2)
		flag, value := "", ""
		switch len(tokens) {
		case 1:
			flag = tokens[0]
		case 2:
			flag = tokens[0]
			value = tokens[1]
		default:
			continue
		}

		// everything after the dash, should be the command arguments
		if !hasDash && flag[0] == '-' {
			option := options.Get(flag[1:])
			if option == nil {
				log.Fatalf("Invalid option: '%v'\n", flag)
			} else {
				if _, ok := option.value.(string); ok {
					option.value = value
				} else {
					option.value = true
				}
			}
		} else {
			if !hasDash {
				if exists, _ := FileExists(arg); exists {
					dirArgs = append(dirArgs, arg)
				} else {
					log.Printf("Invalid path: '%v'", arg)
				}
			} else {
				cmdArgs = append(cmdArgs, arg)
			}
		}
	}

	if options.Bool("h") {
		fmt.Println("Usage: gomon [options] [dir] [-- command]")
		for _, option := range options {
			if _, ok := option.value.(string); ok {
				fmt.Printf("  -%s=%s: %s\n", option.flag, option.value, option.description)
			} else {
				fmt.Printf("  -%s: %s\n", option.flag, option.description)
			}
		}
		os.Exit(0)
	}
	if options.Bool("v") {
		fmt.Printf("gomon %s\n", versionStr)
		os.Exit(0)
	}

	if options.Bool("install-growl-icons") {
		installGrowlIcons()
		os.Exit(0)
	}

	var cmds = CommandSet{}
	var cmd = Command(cmdArgs)

	_ = cmds

	if len(cmd) == 0 {
		if options.Bool("t") {
			cmd = goCommands["test"]
		} else if options.Bool("i") {
			cmd = goCommands["install"]
		} else if options.Bool("f") {
			cmd = goCommands["fmt"]
		} else if options.Bool("r") {
			cmd = goCommands["run"]
		} else if options.Bool("b") {
			cmd = goCommands["build"]
		} else {
			// default behavior
			cmd = goCommands["build"]
		}
		if options.Bool("x") && len(cmd) > 0 {
			cmd = append(cmd, "-x")
		}
	}

	if len(cmd) == 0 {
		fmt.Println("No command specified")
		os.Exit(2)
	}

	if len(dirArgs) == 0 {
		var cwd, err = os.Getwd()
		if err != nil {
			fmt.Println(err)
			os.Exit(1)
		}
		dirArgs = []string{cwd}
	}

	fmt.Println("Watching", dirArgs, "for", cmd)

	watcher, err := fsnotify.NewWatcher()

	if err != nil {
		log.Fatal(err)
	}

	for _, dir := range dirArgs {
		subfolders := Subfolders(dir)
		for _, f := range subfolders {
			err = watcher.WatchFlags(f, fsnotify.FSN_ALL)
			if err != nil {
				log.Fatal(err)
			}
		}
	}

	var wasFailed bool = false
	var task *exec.Cmd

	runCommand := func(task *exec.Cmd) {
		var err error
		err = task.Start()
		if err != nil {
			log.Println(err)
			if options.Bool("growl") {
				notifyFail(options.String("gntp"), err.Error(), "")
			}
			failed("Failed!")
			wasFailed = true
			return
		}
		err = task.Wait()
		if err != nil {
			log.Println(err)
			if options.Bool("growl") {
				notifyFail(options.String("gntp"), err.Error(), "")
			}
			failed("Failed!")
			wasFailed = true
			return
		}

		// fixed
		if wasFailed {
			wasFailed = false
			if options.Bool("growl") {
				notifyFixed(options.String("gntp"), "Congratulations! It's fixed!", "")
			}
			success("Congratulations! It's fixed!")
		}
	}

	var fired bool = false
	for {
		select {
		case e := <-watcher.Event:
			matched, err := regexp.MatchString("\\.(go|c|h)$", e.Name)
			if err != nil {
				log.Println(err)
			}

			if !matched {
				if options.Bool("d") {
					log.Println("Ignore:", e)
				}
				continue
			}

			if options.Bool("d") {
				log.Println("Event:", e)
			} else {
				log.Println(e.Name)
			}

			if !fired {
				fired = true
				go func() {
					// duration to avoid to run commands frequency at once
					select {
					case <-time.After(100 * time.Millisecond):
						fired = false
						if task != nil && task.ProcessState != nil && !task.ProcessState.Exited() {
							fmt.Println("Stopping Task...")
							err := task.Process.Kill()
							if err != nil {
								log.Println(err)
							}
						}
						fmt.Println("Running Task:", cmd)
						task = exec.Command(cmd[0], cmd[1:]...)
						task.Stdout = os.Stdout
						task.Stderr = os.Stderr
						runCommand(task)
					}
				}()
			}

		case err := <-watcher.Error:
			log.Println("Error:", err)
		}
	}

	watcher.Close()
}
<|endoftext|>


<commit_before>package main

import (
	"bufio"
	"fmt"
	"github.com/PuerkitoBio/goquery"
	"github.com/jessevdk/go-flags"
	"github.com/mattn/go-colorable"
	"io"
	"net/url"
	"os"
	"regexp"
	"strconv"
	"strings"
)

const (
	GREY    = "\033[0;30;1m"
	RED     = "\033[0;31;1m"
	GREEN   = "\033[0;32;1m"
	YELLOW  = "\033[0;33;1m"
	BLUE    = "\033[0;34;1m"
	MAGENTA = "\033[0;35;1m"
	CYAN    = "\033[0;36;1m"
	WHITE   = "\033[0;37;1m"
	END     = "\033[0m"
)

func displayContent(w io.Writer, content *goquery.Selection) {
	if content.Is("ol") || content.Is("ul") {
		li := content.Find("li")
		if li.Size() > 0 {
			li.Each(func(i int, l *goquery.Selection) {
				fmt.Fprintln(w, GREY+strconv.Itoa(i+1)+"."+END+" "+l.Text())
			})
		} else {
			fmt.Fprintln(w, content.Text())
		}
	} else {
		fmt.Fprintln(w, content.Text())
	}
}

var opts struct {
	Word  string `description:"search word"`
	Range string `long:"range" short:"r" description:"range of showing" default:"1:3"`
}

func main() {
	stdOut := bufio.NewWriter(colorable.NewColorableStdout())

	parser := flags.NewParser(&opts, flags.Default)
	parser.Name = "alc"
	parser.Usage = "WORD [OPTIONS]"

	args, err := parser.Parse()
	if err != nil {
		return
	}

	if len(args) < 1 {
		parser.WriteHelp(os.Stdout)
		return
	}

	word := url.QueryEscape(strings.Join(args, " "))
	doc, err := goquery.NewDocument("https://eow.alc.co.jp/search?q=" + word)
	if err != nil {
		panic(err)
	}

	doc.Find(".ex_sentence, .kana").Each(func(i int, ex *goquery.Selection) {
		ex.Remove()
	})

	rxrange := regexp.MustCompile(`(\d+):(\d+)`)
	rxlvl := regexp.MustCompile(`【レベル】\d+、`)
	rxkana := regexp.MustCompile(`【＠】`)

	begin, err := strconv.Atoi(rxrange.ReplaceAllString(opts.Range, "$1"))
	if err != nil {
		panic(err)
	}
	end, err := strconv.Atoi(rxrange.ReplaceAllString(opts.Range, "$2"))
	if err != nil {
		panic(err)
	}
	doc.Find("#resultsList").Each(func(i int, result *goquery.Selection) {
		result.Find(".midashi, .midashi_je").Each(func(_i int, midashi *goquery.Selection) {
			if begin <= _i+1 && _i+1 <= end {
				fmt.Fprintln(stdOut, RED+midashi.Text()+END)
				content := midashi.Next()
				content.Find(".attr").Each(func(i int, attr *goquery.Selection) {
					str := rxlvl.ReplaceAllString(attr.Text(), "")
					str = rxkana.ReplaceAllString(str, "【カナ】")
					fmt.Fprintln(stdOut, YELLOW+str+END)
				})
				if content.Is("div") {
					wordclass := content.Find(".wordclass")
					if wordclass.Size() > 0 {
						wordclass.Each(func(__i int, w *goquery.Selection) {
							fmt.Fprintln(stdOut, BLUE+w.Text()+END)
							displayContent(stdOut, w.Next())
						})
					} else {
						list := content.Find("ul, ol")
						if list.Size() > 0 {
							displayContent(stdOut, list)
						} else {
							displayContent(stdOut, content)
						}
					}
				}
			}
		})
	})

	stdOut.Flush()
}
<commit_msg>Add suggestion<commit_after>package main

import (
	"bufio"
	"fmt"
	"github.com/PuerkitoBio/goquery"
	"github.com/jessevdk/go-flags"
	"github.com/mattn/go-colorable"
	"io"
	"net/url"
	"os"
	"regexp"
	"strconv"
	"strings"
)

const (
	GREY    = "\033[0;30;1m"
	RED     = "\033[0;31;1m"
	GREEN   = "\033[0;32;1m"
	YELLOW  = "\033[0;33;1m"
	BLUE    = "\033[0;34;1m"
	MAGENTA = "\033[0;35;1m"
	CYAN    = "\033[0;36;1m"
	WHITE   = "\033[0;37;1m"
	END     = "\033[0m"
)

func displayContent(w io.Writer, content *goquery.Selection) {
	if content.Is("ol") || content.Is("ul") {
		li := content.Find("li")
		if li.Size() > 0 {
			li.Each(func(i int, l *goquery.Selection) {
				fmt.Fprintln(w, GREY+strconv.Itoa(i+1)+"."+END+" "+l.Text())
			})
		} else {
			fmt.Fprintln(w, content.Text())
		}
	} else {
		fmt.Fprintln(w, content.Text())
	}
}

var opts struct {
	Word  string `description:"search word"`
	Range string `long:"range" short:"r" description:"range of showing" default:"1:3"`
}

func main() {
	stdOut := bufio.NewWriter(colorable.NewColorableStdout())

	parser := flags.NewParser(&opts, flags.Default)
	parser.Name = "alc"
	parser.Usage = "WORD [OPTIONS]"

	args, err := parser.Parse()
	if err != nil {
		return
	}

	if len(args) < 1 {
		parser.WriteHelp(os.Stdout)
		return
	}

	word := url.QueryEscape(strings.Join(args, " "))
	doc, err := goquery.NewDocument("https://eow.alc.co.jp/search?q=" + word)
	if err != nil {
		panic(err)
	}

	doc.Find(".ex_sentence, .kana").Each(func(i int, ex *goquery.Selection) {
		ex.Remove()
	})

	rxrange := regexp.MustCompile(`(\d+):(\d+)`)
	rxlvl := regexp.MustCompile(`【レベル】\d+、`)
	rxkana := regexp.MustCompile(`【＠】`)

	begin, err := strconv.Atoi(rxrange.ReplaceAllString(opts.Range, "$1"))
	if err != nil {
		panic(err)
	}
	end, err := strconv.Atoi(rxrange.ReplaceAllString(opts.Range, "$2"))
	if err != nil {
		panic(err)
	}
	doc.Find("#resultsList").Each(func(i int, result *goquery.Selection) {
		result.Find(".midashi, .midashi_je").Each(func(_i int, midashi *goquery.Selection) {
			if begin <= _i+1 && _i+1 <= end {
				fmt.Fprintln(stdOut, RED+midashi.Text()+END)
				content := midashi.Next()
				content.Find(".attr").Each(func(i int, attr *goquery.Selection) {
					str := rxlvl.ReplaceAllString(attr.Text(), "")
					str = rxkana.ReplaceAllString(str, "【カナ】")
					fmt.Fprintln(stdOut, YELLOW+str+END)
				})
				if content.Is("div") {
					wordclass := content.Find(".wordclass")
					if wordclass.Size() > 0 {
						wordclass.Each(func(__i int, w *goquery.Selection) {
							fmt.Fprintln(stdOut, BLUE+w.Text()+END)
							displayContent(stdOut, w.Next())
						})
					} else {
						list := content.Find("ul, ol")
						if list.Size() > 0 {
							displayContent(stdOut, list)
						} else {
							displayContent(stdOut, content)
						}
					}
				}
			}
		})
	})

	doc.Find("#sas_word").Each(func(i int, sas *goquery.Selection) {
		fmt.Fprintln(stdOut, "Suggestion:")
		l := []string{}
		sas.Find("span > a").Each(func(_i int, w *goquery.Selection) {
			l = append(l, w.Text())
		})
		fmt.Fprintln(stdOut, "\t"+BLUE+strings.Join(l, ", ")+END)
	})

	stdOut.Flush()
}
<|endoftext|>


<commit_before>package negroni

import (
	"bufio"
	"fmt"
	"net"
	"net/http"
)

// ResponseWriter is a wrapper around http.ResponseWriter that provides extra information about
// the response. It is recommended that middleware handlers use this construct to wrap a responsewriter
// if the functionality calls for it.
type ResponseWriter interface {
	http.ResponseWriter
	http.Flusher
	// Status returns the status code of the response or 200 if the response has
	// not been written (as this is the default response code in net/http)
	Status() int
	// Written returns whether or not the ResponseWriter has been written.
	Written() bool
	// Size returns the size of the response body.
	Size() int
	// Before allows for a function to be called before the ResponseWriter has been written to. This is
	// useful for setting headers or any other operations that must happen before a response has been written.
	Before(func(ResponseWriter))
}

type beforeFunc func(ResponseWriter)

// NewResponseWriter creates a ResponseWriter that wraps an http.ResponseWriter
func NewResponseWriter(rw http.ResponseWriter) ResponseWriter {
	return &responseWriter{
		ResponseWriter: rw,
	}
}

type responseWriter struct {
	http.ResponseWriter
	status      int
	size        int
	beforeFuncs []beforeFunc
	wroteHeader bool
}

func (rw *responseWriter) WriteHeader(s int) {
	rw.status = s
	rw.callBefore()
	rw.ResponseWriter.WriteHeader(s)
	rw.wroteHeader = true
}

func (rw *responseWriter) Write(b []byte) (int, error) {
	if !rw.Written() {
		// The status will be StatusOK if WriteHeader has not been called yet
		rw.WriteHeader(http.StatusOK)
		rw.wroteHeader = true
	}
	size, err := rw.ResponseWriter.Write(b)
	rw.size += size
	return size, err
}

func (rw *responseWriter) Status() int {
	// Default status code is 200
	if !rw.Written() {
		return http.StatusOK
	}

	return rw.status
}

func (rw *responseWriter) Size() int {
	return rw.size
}

func (rw *responseWriter) Written() bool {
	return rw.wroteHeader
}

func (rw *responseWriter) Before(before func(ResponseWriter)) {
	rw.beforeFuncs = append(rw.beforeFuncs, before)
}

func (rw *responseWriter) Hijack() (net.Conn, *bufio.ReadWriter, error) {
	hijacker, ok := rw.ResponseWriter.(http.Hijacker)
	if !ok {
		return nil, nil, fmt.Errorf("the ResponseWriter doesn't support the Hijacker interface")
	}
	return hijacker.Hijack()
}

func (rw *responseWriter) CloseNotify() <-chan bool {
	return rw.ResponseWriter.(http.CloseNotifier).CloseNotify()
}

func (rw *responseWriter) callBefore() {
	for i := len(rw.beforeFuncs) - 1; i >= 0; i-- {
		rw.beforeFuncs[i](rw)
	}
}

func (rw *responseWriter) Flush() {
	flusher, ok := rw.ResponseWriter.(http.Flusher)
	if ok {
		flusher.Flush()
	}
}
<commit_msg>Remove redundant set of `wroteHeader`<commit_after>package negroni

import (
	"bufio"
	"fmt"
	"net"
	"net/http"
)

// ResponseWriter is a wrapper around http.ResponseWriter that provides extra information about
// the response. It is recommended that middleware handlers use this construct to wrap a responsewriter
// if the functionality calls for it.
type ResponseWriter interface {
	http.ResponseWriter
	http.Flusher
	// Status returns the status code of the response or 200 if the response has
	// not been written (as this is the default response code in net/http)
	Status() int
	// Written returns whether or not the ResponseWriter has been written.
	Written() bool
	// Size returns the size of the response body.
	Size() int
	// Before allows for a function to be called before the ResponseWriter has been written to. This is
	// useful for setting headers or any other operations that must happen before a response has been written.
	Before(func(ResponseWriter))
}

type beforeFunc func(ResponseWriter)

// NewResponseWriter creates a ResponseWriter that wraps an http.ResponseWriter
func NewResponseWriter(rw http.ResponseWriter) ResponseWriter {
	return &responseWriter{
		ResponseWriter: rw,
	}
}

type responseWriter struct {
	http.ResponseWriter
	status      int
	size        int
	beforeFuncs []beforeFunc
	wroteHeader bool
}

func (rw *responseWriter) WriteHeader(s int) {
	rw.status = s
	rw.callBefore()
	rw.ResponseWriter.WriteHeader(s)
	rw.wroteHeader = true
}

func (rw *responseWriter) Write(b []byte) (int, error) {
	if !rw.Written() {
		// The status will be StatusOK if WriteHeader has not been called yet
		rw.WriteHeader(http.StatusOK)
	}
	size, err := rw.ResponseWriter.Write(b)
	rw.size += size
	return size, err
}

func (rw *responseWriter) Status() int {
	// Default status code is 200
	if !rw.Written() {
		return http.StatusOK
	}

	return rw.status
}

func (rw *responseWriter) Size() int {
	return rw.size
}

func (rw *responseWriter) Written() bool {
	return rw.wroteHeader
}

func (rw *responseWriter) Before(before func(ResponseWriter)) {
	rw.beforeFuncs = append(rw.beforeFuncs, before)
}

func (rw *responseWriter) Hijack() (net.Conn, *bufio.ReadWriter, error) {
	hijacker, ok := rw.ResponseWriter.(http.Hijacker)
	if !ok {
		return nil, nil, fmt.Errorf("the ResponseWriter doesn't support the Hijacker interface")
	}
	return hijacker.Hijack()
}

func (rw *responseWriter) CloseNotify() <-chan bool {
	return rw.ResponseWriter.(http.CloseNotifier).CloseNotify()
}

func (rw *responseWriter) callBefore() {
	for i := len(rw.beforeFuncs) - 1; i >= 0; i-- {
		rw.beforeFuncs[i](rw)
	}
}

func (rw *responseWriter) Flush() {
	flusher, ok := rw.ResponseWriter.(http.Flusher)
	if ok {
		flusher.Flush()
	}
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"fmt"
	"net/http"
	"net/url"
	"os"
	"time"

	"github.com/go-kit/kit/log/level"
	"github.com/justwatchcom/elasticsearch_exporter/collector"
	"github.com/prometheus/client_golang/prometheus"
	"github.com/prometheus/common/version"
)

func main() {
	var (
		Name                 = "elasticsearch_exporter"
		listenAddress        = flag.String("web.listen-address", ":9108", "Address to listen on for web interface and telemetry.")
		metricsPath          = flag.String("web.telemetry-path", "/metrics", "Path under which to expose metrics.")
		esURI                = flag.String("es.uri", "http://localhost:9200", "HTTP API address of an Elasticsearch node.")
		esTimeout            = flag.Duration("es.timeout", 5*time.Second, "Timeout for trying to get stats from Elasticsearch.")
		esAllNodes           = flag.Bool("es.all", false, "Export stats for all nodes in the cluster.")
		esNode               = flag.String("es.node", "_local", "Node's name of which metrics should be exposed.")
		esExportIndices      = flag.Bool("es.indices", false, "Export stats for indices in the cluster.")
		esExportShards       = flag.Bool("es.shards", false, "Export stats for shards in the cluster (implies es.indices=true).")
		esCA                 = flag.String("es.ca", "", "Path to PEM file that contains trusted CAs for the Elasticsearch connection.")
		esClientPrivateKey   = flag.String("es.client-private-key", "", "Path to PEM file that contains the private key for client auth when connecting to Elasticsearch.")
		esClientCert         = flag.String("es.client-cert", "", "Path to PEM file that contains the corresponding cert for the private key to connect to Elasticsearch.")
		esInsecureSkipVerify = flag.Bool("es.ssl-skip-verify", false, "Skip SSL verification when connecting to Elasticsearch.")
		logLevel             = flag.String("log.level", "info", "Sets the loglevel. Valid levels are debug, info, warn, error")
		logFormat            = flag.String("log.format", "logfmt", "Sets the log format. Valid formats are json and logfmt")
		logOutput            = flag.String("log.output", "stdout", "Sets the log output. Valid outputs are stdout and stderr")
		showVersion          = flag.Bool("version", false, "Show version and exit")
	)
	flag.Parse()

	if *showVersion {
		fmt.Print(version.Print(Name))
		os.Exit(0)
	}

	logger := getLogger(*logLevel, *logOutput, *logFormat)

	esURIEnv, ok := os.LookupEnv("ES_URI")
	if ok {
		*esURI = esURIEnv
	}
	esURL, err := url.Parse(*esURI)
	if err != nil {
		_ = level.Error(logger).Log(
			"msg", "failed to parse es.uri",
			"err", err,
		)
		os.Exit(1)
	}

	// returns nil if not provided and falls back to simple TCP.
	tlsConfig := createTLSConfig(*esCA, *esClientCert, *esClientPrivateKey, *esInsecureSkipVerify)

	httpClient := &http.Client{
		Timeout: *esTimeout,
		Transport: &http.Transport{
			TLSClientConfig: tlsConfig,
		},
	}

	// version metric
	versionMetric := version.NewCollector(Name)
	prometheus.MustRegister(versionMetric)
	prometheus.MustRegister(collector.NewClusterHealth(logger, httpClient, esURL))
	prometheus.MustRegister(collector.NewNodes(logger, httpClient, esURL, *esAllNodes, *esNode))
	if *esExportIndices || *esExportShards {
		prometheus.MustRegister(collector.NewIndices(logger, httpClient, esURL, *esExportShards))
	}

	http.Handle(*metricsPath, prometheus.Handler())
	http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
		_, err = w.Write([]byte(`
			<title>Elasticsearch Exporter</title>

Elasticsearch Exporter

<a href="` + *metricsPath + `">Metrics

			`))
		if err != nil {
			_ = level.Error(logger).Log(
				"msg", "failed handling writer",
				"err", err,
			)
		}
	})

	_ = level.Info(logger).Log(
		"msg", "starting elasticsearch_exporter",
		"addr", *listenAddress,
	)

	if err := http.ListenAndServe(*listenAddress, nil); err != nil {
		_ = level.Error(logger).Log(
			"msg", "http server quit",
			"err", err,
		)
	}
}
<commit_msg>Add a more explicit description to the es.all flag<commit_after>package main

import (
	"flag"
	"fmt"
	"net/http"
	"net/url"
	"os"
	"time"

	"github.com/go-kit/kit/log/level"
	"github.com/justwatchcom/elasticsearch_exporter/collector"
	"github.com/prometheus/client_golang/prometheus"
	"github.com/prometheus/common/version"
)

func main() {
	var (
		Name                 = "elasticsearch_exporter"
		listenAddress        = flag.String("web.listen-address", ":9108", "Address to listen on for web interface and telemetry.")
		metricsPath          = flag.String("web.telemetry-path", "/metrics", "Path under which to expose metrics.")
		esURI                = flag.String("es.uri", "http://localhost:9200", "HTTP API address of an Elasticsearch node.")
		esTimeout            = flag.Duration("es.timeout", 5*time.Second, "Timeout for trying to get stats from Elasticsearch.")
		esAllNodes           = flag.Bool("es.all", false, "Export stats for all nodes in the cluster. If used, this flag will override the flag es.node.")
		esNode               = flag.String("es.node", "_local", "Node's name of which metrics should be exposed.")
		esExportIndices      = flag.Bool("es.indices", false, "Export stats for indices in the cluster.")
		esExportShards       = flag.Bool("es.shards", false, "Export stats for shards in the cluster (implies es.indices=true).")
		esCA                 = flag.String("es.ca", "", "Path to PEM file that contains trusted CAs for the Elasticsearch connection.")
		esClientPrivateKey   = flag.String("es.client-private-key", "", "Path to PEM file that contains the private key for client auth when connecting to Elasticsearch.")
		esClientCert         = flag.String("es.client-cert", "", "Path to PEM file that contains the corresponding cert for the private key to connect to Elasticsearch.")
		esInsecureSkipVerify = flag.Bool("es.ssl-skip-verify", false, "Skip SSL verification when connecting to Elasticsearch.")
		logLevel             = flag.String("log.level", "info", "Sets the loglevel. Valid levels are debug, info, warn, error")
		logFormat            = flag.String("log.format", "logfmt", "Sets the log format. Valid formats are json and logfmt")
		logOutput            = flag.String("log.output", "stdout", "Sets the log output. Valid outputs are stdout and stderr")
		showVersion          = flag.Bool("version", false, "Show version and exit")
	)
	flag.Parse()

	if *showVersion {
		fmt.Print(version.Print(Name))
		os.Exit(0)
	}

	logger := getLogger(*logLevel, *logOutput, *logFormat)

	esURIEnv, ok := os.LookupEnv("ES_URI")
	if ok {
		*esURI = esURIEnv
	}
	esURL, err := url.Parse(*esURI)
	if err != nil {
		_ = level.Error(logger).Log(
			"msg", "failed to parse es.uri",
			"err", err,
		)
		os.Exit(1)
	}

	// returns nil if not provided and falls back to simple TCP.
	tlsConfig := createTLSConfig(*esCA, *esClientCert, *esClientPrivateKey, *esInsecureSkipVerify)

	httpClient := &http.Client{
		Timeout: *esTimeout,
		Transport: &http.Transport{
			TLSClientConfig: tlsConfig,
		},
	}

	// version metric
	versionMetric := version.NewCollector(Name)
	prometheus.MustRegister(versionMetric)
	prometheus.MustRegister(collector.NewClusterHealth(logger, httpClient, esURL))
	prometheus.MustRegister(collector.NewNodes(logger, httpClient, esURL, *esAllNodes, *esNode))
	if *esExportIndices || *esExportShards {
		prometheus.MustRegister(collector.NewIndices(logger, httpClient, esURL, *esExportShards))
	}

	http.Handle(*metricsPath, prometheus.Handler())
	http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
		_, err = w.Write([]byte(`
			<title>Elasticsearch Exporter</title>

Elasticsearch Exporter

<a href="` + *metricsPath + `">Metrics

			`))
		if err != nil {
			_ = level.Error(logger).Log(
				"msg", "failed handling writer",
				"err", err,
			)
		}
	})

	_ = level.Info(logger).Log(
		"msg", "starting elasticsearch_exporter",
		"addr", *listenAddress,
	)

	if err := http.ListenAndServe(*listenAddress, nil); err != nil {
		_ = level.Error(logger).Log(
			"msg", "http server quit",
			"err", err,
		)
	}
}
<|endoftext|>


<commit_before>/*
Copyright 2015-2016, RadiantBlue Technologies, Inc.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

  http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

/*
pzsvc-gdaldem provides an endpoint for accepting PDAL requests.

Examples

  $ curl -v -X POST -H "Content-Type: application/json" \
    -d '{"source":{"bucket":"venicegeo-sample-data","key":"pointcloud/samp11-utm.laz"},"function":"info"}' http://hostIP:8080/pdal
*/
package main

import (
	"fmt"
	"log"
	"net/http"
	"os"

	"github.com/julienschmidt/httprouter"
	"github.com/venicegeo/pzsvc-gdaldem/handlers"
)

func main() {
	router := httprouter.New()

	router.GET("/", func(w http.ResponseWriter, _ *http.Request, _ httprouter.Params) {
		fmt.Fprintf(w, "Hi!")
	})

	// Setup the PDAL service.
	router.POST("/gdaldem", handlers.GdalDemHandler)

	var defaultPort = os.Getenv("PORT")
	if defaultPort == "" {
		defaultPort = "8080"
	}

	log.Println("Starting on port ", defaultPort)

	log.Println(os.Getenv("PATH"))

	log.Println(os.Getenv("LD_LIBRARY_PATH"))
	if err := http.ListenAndServe(":"+defaultPort, router); err != nil {
		log.Fatal(err)
	}
}
<commit_msg>Force rebuild<commit_after>/*
Copyright 2015-2016, RadiantBlue Technologies, Inc.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

  http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

/*
pzsvc-gdaldem provides an endpoint for accepting PDAL requests.

Examples

  $ curl -v -X POST -H "Content-Type: application/json" \
    -d '{"source":{"bucket":"venicegeo-sample-data","key":"pointcloud/samp11-utm.laz"},"function":"info"}' http://hostIP:8080/pdal
*/
package main

import (
	"fmt"
	"log"
	"net/http"
	"os"

	"github.com/julienschmidt/httprouter"
	"github.com/venicegeo/pzsvc-gdaldem/handlers"
)

func main() {
	router := httprouter.New()

	router.GET("/", func(w http.ResponseWriter, _ *http.Request, _ httprouter.Params) {
		fmt.Fprintf(w, "Hi!")
	})

	// Setup the PDAL service.
	router.POST("/gdaldem", handlers.GdalDemHandler)

	var defaultPort = os.Getenv("PORT")
	if defaultPort == "" {
		defaultPort = "8080"
	}

	log.Println("Starting on port ", defaultPort)
	log.Println(os.Getenv("PATH"))
	log.Println(os.Getenv("LD_LIBRARY_PATH"))
	if err := http.ListenAndServe(":"+defaultPort, router); err != nil {
		log.Fatal(err)
	}
}
<|endoftext|>