<commit_before>// Copyright 2015 Hajime Hoshi
//
// 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.

// +build js

package audio

import (
	"io"
	"io/ioutil"

	"github.com/gopherjs/gopherjs/js"
)

var context *js.Object

type player struct {
	src          io.ReadSeeker
	sampleRate   int
	position     float64
	bufferSource *js.Object
}

func initialize() bool {
	// Do nothing in node.js.
	if js.Global.Get("require") != js.Undefined {
		return false
	}

	class := js.Global.Get("AudioContext")
	if class == js.Undefined {
		class = js.Global.Get("webkitAudioContext")
	}
	if class == js.Undefined {
		return false
	}
	context = class.New()
	return true
}

func newPlayer(src io.ReadSeeker, sampleRate int) (*Player, error) {
	if context == nil {
		if !initialize() {
			panic("audio couldn't be initialized")
		}
	}

	p := &player{
		src:          src,
		sampleRate:   sampleRate,
		position:     context.Get("currentTime").Float(),
		bufferSource: nil,
	}
	return &Player{p}, nil
}

func toLR(data []byte) ([]int16, []int16) {
	l := make([]int16, len(data)/4)
	r := make([]int16, len(data)/4)
	for i := 0; i < len(data)/4; i++ {
		l[i] = int16(data[4*i]) | int16(data[4*i+1])<<8
		r[i] = int16(data[4*i+2]) | int16(data[4*i+3])<<8
	}
	return l, r
}

func (p *player) play() error {
	// TODO: Reading all data at once is temporary implemntation. Treat this as stream.
	buf, err := ioutil.ReadAll(p.src)
	if err != nil {
		return err
	}
	if len(buf) == 0 {
		return nil
	}
	// TODO: p.position should be updated
	if p.bufferSource != nil {
		p.bufferSource.Call("start", p.position)
		return nil
	}
	const channelNum = 2
	const bytesPerSample = channelNum * 16 / 8
	b := context.Call("createBuffer", channelNum, len(buf)/bytesPerSample, p.sampleRate)
	l := b.Call("getChannelData", 0)
	r := b.Call("getChannelData", 1)
	il, ir := toLR(buf)
	const max = 1 << 15
	for i := 0; i < len(il); i++ {
		l.SetIndex(i, float64(il[i])/max)
		r.SetIndex(i, float64(ir[i])/max)
	}
	p.bufferSource = context.Call("createBufferSource")
	p.bufferSource.Set("buffer", b)
	p.bufferSource.Call("connect", context.Get("destination"))
	p.bufferSource.Call("start", p.position)
	p.position += b.Get("duration").Float()
	return nil
}

func (p *player) close() error {
	p.bufferSource.Call("stop")
	p.bufferSource.Call("disconnect")
	return nil
}
<commit_msg>audio: Inifite stream in JS<commit_after>// Copyright 2015 Hajime Hoshi
//
// 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.

// +build js

package audio

import (
	"io"
	"time"

	"github.com/gopherjs/gopherjs/js"
)

var context *js.Object

type player struct {
	src          io.ReadSeeker
	sampleRate   int
	position     float64
	bufferSource *js.Object
}

func initialize() bool {
	// Do nothing in node.js.
	if js.Global.Get("require") != js.Undefined {
		return false
	}

	class := js.Global.Get("AudioContext")
	if class == js.Undefined {
		class = js.Global.Get("webkitAudioContext")
	}
	if class == js.Undefined {
		return false
	}
	context = class.New()
	return true
}

func newPlayer(src io.ReadSeeker, sampleRate int) (*Player, error) {
	if context == nil {
		if !initialize() {
			panic("audio couldn't be initialized")
		}
	}

	p := &player{
		src:          src,
		sampleRate:   sampleRate,
		position:     context.Get("currentTime").Float(),
		bufferSource: nil,
	}
	return &Player{p}, nil
}

func toLR(data []byte) ([]int16, []int16) {
	l := make([]int16, len(data)/4)
	r := make([]int16, len(data)/4)
	for i := 0; i < len(data)/4; i++ {
		l[i] = int16(data[4*i]) | int16(data[4*i+1])<<8
		r[i] = int16(data[4*i+2]) | int16(data[4*i+3])<<8
	}
	return l, r
}

func (p *player) proceed() error {
	buf := make([]byte, 4096)
	n, err := p.src.Read(buf)
	if 0 < n {
		const channelNum = 2
		const bytesPerSample = channelNum * 16 / 8
		b := context.Call("createBuffer", channelNum, n/bytesPerSample, p.sampleRate)
		l := b.Call("getChannelData", 0)
		r := b.Call("getChannelData", 1)
		il, ir := toLR(buf[:n])
		const max = 1 << 15
		for i := 0; i < len(il); i++ {
			l.SetIndex(i, float64(il[i])/max)
			r.SetIndex(i, float64(ir[i])/max)
		}
		p.bufferSource = context.Call("createBufferSource")
		p.bufferSource.Set("buffer", b)
		p.bufferSource.Call("connect", context.Get("destination"))
		p.bufferSource.Call("start", p.position)
		p.position += b.Get("duration").Float()
	}
	return err
}

func (p *player) play() error {
	// TODO: What if play is already called?
	go func() {
		defer p.close()
		for {
			err := p.proceed()
			if err == io.EOF {
				break
			}
			if err != nil {
				// TODO: Record the last error
				panic(err)
			}
			time.Sleep(1)
		}
	}()
	return nil
}

func (p *player) close() error {
	if p.bufferSource == nil {
		return nil
	}
	p.bufferSource.Call("stop")
	p.bufferSource.Call("disconnect")
	p.bufferSource = nil
	return nil
}
<|endoftext|>


<commit_before>package exporter

import (
	"fmt"
	log "github.com/Sirupsen/logrus"
	"github.com/kawamuray/prometheus-exporter-harness/harness"
	"github.com/prometheus/client_golang/prometheus"
	"os/exec"
	"strconv"
	"strings"
	"sync"
	"sync/atomic"
)

type Collector struct {
	BootstrapServers         string
	ConsumerGroupCommandPath string
	fetchBarrier             uintptr
	updateLock               sync.Mutex
	lastValue                map[string][]*PartitionInfo
}

func NewCollector(bootstrapServers, consumerGroupCommandPath string) *Collector {
	return &Collector{
		BootstrapServers:         bootstrapServers,
		ConsumerGroupCommandPath: consumerGroupCommandPath,
	}
}

func (col *Collector) execConsumerGroupCommand(args ...string) (string, error) {
	allArgs := append([]string{"--new-consumer", "--bootstrap-server", col.BootstrapServers}, args...)
	cmd := exec.Command(col.ConsumerGroupCommandPath, allArgs...)
	output, err := cmd.CombinedOutput()
	if err != nil {
		return "", err
	}
	return string(output), nil
}

func (col *Collector) groupList() ([]string, error) {
	output, err := col.execConsumerGroupCommand("--list")
	if err != nil {
		return nil, err
	}
	lines := strings.Split(output, "\n")
	groups := make([]string, 0, len(lines))
	for _, line := range lines {
		if line != "" {
			groups = append(groups, line)
		}
	}

	return groups, nil
}

func parseClientIdAndConsumerAddress(clientIdAndConsumerAddress string) (string, string) {
	const Separator = "_/"
	splitPoint := strings.LastIndex(clientIdAndConsumerAddress, Separator)
	if splitPoint == -1 {
		return clientIdAndConsumerAddress, ""
	}
	return clientIdAndConsumerAddress[:splitPoint], clientIdAndConsumerAddress[splitPoint+len(Separator):]
}

func parseLong(value string) int64 {
	longVal, err := strconv.ParseInt(value, 10, 64)
	if err != nil {
		return -1
	}
	return longVal
}

type PartitionInfo struct {
	Topic           string
	PartitionId     string
	CurrentOffset   int64
	Lag             int64
	ClientId        string
	ConsumerAddress string
}

func parsePartitionInfo(line string) (*PartitionInfo, error) {
	fields := strings.Split(line, ", ")
	if len(fields) != 7 {
		return nil, fmt.Errorf("malformed line")
	}

	clientId, consumerAddress := parseClientIdAndConsumerAddress(fields[6])
	partitionInfo := &PartitionInfo{
		Topic:           fields[1],
		PartitionId:     fields[2],
		CurrentOffset:   parseLong(fields[3]),
		Lag:             parseLong(fields[5]),
		ClientId:        clientId,
		ConsumerAddress: consumerAddress,
	}

	return partitionInfo, nil
}

func (col *Collector) describeGroup(group string) ([]*PartitionInfo, error) {
	output, err := col.execConsumerGroupCommand("--describe", "--group", group)
	if err != nil {
		return nil, err
	}
	lines := strings.Split(output, "\n")[1:] /* discard header line */
	partitionInfos := make([]*PartitionInfo, 0, len(lines))
	for _, line := range lines {
		if line == "" {
			continue
		}
		partitionInfo, err := parsePartitionInfo(line)
		if err != nil {
			log.Warnf("failed to parse a line of group description: '%s'", line)
			continue
		}
		partitionInfos = append(partitionInfos, partitionInfo)
	}

	return partitionInfos, nil

}

func (col *Collector) maybeUpdate() {
	// Prevent multiple queries run simultaneously
	if !atomic.CompareAndSwapUintptr(&col.fetchBarrier, 0, 1) {
		return
	}
	defer atomic.CompareAndSwapUintptr(&col.fetchBarrier, 1, 0)

	nextValue := make(map[string][]*PartitionInfo)

	groups, err := col.groupList()
	if err != nil {
		log.Errorf("failed to get group list: %s", err)
		return
	}

	for _, group := range groups {
		partitionInfos, err := col.describeGroup(group)
		if err != nil {
			log.Errorf("failed to get group description of %s: %s", group, err)
			continue
		}
		nextValue[group] = partitionInfos
	}

	col.updateLock.Lock()
	defer col.updateLock.Unlock()
	col.lastValue = nextValue
}

func (col *Collector) Collect(reg *harness.MetricRegistry) {
	col.updateLock.Lock()
	defer col.updateLock.Unlock()

	for group, partitionInfos := range col.lastValue {
		for _, partitionInfo := range partitionInfos {
			labels := map[string]string{
				"group_id":         group,
				"consumer_address": partitionInfo.ConsumerAddress,
				"client_id":        partitionInfo.ClientId,
				"topic":            partitionInfo.Topic,
				"partition":        partitionInfo.PartitionId,
			}

			reg.Get(MetricCurrentOffset).(*prometheus.GaugeVec).With(labels).Set(float64(partitionInfo.CurrentOffset))
			reg.Get(MetricOffsetLag).(*prometheus.GaugeVec).With(labels).Set(float64(partitionInfo.Lag))
		}
	}

	// Prepare next update(if necessary)
	go col.maybeUpdate()
}
<commit_msg>Allow consecutive whitespaces as fields separtor to support kafka version 0.10<commit_after>package exporter

import (
	"fmt"
	log "github.com/Sirupsen/logrus"
	"github.com/kawamuray/prometheus-exporter-harness/harness"
	"github.com/prometheus/client_golang/prometheus"
	"os/exec"
	"regexp"
	"strconv"
	"strings"
	"sync"
	"sync/atomic"
)

// Fields separator is different between kafka versions
// 0.9.X  => ", "
// 0.10.X => \s+
var ConsumerGroupCommandDescribeOutputSeparatorRegexp = regexp.MustCompile(`,?\s+`)

type Collector struct {
	BootstrapServers         string
	ConsumerGroupCommandPath string
	fetchBarrier             uintptr
	updateLock               sync.Mutex
	lastValue                map[string][]*PartitionInfo
}

func NewCollector(bootstrapServers, consumerGroupCommandPath string) *Collector {
	return &Collector{
		BootstrapServers:         bootstrapServers,
		ConsumerGroupCommandPath: consumerGroupCommandPath,
	}
}

func (col *Collector) execConsumerGroupCommand(args ...string) (string, error) {
	allArgs := append([]string{"--new-consumer", "--bootstrap-server", col.BootstrapServers}, args...)
	cmd := exec.Command(col.ConsumerGroupCommandPath, allArgs...)
	output, err := cmd.CombinedOutput()
	if err != nil {
		return "", err
	}
	return string(output), nil
}

func (col *Collector) groupList() ([]string, error) {
	output, err := col.execConsumerGroupCommand("--list")
	if err != nil {
		return nil, err
	}
	lines := strings.Split(output, "\n")
	groups := make([]string, 0, len(lines))
	for _, line := range lines {
		if line != "" {
			groups = append(groups, line)
		}
	}

	return groups, nil
}

func parseClientIdAndConsumerAddress(clientIdAndConsumerAddress string) (string, string) {
	const Separator = "_/"
	splitPoint := strings.LastIndex(clientIdAndConsumerAddress, Separator)
	if splitPoint == -1 {
		return clientIdAndConsumerAddress, ""
	}
	return clientIdAndConsumerAddress[:splitPoint], clientIdAndConsumerAddress[splitPoint+len(Separator):]
}

func parseLong(value string) int64 {
	longVal, err := strconv.ParseInt(value, 10, 64)
	if err != nil {
		return -1
	}
	return longVal
}

type PartitionInfo struct {
	Topic           string
	PartitionId     string
	CurrentOffset   int64
	Lag             int64
	ClientId        string
	ConsumerAddress string
}

func parsePartitionInfo(line string) (*PartitionInfo, error) {
	fields := ConsumerGroupCommandDescribeOutputSeparatorRegexp.Split(line, -1)
	if len(fields) != 7 {
		return nil, fmt.Errorf("malformed line")
	}

	clientId, consumerAddress := parseClientIdAndConsumerAddress(fields[6])
	partitionInfo := &PartitionInfo{
		Topic:           fields[1],
		PartitionId:     fields[2],
		CurrentOffset:   parseLong(fields[3]),
		Lag:             parseLong(fields[5]),
		ClientId:        clientId,
		ConsumerAddress: consumerAddress,
	}

	return partitionInfo, nil
}

