<commit_before>package kcp

import (
	"sync"

	"github.com/v2ray/v2ray-core/common"
	"github.com/v2ray/v2ray-core/common/alloc"
	_ "github.com/v2ray/v2ray-core/common/log"
	"github.com/v2ray/v2ray-core/common/serial"
)

var (
	dataSegmentPool = &sync.Pool{
		New: func() interface{} { return new(DataSegment) },
	}
	ackSegmentPool = &sync.Pool{
		New: func() interface{} { return new(AckSegment) },
	}
	cmdSegmentPool = &sync.Pool{
		New: func() interface{} { return new(CmdOnlySegment) },
	}
)

type SegmentCommand byte

const (
	SegmentCommandACK        SegmentCommand = 0
	SegmentCommandData       SegmentCommand = 1
	SegmentCommandTerminated SegmentCommand = 2
	SegmentCommandPing       SegmentCommand = 3
)

type SegmentOption byte

const (
	SegmentOptionClose SegmentOption = 1
)

type Segment interface {
	common.Releasable
	ByteSize() int
	Bytes([]byte) []byte
}

const (
	DataSegmentOverhead = 18
)

type DataSegment struct {
	Conv        uint16
	Opt         SegmentOption
	Timestamp   uint32
	Number      uint32
	SendingNext uint32
	Data        *alloc.Buffer

	timeout    uint32
	ackSkipped uint32
	transmit   uint32
}

func NewDataSegment() *DataSegment {
	return dataSegmentPool.Get().(*DataSegment)
}

func (this *DataSegment) Bytes(b []byte) []byte {
	b = serial.Uint16ToBytes(this.Conv, b)
	b = append(b, byte(SegmentCommandData), byte(this.Opt))
	b = serial.Uint32ToBytes(this.Timestamp, b)
	b = serial.Uint32ToBytes(this.Number, b)
	b = serial.Uint32ToBytes(this.SendingNext, b)
	b = serial.Uint16ToBytes(uint16(this.Data.Len()), b)
	b = append(b, this.Data.Value...)
	return b
}

func (this *DataSegment) ByteSize() int {
	return 2 + 1 + 1 + 4 + 4 + 4 + 2 + this.Data.Len()
}

func (this *DataSegment) Release() {
	this.Data.Release()
	this.Data = nil
	this.Opt = 0
	this.timeout = 0
	this.ackSkipped = 0
	this.transmit = 0
	dataSegmentPool.Put(this)
}

type AckSegment struct {
	Conv            uint16
	Opt             SegmentOption
	ReceivingWindow uint32
	ReceivingNext   uint32
	Count           byte
	NumberList      []uint32
	TimestampList   []uint32
}

func NewAckSegment() *AckSegment {
	seg := ackSegmentPool.Get().(*AckSegment)
	if seg.NumberList == nil {
		seg.NumberList = make([]uint32, 0, 128)
	}
	if seg.TimestampList == nil {
		seg.TimestampList = make([]uint32, 0, 128)
	}
	return seg
}

func (this *AckSegment) PutNumber(number uint32, timestamp uint32) {
	this.Count++
	this.NumberList = append(this.NumberList, number)
	this.TimestampList = append(this.TimestampList, timestamp)
}

func (this *AckSegment) IsFull() bool {
	return this.Count == 128
}

func (this *AckSegment) ByteSize() int {
	return 2 + 1 + 1 + 4 + 4 + 1 + int(this.Count)*4 + int(this.Count)*4
}

func (this *AckSegment) Bytes(b []byte) []byte {
	b = serial.Uint16ToBytes(this.Conv, b)
	b = append(b, byte(SegmentCommandACK), byte(this.Opt))
	b = serial.Uint32ToBytes(this.ReceivingWindow, b)
	b = serial.Uint32ToBytes(this.ReceivingNext, b)
	b = append(b, this.Count)
	for i := byte(0); i < this.Count; i++ {
		b = serial.Uint32ToBytes(this.NumberList[i], b)
		b = serial.Uint32ToBytes(this.TimestampList[i], b)
	}
	return b
}

func (this *AckSegment) Release() {
	this.Opt = 0
	this.Count = 0
	this.NumberList = this.NumberList[:0]
	this.TimestampList = this.TimestampList[:0]
	ackSegmentPool.Put(this)
}

type CmdOnlySegment struct {
	Conv         uint16
	Cmd          SegmentCommand
	Opt          SegmentOption
	SendingNext  uint32
	ReceivinNext uint32
}

func NewCmdOnlySegment() *CmdOnlySegment {
	return cmdSegmentPool.Get().(*CmdOnlySegment)
}

func (this *CmdOnlySegment) ByteSize() int {
	return 2 + 1 + 1 + 4 + 4
}

func (this *CmdOnlySegment) Bytes(b []byte) []byte {
	b = serial.Uint16ToBytes(this.Conv, b)
	b = append(b, byte(this.Cmd), byte(this.Opt))
	b = serial.Uint32ToBytes(this.SendingNext, b)
	b = serial.Uint32ToBytes(this.ReceivinNext, b)
	return b
}

func (this *CmdOnlySegment) Release() {
	this.Opt = 0
	cmdSegmentPool.Put(this)
}

func ReadSegment(buf []byte) (Segment, []byte) {
	if len(buf) <= 4 {
		return nil, nil
	}

	conv := serial.BytesToUint16(buf)
	buf = buf[2:]

	cmd := SegmentCommand(buf[0])
	opt := SegmentOption(buf[1])
	buf = buf[2:]

	if cmd == SegmentCommandData {
		seg := &DataSegment{
			Conv: conv,
			Opt:  opt,
		}
		if len(buf) < 16 {
			return nil, nil
		}
		seg.Timestamp = serial.BytesToUint32(buf)
		buf = buf[4:]

		seg.Number = serial.BytesToUint32(buf)
		buf = buf[4:]

		seg.SendingNext = serial.BytesToUint32(buf)
		buf = buf[4:]

		dataLen := int(serial.BytesToUint16(buf))
		buf = buf[2:]

		if len(buf) < dataLen {
			return nil, nil
		}
		seg.Data = alloc.NewSmallBuffer().Clear().Append(buf[:dataLen])
		buf = buf[dataLen:]

		return seg, buf
	}

	if cmd == SegmentCommandACK {
		seg := &AckSegment{
			Conv: conv,
			Opt:  opt,
		}
		if len(buf) < 9 {
			return nil, nil
		}

		seg.ReceivingWindow = serial.BytesToUint32(buf)
		buf = buf[4:]

		seg.ReceivingNext = serial.BytesToUint32(buf)
		buf = buf[4:]

		seg.Count = buf[0]
		buf = buf[1:]

		seg.NumberList = make([]uint32, 0, seg.Count)
		seg.TimestampList = make([]uint32, 0, seg.Count)

		if len(buf) < int(seg.Count)*8 {
			return nil, nil
		}
		for i := 0; i < int(seg.Count); i++ {
			seg.NumberList = append(seg.NumberList, serial.BytesToUint32(buf))
			seg.TimestampList = append(seg.TimestampList, serial.BytesToUint32(buf[4:]))
			buf = buf[8:]
		}

		return seg, buf
	}

	seg := &CmdOnlySegment{
		Conv: conv,
		Cmd:  cmd,
		Opt:  opt,
	}

	if len(buf) < 8 {
		return nil, nil
	}

	seg.SendingNext = serial.BytesToUint32(buf)
	buf = buf[4:]

	seg.ReceivinNext = serial.BytesToUint32(buf)
	buf = buf[4:]

	return seg, buf
}
<commit_msg>leverage pool functions<commit_after>package kcp

import (
	"sync"

	"github.com/v2ray/v2ray-core/common"
	"github.com/v2ray/v2ray-core/common/alloc"
	_ "github.com/v2ray/v2ray-core/common/log"
	"github.com/v2ray/v2ray-core/common/serial"
)

var (
	dataSegmentPool = &sync.Pool{
		New: func() interface{} { return new(DataSegment) },
	}
	ackSegmentPool = &sync.Pool{
		New: func() interface{} { return new(AckSegment) },
	}
	cmdSegmentPool = &sync.Pool{
		New: func() interface{} { return new(CmdOnlySegment) },
	}
)

type SegmentCommand byte

const (
	SegmentCommandACK        SegmentCommand = 0
	SegmentCommandData       SegmentCommand = 1
	SegmentCommandTerminated SegmentCommand = 2
	SegmentCommandPing       SegmentCommand = 3
)

type SegmentOption byte

const (
	SegmentOptionClose SegmentOption = 1
)

type Segment interface {
	common.Releasable
	ByteSize() int
	Bytes([]byte) []byte
}

const (
	DataSegmentOverhead = 18
)

type DataSegment struct {
	Conv        uint16
	Opt         SegmentOption
	Timestamp   uint32
	Number      uint32
	SendingNext uint32
	Data        *alloc.Buffer

	timeout    uint32
	ackSkipped uint32
	transmit   uint32
}

func NewDataSegment() *DataSegment {
	return dataSegmentPool.Get().(*DataSegment)
}

func (this *DataSegment) Bytes(b []byte) []byte {
	b = serial.Uint16ToBytes(this.Conv, b)
	b = append(b, byte(SegmentCommandData), byte(this.Opt))
	b = serial.Uint32ToBytes(this.Timestamp, b)
	b = serial.Uint32ToBytes(this.Number, b)
	b = serial.Uint32ToBytes(this.SendingNext, b)
	b = serial.Uint16ToBytes(uint16(this.Data.Len()), b)
	b = append(b, this.Data.Value...)
	return b
}

func (this *DataSegment) ByteSize() int {
	return 2 + 1 + 1 + 4 + 4 + 4 + 2 + this.Data.Len()
}

func (this *DataSegment) Release() {
	this.Data.Release()
	this.Data = nil
	this.Opt = 0
	this.timeout = 0
	this.ackSkipped = 0
	this.transmit = 0
	dataSegmentPool.Put(this)
}

type AckSegment struct {
	Conv            uint16
	Opt             SegmentOption
	ReceivingWindow uint32
	ReceivingNext   uint32
	Count           byte
	NumberList      []uint32
	TimestampList   []uint32
}

func NewAckSegment() *AckSegment {
	seg := ackSegmentPool.Get().(*AckSegment)
	if seg.NumberList == nil {
		seg.NumberList = make([]uint32, 0, 128)
	}
	if seg.TimestampList == nil {
		seg.TimestampList = make([]uint32, 0, 128)
	}
	return seg
}

func (this *AckSegment) PutNumber(number uint32, timestamp uint32) {
	this.Count++
	this.NumberList = append(this.NumberList, number)
	this.TimestampList = append(this.TimestampList, timestamp)
}

func (this *AckSegment) IsFull() bool {
	return this.Count == 128
}

func (this *AckSegment) ByteSize() int {
	return 2 + 1 + 1 + 4 + 4 + 1 + int(this.Count)*4 + int(this.Count)*4
}

func (this *AckSegment) Bytes(b []byte) []byte {
	b = serial.Uint16ToBytes(this.Conv, b)
	b = append(b, byte(SegmentCommandACK), byte(this.Opt))
	b = serial.Uint32ToBytes(this.ReceivingWindow, b)
	b = serial.Uint32ToBytes(this.ReceivingNext, b)
	b = append(b, this.Count)
	for i := byte(0); i < this.Count; i++ {
		b = serial.Uint32ToBytes(this.NumberList[i], b)
		b = serial.Uint32ToBytes(this.TimestampList[i], b)
	}
	return b
}

func (this *AckSegment) Release() {
	this.Opt = 0
	this.Count = 0
	this.NumberList = this.NumberList[:0]
	this.TimestampList = this.TimestampList[:0]
	ackSegmentPool.Put(this)
}

type CmdOnlySegment struct {
	Conv         uint16
	Cmd          SegmentCommand
	Opt          SegmentOption
	SendingNext  uint32
	ReceivinNext uint32
}

func NewCmdOnlySegment() *CmdOnlySegment {
	return cmdSegmentPool.Get().(*CmdOnlySegment)
}

func (this *CmdOnlySegment) ByteSize() int {
	return 2 + 1 + 1 + 4 + 4
}

func (this *CmdOnlySegment) Bytes(b []byte) []byte {
	b = serial.Uint16ToBytes(this.Conv, b)
	b = append(b, byte(this.Cmd), byte(this.Opt))
	b = serial.Uint32ToBytes(this.SendingNext, b)
	b = serial.Uint32ToBytes(this.ReceivinNext, b)
	return b
}

func (this *CmdOnlySegment) Release() {
	this.Opt = 0
	cmdSegmentPool.Put(this)
}

func ReadSegment(buf []byte) (Segment, []byte) {
	if len(buf) <= 4 {
		return nil, nil
	}

	conv := serial.BytesToUint16(buf)
	buf = buf[2:]

	cmd := SegmentCommand(buf[0])
	opt := SegmentOption(buf[1])
	buf = buf[2:]

	if cmd == SegmentCommandData {
		seg := NewDataSegment()
		seg.Conv = conv
		seg.Opt = opt
		if len(buf) < 16 {
			return nil, nil
		}
		seg.Timestamp = serial.BytesToUint32(buf)
		buf = buf[4:]

		seg.Number = serial.BytesToUint32(buf)
		buf = buf[4:]

		seg.SendingNext = serial.BytesToUint32(buf)
		buf = buf[4:]

		dataLen := int(serial.BytesToUint16(buf))
		buf = buf[2:]

		if len(buf) < dataLen {
			return nil, nil
		}
		seg.Data = alloc.NewSmallBuffer().Clear().Append(buf[:dataLen])
		buf = buf[dataLen:]

		return seg, buf
	}

	if cmd == SegmentCommandACK {
		seg := NewAckSegment()
		seg.Conv = conv
		seg.Opt = opt
		if len(buf) < 9 {
			return nil, nil
		}

		seg.ReceivingWindow = serial.BytesToUint32(buf)
		buf = buf[4:]

		seg.ReceivingNext = serial.BytesToUint32(buf)
		buf = buf[4:]

		seg.Count = buf[0]
		buf = buf[1:]

		seg.NumberList = make([]uint32, 0, seg.Count)
		seg.TimestampList = make([]uint32, 0, seg.Count)

		if len(buf) < int(seg.Count)*8 {
			return nil, nil
		}
		for i := 0; i < int(seg.Count); i++ {
			seg.NumberList = append(seg.NumberList, serial.BytesToUint32(buf))
			seg.TimestampList = append(seg.TimestampList, serial.BytesToUint32(buf[4:]))
			buf = buf[8:]
		}

		return seg, buf
	}

	seg := NewCmdOnlySegment()
	seg.Conv = conv
	seg.Cmd = cmd
	seg.Opt = opt

	if len(buf) < 8 {
		return nil, nil
	}

	seg.SendingNext = serial.BytesToUint32(buf)
	buf = buf[4:]

	seg.ReceivinNext = serial.BytesToUint32(buf)
	buf = buf[4:]

	return seg, buf
}
<|endoftext|>


