<commit_before>/*
 * Copyright (C) 2014 Michael Wendland
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published
 * by the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 * Authors:
 *   Michael Wendland <michael@michiwend.com>
 */

/*
package goefa implements a go (golang) client library to access data of public
transport companies which provide an EFA interface. You can search a stop, get
its next departures or request a trip.
*/
package goefa

import (
	"encoding/xml"
	"net/http"
	"net/url"
	"path"
	"strings"

	"code.google.com/p/go-charset/charset"
	_ "code.google.com/p/go-charset/data"
)

// EFAProvider represents a public transport company that provides access to
// its EFA instance. Use providers.json to store a list of known providers.
type EFAProvider struct {
	Name           string
	BaseURL        string //FIXME use url.URL
	EnableRealtime bool
}

}

type EFAResult interface {
	endpoint() string
type efaResponse struct {
	XMLName xml.Name `xml:"itdRequest"`

	client     string `xml:"client,attr"`
	clientIP   string `xml:"clientIP,attr"`
	language   string `xml:"language,attr"`
	lengthUnit string `xml:"lengthUnit,attr"`
	now        string `xml:"now,attr"`
	nowWD      int    `xml:"nowID,attr"`
	serverID   string `xml:"serverID,attr"`
	sessionID  int    `xml:"sessionID,attr"`
	version    string `xml:"version,attr"`
	virtDir    string `xml:"virtDir,attr"`

	VersionInfo struct {
		AppVersion string `xml:"ptKernel>appVersion"`
		DataFormat string `xml:"ptKernel>dataFormat"`
		DataBuild  string `xml:"ptKernel>dataBuild"`
	} `xml:"itdVersionInfo"`
}

func (efa *EFAProvider) postRequest(result EFAResult, params url.Values) error {

	client := http.Client{}

	reqUrl, err := url.Parse(efa.BaseURL)
	if err != nil {
		return err
	}
	reqUrl.Path = path.Join(reqUrl.Path, result.endpoint())

	req, err := http.NewRequest("POST", reqUrl.String(), strings.NewReader(params.Encode()))
	if err != nil {
		return err
	}
	req.Header.Set(
		"User-Agent",
		"GoEFA, a golang EFA client / 0.0.1 (https://github.com/michiwend/goefa)",
	)

	resp, err := client.Do(req)
	if err != nil {
		return err
	}
	defer resp.Body.Close() // FIXME, refer to http://golang.org/pkg/net/http/#NewRequest
	defer req.Body.Close()

	decoder := xml.NewDecoder(resp.Body)
	decoder.CharsetReader = charset.NewReader
	if err = decoder.Decode(result); err != nil {
		return err
	}

	return nil
}
<commit_msg>hide efaResult inteface<commit_after>/*
 * Copyright (C) 2014 Michael Wendland
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published
 * by the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 * Authors:
 *   Michael Wendland <michael@michiwend.com>
 */

/*
package goefa implements a go (golang) client library to access data of public
transport companies which provide an EFA interface. You can search a stop, get
its next departures or request a trip.
*/
package goefa

import (
	"encoding/xml"
	"net/http"
	"net/url"
	"path"
	"strings"

	"code.google.com/p/go-charset/charset"
	_ "code.google.com/p/go-charset/data"
)

// EFAProvider represents a public transport company that provides access to
// its EFA instance. Use providers.json to store a list of known providers.
type EFAProvider struct {
	Name           string
	BaseURL        string //FIXME use url.URL
	EnableRealtime bool
}

type efaResult interface {
	endpoint() string
}

type efaResponse struct {
	XMLName xml.Name `xml:"itdRequest"`

	client     string `xml:"client,attr"`
	clientIP   string `xml:"clientIP,attr"`
	language   string `xml:"language,attr"`
	lengthUnit string `xml:"lengthUnit,attr"`
	now        string `xml:"now,attr"`
	nowWD      int    `xml:"nowID,attr"`
	serverID   string `xml:"serverID,attr"`
	sessionID  int    `xml:"sessionID,attr"`
	version    string `xml:"version,attr"`
	virtDir    string `xml:"virtDir,attr"`

	VersionInfo struct {
		AppVersion string `xml:"ptKernel>appVersion"`
		DataFormat string `xml:"ptKernel>dataFormat"`
		DataBuild  string `xml:"ptKernel>dataBuild"`
	} `xml:"itdVersionInfo"`
}

func (efa *EFAProvider) postRequest(result efaResult, params url.Values) error {

	client := http.Client{}

	reqUrl, err := url.Parse(efa.BaseURL)
	if err != nil {
		return err
	}
	reqUrl.Path = path.Join(reqUrl.Path, result.endpoint())

	req, err := http.NewRequest("POST", reqUrl.String(), strings.NewReader(params.Encode()))
	if err != nil {
		return err
	}
	req.Header.Set(
		"User-Agent",
		"GoEFA, a golang EFA client / 0.0.1 (https://github.com/michiwend/goefa)",
	)

	resp, err := client.Do(req)
	if err != nil {
		return err
	}
	defer resp.Body.Close() // FIXME, refer to http://golang.org/pkg/net/http/#NewRequest
	defer req.Body.Close()

	decoder := xml.NewDecoder(resp.Body)
	decoder.CharsetReader = charset.NewReader
	if err = decoder.Decode(result); err != nil {
		return err
	}

	return nil
}
<|endoftext|>


<commit_before>package golis

import (
	"bytes"
	"encoding/binary"
	"errors"
	"fmt"
	"io"
	"net"
	"os"
)

//系统变量定义

var (
	GolisHandler IoHandler                //事件处理
	Unpacket     func([]byte) interface{} //拆包
	Packet       func(interface{}) []byte //封包
)

//定义session
type Iosession struct {
	conn net.Conn
}

//session写入数据
func (this *Iosession) Write(message *interface{}) {
	//触发消息发送事件
	GolisHandler.MessageSent(this, message)
	data := Packet(message)
	totalLen := len(data)
	this.conn.Write(append(IntToBytes(totalLen), data...))
}

//事件触发接口定义
type IoHandler interface {
	//session打开
	SessionOpened(session *Iosession)
	//session关闭
	SessionClosed(session *Iosession)
	//收到消息时触发
	MessageReceived(session *Iosession, message interface{})
	//消息发送时触发
	MessageSent(session *Iosession, message interface{})
}

//运行golis
//netPro：运行协议参数，tcp/udp
//laddr ：程序监听ip和端口，如127.0.0.1:8080
func Run(netPro, laddr string) {
	Log("初始化系统完成")
	netLis, err := net.Listen(netPro, laddr)
	CheckError(err)
	defer netLis.Close()
	Log("等待客户端连接...")
	for {
		conn, err := netLis.Accept()
		if err != nil {
			continue
		}
		go connectHandle(conn)
	}
}

//处理新连接
func connectHandle(conn net.Conn) {
	//声明一个临时缓冲区，用来存储被截断的数据
	tmpBuffer := make([]byte, 0)
	buffer := make([]byte, 1024)

	//声明一个管道用于接收解包的数据
	readerChannel := make(chan []byte, 16)
	//创建session
	session := Iosession{conn}
	//触发sessionCreated事件
	GolisHandler.SessionOpened(&session)

	go reader(&session, readerChannel)

	flag := true
	for flag {
		n, err := conn.Read(buffer)
		switch err {
		case nil:
			//			tmp, data, err := getReadyData(append(tmpBuffer, buffer[:n]...))
			//			tmpBuffer = tmp
			//			if err != nil {
			//				Log(err.Error())
			//			} else {
			//				readFromData(&session, data)
			//			}
			tmpBuffer = unpack(append(tmpBuffer, buffer[:n]...), readerChannel)
		case io.EOF:
			Log("client is disconnected")
			//session关闭
			GolisHandler.SessionClosed(&session)
			flag = false
			break
		default:
			Log("none")
		}
	}

}

const (
	constDataLength = 4
)

//解包
func unpack(buffer []byte, readerChannel chan []byte) []byte {
	length := len(buffer)

	var i int
	for i = 0; i < length; i = i + 1 {
		if length < i+constDataLength {
			break
		}
		messageLength := BytesToInt(buffer[i : i+constDataLength])
		if length < i+constDataLength+messageLength {
			break
		}
		data := buffer[i+constDataLength : i+constDataLength+messageLength]
		readerChannel <- data
		i += constDataLength + messageLength - 1
	}

	if i == length {
		return make([]byte, 0)
	}
	return buffer[i:]
}

//协议中查看协议头是否满足一个协议报
func getReadyData(buffer []byte) ([]byte, []byte, error) {
	length := len(buffer)
	//	Log("length = ", length)
	if length >= 4 {
		totalLen := BytesToInt(buffer[0:4]) //get totalLen
		if totalLen == 0 {
			return make([]byte, 0), nil, errors.New("msg is null")
		} else if totalLen <= length-4 {
			return buffer[totalLen+4:], buffer[4:totalLen], nil
		}

	}
	return buffer, nil, errors.New("msg is not ready")
}

func reader(session *Iosession, readerChannel chan []byte) {
	for {
		select {
		case data := <-readerChannel:
			readFromData(session, data)
		}
	}
}

//从准备好的数据读取
func readFromData(session *Iosession, data []byte) {
	message := Unpacket(data) //拆包
	//收到消息时到达
	GolisHandler.MessageReceived(session, message)
}

//整形转换成字节
func IntToBytes(n int) []byte {
	x := int32(n)

	bytesBuffer := bytes.NewBuffer([]byte{})
	binary.Write(bytesBuffer, binary.BigEndian, x)
	return bytesBuffer.Bytes()
}

//字节转换成整形
func BytesToInt(b []byte) int {
	bytesBuffer := bytes.NewBuffer(b)

	var x int32
	binary.Read(bytesBuffer, binary.BigEndian, &x)

	return int(x)
}

//简单日志输出
func Log(v ...interface{}) {
	fmt.Println(v...)
}

//检查错误并退出程序
func CheckError(err error) {
	if err != nil {
		fmt.Fprintln(os.Stderr, "Fatal error:%s", err.Error())
		os.Exit(1)
	}
}
<commit_msg>+添加int64转byte数组<commit_after>package golis

import (
	"bytes"
	"encoding/binary"
	"errors"
	"fmt"
	"io"
	"net"
	"os"
)

//系统变量定义

var (
	GolisHandler IoHandler                //事件处理
	Unpacket     func([]byte) interface{} //拆包
	Packet       func(interface{}) []byte //封包
)

//定义session
type Iosession struct {
	conn net.Conn
}

//session写入数据
func (this *Iosession) Write(message *interface{}) {
	//触发消息发送事件
	GolisHandler.MessageSent(this, message)
	data := Packet(message)
	totalLen := len(data)
	this.conn.Write(append(IntToBytes(totalLen), data...))
}

//事件触发接口定义
type IoHandler interface {
	//session打开
	SessionOpened(session *Iosession)
	//session关闭
	SessionClosed(session *Iosession)
	//收到消息时触发
	MessageReceived(session *Iosession, message interface{})
	//消息发送时触发
	MessageSent(session *Iosession, message interface{})
}

//运行golis
//netPro：运行协议参数，tcp/udp
//laddr ：程序监听ip和端口，如127.0.0.1:8080
func Run(netPro, laddr string) {
	Log("初始化系统完成")
	netLis, err := net.Listen(netPro, laddr)
	CheckError(err)
	defer netLis.Close()
	Log("等待客户端连接...")
	for {
		conn, err := netLis.Accept()
		if err != nil {
			continue
		}
		go connectHandle(conn)
	}
}

//处理新连接
func connectHandle(conn net.Conn) {
	//声明一个临时缓冲区，用来存储被截断的数据
	tmpBuffer := make([]byte, 0)
	buffer := make([]byte, 1024)

	//声明一个管道用于接收解包的数据
	readerChannel := make(chan []byte, 16)
	//创建session
	session := Iosession{conn}
	//触发sessionCreated事件
	GolisHandler.SessionOpened(&session)

	go reader(&session, readerChannel)

	flag := true
	for flag {
		n, err := conn.Read(buffer)
		switch err {
		case nil:
			//			tmp, data, err := getReadyData(append(tmpBuffer, buffer[:n]...))
			//			tmpBuffer = tmp
			//			if err != nil {
			//				Log(err.Error())
			//			} else {
			//				readFromData(&session, data)
			//			}
			tmpBuffer = unpack(append(tmpBuffer, buffer[:n]...), readerChannel)
		case io.EOF:
			Log("client is disconnected")
			//session关闭
			GolisHandler.SessionClosed(&session)
			flag = false
			break
		default:
			Log("none")
		}
	}

}

const (
	constDataLength = 4
)

//解包
func unpack(buffer []byte, readerChannel chan []byte) []byte {
	length := len(buffer)

	var i int
	for i = 0; i < length; i = i + 1 {
		if length < i+constDataLength {
			break
		}
		messageLength := BytesToInt(buffer[i : i+constDataLength])
		if length < i+constDataLength+messageLength {
			break
		}
		data := buffer[i+constDataLength : i+constDataLength+messageLength]
		readerChannel <- data
		i += constDataLength + messageLength - 1
	}

	if i == length {
		return make([]byte, 0)
	}
	return buffer[i:]
}

//协议中查看协议头是否满足一个协议报
func getReadyData(buffer []byte) ([]byte, []byte, error) {
	length := len(buffer)
	//	Log("length = ", length)
	if length >= 4 {
		totalLen := BytesToInt(buffer[0:4]) //get totalLen
		if totalLen == 0 {
			return make([]byte, 0), nil, errors.New("msg is null")
		} else if totalLen <= length-4 {
			return buffer[totalLen+4:], buffer[4:totalLen], nil
		}

	}
	return buffer, nil, errors.New("msg is not ready")
}

func reader(session *Iosession, readerChannel chan []byte) {
	for {
		select {
		case data := <-readerChannel:
			readFromData(session, data)
		}
	}
}

//从准备好的数据读取
func readFromData(session *Iosession, data []byte) {
	message := Unpacket(data) //拆包
	//收到消息时到达
	GolisHandler.MessageReceived(session, message)
}

//整形转换成字节
func IntToBytes(n int) []byte {
	x := int32(n)

	bytesBuffer := bytes.NewBuffer([]byte{})
	binary.Write(bytesBuffer, binary.BigEndian, x)
	return bytesBuffer.Bytes()
}

//字节转换成整形
func BytesToInt(b []byte) int {
	bytesBuffer := bytes.NewBuffer(b)

	var x int32
	binary.Read(bytesBuffer, binary.BigEndian, &x)

	return int(x)
}

//整形64转换成字节
func Int64ToBytes(n int) []byte {
	x := int64(n)

	bytesBuffer := bytes.NewBuffer([]byte{})
	binary.Write(bytesBuffer, binary.BigEndian, x)
	return bytesBuffer.Bytes()
}

//字节转换成整形64
func BytesToInt64(b []byte) int {
	bytesBuffer := bytes.NewBuffer(b)

	var x int64
	binary.Read(bytesBuffer, binary.BigEndian, &x)

	return int(x)
}

//简单日志输出
func Log(v ...interface{}) {
	fmt.Println(v...)
}

//检查错误并退出程序
func CheckError(err error) {
	if err != nil {
		fmt.Fprintln(os.Stderr, "Fatal error:%s", err.Error())
		os.Exit(1)
	}
}
<|endoftext|>


<commit_before>package gotak

import (
	"crypto/x509"
	"encoding/json"
	"fmt"
	"io"
)

type TlsVersion uint16

const (
	TLS_1_0 TlsVersion = 10
	TLS_1_1            = 11
	TLS_1_2            = 12
)

func (t TlsVersion) String() string {
	switch t {
	case TLS_1_0:
		return "1.0"
	case TLS_1_1:
		return "1.1"
	case TLS_1_2:
		return "1.2"
	default:
		return ""
	}
}

func cryptVersTlsToGotak(vers uint16) (TlsVersion, error) {
	switch vers {
	case 0x0300, 0x0301:
		return TLS_1_0, nil
	case 0x0302:
		return TLS_1_1, nil
	case 0x0303:
		return TLS_1_2, nil
	default:
		return 0, fmt.Errorf("Error: Could not parse version %d.", vers)
	}
}

type Diagnostics struct {
	Version      TlsVersion
	CipherSuite  string
	Certificates []*x509.Certificate
	NPN          bool
	NpnStrings   []string
}

func (d *Diagnostics) JSON() ([]byte, error) {
	jd := new(jsonDiagnostics)
	jd.Version = d.Version.String()
	jd.CipherSuite = d.CipherSuite
	jd.NPN = d.NpnStrings

	return json.Marshal(jd)
}

func (d *Diagnostics) EncodeJSON(w io.Writer) error {
	jd := new(jsonDiagnostics)
	jd.Version = d.Version.String()
	jd.CipherSuite = d.CipherSuite
	jd.NPN = d.NpnStrings

	return json.NewEncoder(w).Encode(jd)
}

type jsonDiagnostics struct {
	Version     string   `json:"version"`
	CipherSuite string   `json:"cipher_suite"`
	NPN         []string `json:"next_protocol_negotiation,omitempty"`
}
<commit_msg>Added Diagnose helper function<commit_after>package gotak

import (
	"crypto/x509"
	"encoding/json"
	"fmt"
	"io"
	"net/http"
	"net/http/httputil"
	"strings"
)

type TlsVersion uint16

const (
	TLS_1_0 TlsVersion = 10
	TLS_1_1            = 11
	TLS_1_2            = 12
)

func (t TlsVersion) String() string {
	switch t {
	case TLS_1_0:
		return "1.0"
	case TLS_1_1:
		return "1.1"
	case TLS_1_2:
		return "1.2"
	default:
		return ""
	}
}

func cryptVersTlsToGotak(vers uint16) (TlsVersion, error) {
	switch vers {
	case 0x0300, 0x0301:
		return TLS_1_0, nil
	case 0x0302:
		return TLS_1_1, nil
	case 0x0303:
		return TLS_1_2, nil
	default:
		return 0, fmt.Errorf("Error: Could not parse version %d.", vers)
	}
}

func Diagnose(addr string, config *Config) (*Diagnostics, error) {
	if config == nil {
		config = new(Config)
		config.NextProtos = []string{"http/1.1"}
	}

	if !strings.Contains(addr, ":") {
		addr = addr + ":443"
	}

	conn, diag, err := Dial("tcp", addr, config)
	if err != nil {
		return nil, err
	}
	defer conn.Close()

	clientConn := httputil.NewClientConn(conn, nil)

	req, err := http.NewRequest("HEAD", "/", nil)
	if err != nil {
		return nil, err
	}

	_, err = clientConn.Do(req)
	if err != nil {
		return nil, err
	}

	return diag, nil
}

type Diagnostics struct {
	Version      TlsVersion
	CipherSuite  string
	Certificates []*x509.Certificate
	NPN          bool
	NpnStrings   []string
}

func (d *Diagnostics) JSON() ([]byte, error) {
	jd := new(jsonDiagnostics)
	jd.Version = d.Version.String()
	jd.CipherSuite = d.CipherSuite
	jd.NPN = d.NpnStrings

	return json.Marshal(jd)
}

func (d *Diagnostics) EncodeJSON(w io.Writer) error {
	jd := new(jsonDiagnostics)
	jd.Version = d.Version.String()
	jd.CipherSuite = d.CipherSuite
	jd.NPN = d.NpnStrings

	return json.NewEncoder(w).Encode(jd)
}

type jsonDiagnostics struct {
	Version     string   `json:"version"`
	CipherSuite string   `json:"cipher_suite"`
	NPN         []string `json:"next_protocol_negotiation,omitempty"`
}
<|endoftext|>


<commit_before>// Package grace allows for gracefully waiting for a listener to
// finish serving it's active requests.
package grace

import (
	"errors"
	"fmt"
	"net"
	"os"
	"os/exec"
	"os/signal"
	"strconv"
	"strings"
	"sync"
	"syscall"
	"time"
)

var (
	// This error is returned by Inherits() when we're not inheriting any fds.
	ErrNotInheriting = errors.New("no inherited listeners")

	// This error is returned by Listener.Accept() when Close is in progress.
	ErrAlreadyClosed = errors.New("already closed")

	// Time in the past to trigger immediate deadline.
	timeInPast = time.Date(1983, time.November, 6, 0, 0, 0, 0, time.UTC)
)

const (
	// Used to indicate a graceful restart in the new process.
	envCountKey = "LISTEN_FDS"

	// The error returned by the standard library when the socket is closed.
	errClosed = "use of closed network connection"
)

// A Listener providing a graceful Close process and can be sent
// across processes using the underlying File descriptor.
type Listener interface {
	net.Listener

	// Will return the underlying file representing this Listener.
	File() (f *os.File, err error)
}

type listener struct {
	Listener
	closed      bool
	closedMutex sync.RWMutex
	wg          sync.WaitGroup
}

type deadliner interface {
	SetDeadline(t time.Time) error
}

// Allows for us to notice when the connection is closed.
type conn struct {
	net.Conn
	wg *sync.WaitGroup
}

func (c conn) Close() error {
	defer c.wg.Done()
	return c.Conn.Close()
}

// Wraps an existing File listener to provide a graceful Close() process.
func NewListener(l Listener) Listener {
	return &listener{Listener: l}
}

func (l *listener) Close() error {
	l.closedMutex.Lock()
	l.closed = true
	l.closedMutex.Unlock()

	var err error
	// Init provided sockets dont actually close so we trigger Accept to return
	// by setting the deadline.
	if os.Getppid() == 1 {
		if ld, ok := l.Listener.(deadliner); ok {
			ld.SetDeadline(timeInPast)
		} else {
			fmt.Fprintln(os.Stderr, "init activated server did not have SetDeadline")
		}
	} else {
		err = l.Listener.Close()
	}
	l.wg.Wait()
	return err
}

func (l *listener) Accept() (c net.Conn, err error) {
	// Presume we'll accept and decrement in defer if we don't. If we did this
	// after a successful accept we would have a race condition where we may end
	// up incorrectly shutting down between the time we do a successful accept
	// and the increment.
	l.wg.Add(1)
	defer func() {
		// If we didn't accept, we decrement our presumptuous count above.
		if c == nil {
			l.wg.Done()
		}
	}()

	l.closedMutex.RLock()
	if l.closed {
		l.closedMutex.RUnlock()
		return nil, ErrAlreadyClosed
	}
	l.closedMutex.RUnlock()

	c, err = l.Listener.Accept()
	if err != nil {
		if strings.HasSuffix(err.Error(), errClosed) {
			return nil, ErrAlreadyClosed
		}

		// We use SetDeadline above to trigger Accept to return when we're trying
		// to handoff to a child as part of our restart process. In this scenario
		// we want to treat the timeout the same as a Close.
		if nerr, ok := err.(net.Error); ok && nerr.Timeout() {
			l.closedMutex.RLock()
			if l.closed {
				l.closedMutex.RUnlock()
				return nil, ErrAlreadyClosed
			}
			l.closedMutex.RUnlock()
		}
		return nil, err
	}
	return conn{Conn: c, wg: &l.wg}, nil
}

// Wait for signals to gracefully terminate or restart the process.
func Wait(listeners []Listener) (err error) {
	ch := make(chan os.Signal, 2)
	signal.Notify(ch, syscall.SIGTERM, syscall.SIGUSR2)
	for {
		sig := <-ch
		switch sig {
		case syscall.SIGTERM:
			var wg sync.WaitGroup
			wg.Add(len(listeners))
			for _, l := range listeners {
				go func(l Listener) {
					cErr := l.Close()
					if cErr != nil {
						err = cErr
					}
					wg.Done()
				}(l)
			}
			wg.Wait()
			return
		case syscall.SIGUSR2:
			rErr := Restart(listeners)
			if rErr != nil {
				return rErr
			}
		}
	}
}

// Try to inherit listeners from the parent process.
func Inherit() (listeners []Listener, err error) {
	countStr := os.Getenv(envCountKey)
	if countStr == "" {
		return nil, ErrNotInheriting
	}
	count, err := strconv.Atoi(countStr)
	if err != nil {
		return nil, err
	}
	// If we are inheriting, the listeners will begin at fd 3
	for i := 3; i < 3+count; i++ {
		file := os.NewFile(uintptr(i), "listener")
		tmp, err := net.FileListener(file)
		file.Close()
		if err != nil {
			return nil, err
		}
		l := tmp.(*net.TCPListener)
		listeners = append(listeners, NewListener(l))
	}
	return
}

// Start the Close process in the parent. This does not wait for the
// parent to close and simply sends it the TERM signal.
func CloseParent() error {
	ppid := os.Getppid()
	if ppid == 1 { // init provided sockets, for example systemd
		return nil
	}
	return syscall.Kill(ppid, syscall.SIGTERM)
}

// Restart the process passing the given listeners to the new process.
func Restart(listeners []Listener) (err error) {
	if len(listeners) == 0 {
		return errors.New("restart must be given listeners.")
	}
	files := make([]*os.File, len(listeners))
	for i, l := range listeners {
		files[i], err = l.File()
		if err != nil {
			return err
		}
		defer files[i].Close()
		syscall.CloseOnExec(int(files[i].Fd()))
	}
	argv0, err := exec.LookPath(os.Args[0])
	if err != nil {
		return err
	}
	wd, err := os.Getwd()
	if err != nil {
		return err
	}
	allFiles := append([]*os.File{os.Stdin, os.Stdout, os.Stderr}, files...)
	allFiles = append(allFiles, nil)
	_, err = os.StartProcess(argv0, os.Args, &os.ProcAttr{
		Dir:   wd,
		Env:   append(os.Environ(), fmt.Sprintf("%s=%d", envCountKey, len(files))),
		Files: allFiles,
	})
	return err
}
<commit_msg>dont use named return variables in a strange way<commit_after>// Package grace allows for gracefully waiting for a listener to
// finish serving it's active requests.
package grace

import (
	"errors"
	"fmt"
	"net"
	"os"
	"os/exec"
	"os/signal"
	"strconv"
	"strings"
	"sync"
	"syscall"
	"time"
)

var (
	// This error is returned by Inherits() when we're not inheriting any fds.
	ErrNotInheriting = errors.New("no inherited listeners")

	// This error is returned by Listener.Accept() when Close is in progress.
	ErrAlreadyClosed = errors.New("already closed")

	// Time in the past to trigger immediate deadline.
	timeInPast = time.Date(1983, time.November, 6, 0, 0, 0, 0, time.UTC)
)

const (
	// Used to indicate a graceful restart in the new process.
	envCountKey = "LISTEN_FDS"

	// The error returned by the standard library when the socket is closed.
	errClosed = "use of closed network connection"
)

// A Listener providing a graceful Close process and can be sent
// across processes using the underlying File descriptor.
type Listener interface {
	net.Listener

	// Will return the underlying file representing this Listener.
	File() (f *os.File, err error)
}

type listener struct {
	Listener
	closed      bool
	closedMutex sync.RWMutex
	wg          sync.WaitGroup
}

type deadliner interface {
	SetDeadline(t time.Time) error
}

// Allows for us to notice when the connection is closed.
type conn struct {
	net.Conn
	wg *sync.WaitGroup
}

func (c conn) Close() error {
	defer c.wg.Done()
	return c.Conn.Close()
}

// Wraps an existing File listener to provide a graceful Close() process.
func NewListener(l Listener) Listener {
	return &listener{Listener: l}
}

func (l *listener) Close() error {
	l.closedMutex.Lock()
	l.closed = true
	l.closedMutex.Unlock()

	var err error
	// Init provided sockets dont actually close so we trigger Accept to return
	// by setting the deadline.
	if os.Getppid() == 1 {
		if ld, ok := l.Listener.(deadliner); ok {
			ld.SetDeadline(timeInPast)
		} else {
			fmt.Fprintln(os.Stderr, "init activated server did not have SetDeadline")
		}
	} else {
		err = l.Listener.Close()
	}
	l.wg.Wait()
	return err
}

func (l *listener) Accept() (net.Conn, error) {
	// Presume we'll accept and decrement in defer if we don't. If we did this
	// after a successful accept we would have a race condition where we may end
	// up incorrectly shutting down between the time we do a successful accept
	// and the increment.
	var c net.Conn
	l.wg.Add(1)
	defer func() {
		// If we didn't accept, we decrement our presumptuous count above.
		if c == nil {
			l.wg.Done()
		}
	}()

	l.closedMutex.RLock()
	if l.closed {
		l.closedMutex.RUnlock()
		return nil, ErrAlreadyClosed
	}
	l.closedMutex.RUnlock()

	c, err := l.Listener.Accept()
	if err != nil {
		if strings.HasSuffix(err.Error(), errClosed) {
			return nil, ErrAlreadyClosed
		}

		// We use SetDeadline above to trigger Accept to return when we're trying
		// to handoff to a child as part of our restart process. In this scenario
		// we want to treat the timeout the same as a Close.
		if nerr, ok := err.(net.Error); ok && nerr.Timeout() {
			l.closedMutex.RLock()
			if l.closed {
				l.closedMutex.RUnlock()
				return nil, ErrAlreadyClosed
			}
			l.closedMutex.RUnlock()
		}
		return nil, err
	}
	return conn{Conn: c, wg: &l.wg}, nil
}

// Wait for signals to gracefully terminate or restart the process.
func Wait(listeners []Listener) (err error) {
	ch := make(chan os.Signal, 2)
	signal.Notify(ch, syscall.SIGTERM, syscall.SIGUSR2)
	for {
		sig := <-ch
		switch sig {
		case syscall.SIGTERM:
			var wg sync.WaitGroup
			wg.Add(len(listeners))
			for _, l := range listeners {
				go func(l Listener) {
					cErr := l.Close()
					if cErr != nil {
						err = cErr
					}
					wg.Done()
				}(l)
			}
			wg.Wait()
			return
		case syscall.SIGUSR2:
			rErr := Restart(listeners)
			if rErr != nil {
				return rErr
			}
		}
	}
}

// Try to inherit listeners from the parent process.
func Inherit() (listeners []Listener, err error) {
	countStr := os.Getenv(envCountKey)
	if countStr == "" {
		return nil, ErrNotInheriting
	}
	count, err := strconv.Atoi(countStr)
	if err != nil {
		return nil, err
	}
	// If we are inheriting, the listeners will begin at fd 3
	for i := 3; i < 3+count; i++ {
		file := os.NewFile(uintptr(i), "listener")
		tmp, err := net.FileListener(file)
		file.Close()
		if err != nil {
			return nil, err
		}
		l := tmp.(*net.TCPListener)
		listeners = append(listeners, NewListener(l))
	}
	return
}

// Start the Close process in the parent. This does not wait for the
// parent to close and simply sends it the TERM signal.
func CloseParent() error {
	ppid := os.Getppid()
	if ppid == 1 { // init provided sockets, for example systemd
		return nil
	}
	return syscall.Kill(ppid, syscall.SIGTERM)
}

// Restart the process passing the given listeners to the new process.
func Restart(listeners []Listener) (err error) {
	if len(listeners) == 0 {
		return errors.New("restart must be given listeners.")
	}
	files := make([]*os.File, len(listeners))
	for i, l := range listeners {
		files[i], err = l.File()
		if err != nil {
			return err
		}
		defer files[i].Close()
		syscall.CloseOnExec(int(files[i].Fd()))
	}
	argv0, err := exec.LookPath(os.Args[0])
	if err != nil {
		return err
	}
	wd, err := os.Getwd()
	if err != nil {
		return err
	}
	allFiles := append([]*os.File{os.Stdin, os.Stdout, os.Stderr}, files...)
	allFiles = append(allFiles, nil)
	_, err = os.StartProcess(argv0, os.Args, &os.ProcAttr{
		Dir:   wd,
		Env:   append(os.Environ(), fmt.Sprintf("%s=%d", envCountKey, len(files))),
		Files: allFiles,
	})
	return err
}
<|endoftext|>


<commit_before>package main

import (
	"os"
	"gopkg.in/alecthomas/kingpin.v2"
	"fmt"
	"github.com/sandreas/graft/pattern"
	"github.com/sandreas/graft/file"
	"strconv"
	"regexp"
	"path"
	"strings"
	"math"
)

var (
	app = kingpin.New("graft", "A command-line tool to locate and transfer files")
	sourcePatternParameter = app.Arg("source-pattern", "source pattern - used to locate files (e.g. src/*)").Required().String()
	destinationPatternParameter = app.Arg("destination-pattern", "destination pattern for transfer (e.g. dst/$1)").Default("").String()

	exportTo = app.Flag("export-to", "export source listing to file, one line per found item").Default("").String()
	// filesFrom = app.Flag("files-from", "import source listing from file, one line per item").Default("").String()

	caseSensitive = app.Flag("case-sensitive", "be case sensitive when matching files and folders").Bool()
	dryRun = app.Flag("dry-run", "dry-run / simulation mode").Bool()
	hideMatches = app.Flag("hide-matches", "hide matches in search mode ($1: ...)").Bool()
	move = app.Flag("move", "move / rename files - do not make a copy").Bool()
	quiet = app.Flag("quiet", "quiet mode - do not show any output").Bool()
	regex = app.Flag("regex", "use a real regex instead of glob patterns (e.g. src/.*\\.jpg)").Bool()
	times = app.Flag("times", "transfer source modify times to destination").Bool()
)

var dirsToRemove = make([]string, 0)

func main() {
	kingpin.MustParse(app.Parse(os.Args[1:]))
	sourcePattern := *sourcePatternParameter
	destinationPattern := *destinationPatternParameter

	//if *filesFrom == "" {
	patternPath, pat := pattern.ParsePathPattern(sourcePattern)
	if destinationPattern == "" {
		prntln("search in " + patternPath + ": " + pat)
	} else if (*move) {
		prntln("move: " + sourcePattern + " => " + destinationPattern)
	} else {
		prntln("copy: " + sourcePattern + " => " + destinationPattern)
	}

	prntln("")

	if ! *regex {
		pat = pattern.GlobToRegex(pat)
	}

	caseInsensitiveQualifier := "(?i)"
	if *caseSensitive {
		caseInsensitiveQualifier = ""
	}

	compiledPattern, err := pattern.CompileNormalizedPathPattern(patternPath, caseInsensitiveQualifier + pat)
	if err == nil && compiledPattern.NumSubexp() == 0 && pat != "" {
		compiledPattern, err = pattern.CompileNormalizedPathPattern(patternPath, caseInsensitiveQualifier + "(" + pat + ")")
	}

	if err != nil {
		prntln("could not compile source pattern, please use slashes to qualify paths (recognized path: " + patternPath + ", pattern" + pat + ")")
		return
	}

	matchingPaths, err := file.WalkPathByPattern(patternPath, compiledPattern)
	if err != nil {
		prntln("Could not scan path " + patternPath + ":", err.Error())
		return
	}
	if *exportTo != "" {
		exportFile(*exportTo, matchingPaths)
	}
	//} else {
	//
	//}

	if destinationPattern == "" {
		for _, element := range matchingPaths {
			findElementHandler(element, compiledPattern)
		}
		return
	}

	for _, element := range matchingPaths {
		transferElementHandler(element, destinationPattern, compiledPattern)
	}

	if *move {
		for _, dirToRemove := range dirsToRemove {
			os.Remove(dirToRemove)
		}
	}
	return
}

func exportFile(file string, lines []string) {
	f, err := os.Create(*exportTo)
	if err != nil {
		prntln("could not create export file " + file + ": " + err.Error())
		return;
	}
	_, err = f.WriteString(strings.Join(lines, "\n"))
	defer f.Close()
	if err != nil {
		prntln("could not write export file " + file + ": " + err.Error())
	}

}

func appendRemoveDir(dir string) {
	if (*move) {
		dirsToRemove = append(dirsToRemove, dir)
	}
}

func handleProgress(bytesTransferred, size, chunkSize int64) (int64) {

	if size <= 0 {
		return chunkSize
	}

	percent := float64(bytesTransferred) / float64(size)
	progressChars := int(math.Floor(percent * 10) * 2)
	progressBar := fmt.Sprintf("[%-21s] %3d%%", strings.Repeat("=", progressChars) + ">", int64(percent * 100))
	// prnt("\x0c" + progressBar)
	prnt("\r" + progressBar)
	if bytesTransferred == size {
		prntln("")
	}
	// fmt.Print("\r" + progressBar)
	return chunkSize
}

func prntln(a ...interface{}) (n int, err error) {
	if ! *quiet {
		return fmt.Println(a...)
	}
	return n, err
}

func prnt(a...interface{}) (n int, err error) {
	if ! *quiet {
		return fmt.Print(a...)
	}
	return n, err
}

func findElementHandler(element string, compiledPattern *regexp.Regexp) {
	prntln(element)
	if *hideMatches {
		return
	}
	elementMatches := pattern.BuildMatchList(compiledPattern, element)
	for i := 0; i < len(elementMatches); i++ {
		prntln("    $" + strconv.Itoa(i + 1) + ": " + elementMatches[i])
	}

}

func transferElementHandler(src, destinationPattern string, compiledPattern  *regexp.Regexp) {
	dst := compiledPattern.ReplaceAllString(pattern.NormalizeDirSep(src), pattern.NormalizeDirSep(destinationPattern))

	prntln(src + " => " + dst)

	if *dryRun {
		return
	}

	srcStat, srcErr := os.Stat(src)

	if srcErr != nil {
		prntln("could not read source: ", srcErr)
		return
	}

	dstStat, _ := os.Stat(dst)
	dstExists := file.Exists(dst)
	if srcStat.IsDir() {
		if ! dstExists {
			if os.MkdirAll(dst, srcStat.Mode()) != nil {
				prntln("Could not create destination directory")
			}
			appendRemoveDir(dst)
			fixTimes(dst, srcStat)
			return
		}

		if dstStat.IsDir() {
			appendRemoveDir(dst)
			fixTimes(dst, srcStat)
			return
		}

		prntln("destination already exists as file, source is a directory")
		return
	}

	if dstExists && dstStat.IsDir() {
		prntln("destination already exists as directory, source is a file")
		return
	}

	srcDir := path.Dir(src)
	srcDirStat, _ := os.Stat(srcDir)

	dstDir := path.Dir(dst)
	if ! file.Exists(dstDir) {
		os.MkdirAll(dstDir, srcDirStat.Mode())
	}

	if *move {
		renameErr := os.Rename(src, dst)
		if renameErr == nil {
			appendRemoveDir(srcDir)
			fixTimes(dst, srcStat)
			return
		}
		prntln("Could not rename source")
		return
	}

	srcPointer, srcPointerErr := os.Open(src)
	if srcPointerErr != nil {
		prntln("Could not open source file")
		return
	}
	dstPointer, dstPointerErr := os.OpenFile(dst, os.O_WRONLY | os.O_CREATE, srcStat.Mode())

	if dstPointerErr != nil {
		prntln("Could not create destination file", dstPointerErr.Error())
		return
	}

	file.CopyResumed(srcPointer, dstPointer, handleProgress)
	fixTimes(dst, srcStat)
}

func fixTimes(dst string, inStats os.FileInfo) {
	if *times {
		os.Chtimes(dst, inStats.ModTime(), inStats.ModTime())
	}
}<commit_msg>Fix for transfers without patterns / expressions<commit_after>package main

import (
	"os"
	"gopkg.in/alecthomas/kingpin.v2"
	"fmt"
	"github.com/sandreas/graft/pattern"
	"github.com/sandreas/graft/file"
	"strconv"
	"regexp"
	"path"
	"strings"
	"math"
)

var (
	app = kingpin.New("graft", "A command-line tool to locate and transfer files")
	sourcePatternParameter = app.Arg("source-pattern", "source pattern - used to locate files (e.g. src/*)").Required().String()
	destinationPatternParameter = app.Arg("destination-pattern", "destination pattern for transfer (e.g. dst/$1)").Default("").String()

	exportTo = app.Flag("export-to", "export source listing to file, one line per found item").Default("").String()
	// filesFrom = app.Flag("files-from", "import source listing from file, one line per item").Default("").String()

	caseSensitive = app.Flag("case-sensitive", "be case sensitive when matching files and folders").Bool()
	dryRun = app.Flag("dry-run", "dry-run / simulation mode").Bool()
	hideMatches = app.Flag("hide-matches", "hide matches in search mode ($1: ...)").Bool()
	move = app.Flag("move", "move / rename files - do not make a copy").Bool()
	quiet = app.Flag("quiet", "quiet mode - do not show any output").Bool()
	regex = app.Flag("regex", "use a real regex instead of glob patterns (e.g. src/.*\\.jpg)").Bool()
	times = app.Flag("times", "transfer source modify times to destination").Bool()
)

var dirsToRemove = make([]string, 0)

func main() {
	kingpin.MustParse(app.Parse(os.Args[1:]))
	sourcePattern := *sourcePatternParameter
	destinationPattern := *destinationPatternParameter

	//if *filesFrom == "" {
	patternPath, pat := pattern.ParsePathPattern(sourcePattern)
	if destinationPattern == "" {
		searchIn := patternPath
		if patternPath == "" {
			searchIn = "./"
		}

		searchFor := ""
		if pat != "" {
			searchFor = pat
		}
		prntln("search in " + searchIn + ": " + searchFor)

	} else if (*move) {
		prntln("move: " + sourcePattern + " => " + destinationPattern)
	} else {
		prntln("copy: " + sourcePattern + " => " + destinationPattern)
	}

	prntln("")

	if ! *regex {
		pat = pattern.GlobToRegex(pat)
	}

	caseInsensitiveQualifier := "(?i)"
	if *caseSensitive {
		caseInsensitiveQualifier = ""
	}

	compiledPattern, err := pattern.CompileNormalizedPathPattern(patternPath, caseInsensitiveQualifier + pat)
	if err == nil && compiledPattern.NumSubexp() == 0 && pat != "" {
		compiledPattern, err = pattern.CompileNormalizedPathPattern(patternPath, caseInsensitiveQualifier + "(" + pat + ")")
	}

	if err != nil {
		prntln("could not compile source pattern, please use slashes to qualify paths (recognized path: " + patternPath + ", pattern" + pat + ")")
		return
	}

	matchingPaths, err := file.WalkPathByPattern(patternPath, compiledPattern)
	if err != nil {
		prntln("Could not scan path " + patternPath + ":", err.Error())
		return
	}
	if *exportTo != "" {
		exportFile(*exportTo, matchingPaths)
	}
	//} else {
	//
	//}

	if destinationPattern == "" {
		for _, element := range matchingPaths {
			findElementHandler(element, compiledPattern)
		}
		return
	}

	dstPath, dstPatt := pattern.ParsePathPattern(destinationPattern)
	var dst string
	for _, element := range matchingPaths {
		if dstPatt == "" {
			dst = pattern.NormalizeDirSep(dstPath + element[len(patternPath)+1:])
		} else {
			dst = compiledPattern.ReplaceAllString(pattern.NormalizeDirSep(element), pattern.NormalizeDirSep(destinationPattern))
		}
		transferElementHandler(element, dst)
	}

	if *move {
		for _, dirToRemove := range dirsToRemove {
			os.Remove(dirToRemove)
		}
	}
	return
}

func exportFile(file string, lines []string) {
	f, err := os.Create(*exportTo)
	if err != nil {
		prntln("could not create export file " + file + ": " + err.Error())
		return;
	}
	_, err = f.WriteString(strings.Join(lines, "\n"))
	defer f.Close()
	if err != nil {
		prntln("could not write export file " + file + ": " + err.Error())
	}

}

func appendRemoveDir(dir string) {
	if (*move) {
		dirsToRemove = append(dirsToRemove, dir)
	}
}

func handleProgress(bytesTransferred, size, chunkSize int64) (int64) {

	if size <= 0 {
		return chunkSize
	}

	percent := float64(bytesTransferred) / float64(size)
	progressChars := int(math.Floor(percent * 10) * 2)
	progressBar := fmt.Sprintf("[%-21s] %3d%%", strings.Repeat("=", progressChars) + ">", int64(percent * 100))
	// prnt("\x0c" + progressBar)
	prnt("\r" + progressBar)
	if bytesTransferred == size {
		prntln("")
	}
	// fmt.Print("\r" + progressBar)
	return chunkSize
}

func prntln(a ...interface{}) (n int, err error) {
	if ! *quiet {
		return fmt.Println(a...)
	}
	return n, err
}

func prnt(a...interface{}) (n int, err error) {
	if ! *quiet {
		return fmt.Print(a...)
	}
	return n, err
}

func findElementHandler(element string, compiledPattern *regexp.Regexp) {
	prntln(element)
	if *hideMatches {
		return
	}
	elementMatches := pattern.BuildMatchList(compiledPattern, element)
	for i := 0; i < len(elementMatches); i++ {
		prntln("    $" + strconv.Itoa(i + 1) + ": " + elementMatches[i])
	}

}

func transferElementHandler(src, dst string) {

	prntln(src + " => " + dst)

	if *dryRun {
		return
	}

	srcStat, srcErr := os.Stat(src)

	if srcErr != nil {
		prntln("could not read source: ", srcErr)
		return
	}

	dstStat, _ := os.Stat(dst)
	dstExists := file.Exists(dst)
	if srcStat.IsDir() {
		if ! dstExists {
			if os.MkdirAll(dst, srcStat.Mode()) != nil {
				prntln("Could not create destination directory")
			}
			appendRemoveDir(dst)
			fixTimes(dst, srcStat)
			return
		}

		if dstStat.IsDir() {
			appendRemoveDir(dst)
			fixTimes(dst, srcStat)
			return
		}

		prntln("destination already exists as file, source is a directory")
		return
	}

	if dstExists && dstStat.IsDir() {
		prntln("destination already exists as directory, source is a file")
		return
	}

	srcDir := path.Dir(src)
	srcDirStat, _ := os.Stat(srcDir)

	dstDir := path.Dir(dst)
	if ! file.Exists(dstDir) {
		os.MkdirAll(dstDir, srcDirStat.Mode())
	}

	if *move {
		renameErr := os.Rename(src, dst)
		if renameErr == nil {
			appendRemoveDir(srcDir)
			fixTimes(dst, srcStat)
			return
		}
		prntln("Could not rename source")
		return
	}

	srcPointer, srcPointerErr := os.Open(src)
	if srcPointerErr != nil {
		prntln("Could not open source file")
		return
	}
	dstPointer, dstPointerErr := os.OpenFile(dst, os.O_WRONLY | os.O_CREATE, srcStat.Mode())

	if dstPointerErr != nil {
		prntln("Could not create destination file", dstPointerErr.Error())
		return
	}

	file.CopyResumed(srcPointer, dstPointer, handleProgress)
	fixTimes(dst, srcStat)
}

func fixTimes(dst string, inStats os.FileInfo) {
	if *times {
		os.Chtimes(dst, inStats.ModTime(), inStats.ModTime())
	}
}<|endoftext|>


<commit_before>// Copyright ©2014 The gonum 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 graph

// All a node needs to do is identify itself. This allows the user to pass in nodes more
// interesting than an int, but also allow us to reap the benefits of having a map-storable,
// ==able type.
type Node interface {
	ID() int
}

// Allows edges to do something more interesting that just be a group of nodes. While the methods
// are called Head and Tail, they are not considered directed unless the given interface specifies
// otherwise.
type Edge interface {
	Head() Node
	Tail() Node
}

// A Graph implements the behavior of an undirected graph.
//
// All methods in Graph are implicitly undirected. Graph algorithms that care about directionality
// will intelligently choose the DirectedGraph behavior if that interface is also implemented,
// even if the function itself only takes in a Graph (or a super-interface of graph).
type Graph interface {
	// NodeExists returns true when node is currently in the graph.
	NodeExists(Node) bool

	// NodeList returns a list of all nodes in no particular order, useful for
	// determining things like if a graph is fully connected. The caller is
	// free to modify this list. Implementations should construct a new list
	// and not return internal representation.
	NodeList() []Node

	// Neighbors returns all nodes connected by any edge to this node.
	Neighbors(Node) []Node

	// EdgeBetween returns an edge between node and neighbor such that
	// Head is one argument and Tail is the other. If no
	// such edge exists, this function returns nil.
	EdgeBetween(node, neighbor Node) Edge
}

// Directed graphs are characterized by having seperable Heads and Tails in their edges.
// That is, if node1 goes to node2, that does not necessarily imply that node2 goes to node1.
//
// While it's possible for a directed graph to have fully reciprocal edges (i.e. the graph is
// symmetric) -- it is not required to be. The graph is also required to implement Graph
// because in many cases it can be useful to know all neighbors regardless of direction.
type DirectedGraph interface {
	Graph
	// Successors gives the nodes connected by OUTBOUND edges.
	// If the graph is an undirected graph, this set is equal to Predecessors.
	Successors(Node) []Node

	// EdgeTo returns an edge between node and successor such that
	// Head returns node and Tail returns successor, if no
	// such edge exists, this function returns nil.
	EdgeTo(node, successor Node) Edge

	// Predecessors gives the nodes connected by INBOUND edges.
	// If the graph is an undirected graph, this set is equal to Successors.
	Predecessors(Node) []Node
}

// Returns all undirected edges in the graph
type EdgeLister interface {
	EdgeList() []Edge
}

type EdgeListGraph interface {
	Graph
	EdgeLister
}

// Returns all directed edges in the graph.
type DirectedEdgeLister interface {
	DirectedEdgeList() []Edge
}

type DirectedEdgeListGraph interface {
	Graph
	DirectedEdgeLister
}

// A crunch graph forces a sparse graph to become a dense graph. That is, if the node IDs are
// [1,4,9,7] it would "crunch" the ids into the contiguous block [0,1,2,3]. Order is not
// required to be preserved between the non-cruched and crunched instances (that means in
// the example above 0 may correspond to 4 or 7 or 9, not necessarily 1).
//
// All dense graphs must have the first ID as 0.
type CrunchGraph interface {
	Graph
	Crunch()
}

// A Graph that implements Coster has an actual cost between adjacent nodes, also known as a
// weighted graph. If a graph implements coster and a function needs to read cost (e.g. A*),
// this function will take precedence over the Uniform Cost function (all weights are 1) if "nil"
// is passed in for the function argument.
//
// If the argument is nil, or the edge is invalid for some reason, this should return math.Inf(1)
type Coster interface {
	Cost(edge Edge) float64
}

type CostGraph interface {
	Coster
	Graph
}

type CostDirectedGraph interface {
	Coster
	DirectedGraph
}

// A graph that implements HeuristicCoster implements a heuristic between any two given nodes.
// Like Coster, if a graph implements this and a function needs a heuristic cost (e.g. A*), this
// function will take precedence over the Null Heuristic (always returns 0) if "nil" is passed in
// for the function argument. If HeuristicCost is not intended to be used, it can be implemented as
// the null heuristic (always returns 0.)
type HeuristicCoster interface {
	// HeuristicCost returns a heuristic cost between any two nodes.
	HeuristicCost(node1, node2 Node) float64
}

// A Mutable is a graph that can have arbitrary nodes and edges added or removed.
//
// Anything implementing Mutable is required to store the actual argument. So if AddNode(myNode) is
// called and later a user calls on the graph graph.NodeList(), the node added by AddNode must be
// an the exact node, not a new node with the same ID.
//
// In any case where conflict is possible (e.g. adding two nodes with the same ID), the later
// call always supercedes the earlier one.
//
// Functions will generally expect one of MutableGraph or MutableDirectedGraph and not Mutable
// itself. That said, any function that takes Mutable[x], the destination mutable should
// always be a different graph than the source.
type Mutable interface {
	// NewNode adds a node with an arbitrary ID and returns the new, unique ID
	// used.
	NewNode() Node

	// Adds a node to the graph. If this is called multiple times for the same ID, the newer node
	// overwrites the old one.
	AddNode(Node)

	// EmptyGraph clears the graph of all nodes and edges.
	EmptyGraph()

	// RemoveNode removes a node from the graph, as well as any edges
	// attached to it. If no such node exists, this is a no-op, not an error.
	RemoveNode(Node)
}

// MutableGraph is an interface ensuring the implementation of the ability to construct
// an arbitrary undirected graph. It is very important to note that any implementation
// of MutableGraph absolutely cannot safely implement the DirectedGraph interface.
//
// A MutableGraph is required to store any Edge argument in the same way Mutable must
// store a Node argument -- any retrieval call is required to return the exact supplied edge.
// This is what makes it incompatible with DirectedGraph.
//
// A call to AddEdgeBetween(Edge{head,tail}) make is so there is simply no way to safely
// return EdgeTo(tail, head) since the edge returned will, by this contract, need to be
// Head() == head and Tail() == tail when the reverse must be true to fulfill the
// functionality guaranteed of EdgeTo.
type MutableGraph interface {
	CostGraph
	Mutable

	// Like EdgeBetween in Graph, AddEdgeBetween adds an edge between two nodes.
	// If one or both nodes do not exist, the Graph is expected to add them.
	AddEdgeBetween(e Edge, cost float64)

	// RemoveEdge clears the stored edge between two nodes. Calling this will never
	// remove a node. If the edge does not exist this is a no-op, not an error.
	RemoveEdgeBetween(e Edge)
}

// MutableDirectedGraph is an interface that ensures one can construct an arbitrary directed
// graph. Naturally, a MutableDirectedGraph works for both undirected and directed cases,
// but simply using a MutableGraph may be cleaner. As the documentation for MutableGraph
// notes, however, a graph cannot safely implement MutableGraph and MutableDirectedGraph
// at the same time, because of the functionality of a EdgeTo in DirectedGraph.
type MutableDirectedGraph interface {
	CostDirectedGraph
	Mutable

	// Adds an edge FROM e.Head TO e.Tail. Newer calls overwrite older ones.
	// If the nodes Head or Tail do not exist in the graph, this must add them.
	AddEdgeTo(e Edge, cost float64)

	// Removes an edge FROM e.Head TO e.Tail. If no such edge exists, this is a no-op,
	// not an error.
	RemoveEdgeTo(e Edge)
}

// A function that returns the cost of following an edge
type CostFunc func(Edge) float64

// Estimates the cost of travelling between two nodes
type HeuristicCostFunc func(Node, Node) float64

// Determines if a MutableGraph implements DirectedGraph and panics if it does.
// This is a utility function to detect unsafe implementations. It's mostly for internal use,
// but is exported since it may be useful to people who use the package for their own tests.
func VetMutableGraph(g MutableGraph) {
	if _, ok := g.(DirectedGraph); ok {
		panic("A MutableGraph implements DirectedGraph; this is unsafe!")
	}
}
<commit_msg>Up and removed VetMutableGraph<commit_after>// Copyright ©2014 The gonum 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 graph

// All a node needs to do is identify itself. This allows the user to pass in nodes more
// interesting than an int, but also allow us to reap the benefits of having a map-storable,
// ==able type.
type Node interface {
	ID() int
}

// Allows edges to do something more interesting that just be a group of nodes. While the methods
// are called Head and Tail, they are not considered directed unless the given interface specifies
// otherwise.
type Edge interface {
	Head() Node
	Tail() Node
}

// A Graph implements the behavior of an undirected graph.
//
// All methods in Graph are implicitly undirected. Graph algorithms that care about directionality
// will intelligently choose the DirectedGraph behavior if that interface is also implemented,
// even if the function itself only takes in a Graph (or a super-interface of graph).
type Graph interface {
	// NodeExists returns true when node is currently in the graph.
	NodeExists(Node) bool

	// NodeList returns a list of all nodes in no particular order, useful for
	// determining things like if a graph is fully connected. The caller is
	// free to modify this list. Implementations should construct a new list
	// and not return internal representation.
	NodeList() []Node

	// Neighbors returns all nodes connected by any edge to this node.
	Neighbors(Node) []Node

	// EdgeBetween returns an edge between node and neighbor such that
	// Head is one argument and Tail is the other. If no
	// such edge exists, this function returns nil.
	EdgeBetween(node, neighbor Node) Edge
}

// Directed graphs are characterized by having seperable Heads and Tails in their edges.
// That is, if node1 goes to node2, that does not necessarily imply that node2 goes to node1.
//
// While it's possible for a directed graph to have fully reciprocal edges (i.e. the graph is
// symmetric) -- it is not required to be. The graph is also required to implement Graph
// because in many cases it can be useful to know all neighbors regardless of direction.
type DirectedGraph interface {
	Graph
	// Successors gives the nodes connected by OUTBOUND edges.
	// If the graph is an undirected graph, this set is equal to Predecessors.
	Successors(Node) []Node

	// EdgeTo returns an edge between node and successor such that
	// Head returns node and Tail returns successor, if no
	// such edge exists, this function returns nil.
	EdgeTo(node, successor Node) Edge

	// Predecessors gives the nodes connected by INBOUND edges.
	// If the graph is an undirected graph, this set is equal to Successors.
	Predecessors(Node) []Node
}

// Returns all undirected edges in the graph
type EdgeLister interface {
	EdgeList() []Edge
}

type EdgeListGraph interface {
	Graph
	EdgeLister
}

// Returns all directed edges in the graph.
type DirectedEdgeLister interface {
	DirectedEdgeList() []Edge
}

type DirectedEdgeListGraph interface {
	Graph
	DirectedEdgeLister
}

// A crunch graph forces a sparse graph to become a dense graph. That is, if the node IDs are
// [1,4,9,7] it would "crunch" the ids into the contiguous block [0,1,2,3]. Order is not
// required to be preserved between the non-cruched and crunched instances (that means in
// the example above 0 may correspond to 4 or 7 or 9, not necessarily 1).
//
// All dense graphs must have the first ID as 0.
type CrunchGraph interface {
	Graph
	Crunch()
}

// A Graph that implements Coster has an actual cost between adjacent nodes, also known as a
// weighted graph. If a graph implements coster and a function needs to read cost (e.g. A*),
// this function will take precedence over the Uniform Cost function (all weights are 1) if "nil"
// is passed in for the function argument.
//
// If the argument is nil, or the edge is invalid for some reason, this should return math.Inf(1)
type Coster interface {
	Cost(edge Edge) float64
}

type CostGraph interface {
	Coster
	Graph
}

type CostDirectedGraph interface {
	Coster
	DirectedGraph
}

// A graph that implements HeuristicCoster implements a heuristic between any two given nodes.
// Like Coster, if a graph implements this and a function needs a heuristic cost (e.g. A*), this
// function will take precedence over the Null Heuristic (always returns 0) if "nil" is passed in
// for the function argument. If HeuristicCost is not intended to be used, it can be implemented as
// the null heuristic (always returns 0.)
type HeuristicCoster interface {
	// HeuristicCost returns a heuristic cost between any two nodes.
	HeuristicCost(node1, node2 Node) float64
}

// A Mutable is a graph that can have arbitrary nodes and edges added or removed.
//
// Anything implementing Mutable is required to store the actual argument. So if AddNode(myNode) is
// called and later a user calls on the graph graph.NodeList(), the node added by AddNode must be
// an the exact node, not a new node with the same ID.
//
// In any case where conflict is possible (e.g. adding two nodes with the same ID), the later
// call always supercedes the earlier one.
//
// Functions will generally expect one of MutableGraph or MutableDirectedGraph and not Mutable
// itself. That said, any function that takes Mutable[x], the destination mutable should
// always be a different graph than the source.
type Mutable interface {
	// NewNode adds a node with an arbitrary ID and returns the new, unique ID
	// used.
	NewNode() Node

	// Adds a node to the graph. If this is called multiple times for the same ID, the newer node
	// overwrites the old one.
	AddNode(Node)

	// EmptyGraph clears the graph of all nodes and edges.
	EmptyGraph()

	// RemoveNode removes a node from the graph, as well as any edges
	// attached to it. If no such node exists, this is a no-op, not an error.
	RemoveNode(Node)
}

// MutableGraph is an interface ensuring the implementation of the ability to construct
// an arbitrary undirected graph. It is very important to note that any implementation
// of MutableGraph absolutely cannot safely implement the DirectedGraph interface.
//
// A MutableGraph is required to store any Edge argument in the same way Mutable must
// store a Node argument -- any retrieval call is required to return the exact supplied edge.
// This is what makes it incompatible with DirectedGraph.
//
// A call to AddEdgeBetween(Edge{head,tail}) make is so there is simply no way to safely
// return EdgeTo(tail, head) since the edge returned will, by this contract, need to be
// Head() == head and Tail() == tail when the reverse must be true to fulfill the
// functionality guaranteed of EdgeTo.
type MutableGraph interface {
	CostGraph
	Mutable

	// Like EdgeBetween in Graph, AddEdgeBetween adds an edge between two nodes.
	// If one or both nodes do not exist, the Graph is expected to add them.
	AddEdgeBetween(e Edge, cost float64)

	// RemoveEdge clears the stored edge between two nodes. Calling this will never
	// remove a node. If the edge does not exist this is a no-op, not an error.
	RemoveEdgeBetween(e Edge)
}

// MutableDirectedGraph is an interface that ensures one can construct an arbitrary directed
// graph. Naturally, a MutableDirectedGraph works for both undirected and directed cases,
// but simply using a MutableGraph may be cleaner. As the documentation for MutableGraph
// notes, however, a graph cannot safely implement MutableGraph and MutableDirectedGraph
// at the same time, because of the functionality of a EdgeTo in DirectedGraph.
type MutableDirectedGraph interface {
	CostDirectedGraph
	Mutable

	// Adds an edge FROM e.Head TO e.Tail. Newer calls overwrite older ones.
	// If the nodes Head or Tail do not exist in the graph, this must add them.
	AddEdgeTo(e Edge, cost float64)

	// Removes an edge FROM e.Head TO e.Tail. If no such edge exists, this is a no-op,
	// not an error.
	RemoveEdgeTo(e Edge)
}

// A function that returns the cost of following an edge
type CostFunc func(Edge) float64

// Estimates the cost of travelling between two nodes
type HeuristicCostFunc func(Node, Node) float64
<|endoftext|>


<commit_before>package flow

import (
	"sync"
	"reflect"
)

type connection reflect.Value

// GraphConfig sets up properties for a graph
type GraphConfig struct {
	Capacity uint
	BufferSize uint
}

// defaultGraphConfig provides defaults for GraphConfig
func defaultGraphConfig() GraphConfig {
	return GraphConfig {
		Capacity: 32,
		BufferSize: 0,
	}
}

// Graph is a component that consists of other components connected with channels
type Graph struct {
	procs map[string]Component
	conns map[string]connection
	childGrp *sync.WaitGroup
}

// NewGraph returns a new initialized empty graph instance
func NewGraph(config ...GraphConfig) *Graph {
	conf := defaultGraphConfig()
	if (len(config) == 1) {
		conf = config[0]
	}

	return &Graph{
		procs: make(map[string]Component, conf.Capacity),
		conns: make(map[string]connection, conf.Capacity),
		childGrp: new(sync.WaitGroup),
	}
}

// Add a component to the graph
func (n *Graph) Add(name string, c Component) error {
	n.procs[name] = c
	return nil
}<commit_msg>Delete new graph.go, stick to refactoring network.go<commit_after><|endoftext|>


<commit_before>// Copyright (c) 2019 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 zanzibar

import (
	"bytes"
	"context"
	"encoding/json"
	"fmt"
	"net/http"
	"time"

	"github.com/opentracing/opentracing-go"
	"github.com/pkg/errors"
	"go.uber.org/zap"
)

// ClientHTTPRequest is the struct for making a single client request using an outbound http client.
type ClientHTTPRequest struct {
	ClientID       string
	MethodName     string
	client         *HTTPClient
	httpReq        *http.Request
	res            *ClientHTTPResponse
	started        bool
	startTime      time.Time
	Logger         *zap.Logger
	ContextLogger  ContextLogger
	rawBody        []byte
	defaultHeaders map[string]string
	ctx            context.Context
	metrics        ContextMetrics
}

// NewClientHTTPRequest allocates a ClientHTTPRequest. The ctx parameter is the context associated with the outbound requests.
func NewClientHTTPRequest(
	ctx context.Context,
	clientID, methodName string,
	client *HTTPClient,
) *ClientHTTPRequest {
	scopeTags := map[string]string{scopeTagClientMethod: methodName, scopeTagClient: clientID}
	ctx = WithScopeTags(ctx, scopeTags)
	req := &ClientHTTPRequest{
		ClientID:       clientID,
		MethodName:     methodName,
		client:         client,
		Logger:         client.loggers[methodName],
		ContextLogger:  NewContextLogger(client.loggers[methodName]),
		defaultHeaders: client.DefaultHeaders,
		ctx:            ctx,
		metrics:        client.contextMetrics,
	}
	req.res = NewClientHTTPResponse(req)
	req.start()
	return req
}

// Start the request, do some metrics book keeping
func (req *ClientHTTPRequest) start() {
	if req.started {
		/* coverage ignore next line */
		req.Logger.Error("Cannot start ClientHTTPRequest twice")
		/* coverage ignore next line */
		return
	}
	req.started = true
	req.startTime = time.Now()
}

// CheckHeaders verifies that the outbound request contains required headers
func (req *ClientHTTPRequest) CheckHeaders(expected []string) error {
	if req.httpReq == nil {
		/* coverage ignore next line */
		panic("must call `req.WriteJSON()` before `req.CheckHeaders()`")
	}

	actualHeaders := req.httpReq.Header

	for _, headerName := range expected {
		// headerName is case insensitive, http.Header Get canonicalize the key
		headerValue := actualHeaders.Get(headerName)
		if headerValue == "" {
			req.Logger.Warn("Got outbound request without mandatory header",
				zap.String("headerName", headerName),
			)

			return errors.New("Missing mandatory header: " + headerName)
		}
	}

	return nil
}

// WriteJSON will send a json http request out.
func (req *ClientHTTPRequest) WriteJSON(
	method, url string,
	headers map[string]string,
	body json.Marshaler,
) error {
	var httpReq *http.Request
	var httpErr error
	if body != nil {
		rawBody, err := body.MarshalJSON()
		if err != nil {
			req.Logger.Error("Could not serialize request json", zap.Error(err))
			return errors.Wrapf(
				err, "Could not serialize %s.%s request json",
				req.ClientID, req.MethodName,
			)
		}
		req.rawBody = rawBody
		httpReq, httpErr = http.NewRequest(method, url, bytes.NewReader(rawBody))
	} else {
		httpReq, httpErr = http.NewRequest(method, url, nil)
	}

	if httpErr != nil {
		req.Logger.Error("Could not create outbound request", zap.Error(httpErr))
		return errors.Wrapf(
			httpErr, "Could not create outbound %s.%s request",
			req.ClientID, req.MethodName,
		)
	}

	// Using `Add` over `Set` intentionally, allowing us to create a list
	// of headerValues for a given key.
	for headerKey, headerValue := range req.filteredDefaultHeaders(req.defaultHeaders, headers) {
		httpReq.Header.Add(headerKey, headerValue)
	}

	for k := range headers {
		httpReq.Header.Add(k, headers[k])
	}

	if body != nil {
		httpReq.Header.Set("Content-Type", "application/json")
	}

	req.httpReq = httpReq
	req.ctx = WithLogFields(req.ctx,
		zap.String(logFieldRequestMethod, method),
		zap.String(logFieldRequestURL, url),
		zap.Time(logFieldRequestStartTime, req.startTime),
	)

	return nil
}

// Do will send the request out.
func (req *ClientHTTPRequest) Do() (*ClientHTTPResponse, error) {
	opName := fmt.Sprintf("%s.%s", req.ClientID, req.MethodName)
	urlTag := opentracing.Tag{Key: "URL", Value: req.httpReq.URL}
	methodTag := opentracing.Tag{Key: "Method", Value: req.httpReq.Method}
	span, ctx := opentracing.StartSpanFromContext(req.ctx, opName, urlTag, methodTag)
	err := req.InjectSpanToHeader(span, opentracing.HTTPHeaders)
	if err != nil {
		/* coverage ignore next line */
		req.Logger.Error("Fail to inject span to headers", zap.Error(err))
		/* coverage ignore next line */
		return nil, err
	}

	logFields := make([]zap.Field, 0, len(req.httpReq.Header))
	for k, v := range req.httpReq.Header {
		logFields = append(logFields, zap.String(fmt.Sprintf("%s-%s", logFieldRequestHeaderPrefix, k), v[0]))
	}
	ctx = WithLogFields(ctx, logFields...)
	req.ctx = ctx

	res, err := req.client.Client.Do(req.httpReq.WithContext(ctx))
	span.Finish()
	if err != nil {
		req.Logger.Error("Could not make outbound request", zap.Error(err))
		return nil, err
	}

	// emit metrics
	req.metrics.IncCounter(req.ctx, clientRequest, 1)

	req.res.setRawHTTPResponse(res)
	return req.res, nil
}

// InjectSpanToHeader will inject span to request header
// This method is current used for unit tests
// TODO: we need to set source and test code as same pkg name which would makes UTs easier
func (req *ClientHTTPRequest) InjectSpanToHeader(span opentracing.Span, format interface{}) error {
	carrier := opentracing.HTTPHeadersCarrier(req.httpReq.Header)
	if err := span.Tracer().Inject(span.Context(), format, carrier); err != nil {
		req.Logger.Error("Failed to inject tracing span.", zap.Error(err))
		return err
	}

	return nil
}

func (req *ClientHTTPRequest) filteredDefaultHeaders(defaultHeaders map[string]string, headers map[string]string) map[string]string {
	filteredDefaultHeaders := make(map[string]string)
	// Copy from the original map to the filtered map
	for key, value := range defaultHeaders {
		filteredDefaultHeaders[key] = value
	}

	sourceHeader := "x-uber-source"
	if filteredDefaultHeaders[sourceHeader] != "" && headers[sourceHeader] != "" {
		delete(filteredDefaultHeaders, sourceHeader)
	}
	return filteredDefaultHeaders
}
<commit_msg>Replaced .add with .set for HTTP request headers<commit_after>// Copyright (c) 2019 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 zanzibar

import (
	"bytes"
	"context"
	"encoding/json"
	"fmt"
	"net/http"
	"time"

	"github.com/opentracing/opentracing-go"
	"github.com/pkg/errors"
	"go.uber.org/zap"
)

// ClientHTTPRequest is the struct for making a single client request using an outbound http client.
type ClientHTTPRequest struct {
	ClientID       string
	MethodName     string
	client         *HTTPClient
	httpReq        *http.Request
	res            *ClientHTTPResponse
	started        bool
	startTime      time.Time
	Logger         *zap.Logger
	ContextLogger  ContextLogger
	rawBody        []byte
	defaultHeaders map[string]string
	ctx            context.Context
	metrics        ContextMetrics
}

// NewClientHTTPRequest allocates a ClientHTTPRequest. The ctx parameter is the context associated with the outbound requests.
func NewClientHTTPRequest(
	ctx context.Context,
	clientID, methodName string,
	client *HTTPClient,
) *ClientHTTPRequest {
	scopeTags := map[string]string{scopeTagClientMethod: methodName, scopeTagClient: clientID}
	ctx = WithScopeTags(ctx, scopeTags)
	req := &ClientHTTPRequest{
		ClientID:       clientID,
		MethodName:     methodName,
		client:         client,
		Logger:         client.loggers[methodName],
		ContextLogger:  NewContextLogger(client.loggers[methodName]),
		defaultHeaders: client.DefaultHeaders,
		ctx:            ctx,
		metrics:        client.contextMetrics,
	}
	req.res = NewClientHTTPResponse(req)
	req.start()
	return req
}

// Start the request, do some metrics book keeping
func (req *ClientHTTPRequest) start() {
	if req.started {
		/* coverage ignore next line */
		req.Logger.Error("Cannot start ClientHTTPRequest twice")
		/* coverage ignore next line */
		return
	}
	req.started = true
	req.startTime = time.Now()
}

// CheckHeaders verifies that the outbound request contains required headers
func (req *ClientHTTPRequest) CheckHeaders(expected []string) error {
	if req.httpReq == nil {
		/* coverage ignore next line */
		panic("must call `req.WriteJSON()` before `req.CheckHeaders()`")
	}

	actualHeaders := req.httpReq.Header

	for _, headerName := range expected {
		// headerName is case insensitive, http.Header Get canonicalize the key
		headerValue := actualHeaders.Get(headerName)
		if headerValue == "" {
			req.Logger.Warn("Got outbound request without mandatory header",
				zap.String("headerName", headerName),
			)

			return errors.New("Missing mandatory header: " + headerName)
		}
	}

	return nil
}

// WriteJSON will send a json http request out.
func (req *ClientHTTPRequest) WriteJSON(
	method, url string,
	headers map[string]string,
	body json.Marshaler,
) error {
	var httpReq *http.Request
	var httpErr error
	if body != nil {
		rawBody, err := body.MarshalJSON()
		if err != nil {
			req.Logger.Error("Could not serialize request json", zap.Error(err))
			return errors.Wrapf(
				err, "Could not serialize %s.%s request json",
				req.ClientID, req.MethodName,
			)
		}
		req.rawBody = rawBody
		httpReq, httpErr = http.NewRequest(method, url, bytes.NewReader(rawBody))
	} else {
		httpReq, httpErr = http.NewRequest(method, url, nil)
	}

	if httpErr != nil {
		req.Logger.Error("Could not create outbound request", zap.Error(httpErr))
		return errors.Wrapf(
			httpErr, "Could not create outbound %s.%s request",
			req.ClientID, req.MethodName,
		)
	}

	// Using `Add` over `Set` intentionally, allowing us to create a list
	// of headerValues for a given key.
	for headerKey, headerValue := range req.defaultHeaders {
		httpReq.Header.Set(headerKey, headerValue)
	}

	for k := range headers {
		httpReq.Header.Set(k, headers[k])
	}

	if body != nil {
		httpReq.Header.Set("Content-Type", "application/json")
	}

	req.httpReq = httpReq
	req.ctx = WithLogFields(req.ctx,
		zap.String(logFieldRequestMethod, method),
		zap.String(logFieldRequestURL, url),
		zap.Time(logFieldRequestStartTime, req.startTime),
	)

	return nil
}

// Do will send the request out.
func (req *ClientHTTPRequest) Do() (*ClientHTTPResponse, error) {
	opName := fmt.Sprintf("%s.%s", req.ClientID, req.MethodName)
	urlTag := opentracing.Tag{Key: "URL", Value: req.httpReq.URL}
	methodTag := opentracing.Tag{Key: "Method", Value: req.httpReq.Method}
	span, ctx := opentracing.StartSpanFromContext(req.ctx, opName, urlTag, methodTag)
	err := req.InjectSpanToHeader(span, opentracing.HTTPHeaders)
	if err != nil {
		/* coverage ignore next line */
		req.Logger.Error("Fail to inject span to headers", zap.Error(err))
		/* coverage ignore next line */
		return nil, err
	}

	logFields := make([]zap.Field, 0, len(req.httpReq.Header))
	for k, v := range req.httpReq.Header {
		logFields = append(logFields, zap.String(fmt.Sprintf("%s-%s", logFieldRequestHeaderPrefix, k), v[0]))
	}
	ctx = WithLogFields(ctx, logFields...)
	req.ctx = ctx

	res, err := req.client.Client.Do(req.httpReq.WithContext(ctx))
	span.Finish()
	if err != nil {
		req.Logger.Error("Could not make outbound request", zap.Error(err))
		return nil, err
	}

	// emit metrics
	req.metrics.IncCounter(req.ctx, clientRequest, 1)

	req.res.setRawHTTPResponse(res)
	return req.res, nil
}

// InjectSpanToHeader will inject span to request header
// This method is current used for unit tests
// TODO: we need to set source and test code as same pkg name which would makes UTs easier
func (req *ClientHTTPRequest) InjectSpanToHeader(span opentracing.Span, format interface{}) error {
	carrier := opentracing.HTTPHeadersCarrier(req.httpReq.Header)
	if err := span.Tracer().Inject(span.Context(), format, carrier); err != nil {
		req.Logger.Error("Failed to inject tracing span.", zap.Error(err))
		return err
	}

	return nil
}
<|endoftext|>


<commit_before>package connector

import "fmt"

//Connector is a class to form a parseable structure from
type Connector struct {
	Type     string
	Literal  string
	Children []Connector
}

//String returns the string representation of the Connector, recursively
func (c Connector) String() string {
	if c.Type == "Literal" {
		return fmt.Sprintf("{%s: %s}", c.Type, c.Literal)
	} else if c.Type == "Neg" && len(c.Children) == 1 {
		return fmt.Sprintf("{%s: %s}", c.Type, c.Children[0])
	}
	return fmt.Sprintf("{%s: %s}", c.Type, c.Children)
}
<commit_msg>full parsing for inputs that don't contain parens()<commit_after>package main

import (
	"fmt"
	"strings"
)

//Connector is a class to form a parseable structure from
type Connector struct {
	Type     string
	Literal  string
	Children []Connector
}

//String returns the string representation of the Connector, recursively
func (c Connector) String() string {
	if c.Type == "Literal" {
		return fmt.Sprintf("{%s: %s}", c.Type, c.Literal)
	} else if c.Type == "Neg" && len(c.Children) == 1 {
		return fmt.Sprintf("{%s: %s}", c.Type, c.Children[0])
	}
	return fmt.Sprintf("{%s: %s}", c.Type, c.Children)
}

//Parse parses a plaintext line into a Connector sequence
func Parse(plaintext string) Connector {
	plaintext = strings.Replace(plaintext, " ", "", -1)

	//special cases for dealing with literals (or negations of literals)
	if len(plaintext) == 1 {
		return Connector{Type: "Literal", Literal: plaintext}
	} else if len(plaintext) == 2 {
		plaintext = strings.Trim(plaintext, "~")
		return Connector{Type: "Neg", Children: []Connector{Connector{Type: "Literal", Literal: plaintext}}}
	}

	connectors := make(map[string]string)
	connectors["^"] = "And"
	connectors["v"] = "Or"
	connectors["<->"] = "Equiv"
	connectors["->"] = "Imp"

	//simple cases: no parens...
	if !strings.Contains(plaintext, "(") {

		for key, op := range connectors {
			if strings.Contains(plaintext, key) {
				splitPlain := strings.Split(plaintext, key)
				children := []Connector{}
				for _, child := range splitPlain {
					children = append(children, Parse(child))
				}
				return Connector{Type: op, Children: children}
			}
		}
	}

	return Connector{}
}

func main() {
	cases := []string{"A", "B", "~A", "A^B", "~A^B", "AvB", "Av~B", "A->B", "A<->B"}
	for _, c := range cases {
		fmt.Println(Parse(c))
	}
}
<|endoftext|>


<commit_before>package tools

import (
	"io/ioutil"
	"net/http"
	"net/url"
	"os"
	"io"
	"bufio"
	"math/rand"
	"time"
	"net"
	"fmt"
	"errors"
)

var ErrBadFmt = errors.New("bad format")
var ErrNoSuch = errors.New("no such")
var ErrDupData = errors.New("dup data")

func RandStr(w int) string {
	rand.Seed(time.Now().UnixNano())
	base := "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
	str := ""
	for i := 0;i < w;i ++ {
		idx := rand.Int31n(int32(len(base)))
		str = str + string(base[idx])
	}
	return str
}

func ReadFile(fn string) ([]byte, error) {
	file, err := os.Open(fn)
	if err != nil {
		return nil, err
	}
	defer file.Close()
	return ioutil.ReadAll(file)
}

func DoPost(url string, v *url.Values) ([]byte, error) {
	resp, err := http.PostForm(url, *v)
	if err != nil {
		return nil, err
	}
	defer resp.Body.Close()
	return ioutil.ReadAll(resp.Body)
}

func DoGet(url string) ([]byte, error) {
	resp, err := http.Get(url)
	if err != nil {
		return nil, err
	}
	defer resp.Body.Close()
	return ioutil.ReadAll(resp.Body)
}

type LineFunc func (line string) error

func ReadLine(fn string, lf LineFunc) error {
	file, err := os.Open(fn)
	if err != nil {
		return err
	}
	defer file.Close()
	rd := bufio.NewReader(file)
	for {
		line, err := rd.ReadString('\n')
		if err != nil && err != io.EOF {
			return err
		}
		if err == io.EOF {
			break
		}
		if line == "" {
			continue
		}
		line = line[:len(line) - 1]
		err = lf(line)
		if err != nil {
			return err
		}
	}
	return nil
}

func Proxy(c *net.TCPConn) {
	defer c.Close()
	now := time.Now()
	fmt.Println(now, "we get an conn from", c.RemoteAddr())
	fmt.Println(now, "and we are going to 119.28.77.61:8000...")
	var raddr net.TCPAddr
	raddr.IP = net.ParseIP("119.28.77.61")
	raddr.Port = 8000
	r, err := net.DialTCP("tcp4", nil, &raddr)
	if err != nil {
		fmt.Println("dial remote", err)
		return
	}
	go io.Copy(c, r)
	io.Copy(r, c)
}

func Run() error {
	var addr net.TCPAddr
	addr.Port = 8080
	ls, err := net.ListenTCP("tcp4", &addr)
	if err != nil {
		return err
	}
	for {
		c, err := ls.AcceptTCP()
		if err != nil {
			fmt.Println("accept error", err)
			continue
		}
		go Proxy(c)
	}
}
<commit_msg>add error types<commit_after>package tools

import (
	"bufio"
	"fmt"
	"io"
	"io/ioutil"
	"math/rand"
	"net"
	"net/http"
	"net/url"
	"os"
	"time"
	"errors"
)

var ErrBadFmt = errors.New("bad format")
var ErrNoSuch = errors.New("no such")
var ErrDupData = errors.New("dup data")

func RandInt(w int) int32 {
	rand.Seed(time.Now().UnixNano())
	return rand.Int31n(int32(w))
}

func RandStr(w int) string {
	rand.Seed(time.Now().UnixNano())
	base := "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
	str := ""
	for i := 0; i < w; i++ {
		idx := rand.Int31n(int32(len(base)))
		str = str + string(base[idx])
	}
	return str
}

func ReadFile(fn string) ([]byte, error) {
	file, err := os.Open(fn)
	if err != nil {
		return nil, err
	}
	defer file.Close()
	return ioutil.ReadAll(file)
}

func DoPost(url string, v *url.Values) ([]byte, error) {
	resp, err := http.PostForm(url, *v)
	if err != nil {
		return nil, err
	}
	defer resp.Body.Close()
	return ioutil.ReadAll(resp.Body)
}

func DoGet(url string) ([]byte, error) {
	resp, err := http.Get(url)
	if err != nil {
		return nil, err
	}
	defer resp.Body.Close()
	return ioutil.ReadAll(resp.Body)
}

type LineFunc func(line string) error

func ReadLine(fn string, lf LineFunc) error {
	file, err := os.Open(fn)
	if err != nil {
		return err
	}
	defer file.Close()
	rd := bufio.NewReader(file)
	for {
		line, err := rd.ReadString('\n')
		if err != nil && err != io.EOF {
			return err
		}
		if err == io.EOF {
			break
		}
		if line == "" {
			continue
		}
		line = line[:len(line)-1]
		err = lf(line)
		if err != nil {
			return err
		}
	}
	return nil
}

func Proxy(c *net.TCPConn) {
	defer c.Close()
	now := time.Now()
	fmt.Println(now, "we get an conn from", c.RemoteAddr())
	fmt.Println(now, "and we are going to 119.28.77.61:8000...")
	var raddr net.TCPAddr
	raddr.IP = net.ParseIP("119.28.77.61")
	raddr.Port = 8000
	r, err := net.DialTCP("tcp4", nil, &raddr)
	if err != nil {
		fmt.Println("dial remote", err)
		return
	}
	go io.Copy(c, r)
	io.Copy(r, c)
}

func Run() error {
	var addr net.TCPAddr
	addr.Port = 8080
	ls, err := net.ListenTCP("tcp4", &addr)
	if err != nil {
		return err
	}
	for {
		c, err := ls.AcceptTCP()
		if err != nil {
			fmt.Println("accept error", err)
			continue
		}
		go Proxy(c)
	}
}
<|endoftext|>


<commit_before>package main

import (
	"log"
	"math/rand"
	"github.com/astaxie/beego"
	"github.com/astaxie/beego/orm"

	_ "github.com/go-sql-driver/mysql"
	//"runtime"
)

const (
	// Database
	connectionString   = "benchmarkdbuser:benchmarkdbpass@tcp(localhost:3306)/hello_world"
	worldRowCount      = 10000
	macIdleConnection  = 30
	maxConnectionCount = 256

	helloWorldString = "Hello, World!"
)

var (
	helloWorldBytes = []byte(helloWorldString)
)

type MessageStruct struct {
	Message string `json:"message"`
}

type World struct {
	Id           uint16 `orm:"pk" json:"id"`
	RandomNumber uint16 `orm:"column(randomNumber)" json:"randomNumber"`
}

type JsonController struct {
	beego.Controller
}

func (this *JsonController) Get() {
	m := MessageStruct{"Hello, World!"}
	this.Data["json"] = &m
	this.ServeJson()
}

type PlaintextController struct {
	beego.Controller
}

func (this *PlaintextController) Get() {
	this.Ctx.Output.Header("Content-Type", "text/plain")
	this.Ctx.Output.Body(helloWorldBytes)
}

type DBController struct {
	beego.Controller
}

func (this *DBController) Get() {
	o := orm.NewOrm()
	w := World{Id: uint16(rand.Intn(worldRowCount) + 1)}
	err := o.Read(&w)
	if err != nil {
		log.Fatalf("Error read world row: %s", err.Error())
	}
	this.Data["json"] = &w
	this.ServeJson()
}

func main() {
	//don't need this set, beego default set it
	//runtime.GOMAXPROCS(runtime.NumCPU())
	beego.RunMode = "prod"
	beego.Router("/json", &JsonController{})
	beego.Router("/db", &DBController{})
	beego.Router("/plaintext", &PlaintextController{})
	beego.Run()
}

func init() {
	orm.RegisterModel(new(World))
	orm.RegisterDataBase("default", "mysql", connectionString, macIdleConnection, maxConnectionCount)
}
<commit_msg>bee fix<commit_after>package main

import (
	"log"
	"math/rand"
	"github.com/astaxie/beego"
	"github.com/astaxie/beego/orm"

	_ "github.com/go-sql-driver/mysql"
	//"runtime"
)

const (
	// Database
	connectionString   = "benchmarkdbuser:benchmarkdbpass@tcp(localhost:3306)/hello_world"
	worldRowCount      = 10000
	macIdleConnection  = 30
	maxConnectionCount = 256

	helloWorldString = "Hello, World!"
)

var (
	helloWorldBytes = []byte(helloWorldString)
)

type MessageStruct struct {
	Message string `json:"message"`
}

type World struct {
	Id           uint16 `orm:"pk" json:"id"`
	RandomNumber uint16 `orm:"column(randomNumber)" json:"randomNumber"`
}

type JsonController struct {
	beego.Controller
}

func (this *JsonController) Get() {
	m := MessageStruct{"Hello, World!"}
	this.Data["json"] = &m
	this.ServeJSON()
}

type PlaintextController struct {
	beego.Controller
}

func (this *PlaintextController) Get() {
	this.Ctx.Output.Header("Content-Type", "text/plain")
	this.Ctx.Output.Body(helloWorldBytes)
}

type DBController struct {
	beego.Controller
}

func (this *DBController) Get() {
	o := orm.NewOrm()
	w := World{Id: uint16(rand.Intn(worldRowCount) + 1)}
	err := o.Read(&w)
	if err != nil {
		log.Fatalf("Error read world row: %s", err.Error())
	}
	this.Data["json"] = &w
	this.ServeJSON()
}

func main() {
	//don't need this set, beego default set it
	//runtime.GOMAXPROCS(runtime.NumCPU())
	beego.BConfig.RunMode = "prod"
	beego.Router("/json", &JsonController{})
	beego.Router("/db", &DBController{})
	beego.Router("/plaintext", &PlaintextController{})
	beego.Run()
}

func init() {
	orm.RegisterModel(new(World))
	orm.RegisterDataBase("default", "mysql", connectionString, macIdleConnection, maxConnectionCount)
}
<|endoftext|>


<commit_before>/* Package guard provides a simple construct to help you write a RAII-like
construct in Go.

Go doesn't provide a deterministic way to fire code at garbage collection
time, but you can sort of do it when `defer` gets fired.

	func Foo() {
		defer CleanupCode()

		...
	}

The guard package gives you one more additional layer of functionality.
For example, if you're doing a database operation, you might want to
register a `Rollback()` call, only to make sure that in case you return
before committing, you make sure your previous operations are discarded:

	func DatabaseOperation(db *sql.DB) {
		tx := db.Begin()
		defer tx.Rollback()

		... // database operation that may fail
		if err != nil {
			return
		}

		tx.Commit()
	}

Except, if the operation is successful, you will be calling `Commit()`
and then `Rollback()`, which causes an error. So you would need to keep track
if you have actually called `Commit()`

	func DatabaseOperation(db *sql.DB) {
		tx := db.Begin()
		commited := false
		defer func() {
			if commited {
				return
			}
			tx.Rollback()
		}

		... // database operation that may fail
		if err != nil {
			return
		}

		tx.Commit()
		commited = true
	}

This is doable, but you probably don't want to do that all over the place.

This is where this package comes in. The `Guard` interface
specifies `Fire()` and `Cancel()`, which makes the above construct
easier:

	func DatabaseOperation(db *sql.DB) {
		tx := db.Begin()
		g := guard.Callback(func() error {
			return tx.Rollback()
		})
		defer g.Fire()

		... // database operation that may fail
		if err != nil {
			return
		}

		if err := tx.Commit(); err != nil {
			// If the commit is successful, we don't need to
			// rollback, so cancel the guard.
			return g.Cancel()
		}
	}

Once `Fire()` or `Cancel()` is called, the Guard never fires again, so
you can safely use it both in the success and failure cases.

Please also see: https://github.com/lestrrat/go-tx-guard

*/
package guard

func (ng nilGuard) Fire() error   { return nil }
func (ng nilGuard) Cancel() error { return nil }

// Callback creates a new callback based guard.
func Callback(onFire func() error) *CB {
	return &CB{
		onFire: onFire,
	}
}

// NewCB is a deprecated constructor. Please use `Callback`
func NewCB(onFire func() error) *CB {
	return Callback(onFire)
}

func (c *CB) matchState(st int8) bool {
	c.mutex.Lock()
	defer c.mutex.Unlock()
	return c.state&st == st
}

func (c *CB) setState(st int8) {
	c.mutex.Lock()
	defer c.mutex.Unlock()
	c.state = c.state ^ st
}

// Fire executes the registered callback, only if the guard has not
// previously fired, and has not been canceled. The return value is
// nil if the callback successfully fired, and the callback did not
// return any errors.
func (c *CB) Fire() error {
	if c.matchState(stCanceled) {
		return errCanceled
	}
	if c.matchState(stFired) {
		return errFired
	}

	defer c.setState(stFired)
	if cb := c.onFire; cb != nil {
		return cb()
	}
	return nil
}

// Cancel sets the cancel flag so that subsequen calls to `Fire()`
// does not cause the callback to execute. It will return errors
// if the guard has already been fired or canceled.
func (c *CB) Cancel() error {
	if c.matchState(stCanceled) {
		return errCanceled
	}
	if c.matchState(stFired) {
		return errFired
	}

	c.setState(stCanceled)
	return nil
}
<commit_msg>docs: again, see if this works<commit_after>// Package guard provides a simple construct to help you write a RAII-like construct in Go.
//
// Go doesn't provide a deterministic way to fire code at garbage collection
// time, but you can sort of do it when `defer` gets fired.
//
// 	func Foo() {
// 		defer CleanupCode()
//
// 		...
// 	}
//
// The guard package gives you one more additional layer of functionality.
// For example, if you're doing a database operation, you might want to
// register a `Rollback()` call, only to make sure that in case you return
// before committing, you make sure your previous operations are discarded:
//
// 	func DatabaseOperation(db *sql.DB) {
// 		tx := db.Begin()
// 		defer tx.Rollback()
//
// 		... // database operation that may fail
// 		if err != nil {
// 			return
// 		}
//
// 		tx.Commit()
// 	}
//
// Except, if the operation is successful, you will be calling `Commit()`
// and then `Rollback()`, which causes an error. So you would need to keep track
// if you have actually called `Commit()`
//
// 	func DatabaseOperation(db *sql.DB) {
// 		tx := db.Begin()
// 		commited := false
// 		defer func() {
// 			if commited {
// 				return
// 			}
// 			tx.Rollback()
// 		}
//
// 		... // database operation that may fail
// 		if err != nil {
// 			return
// 		}
//
// 		tx.Commit()
// 		commited = true
// 	}
//
// This is doable, but you probably don't want to do that all over the place.
//
// This is where this package comes in. The `Guard` interface
// specifies `Fire()` and `Cancel()`, which makes the above construct
// easier:
//
// 	func DatabaseOperation(db *sql.DB) {
// 		tx := db.Begin()
// 		g := guard.Callback(func() error {
// 			return tx.Rollback()
// 		})
// 		defer g.Fire()
//
// 		... // database operation that may fail
// 		if err != nil {
// 			return
// 		}
//
// 		if err := tx.Commit(); err != nil {
// 			// If the commit is successful, we don't need to
// 			// rollback, so cancel the guard.
// 			return g.Cancel()
// 		}
// 	}
//
// Once `Fire()` or `Cancel()` is called, the Guard never fires again, so
// you can safely use it both in the success and failure cases.
//
// Please also see: https://github.com/lestrrat/go-tx-guard
package guard

func (ng nilGuard) Fire() error   { return nil }
func (ng nilGuard) Cancel() error { return nil }

// Callback creates a new callback based guard.
func Callback(onFire func() error) *CB {
	return &CB{
		onFire: onFire,
	}
}

// NewCB is a deprecated constructor. Please use `Callback`
func NewCB(onFire func() error) *CB {
	return Callback(onFire)
}

func (c *CB) matchState(st int8) bool {
	c.mutex.Lock()
	defer c.mutex.Unlock()
	return c.state&st == st
}

func (c *CB) setState(st int8) {
	c.mutex.Lock()
	defer c.mutex.Unlock()
	c.state = c.state ^ st
}

// Fire executes the registered callback, only if the guard has not
// previously fired, and has not been canceled. The return value is
// nil if the callback successfully fired, and the callback did not
// return any errors.
func (c *CB) Fire() error {
	if c.matchState(stCanceled) {
		return errCanceled
	}
	if c.matchState(stFired) {
		return errFired
	}

	defer c.setState(stFired)
	if cb := c.onFire; cb != nil {
		return cb()
	}
	return nil
}

// Cancel sets the cancel flag so that subsequen calls to `Fire()`
// does not cause the callback to execute. It will return errors
// if the guard has already been fired or canceled.
func (c *CB) Cancel() error {
	if c.matchState(stCanceled) {
		return errCanceled
	}
	if c.matchState(stFired) {
		return errFired
	}

	c.setState(stCanceled)
	return nil
}
<|endoftext|>


<commit_before><commit_msg>Update: start exec timeout changed to 5s (for heavy-load docker host) Add: when event trigger, loop until get ip from exec or timeout happens<commit_after><|endoftext|>


<commit_before>package main

import "fmt"

func main() {
	fmt.Println("Hello, ??")
}<commit_msg>Update hello.go<commit_after>package main

import "fmt"

func main() {
	fmt.Println("Hello, ??")
	fmt.Println("Heisann")
}
<|endoftext|>


<commit_before>package main

import (
	"bufio"
	"encoding/json"
	"fmt"
	"github.com/GeertJohan/go.rice"
	"github.com/codegangsta/negroni"
	"github.com/gorilla/mux"
	"github.com/gorilla/websocket"
	"log"
	"net"
	"net/http"
	"os"
	"runtime"
	"strings"
)

var conns []*websocket.Conn

type User struct {
	Id   int
	Name string
	Age  int
}

type postBodySwitchMode struct {
	Address string `json: address`
	Mode    string `json: mode`
}

var upgrader = websocket.Upgrader{
	ReadBufferSize:  1024,
	WriteBufferSize: 1024,
}

// Format command for settings a input to multiple outputs
func inputToOutputs(input int, outputs ...int) string {
	command := fmt.Sprintf("x%dAV", input)
	outputStrs := make([]string, len(outputs))
	for i, output := range outputs {
		outputStrs[i] = fmt.Sprintf("x%d", output)
	}
	return command + strings.Join(outputStrs, ",")
}

func sendSignal(address string, commands []string) {
	logNPush(fmt.Sprintf("Sending signals... -> %s\n", address))

	logNPush(fmt.Sprintf("Dialing %s...", address))

	conn, err := net.Dial("tcp", address)
	if nil != err {
		logNPush(err.Error())
		return
	}

	defer conn.Close()

	readBuffer := bufio.NewReader(conn)

	for _, command := range commands {
		logNPush("-> " + command)
		fmt.Fprintln(conn, command)
		response, err := readBuffer.ReadString('\n')
		if err != nil {
			logNPush("<- " + err.Error())
		} else {
			logNPush("<- " + response)
		}
	}
}

func logNPush(line string) {
	log.Println(line)
	pushLine(line)
}

func pushLine(line string) {
	for _, conn := range conns {
		err := conn.WriteMessage(websocket.TextMessage, []byte(line))
		if nil != err {
			log.Println(err)
		}
	}
}

func switchMode(mode, address string) {
	log.Println("Switching mode...", mode, address)
	if mode == "apple-tv" {
		sendSignal(address, []string{
			inputToOutputs(2, 1, 2),
		})
	} else if mode == "imac" {
		sendSignal(address, []string{
			inputToOutputs(1, 1, 2),
		})
	} else if mode == "chromecast" {
		sendSignal(address, []string{
			inputToOutputs(3, 1, 2),
		})
	}
}

func toJson(data interface{}) string {
	json, _ := json.MarshalIndent(data, "", "  ")
	return string(json)
}

func main() {
	log.Println("Starting...")
	runtime.GOMAXPROCS(runtime.NumCPU())

	r := mux.NewRouter()

	r.HandleFunc("/socket", func(w http.ResponseWriter, req *http.Request) {
		conn, err := upgrader.Upgrade(w, req, nil)
		if err != nil {
			log.Println(err)
			return
		}

		conns = append(conns, conn)
	})

	r.Methods("POST").Path("/switch-mode").HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
		var post postBodySwitchMode
		dec := json.NewDecoder(req.Body)
		err := dec.Decode(&post)

		if err != nil {
			log.Println(err)
			http.Error(w, err.Error(), http.StatusInternalServerError)
			return
		}

		switchMode(post.Mode, post.Address)
	})

	n := negroni.New(
		negroni.NewRecovery(),
		negroni.NewLogger(),
		negroni.NewStatic(rice.MustFindBox("public").HTTPBox()),
	)
	n.UseHandler(r)
	listen := os.Getenv("LISTEN")
	if listen == "" {
		listen = ":3000"
	}
	n.Run(listen)
}
<commit_msg>Send CR and ignore first two response lines<commit_after>package main