func (col *Collector) describeGroup(group string) ([]*PartitionInfo, error) {
	output, err := col.execConsumerGroupCommand("--describe", "--group", group)
	if err != nil {
		return nil, err
	}
	lines := strings.Split(output, "\n")[1:] /* discard header line */
	partitionInfos := make([]*PartitionInfo, 0, len(lines))
	for _, line := range lines {
		if line == "" {
			continue
		}
		partitionInfo, err := parsePartitionInfo(line)
		if err != nil {
			log.Warnf("failed to parse a line of group description: '%s'", line)
			continue
		}
		partitionInfos = append(partitionInfos, partitionInfo)
	}

	return partitionInfos, nil

}

func (col *Collector) maybeUpdate() {
	// Prevent multiple queries run simultaneously
	if !atomic.CompareAndSwapUintptr(&col.fetchBarrier, 0, 1) {
		return
	}
	defer atomic.CompareAndSwapUintptr(&col.fetchBarrier, 1, 0)

	nextValue := make(map[string][]*PartitionInfo)

	groups, err := col.groupList()
	if err != nil {
		log.Errorf("failed to get group list: %s", err)
		return
	}

	for _, group := range groups {
		partitionInfos, err := col.describeGroup(group)
		if err != nil {
			log.Errorf("failed to get group description of %s: %s", group, err)
			continue
		}
		nextValue[group] = partitionInfos
	}

	col.updateLock.Lock()
	defer col.updateLock.Unlock()
	col.lastValue = nextValue
}

func (col *Collector) Collect(reg *harness.MetricRegistry) {
	col.updateLock.Lock()
	defer col.updateLock.Unlock()

	for group, partitionInfos := range col.lastValue {
		for _, partitionInfo := range partitionInfos {
			labels := map[string]string{
				"group_id":         group,
				"consumer_address": partitionInfo.ConsumerAddress,
				"client_id":        partitionInfo.ClientId,
				"topic":            partitionInfo.Topic,
				"partition":        partitionInfo.PartitionId,
			}

			reg.Get(MetricCurrentOffset).(*prometheus.GaugeVec).With(labels).Set(float64(partitionInfo.CurrentOffset))
			reg.Get(MetricOffsetLag).(*prometheus.GaugeVec).With(labels).Set(float64(partitionInfo.Lag))
		}
	}

	// Prepare next update(if necessary)
	go col.maybeUpdate()
}
<|endoftext|>


<commit_before><commit_msg>gidallocator: fix warning message<commit_after><|endoftext|>


<commit_before>package data

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

	"github.com/cozy/cozy-stack/couchdb"
)

// HTTPStatus gives the http status for given error
func HTTPStatus(err error) (code int) {
	if os.IsNotExist(err) {
		code = http.StatusNotFound
	} else if os.IsExist(err) {
		code = http.StatusConflict
	} else if couchErr, isCouchErr := err.(*couchdb.Error); isCouchErr {
		code = couchErr.StatusCode
	}

	if code == 0 {
		code = http.StatusInternalServerError
	}

	return
}

func invalidDoctypeErr(doctype string) error {
	return fmt.Errorf("Invalid doctype '%s'", doctype)
}

var errVfsNotData = fmt.Errorf("Type io.cozy.files belongs to the vfs and cannot be manipulated from the /data endpoint.")
<commit_msg>remove dead code<commit_after>package data

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

	"github.com/cozy/cozy-stack/couchdb"
)

// HTTPStatus gives the http status for given error
func HTTPStatus(err error) (code int) {
	if os.IsNotExist(err) {
		code = http.StatusNotFound
	} else if os.IsExist(err) {
		code = http.StatusConflict
	} else if couchErr, isCouchErr := err.(*couchdb.Error); isCouchErr {
		code = couchErr.StatusCode
	}

	if code == 0 {
		code = http.StatusInternalServerError
	}

	return
}

func invalidDoctypeErr(doctype string) error {
	return fmt.Errorf("Invalid doctype '%s'", doctype)
}
<|endoftext|>


<commit_before>// Package outbound implements multiple dns client and dispatcher for outbound connection.
package outbound

import (
	"math/rand"
	"net"
	"time"

	log "github.com/Sirupsen/logrus"
	"github.com/miekg/dns"
	"github.com/shawn1m/overture/core/cache"
	"github.com/shawn1m/overture/core/common"
	"github.com/shawn1m/overture/core/hosts"
	"golang.org/x/net/proxy"
)

type Client struct {
	ResponseMessage *dns.Msg
	QuestionMessage *dns.Msg

	DNSUpstream        *common.DNSUpstream
	EDNSClientSubnetIP string
	InboundIP          string

	Hosts *hosts.Hosts
	Cache *cache.Cache
}

func NewClient(q *dns.Msg, u *common.DNSUpstream, ip string, h *hosts.Hosts, cache *cache.Cache) *Client {

	c := &Client{QuestionMessage: q.Copy(), DNSUpstream: u, InboundIP: ip, Hosts: h, Cache: cache}

	c.getEDNSClientSubnetIP()
	return c
}

func (c *Client) getEDNSClientSubnetIP() {

	switch c.DNSUpstream.EDNSClientSubnet.Policy {
	case "auto":
		if !common.IsIPMatchList(net.ParseIP(c.InboundIP), common.ReservedIPNetworkList, false, "") {
			c.EDNSClientSubnetIP = c.InboundIP
		} else {
			c.EDNSClientSubnetIP = c.DNSUpstream.EDNSClientSubnet.ExternalIP
		}
	case "disable":
	}
}

func (c *Client) ExchangeFromRemote(isCache bool, isLog bool) {

	common.SetEDNSClientSubnet(c.QuestionMessage, c.EDNSClientSubnetIP)
	c.EDNSClientSubnetIP = common.GetEDNSClientSubnetIP(c.QuestionMessage)

	var conn net.Conn
	if c.DNSUpstream.SOCKS5Address != "" {
		s, err := proxy.SOCKS5(c.DNSUpstream.Protocol, c.DNSUpstream.SOCKS5Address, nil, proxy.Direct)
		if err != nil {
			log.Warn("Get socks5 proxy dialer failed: ", err)
			return
		}
		conn, err = s.Dial(c.DNSUpstream.Protocol, c.DNSUpstream.Address)
		if err != nil {
			log.Warn("Dial DNS upstream with SOCKS5 proxy failed: ", err)
			return
		}
	} else {
		var err error
		if conn, err = net.Dial(c.DNSUpstream.Protocol, c.DNSUpstream.Address); err != nil {
			log.Warn("Dial DNS upstream failed: ", err)
			return
		}
	}

	dnsTimeout := time.Duration(c.DNSUpstream.Timeout) * time.Second / 3

	conn.SetDeadline(time.Now().Add(dnsTimeout))
	conn.SetReadDeadline(time.Now().Add(dnsTimeout))
	conn.SetWriteDeadline(time.Now().Add(dnsTimeout))

	dc := &dns.Conn{Conn: conn}
	defer dc.Close()
	err := dc.WriteMsg(c.QuestionMessage)
	if err != nil {
		log.Warn(c.DNSUpstream.Name + " Fail: Send question message failed")
		return
	}
	temp, err := dc.ReadMsg()

	if err != nil {
		if err == dns.ErrTruncated {
			log.Warn(c.DNSUpstream.Name + " Fail: Maybe this server does not support EDNS Client Subnet")
			return
		}
	}
	if temp == nil {
		log.Debug(c.DNSUpstream.Name + " Fail: Response message is nil, maybe timeout, please check your query or dns configuration")
		return
	}

	c.ResponseMessage = temp

	//for i := 0;i < len(c.ResponseMessage.Answer); i++{
	//	if c.ResponseMessage.Answer[i].Header().Rrtype == dns.TypeA || c.ResponseMessage.Answer[i].Header().Rrtype == dns.TypeAAAA{
	//		c.ResponseMessage.Answer[i].Header().Name = c.QuestionMessage.Question[0].Name
	//	}
	//	if c.ResponseMessage.Answer[i].Header().Rrtype == dns.TypeCNAME{
	//		c.ResponseMessage.Answer = c.ResponseMessage.Answer[:i+copy(c.ResponseMessage.Answer[i:], c.ResponseMessage.Answer[i+1:])]
	//		i -= 1
	//	}
	//}

	if isLog {
		c.logAnswer("")
	}

	if isCache {
		c.CacheResult()
	}
}

func (c *Client) ExchangeFromCache() bool {

	if c.Cache == nil {
		return false
	}

	m := c.Cache.Hit(cache.Key(c.QuestionMessage.Question[0], c.EDNSClientSubnetIP), c.QuestionMessage.Id)
	if m != nil {
		log.Debug("Cache Hit: " + cache.Key(c.QuestionMessage.Question[0], c.EDNSClientSubnetIP))
		c.ResponseMessage = m
		return true
	}

	return false
}

func (c *Client) ExchangeFromLocal() bool {

	if c.ExchangeFromCache() {
		return true
	}

	raw_name := c.QuestionMessage.Question[0].Name

	if c.ExchangeFromHosts(raw_name) || c.ExchangeFromIP(raw_name) {
		return true
	}

	return false
}

func (c *Client) ExchangeFromHosts(raw_name string) bool {

	if c.Hosts == nil {
		return false
	}

	name := raw_name[:len(raw_name)-1]
	ipv4List, ipv6List := c.Hosts.Find(name)

	if c.QuestionMessage.Question[0].Qtype == dns.TypeA && len(ipv4List) > 0 {
		var rrl []dns.RR
		for _, ip := range ipv4List {
			a, _ := dns.NewRR(raw_name + " IN A " + ip.String())
			rrl = append(rrl, a)
		}
		c.setLocalResponseMessage(rrl)
		if c.ResponseMessage != nil {
			return true
		}
	} else if c.QuestionMessage.Question[0].Qtype == dns.TypeAAAA && len(ipv6List) > 0 {
		var rrl []dns.RR
		for _, ip := range ipv6List {
			aaaa, _ := dns.NewRR(raw_name + " IN AAAA " + ip.String())
			rrl = append(rrl, aaaa)
		}
		c.setLocalResponseMessage(rrl)
		if c.ResponseMessage != nil {
			return true
		}
	}

	return false
}

func (c *Client) ExchangeFromIP(raw_name string) bool {

	name := raw_name[:len(raw_name)-1]
	ip := net.ParseIP(name)
	if ip == nil {
		return false
	}
	if ip.To4() == nil && ip.To16() != nil && c.QuestionMessage.Question[0].Qtype == dns.TypeAAAA {
		aaaa, _ := dns.NewRR(raw_name + " IN AAAA " + ip.String())
		c.setLocalResponseMessage([]dns.RR{aaaa})
		return true
	} else if ip.To4() != nil && c.QuestionMessage.Question[0].Qtype == dns.TypeA {
		a, _ := dns.NewRR(raw_name + " IN A " + ip.String())
		c.setLocalResponseMessage([]dns.RR{a})
		return true
	}

	return false
}

func (c *Client) setLocalResponseMessage(rrl []dns.RR) {

	shuffleRRList := func(rrl []dns.RR) {
		rand.Seed(time.Now().UnixNano())
		for i := range rrl {
			j := rand.Intn(i + 1)
			rrl[i], rrl[j] = rrl[j], rrl[i]
		}
	}

	c.ResponseMessage = new(dns.Msg)
	for _, rr := range rrl {
		c.ResponseMessage.Answer = append(c.ResponseMessage.Answer, rr)
	}
	shuffleRRList(c.ResponseMessage.Answer)
	c.ResponseMessage.SetReply(c.QuestionMessage)
	c.ResponseMessage.RecursionAvailable = true
}

func (c *Client) logAnswer(indicator string) {

	for _, a := range c.ResponseMessage.Answer {
		var name string
		if indicator != "" {
			name = indicator
		} else {
			name = c.DNSUpstream.Name
		}
		log.Debug("Answer from " + name + ": " + a.String())
	}
}