<commit_before>// Copyright (c) 2016 Uber Technologies, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

package transporttest

import (
	"bytes"
	"fmt"
	"io/ioutil"
	"strings"
	"testing"
	"time"

	"github.com/yarpc/yarpc-go/transport"
)

// DefaultTTLDelta is the default TTLDelta used by RequestMatchers.
const DefaultTTLDelta = 5 * time.Millisecond

// RequestMatcher may be used in gomock argument lists to assert that two
// requests match.
//
// Requests are considered to be matching if:
//
// - All their primitive parameters match.
// - The headers of the received request include all the headers from the
//   source request. It may include extra headers.
// - The contents of the request bodies are the same.
type RequestMatcher struct {
	t    *testing.T
	req  *transport.Request
	body []byte

	// Maximum amount of variation allowed when comparing TTLs. Defaults to 5
	// milliseconds.
	TTLDelta time.Duration
}

// NewRequestMatcher constructs a new RequestMatcher from the given testing.T
// and request.
//
// The request's contents are read in their entirety and replaced with a
// bytes.Reader.
func NewRequestMatcher(t *testing.T, r *transport.Request) RequestMatcher {
	body, err := ioutil.ReadAll(r.Body)
	if err != nil {
		t.Fatalf("failed to read request body: %v", err)
	}

	// restore a copy of the body so that the caller can still use the request
	// object
	r.Body = bytes.NewReader(body)
	return RequestMatcher{t: t, req: r, body: body, TTLDelta: DefaultTTLDelta}
}

// TODO: Headers like User-Agent, Content-Length, etc. make their way to the
// user-level Request object. For now, we're doing the super set check but we
// should do something more specific once yarpc/yarpc.io#2 is resolved.

// Matches checks if the given object matches the Request provided in
// NewRequestMatcher.
func (m RequestMatcher) Matches(got interface{}) bool {
	l := m.req
	r, ok := got.(*transport.Request)
	if !ok {
		panic(fmt.Sprintf("expected *transport.Request, got %v", got))
	}

	if l.Caller != r.Caller {
		m.t.Logf("Caller mismatch: %s != %s", l.Caller, r.Caller)
		return false
	}

	if l.Service != r.Service {
		m.t.Logf("Service mismatch: %s != %s", l.Service, r.Service)
		return false
	}

	if l.Encoding != r.Encoding {
		m.t.Logf("Encoding mismatch: %s != %s", l.Service, r.Service)
		return false
	}

	if l.Procedure != r.Procedure {
		m.t.Logf("Procedure mismatch: %s != %s", l.Procedure, r.Procedure)
		return false
	}

	ttlDiff := l.TTL - r.TTL
	if ttlDiff < 0 {
		ttlDiff = -ttlDiff
	}
	if ttlDiff > m.TTLDelta {
		m.t.Logf("TTL mismatch: %v != %v", l.TTL, r.TTL)
		return false
	}

	if err := checkSuperSet(l.Headers, r.Headers); err != nil {
		m.t.Logf("Headers mismatch: %v != %v\n\t%v", l.Headers, r.Headers, err)
		return false
	}

	rbody, err := ioutil.ReadAll(r.Body)
	if err != nil {
		m.t.Fatalf("failed to read body: %v", err)
	}
	r.Body = bytes.NewReader(rbody) // in case it is reused

	if !bytes.Equal(m.body, rbody) {
		m.t.Logf("Body mismatch: %v != %v", m.body, rbody)
		return false
	}

	return true
}

func (m RequestMatcher) String() string {
	return fmt.Sprintf("matches request %v with body %v", m.req, m.body)
}

// checkSuperSet checks if the items in l are all also present in r.
func checkSuperSet(l, r transport.Headers) error {
	missing := make([]string, 0, len(l))
	for k, vl := range l {
		vr, ok := r.Get(k)
		if !ok || vr != vl {
			missing = append(missing, k)
		}
	}

	if len(missing) > 0 {
		return fmt.Errorf("missing headers: %v", strings.Join(missing, ", "))
	}
	return nil
}

// ResponseMatcher is similar to RequestMatcher but for responses.
type ResponseMatcher struct {
	t    *testing.T
	res  *transport.Response
	body []byte
}

// NewResponseMatcher builds a new ResponseMatcher that verifies that
// responses match the given Response.
func NewResponseMatcher(t *testing.T, r *transport.Response) ResponseMatcher {
	body, err := ioutil.ReadAll(r.Body)
	defer r.Body.Close()
	if err != nil {
		t.Fatalf("failed to read response body: %v", err)
	}

	// restore a copy of the body so that the caller can still use the
	// response object
	r.Body = ioutil.NopCloser(bytes.NewReader(body))
	return ResponseMatcher{t: t, res: r, body: body}
}

// Matches checks if the given object matches the Response provided in
// NewResponseMatcher.
func (m ResponseMatcher) Matches(got interface{}) bool {
	l := m.res
	r, ok := got.(*transport.Response)
	if !ok {
		panic(fmt.Sprintf("expected *transport.Response, got %v", got))
	}

	if err := checkSuperSet(l.Headers, r.Headers); err != nil {
		m.t.Logf("Headers mismatch: %v != %v\n\t%v", l.Headers, r.Headers, err)
		return false
	}

	rbody, err := ioutil.ReadAll(r.Body)
	if err != nil {
		m.t.Fatalf("failed to read body: %v", err)
	}
	r.Body = ioutil.NopCloser(bytes.NewReader(rbody)) // in case it is reused

	if !bytes.Equal(m.body, rbody) {
		m.t.Logf("Body mismatch: %v != %v", m.body, rbody)
		return false
	}

	return true
}

// FakeResponseWriter is a ResponseWriter that records the headers and the body
// written to it.
type FakeResponseWriter struct {
	Headers transport.Headers
	Body    bytes.Buffer
}

// AddHeaders for FakeResponseWriter.
func (fw *FakeResponseWriter) AddHeaders(h transport.Headers) {
	if fw.Headers == nil {
		fw.Headers = make(transport.Headers)
	}
	for k, v := range h {
		fw.Headers.Set(k, v)
	}
}