import (
	"bufio"
	"encoding/json"
	"fmt"
	"github.com/GeertJohan/go.rice"
	"github.com/codegangsta/negroni"
	"github.com/gorilla/mux"
	"github.com/gorilla/websocket"
	"log"
	"net"
	"net/http"
	"os"
	"runtime"
	"strings"
)

var conns []*websocket.Conn

type User struct {
	Id   int
	Name string
	Age  int
}

type postBodySwitchMode struct {
	Address string `json: address`
	Mode    string `json: mode`
}

var upgrader = websocket.Upgrader{
	ReadBufferSize:  1024,
	WriteBufferSize: 1024,
}

// Format command for settings a input to multiple outputs
func inputToOutputs(input int, outputs ...int) string {
	command := fmt.Sprintf("x%dAV", input)
	outputStrs := make([]string, len(outputs))
	for i, output := range outputs {
		outputStrs[i] = fmt.Sprintf("x%d", output)
	}
	return command + strings.Join(outputStrs, ",")
}

func sendSignal(address string, commands []string) {
	logNPush(fmt.Sprintf("Sending signals... -> %s\n", address))

	logNPush(fmt.Sprintf("Dialing %s...", address))

	conn, err := net.Dial("tcp", address)
	if nil != err {
		logNPush(err.Error())
		return
	}

	defer conn.Close()

	readBuffer := bufio.NewReader(conn)

	logNPush("// Reading some lines")

	for i := 0; i < 2; i++ {
		response, err := readBuffer.ReadString('\n')
		if nil != err {
			logNPush(err.Error())
		}

		logNPush(response)
	}

	logNPush("// Read some lines...")

	for _, command := range commands {
		logNPush("-> " + command)
		fmt.Fprintln(conn, command+"\r")

		// Discard two lines
		_, err := readBuffer.ReadString('\n')
		_, err = readBuffer.ReadString('\n')
		response, err := readBuffer.ReadString('\n')

		if err != nil {
			logNPush("<- " + err.Error())
		} else {
			logNPush("<- " + response)
		}
	}
}