func (c *Client) CacheResult() {

	if c.Cache != nil {
		c.Cache.InsertMessage(cache.Key(c.QuestionMessage.Question[0], common.GetEDNSClientSubnetIP(c.QuestionMessage)), c.ResponseMessage)
	}
}
<commit_msg>Add error log for all types(#96)<commit_after>// Package outbound implements multiple dns client and dispatcher for outbound connection.
package outbound

import (
	"math/rand"
	"net"
	"time"

	log "github.com/Sirupsen/logrus"
	"github.com/miekg/dns"
	"github.com/shawn1m/overture/core/cache"
	"github.com/shawn1m/overture/core/common"
	"github.com/shawn1m/overture/core/hosts"
	"golang.org/x/net/proxy"
)

type Client struct {
	ResponseMessage *dns.Msg
	QuestionMessage *dns.Msg

	DNSUpstream        *common.DNSUpstream
	EDNSClientSubnetIP string
	InboundIP          string

	Hosts *hosts.Hosts
	Cache *cache.Cache
}

func NewClient(q *dns.Msg, u *common.DNSUpstream, ip string, h *hosts.Hosts, cache *cache.Cache) *Client {

	c := &Client{QuestionMessage: q.Copy(), DNSUpstream: u, InboundIP: ip, Hosts: h, Cache: cache}

	c.getEDNSClientSubnetIP()
	return c
}

func (c *Client) getEDNSClientSubnetIP() {

	switch c.DNSUpstream.EDNSClientSubnet.Policy {
	case "auto":
		if !common.IsIPMatchList(net.ParseIP(c.InboundIP), common.ReservedIPNetworkList, false, "") {
			c.EDNSClientSubnetIP = c.InboundIP
		} else {
			c.EDNSClientSubnetIP = c.DNSUpstream.EDNSClientSubnet.ExternalIP
		}
	case "disable":
	}
}

func (c *Client) ExchangeFromRemote(isCache bool, isLog bool) {

	common.SetEDNSClientSubnet(c.QuestionMessage, c.EDNSClientSubnetIP)
	c.EDNSClientSubnetIP = common.GetEDNSClientSubnetIP(c.QuestionMessage)

	var conn net.Conn
	if c.DNSUpstream.SOCKS5Address != "" {
		s, err := proxy.SOCKS5(c.DNSUpstream.Protocol, c.DNSUpstream.SOCKS5Address, nil, proxy.Direct)
		if err != nil {
			log.Warn("Get socks5 proxy dialer failed: ", err)
			return
		}
		conn, err = s.Dial(c.DNSUpstream.Protocol, c.DNSUpstream.Address)
		if err != nil {
			log.Warn("Dial DNS upstream with SOCKS5 proxy failed: ", err)
			return
		}
	} else {
		var err error
		if conn, err = net.Dial(c.DNSUpstream.Protocol, c.DNSUpstream.Address); err != nil {
			log.Warn("Dial DNS upstream failed: ", err)
			return
		}
	}

	dnsTimeout := time.Duration(c.DNSUpstream.Timeout) * time.Second / 3

	conn.SetDeadline(time.Now().Add(dnsTimeout))
	conn.SetReadDeadline(time.Now().Add(dnsTimeout))
	conn.SetWriteDeadline(time.Now().Add(dnsTimeout))

	dc := &dns.Conn{Conn: conn}
	defer dc.Close()
	err := dc.WriteMsg(c.QuestionMessage)
	if err != nil {
		log.Warn(c.DNSUpstream.Name + " Fail: Send question message failed")
		return
	}
	temp, err := dc.ReadMsg()

	if err != nil {
		if err == dns.ErrTruncated {
			log.Warn(c.DNSUpstream.Name + " Fail: Maybe this server does not support EDNS Client Subnet")
		}else{
			log.Warn(c.DNSUpstream.Name + " Fail: ", err)
		}
		return
	}
	if temp == nil {
		log.Debug(c.DNSUpstream.Name + " Fail: Response message is nil, maybe timeout, please check your query or dns configuration")
		return
	}

	c.ResponseMessage = temp

	//for i := 0;i < len(c.ResponseMessage.Answer); i++{
	//	if c.ResponseMessage.Answer[i].Header().Rrtype == dns.TypeA || c.ResponseMessage.Answer[i].Header().Rrtype == dns.TypeAAAA{
	//		c.ResponseMessage.Answer[i].Header().Name = c.QuestionMessage.Question[0].Name
	//	}
	//	if c.ResponseMessage.Answer[i].Header().Rrtype == dns.TypeCNAME{
	//		c.ResponseMessage.Answer = c.ResponseMessage.Answer[:i+copy(c.ResponseMessage.Answer[i:], c.ResponseMessage.Answer[i+1:])]
	//		i -= 1
	//	}
	//}

	if isLog {
		c.logAnswer("")
	}

	if isCache {
		c.CacheResult()
	}
}

func (c *Client) ExchangeFromCache() bool {

	if c.Cache == nil {
		return false
	}

	m := c.Cache.Hit(cache.Key(c.QuestionMessage.Question[0], c.EDNSClientSubnetIP), c.QuestionMessage.Id)
	if m != nil {
		log.Debug("Cache Hit: " + cache.Key(c.QuestionMessage.Question[0], c.EDNSClientSubnetIP))
		c.ResponseMessage = m
		return true
	}

	return false
}

func (c *Client) ExchangeFromLocal() bool {

	if c.ExchangeFromCache() {
		return true
	}

	raw_name := c.QuestionMessage.Question[0].Name

	if c.ExchangeFromHosts(raw_name) || c.ExchangeFromIP(raw_name) {
		return true
	}

	return false
}

func (c *Client) ExchangeFromHosts(raw_name string) bool {

	if c.Hosts == nil {
		return false
	}

	name := raw_name[:len(raw_name)-1]
	ipv4List, ipv6List := c.Hosts.Find(name)

	if c.QuestionMessage.Question[0].Qtype == dns.TypeA && len(ipv4List) > 0 {
		var rrl []dns.RR
		for _, ip := range ipv4List {
			a, _ := dns.NewRR(raw_name + " IN A " + ip.String())
			rrl = append(rrl, a)
		}
		c.setLocalResponseMessage(rrl)
		if c.ResponseMessage != nil {
			return true
		}
	} else if c.QuestionMessage.Question[0].Qtype == dns.TypeAAAA && len(ipv6List) > 0 {
		var rrl []dns.RR
		for _, ip := range ipv6List {
			aaaa, _ := dns.NewRR(raw_name + " IN AAAA " + ip.String())
			rrl = append(rrl, aaaa)
		}
		c.setLocalResponseMessage(rrl)
		if c.ResponseMessage != nil {
			return true
		}
	}

	return false
}

func (c *Client) ExchangeFromIP(raw_name string) bool {

	name := raw_name[:len(raw_name)-1]
	ip := net.ParseIP(name)
	if ip == nil {
		return false
	}
	if ip.To4() == nil && ip.To16() != nil && c.QuestionMessage.Question[0].Qtype == dns.TypeAAAA {
		aaaa, _ := dns.NewRR(raw_name + " IN AAAA " + ip.String())
		c.setLocalResponseMessage([]dns.RR{aaaa})
		return true
	} else if ip.To4() != nil && c.QuestionMessage.Question[0].Qtype == dns.TypeA {
		a, _ := dns.NewRR(raw_name + " IN A " + ip.String())
		c.setLocalResponseMessage([]dns.RR{a})
		return true
	}

	return false
}

func (c *Client) setLocalResponseMessage(rrl []dns.RR) {

	shuffleRRList := func(rrl []dns.RR) {
		rand.Seed(time.Now().UnixNano())
		for i := range rrl {
			j := rand.Intn(i + 1)
			rrl[i], rrl[j] = rrl[j], rrl[i]
		}
	}

	c.ResponseMessage = new(dns.Msg)
	for _, rr := range rrl {
		c.ResponseMessage.Answer = append(c.ResponseMessage.Answer, rr)
	}
	shuffleRRList(c.ResponseMessage.Answer)
	c.ResponseMessage.SetReply(c.QuestionMessage)
	c.ResponseMessage.RecursionAvailable = true
}

func (c *Client) logAnswer(indicator string) {

	for _, a := range c.ResponseMessage.Answer {
		var name string
		if indicator != "" {
			name = indicator
		} else {
			name = c.DNSUpstream.Name
		}
		log.Debug("Answer from " + name + ": " + a.String())
	}
}

func (c *Client) CacheResult() {

	if c.Cache != nil {
		c.Cache.InsertMessage(cache.Key(c.QuestionMessage.Question[0], common.GetEDNSClientSubnetIP(c.QuestionMessage)), c.ResponseMessage)
	}
}
<|endoftext|>


<commit_before>// Copyright 2010 The Go Authors.  All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// Wrappers for Go parser.

package main

import (
	"path"
	"os"
	"log"
	"strings"
	"strconv"
	"go/ast"
	"go/parser"
)

// goFiles returns a list of the *.go source files in dir, excluding
// those in package main (unless allowMain is true) or ending in
// _test.go.  It also returns a map giving the packages imported by
// those files, and the package name.
// The map keys are the imported paths.  The key's value
// is one file that imports that path.
func goFiles(dir string, allowMain bool) (files []string, imports map[string]string, pkgName string, err os.Error) {
	f, err := os.Open(dir, os.O_RDONLY, 0)
	if err != nil {
		return nil, nil, "", err
	}
	dirs, err := f.Readdir(-1)
	f.Close()
	if err != nil {
		return nil, nil, "", err
	}

	files = make([]string, 0, len(dirs))
	imports = make(map[string]string)
	for i := range dirs {
		d := &dirs[i]
		if !strings.HasSuffix(d.Name, ".go") || strings.HasSuffix(d.Name, "_test.go") {
			continue
		}
		filename := path.Join(dir, d.Name)
		pf, err := parser.ParseFile(filename, nil, parser.ImportsOnly)
		if err != nil {
			return nil, nil, "", err
		}
		s := string(pf.Name.Name)
		if s == "main" && !allowMain {
			continue
		}
		if pkgName == "" {
			pkgName = s
		} else if pkgName != s {
			// Only if all files in the directory are in package main
			// do we return pkgName=="main".
			// A mix of main and another package reverts
			// to the original (allowMain=false) behaviour.
			if allowMain && pkgName == "main" {
				return goFiles(dir, false)
			}
			return nil, nil, "", os.ErrorString("multiple package names in " + dir)
		}
		n := len(files)
		files = files[0 : n+1]
		files[n] = filename
		for _, decl := range pf.Decls {
			for _, spec := range decl.(*ast.GenDecl).Specs {
				quoted := string(spec.(*ast.ImportSpec).Path.Value)
				unquoted, err := strconv.Unquote(quoted)
				if err != nil {
					log.Panicf("%s: parser returned invalid quoted string: <%s>", filename, quoted)
				}
				imports[unquoted] = filename
			}
		}
	}
	return files, imports, pkgName, nil
}
<commit_msg>goinstall: don't wrongly error out with "multiple package names"<commit_after>// Copyright 2010 The Go Authors.  All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// Wrappers for Go parser.

package main

import (
	"path"
	"os"
	"log"
	"strings"
	"strconv"
	"go/ast"
	"go/parser"
)

// goFiles returns a list of the *.go source files in dir, excluding
// those in package main (unless allowMain is true) or ending in
// _test.go.  It also returns a map giving the packages imported by
// those files, and the package name.
// The map keys are the imported paths.  The key's value
// is one file that imports that path.
func goFiles(dir string, allowMain bool) (files []string, imports map[string]string, pkgName string, err os.Error) {
	f, err := os.Open(dir, os.O_RDONLY, 0)
	if err != nil {
		return nil, nil, "", err
	}
	dirs, err := f.Readdir(-1)
	f.Close()
	if err != nil {
		return nil, nil, "", err
	}

	files = make([]string, 0, len(dirs))
	imports = make(map[string]string)
	for i := range dirs {
		d := &dirs[i]
		if !strings.HasSuffix(d.Name, ".go") || strings.HasSuffix(d.Name, "_test.go") {
			continue
		}
		filename := path.Join(dir, d.Name)
		pf, err := parser.ParseFile(filename, nil, parser.ImportsOnly)
		if err != nil {
			return nil, nil, "", err
		}
		s := string(pf.Name.Name)
		if s == "main" && !allowMain {
			continue
		}
		if pkgName == "" {
			pkgName = s
		} else if pkgName != s {
			// Only if all files in the directory are in package main
			// do we return pkgName=="main".
			// A mix of main and another package reverts
			// to the original (allowMain=false) behaviour.
			if s == "main" || pkgName == "main" {
				return goFiles(dir, false)
			}
			return nil, nil, "", os.ErrorString("multiple package names in " + dir)
		}
		n := len(files)
		files = files[0 : n+1]
		files[n] = filename
		for _, decl := range pf.Decls {
			for _, spec := range decl.(*ast.GenDecl).Specs {
				quoted := string(spec.(*ast.ImportSpec).Path.Value)
				unquoted, err := strconv.Unquote(quoted)
				if err != nil {
					log.Panicf("%s: parser returned invalid quoted string: <%s>", filename, quoted)
				}
				imports[unquoted] = filename
			}
		}
	}
	return files, imports, pkgName, nil
}
<|endoftext|>


<commit_before>package main

import (
	"bytes"
	"encoding/json"
	"fmt"
	"github.com/beatgammit/semver"
	"github.com/beatgammit/stein"
	"net/http"
)

type CouchDB struct {
	addr, database, design string
	version                semver.Semver
	user, pass             string
}

func NewCouchDB(addr, database, user, pass string) (DB, error) {
	// it's possible the user wants https:// or it's behind
	// a proxy, so let them specify that if they like
	if addr[:4] != "http" {
		addr = "http://" + addr
	}
	if addr[len(addr)-1] != '/' {
		addr += "/"
	}

	resp, err := http.Get(addr)
	if err != nil {
		return nil, err
	}
	var m map[string]interface{}
	err = json.NewDecoder(resp.Body).Decode(&m)
	if err != nil {
		return nil, err
	} else if _, ok := m["version"]; !ok {
		return nil, fmt.Errorf("Invalid CouchDB server")
	}

	db := CouchDB{
		addr:     addr,
		database: database,
		user:     user,
		pass:     pass,
		design:   "stein",
	}
	db.version, err = semver.Parse(m["version"].(string))
	if err != nil {
		return nil, fmt.Errorf("Error parsing version: %s", err)
	}
	return db, db.init()
}

// init ensures that the database is configured correctly:
// - creates database
// - creates views
func (db CouchDB) init() error {
	req, err := http.NewRequest("PUT", db.addr+db.database, nil)
	if err != nil {
		return fmt.Errorf("Error sending DB create request")
	}
	if db.user != "" {
		req.SetBasicAuth(db.user, db.pass)
	}
	if resp, err := http.DefaultClient.Do(req); err != nil {
		return err
	} else {
		// TODO: check for errors
		resp.Body.Close()
	}

	designDocUrl := db.addr + db.database + "/_design/" + db.design

	resp, err := http.Get(designDocUrl)
	if err != nil {
		return err
	}
	var m map[string]interface{}
	if resp.StatusCode >= 200 && resp.StatusCode < 300 {
		// design doc already exists, so update it
		if err = json.NewDecoder(resp.Body).Decode(&m); err != nil {
			return err
		}
	} else {
		m = make(map[string]interface{})
	}
	if _, ok := m["views"]; !ok {
		m["views"] = make(map[string]interface{})
		m["language"] = "javascript"
	}
	views := m["views"].(map[string]interface{})
	// by_project maps projects to documents
	// use reduce=false to get all documents, or
	// reduce=true to get counts per project
	views["by_project"] = map[string]interface{}{
		"map": `function(doc) {
		   emit(doc.project, doc);
	   }`,
		"reduce": `function (keys, values, meh) {
		   return keys.reduce(function (p, key) {
			   var k = key[0];
			   p[k] = k in p ? p[k] + 1 : 1;
			   return p;
		   }, {});
	   }`,
	}

	b, err := json.Marshal(m)
	if err != nil {
		return err
	}

	buf := bytes.NewBuffer(b)
	if rev, ok := m["_rev"].(string); ok {
		req, err = http.NewRequest("PUT", designDocUrl+"?rev="+rev, buf)
	} else {
		req, err = http.NewRequest("PUT", designDocUrl, buf)
	}
	if db.user != "" {
		req.SetBasicAuth(db.user, db.pass)
	}
	if err != nil {
		return err
	}
	resp, err = http.DefaultClient.Do(req)
	if err != nil {
		return err
	} else if resp.StatusCode >= 400 {
		fmt.Println(designDocUrl)
		return fmt.Errorf("Error updating view: %d", resp.StatusCode)
	}
	return nil
}

func (db CouchDB) GetProjects() ([]string, error) {
	resp, err := http.Get(db.addr + db.database + "/_design/" + db.design + "/_view/by_project")
	if err != nil {
		return nil, err
	}
	var m map[string]interface{}
	if err = json.NewDecoder(resp.Body).Decode(&m); err != nil {
		return nil, err
	}

	rows := m["rows"].([]interface{})
	match := rows[0].(map[string]interface{})
	counts := match["value"].(map[string]interface{})
	var projects []string
	for project := range counts {
		projects = append(projects, project)
	}
	return projects, nil
}

func (db CouchDB) GetTests(project string) ([]string, error) {
	resp, err := http.Get(db.addr + db.database + "/_design/" + db.design + "/_view/by_project?reduce=false")
	if err != nil {
		return nil, err
	}
	var m map[string]interface{}
	if err = json.NewDecoder(resp.Body).Decode(&m); err != nil {
		return nil, err
	}

	var tests []string
	rows := m["rows"].([]interface{})
	for _, row := range rows {
		// TODO: make this safer
		val := row.(map[string]interface{})["value"].(map[string]interface{})
		id := val["_id"].(string)
		tests = append(tests, id)
	}
	return tests, nil
}

func (db CouchDB) GetTest(project, test string) (*stein.Suite, error) {
	resp, err := http.Get(db.addr + db.database + "/" + test)
	if err != nil {
		return nil, err
	}

	var s stein.Suite
	return &s, json.NewDecoder(resp.Body).Decode(&s)
}

func (db CouchDB) Save(project, test string, s *stein.Suite) error {
	b, err := json.Marshal(s)
	if err != nil {
		return err
	}
	var m map[string]interface{}
	err = json.Unmarshal(b, &m)
	if err != nil {
		return err
	}
	m["project"] = project
	b, err = json.Marshal(m)
	if err != nil {
		return err
	}

	testAddr := db.addr + db.database + "/" + test

	var rev string
	resp, err := http.Get(testAddr)
	if err != nil {
		return err
	} else if resp.StatusCode >= 200 && resp.StatusCode < 300 {
		var cur map[string]interface{}
		err := json.NewDecoder(resp.Body).Decode(&cur)
		if err != nil {
			return err
		}
		rev = cur["_rev"].(string)
	}

	var req *http.Request
	buf := bytes.NewBuffer(b)
	if rev == "" {
		// create a new one
		req, err = http.NewRequest("PUT", testAddr, buf)
	} else {
		// update existing
		req, err = http.NewRequest("PUT", testAddr+"?rev="+rev, buf)
	}
	if db.user != "" {
		req.SetBasicAuth(db.user, db.pass)
	}
	resp, err = http.DefaultClient.Do(req)
	if err != nil {
		return err
	} else if resp.StatusCode >= 400 {
		return fmt.Errorf("Error updating document: %d", resp.StatusCode)
	}
	resp.Body.Close()
	return nil
}
<commit_msg>Fix panic when no projects exist<commit_after>package main

import (
	"bytes"
	"encoding/json"
	"fmt"
	"github.com/beatgammit/semver"
	"github.com/beatgammit/stein"
	"net/http"
)

type CouchDB struct {
	addr, database, design string
	version                semver.Semver
	user, pass             string
}

func NewCouchDB(addr, database, user, pass string) (DB, error) {
	// it's possible the user wants https:// or it's behind
	// a proxy, so let them specify that if they like
	if addr[:4] != "http" {
		addr = "http://" + addr
	}
	if addr[len(addr)-1] != '/' {
		addr += "/"
	}

	resp, err := http.Get(addr)
	if err != nil {
		return nil, err
	}
	var m map[string]interface{}
	err = json.NewDecoder(resp.Body).Decode(&m)
	if err != nil {
		return nil, err
	} else if _, ok := m["version"]; !ok {
		return nil, fmt.Errorf("Invalid CouchDB server")
	}

	db := CouchDB{
		addr:     addr,
		database: database,
		user:     user,
		pass:     pass,
		design:   "stein",
	}
	db.version, err = semver.Parse(m["version"].(string))
	if err != nil {
		return nil, fmt.Errorf("Error parsing version: %s", err)
	}
	return db, db.init()
}

// init ensures that the database is configured correctly:
// - creates database
// - creates views
func (db CouchDB) init() error {
	req, err := http.NewRequest("PUT", db.addr+db.database, nil)
	if err != nil {
		return fmt.Errorf("Error sending DB create request")
	}
	if db.user != "" {
		req.SetBasicAuth(db.user, db.pass)
	}
	if resp, err := http.DefaultClient.Do(req); err != nil {
		return err
	} else {
		// TODO: check for errors
		resp.Body.Close()
	}

	designDocUrl := db.addr + db.database + "/_design/" + db.design

	resp, err := http.Get(designDocUrl)
	if err != nil {
		return err
	}
	var m map[string]interface{}
	if resp.StatusCode >= 200 && resp.StatusCode < 300 {
		// design doc already exists, so update it
		if err = json.NewDecoder(resp.Body).Decode(&m); err != nil {
			return err
		}
	} else {
		m = make(map[string]interface{})
	}
	if _, ok := m["views"]; !ok {
		m["views"] = make(map[string]interface{})
		m["language"] = "javascript"
	}
	views := m["views"].(map[string]interface{})
	// by_project maps projects to documents
	// use reduce=false to get all documents, or
	// reduce=true to get counts per project
	views["by_project"] = map[string]interface{}{
		"map": `function(doc) {
		   emit(doc.project, doc);
	   }`,
		"reduce": `function (keys, values, meh) {
		   return keys.reduce(function (p, key) {
			   var k = key[0];
			   p[k] = k in p ? p[k] + 1 : 1;
			   return p;
		   }, {});
	   }`,
	}

	b, err := json.Marshal(m)
	if err != nil {
		return err
	}

	buf := bytes.NewBuffer(b)
	if rev, ok := m["_rev"].(string); ok {
		req, err = http.NewRequest("PUT", designDocUrl+"?rev="+rev, buf)
	} else {
		req, err = http.NewRequest("PUT", designDocUrl, buf)
	}
	if db.user != "" {
		req.SetBasicAuth(db.user, db.pass)
	}
	if err != nil {
		return err
	}
	resp, err = http.DefaultClient.Do(req)
	if err != nil {
		return err
	} else if resp.StatusCode >= 400 {
		fmt.Println(designDocUrl)
		return fmt.Errorf("Error updating view: %d", resp.StatusCode)
	}
	return nil
}

func (db CouchDB) GetProjects() ([]string, error) {
	resp, err := http.Get(db.addr + db.database + "/_design/" + db.design + "/_view/by_project")
	if err != nil {
		return nil, err
	}
	var m map[string]interface{}
	if err = json.NewDecoder(resp.Body).Decode(&m); err != nil {
		return nil, err
	}

	projects := []string{}
	rows, ok := m["rows"].([]interface{})
	if !ok || len(rows) == 0 {
		// no projects yet
		return projects, nil
	}
	match := rows[0].(map[string]interface{})
	counts := match["value"].(map[string]interface{})
	for project := range counts {
		projects = append(projects, project)
	}
	return projects, nil
}

func (db CouchDB) GetTests(project string) ([]string, error) {
	resp, err := http.Get(db.addr + db.database + "/_design/" + db.design + "/_view/by_project?reduce=false")
	if err != nil {
		return nil, err
	}
	var m map[string]interface{}
	if err = json.NewDecoder(resp.Body).Decode(&m); err != nil {
		return nil, err
	}

	var tests []string
	rows := m["rows"].([]interface{})
	for _, row := range rows {
		// TODO: make this safer
		val := row.(map[string]interface{})["value"].(map[string]interface{})
		id := val["_id"].(string)
		tests = append(tests, id)
	}
	return tests, nil
}

func (db CouchDB) GetTest(project, test string) (*stein.Suite, error) {
	resp, err := http.Get(db.addr + db.database + "/" + test)
	if err != nil {
		return nil, err
	}

	var s stein.Suite
	return &s, json.NewDecoder(resp.Body).Decode(&s)
}

func (db CouchDB) Save(project, test string, s *stein.Suite) error {
	b, err := json.Marshal(s)
	if err != nil {
		return err
	}
	var m map[string]interface{}
	err = json.Unmarshal(b, &m)
	if err != nil {
		return err
	}
	m["project"] = project
	b, err = json.Marshal(m)
	if err != nil {
		return err
	}

	testAddr := db.addr + db.database + "/" + test

	var rev string
	resp, err := http.Get(testAddr)
	if err != nil {
		return err
	} else if resp.StatusCode >= 200 && resp.StatusCode < 300 {
		var cur map[string]interface{}
		err := json.NewDecoder(resp.Body).Decode(&cur)
		if err != nil {
			return err
		}
		rev = cur["_rev"].(string)
	}

	var req *http.Request
	buf := bytes.NewBuffer(b)
	if rev == "" {
		// create a new one
		req, err = http.NewRequest("PUT", testAddr, buf)
	} else {
		// update existing
		req, err = http.NewRequest("PUT", testAddr+"?rev="+rev, buf)
	}
	if db.user != "" {
		req.SetBasicAuth(db.user, db.pass)
	}
	resp, err = http.DefaultClient.Do(req)
	if err != nil {
		return err
	} else if resp.StatusCode >= 400 {
		return fmt.Errorf("Error updating document: %d", resp.StatusCode)
	}
	resp.Body.Close()
	return nil
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"github.com/geordanr/go_xwing/attack"
	"github.com/geordanr/go_xwing/attack/modification"
	"github.com/geordanr/go_xwing/attack/runner"
	"github.com/geordanr/go_xwing/attack/step"
	"github.com/geordanr/go_xwing/constants"
	"github.com/geordanr/go_xwing/gamestate"
	"github.com/geordanr/go_xwing/interfaces"
	"github.com/geordanr/go_xwing/ship"
	"github.com/geordanr/go_xwing/stats"
	"math/rand"
	"time"
)

func main() {
	rand.Seed(time.Now().UnixNano())

	nIterations := 100000
	runner := runner.New(step.Steps, nIterations)
	output := make(chan interfaces.GameState, nIterations)
	hitStats := new(stats.Integers)
	critStats := new(stats.Integers)

	go runner.Run(output)

	for i := 0; i < nIterations; i++ {
		runner.InjectState(makeState(hitStats, critStats))
	}

	for i := 0; i < nIterations; i++ {
		<-output
	}

	fmt.Printf("Average hits : %3.2f\n", hitStats.Average())
	fmt.Printf("Stddev hits  : %3.2f\n", hitStats.Stddev())
	fmt.Printf("Average crits: %3.2f\n", critStats.Average())
	fmt.Printf("Stddev crits : %3.2f\n", critStats.Stddev())
}

func makeState(hitStats, critStats *stats.Integers) *gamestate.GameState {
	attacker := ship.New("TIE Fighter", 2, 3, 3, 0)
	defender := ship.New("X-Wing", 3, 2, 3, 2)
	mods := map[string][]interfaces.Modification{
		"Suffer Damage": []interfaces.Modification{
			modification.All["Suffer Damage"],
			&TabulateHits{stats: hitStats},
			&TabulateCrits{stats: critStats},
		},
	}
	state := gamestate.GameState{}
	state.EnqueueAttack(attack.New(attacker, defender, mods))
	// state.EnqueueAttack(attack.New(defender, attacker, mods))
	return &state
}

type TabulateHits struct {
	stats *stats.Integers
	actor constants.ModificationActor
}

func (mod *TabulateHits) ModifyState(state interfaces.GameState, ship interfaces.Ship) {
	mod.stats.Update(int(state.HitsLanded()))
}

func (mod TabulateHits) Actor() constants.ModificationActor          { return mod.actor }
func (mod *TabulateHits) SetActor(actor constants.ModificationActor) { mod.actor = actor }
func (mod TabulateHits) String() string                              { return "Tabulate Hits" }

type TabulateCrits struct {
	stats *stats.Integers
	actor constants.ModificationActor
}

func (mod *TabulateCrits) ModifyState(state interfaces.GameState, ship interfaces.Ship) {
	mod.stats.Update(int(state.CritsLanded()))
}

func (mod TabulateCrits) Actor() constants.ModificationActor          { return mod.actor }
func (mod *TabulateCrits) SetActor(actor constants.ModificationActor) { mod.actor = actor }
func (mod TabulateCrits) String() string                              { return "Tabulate Crits" }
<commit_msg>Consolidate tabulation into one modification.<commit_after>package main

import (
	"fmt"
	"github.com/geordanr/go_xwing/attack"
	"github.com/geordanr/go_xwing/attack/modification"
	"github.com/geordanr/go_xwing/attack/runner"
	"github.com/geordanr/go_xwing/attack/step"
	"github.com/geordanr/go_xwing/constants"
	"github.com/geordanr/go_xwing/gamestate"
	"github.com/geordanr/go_xwing/interfaces"
	"github.com/geordanr/go_xwing/ship"
	"github.com/geordanr/go_xwing/stats"
	"math/rand"
	"time"
)

func main() {
	rand.Seed(time.Now().UnixNano())

	nIterations := 100000
	runner := runner.New(step.Steps, nIterations)
	output := make(chan interfaces.GameState, nIterations)
	attackerStats := ShipStats{
		Hits:  new(stats.Integers),
		Crits: new(stats.Integers),
	}
	defenderStats := ShipStats{
		Hits:  new(stats.Integers),
		Crits: new(stats.Integers),
	}

	go runner.Run(output)

	for i := 0; i < nIterations; i++ {
		runner.InjectState(makeState(&attackerStats, &defenderStats))
	}

	for i := 0; i < nIterations; i++ {
		<-output
	}

	fmt.Println("Attacker")
	fmt.Println("--------")
	fmt.Printf("Average hits : %3.2f\n", attackerStats.Hits.Average())
	fmt.Printf("Stddev hits  : %3.2f\n", attackerStats.Hits.Stddev())
	fmt.Printf("Average crits: %3.2f\n", attackerStats.Crits.Average())
	fmt.Printf("Stddev crits : %3.2f\n", attackerStats.Crits.Stddev())
	fmt.Println()
	fmt.Println("Defender")
	fmt.Println("--------")
	fmt.Printf("Average hits : %3.2f\n", defenderStats.Hits.Average())
	fmt.Printf("Stddev hits  : %3.2f\n", defenderStats.Hits.Stddev())
	fmt.Printf("Average crits: %3.2f\n", defenderStats.Crits.Average())
	fmt.Printf("Stddev crits : %3.2f\n", defenderStats.Crits.Stddev())
}

func makeState(attackerStats, defenderStats *ShipStats) *gamestate.GameState {
	attacker := ship.New("TIE Fighter", 2, 3, 3, 0)
	defender := ship.New("X-Wing", 3, 2, 3, 2)
	mods := map[string][]interfaces.Modification{
		"Suffer Damage": []interfaces.Modification{
			modification.All["Suffer Damage"],
			&TabulateStats{
				ship:  attacker,
				stats: attackerStats,
			},
			&TabulateStats{
				ship:  defender,
				stats: defenderStats,
			},
		},
	}
	state := gamestate.GameState{}
	state.EnqueueAttack(attack.New(attacker, defender, mods))
	state.EnqueueAttack(attack.New(defender, attacker, mods))
	return &state
}

type ShipStats struct {
	Hits  *stats.Integers
	Crits *stats.Integers
}

type TabulateStats struct {
	ship  *ship.Ship
	stats *ShipStats
	actor constants.ModificationActor
}

func (mod *TabulateStats) ModifyState(state interfaces.GameState, ship interfaces.Ship) {
	if ship == mod.ship {
		mod.stats.Hits.Update(int(state.HitsLanded()))
		mod.stats.Crits.Update(int(state.CritsLanded()))
	}
}

func (mod TabulateStats) Actor() constants.ModificationActor          { return mod.actor }
func (mod *TabulateStats) SetActor(actor constants.ModificationActor) { mod.actor = actor }
func (mod TabulateStats) String() string                              { return "Tabulate Stats" }
<|endoftext|>


<commit_before>// Copyright (c) 2015 Monetas.
// Copyright 2016 Daniel Krawisz.
// Use of this source code is governed by an ISC
// license that can be found in the LICENSE file.

package store

import (
	"bytes"
	"encoding/binary"
	"errors"
	"time"
	"fmt"

	"github.com/boltdb/bolt"
)

// Data keys of a mailbox.
var (
	// mailboxCreatedOnKey contains the time of creation of mailbox.
	mailboxCreatedOnKey = []byte("createdOn")

	// ErrDuplicateID is returned by InsertMessage when the a message with the
	// specified ID already exists in the mailbox.
	ErrDuplicateID = errors.New("duplicate ID")
)

// Mailbox is a mailbox corresponding to a private identity or broadcast. It's
// designed such that any kind of message (not just text based) can be stored
// in the data store.
type Mailbox struct {
	store *Store
	uname []byte
	name  string
}

// initializeMailbox initializes a mailbox.
func initializeMailbox(store *Store, uname []byte, name string) error {

	err := store.db.Update(func(tx *bolt.Tx) error {
		// Get bucket for mailbox.
		bucket := tx.Bucket(uname).Bucket(mailboxesBucket).Bucket([]byte(name))

		if bucket == nil {
			// New mailbox so initialize it with all the data.
			bucket, err := tx.Bucket(uname).CreateBucketIfNotExists(mailboxesBucket)
			if err != nil {
				return err
			}

			bucket, err = tx.Bucket(uname).Bucket(mailboxesBucket).CreateBucket([]byte(name))
			if err != nil {
				return err
			}

			data, err := bucket.CreateBucket(mailboxDataBucket)
			if err != nil {
				return err
			}

			now, err := time.Now().MarshalBinary()
			if err != nil {
				return err
			}

			err = data.Put(mailboxCreatedOnKey, now)
			if err != nil {
				return err
			}
		}
		return nil
	})
	if err != nil {
		return fmt.Errorf("Failed to create/load mailbox %s: %v",
			name, err)
	}

	return nil
}

// InsertMessage inserts a new message with the specified suffix and id into the
// mailbox and returns the ID. If input id is 0, then the store automatically
// generates a unique index value. For normal mailboxes, suffix could be the
// encoding type. For special use mailboxes like "Pending", suffix could be
// used as a 'key', like a reason code (why the message is marked as Pending).
func (mbox *Mailbox) InsertMessage(msg []byte, id, suffix uint64) (uint64, error) {
	enc, err := mbox.store.encrypt(msg)
	if err != nil {
		return 0, err
	}

	err = mbox.store.db.Update(func(tx *bolt.Tx) error {
		bucket := tx.Bucket(mbox.uname)
		if bucket == nil {
			return ErrNotFound
		}
		m := bucket.Bucket(mailboxesBucket).Bucket([]byte(mbox.name))

		// Generate a new ID if we asked for it.
		if id == 0 {
			bucket := tx.Bucket(mbox.uname)
			if bucket == nil {
				return ErrNotFound
			}
			latestId := bucket.Bucket(miscBucket).Get(mailboxLatestIDKey)
			id = binary.BigEndian.Uint64(latestId) + 1

			// Increment mailboxLatestID.
			idB := make([]byte, 8)
			binary.BigEndian.PutUint64(idB, id)

			err = tx.Bucket(mbox.uname).Bucket(miscBucket).Put(mailboxLatestIDKey, idB)
			if err != nil {
				return err
			}
		}

		// Insert message using ID as the first 8 bytes and suffix as the
		// latter 8 bytes of the key.
		k := make([]byte, 16)
		binary.BigEndian.PutUint64(k[:8], id)     // first half
		binary.BigEndian.PutUint64(k[8:], suffix) // second half

		// Check if a message with the given ID already exists.
		kk, _ := m.Cursor().Seek(k[:8])
		if kk != nil && bytes.Equal(kk[:8], k[:8]) {
			return ErrDuplicateID
		}

		return m.Put(k, enc)
	})
	if err != nil {
		return 0, err
	}

	return id, nil
}

// GetMessage retrieves a message from the mailbox by its index. It returns the
// suffix and the message. An error is returned if the message with the given
// index doesn't exist in the database.
func (mbox *Mailbox) GetMessage(id uint64) (uint64, []byte, error) {
	var suffix uint64
	var msg []byte

	var success bool

	idBytes := make([]byte, 8)
	binary.BigEndian.PutUint64(idBytes, id)

	err := mbox.store.db.View(func(tx *bolt.Tx) error {
		bucket := tx.Bucket(mbox.uname)
		if bucket == nil {
			return ErrNotFound
		}

		bucket = bucket.Bucket(mailboxesBucket)
		if bucket == nil {
			return ErrNotFound
		}

		cursor := bucket.Bucket([]byte(mbox.name)).Cursor()
		k, v := cursor.Seek(idBytes)

		// Check if the first 8 bytes match the index.
		if k == nil || v == nil || !bytes.Equal(k[:8], idBytes) {
			return ErrNotFound
		}

		suffix = binary.BigEndian.Uint64(k[8:])
		msg, success = mbox.store.decrypt(v)
		if !success {
			return ErrDecryptionFailed
		}

		return nil
	})
	if err != nil {
		return 0, nil, err
	}

	return suffix, msg, nil
}

// ForEachMessage runs the given function for messages that have IDs between
// lowID and highID with the given suffix. If lowID is 0, it starts from the
// first message. If highID is 0, it returns all messages with id >= lowID with
// the given suffix. If suffix is zero, it returns all messages between lowID
// and highID, irrespective of the suffix. Note that any combination of lowID,
// highID and suffix can be zero for the desired results. Both lowID and highID
// are inclusive.
//
// Suffix is useful for getting all messages of a particular type. For example,
// retrieving all messages with encoding type 2.
//
// The function terminates early if an error occurs and iterates in the
// increasing order of index. Make sure it doesn't take long to execute. DO NOT
// execute any other database operations in it.
func (mbox *Mailbox) ForEachMessage(lowID, highID, suffix uint64,
	f func(id, suffix uint64, msg []byte) error) error {
	if highID != 0 && lowID > highID {
		return errors.New("Nice try, son. But lowID cannot be greater than highID.")
	}

	bLowID := make([]byte, 8)
	binary.BigEndian.PutUint64(bLowID, lowID)

	return mbox.store.db.View(func(tx *bolt.Tx) error {
		bucket := tx.Bucket(mbox.uname)
		if (bucket == nil) {
			return ErrNotFound
		}
		cursor := bucket.Bucket(mailboxesBucket).Bucket([]byte(mbox.name)).Cursor()

		for k, v := cursor.Seek(bLowID); k != nil; k, v = cursor.Next() {
			// We need this safeguard because BoltDB also loops over buckets. We
			// don't want to include the bucket "data" in our query.
			if v == nil {
				continue
			}

			id := binary.BigEndian.Uint64(k[:8])
			sfx := binary.BigEndian.Uint64(k[8:])

			// We already exceeded the highest ID, so stop.
			if highID != 0 && id > highID {
				return nil // We're done with all the looping.
			}

			// The suffix doesn't match so go to next message.
			if suffix != 0 && sfx != suffix {
				continue
			}

			msg, success := mbox.store.decrypt(v)
			if !success {
				return ErrDecryptionFailed
			}

			if err := f(id, sfx, msg); err != nil {
				return err
			}
		}

		return nil
	})
}

// DeleteMessage deletes a message with the given index from the store. An error
// is returned if the message doesn't exist in the store.
func (mbox *Mailbox) DeleteMessage(id uint64) error {
	idxBytes := make([]byte, 8)
	binary.BigEndian.PutUint64(idxBytes, id)

	return mbox.store.db.Update(func(tx *bolt.Tx) error {
		bucket := tx.Bucket(mbox.uname)
		if bucket == nil {
			return ErrNotFound
		}
		bucket = bucket.Bucket(mailboxesBucket).Bucket([]byte(mbox.name))
		k, v := bucket.Cursor().Seek(idxBytes)

		// Check if the first 8 bytes match the index.
		if k == nil || v == nil || !bytes.Equal(k[:8], idxBytes) {
			return ErrNotFound
		}

		return bucket.Delete(k)
	})
}

// Name returns the user-friendly name of the mailbox.
func (mbox *Mailbox) Name() string {
	return mbox.name
}

// SetName changes the name of the mailbox.
func (mbox *Mailbox) SetName(name string) error {
	if name == "" {
		return errors.New("Name cannot be empty.")
	}

	err := mbox.store.db.Update(func(tx *bolt.Tx) error {
		// Check if some other mailbox has the same name.
		err := tx.Bucket(mbox.uname).Bucket(mailboxesBucket).ForEach(func(k, _ []byte) error {
			if string(k) == name {
				return ErrDuplicateMailbox
			}
			return nil
		})
		if err != nil {
			return err
		}

		// Create the new mailbox.
		b, err := tx.Bucket(mbox.uname).Bucket(mailboxesBucket).CreateBucket([]byte(name))
		if err != nil {
			return err
		}

		// Copy everything.
		oldB := tx.Bucket(mbox.uname).Bucket(mailboxesBucket).Bucket([]byte(mbox.name))
		oldB.ForEach(func(k, v []byte) error {
			if v == nil { // It's a bucket.
				b1, err := b.CreateBucket(k)
				if err != nil {
					return err
				}

				// Copy all keys.
				return oldB.Bucket(k).ForEach(func(k1, v1 []byte) error {
					return b1.Put(k1, v1)
				})
			}
			return b.Put(k, v)
		})

		// Delete old mailbox.
		return tx.Bucket(mbox.uname).Bucket(mailboxesBucket).DeleteBucket([]byte(mbox.name))
	})
	if err != nil {
		return err
	}

	mbox.name = name
	return nil
}

// Delete deletes the mailbox. Any operations after a Delete are invalid.
func (mbox *Mailbox) Delete() error {
	return mbox.store.db.Update(func(tx *bolt.Tx) error {
		// Delete the mailbox and associated data.
		bucket := tx.Bucket(mbox.uname)
		if bucket == nil {
			return ErrNotFound
		}
		err := bucket.Bucket(mailboxesBucket).DeleteBucket([]byte(mbox.name))
		if err != nil {
			return err
		}

		// Delete mailbox from store.
		delete(mbox.store.mailboxes, mbox.name)
		return nil
	})
}

// NextID returns the next index value that will be assigned in the mailbox..
func (mbox *Mailbox) NextID() (uint64, error) {
	var id uint64

	err := mbox.store.db.View(func(tx *bolt.Tx) error {
		// Only one id is used for the entire set of mailboxes for a given user.
		id = binary.BigEndian.Uint64(tx.Bucket(mbox.uname).Bucket(miscBucket).Get(mailboxLatestIDKey)) + 1
		return nil
	})
	if err != nil {
		return 0, err
	}
	return id, nil
}

// LastID returns the highest index value in the mailbox.
func (mbox *Mailbox) LastID() (uint64, error) {
	var id uint64

	err := mbox.store.db.View(func(tx *bolt.Tx) error {
		bucket := tx.Bucket(mbox.uname)
		if bucket == nil {
			return ErrNotFound
		}
		cursor := bucket.Bucket(mailboxesBucket).Bucket([]byte(mbox.name)).Cursor()

		// Read from the end until we have a non-nil value.
		for k, _ := cursor.Last(); ; k, _ = cursor.Prev() {
			if k == nil { // No records
				return ErrNotFound
			}
			if len(k) != 16 { // Don't want to read key from a bucket.
				continue
			}
			id = binary.BigEndian.Uint64(k[:8])
			return nil
		}
	})
	if err != nil {
		return 0, err
	}
	return id, nil
}

// LastIDBySuffix returns the highest index value from messages with the
// specified suffix in the mailbox.
func (mbox *Mailbox) LastIDBySuffix(suffix uint64) (uint64, error) {
	var id uint64
	err := mbox.store.db.View(func(tx *bolt.Tx) error {
		bucket := tx.Bucket(mbox.uname)
		if bucket == nil {
			return ErrNotFound
		}

		cursor := bucket.Bucket(mailboxesBucket).Bucket([]byte(mbox.name)).Cursor()

		// Loop from the end, returning the first found match.
		for k, _ := cursor.Last(); k != nil; k, _ = cursor.Prev() {
			if len(k) != 16 { // Don't want to loop over buckets.
				continue
			}
			sfx := binary.BigEndian.Uint64(k[8:])
			if sfx == suffix {
				id = binary.BigEndian.Uint64(k[:8])
				return nil
			}
		}
		return ErrNotFound
	})
	if err != nil {
		return 0, err
	}
	return id, nil
}
<commit_msg>Fix bug caused by an attempt to create a slice longer than the underlying array.<commit_after>// Copyright (c) 2015 Monetas.
// Copyright 2016 Daniel Krawisz.
// Use of this source code is governed by an ISC
// license that can be found in the LICENSE file.

package store

import (
	"bytes"
	"encoding/binary"
	"errors"
	"time"
	"fmt"

	"github.com/boltdb/bolt"
)

// Data keys of a mailbox.
var (
	// mailboxCreatedOnKey contains the time of creation of mailbox.
	mailboxCreatedOnKey = []byte("createdOn")

	// ErrDuplicateID is returned by InsertMessage when the a message with the
	// specified ID already exists in the mailbox.
	ErrDuplicateID = errors.New("duplicate ID")
)

// Mailbox is a mailbox corresponding to a private identity or broadcast. It's
// designed such that any kind of message (not just text based) can be stored
// in the data store.
type Mailbox struct {
	store *Store
	uname []byte
	name  string
}

// initializeMailbox initializes a mailbox.
func initializeMailbox(store *Store, uname []byte, name string) error {

	err := store.db.Update(func(tx *bolt.Tx) error {
		// Get bucket for mailbox.
		bucket := tx.Bucket(uname).Bucket(mailboxesBucket).Bucket([]byte(name))

		if bucket == nil {
			// New mailbox so initialize it with all the data.
			bucket, err := tx.Bucket(uname).CreateBucketIfNotExists(mailboxesBucket)
			if err != nil {
				return err
			}

			bucket, err = tx.Bucket(uname).Bucket(mailboxesBucket).CreateBucket([]byte(name))
			if err != nil {
				return err
			}

			data, err := bucket.CreateBucket(mailboxDataBucket)
			if err != nil {
				return err
			}

			now, err := time.Now().MarshalBinary()
			if err != nil {
				return err
			}

			err = data.Put(mailboxCreatedOnKey, now)
			if err != nil {
				return err
			}
		}
		return nil
	})
	if err != nil {
		return fmt.Errorf("Failed to create/load mailbox %s: %v",
			name, err)
	}

	return nil
}

// InsertMessage inserts a new message with the specified suffix and id into the
// mailbox and returns the ID. If input id is 0, then the store automatically
// generates a unique index value. For normal mailboxes, suffix could be the
// encoding type. For special use mailboxes like "Pending", suffix could be
// used as a 'key', like a reason code (why the message is marked as Pending).
func (mbox *Mailbox) InsertMessage(msg []byte, id, suffix uint64) (uint64, error) {
	enc, err := mbox.store.encrypt(msg)
	if err != nil {
		return 0, err
	}

	err = mbox.store.db.Update(func(tx *bolt.Tx) error {
		bucket := tx.Bucket(mbox.uname)
		if bucket == nil {
			return ErrNotFound
		}
		m := bucket.Bucket(mailboxesBucket).Bucket([]byte(mbox.name))

		// Generate a new ID if we asked for it.
		if id == 0 {
			latestId := bucket.Bucket(miscBucket).Get(mailboxLatestIDKey)
			id = binary.BigEndian.Uint64(latestId) + 1

			// Increment mailboxLatestID.
			idB := make([]byte, 8)
			binary.BigEndian.PutUint64(idB, id)

			err = bucket.Bucket(miscBucket).Put(mailboxLatestIDKey, idB)
			if err != nil {
				return err
			}
		}

		// Insert message using ID as the first 8 bytes and suffix as the
		// latter 8 bytes of the key.
		k := make([]byte, 16)
		binary.BigEndian.PutUint64(k[:8], id)     // first half
		binary.BigEndian.PutUint64(k[8:], suffix) // second half

		// Check if a message with the given ID already exists.
		kk, _ := m.Cursor().Seek(k[:8])
		if kk != nil && len(kk) >= 8 && bytes.Equal(kk[:8], k[:8]) {
			return ErrDuplicateID
		}

		return m.Put(k, enc)
	})
	if err != nil {
		return 0, err
	}

	return id, nil
}

// GetMessage retrieves a message from the mailbox by its index. It returns the
// suffix and the message. An error is returned if the message with the given
// index doesn't exist in the database.
func (mbox *Mailbox) GetMessage(id uint64) (uint64, []byte, error) {
	var suffix uint64
	var msg []byte

	var success bool

	idBytes := make([]byte, 8)
	binary.BigEndian.PutUint64(idBytes, id)

	err := mbox.store.db.View(func(tx *bolt.Tx) error {
		bucket := tx.Bucket(mbox.uname)
		if bucket == nil {
			return ErrNotFound
		}

		bucket = bucket.Bucket(mailboxesBucket)
		if bucket == nil {
			return ErrNotFound
		}

		cursor := bucket.Bucket([]byte(mbox.name)).Cursor()
		k, v := cursor.Seek(idBytes)

		// Check if the first 8 bytes match the index.
		if k == nil || v == nil || !bytes.Equal(k[:8], idBytes) {
			return ErrNotFound
		}

		suffix = binary.BigEndian.Uint64(k[8:])
		msg, success = mbox.store.decrypt(v)
		if !success {
			return ErrDecryptionFailed
		}

		return nil
	})
	if err != nil {
		return 0, nil, err
	}

	return suffix, msg, nil
}

// ForEachMessage runs the given function for messages that have IDs between
// lowID and highID with the given suffix. If lowID is 0, it starts from the
// first message. If highID is 0, it returns all messages with id >= lowID with
// the given suffix. If suffix is zero, it returns all messages between lowID
// and highID, irrespective of the suffix. Note that any combination of lowID,
// highID and suffix can be zero for the desired results. Both lowID and highID
// are inclusive.
//
// Suffix is useful for getting all messages of a particular type. For example,
// retrieving all messages with encoding type 2.
//
// The function terminates early if an error occurs and iterates in the
// increasing order of index. Make sure it doesn't take long to execute. DO NOT
// execute any other database operations in it.
func (mbox *Mailbox) ForEachMessage(lowID, highID, suffix uint64,
	f func(id, suffix uint64, msg []byte) error) error {
	if highID != 0 && lowID > highID {
		return errors.New("Nice try, son. But lowID cannot be greater than highID.")
	}

	bLowID := make([]byte, 8)
	binary.BigEndian.PutUint64(bLowID, lowID)

	return mbox.store.db.View(func(tx *bolt.Tx) error {
		bucket := tx.Bucket(mbox.uname)
		if (bucket == nil) {
			return ErrNotFound
		}
		cursor := bucket.Bucket(mailboxesBucket).Bucket([]byte(mbox.name)).Cursor()

		for k, v := cursor.Seek(bLowID); k != nil; k, v = cursor.Next() {
			// We need this safeguard because BoltDB also loops over buckets. We
			// don't want to include the bucket "data" in our query.
			if v == nil {
				continue
			}

			id := binary.BigEndian.Uint64(k[:8])
			sfx := binary.BigEndian.Uint64(k[8:])

			// We already exceeded the highest ID, so stop.
			if highID != 0 && id > highID {
				return nil // We're done with all the looping.
			}

			// The suffix doesn't match so go to next message.
			if suffix != 0 && sfx != suffix {
				continue
			}

			msg, success := mbox.store.decrypt(v)
			if !success {
				return ErrDecryptionFailed
			}

			if err := f(id, sfx, msg); err != nil {
				return err
			}
		}

		return nil
	})
}

// DeleteMessage deletes a message with the given index from the store. An error
// is returned if the message doesn't exist in the store.
func (mbox *Mailbox) DeleteMessage(id uint64) error {
	idxBytes := make([]byte, 8)
	binary.BigEndian.PutUint64(idxBytes, id)

	return mbox.store.db.Update(func(tx *bolt.Tx) error {
		bucket := tx.Bucket(mbox.uname)
		if bucket == nil {
			return ErrNotFound
		}
		bucket = bucket.Bucket(mailboxesBucket).Bucket([]byte(mbox.name))
		k, v := bucket.Cursor().Seek(idxBytes)

		// Check if the first 8 bytes match the index.
		if k == nil || v == nil || !bytes.Equal(k[:8], idxBytes) {
			return ErrNotFound
		}

		return bucket.Delete(k)
	})
}

// Name returns the user-friendly name of the mailbox.
func (mbox *Mailbox) Name() string {
	return mbox.name
}

// SetName changes the name of the mailbox.
func (mbox *Mailbox) SetName(name string) error {
	if name == "" {
		return errors.New("Name cannot be empty.")
	}

	err := mbox.store.db.Update(func(tx *bolt.Tx) error {
		// Check if some other mailbox has the same name.
		err := tx.Bucket(mbox.uname).Bucket(mailboxesBucket).ForEach(func(k, _ []byte) error {
			if string(k) == name {
				return ErrDuplicateMailbox
			}
			return nil
		})
		if err != nil {
			return err
		}

		// Create the new mailbox.
		b, err := tx.Bucket(mbox.uname).Bucket(mailboxesBucket).CreateBucket([]byte(name))
		if err != nil {
			return err
		}

		// Copy everything.
		oldB := tx.Bucket(mbox.uname).Bucket(mailboxesBucket).Bucket([]byte(mbox.name))
		oldB.ForEach(func(k, v []byte) error {
			if v == nil { // It's a bucket.
				b1, err := b.CreateBucket(k)
				if err != nil {
					return err
				}

				// Copy all keys.
				return oldB.Bucket(k).ForEach(func(k1, v1 []byte) error {
					return b1.Put(k1, v1)
				})
			}
			return b.Put(k, v)
		})

		// Delete old mailbox.
		return tx.Bucket(mbox.uname).Bucket(mailboxesBucket).DeleteBucket([]byte(mbox.name))
	})
	if err != nil {
		return err
	}

	mbox.name = name
	return nil
}

// Delete deletes the mailbox. Any operations after a Delete are invalid.
func (mbox *Mailbox) Delete() error {
	return mbox.store.db.Update(func(tx *bolt.Tx) error {
		// Delete the mailbox and associated data.
		bucket := tx.Bucket(mbox.uname)
		if bucket == nil {
			return ErrNotFound
		}
		err := bucket.Bucket(mailboxesBucket).DeleteBucket([]byte(mbox.name))
		if err != nil {
			return err
		}

		// Delete mailbox from store.
		delete(mbox.store.mailboxes, mbox.name)
		return nil
	})
}

// NextID returns the next index value that will be assigned in the mailbox..
func (mbox *Mailbox) NextID() (uint64, error) {
	var id uint64

	err := mbox.store.db.View(func(tx *bolt.Tx) error {
		// Only one id is used for the entire set of mailboxes for a given user.
		id = binary.BigEndian.Uint64(tx.Bucket(mbox.uname).Bucket(miscBucket).Get(mailboxLatestIDKey)) + 1
		return nil
	})
	if err != nil {
		return 0, err
	}
	return id, nil
}

// LastID returns the highest index value in the mailbox.
func (mbox *Mailbox) LastID() (uint64, error) {
	var id uint64

	err := mbox.store.db.View(func(tx *bolt.Tx) error {
		bucket := tx.Bucket(mbox.uname)
		if bucket == nil {
			return ErrNotFound
		}
		cursor := bucket.Bucket(mailboxesBucket).Bucket([]byte(mbox.name)).Cursor()

		// Read from the end until we have a non-nil value.
		for k, _ := cursor.Last(); ; k, _ = cursor.Prev() {
			if k == nil { // No records
				return ErrNotFound
			}
			if len(k) != 16 { // Don't want to read key from a bucket.
				continue
			}
			id = binary.BigEndian.Uint64(k[:8])
			return nil
		}
	})
	if err != nil {
		return 0, err
	}
	return id, nil
}

// LastIDBySuffix returns the highest index value from messages with the
// specified suffix in the mailbox.
func (mbox *Mailbox) LastIDBySuffix(suffix uint64) (uint64, error) {
	var id uint64
	err := mbox.store.db.View(func(tx *bolt.Tx) error {
		bucket := tx.Bucket(mbox.uname)
		if bucket == nil {
			return ErrNotFound
		}

		cursor := bucket.Bucket(mailboxesBucket).Bucket([]byte(mbox.name)).Cursor()

		// Loop from the end, returning the first found match.
		for k, _ := cursor.Last(); k != nil; k, _ = cursor.Prev() {
			if len(k) != 16 { // Don't want to loop over buckets.
				continue
			}
			sfx := binary.BigEndian.Uint64(k[8:])
			if sfx == suffix {
				id = binary.BigEndian.Uint64(k[:8])
				return nil
			}
		}
		return ErrNotFound
	})
	if err != nil {
		return 0, err
	}
	return id, nil
}
<|endoftext|>


<commit_before>package stream

import (
	"encoding/json"
	"fmt"
	"github.com/andygrunwald/gotrap/config"
	"github.com/andygrunwald/gotrap/gerrit"
	"github.com/andygrunwald/gotrap/github"
	"github.com/streadway/amqp"
	"log"
	"strings"
)

func handleNewMessage(g github.GithubClient, gerritClient gerrit.GerritInstance, c *config.Configuration, event amqp.Delivery) {
	// Acknowledge message
	defer event.Ack(false)

	var change gerrit.Message

	err := json.Unmarshal(event.Body, &change)
	if err != nil {
		log.Fatal(err)
	}

	// Stream events are documented
	// See https://git.eclipse.org/r/Documentation/cmd-stream-events.html
	switch change.Type {
	case "patchset-created":
		log.Printf("> New patchset-created message incoming for ref \"%s\" in \"%s\" (\"%s\")", change.Patchset.Ref, change.Change.Project, change.Change.URL)

		if change.Change.Project != "Packages/TYPO3.CMS" {
			log.Printf("> Project \"%s\" currently not supported. Only \"%s\"", change.Change.Project, "Packages/TYPO3.CMS")
			return
		}

		// TODO: Get current revision number
		// If this revision / patchset number is not the current number
		// we will skip this patchset-created request, because
		// why should we create a pull request for an old patchset?
		// The current patchset will be delivered later as message.
		// So we won`t skip this changeset
		// https://review.typo3.org/a/changes/I640486e9f32da6ac1eba05e3c38d15a0aba41055/?o=CURRENT_REVISION
		if currentPatchset, _ := gerritClient.IsPatchsetTheCurrentPatchset(change.Change.ID, change.Patchset.Number); currentPatchset == false {
			log.Printf("> Patchset skipped, because it is not the current one (Ref: %s)", change.Patchset.Ref)
			return
		}

		// Create the pull request
		pullRequest, err := g.CreatePullRequestForPatchset(&change)
		if err != nil {
			// TODO: I don`t have an idea what to do if i fail to create a PR
			log.Println("> Error during creating new pull request", err)
			return
		}

		log.Printf("> New pull request created: %s", *pullRequest.HTMLURL)

		// Poll travis ci and wait until the PR got a status
		s, _ := g.WaitUntilCommitStatusIsAvailable(*pullRequest)

		var vote int
		switch *s.State {
		// Success if the latest status for all contexts is success
		case "success":
			vote = 0

		// Failure if any of the contexts report as error or failure
		case "failure":
			vote = -1
		}

		// Generate detail information about status
		var statusDetails []string
		for _, repoStatus := range s.Statuses {
			if *repoStatus.State != "success" {
				continue
			}

			statusDetails = append(statusDetails, "Service: "+*repoStatus.Context)
			statusDetails = append(statusDetails, "Description: "+*repoStatus.Description)
			statusDetails = append(statusDetails, "URL: "+*repoStatus.TargetURL)
			statusDetails = append(statusDetails, "\n")
		}

		// Build template for Gerrit vote action
		msg := gerritClient.Template
		msg = strings.Replace(msg, "%state%", *s.State, 1)
		msg = strings.Replace(msg, "%status%", strings.Join(statusDetails, "\n\n"), 1)
		msg = strings.Replace(msg, "%pr%", *pullRequest.HTMLURL, 1)

		// Post Command + Vote on Changeset
		gerritClient.PostCommentOnChangeset(&change, vote, msg)

		msg = "This PR will be closed, because the tests results were reported back to Gerrit. "
		msg += fmt.Sprintf("See [%s](%s) for details.", change.Change.Subject, change.Change.URL)

		// TODO Add Details to Github Pull Request, before closing
		// This does not work currently. I don`t have a clue why. Check this later ;)
		g.AddCommentToPullRequest(pullRequest, msg)

		g.ClosePullRequest(pullRequest)

	case "change-abandoned":
		// We have to close all PR`s
		// change-restored
		// change-merged
		// ref-updated
		// ref-replicated
		// ref-replication-done
		// comment-added
		// topic-changed
		// ....
	default:
		log.Printf("> Skipped AMQP message (uncovered message type: %s)\n", change.Type)
	}

	return
}
<commit_msg>Ack message as fast as possible<commit_after>package stream

import (
	"encoding/json"
	"fmt"
	"github.com/andygrunwald/gotrap/config"
	"github.com/andygrunwald/gotrap/gerrit"
	"github.com/andygrunwald/gotrap/github"
	"github.com/streadway/amqp"
	"log"
	"strings"
)

func handleNewMessage(g github.GithubClient, gerritClient gerrit.GerritInstance, c *config.Configuration, event amqp.Delivery) {
	// Acknowledge message if we get this
	// We do this, because at the end of proceeding we might lost the connection to AMQP server
	// I know this is wrong, but currently the reconnection does not work correctly :(
	// TODO: Fix this later and Ack message if its done
	event.Ack(false)

	var change gerrit.Message

	err := json.Unmarshal(event.Body, &change)
	if err != nil {
		log.Fatal(err)
	}

	// Stream events are documented
	// See https://git.eclipse.org/r/Documentation/cmd-stream-events.html
	switch change.Type {
	case "patchset-created":
		log.Printf("> New patchset-created message incoming for ref \"%s\" in \"%s\" (\"%s\")", change.Patchset.Ref, change.Change.Project, change.Change.URL)

		if change.Change.Project != "Packages/TYPO3.CMS" {
			log.Printf("> Project \"%s\" currently not supported. Only \"%s\"", change.Change.Project, "Packages/TYPO3.CMS")
			return
		}

		// TODO: Get current revision number
		// If this revision / patchset number is not the current number
		// we will skip this patchset-created request, because
		// why should we create a pull request for an old patchset?
		// The current patchset will be delivered later as message.
		// So we won`t skip this changeset
		// https://review.typo3.org/a/changes/I640486e9f32da6ac1eba05e3c38d15a0aba41055/?o=CURRENT_REVISION
		if currentPatchset, _ := gerritClient.IsPatchsetTheCurrentPatchset(change.Change.ID, change.Patchset.Number); currentPatchset == false {
			log.Printf("> Patchset skipped, because it is not the current one (Ref: %s)", change.Patchset.Ref)
			return
		}

		// Create the pull request
		pullRequest, err := g.CreatePullRequestForPatchset(&change)
		if err != nil {
			// TODO: I don`t have an idea what to do if i fail to create a PR
			log.Println("> Error during creating new pull request", err)
			return
		}

		log.Printf("> New pull request created: %s", *pullRequest.HTMLURL)

		// Poll travis ci and wait until the PR got a status
		s, _ := g.WaitUntilCommitStatusIsAvailable(*pullRequest)

		var vote int
		switch *s.State {
		// Success if the latest status for all contexts is success
		case "success":
			vote = 0

		// Failure if any of the contexts report as error or failure
		case "failure":
			vote = -1
		}

		// Generate detail information about status
		var statusDetails []string
		for _, repoStatus := range s.Statuses {
			if *repoStatus.State != "success" {
				continue
			}

			statusDetails = append(statusDetails, "Service: "+*repoStatus.Context)
			statusDetails = append(statusDetails, "Description: "+*repoStatus.Description)
			statusDetails = append(statusDetails, "URL: "+*repoStatus.TargetURL)
			statusDetails = append(statusDetails, "\n")
		}

		// Build template for Gerrit vote action
		msg := gerritClient.Template
		msg = strings.Replace(msg, "%state%", *s.State, 1)
		msg = strings.Replace(msg, "%status%", strings.Join(statusDetails, "\n\n"), 1)
		msg = strings.Replace(msg, "%pr%", *pullRequest.HTMLURL, 1)

		// Post Command + Vote on Changeset
		gerritClient.PostCommentOnChangeset(&change, vote, msg)

		msg = "This PR will be closed, because the tests results were reported back to Gerrit. "
		msg += fmt.Sprintf("See [%s](%s) for details.", change.Change.Subject, change.Change.URL)

		// TODO Add Details to Github Pull Request, before closing
		// This does not work currently. I don`t have a clue why. Check this later ;)
		g.AddCommentToPullRequest(pullRequest, msg)

		g.ClosePullRequest(pullRequest)

	case "change-abandoned":
		// We have to close all PR`s
		// change-restored
		// change-merged
		// ref-updated
		// ref-replicated
		// ref-replication-done
		// comment-added
		// topic-changed
		// ....
	default:
		log.Printf("> Skipped AMQP message (uncovered message type: %s)\n", change.Type)
	}

	return
}
<|endoftext|>


<commit_before>// Package libsacloud is the SAKURA CLOUD API v1.1 Client for Go.
package libsacloud

// Version バージョン
const Version = "1.18.1"
<commit_msg>Bump to v1.18.2<commit_after>// Package libsacloud is the SAKURA CLOUD API v1.1 Client for Go.
package libsacloud

// Version バージョン
const Version = "1.18.2"
<|endoftext|>


<commit_before>package main

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

	"github.com/nbari/violetear"
	"github.com/nbari/violetear/middleware"
)