// Write for FakeResponseWriter.
func (fw *FakeResponseWriter) Write(s []byte) (int, error) {
	return fw.Body.Write(s)
}
<commit_msg>Reduce flakiness in req-res matching (#123)<commit_after>// Copyright (c) 2016 Uber Technologies, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

package transporttest

import (
	"bytes"
	"fmt"
	"io/ioutil"
	"strings"
	"testing"
	"time"

	"github.com/yarpc/yarpc-go/transport"
)

// DefaultTTLDelta is the default TTLDelta used by RequestMatchers.
const DefaultTTLDelta = 10 * time.Millisecond

// RequestMatcher may be used in gomock argument lists to assert that two
// requests match.
//
// Requests are considered to be matching if:
//
// - All their primitive parameters match.
// - The headers of the received request include all the headers from the
//   source request. It may include extra headers.
// - The contents of the request bodies are the same.
type RequestMatcher struct {
	t    *testing.T
	req  *transport.Request
	body []byte

	// Maximum amount of variation allowed when comparing TTLs. Defaults to 5
	// milliseconds.
	TTLDelta time.Duration
}

// NewRequestMatcher constructs a new RequestMatcher from the given testing.T
// and request.
//
// The request's contents are read in their entirety and replaced with a
// bytes.Reader.
func NewRequestMatcher(t *testing.T, r *transport.Request) RequestMatcher {
	body, err := ioutil.ReadAll(r.Body)
	if err != nil {
		t.Fatalf("failed to read request body: %v", err)
	}

	// restore a copy of the body so that the caller can still use the request
	// object
	r.Body = bytes.NewReader(body)
	return RequestMatcher{t: t, req: r, body: body, TTLDelta: DefaultTTLDelta}
}

// TODO: Headers like User-Agent, Content-Length, etc. make their way to the
// user-level Request object. For now, we're doing the super set check but we
// should do something more specific once yarpc/yarpc.io#2 is resolved.

// Matches checks if the given object matches the Request provided in
// NewRequestMatcher.
func (m RequestMatcher) Matches(got interface{}) bool {
	l := m.req
	r, ok := got.(*transport.Request)
	if !ok {
		panic(fmt.Sprintf("expected *transport.Request, got %v", got))
	}

	if l.Caller != r.Caller {
		m.t.Logf("Caller mismatch: %s != %s", l.Caller, r.Caller)
		return false
	}

	if l.Service != r.Service {
		m.t.Logf("Service mismatch: %s != %s", l.Service, r.Service)
		return false
	}

	if l.Encoding != r.Encoding {
		m.t.Logf("Encoding mismatch: %s != %s", l.Service, r.Service)
		return false
	}

	if l.Procedure != r.Procedure {
		m.t.Logf("Procedure mismatch: %s != %s", l.Procedure, r.Procedure)
		return false
	}

	ttlDiff := l.TTL - r.TTL
	if ttlDiff < 0 {
		ttlDiff = -ttlDiff
	}
	if ttlDiff > m.TTLDelta {
		m.t.Logf("TTL mismatch: %v != %v", l.TTL, r.TTL)
		return false
	}

	if err := checkSuperSet(l.Headers, r.Headers); err != nil {
		m.t.Logf("Headers mismatch: %v != %v\n\t%v", l.Headers, r.Headers, err)
		return false
	}

	rbody, err := ioutil.ReadAll(r.Body)
	if err != nil {
		m.t.Fatalf("failed to read body: %v", err)
	}
	r.Body = bytes.NewReader(rbody) // in case it is reused

	if !bytes.Equal(m.body, rbody) {
		m.t.Logf("Body mismatch: %v != %v", m.body, rbody)
		return false
	}

	return true
}

func (m RequestMatcher) String() string {
	return fmt.Sprintf("matches request %v with body %v", m.req, m.body)
}

// checkSuperSet checks if the items in l are all also present in r.
func checkSuperSet(l, r transport.Headers) error {
	missing := make([]string, 0, len(l))
	for k, vl := range l {
		vr, ok := r.Get(k)
		if !ok || vr != vl {
			missing = append(missing, k)
		}
	}

	if len(missing) > 0 {
		return fmt.Errorf("missing headers: %v", strings.Join(missing, ", "))
	}
	return nil
}

// ResponseMatcher is similar to RequestMatcher but for responses.
type ResponseMatcher struct {
	t    *testing.T
	res  *transport.Response
	body []byte
}

// NewResponseMatcher builds a new ResponseMatcher that verifies that
// responses match the given Response.
func NewResponseMatcher(t *testing.T, r *transport.Response) ResponseMatcher {
	body, err := ioutil.ReadAll(r.Body)
	defer r.Body.Close()
	if err != nil {
		t.Fatalf("failed to read response body: %v", err)
	}

	// restore a copy of the body so that the caller can still use the
	// response object
	r.Body = ioutil.NopCloser(bytes.NewReader(body))
	return ResponseMatcher{t: t, res: r, body: body}
}

// Matches checks if the given object matches the Response provided in
// NewResponseMatcher.
func (m ResponseMatcher) Matches(got interface{}) bool {
	l := m.res
	r, ok := got.(*transport.Response)
	if !ok {
		panic(fmt.Sprintf("expected *transport.Response, got %v", got))
	}

	if err := checkSuperSet(l.Headers, r.Headers); err != nil {
		m.t.Logf("Headers mismatch: %v != %v\n\t%v", l.Headers, r.Headers, err)
		return false
	}

	rbody, err := ioutil.ReadAll(r.Body)
	if err != nil {
		m.t.Fatalf("failed to read body: %v", err)
	}
	r.Body = ioutil.NopCloser(bytes.NewReader(rbody)) // in case it is reused

	if !bytes.Equal(m.body, rbody) {
		m.t.Logf("Body mismatch: %v != %v", m.body, rbody)
		return false
	}

	return true
}

// FakeResponseWriter is a ResponseWriter that records the headers and the body
// written to it.
type FakeResponseWriter struct {
	Headers transport.Headers
	Body    bytes.Buffer
}

// AddHeaders for FakeResponseWriter.
func (fw *FakeResponseWriter) AddHeaders(h transport.Headers) {
	if fw.Headers == nil {
		fw.Headers = make(transport.Headers)
	}
	for k, v := range h {
		fw.Headers.Set(k, v)
	}
}

// Write for FakeResponseWriter.
func (fw *FakeResponseWriter) Write(s []byte) (int, error) {
	return fw.Body.Write(s)
}
<|endoftext|>


<commit_before>// Copyright © 2016 Aaron Longwell
//
// Use of this source code is governed by an MIT licese.
// Details in the LICENSE file.

package trello

// Checklist represents Trello card's checklists.
// A card can have one zero or more checklists.
// https://developers.trello.com/reference/#checklist-object
type Checklist struct {
	ID         string      `json:"id"`
	Name       string      `json:"name"`
	IDBoard    string      `json:"idBoard,omitempty"`
	IDCard     string      `json:"idCard,omitempty"`
	Pos        float64     `json:"pos,omitempty"`
	CheckItems []CheckItem `json:"checkItems,omitempty"`
}

// CheckItem is a nested resource representing an item in Checklist.
type CheckItem struct {
	ID          string  `json:"id"`
	Name        string  `json:"name"`
	State       string  `json:"state"`
	IDChecklist string  `json:"idChecklist,omitempty"`
	Pos         float64 `json:"pos,omitempty"`
}

// Manifestation of CheckItem when it appears in CheckItemStates
// on a Card.
type CheckItemState struct {
	IDCheckItem string `json:"idCheckItem"`
	State       string `json:"state"`
}
<commit_msg>Fix comment style in checklist (golint)<commit_after>// Copyright © 2016 Aaron Longwell
//
// Use of this source code is governed by an MIT licese.
// Details in the LICENSE file.

package trello

// Checklist represents Trello card's checklists.
// A card can have one zero or more checklists.
// https://developers.trello.com/reference/#checklist-object
type Checklist struct {
	ID         string      `json:"id"`
	Name       string      `json:"name"`
	IDBoard    string      `json:"idBoard,omitempty"`
	IDCard     string      `json:"idCard,omitempty"`
	Pos        float64     `json:"pos,omitempty"`
	CheckItems []CheckItem `json:"checkItems,omitempty"`
}

// CheckItem is a nested resource representing an item in Checklist.
type CheckItem struct {
	ID          string  `json:"id"`
	Name        string  `json:"name"`
	State       string  `json:"state"`
	IDChecklist string  `json:"idChecklist,omitempty"`
	Pos         float64 `json:"pos,omitempty"`
}

// CheckItemState represents a CheckItem when it appears in CheckItemStates on a Card.
type CheckItemState struct {
	IDCheckItem string `json:"idCheckItem"`
	State       string `json:"state"`
}
<|endoftext|>


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

package chk

import (
	"fmt"
	"math"
	"math/cmplx"
	"runtime"
	"testing"
)

// PrintTitle returns the Test Title
func PrintTitle(title string) {
	if Verbose {
		fmt.Printf("\n=== %s =================\n", title)
		return
	}
	fmt.Printf("   . . . testing . . .   %s\n", title)
}

// PrintOk prints "OK" in green (if ColorsOn==true)
func PrintOk(msg string, prm ...interface{}) {
	if Verbose {
		fmt.Printf(msg, prm...)
		if ColorsOn {
			fmt.Println(" OK")
			return
		}
		fmt.Println(" OK")
	}
}

// TstFail calls tst.Errorf() with msg and parameters.
// It also prints "FAIL" in red (if ColorsOn==true)
func TstFail(tst *testing.T, msg string, prm ...interface{}) {
	tst.Errorf(msg, prm...)
	if Verbose {
		fmt.Printf(msg, prm...)
		if ColorsOn {
			fmt.Println(" FAIL")
			return
		}
		fmt.Println(" FAIL")
	}
}

// TstDiff tests difference between float64
func TstDiff(tst *testing.T, msg string, tol, a, b float64, showOK bool) (failed bool) {
	diff := math.Abs(a - b)
	if math.IsNaN(diff) || math.IsInf(diff, 0) {
		TstFail(tst, "%s NaN or Inf in a=%v b=%v", msg, a, b)
		return true
	}
	if diff > tol {
		TstFail(tst, "%s %v != %v |diff| = %g", msg, a, b, diff)
		return true
	}
	if showOK {
		PrintOk(msg)
	}
	return
}

// TestDiffC tests difference between complex128.
// It also prints "FAIL" or "OK"
func TestDiffC(tst *testing.T, msg string, tol float64, a, b complex128, showOK bool) (failed bool) {
	diff := cmplx.Abs(a - b)
	if math.IsNaN(diff) || math.IsInf(diff, 0) {
		TstFail(tst, "%s NaN or Inf in a=%v b=%v", msg, a, b)
		return true
	}
	if diff > tol {
		TstFail(tst, "%s |diff| = %g", msg, diff)
		return true
	}
	if showOK {
		PrintOk(msg)
	}
	return
}

// PrintAnaNum formats the output of analytical versus numerical comparisons
func PrintAnaNum(msg string, tol, ana, num float64, verbose bool) (e error) {
	diff := math.Abs(ana - num)
	if math.IsNaN(diff) || math.IsInf(diff, 0) {
		e = Err("%s NaN or Inf: %v", msg, diff)
		return
	}
	if verbose {
		clr := "" // green
		if diff > tol {
			clr = "" // red
		}
		fmt.Printf("%s %23v %23v %s%23v\n", msg, ana, num, clr, diff)
	}
	if diff > tol {
		e = Err("%s |diff| = %g", msg, diff)
	}
	return
}

// PrintAnaNumC formats the output of analytical versus numerical comparisons (complex version)
func PrintAnaNumC(msg string, tol float64, ana, num complex128, verbose bool) (e error) {
	diffR := math.Abs(real(ana) - real(num))
	diffC := math.Abs(imag(ana) - imag(num))
	if math.IsNaN(diffR) || math.IsInf(diffR, 0) {
		e = Err("%s (real part) NaN or Inf: %v", msg, diffR)
		return
	}
	if math.IsNaN(diffC) || math.IsInf(diffC, 0) {
		e = Err("%s (imag part) NaN or Inf: %v", msg, diffC)
		return
	}
	if verbose {
		clrR := "" // green
		clrC := "" // green
		if diffR > tol {
			clrR = "" // red
		}
		if diffC > tol {
			clrC = "" // red
		}
		f := "%" + fmt.Sprintf("%d", len(msg)) + "s"
		fmt.Printf(f+" %23v  %23v  %s%23v\n", msg, real(ana), real(num), clrR, diffR)
		fmt.Printf(f+" %23vi %23vi %s%23v\n", "", imag(ana), imag(num), clrC, diffC)
	}
	if diffR > tol || diffC > tol {
		e = Err("%s |diffR| = %g  |diffC| = %g", msg, diffR, diffC)
	}
	return
}

// CallerInfo returns the file and line positions where an error occurred
//  idx -- use idx=2 to get the caller of Panic
func CallerInfo(idx int) {
	pc, file, line, ok := runtime.Caller(idx)
	if !ok {
		file, line = "?", 0
	}
	var fname string
	f := runtime.FuncForPC(pc)
	if f != nil {
		fname = f.Name()
	}
	if Verbose {
		fmt.Printf("file = %s:%d\n", file, line)
		fmt.Printf("func = %s\n", fname)
	}
}
<commit_msg>Fix handling of colors flag in chk<commit_after>// Copyright 2016 The Gosl Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package chk

import (
	"fmt"
	"math"
	"math/cmplx"
	"runtime"
	"testing"
)

// PrintTitle returns the Test Title
func PrintTitle(title string) {
	if Verbose {
		fmt.Printf("\n=== %s =================\n", title)
		return
	}
	fmt.Printf("   . . . testing . . .   %s\n", title)
}

// PrintOk prints "OK" in green (if ColorsOn==true)
func PrintOk(msg string, prm ...interface{}) {
	if Verbose {
		fmt.Printf(msg, prm...)
		if ColorsOn {
			fmt.Println(" OK")
			return
		}
		fmt.Println(" OK")
	}
}

// TstFail calls tst.Errorf() with msg and parameters.
// It also prints "FAIL" in red (if ColorsOn==true)
func TstFail(tst *testing.T, msg string, prm ...interface{}) {
	tst.Errorf(msg, prm...)
	if Verbose {
		fmt.Printf(msg, prm...)
		if ColorsOn {
			fmt.Println(" FAIL")
			return
		}
		fmt.Println(" FAIL")
	}
}

// TstDiff tests difference between float64
func TstDiff(tst *testing.T, msg string, tol, a, b float64, showOK bool) (failed bool) {
	diff := math.Abs(a - b)
	if math.IsNaN(diff) || math.IsInf(diff, 0) {
		TstFail(tst, "%s NaN or Inf in a=%v b=%v", msg, a, b)
		return true
	}
	if diff > tol {
		TstFail(tst, "%s %v != %v |diff| = %g", msg, a, b, diff)
		return true
	}
	if showOK {
		PrintOk(msg)
	}
	return
}

// TestDiffC tests difference between complex128.
// It also prints "FAIL" or "OK"
func TestDiffC(tst *testing.T, msg string, tol float64, a, b complex128, showOK bool) (failed bool) {
	diff := cmplx.Abs(a - b)
	if math.IsNaN(diff) || math.IsInf(diff, 0) {
		TstFail(tst, "%s NaN or Inf in a=%v b=%v", msg, a, b)
		return true
	}
	if diff > tol {
		TstFail(tst, "%s |diff| = %g", msg, diff)
		return true
	}
	if showOK {
		PrintOk(msg)
	}
	return
}

// PrintAnaNum formats the output of analytical versus numerical comparisons
func PrintAnaNum(msg string, tol, ana, num float64, verbose bool) (e error) {
	diff := math.Abs(ana - num)
	if math.IsNaN(diff) || math.IsInf(diff, 0) {
		if ColorsOn {
			e = Err("%s NaN or Inf: %v", msg, diff)
		} else {
			e = Err("%s NaN or Inf: %v", msg, diff)
		}
		return
	}
	if verbose {
		if ColorsOn {
			clr := "" // green
			if diff > tol {
				clr = "" // red
			}
			fmt.Printf("%s %23v %23v %s%23v\n", msg, ana, num, clr, diff)
		} else {
			fmt.Printf("%s %23v %23v %23v\n", msg, ana, num, diff)
		}
	}
	if diff > tol {
		if ColorsOn {
			e = Err("%s |diff| = %g", msg, diff)
		} else {
			e = Err("%s |diff| = %g", msg, diff)
		}
	}
	return
}

// PrintAnaNumC formats the output of analytical versus numerical comparisons (complex version)
func PrintAnaNumC(msg string, tol float64, ana, num complex128, verbose bool) (e error) {
	diffR := math.Abs(real(ana) - real(num))
	diffC := math.Abs(imag(ana) - imag(num))
	if math.IsNaN(diffR) || math.IsInf(diffR, 0) {
		e = Err("%s (real part) NaN or Inf: %v", msg, diffR)
		return
	}
	if math.IsNaN(diffC) || math.IsInf(diffC, 0) {
		e = Err("%s (imag part) NaN or Inf: %v", msg, diffC)
		return
	}
	if verbose {
		clrR := "" // green
		clrC := "" // green
		if diffR > tol {
			clrR = "" // red
		}
		if diffC > tol {
			clrC = "" // red
		}
		f := "%" + fmt.Sprintf("%d", len(msg)) + "s"
		fmt.Printf(f+" %23v  %23v  %s%23v\n", msg, real(ana), real(num), clrR, diffR)
		fmt.Printf(f+" %23vi %23vi %s%23v\n", "", imag(ana), imag(num), clrC, diffC)
	}
	if diffR > tol || diffC > tol {
		e = Err("%s |diffR| = %g  |diffC| = %g", msg, diffR, diffC)
	}
	return
}

// CallerInfo returns the file and line positions where an error occurred
//  idx -- use idx=2 to get the caller of Panic
func CallerInfo(idx int) {
	pc, file, line, ok := runtime.Caller(idx)
	if !ok {
		file, line = "?", 0
	}
	var fname string
	f := runtime.FuncForPC(pc)
	if f != nil {
		fname = f.Name()
	}
	if Verbose {
		fmt.Printf("file = %s:%d\n", file, line)
		fmt.Printf("func = %s\n", fname)
	}
}
<|endoftext|>


<commit_before>package cli

import (
	"github.com/spf13/cobra"
)

// Global else the nested folders dont work
var RootCmd = &cobra.Command{
    Use:   "proxmox-api-go",
    Short: "Application to configure Proxmox from the Api",
}

func init() {
	RootCmd.PersistentFlags().BoolP("insecure", "i", false, "TLS insecure mode")
	RootCmd.PersistentFlags().BoolP("debug", "d", false, "debug mode")
	RootCmd.PersistentFlags().IntP("timeout", "t", 300, "api task timeout in seconds")
	RootCmd.PersistentFlags().StringP("file", "f", "", "file to get the config from")
	RootCmd.PersistentFlags().StringP("proxyurl", "p", "", "proxy url to connect to")
}

func Execute() {
    if err := RootCmd.Execute(); err != nil {
    	LogFatalError(err)
   	}
}<commit_msg>Copy NewClient logic from main to cobra<commit_after>package cli

import (
	"crypto/tls"
	"log"
	"os"
	"regexp"

	"github.com/Telmate/proxmox-api-go/proxmox"
	"github.com/spf13/cobra"
)

// Global else the nested folders dont work
var RootCmd = &cobra.Command{
    Use:   "proxmox-api-go",
    Short: "Application to configure Proxmox from the Api",
}

func init() {
	RootCmd.PersistentFlags().BoolP("insecure", "i", false, "TLS insecure mode")
	RootCmd.PersistentFlags().BoolP("debug", "d", false, "debug mode")
	RootCmd.PersistentFlags().IntP("timeout", "t", 300, "api task timeout in seconds")
	RootCmd.PersistentFlags().StringP("file", "f", "", "file to get the config from")
	RootCmd.PersistentFlags().StringP("proxyurl", "p", "", "proxy url to connect to")
}

func Execute() {
    if err := RootCmd.Execute(); err != nil {
    	LogFatalError(err)
   	}
}

func NewClient()(c *proxmox.Client) {
	insecure, _ := RootCmd.Flags().GetBool("insecure")
	timeout, _ := RootCmd.Flags().GetInt("timeout")
	proxyUrl, _ := RootCmd.Flags().GetString("proxyurl")

	tlsconf := &tls.Config{InsecureSkipVerify: true}
	if !insecure {
		tlsconf = nil
	}

	c, err := proxmox.NewClient(os.Getenv("PM_API_URL"), nil, tlsconf, proxyUrl, timeout)
	LogFatalError(err)
	if userRequiresAPIToken(os.Getenv("PM_USER")) {
		c.SetAPIToken(os.Getenv("PM_USER"), os.Getenv("PM_PASS"))
		// As test, get the version of the server
		_, err := c.GetVersion()
		if err != nil {
			log.Fatalf("login error: %s", err)
		}
	} else {
		err := c.Login(os.Getenv("PM_USER"), os.Getenv("PM_PASS"), os.Getenv("PM_OTP"))
		LogFatalError(err)
	}
	return
}

var rxUserRequiresToken = regexp.MustCompile("[a-z0-9]+@[a-z0-9]+![a-z0-9]+")

func userRequiresAPIToken(userID string) bool {
	return rxUserRequiresToken.MatchString(userID)
}
<|endoftext|>


<commit_before>package cli

import (
	"github.com/viant/endly/model/msg"
	"time"
)

type MessageGroup struct {
	message     *msg.Message
	startTime   *time.Time
	item        *msg.Styled
	enabled     bool
	pendingLine bool
}

//EnableIfMatched enable group if matched or first message, returns true if previous group matched
func (g *MessageGroup) EnableIfMatched(message *msg.Message) bool {
	if message.Header == nil {
		return false
	}

	if hasPrevious := g.message != nil; !hasPrevious {
		g.Set(message)
		return false
	}

	if g.message.Header.Equals(message.Header) && g.message.Tag.Equals(message.Tag)   {
		g.Set(message)
		return true
	}
	g.Reset()
	return false
}

func (g *MessageGroup) Set(message *msg.Message) {
	if g.startTime == nil {
		now := time.Now()
		g.startTime = &now
	}
	g.message = message
	g.enabled = true
}

func (g *MessageGroup) Reset() {
	g.message = nil
	g.enabled = false
	g.startTime = nil
	g.item = nil
}
<commit_msg>reformated<commit_after>package cli

import (
	"github.com/viant/endly/model/msg"
	"time"
)

type MessageGroup struct {
	message     *msg.Message
	startTime   *time.Time
	item        *msg.Styled
	enabled     bool
	pendingLine bool
}

//EnableIfMatched enable group if matched or first message, returns true if previous group matched
func (g *MessageGroup) EnableIfMatched(message *msg.Message) bool {
	if message.Header == nil {
		return false
	}

	if hasPrevious := g.message != nil; !hasPrevious {
		g.Set(message)
		return false
	}

	if g.message.Header.Equals(message.Header) && g.message.Tag.Equals(message.Tag) {
		g.Set(message)
		return true
	}
	g.Reset()
	return false
}

func (g *MessageGroup) Set(message *msg.Message) {
	if g.startTime == nil {
		now := time.Now()
		g.startTime = &now
	}
	g.message = message
	g.enabled = true
}

func (g *MessageGroup) Reset() {
	g.message = nil
	g.enabled = false
	g.startTime = nil
	g.item = nil
}
<|endoftext|>


<commit_before>/*
Copyright 2021 The Kubernetes Authors.

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

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

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

package controllers

import (
	"sync"

	k8smetrics "k8s.io/component-base/metrics"
	"k8s.io/component-base/metrics/legacyregistry"
)

var (
	once sync.Once
)

// ControllerMetrics includes all the metrics of the proxy server.
type ControllerMetrics struct {
	controllerInstanceCount *k8smetrics.GaugeVec
}

// newControllerMetrics create a new ControllerMetrics, configured with default metric names.
func NewControllerMetrics() *ControllerMetrics {
	controllerInstanceCount := k8smetrics.NewGaugeVec(
		&k8smetrics.GaugeOpts{
			Name:           "managed_controller_instances",
			Help:           "Instances of individual controllers currently running",
			StabilityLevel: k8smetrics.ALPHA,
		},
		[]string{"name", "manager"},
	)
	//legacyregistry.MustRegister(controllerInstanceCount)
	controllerMetrics := &ControllerMetrics{
		controllerInstanceCount: controllerInstanceCount,
	}
	once.Do(func() {
		controllerMetrics.Register()
	})
	return controllerMetrics
}

func (a *ControllerMetrics) Register() {
	legacyregistry.MustRegister(a.controllerInstanceCount)
}

// ControllerStarted sets the controllerInstanceCount to 1.
// These values use set instead of inc/dec to avoid accidentally double counting
// a controller that starts but fails to properly signal when it crashes.
func (a *ControllerMetrics) ControllerStarted(name string, manager string) {
	a.controllerInstanceCount.With(k8smetrics.Labels{"name": name, "manager": manager}).Set(float64(1))
}

// ControllerStopped sets the controllerInstanceCount to 0.
func (a *ControllerMetrics) ControllerStopped(name string, manager string) {
	a.controllerInstanceCount.With(k8smetrics.Labels{"name": name, "manager": manager}).Set(float64(0))
}
<commit_msg>updated help field to better indicate metric intent<commit_after>/*
Copyright 2021 The Kubernetes Authors.

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

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

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

package controllers

import (
	"sync"

	k8smetrics "k8s.io/component-base/metrics"
	"k8s.io/component-base/metrics/legacyregistry"
)

var (
	once sync.Once
)

// ControllerMetrics includes all the metrics of the proxy server.
type ControllerMetrics struct {
	controllerInstanceCount *k8smetrics.GaugeVec
}

// NewControllerMetrics create a new ControllerMetrics, configured with default metric names.
func NewControllerMetrics() *ControllerMetrics {
	controllerInstanceCount := k8smetrics.NewGaugeVec(
		&k8smetrics.GaugeOpts{
			Name:           "managed_controller_instances",
			Help:           "Indicates where instances of a controller are currently running",
			StabilityLevel: k8smetrics.ALPHA,
		},
		[]string{"name", "manager"},
	)
	controllerMetrics := &ControllerMetrics{
		controllerInstanceCount: controllerInstanceCount,
	}
	once.Do(func() {
		controllerMetrics.Register()
	})
	return controllerMetrics
}

func (a *ControllerMetrics) Register() {
	legacyregistry.MustRegister(a.controllerInstanceCount)
}

// ControllerStarted sets the controllerInstanceCount to 1.
// These values use set instead of inc/dec to avoid accidentally double counting
// a controller that starts but fails to properly signal when it crashes.
func (a *ControllerMetrics) ControllerStarted(name string, manager string) {
	a.controllerInstanceCount.With(k8smetrics.Labels{"name": name, "manager": manager}).Set(float64(1))
}

// ControllerStopped sets the controllerInstanceCount to 0.
func (a *ControllerMetrics) ControllerStopped(name string, manager string) {
	a.controllerInstanceCount.With(k8smetrics.Labels{"name": name, "manager": manager}).Set(float64(0))
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"github.com/codegangsta/cli"
	"github.com/keybase/go-libkb"
	"github.com/keybase/go-jsonw"
)

type CmdTrack struct {
	user      string
	assertion string
	track     bool
}

func (v *CmdTrack) ParseArgv(ctx *cli.Context) error {
	nargs := len(ctx.Args())
	var err error
	v.track = ctx.Bool("track-statement")
	if nargs == 1 {
		v.user = ctx.Args()[0]
	} else {
		err = fmt.Errorf("track takes one arg -- the user to track")
	}
	return err
}

func (v *CmdTrack) Run() error {

	u2, err := libkb.LoadUser(libkb.LoadUserArg{
		Name:             v.user,
		RequirePublicKey: true,
		Self:             false,
		LoadSecrets:      false,
		ForceReload:      false,
		SkipVerify:       false,
	})

	if err != nil {
		return err
	}

	me, err := libkb.LoadMe()

	if err != nil {
		return err
	}

	if me.Equal(*u2) {
		return fmt.Errorf("Cannot track yourself")
	}

	err = u2.Identify()
	if err != nil {
		G.Log.Warning("Some proofs failed")
	}

	var jw *jsonw.Wrapper
	jw, err = me.TrackingProofFor(u2)
	if err != nil {
		return err
	}
	fmt.Printf("%v\n", jw.MarshalPretty())

	return nil
}

func NewCmdTrack(cl *CommandLine) cli.Command {
	return cli.Command{
		Name:        "track",
		Usage:       "keybase track <username>",
		Description: "verify a user's authenticity and optionally track them",
		Flags: []cli.Flag{
			cli.StringFlag{
				Name:  "assert, a",
				Usage: "a boolean expression on this identity",
			},
		},
		Action: func(c *cli.Context) {
			cl.ChooseCommand(&CmdTrack{}, "track", c)
		},
	}
}

func (v *CmdTrack) UseConfig() bool   { return true }
func (v *CmdTrack) UseKeyring() bool  { return true }
func (v *CmdTrack) UseAPI() bool      { return true }
func (v *CmdTrack) UseTerminal() bool { return true }
<commit_msg>work ongoing<commit_after>package main

import (
	"fmt"
	"github.com/codegangsta/cli"
	"github.com/keybase/go-libkb"
	"github.com/keybase/go-jsonw"
)

type CmdTrack struct {
	user      string
	assertion string
	track     bool
}

func (v *CmdTrack) ParseArgv(ctx *cli.Context) error {
	nargs := len(ctx.Args())
	var err error
	v.track = ctx.Bool("track-statement")
	if nargs == 1 {
		v.user = ctx.Args()[0]
	} else {
		err = fmt.Errorf("track takes one arg -- the user to track")
	}
	return err
}

func (v *CmdTrack) Run() error {

	u2, err := libkb.LoadUser(libkb.LoadUserArg{
		Name:             v.user,
		RequirePublicKey: true,
		Self:             false,
		LoadSecrets:      false,
		ForceReload:      false,
		SkipVerify:       false,
	})

	if err != nil {
		return err
	}

	me, err := libkb.LoadMe()

	if err != nil {
		return err
	}

	if me.Equal(*u2) {
		return fmt.Errorf("Cannot track yourself")
	}

	err = u2.Identify()
	if err != nil {
		G.Log.Warning("Some proofs failed")
	}

	var jw *jsonw.Wrapper
	jw, err = me.TrackingProofFor(u2)
	if err != nil {
		return err
	}
	fmt.Printf("%v\n", jw.MarshalPretty())
	fmt.Printf("%v\n", u2.IdTable.MakeTrackSet())

	return nil
}

func NewCmdTrack(cl *CommandLine) cli.Command {
	return cli.Command{
		Name:        "track",
		Usage:       "keybase track <username>",
		Description: "verify a user's authenticity and optionally track them",
		Flags: []cli.Flag{
			cli.StringFlag{
				Name:  "assert, a",
				Usage: "a boolean expression on this identity",
			},
		},
		Action: func(c *cli.Context) {
			cl.ChooseCommand(&CmdTrack{}, "track", c)
		},
	}
}

func (v *CmdTrack) UseConfig() bool   { return true }
func (v *CmdTrack) UseKeyring() bool  { return true }
func (v *CmdTrack) UseAPI() bool      { return true }
func (v *CmdTrack) UseTerminal() bool { return true }
<|endoftext|>


<commit_before>package herd

import (
	"errors"
	"flag"
	"github.com/Symantec/Dominator/dom/images"
	"github.com/Symantec/Dominator/lib/constants"
	"github.com/Symantec/Dominator/lib/cpusharer"
	filegenclient "github.com/Symantec/Dominator/lib/filegen/client"
	"github.com/Symantec/Dominator/lib/log"
	"github.com/Symantec/Dominator/lib/objectserver"
	"github.com/Symantec/Dominator/lib/url"
	subproto "github.com/Symantec/Dominator/proto/sub"
	"github.com/Symantec/tricorder/go/tricorder"
	"os"
	"runtime"
	"time"
)

var (
	pollSlotsPerCPU = flag.Uint("pollSlotsPerCPU", 100,
		"Number of poll slots per CPU")
)

func newHerd(imageServerAddress string, objectServer objectserver.ObjectServer,
	metricsDir *tricorder.DirectorySpec, logger log.DebugLogger) *Herd {
	var herd Herd
	herd.imageManager = images.New(imageServerAddress, logger)
	herd.objectServer = objectServer
	herd.computedFilesManager = filegenclient.New(objectServer, logger)
	herd.logger = logger
	herd.configurationForSubs.ScanExclusionList =
		constants.ScanExcludeList
	herd.subsByName = make(map[string]*Sub)
	numPollSlots := uint(runtime.NumCPU()) * *pollSlotsPerCPU
	herd.pollSemaphore = make(chan struct{}, numPollSlots)
	herd.pushSemaphore = make(chan struct{}, runtime.NumCPU())
	herd.cpuSharer = cpusharer.NewFifoCpuSharer()
	herd.cpuSharer.SetGrabTimeout(time.Minute * 15)
	herd.currentScanStartTime = time.Now()
	herd.setupMetrics(metricsDir)
	return &herd
}

func (herd *Herd) clearSafetyShutoff(hostname string) error {
	herd.Lock()
	sub, ok := herd.subsByName[hostname]
	herd.Unlock()
	if !ok {
		return errors.New("unknown sub: " + hostname)
	}
	return sub.clearSafetyShutoff()
}

func (herd *Herd) configureSubs(configuration subproto.Configuration) error {
	herd.Lock()
	defer herd.Unlock()
	herd.configurationForSubs = configuration
	return nil
}

func (herd *Herd) disableUpdates(username, reason string) error {
	if reason == "" {
		return errors.New("error disabling updates: no reason given")
	}
	herd.updatesDisabledBy = username
	herd.updatesDisabledReason = reason
	herd.updatesDisabledTime = time.Now()
	return nil
}

func (herd *Herd) enableUpdates() error {
	herd.updatesDisabledReason = ""
	return nil
}

func (herd *Herd) getSubsConfiguration() subproto.Configuration {
	herd.RLockWithTimeout(time.Minute)
	defer herd.RUnlock()
	return herd.configurationForSubs
}

func (herd *Herd) lockWithTimeout(timeout time.Duration) {
	timeoutFunction(herd.Lock, timeout)
}

func (herd *Herd) pollNextSub() bool {
	if herd.nextSubToPoll >= uint(len(herd.subsByIndex)) {
		herd.nextSubToPoll = 0
		herd.previousScanDuration = time.Since(herd.currentScanStartTime)
		return true
	}
	if herd.nextSubToPoll == 0 {
		herd.currentScanStartTime = time.Now()
	}
	sub := herd.subsByIndex[herd.nextSubToPoll]
	herd.nextSubToPoll++
	if sub.busy { // Quick lockless check.
		return false
	}
	herd.cpuSharer.Go(func() {
		if !sub.tryMakeBusy() {
			return
		}
		sub.connectAndPoll()
		sub.makeUnbusy()
	})
	return false
}

func (herd *Herd) countSelectedSubs(selectFunc func(*Sub) bool) uint64 {
	herd.RLock()
	defer herd.RUnlock()
	if selectFunc == nil {
		return uint64(len(herd.subsByIndex))
	}
	count := 0
	for _, sub := range herd.subsByIndex {
		if selectFunc(sub) {
			count++
		}
	}
	return uint64(count)
}

func (herd *Herd) getSelectedSubs(selectFunc func(*Sub) bool) []*Sub {
	herd.RLock()
	defer herd.RUnlock()
	subs := make([]*Sub, 0, len(herd.subsByIndex))
	for _, sub := range herd.subsByIndex {
		if selectFunc == nil || selectFunc(sub) {
			subs = append(subs, sub)
		}
	}
	return subs
}

func (herd *Herd) getSub(name string) *Sub {
	herd.RLock()
	defer herd.RUnlock()
	return herd.subsByName[name]
}

func (herd *Herd) getReachableSelector(parsedQuery url.ParsedQuery) (
	func(*Sub) bool, error) {
	duration, err := parsedQuery.Last()
	if err != nil {
		return nil, err
	}
	return rDuration(duration).selector, nil
}

func (herd *Herd) rLockWithTimeout(timeout time.Duration) {
	timeoutFunction(herd.RLock, timeout)
}

func (herd *Herd) setDefaultImage(imageName string) error {
	if imageName == "" {
		herd.Lock()
		defer herd.Unlock()
		herd.defaultImageName = ""
		// Cancel blocking operations by affected subs.
		for _, sub := range herd.subsByIndex {
			if sub.mdb.RequiredImage != "" {
				sub.sendCancel()
				sub.status = statusImageUndefined
			}
		}
		return nil
	}
	if imageName == herd.defaultImageName {
		return nil
	}
	herd.Lock()
	herd.nextDefaultImageName = imageName
	herd.Unlock()
	doLockedCleanup := true
	defer func() {
		if doLockedCleanup {
			herd.Lock()
			herd.nextDefaultImageName = ""
			herd.Unlock()
		}
	}()
	img, err := herd.imageManager.Get(imageName, true)
	if err != nil {
		return err
	}
	if img == nil {
		return errors.New("unknown image: " + imageName)
	}
	if img.Filter != nil {
		return errors.New("only sparse images can be set as default")
	}
	if len(img.FileSystem.InodeTable) > 100 {
		return errors.New("cannot set default image with more than 100 inodes")
	}
	doLockedCleanup = false
	herd.Lock()
	defer herd.Unlock()
	herd.defaultImageName = imageName
	herd.nextDefaultImageName = ""
	for _, sub := range herd.subsByIndex {
		if sub.mdb.RequiredImage == "" {
			sub.sendCancel()
			if sub.status == statusSynced { // Synced to previous default image.
				sub.status = statusWaitingToPoll
			}
			if sub.status == statusImageUndefined {
				sub.status = statusWaitingToPoll
			}
		}
	}
	return nil
}

func timeoutFunction(f func(), timeout time.Duration) {
	if timeout < 0 {
		f()
		return
	}
	completionChannel := make(chan struct{})
	go func() {
		f()
		completionChannel <- struct{}{}
	}()
	timer := time.NewTimer(timeout)
	select {
	case <-completionChannel:
		if !timer.Stop() {
			<-timer.C
		}
		return
	case <-timer.C:
		os.Stderr.Write([]byte("lock timeout. Full stack trace follows:\n"))
		buf := make([]byte, 1024*1024)
		nBytes := runtime.Stack(buf, true)
		os.Stderr.Write(buf[0:nBytes])
		os.Stderr.Write([]byte("\n"))
		panic("timeout")
	}
}
<commit_msg>Improve dominator load shedding by waiting for idle CPU before adding work.<commit_after>package herd

import (
	"errors"
	"flag"
	"github.com/Symantec/Dominator/dom/images"
	"github.com/Symantec/Dominator/lib/constants"
	"github.com/Symantec/Dominator/lib/cpusharer"
	filegenclient "github.com/Symantec/Dominator/lib/filegen/client"
	"github.com/Symantec/Dominator/lib/log"
	"github.com/Symantec/Dominator/lib/objectserver"
	"github.com/Symantec/Dominator/lib/url"
	subproto "github.com/Symantec/Dominator/proto/sub"
	"github.com/Symantec/tricorder/go/tricorder"
	"os"
	"runtime"
	"time"
)

var (
	pollSlotsPerCPU = flag.Uint("pollSlotsPerCPU", 100,
		"Number of poll slots per CPU")
)

func newHerd(imageServerAddress string, objectServer objectserver.ObjectServer,
	metricsDir *tricorder.DirectorySpec, logger log.DebugLogger) *Herd {
	var herd Herd
	herd.imageManager = images.New(imageServerAddress, logger)
	herd.objectServer = objectServer
	herd.computedFilesManager = filegenclient.New(objectServer, logger)
	herd.logger = logger
	herd.configurationForSubs.ScanExclusionList =
		constants.ScanExcludeList
	herd.subsByName = make(map[string]*Sub)
	numPollSlots := uint(runtime.NumCPU()) * *pollSlotsPerCPU
	herd.pollSemaphore = make(chan struct{}, numPollSlots)
	herd.pushSemaphore = make(chan struct{}, runtime.NumCPU())
	herd.cpuSharer = cpusharer.NewFifoCpuSharer()
	herd.cpuSharer.SetGrabTimeout(time.Minute * 15)
	herd.currentScanStartTime = time.Now()
	herd.setupMetrics(metricsDir)
	return &herd
}

func (herd *Herd) clearSafetyShutoff(hostname string) error {
	herd.Lock()
	sub, ok := herd.subsByName[hostname]
	herd.Unlock()
	if !ok {
		return errors.New("unknown sub: " + hostname)
	}
	return sub.clearSafetyShutoff()
}

func (herd *Herd) configureSubs(configuration subproto.Configuration) error {
	herd.Lock()
	defer herd.Unlock()
	herd.configurationForSubs = configuration
	return nil
}

func (herd *Herd) disableUpdates(username, reason string) error {
	if reason == "" {
		return errors.New("error disabling updates: no reason given")
	}
	herd.updatesDisabledBy = username
	herd.updatesDisabledReason = reason
	herd.updatesDisabledTime = time.Now()
	return nil
}

func (herd *Herd) enableUpdates() error {
	herd.updatesDisabledReason = ""
	return nil
}

func (herd *Herd) getSubsConfiguration() subproto.Configuration {
	herd.RLockWithTimeout(time.Minute)
	defer herd.RUnlock()
	return herd.configurationForSubs
}

func (herd *Herd) lockWithTimeout(timeout time.Duration) {
	timeoutFunction(herd.Lock, timeout)
}

func (herd *Herd) pollNextSub() bool {
	if herd.nextSubToPoll >= uint(len(herd.subsByIndex)) {
		herd.nextSubToPoll = 0
		herd.previousScanDuration = time.Since(herd.currentScanStartTime)
		return true
	}
	if herd.nextSubToPoll == 0 {
		herd.currentScanStartTime = time.Now()
	}
	sub := herd.subsByIndex[herd.nextSubToPoll]
	herd.nextSubToPoll++
	if sub.busy { // Quick lockless check.
		return false
	}
	herd.cpuSharer.GoWhenIdle(0, -1, func() {
		if !sub.tryMakeBusy() {
			return
		}
		sub.connectAndPoll()
		sub.makeUnbusy()
	})
	return false
}

func (herd *Herd) countSelectedSubs(selectFunc func(*Sub) bool) uint64 {
	herd.RLock()
	defer herd.RUnlock()
	if selectFunc == nil {
		return uint64(len(herd.subsByIndex))
	}
	count := 0
	for _, sub := range herd.subsByIndex {
		if selectFunc(sub) {
			count++
		}
	}
	return uint64(count)
}

func (herd *Herd) getSelectedSubs(selectFunc func(*Sub) bool) []*Sub {
	herd.RLock()
	defer herd.RUnlock()
	subs := make([]*Sub, 0, len(herd.subsByIndex))
	for _, sub := range herd.subsByIndex {
		if selectFunc == nil || selectFunc(sub) {
			subs = append(subs, sub)
		}
	}
	return subs
}

func (herd *Herd) getSub(name string) *Sub {
	herd.RLock()
	defer herd.RUnlock()
	return herd.subsByName[name]
}

func (herd *Herd) getReachableSelector(parsedQuery url.ParsedQuery) (
	func(*Sub) bool, error) {
	duration, err := parsedQuery.Last()
	if err != nil {
		return nil, err
	}
	return rDuration(duration).selector, nil
}

func (herd *Herd) rLockWithTimeout(timeout time.Duration) {
	timeoutFunction(herd.RLock, timeout)
}

func (herd *Herd) setDefaultImage(imageName string) error {
	if imageName == "" {
		herd.Lock()
		defer herd.Unlock()
		herd.defaultImageName = ""
		// Cancel blocking operations by affected subs.
		for _, sub := range herd.subsByIndex {
			if sub.mdb.RequiredImage != "" {
				sub.sendCancel()
				sub.status = statusImageUndefined
			}
		}
		return nil
	}
	if imageName == herd.defaultImageName {
		return nil
	}
	herd.Lock()
	herd.nextDefaultImageName = imageName
	herd.Unlock()
	doLockedCleanup := true
	defer func() {
		if doLockedCleanup {
			herd.Lock()
			herd.nextDefaultImageName = ""
			herd.Unlock()
		}
	}()
	img, err := herd.imageManager.Get(imageName, true)
	if err != nil {
		return err
	}
	if img == nil {
		return errors.New("unknown image: " + imageName)
	}
	if img.Filter != nil {
		return errors.New("only sparse images can be set as default")
	}
	if len(img.FileSystem.InodeTable) > 100 {
		return errors.New("cannot set default image with more than 100 inodes")
	}
	doLockedCleanup = false
	herd.Lock()
	defer herd.Unlock()
	herd.defaultImageName = imageName
	herd.nextDefaultImageName = ""
	for _, sub := range herd.subsByIndex {
		if sub.mdb.RequiredImage == "" {
			sub.sendCancel()
			if sub.status == statusSynced { // Synced to previous default image.
				sub.status = statusWaitingToPoll
			}
			if sub.status == statusImageUndefined {
				sub.status = statusWaitingToPoll
			}
		}
	}
	return nil
}

func timeoutFunction(f func(), timeout time.Duration) {
	if timeout < 0 {
		f()
		return
	}
	completionChannel := make(chan struct{})
	go func() {
		f()
		completionChannel <- struct{}{}
	}()
	timer := time.NewTimer(timeout)
	select {
	case <-completionChannel:
		if !timer.Stop() {
			<-timer.C
		}
		return
	case <-timer.C:
		os.Stderr.Write([]byte("lock timeout. Full stack trace follows:\n"))
		buf := make([]byte, 1024*1024)
		nBytes := runtime.Stack(buf, true)
		os.Stderr.Write(buf[0:nBytes])
		os.Stderr.Write([]byte("\n"))
		panic("timeout")
	}
}
<|endoftext|>


<commit_before>package driver

import (
	"fmt"
)

type Driver interface {
	Name() string
	Type(string) string
	Types() map[string]string
	Path() string
	Appended() bool
	SetFuncs() // sets templates funcs
	ExecuteDatabase(interface{}) ([]byte, error)
	ExecuteQuery(interface{}) ([]byte, error)
	ExecuteModel(interface{}) ([]byte, error)
	ExecuteTable(interface{}) ([]byte, error)
	ExecuteSlice(interface{}) ([]byte, error)
	ExecuteCallbacks(interface{}) ([]byte, error)
}

var drivers map[string]Driver = map[string]Driver{}

func Register(d Driver) {
	if d == nil {
		return
	}
	drivers[d.Name()] = d
}

func Get(name string) (Driver, error) {
	d, ok := drivers[name]
	if !ok {
		return nil, fmt.Errorf("could not find '%s' driver", name)
	}
	return d, nil
}
<commit_msg>Driver almost done<commit_after>package driver

import (
	"fmt"
	"io"
	"text/template"
)

type Driver interface {
	Name() string
	Type(string) string
	Types() map[string]string
	SetFuncs(template.FuncMap) // sets templates funcs
	ExecuteDatabase(io.Writer, interface{}) error
	ExecuteQuery(io.Writer, interface{}) error
	ExecuteModel(io.Writer, interface{}) error
	ExecuteTable(io.Writer, interface{}) error
	ExecuteSlice(io.Writer, interface{}) error
	ExecuteCallbacks(io.Writer, interface{}) error
	GenerateQuery() bool
	GenerateTable() bool
	GenerateDatabase() bool
	GenerateModel() bool
	GenerateSlice() bool
	GenerateCallbacks() bool
}

type BaseDriver struct {
	name      string
	files     []string
	types     map[string]string
	generate  map[string]bool
	templates *template.Template
}

func (d *BaseDriver) Name() string {
	return d.name
}

func (d *BaseDriver) Type(t string) string {
	return d.types[t]
}

func (d *BaseDriver) Types() map[string]string {
	return d.types
}

func (d *BaseDriver) Appended() bool {
	return true
}

func (d *BaseDriver) SetFuncs(f template.FuncMap) { // sets templates funcs
	d.templates = d.templates.Funcs(f)
}

func (d *BaseDriver) Parse() { // sets templates funcs
	d.templates.ParseFiles(d.files...)
}

func (d *BaseDriver) ExecuteDatabase(w io.Writer, data interface{}) error {
	return d.templates.ExecuteTemplate(w, "database", data)
}

func (d *BaseDriver) ExecuteModel(w io.Writer, data interface{}) error {
	return d.templates.ExecuteTemplate(w, "model", data)
}

func (d *BaseDriver) ExecuteQuery(w io.Writer, data interface{}) error {
	return d.templates.ExecuteTemplate(w, "query", data)
}

func (d *BaseDriver) ExecuteTable(w io.Writer, data interface{}) error {
	return d.templates.ExecuteTemplate(w, "table", data)
}

func (d *BaseDriver) ExecuteSlice(w io.Writer, data interface{}) error {
	return d.templates.ExecuteTemplate(w, "slice", data)
}

func (d *BaseDriver) ExecuteCallbacks(w io.Writer, data interface{}) error {
	return d.templates.ExecuteTemplate(w, "callbacks", data)
}

func (d *BaseDriver) GenerateDatabase() bool {
	return d.generate["database"]
}

func (d *BaseDriver) GenerateModel() bool {
	return d.generate["model"]
}

func (d *BaseDriver) GenerateQuery() bool {
	return d.generate["query"]
}

func (d *BaseDriver) GenerateTable() bool {
	return d.generate["table"]
}

func (d *BaseDriver) GenerateSlice() bool {
	return d.generate["slice"]
}

func (d *BaseDriver) GenerateCallbacks() bool {
	return d.generate["callbacks"]
}

var drivers map[string]Driver = map[string]Driver{}

func New(name string, types map[string]string, generate map[string]bool, files []string) BaseDriver {
	return BaseDriver{name, files, types, generate, template.New("")}
}

func Register(d Driver) {
	if d == nil {
		return
	}
	drivers[d.Name()] = d
}

func Get(name string) (Driver, error) {
	d, ok := drivers[name]
	if !ok {
		return nil, fmt.Errorf("could not find '%s' driver", name)
	}
	return d, nil
}
<|endoftext|>


<commit_before>package drivers

import (
	"fmt"

	"github.com/docker/machine/log"
	"github.com/docker/machine/ssh"
	"github.com/docker/machine/utils"
)

func RunSSHCommandFromDriver(d Driver, command string) (ssh.Output, error) {
	var output ssh.Output

	addr, err := d.GetSSHHostname()
	if err != nil {
		return output, err
	}

	port, err := d.GetSSHPort()
	if err != nil {
		return output, err
	}

	auth := &ssh.Auth{
		Keys: []string{d.GetSSHKeyPath()},
	}

	client, err := ssh.NewClient(d.GetSSHUsername(), addr, port, auth)
	if err != nil {
		return output, err
	}

	return client.Run(command)
}

func sshAvailableFunc(d Driver) func() bool {
	return func() bool {
		log.Debug("Getting to WaitForSSH function...")
		hostname, err := d.GetSSHHostname()
		if err != nil {
			log.Debugf("Error getting IP address waiting for SSH: %s", err)
			return false
		}
		port, err := d.GetSSHPort()
		if err != nil {
			log.Debugf("Error getting SSH port: %s", err)
			return false
		}
		if err := ssh.WaitForTCP(fmt.Sprintf("%s:%d", hostname, port)); err != nil {
			log.Debugf("Error waiting for TCP waiting for SSH: %s", err)
			return false
		}

		if _, err := RunSSHCommandFromDriver(d, "exit 0"); err != nil {
			log.Debugf("Error getting ssh command 'exit 0' : %s", err)
			return false
		}
		return true
	}
}

func WaitForSSH(d Driver) error {
	if err := utils.WaitFor(sshAvailableFunc(d)); err != nil {
		return fmt.Errorf("Too many retries.  Last error: %s", err)
	}
	return nil
}
<commit_msg>Log ssh command output to Debug<commit_after>package drivers

import (
	"fmt"

	"github.com/docker/machine/log"
	"github.com/docker/machine/ssh"
	"github.com/docker/machine/utils"
)

func RunSSHCommandFromDriver(d Driver, command string) (ssh.Output, error) {
	var output ssh.Output

	addr, err := d.GetSSHHostname()
	if err != nil {
		return output, err
	}

	port, err := d.GetSSHPort()
	if err != nil {
		return output, err
	}

	auth := &ssh.Auth{
		Keys: []string{d.GetSSHKeyPath()},
	}

	client, err := ssh.NewClient(d.GetSSHUsername(), addr, port, auth)
	if err != nil {
		return output, err
	}

	output, err = client.Run(command)
	log.Debug(fmt.Sprintf("SSH cmd err, output: %v: %s", err, output))
	return output, err
}

func sshAvailableFunc(d Driver) func() bool {
	return func() bool {
		log.Debug("Getting to WaitForSSH function...")
		hostname, err := d.GetSSHHostname()
		if err != nil {
			log.Debugf("Error getting IP address waiting for SSH: %s", err)
			return false
		}
		port, err := d.GetSSHPort()
		if err != nil {
			log.Debugf("Error getting SSH port: %s", err)
			return false
		}
		if err := ssh.WaitForTCP(fmt.Sprintf("%s:%d", hostname, port)); err != nil {
			log.Debugf("Error waiting for TCP waiting for SSH: %s", err)
			return false
		}

		if _, err := RunSSHCommandFromDriver(d, "exit 0"); err != nil {
			log.Debugf("Error getting ssh command 'exit 0' : %s", err)
			return false
		}
		return true
	}
}

func WaitForSSH(d Driver) error {
	if err := utils.WaitFor(sshAvailableFunc(d)); err != nil {
		return fmt.Errorf("Too many retries.  Last error: %s", err)
	}
	return nil
}
<|endoftext|>


<commit_before>package command

import (
	"flag"
	"fmt"
	"io"
	"os"
	"sort"
	"strings"
	"text/tabwriter"
	"time"

	log "github.com/Sirupsen/logrus"
	units "github.com/docker/go-units"

	"github.com/NetSys/quilt/api/client"
	"github.com/NetSys/quilt/api/client/getter"
	"github.com/NetSys/quilt/db"
)

// Container contains the options for querying containers.
type Container struct {
	common       *commonFlags
	clientGetter client.Getter
}

// NewContainerCommand creates a new Container command instance.
func NewContainerCommand() *Container {
	return &Container{
		clientGetter: getter.New(),
		common:       &commonFlags{},
	}
}

// InstallFlags sets up parsing for command line flags
func (cCmd *Container) InstallFlags(flags *flag.FlagSet) {
	cCmd.common.InstallFlags(flags)
	flags.Usage = func() {
		fmt.Println("usage: quilt container [-H=<daemon_host>]")
		fmt.Println("`container` displays the status of quilt-managed " +
			"Docker containers.")

		flags.PrintDefaults()
	}
}

// Parse parses the command line arguments for the container command.
func (cCmd *Container) Parse(args []string) error {
	return nil
}

// Run retrieves and prints the requested containers.
func (cCmd *Container) Run() int {
	localClient, err := cCmd.clientGetter.Client(cCmd.common.host)
	if err != nil {
		log.Error(err)
		return 1
	}
	defer localClient.Close()

	c, err := cCmd.clientGetter.LeaderClient(localClient)
	if err != nil {
		log.WithError(err).Error("Error connecting to leader.")
		return 1
	}
	defer c.Close()

	containers, err := c.QueryContainers()
	if err != nil {
		log.WithError(err).Error("Unable to query containers.")
		return 1
	}

	connections, err := c.QueryConnections()
	if err != nil {
		log.WithError(err).Error("Unable to query connections.")
		return 1
	}

	machines, err := localClient.QueryMachines()
	if err != nil {
		log.WithError(err).Error("Unable to query machines")
		return 1
	}

	writeContainers(os.Stdout, containers, machines, connections)
	return 0
}

func writeContainers(fd io.Writer, containers []db.Container, machines []db.Machine,
	connections []db.Connection) {
	w := tabwriter.NewWriter(fd, 0, 0, 4, ' ', 0)
	defer w.Flush()
	fmt.Fprintln(w, "ID\tMACHINE\tCONTAINER\tLABELS\tSTATUS\tCREATED\tPUBLIC IP")

	labelPublicPortMap := map[string]string{}
	for _, c := range connections {
		if c.From != "public" {
			continue
		}

		if c.MinPort == c.MaxPort {
			labelPublicPortMap[c.To] = fmt.Sprintf("%d", c.MinPort)
		} else {
			labelPublicPortMap[c.To] = fmt.Sprintf(
				"%d-%d", c.MinPort, c.MaxPort)
		}
	}

	ipIDMap := map[string]int{}
	idMachineMap := map[int]db.Machine{}
	for _, m := range machines {
		ipIDMap[m.PrivateIP] = m.ID
		idMachineMap[m.ID] = m
	}

	machineDBC := map[int][]db.Container{}
	for _, dbc := range containers {
		id := ipIDMap[dbc.Minion]
		machineDBC[id] = append(machineDBC[id], dbc)
	}

	var machineIDs []int
	for key := range machineDBC {
		machineIDs = append(machineIDs, key)
	}
	sort.Ints(machineIDs)

	for i, machineID := range machineIDs {
		if i > 0 {
			// Insert a blank line between each machine.
			// Need to print tabs in a blank line; otherwise, spacing will
			// change in subsequent lines.
			fmt.Fprintf(w, "\t\t\t\t\t\t\n")
		}

		dbcs := machineDBC[machineID]
		sort.Sort(db.ContainerSlice(dbcs))
		for _, dbc := range dbcs {
			publicPorts := []string{}
			for _, label := range dbc.Labels {
				if p, ok := labelPublicPortMap[label]; ok {
					publicPorts = append(publicPorts, p)
				}
			}

			machine := machineStr(machineID)
			container := containerStr(dbc.Image, dbc.Command)
			labels := strings.Join(dbc.Labels, ", ")
			status := dbc.Status
			if dbc.Status == "" && dbc.Minion != "" {
				status = "scheduled"
			}
			created := ""
			if !dbc.Created.IsZero() {
				createdTime := dbc.Created.Local()
				duration := units.HumanDuration(time.Since(createdTime))
				created = fmt.Sprintf("%s ago", duration)
			}

			publicIP := publicIPStr(idMachineMap[machineID].PublicIP,
				publicPorts)

			fmt.Fprintf(w, "%v\t%v\t%v\t%v\t%v\t%v\t%v\n",
				dbc.StitchID, machine, container, labels, status,
				created, publicIP)
		}
	}
}

func machineStr(machineID int) string {
	if machineID == 0 {
		return ""
	}
	return fmt.Sprintf("Machine-%d", machineID)
}
func containerStr(image string, args []string) string {
	if image == "" {
		return ""
	}
	return fmt.Sprintf("%s %s", image, strings.Join(args, " "))
}

func publicIPStr(hostPublicIP string, publicPorts []string) string {
	if hostPublicIP == "" || len(publicPorts) == 0 {
		return ""
	}

	if len(publicPorts) == 1 {
		return fmt.Sprintf("%s:%s", hostPublicIP, publicPorts[0])
	}

	return fmt.Sprintf("%s:[%s]", hostPublicIP, strings.Join(publicPorts, ","))
}
<commit_msg>quiltctl: Print an abbreviated container id in `quilt ps`<commit_after>package command

import (
	"flag"
	"fmt"
	"io"
	"os"
	"sort"
	"strings"
	"text/tabwriter"
	"time"

	log "github.com/Sirupsen/logrus"
	units "github.com/docker/go-units"

	"github.com/NetSys/quilt/api/client"
	"github.com/NetSys/quilt/api/client/getter"
	"github.com/NetSys/quilt/db"
	"github.com/NetSys/quilt/util"
)

// Container contains the options for querying containers.
type Container struct {
	common       *commonFlags
	clientGetter client.Getter
}

// NewContainerCommand creates a new Container command instance.
func NewContainerCommand() *Container {
	return &Container{
		clientGetter: getter.New(),
		common:       &commonFlags{},
	}
}

// InstallFlags sets up parsing for command line flags
func (cCmd *Container) InstallFlags(flags *flag.FlagSet) {
	cCmd.common.InstallFlags(flags)
	flags.Usage = func() {
		fmt.Println("usage: quilt container [-H=<daemon_host>]")
		fmt.Println("`container` displays the status of quilt-managed " +
			"Docker containers.")

		flags.PrintDefaults()
	}
}

// Parse parses the command line arguments for the container command.
func (cCmd *Container) Parse(args []string) error {
	return nil
}

// Run retrieves and prints the requested containers.
func (cCmd *Container) Run() int {
	localClient, err := cCmd.clientGetter.Client(cCmd.common.host)
	if err != nil {
		log.Error(err)
		return 1
	}
	defer localClient.Close()

	c, err := cCmd.clientGetter.LeaderClient(localClient)
	if err != nil {
		log.WithError(err).Error("Error connecting to leader.")
		return 1
	}
	defer c.Close()

	containers, err := c.QueryContainers()
	if err != nil {
		log.WithError(err).Error("Unable to query containers.")
		return 1
	}

	connections, err := c.QueryConnections()
	if err != nil {
		log.WithError(err).Error("Unable to query connections.")
		return 1
	}

	machines, err := localClient.QueryMachines()
	if err != nil {
		log.WithError(err).Error("Unable to query machines")
		return 1
	}

	writeContainers(os.Stdout, containers, machines, connections)
	return 0
}

func writeContainers(fd io.Writer, containers []db.Container, machines []db.Machine,
	connections []db.Connection) {
	w := tabwriter.NewWriter(fd, 0, 0, 4, ' ', 0)
	defer w.Flush()
	fmt.Fprintln(w, "ID\tMACHINE\tCONTAINER\tLABELS\tSTATUS\tCREATED\tPUBLIC IP")

	labelPublicPortMap := map[string]string{}
	for _, c := range connections {
		if c.From != "public" {
			continue
		}

		if c.MinPort == c.MaxPort {
			labelPublicPortMap[c.To] = fmt.Sprintf("%d", c.MinPort)
		} else {
			labelPublicPortMap[c.To] = fmt.Sprintf(
				"%d-%d", c.MinPort, c.MaxPort)
		}
	}

	ipIDMap := map[string]int{}
	idMachineMap := map[int]db.Machine{}
	for _, m := range machines {
		ipIDMap[m.PrivateIP] = m.ID
		idMachineMap[m.ID] = m
	}

	machineDBC := map[int][]db.Container{}
	for _, dbc := range containers {
		id := ipIDMap[dbc.Minion]
		machineDBC[id] = append(machineDBC[id], dbc)
	}

	var machineIDs []int
	for key := range machineDBC {
		machineIDs = append(machineIDs, key)
	}
	sort.Ints(machineIDs)

	for i, machineID := range machineIDs {
		if i > 0 {
			// Insert a blank line between each machine.
			// Need to print tabs in a blank line; otherwise, spacing will
			// change in subsequent lines.
			fmt.Fprintf(w, "\t\t\t\t\t\t\n")
		}

		dbcs := machineDBC[machineID]
		sort.Sort(db.ContainerSlice(dbcs))
		for _, dbc := range dbcs {
			publicPorts := []string{}
			for _, label := range dbc.Labels {
				if p, ok := labelPublicPortMap[label]; ok {
					publicPorts = append(publicPorts, p)
				}
			}

			machine := machineStr(machineID)
			container := containerStr(dbc.Image, dbc.Command)
			labels := strings.Join(dbc.Labels, ", ")
			status := dbc.Status
			if dbc.Status == "" && dbc.Minion != "" {
				status = "scheduled"
			}
			created := ""
			if !dbc.Created.IsZero() {
				createdTime := dbc.Created.Local()
				duration := units.HumanDuration(time.Since(createdTime))
				created = fmt.Sprintf("%s ago", duration)
			}

			publicIP := publicIPStr(idMachineMap[machineID].PublicIP,
				publicPorts)

			fmt.Fprintf(w, "%v\t%v\t%v\t%v\t%v\t%v\t%v\n",
				util.ShortUUID(dbc.StitchID), machine, container, labels,
				status, created, publicIP)
		}
	}
}

func machineStr(machineID int) string {
	if machineID == 0 {
		return ""
	}
	return fmt.Sprintf("Machine-%d", machineID)
}
func containerStr(image string, args []string) string {
	if image == "" {
		return ""
	}
	return fmt.Sprintf("%s %s", image, strings.Join(args, " "))
}

func publicIPStr(hostPublicIP string, publicPorts []string) string {
	if hostPublicIP == "" || len(publicPorts) == 0 {
		return ""
	}

	if len(publicPorts) == 1 {
		return fmt.Sprintf("%s:%s", hostPublicIP, publicPorts[0])
	}

	return fmt.Sprintf("%s:[%s]", hostPublicIP, strings.Join(publicPorts, ","))
}
<|endoftext|>


<commit_before>package main

import (
	"log"
	"net/http"
	"io/ioutil"
	"net/url"
)

var gasUrl = "https://creativecommons.tankerkoenig.de/json/prices.php"
var transportUrl = "https://www.rmv.de/hapi/departureBoard"
var weatherUrl = "http://api.openweathermap.org/data/2.5/weather"
var forecastUrl = "http://api.openweathermap.org/data/2.5/forecast"

var client = &http.Client{}

func gasHandler(w http.ResponseWriter, r *http.Request) {
	request := newRequest(gasUrl, r.URL.Query())
	passResponseBody(request, w)
}

func newRequest(url string, params url.Values) (*http.Request) {
	request, err := http.NewRequest("GET", url, nil)
	if err != nil {
		log.Print(err)
	}
	request.Header.Add("Accept", "application/json")
	query := request.URL.Query()

	for key, value := range params {
		for i := range value {
			query.Add(key, value[i])
		}
	}
	request.URL.RawQuery = query.Encode()
	return request
}

func passResponseBody(request *http.Request, w http.ResponseWriter) {
	response, err := client.Do(request)
	if err != nil {
		w.WriteHeader(500) // Internal Server Error
		return
	}
	defer response.Body.Close()
	body, err := ioutil.ReadAll(response.Body)
	if err != nil {
		w.WriteHeader(500) // Internal Server Error
		return
	}
	// pass the status code
	w.WriteHeader(response.StatusCode)
	// pass the body (body should be a JSON file)
	w.Write(body)
}

func transportHandler(w http.ResponseWriter, r *http.Request) {
	request := newRequest(transportUrl, r.URL.Query())
	passResponseBody(request, w)
}

func weatherHandler(w http.ResponseWriter, r *http.Request) {
	request := newRequest(weatherUrl, r.URL.Query())
	passResponseBody(request, w)
}

func forecastHandler(w http.ResponseWriter, r *http.Request) {
	request := newRequest(forecastUrl, r.URL.Query())
	passResponseBody(request, w)
}

func main() {
	http.HandleFunc("/gas", gasHandler)
	http.HandleFunc("/transport", transportHandler)
	http.HandleFunc("/weather", weatherHandler)
	http.HandleFunc("/forecast", forecastHandler)
	log.Fatal(http.ListenAndServe(":8080", nil))
}
<commit_msg>simple status message<commit_after>package main

import (
	"log"
	"net/http"
	"io/ioutil"
	"net/url"
)

var gasUrl = "https://creativecommons.tankerkoenig.de/json/prices.php"
var transportUrl = "https://www.rmv.de/hapi/departureBoard"
var weatherUrl = "http://api.openweathermap.org/data/2.5/weather"
var forecastUrl = "http://api.openweathermap.org/data/2.5/forecast"

var client = &http.Client{}

func rootHandler(w http.ResponseWriter, r *http.Request) {
	w.Write([]byte("online"))
}

func gasHandler(w http.ResponseWriter, r *http.Request) {
	request := newRequest(gasUrl, r.URL.Query())
	passResponseBody(request, w)
}

func newRequest(url string, params url.Values) (*http.Request) {
	request, err := http.NewRequest("GET", url, nil)
	if err != nil {
		log.Print(err)
	}
	request.Header.Add("Accept", "application/json")
	query := request.URL.Query()

	for key, value := range params {
		for i := range value {
			query.Add(key, value[i])
		}
	}
	request.URL.RawQuery = query.Encode()
	return request
}

func passResponseBody(request *http.Request, w http.ResponseWriter) {
	response, err := client.Do(request)
	if err != nil {
		w.WriteHeader(500) // Internal Server Error
		return
	}
	defer response.Body.Close()
	body, err := ioutil.ReadAll(response.Body)
	if err != nil {
		w.WriteHeader(500) // Internal Server Error
		return
	}
	// pass the status code
	w.WriteHeader(response.StatusCode)
	// pass the body (body should be a JSON file)
	w.Write(body)
}

func transportHandler(w http.ResponseWriter, r *http.Request) {
	request := newRequest(transportUrl, r.URL.Query())
	passResponseBody(request, w)
}

func weatherHandler(w http.ResponseWriter, r *http.Request) {
	request := newRequest(weatherUrl, r.URL.Query())
	passResponseBody(request, w)
}

func forecastHandler(w http.ResponseWriter, r *http.Request) {
	request := newRequest(forecastUrl, r.URL.Query())
	passResponseBody(request, w)
}

func main() {
	http.HandleFunc("/", rootHandler)
	http.HandleFunc("/gas", gasHandler)
	http.HandleFunc("/transport", transportHandler)
	http.HandleFunc("/weather", weatherHandler)
	http.HandleFunc("/forecast", forecastHandler)
	log.Fatal(http.ListenAndServe(":8080", nil))
}
<|endoftext|>


<commit_before>package main

import (
	"encoding/json"
	"encoding/xml"
	"fmt"
	"io/ioutil"
	"net/http"

	"github.com/go-martini/martini"
)

var places = map[string]string{
	"blekinge":       "https://polisen.se/Halland/Aktuellt/RSS/Lokal-RSS---Handelser/Lokala-RSS-listor1/Handelser-RSS---Blekinge/?feed=rss",
	"dalarna":        "https://polisen.se/Halland/Aktuellt/RSS/Lokal-RSS---Handelser/Lokala-RSS-listor1/Handelser-RSS---Dalarna/?feed=rss",
	"gotland":        "https://polisen.se/Halland/Aktuellt/RSS/Lokal-RSS---Handelser/Lokala-RSS-listor1/Handelser-RSS---Gotland/?feed=rss",
	"gavleborg":      "https://polisen.se/Halland/Aktuellt/RSS/Lokal-RSS---Handelser/Lokala-RSS-listor1/Handelser-RSS---Gavleborg/?feed=rss",
	"halland":        "https://polisen.se/Halland/Aktuellt/RSS/Lokal-RSS---Handelser/Lokala-RSS-listor1/Handelser-RSS---Halland/?feed=rss",
	"jamtland":       "https://polisen.se/Halland/Aktuellt/RSS/Lokal-RSS---Handelser/Lokala-RSS-listor1/Handelser-RSS---Jamtland/?feed=rss",
	"jonkoping":      "https://polisen.se/Halland/Aktuellt/RSS/Lokal-RSS---Handelser/Lokala-RSS-listor1/Handelser-RSS---Jonkoping/?feed=rss",
	"kalmar":         "https://polisen.se/Halland/Aktuellt/RSS/Lokal-RSS---Handelser/Lokala-RSS-listor1/Handelser-RSS---Kalmar?feed=rss",
	"kronoberg":      "https://polisen.se/Halland/Aktuellt/RSS/Lokal-RSS---Handelser/Lokala-RSS-listor1/Handelser-RSS---Kronoberg?feed=rss",
	"norrbotten":     "https://polisen.se/Halland/Aktuellt/RSS/Lokal-RSS---Handelser/Lokala-RSS-listor1/Handelser-RSS---Norrbotten?feed=rss",
	"skane":          "https://polisen.se/Halland/Aktuellt/RSS/Lokal-RSS---Handelser/Lokala-RSS-listor1/Handelser-RSS---Skane?feed=rss",
	"stockholm":      "https://polisen.se/Stockholms_lan/Aktuellt/RSS/Lokal-RSS---Handelser/Lokala-RSS-listor1/Handelser-RSS---Stockholms-lan/?feed=rss",
	"sodermanland":   "https://polisen.se/Halland/Aktuellt/RSS/Lokal-RSS---Handelser/Lokala-RSS-listor1/Handelser-RSS---Sodermanland?feed=rss",
	"uppsala":        "https://polisen.se/Halland/Aktuellt/RSS/Lokal-RSS---Handelser/Lokala-RSS-listor1/Handelser-RSS---Uppsala?feed=rss",
	"varmland":       "https://polisen.se/Halland/Aktuellt/RSS/Lokal-RSS---Handelser/Lokala-RSS-listor1/Handelser-RSS---Varmland?feed=rss",
	"vasterbotten":   "https://polisen.se/Halland/Aktuellt/RSS/Lokal-RSS---Handelser/Lokala-RSS-listor1/Handelser-RSS---Vasterbotten?feed=rss",
	"vasternorrland": "https://polisen.se/Halland/Aktuellt/RSS/Lokal-RSS---Handelser/Lokala-RSS-listor1/Handelser-RSS---Vasternorrland?feed=rss",
	"vastmanland":    "https://polisen.se/Halland/Aktuellt/RSS/Lokal-RSS---Handelser/Lokala-RSS-listor1/Handelser-RSS---Vastmanland?feed=rss",
	"vastragotaland": "https://polisen.se/Halland/Aktuellt/RSS/Lokal-RSS---Handelser/Lokala-RSS-listor1/Handelser-RSS---Vastragotaland?feed=rss",
	"orebro":         "https://polisen.se/Halland/Aktuellt/RSS/Lokal-RSS---Handelser/Lokala-RSS-listor1/Handelser-RSS---Orebro?feed=rss",
	"ostergotland":   "https://polisen.se/Halland/Aktuellt/RSS/Lokal-RSS---Handelser/Lokala-RSS-listor1/Handelser-RSS---Ostergotland?feed=rss",
}

func main() {
	m := martini.Classic()

	m.Group("/", func(r martini.Router) {
		r.Get(":place", allEvents)
		r.Get(":place/(?P<number>10|[1-9])", singleEvent)
	})

	m.Run()

	// //http.Handle("/css/", http.StripPrefix("/css/", http.FileServer(http.Dir("./css")))) //To find css-files in the css-folder
	// http.ListenAndServe(":9090", nil)
}

func allEvents(res http.ResponseWriter, req *http.Request, params martini.Params) {
	place := params["place"]

	if isPlaceValid(place) {
		json := callExternalServicesAndCreateJson(place)
		res.Header().Add("Content-type", "application/json")
		res.Write([]byte(json))
	} else {
		status := http.StatusBadRequest
		res.WriteHeader(status) // http-status 400
		errorMessage := fmt.Sprintf("%v: %v \n\n\"%v\" is not a valid place", status, http.StatusText(status), place)
		res.Write([]byte(errorMessage))
	}
}

func singleEvent(params martini.Params) string {
	return params["number"]
}

func isPlaceValid(parameter string) bool {
	for place, _ := range places {
		if place == parameter {
			return true
		}
	}
	return false
}

func callExternalServicesAndCreateJson(place string) string {
	/*
		1. Get Police RSS XML
		2. Save each event as event-struct-array
		3. Fill "searchwords"-fields by using the filters
		4. Get google search results using "searchwords" - save coordinates as fields in struct
		5. Convert search result as JSON and return string
	*/

	policeRSSxml := callPoliceRSS(places[place])
	policeEvents := policeXMLtoStructs(policeRSSxml)
	// 3. Fill "searchwords"-fields by using the filters
	// 4. Get google search results using "searchwords" - save coordinates as fields in struct
	policeEventsAsJson := encodePoliceEventsToJSON(policeEvents)

	return string(policeEventsAsJson)
}