func logNPush(line string) {
	log.Println(line)
	pushLine(line)
}

func pushLine(line string) {
	for _, conn := range conns {
		err := conn.WriteMessage(websocket.TextMessage, []byte(line))
		if nil != err {
			log.Println(err)
		}
	}
}

func switchMode(mode, address string) {
	log.Println("Switching mode...", mode, address)
	if mode == "apple-tv" {
		sendSignal(address, []string{
			inputToOutputs(2, 1, 2),
		})
	} else if mode == "imac" {
		sendSignal(address, []string{
			inputToOutputs(1, 1, 2),
		})
	} else if mode == "chromecast" {
		sendSignal(address, []string{
			inputToOutputs(3, 1, 2),
		})
	}
}

func toJson(data interface{}) string {
	json, _ := json.MarshalIndent(data, "", "  ")
	return string(json)
}

func main() {
	log.Println("Starting...")
	runtime.GOMAXPROCS(runtime.NumCPU())

	r := mux.NewRouter()

	r.HandleFunc("/socket", func(w http.ResponseWriter, req *http.Request) {
		conn, err := upgrader.Upgrade(w, req, nil)
		if err != nil {
			log.Println(err)
			return
		}

		conns = append(conns, conn)
	})

	r.Methods("POST").Path("/switch-mode").HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
		var post postBodySwitchMode
		dec := json.NewDecoder(req.Body)
		err := dec.Decode(&post)

		if err != nil {
			log.Println(err)
			http.Error(w, err.Error(), http.StatusInternalServerError)
			return
		}

		switchMode(post.Mode, post.Address)
	})

	n := negroni.New(
		negroni.NewRecovery(),
		negroni.NewLogger(),
		negroni.NewStatic(rice.MustFindBox("public").HTTPBox()),
	)
	n.UseHandler(r)
	listen := os.Getenv("LISTEN")
	if listen == "" {
		listen = ":3000"
	}
	n.Run(listen)
}
<|endoftext|>


<commit_before>package main

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

func main() {
  http.HandleFunc("/", hello)
  port := os.Getenv("PORT")
  if port == "" {
    port = "5000"
  }
  fmt.Println("listening", port)
  err := http.ListenAndServe(":5000", nil)
  if err != nil {
    panic(err)
  }
}

func hello(res http.ResponseWriter, req *http.Request) {
  fmt.Fprintln(res, "hello, world")
}<commit_msg>Add exclaimation point<commit_after>package main

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

func main() {
  http.HandleFunc("/", hello)
  port := os.Getenv("PORT")
  if port == "" {
    port = "5000"
  }
  fmt.Println("listening", port)
  err := http.ListenAndServe(":5000", nil)
  if err != nil {
    panic(err)
  }
}

func hello(res http.ResponseWriter, req *http.Request) {
  fmt.Fprintln(res, "hello, world!")
}<|endoftext|>