func hello_world(w http.ResponseWriter, r *http.Request) {
	fmt.Fprintf(w, "Hi there, I love %s!", r.URL.Path[1:])
}
func hello_world_all(w http.ResponseWriter, r *http.Request) {
	fmt.Fprintf(w, "catch %s!", r.URL.Path)
}
func not_found(w http.ResponseWriter, r *http.Request) {
	fmt.Fprintf(w, "not found %s!", r.URL.Path)
}

func commonHeaders(fn http.HandlerFunc) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		w.Header().Set("X-app-Version", "1.0")
		fn(w, r)
	}
}

func exampleMiddleware(next http.Handler) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		// Our middleware logic goes here...
		w.Header().Set("X-app-Version", "1.0")
		next.ServeHTTP(w, r)
	})
}

func logger(next http.Handler) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		lw := violetear.NewResponseWriter(w)
		w.Header().Set("request-id", "naranjas")
		next.ServeHTTP(lw, r)
		log.Printf("%s [%s] %d %d",
			r.RemoteAddr,
			r.URL,
			lw.Status(),
			lw.Size())
	})
}

func middlewareOne(next http.Handler) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		log.Println("Executing middlewareOne")
		next.ServeHTTP(w, r)
		log.Println("Executing middlewareOne again")
	})
}