func callPoliceRSS(url string) []byte {
	httpResponse, _ := http.Get(url)
	xmlResponse, _ := ioutil.ReadAll(httpResponse.Body)

	defer httpResponse.Body.Close()

	return xmlResponse
}

func policeXMLtoStructs(policeRSSxml []byte) PoliceEvents {
	var policeEvents PoliceEvents
	xml.Unmarshal(policeRSSxml, &policeEvents)

	return policeEvents
}

func encodePoliceEventsToJSON(policeEvents PoliceEvents) []byte {
	policeEventsAsJson, _ := json.Marshal(policeEvents)

	return policeEventsAsJson
}

/* -- STRUCTS -- */

type PoliceEvents struct {
	Events []PoliceEvent `xml:"channel>item"`
}

type PoliceEvent struct {
	Title         string `xml:"title"`
	Link          string `xml:"link"`
	Description   string `xml:"description"`
	LocationWords []string
	Longitude     float32
	Latitude      float32
}

// func moviesearch(wr http.ResponseWriter, re *http.Request) {
// 	//1. lookup omdb-rate (first result only)
// 	//2. lookup rotten-rate (first result only)
// 	//3. create html-page
// 	//4. write html-page with wr

// 	moviename := re.URL.Query().Get("name")

// 	/*if moviename == "" {
// 		wr.Write([]byte("Please enter a valid movie name"))
// 		return
// 	}*/

// 	omovie := omdbquery(moviename)
// 	log.Printf("ImdbMovie: %s, score: %s", omovie.Movietitle, omovie.Imdbscore)

// 	rmovie := rottenquery(moviename)
// 	log.Printf("RottenMovie-score: %d", rmovie.Movies[0].Ratings.Rottenscore)

// 	combinedmoviedata := CombinedMovieData{omovie.Movietitle, omovie.Imdbscore, rmovie.Movies[0].Ratings.Rottenscore}

// 	movietemplate, _ := template.ParseFiles("name.html")
// 	movietemplate.Execute(wr, combinedmoviedata)
// 	//template.Must(template.ParseFiles("name.html")).Execute(wr, combinedmoviedata)

// }

// func omdbquery(moviename string) OmdbMovie {
// 	url := "http://www.omdbapi.com/?t=" + moviename + "&y&plot=short&r=json&tomatoes=true"

// 	omdbresponse, err := http.Get(url)
// 	if err != nil {
// 		log.Println("Error on http.Get: ", err)
// 		return OmdbMovie{}
// 	}

// 	defer omdbresponse.Body.Close()

// 	var omdbmovie OmdbMovie

// 	json.NewDecoder(omdbresponse.Body).Decode(&omdbmovie)

// 	return omdbmovie
// }