func middlewareTwo(next http.Handler) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		log.Println("Executing middlewareTwo")
		if r.URL.Path != "/" {
			return
		}
		next.ServeHTTP(w, r)
		log.Println("Executing middlewareTwo again")
	})
}

func final(w http.ResponseWriter, r *http.Request) {
	log.Println("Executing finalHandler")
	w.Write([]byte("OK"))
}

func main() {
	router := violetear.New()
	router.LogRequests = true
	router.RequestID = "request-id"
	//	router.Verbose = false

	router.AddRegex(":uuid", `[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}`)
	router.AddRegex(":sopas", `sopas`)

	stdChain := middleware.New(logger, middlewareOne, middlewareTwo)

	router.Handle("/", stdChain.ThenFunc(final), "GET")
	router.Handle("/foo", stdChain.ThenFunc(final), "GET")
	router.HandleFunc("/hello/world/:sopas", hello_world_all, "GET")
	router.HandleFunc(":uuid", hello_world)
	router.HandleFunc("*", hello_world)
	router.HandleFunc("/hola/*", hello_world)
	router.HandleFunc("/hola/:sopas", hello_world)
	router.HandleFunc("/hola/epazote", hello_world)
	router.HandleFunc("/hola/epazote/*", hello_world)
	router.HandleFunc("/hola/epazote/a/papas", hello_world)

	log.Fatal(http.ListenAndServe(":8080", router))
}
<commit_msg>update<commit_after>package main

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

	"github.com/nbari/violetear"
	"github.com/nbari/violetear/middleware"
)