// func rottenquery(moviename string) RottenMovie {
// 	url := "http://api.rottentomatoes.com/api/public/v1.0/movies.json?apikey=***REMOVED***&q=" + moviename

// 	rottenresponse, err := http.Get(url)
// 	if err != nil {
// 		log.Println("Error on http.Get: ", err)
// 		return RottenMovie{}
// 	}

// 	defer rottenresponse.Body.Close()

// 	var rottenmovie RottenMovie
// 	json.NewDecoder(rottenresponse.Body).Decode(&rottenmovie)

// 	return rottenmovie
// }

// type OmdbMovie struct {
// 	Movietitle string `json:"Title"`
// 	Imdbscore  string `json:"imdbRating"`
// }

// type RottenMovie struct {
// 	Movies []struct {
// 		MovieTitle string `json:"title"`
// 		Ratings    struct {
// 			Rottenscore int `json:"critics_score"`
// 		} `json:"ratings"`
// 	} `json:"movies"`
// }

// type CombinedMovieData struct {
// 	Movietitle  string
// 	Imdbscore   string
// 	Rottenscore int
// }
<commit_msg>Added methods for finding the location search words and adding it to the policeEvents-objects, added URLifiedURL to each object as well<commit_after>package main

import (
	"encoding/json"
	"encoding/xml"
	"fmt"
	"io/ioutil"
	"net/http"
	"net/url"
	"poliskarta/filterdescription"
	"poliskarta/filtertitle"
	"strings"

	"github.com/go-martini/martini"
)

var places = map[string]string{
	"blekinge":       "https://polisen.se/Halland/Aktuellt/RSS/Lokal-RSS---Handelser/Lokala-RSS-listor1/Handelser-RSS---Blekinge/?feed=rss",
	"dalarna":        "https://polisen.se/Halland/Aktuellt/RSS/Lokal-RSS---Handelser/Lokala-RSS-listor1/Handelser-RSS---Dalarna/?feed=rss",
	"gotland":        "https://polisen.se/Halland/Aktuellt/RSS/Lokal-RSS---Handelser/Lokala-RSS-listor1/Handelser-RSS---Gotland/?feed=rss",
	"gavleborg":      "https://polisen.se/Halland/Aktuellt/RSS/Lokal-RSS---Handelser/Lokala-RSS-listor1/Handelser-RSS---Gavleborg/?feed=rss",
	"halland":        "https://polisen.se/Halland/Aktuellt/RSS/Lokal-RSS---Handelser/Lokala-RSS-listor1/Handelser-RSS---Halland/?feed=rss",
	"jamtland":       "https://polisen.se/Halland/Aktuellt/RSS/Lokal-RSS---Handelser/Lokala-RSS-listor1/Handelser-RSS---Jamtland/?feed=rss",
	"jonkoping":      "https://polisen.se/Halland/Aktuellt/RSS/Lokal-RSS---Handelser/Lokala-RSS-listor1/Handelser-RSS---Jonkoping/?feed=rss",
	"kalmar":         "https://polisen.se/Halland/Aktuellt/RSS/Lokal-RSS---Handelser/Lokala-RSS-listor1/Handelser-RSS---Kalmar?feed=rss",
	"kronoberg":      "https://polisen.se/Halland/Aktuellt/RSS/Lokal-RSS---Handelser/Lokala-RSS-listor1/Handelser-RSS---Kronoberg?feed=rss",
	"norrbotten":     "https://polisen.se/Halland/Aktuellt/RSS/Lokal-RSS---Handelser/Lokala-RSS-listor1/Handelser-RSS---Norrbotten?feed=rss",
	"skane":          "https://polisen.se/Halland/Aktuellt/RSS/Lokal-RSS---Handelser/Lokala-RSS-listor1/Handelser-RSS---Skane?feed=rss",
	"stockholm":      "https://polisen.se/Stockholms_lan/Aktuellt/RSS/Lokal-RSS---Handelser/Lokala-RSS-listor1/Handelser-RSS---Stockholms-lan/?feed=rss",
	"sodermanland":   "https://polisen.se/Halland/Aktuellt/RSS/Lokal-RSS---Handelser/Lokala-RSS-listor1/Handelser-RSS---Sodermanland?feed=rss",
	"uppsala":        "https://polisen.se/Halland/Aktuellt/RSS/Lokal-RSS---Handelser/Lokala-RSS-listor1/Handelser-RSS---Uppsala?feed=rss",
	"varmland":       "https://polisen.se/Halland/Aktuellt/RSS/Lokal-RSS---Handelser/Lokala-RSS-listor1/Handelser-RSS---Varmland?feed=rss",
	"vasterbotten":   "https://polisen.se/Halland/Aktuellt/RSS/Lokal-RSS---Handelser/Lokala-RSS-listor1/Handelser-RSS---Vasterbotten?feed=rss",
	"vasternorrland": "https://polisen.se/Halland/Aktuellt/RSS/Lokal-RSS---Handelser/Lokala-RSS-listor1/Handelser-RSS---Vasternorrland?feed=rss",
	"vastmanland":    "https://polisen.se/Halland/Aktuellt/RSS/Lokal-RSS---Handelser/Lokala-RSS-listor1/Handelser-RSS---Vastmanland?feed=rss",
	"vastragotaland": "https://polisen.se/Halland/Aktuellt/RSS/Lokal-RSS---Handelser/Lokala-RSS-listor1/Handelser-RSS---Vastragotaland?feed=rss",
	"orebro":         "https://polisen.se/Halland/Aktuellt/RSS/Lokal-RSS---Handelser/Lokala-RSS-listor1/Handelser-RSS---Orebro?feed=rss",
	"ostergotland":   "https://polisen.se/Halland/Aktuellt/RSS/Lokal-RSS---Handelser/Lokala-RSS-listor1/Handelser-RSS---Ostergotland?feed=rss",
}