func hello_world(w http.ResponseWriter, r *http.Request) {
	fmt.Fprintf(w, "Hi there, I love %s!", r.URL.Path[1:])
}
func hello_world_all(w http.ResponseWriter, r *http.Request) {
	fmt.Fprintf(w, "catch %s!", r.URL.Path)
}
func not_found(w http.ResponseWriter, r *http.Request) {
	fmt.Fprintf(w, "not found %s!", r.URL.Path)
}

func commonHeaders(fn http.HandlerFunc) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		w.Header().Set("X-app-Version", "1.0")
		fn(w, r)
	}
}

func exampleMiddleware(next http.Handler) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		// Our middleware logic goes here...
		w.Header().Set("X-app-Version", "1.0")
		next.ServeHTTP(w, r)
	})
}

func logger(next http.Handler) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		lw := violetear.NewResponseWriter(w, "")
		w.Header().Set("request-id", "naranjas")
		next.ServeHTTP(lw, r)
		log.Printf("---- %s [%s] %d %d",
			r.RemoteAddr,
			r.URL,
			lw.Status(),
			lw.Size())
	})
}

func middlewareOne(next http.Handler) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		log.Println("Executing middlewareOne")
		next.ServeHTTP(w, r)
		log.Println("Executing middlewareOne again")
	})
}

func middlewareTwo(next http.Handler) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		log.Println("Executing middlewareTwo")
		if r.URL.Path != "/" {
			return
		}
		next.ServeHTTP(w, r)
		log.Println("Executing middlewareTwo again")
	})
}

func final(w http.ResponseWriter, r *http.Request) {
	log.Println("Executing finalHandler")
	w.Write([]byte("OK"))
}

func main() {
	router := violetear.New()
	router.LogRequests = true
	router.RequestID = "request-id"
	//	router.Verbose = false

	router.AddRegex(":uuid", `[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}`)
	router.AddRegex(":sopas", `sopas`)

	stdChain := middleware.New(logger, middlewareOne, middlewareTwo)

	router.Handle("/", stdChain.ThenFunc(final), "GET")
	router.Handle("/foo", stdChain.ThenFunc(final), "GET")
	router.HandleFunc("/hello/world/:sopas", hello_world_all, "GET")
	router.HandleFunc(":uuid", hello_world)
	router.HandleFunc("*", hello_world)
	router.HandleFunc("/hola/*", hello_world)
	router.HandleFunc("/hola/:sopas", hello_world)
	router.HandleFunc("/hola/epazote", hello_world)
	router.HandleFunc("/hola/epazote/*", hello_world)
	router.HandleFunc("/hola/epazote/a/papas", hello_world)

	log.Fatal(http.ListenAndServe(":8080", router))
}
<|endoftext|>