func main() {
	m := martini.Classic()

	m.Group("/", func(r martini.Router) {
		r.Get(":place", allEvents)
		r.Get(":place/(?P<number>10|[1-9])", singleEvent)
	})

	m.Run()

	// //http.Handle("/css/", http.StripPrefix("/css/", http.FileServer(http.Dir("./css")))) //To find css-files in the css-folder
	// http.ListenAndServe(":9090", nil)
}

func allEvents(res http.ResponseWriter, req *http.Request, params martini.Params) {
	place := params["place"]

	if isPlaceValid(place) {
		json := callExternalServicesAndCreateJson(place)
		res.Header().Add("Content-type", "application/json; charset=utf-8")
		res.Write([]byte(json))
	} else {
		status := http.StatusBadRequest
		res.WriteHeader(status) // http-status 400
		errorMessage := fmt.Sprintf("%v: %v \n\n\"%v\" is not a valid place", status, http.StatusText(status), place)
		res.Write([]byte(errorMessage))
	}
}

func singleEvent(params martini.Params) string {
	return params["number"]
}

func isPlaceValid(parameter string) bool {
	for place, _ := range places {
		if place == parameter {
			return true
		}
	}
	return false
}

func callExternalServicesAndCreateJson(place string) string {
	/*
		1. Get Police RSS XML
		2. Save each event as event-struct-array
		3. Fill "searchwords"-fields by using the filters
		4. Get google search results using "searchwords" - save coordinates as fields in struct
		5. Convert search result as JSON and return string
	*/

	policeRSSxml := callPoliceRSS(places[place])
	policeEvents := policeXMLtoStructs(policeRSSxml)
	findAndFillLocationWords(&policeEvents)
	// 4. Get google search results using "searchwords" - save coordinates as fields in struct
	policeEventsAsJson := encodePoliceEventsToJSON(policeEvents)

	return string(policeEventsAsJson)
}

func callPoliceRSS(url string) []byte {
	httpResponse, _ := http.Get(url)
	xmlResponse, _ := ioutil.ReadAll(httpResponse.Body)

	defer httpResponse.Body.Close()

	return xmlResponse
}

func policeXMLtoStructs(policeRSSxml []byte) PoliceEvents {
	var policeEvents PoliceEvents
	xml.Unmarshal(policeRSSxml, &policeEvents)
	xml.Unmarshal(policeRSSxml, &policeEvents)

	return policeEvents
}

func encodePoliceEventsToJSON(policeEvents PoliceEvents) []byte {
	policeEventsAsJson, _ := json.Marshal(policeEvents)

	return policeEventsAsJson
}

/* -- STRUCTS -- */

type PoliceEvents struct {
	Events []PoliceEvent `xml:"channel>item"`
}

type PoliceEvent struct {
	Title            string `xml:"title"`
	Link             string `xml:"link"`
	Description      string `xml:"description"`
	HasLocation      bool
	LocationWords    []string
	URLifiedLocation string
	Longitude        float32
	Latitude         float32
}

func findAndFillLocationWords(policeEvents *PoliceEvents) {
	eventsCopy := *policeEvents

	for index, _ := range eventsCopy.Events {
		titleWords, err := filtertitle.FilterTitleWords(eventsCopy.Events[index].Title)
		fmt.Println("Titlewords: ", titleWords)

		if err != nil {
			eventsCopy.Events[index].HasLocation = false
		} else {
			eventsCopy.Events[index].HasLocation = true
			descriptionWords := filterdescription.FilterDescriptionWords(eventsCopy.Events[index].Description)
			fmt.Println("Descwords: ", descriptionWords)
			removeDuplicatesAndCombineLocationWords(titleWords, descriptionWords, &eventsCopy.Events[index].LocationWords)
			AddURLifiedURL(&eventsCopy.Events[index])
		}

	}

	fmt.Println("EventsCopy.Events", eventsCopy.Events[0].LocationWords)

	*policeEvents = eventsCopy
}

func AddURLifiedURL(policeEvent *PoliceEvent) {
	eventCopy := *policeEvent
	str := ""
	for _, word := range eventCopy.LocationWords {
		str += word + " "
	}
	str = url.QueryEscape(str)
	str = strings.TrimSuffix(str, "+")

	eventCopy.URLifiedLocation = str
	*policeEvent = eventCopy
}

func removeDuplicatesAndCombineLocationWords(titleWords []string, descriptionWords []string, locationWords *[]string) {
	location := []string{}

	for _, descWord := range descriptionWords {
		location = append(location, descWord)
	}

	wordAlreadyExists := false

	for _, titleWord := range titleWords {
		for _, locationWord := range location {
			if titleWord == locationWord {
				wordAlreadyExists = true
				break
			}
		}
		if !wordAlreadyExists {
			location = append(location, titleWord)
		}
	}

	*locationWords = location
}

// func moviesearch(wr http.ResponseWriter, re *http.Request) {
// 	//1. lookup omdb-rate (first result only)
// 	//2. lookup rotten-rate (first result only)
// 	//3. create html-page
// 	//4. write html-page with wr

// 	moviename := re.URL.Query().Get("name")

// 	/*if moviename == "" {
// 		wr.Write([]byte("Please enter a valid movie name"))
// 		return
// 	}*/

// 	omovie := omdbquery(moviename)
// 	log.Printf("ImdbMovie: %s, score: %s", omovie.Movietitle, omovie.Imdbscore)

// 	rmovie := rottenquery(moviename)
// 	log.Printf("RottenMovie-score: %d", rmovie.Movies[0].Ratings.Rottenscore)

// 	combinedmoviedata := CombinedMovieData{omovie.Movietitle, omovie.Imdbscore, rmovie.Movies[0].Ratings.Rottenscore}

// 	movietemplate, _ := template.ParseFiles("name.html")
// 	movietemplate.Execute(wr, combinedmoviedata)
// 	//template.Must(template.ParseFiles("name.html")).Execute(wr, combinedmoviedata)

// }

// func omdbquery(moviename string) OmdbMovie {
// 	url := "http://www.omdbapi.com/?t=" + moviename + "&y&plot=short&r=json&tomatoes=true"

// 	omdbresponse, err := http.Get(url)
// 	if err != nil {
// 		log.Println("Error on http.Get: ", err)
// 		return OmdbMovie{}
// 	}

// 	defer omdbresponse.Body.Close()

// 	var omdbmovie OmdbMovie

// 	json.NewDecoder(omdbresponse.Body).Decode(&omdbmovie)

// 	return omdbmovie
// }

// func rottenquery(moviename string) RottenMovie {
// 	url := "http://api.rottentomatoes.com/api/public/v1.0/movies.json?apikey=***REMOVED***&q=" + moviename

// 	rottenresponse, err := http.Get(url)
// 	if err != nil {
// 		log.Println("Error on http.Get: ", err)
// 		return RottenMovie{}
// 	}

// 	defer rottenresponse.Body.Close()

// 	var rottenmovie RottenMovie
// 	json.NewDecoder(rottenresponse.Body).Decode(&rottenmovie)

// 	return rottenmovie
// }

// type OmdbMovie struct {
// 	Movietitle string `json:"Title"`
// 	Imdbscore  string `json:"imdbRating"`
// }

// type RottenMovie struct {
// 	Movies []struct {
// 		MovieTitle string `json:"title"`
// 		Ratings    struct {
// 			Rottenscore int `json:"critics_score"`
// 		} `json:"ratings"`
// 	} `json:"movies"`
// }

// type CombinedMovieData struct {
// 	Movietitle  string
// 	Imdbscore   string
// 	Rottenscore int
// }
<|endoftext|>