<commit_before>// Copyright 2013 The Bufferpool Authors. All rights reserved.
// Use of this source code is governed by the BSD 2-Clause license,
// which can be found in the LICENSE file.

package bufferpool_test

import (
	"bytes"
	"fmt"
	"testing"

	"github.com/jzelinskie/bufferpool"
)

func TestTakeFromEmpty(t *testing.T) {
	bp := bufferpool.New(1, 1)
	poolBuf := bp.Take()
	if !bytes.Equal(poolBuf.Bytes(), []byte("")) {
		t.Fatalf("Buffer from empty bufferpool was allocated incorrectly.")
	}
}

func TestTakeFromFilled(t *testing.T) {
	bp := bufferpool.New(1, 1)
	bp.Give(bytes.NewBuffer([]byte("X")))
	reusedBuf := bp.Take()
	if !bytes.Equal(reusedBuf.Bytes(), []byte("")) {
		t.Fatalf("Buffer from filled bufferpool was recycled incorrectly.")
	}
}

func ExampleNew() {
	catBuffer := bytes.NewBuffer([]byte("cat"))
	bp := bufferpool.New(10, catBuffer.Len())
	bp.Give(catBuffer) // An error is returned, but not neccessary to check
	reusedBuffer := bp.Take()
	reusedBuffer.Write([]byte("dog"))
	fmt.Println(reusedBuffer)
	// Output:
	// dog
}
<commit_msg>Fix import path in test<commit_after>// Copyright 2013 The Bufferpool Authors. All rights reserved.
// Use of this source code is governed by the BSD 2-Clause license,
// which can be found in the LICENSE file.

package bufferpool_test

import (
	"bytes"
	"fmt"
	"testing"

	"github.com/pushrax/bufferpool"
)

func TestTakeFromEmpty(t *testing.T) {
	bp := bufferpool.New(1, 1)
	poolBuf := bp.Take()
	if !bytes.Equal(poolBuf.Bytes(), []byte("")) {
		t.Fatalf("Buffer from empty bufferpool was allocated incorrectly.")
	}
}

func TestTakeFromFilled(t *testing.T) {
	bp := bufferpool.New(1, 1)
	bp.Give(bytes.NewBuffer([]byte("X")))
	reusedBuf := bp.Take()
	if !bytes.Equal(reusedBuf.Bytes(), []byte("")) {
		t.Fatalf("Buffer from filled bufferpool was recycled incorrectly.")
	}
}

func ExampleNew() {
	catBuffer := bytes.NewBuffer([]byte("cat"))
	bp := bufferpool.New(10, catBuffer.Len())
	bp.Give(catBuffer) // An error is returned, but not neccessary to check
	reusedBuffer := bp.Take()
	reusedBuffer.Write([]byte("dog"))
	fmt.Println(reusedBuffer)
	// Output:
	// dog
}
<|endoftext|>


<commit_before>package pbkdf2

import (
	"crypto/rand"
	"crypto/sha256"
	"crypto/sha512"
	"fmt"
	"hash"

	"golang.org/x/crypto/pbkdf2"
)

type PBKDF2 struct {
	Hash       string `json:"hash,omitempty" toml:"hash"`
	Iterations int    `json:"iterations,omitempty" toml:"iterations"`
	SaltLen    int    `json:"saltlen,omitempty" toml:"saltlen"`
}

const (
	hashSHA256        = "sha256"
	hashSHA512        = "sha512"
	defaultHash       = hashSHA512
	defaultIterations = 100000
	defaultSaltLen    = 16
)

func New() *PBKDF2 {
	return &PBKDF2{
		Hash:       defaultHash,
		Iterations: defaultIterations,
		SaltLen:    defaultSaltLen,
	}
}

func (p *PBKDF2) HashFunc() func() hash.Hash {
	hash := p.Hash
	switch hash {
	default:
		if hash != "" {
			fmt.Println("Invalid PBKDF2 Hash, using default")
		}
		fallthrough
	case hashSHA512:
		return sha512.New
	case hashSHA256:
		return sha256.New
	}
}

func (p *PBKDF2) DeriveKeyWithSalt(password []byte, salt []byte, keyLen int) ([]byte, error) {
	iterations := p.Iterations
	hashFunc := p.HashFunc()
	return pbkdf2.Key(password, salt, iterations, keyLen, hashFunc), nil
}

func (p *PBKDF2) DeriveKey(password []byte, keyLen int) ([]byte, []byte, error) {
	salt := make([]byte, p.SaltLen)
	if _, err := rand.Read(salt); err != nil {
		return nil, nil, err
	}

	key, _ := p.DeriveKeyWithSalt(password, salt, keyLen)

	return key, salt, nil
}
<commit_msg>crypto/pbkdf2: Check error return value (#163)<commit_after>package pbkdf2

import (
	"crypto/rand"
	"crypto/sha256"
	"crypto/sha512"
	"fmt"
	"hash"

	"golang.org/x/crypto/pbkdf2"
)

type PBKDF2 struct {
	Hash       string `json:"hash,omitempty" toml:"hash"`
	Iterations int    `json:"iterations,omitempty" toml:"iterations"`
	SaltLen    int    `json:"saltlen,omitempty" toml:"saltlen"`
}

const (
	hashSHA256        = "sha256"
	hashSHA512        = "sha512"
	defaultHash       = hashSHA512
	defaultIterations = 100000
	defaultSaltLen    = 16
)

func New() *PBKDF2 {
	return &PBKDF2{
		Hash:       defaultHash,
		Iterations: defaultIterations,
		SaltLen:    defaultSaltLen,
	}
}

func (p *PBKDF2) HashFunc() func() hash.Hash {
	hash := p.Hash
	switch hash {
	default:
		if hash != "" {
			fmt.Println("Invalid PBKDF2 Hash, using default")
		}
		fallthrough
	case hashSHA512:
		return sha512.New
	case hashSHA256:
		return sha256.New
	}
}

func (p *PBKDF2) DeriveKeyWithSalt(password []byte, salt []byte, keyLen int) ([]byte, error) {
	iterations := p.Iterations
	hashFunc := p.HashFunc()
	return pbkdf2.Key(password, salt, iterations, keyLen, hashFunc), nil
}

func (p *PBKDF2) DeriveKey(password []byte, keyLen int) ([]byte, []byte, error) {
	salt := make([]byte, p.SaltLen)
	if _, err := rand.Read(salt); err != nil {
		return nil, nil, err
	}

	key, err := p.DeriveKeyWithSalt(password, salt, keyLen)
	if err != nil {
		return nil, nil, err
	}

	return key, salt, nil
}
<|endoftext|>


<commit_before><commit_msg>Change the API return status code from 202 to 503<commit_after><|endoftext|>


<commit_before>package commands

import (
	"fmt"
	"net/url"
	"os"
	"strconv"

	"github.com/concourse/concourse/fly/commands/internal/flaghelpers"
	"github.com/concourse/concourse/fly/eventstream"
	"github.com/concourse/concourse/fly/rc"
)

type WatchCommand struct {
	Job       flaghelpers.JobFlag `short:"j" long:"job"         value-name:"PIPELINE/JOB"  description:"Watches builds of the given job"`
	Build     string              `short:"b" long:"build"                                  description:"Watches a specific build"`
	Url       string              `short:"u" long:"url"                                    description:"URL for the build or job to watch"`
	Timestamp bool                `short:"t" long:"timestamps"                             description:"Print with local timestamp"`
}

func getBuildIDFromURL(target rc.Target, urlParam string) (int, error) {
	var buildId int
	client := target.Client()

	u, err := url.Parse(urlParam)
	if err != nil {
		return 0, err
	}
	urlMap := parseUrlPath(u.Path)

	if urlMap["pipelines"] != "" && urlMap["jobs"] != "" {
		build, err := GetBuild(client, target.Team(), urlMap["jobs"], urlMap["builds"], urlMap["pipelines"])

		if err != nil {
			return 0, err
		}
		buildId = build.ID
	} else if urlMap["builds"] != "" {
		buildId, err = strconv.Atoi(urlMap["builds"])

		if err != nil {
			return 0, err
		}
	} else {
		return 0, fmt.Errorf("No build found in %s", urlParam)
	}
	return buildId, nil
}

func (command *WatchCommand) Execute(args []string) error {
	target, err := rc.LoadTarget(Fly.Target, Fly.Verbose)
	if err != nil {
		return err
	}

	err = target.Validate()
	if err != nil {
		return err
	}

	var buildId int
	client := target.Client()
	if command.Job.JobName != "" || command.Build == "" && command.Url == "" {
		build, err := GetBuild(client, target.Team(), command.Job.JobName, command.Build, command.Job.PipelineName)
		if err != nil {
			return err
		}
		buildId = build.ID
	} else if command.Build != "" {
		buildId, err = strconv.Atoi(command.Build)

		if err != nil {
			return err
		}
	} else if command.Url != "" {
		buildId, err = getBuildIDFromURL(target, command.Url)

		if err != nil {
			return err
		}
	}

	eventSource, err := client.BuildEvents(fmt.Sprintf("%d", buildId))
	if err != nil {
		return err
	}

	renderOptions := eventstream.RenderOptions{ShowTimestamp: command.Timestamp}

	exitCode := eventstream.Render(os.Stdout, eventSource, renderOptions)

	eventSource.Close()

	os.Exit(exitCode)

	return nil
}
<commit_msg>Add more URL verification<commit_after>package commands

import (
	"fmt"
	"net/url"
	"os"
	"strconv"

	"github.com/concourse/concourse/fly/commands/internal/flaghelpers"
	"github.com/concourse/concourse/fly/eventstream"
	"github.com/concourse/concourse/fly/rc"
)

type WatchCommand struct {
	Job       flaghelpers.JobFlag `short:"j" long:"job"         value-name:"PIPELINE/JOB"  description:"Watches builds of the given job"`
	Build     string              `short:"b" long:"build"                                  description:"Watches a specific build"`
	Url       string              `short:"u" long:"url"                                    description:"URL for the build or job to watch"`
	Timestamp bool                `short:"t" long:"timestamps"                             description:"Print with local timestamp"`
}

func getBuildIDFromURL(target rc.Target, urlParam string) (int, error) {
	var buildId int
	client := target.Client()

	u, err := url.Parse(urlParam)
	if err != nil {
		return 0, err
	}

	urlMap := parseUrlPath(u.Path)

	parsedTargetUrl := url.URL{
		Scheme: u.Scheme,
		Host:   u.Host,
	}

	host := parsedTargetUrl.String()
	if host != target.URL() {
		err = fmt.Errorf("URL doesn't match target (%s, %s)", urlParam, target.URL())
		return 0, err
	}

	team := urlMap["teams"]
	if team != "" && team != target.Team().Name() {
		err = fmt.Errorf("Team in URL doesn't match the current team of the target (%s, %s)", urlParam, team)
		return 0, err
	}

	if urlMap["pipelines"] != "" && urlMap["jobs"] != "" {
		build, err := GetBuild(client, target.Team(), urlMap["jobs"], urlMap["builds"], urlMap["pipelines"])

		if err != nil {
			return 0, err
		}
		buildId = build.ID
	} else if urlMap["builds"] != "" {
		buildId, err = strconv.Atoi(urlMap["builds"])

		if err != nil {
			return 0, err
		}
	} else {
		return 0, fmt.Errorf("No build found in %s", urlParam)
	}
	return buildId, nil
}

func (command *WatchCommand) Execute(args []string) error {
	target, err := rc.LoadTarget(Fly.Target, Fly.Verbose)
	if err != nil {
		return err
	}

	err = target.Validate()
	if err != nil {
		return err
	}

	var buildId int
	client := target.Client()
	if command.Job.JobName != "" || command.Build == "" && command.Url == "" {
		build, err := GetBuild(client, target.Team(), command.Job.JobName, command.Build, command.Job.PipelineName)
		if err != nil {
			return err
		}
		buildId = build.ID
	} else if command.Build != "" {
		buildId, err = strconv.Atoi(command.Build)

		if err != nil {
			return err
		}
	} else if command.Url != "" {
		buildId, err = getBuildIDFromURL(target, command.Url)

		if err != nil {
			return err
		}
	}

	eventSource, err := client.BuildEvents(fmt.Sprintf("%d", buildId))
	if err != nil {
		return err
	}

	renderOptions := eventstream.RenderOptions{ShowTimestamp: command.Timestamp}

	exitCode := eventstream.Render(os.Stdout, eventSource, renderOptions)

	eventSource.Close()

	os.Exit(exitCode)

	return nil
}
<|endoftext|>