<commit_before>package http

import (
	"bytes"
	"compress/flate"
	"compress/gzip"
	"encoding/json"
	"fmt"
	"io"
	"io/ioutil"
	"log"
	"net/http"
	"net/url"
	"path"
	"reflect"
	"strconv"
	"strings"
	"text/template"

	c "github.com/d0ngw/go/common"
)

// RequestError is the http request response error
type RequestError struct {
	Status int
	Err    error
}

func (p *RequestError) Error() string {
	return fmt.Sprintf("status:%d,data:%s", p.Status, p.Err)
}

// CheckRequestError if err is RequestError,then return response status code
func CheckRequestError(err error) (status int, ok bool) {
	if err == nil {
		return
	}
	if e, ok := err.(*RequestError); ok {
		return e.Status, true
	}
	return
}

// RedirectError redirect error
type RedirectError struct {
	RedirectURL string
}

func (p *RedirectError) Error() string {
	return fmt.Sprintf("redirect:%s", p.RedirectURL)
}

// CheckRedirectError if err is RedirectError ,then return redirect error
func CheckRedirectError(err error) (url string, ok bool) {
	if err == nil {
		return
	}
	if e, ok := err.(*RedirectError); ok {
		return e.RedirectURL, true
	}
	return
}

// NewRedirectError redirect error
func NewRedirectError(req *http.Request, via []*http.Request) error {
	return &RedirectError{
		RedirectURL: req.URL.String(),
	}
}

// Resp JSON Http响应
type Resp struct {
	Success bool        `json:"success"`
	Data    interface{} `json:"data"`
	Msg     string      `json:"msg"`
}

// NewSuccResp 构建成功的响应
func NewSuccResp(data interface{}) *Resp {
	return &Resp{
		Success: true,
		Data:    data,
	}
}

// NewFailResp 构建失败的响应
func NewFailResp(msg string) *Resp {
	return &Resp{
		Success: false,
		Msg:     msg,
	}
}

// ResponseHandler 响应处理
type ResponseHandler struct {
	Success bool
	Data    interface{}
	Msg     string
	w       http.ResponseWriter
}

// SuccessWithData 设置成功及数据
func (p *ResponseHandler) SuccessWithData(data interface{}) {
	p.Success = true
	p.Data = data
}

// FailWithMsg 设置失败及出错的消息
func (p *ResponseHandler) FailWithMsg(msg string) {
	p.Success = false
	p.Msg = msg
}

func (p *ResponseHandler) Run() {
	if !p.Success {
		RenderJSON(p.w, &Resp{Success: false, Msg: p.Msg})
	} else {
		RenderJSON(p.w, &Resp{Success: true, Data: p.Data})
	}
}

// NewResponseHandler 构建响应处理
func NewResponseHandler(w http.ResponseWriter) *ResponseHandler {
	return &ResponseHandler{
		w: w,
	}
}

var (
	errNoparam = fmt.Errorf("missing param")
)

// GetParameter 取得由name指定的参数值
func GetParameter(r url.Values, name string) string {
	return strings.TrimSpace(r.Get(name))
}

func getIntParameter(r url.Values, name string, bitSize int) (val int64, err error) {
	value := GetParameter(r, name)
	if value == "" {
		return 0, errNoparam
	}
	val, err = strconv.ParseInt(value, 10, bitSize)
	return
}

// GetInt64Parameter 取得由name指定的64位整数参数值
func GetInt64Parameter(r url.Values, name string) (val int64, err error) {
	val, err = getIntParameter(r, name, 64)
	return
}

// GetInt32Parameter 取得由name指定的32位整数参数值
func GetInt32Parameter(r url.Values, name string) (val int32, err error) {
	val64, err := getIntParameter(r, name, 32)
	if err == nil {
		return int32(val64), nil
	}
	return 0, err
}

func getFloatParameter(r url.Values, name string, bitSize int) (val float64, err error) {
	value := GetParameter(r, name)
	if value == "" {
		return 0, errNoparam
	}
	val, err = strconv.ParseFloat(value, bitSize)
	return
}

// GetFloat64Parameter 取得由name指定的64位浮点数参数值
func GetFloat64Parameter(r url.Values, name string) (val float64, err error) {
	val, err = getFloatParameter(r, name, 64)
	return
}

// GetFloat32Parameter 取得由name指定的32位浮点数参数值
func GetFloat32Parameter(r url.Values, name string) (val float32, err error) {
	val64, err := getFloatParameter(r, name, 32)
	if err == nil {
		return float32(val64), nil
	}
	return 0, err
}

// RenderTemplate 渲染模板
func RenderTemplate(w http.ResponseWriter, templateDir, tmpl string, data interface{}) {
	templatePath := path.Join(templateDir, tmpl+".html")
	t, err := template.ParseFiles(templatePath)
	if err != nil {
		log.Printf("Parse template err:%s\n", err)
		http.Error(w, err.Error(), http.StatusInternalServerError)
	}
	if err := t.Execute(w, data); err != nil {
		log.Printf("Execute template err:%s\n", err)
		http.Error(w, err.Error(), http.StatusInternalServerError)
	}
}

// RenderJSON 渲染JSON
func RenderJSON(w http.ResponseWriter, jsonData interface{}) {
	w.Header().Set("Content-Type", "application/json; charset=utf-8")
	encoder := json.NewEncoder(w)
	encoder.SetEscapeHTML(false)
	err := encoder.Encode(jsonData)
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
}

// RenderText 渲染Text
func RenderText(w http.ResponseWriter, text string) {
	w.Header().Set("Content-Type", "text/plain; charset=utf-8")
	w.Write([]byte(text))
}

// GetURL 请求URL
func GetURL(client *http.Client, url string, params url.Values) (string, error) {
	return GetURLWithCookie(client, url, params, nil)
}

// GetURLWithCookie 请求URL
func GetURLWithCookie(client *http.Client, url string, params url.Values, cookies map[string]string) (string, error) {
	_, body, err := GetURLRaw(client, url, params, nil, cookies)
	if err != nil {
		return "", err
	}
	return string(body), nil
}

// GetURLRawToWriter 请求URL
func GetURLRawToWriter(client *http.Client, url string, params url.Values, reqHeader http.Header, cookies map[string]string, writer io.Writer) (header http.Header, err error) {
	var req *http.Request
	if params != nil {
		req, err = http.NewRequest("GET", url+"?"+params.Encode(), nil)
	} else {
		req, err = http.NewRequest("GET", url, nil)
	}
	if err != nil {
		return nil, err
	}
	if reqHeader != nil {
		req.Header = reqHeader
	}
	for k, v := range cookies {
		req.AddCookie(&http.Cookie{Name: k, Value: v})
	}
	resp, err := client.Do(req)
	if err != nil {
		e := &RequestError{Err: err}
		if resp != nil {
			e.Status = resp.StatusCode
		}
		return nil, e
	}
	if resp.Body != nil {
		defer resp.Body.Close()
	}
	if resp.StatusCode != 200 {
		return nil, &RequestError{Status: resp.StatusCode}
	}
	contentEncoding := resp.Header.Get("Content-Encoding")
	switch contentEncoding {
	case "gzip":
		fallthrough
	case "deflate":
		var (
			reader io.ReadCloser
			err    error
		)
		if contentEncoding == "gzip" {
			reader, err = gzip.NewReader(resp.Body)
		} else if contentEncoding == "deflate" {
			reader = flate.NewReader(resp.Body)
		}
		if err != nil {
			return nil, err
		}
		if reader == nil {
			return nil, fmt.Errorf("no uncompress reader")
		}
		defer reader.Close()
		_, err = io.Copy(writer, reader)
		if err != nil {
			return nil, err
		}
	default:
		_, err = io.Copy(writer, resp.Body)
		if err != nil {
			return nil, err
		}
	}
	return resp.Header, nil
}

// GetURLRaw 请求URL
func GetURLRaw(client *http.Client, url string, params url.Values, reqHeader http.Header, cookies map[string]string) (header http.Header, body []byte, err error) {
	var writer = &bytes.Buffer{}
	header, err = GetURLRawToWriter(client, url, params, reqHeader, cookies, writer)
	if err != nil {
		return header, nil, err
	}
	return header, writer.Bytes(), nil
}

// PostURL 请求URL
func PostURL(client *http.Client, url string, params url.Values, contentType string, requestBody io.Reader) ([]byte, http.Header, error) {
	return PostURLWithCookie(client, url, params, contentType, requestBody, nil)
}

// PostURLWithCookie 请求URL
func PostURLWithCookie(client *http.Client, url string, params url.Values, contentType string, requestBody io.Reader, cookies map[string]string) ([]byte, http.Header, error) {
	if requestBody == nil {
		requestBody = strings.NewReader(params.Encode())
	} else {
		url = url + "?" + params.Encode()
	}

	req, err := http.NewRequest("POST", url, requestBody)
	if err != nil {
		return nil, nil, err
	}
	if contentType != "" {
		req.Header.Set("Content-Type", contentType)
	}
	for k, v := range cookies {
		req.AddCookie(&http.Cookie{Name: k, Value: v})
	}

	resp, err := client.Do(req)
	if err != nil {
		return nil, nil, err
	}
	if resp.Body != nil {
		defer resp.Body.Close()
	}
	if resp.StatusCode != 200 {
		return nil, nil, &RequestError{Status: resp.StatusCode}
	}
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return nil, nil, err
	}
	return body, resp.Header, nil
}

// ParseParams 从r中解析参数,并填充到dest中,params应该是struct指针
func ParseParams(r url.Values, dest interface{}) error {
	if r == nil || dest == nil {
		return fmt.Errorf("invalid args")
	}

	val, ind, typ := c.ExtractRefTuple(dest)
	if val.Kind() != reflect.Ptr {
		return fmt.Errorf("Expect ptr ,but it's %s", val.Kind())
	}
	if typ.Kind() != reflect.Struct {
		return fmt.Errorf("Expect struct,but it's %s", typ.Kind())
	}

	for i := 0; i < ind.NumField(); i++ {
		field := typ.Field(i)
		tag := field.Tag
		paramName := tag.Get("pname")
		if paramName == "" {
			paramName = ToUnderlineName(field.Name)
		}

		if paramName == "_" {
			continue
		}

		fieldVal := ind.Field(i)
		switch field.Type.Kind() {
		case reflect.Int:
			fallthrough
		case reflect.Int8:
			fallthrough
		case reflect.Int16:
			fallthrough
		case reflect.Int32:
			fallthrough
		case reflect.Int64:
			if val64, err := getIntParameter(r, paramName, 64); err == nil {
				fieldVal.SetInt(val64)
			}
		case reflect.Float32:
			fallthrough
		case reflect.Float64:
			if val64, err := getFloatParameter(r, paramName, 64); err == nil {
				fieldVal.SetFloat(val64)
			}
		case reflect.String:
			fieldVal.SetString(GetParameter(r, paramName))
		case reflect.Bool:
			v := strings.ToLower(GetParameter(r, paramName))
			fieldVal.SetBool(v == "1" || v == "y" || v == "true")
		case reflect.Slice:
			paramSep := tag.Get("psep")
			var vals []string
			if paramSep == "" {
				if ps, ok := r[paramName]; ok {
					vals = c.TrimOmitEmpty(ps)
				}
			} else {
				vals = c.SplitTrimOmitEmpty(GetParameter(r, paramName), paramSep)
			}

			strSlice := c.StringSlice(vals)
			var elem = field.Type.Elem()
			switch elem.Kind() {
			case reflect.String:
				fieldVal.Set(reflect.ValueOf(vals))
			case reflect.Int32:
				if intSlice, err := strSlice.ToInt32(); err == nil {
					fieldVal.Set(reflect.ValueOf(intSlice))
				}
			case reflect.Int64:
				if intSlice, err := strSlice.ToInt64(); err == nil {
					fieldVal.Set(reflect.ValueOf(intSlice))
				}
			case reflect.Float32:
				if intSlice, err := strSlice.ToFloat32(); err == nil {
					fieldVal.Set(reflect.ValueOf(intSlice))
				}
			case reflect.Float64:
				if intSlice, err := strSlice.ToFloat64(); err == nil {
					fieldVal.Set(reflect.ValueOf(intSlice))
				}
			default:
				return fmt.Errorf("Unsupported type %s", elem.Kind())
			}
		case reflect.Struct:
			if fieldVal.IsValid() && fieldVal.CanInterface() && fieldVal.CanAddr() {
				ParseParams(r, fieldVal.Addr().Interface())
			} else {
				return fmt.Errorf("Unsupported struct type %s", fieldVal.Type())
			}
		default:
			return fmt.Errorf("Unsupported field type %s", field.Type.Kind())
		}
	}
	return nil
}
<commit_msg>fix run to Run<commit_after>package http

import (
	"bytes"
	"compress/flate"
	"compress/gzip"
	"encoding/json"
	"fmt"
	"io"
	"io/ioutil"
	"log"
	"net/http"
	"net/url"
	"path"
	"reflect"
	"strconv"
	"strings"
	"text/template"

	c "github.com/d0ngw/go/common"
)

// RequestError is the http request response error
type RequestError struct {
	Status int
	Err    error
}

func (p *RequestError) Error() string {
	return fmt.Sprintf("status:%d,data:%s", p.Status, p.Err)
}

// CheckRequestError if err is RequestError,then return response status code
func CheckRequestError(err error) (status int, ok bool) {
	if err == nil {
		return
	}
	if e, ok := err.(*RequestError); ok {
		return e.Status, true
	}
	return
}

// RedirectError redirect error
type RedirectError struct {
	RedirectURL string
}

func (p *RedirectError) Error() string {
	return fmt.Sprintf("redirect:%s", p.RedirectURL)
}

// CheckRedirectError if err is RedirectError ,then return redirect error
func CheckRedirectError(err error) (url string, ok bool) {
	if err == nil {
		return
	}
	if e, ok := err.(*RedirectError); ok {
		return e.RedirectURL, true
	}
	return
}

// NewRedirectError redirect error
func NewRedirectError(req *http.Request, via []*http.Request) error {
	return &RedirectError{
		RedirectURL: req.URL.String(),
	}
}

// Resp JSON Http响应
type Resp struct {
	Success bool        `json:"success"`
	Data    interface{} `json:"data"`
	Msg     string      `json:"msg"`
}

// NewSuccResp 构建成功的响应
func NewSuccResp(data interface{}) *Resp {
	return &Resp{
		Success: true,
		Data:    data,
	}
}

// NewFailResp 构建失败的响应
func NewFailResp(msg string) *Resp {
	return &Resp{
		Success: false,
		Msg:     msg,
	}
}

// ResponseHandler 响应处理
type ResponseHandler struct {
	Success bool
	Data    interface{}
	Msg     string
	w       http.ResponseWriter
}

// SuccessWithData 设置成功及数据
func (p *ResponseHandler) SuccessWithData(data interface{}) {
	p.Success = true
	p.Data = data
}

// FailWithMsg 设置失败及出错的消息
func (p *ResponseHandler) FailWithMsg(msg string) {
	p.Success = false
	p.Msg = msg
}

// Run exec run
func (p *ResponseHandler) Run() {
	if !p.Success {
		RenderJSON(p.w, &Resp{Success: false, Msg: p.Msg})
	} else {
		RenderJSON(p.w, &Resp{Success: true, Data: p.Data})
	}
}

// NewResponseHandler 构建响应处理
func NewResponseHandler(w http.ResponseWriter) *ResponseHandler {
	return &ResponseHandler{
		w: w,
	}
}

var (
	errNoparam = fmt.Errorf("missing param")
)

// GetParameter 取得由name指定的参数值
func GetParameter(r url.Values, name string) string {
	return strings.TrimSpace(r.Get(name))
}

func getIntParameter(r url.Values, name string, bitSize int) (val int64, err error) {
	value := GetParameter(r, name)
	if value == "" {
		return 0, errNoparam
	}
	val, err = strconv.ParseInt(value, 10, bitSize)
	return
}

// GetInt64Parameter 取得由name指定的64位整数参数值
func GetInt64Parameter(r url.Values, name string) (val int64, err error) {
	val, err = getIntParameter(r, name, 64)
	return
}

// GetInt32Parameter 取得由name指定的32位整数参数值
func GetInt32Parameter(r url.Values, name string) (val int32, err error) {
	val64, err := getIntParameter(r, name, 32)
	if err == nil {
		return int32(val64), nil
	}
	return 0, err
}

func getFloatParameter(r url.Values, name string, bitSize int) (val float64, err error) {
	value := GetParameter(r, name)
	if value == "" {
		return 0, errNoparam
	}
	val, err = strconv.ParseFloat(value, bitSize)
	return
}

// GetFloat64Parameter 取得由name指定的64位浮点数参数值
func GetFloat64Parameter(r url.Values, name string) (val float64, err error) {
	val, err = getFloatParameter(r, name, 64)
	return
}

// GetFloat32Parameter 取得由name指定的32位浮点数参数值
func GetFloat32Parameter(r url.Values, name string) (val float32, err error) {
	val64, err := getFloatParameter(r, name, 32)
	if err == nil {
		return float32(val64), nil
	}
	return 0, err
}

// RenderTemplate 渲染模板
func RenderTemplate(w http.ResponseWriter, templateDir, tmpl string, data interface{}) {
	templatePath := path.Join(templateDir, tmpl+".html")
	t, err := template.ParseFiles(templatePath)
	if err != nil {
		log.Printf("Parse template err:%s\n", err)
		http.Error(w, err.Error(), http.StatusInternalServerError)
	}
	if err := t.Execute(w, data); err != nil {
		log.Printf("Execute template err:%s\n", err)
		http.Error(w, err.Error(), http.StatusInternalServerError)
	}
}

// RenderJSON 渲染JSON
func RenderJSON(w http.ResponseWriter, jsonData interface{}) {
	w.Header().Set("Content-Type", "application/json; charset=utf-8")
	encoder := json.NewEncoder(w)
	encoder.SetEscapeHTML(false)
	err := encoder.Encode(jsonData)
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
}

// RenderText 渲染Text
func RenderText(w http.ResponseWriter, text string) {
	w.Header().Set("Content-Type", "text/plain; charset=utf-8")
	w.Write([]byte(text))
}

// GetURL 请求URL
func GetURL(client *http.Client, url string, params url.Values) (string, error) {
	return GetURLWithCookie(client, url, params, nil)
}

// GetURLWithCookie 请求URL
func GetURLWithCookie(client *http.Client, url string, params url.Values, cookies map[string]string) (string, error) {
	_, body, err := GetURLRaw(client, url, params, nil, cookies)
	if err != nil {
		return "", err
	}
	return string(body), nil
}

// GetURLRawToWriter 请求URL
func GetURLRawToWriter(client *http.Client, url string, params url.Values, reqHeader http.Header, cookies map[string]string, writer io.Writer) (header http.Header, err error) {
	var req *http.Request
	if params != nil {
		req, err = http.NewRequest("GET", url+"?"+params.Encode(), nil)
	} else {
		req, err = http.NewRequest("GET", url, nil)
	}
	if err != nil {
		return nil, err
	}
	if reqHeader != nil {
		req.Header = reqHeader
	}
	for k, v := range cookies {
		req.AddCookie(&http.Cookie{Name: k, Value: v})
	}
	resp, err := client.Do(req)
	if err != nil {
		e := &RequestError{Err: err}
		if resp != nil {
			e.Status = resp.StatusCode
		}
		return nil, e
	}
	if resp.Body != nil {
		defer resp.Body.Close()
	}
	if resp.StatusCode != 200 {
		return nil, &RequestError{Status: resp.StatusCode}
	}
	contentEncoding := resp.Header.Get("Content-Encoding")
	switch contentEncoding {
	case "gzip":
		fallthrough
	case "deflate":
		var (
			reader io.ReadCloser
			err    error
		)
		if contentEncoding == "gzip" {
			reader, err = gzip.NewReader(resp.Body)
		} else if contentEncoding == "deflate" {
			reader = flate.NewReader(resp.Body)
		}
		if err != nil {
			return nil, err
		}
		if reader == nil {
			return nil, fmt.Errorf("no uncompress reader")
		}
		defer reader.Close()
		_, err = io.Copy(writer, reader)
		if err != nil {
			return nil, err
		}
	default:
		_, err = io.Copy(writer, resp.Body)
		if err != nil {
			return nil, err
		}
	}
	return resp.Header, nil
}

// GetURLRaw 请求URL
func GetURLRaw(client *http.Client, url string, params url.Values, reqHeader http.Header, cookies map[string]string) (header http.Header, body []byte, err error) {
	var writer = &bytes.Buffer{}
	header, err = GetURLRawToWriter(client, url, params, reqHeader, cookies, writer)
	if err != nil {
		return header, nil, err
	}
	return header, writer.Bytes(), nil
}

// PostURL 请求URL
func PostURL(client *http.Client, url string, params url.Values, contentType string, requestBody io.Reader) ([]byte, http.Header, error) {
	return PostURLWithCookie(client, url, params, contentType, requestBody, nil)
}

// PostURLWithCookie 请求URL
func PostURLWithCookie(client *http.Client, url string, params url.Values, contentType string, requestBody io.Reader, cookies map[string]string) ([]byte, http.Header, error) {
	if requestBody == nil {
		requestBody = strings.NewReader(params.Encode())
	} else {
		url = url + "?" + params.Encode()
	}

	req, err := http.NewRequest("POST", url, requestBody)
	if err != nil {
		return nil, nil, err
	}
	if contentType != "" {
		req.Header.Set("Content-Type", contentType)
	}
	for k, v := range cookies {
		req.AddCookie(&http.Cookie{Name: k, Value: v})
	}

	resp, err := client.Do(req)
	if err != nil {
		return nil, nil, err
	}
	if resp.Body != nil {
		defer resp.Body.Close()
	}
	if resp.StatusCode != 200 {
		return nil, nil, &RequestError{Status: resp.StatusCode}
	}
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return nil, nil, err
	}
	return body, resp.Header, nil
}

// ParseParams 从r中解析参数,并填充到dest中,params应该是struct指针
func ParseParams(r url.Values, dest interface{}) error {
	if r == nil || dest == nil {
		return fmt.Errorf("invalid args")
	}

	val, ind, typ := c.ExtractRefTuple(dest)
	if val.Kind() != reflect.Ptr {
		return fmt.Errorf("Expect ptr ,but it's %s", val.Kind())
	}
	if typ.Kind() != reflect.Struct {
		return fmt.Errorf("Expect struct,but it's %s", typ.Kind())
	}

	for i := 0; i < ind.NumField(); i++ {
		field := typ.Field(i)
		tag := field.Tag
		paramName := tag.Get("pname")
		if paramName == "" {
			paramName = ToUnderlineName(field.Name)
		}

		if paramName == "_" {
			continue
		}

		fieldVal := ind.Field(i)
		switch field.Type.Kind() {
		case reflect.Int:
			fallthrough
		case reflect.Int8:
			fallthrough
		case reflect.Int16:
			fallthrough
		case reflect.Int32:
			fallthrough
		case reflect.Int64:
			if val64, err := getIntParameter(r, paramName, 64); err == nil {
				fieldVal.SetInt(val64)
			}
		case reflect.Float32:
			fallthrough
		case reflect.Float64:
			if val64, err := getFloatParameter(r, paramName, 64); err == nil {
				fieldVal.SetFloat(val64)
			}
		case reflect.String:
			fieldVal.SetString(GetParameter(r, paramName))
		case reflect.Bool:
			v := strings.ToLower(GetParameter(r, paramName))
			fieldVal.SetBool(v == "1" || v == "y" || v == "true")
		case reflect.Slice:
			paramSep := tag.Get("psep")
			var vals []string
			if paramSep == "" {
				if ps, ok := r[paramName]; ok {
					vals = c.TrimOmitEmpty(ps)
				}
			} else {
				vals = c.SplitTrimOmitEmpty(GetParameter(r, paramName), paramSep)
			}

			strSlice := c.StringSlice(vals)
			var elem = field.Type.Elem()
			switch elem.Kind() {
			case reflect.String:
				fieldVal.Set(reflect.ValueOf(vals))
			case reflect.Int32:
				if intSlice, err := strSlice.ToInt32(); err == nil {
					fieldVal.Set(reflect.ValueOf(intSlice))
				}
			case reflect.Int64:
				if intSlice, err := strSlice.ToInt64(); err == nil {
					fieldVal.Set(reflect.ValueOf(intSlice))
				}
			case reflect.Float32:
				if intSlice, err := strSlice.ToFloat32(); err == nil {
					fieldVal.Set(reflect.ValueOf(intSlice))
				}
			case reflect.Float64:
				if intSlice, err := strSlice.ToFloat64(); err == nil {
					fieldVal.Set(reflect.ValueOf(intSlice))
				}
			default:
				return fmt.Errorf("Unsupported type %s", elem.Kind())
			}
		case reflect.Struct:
			if fieldVal.IsValid() && fieldVal.CanInterface() && fieldVal.CanAddr() {
				ParseParams(r, fieldVal.Addr().Interface())
			} else {
				return fmt.Errorf("Unsupported struct type %s", fieldVal.Type())
			}
		default:
			return fmt.Errorf("Unsupported field type %s", field.Type.Kind())
		}
	}
	return nil
}
<|endoftext|>


<commit_before>package acceptance_test

import (
	"encoding/json"
	"net"
	"net/http"
	"os/exec"

	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"

	"github.com/appc/cni/pkg/types"
	"github.com/onsi/gomega/gexec"
	"github.com/onsi/gomega/ghttp"
)

type IPAM struct {
	Type   string              `json:"type,omitempty"`
	Subnet string              `json:"subnet,omitempty"`
	Routes []map[string]string `json:"routes,omitempty"`
}

type Config struct {
	Name          string `json:"name"`
	Type          string `json:"type"`
	NetworkID     string `json:"network_id"`
	DaemonBaseURL string `json:"daemon_base_url"`
}

const DEFAULT_TIMEOUT = "3s"

var _ = Describe("VXLAN ADD", func() {
	var (
		netConfig Config
		session   *gexec.Session
		server    *ghttp.Server

		containerID string

		containerNSPath string

		ipamResult types.Result
	)

	BeforeEach(func() {
		containerID = "guid-1"
		containerNSPath = "/some/container/namespace/path"

		server = ghttp.NewServer()
		serverURL := server.URL()

		netConfig = Config{
			Name:          "test-network",
			Type:          "vxlan",
			NetworkID:     "some-network-id",
			DaemonBaseURL: serverURL,
		}

		ipamResult = types.Result{
			IP4: &types.IPConfig{
				IP: net.IPNet{
					IP:   net.ParseIP("192.168.1.2"),
					Mask: net.CIDRMask(24, 32),
				},
				Gateway: net.ParseIP("192.168.1.1"),
				Routes: []types.Route{{
					Dst: net.IPNet{
						IP:   net.ParseIP("192.168.0.0"),
						Mask: net.CIDRMask(16, 32),
					},
					GW: net.ParseIP("192.168.1.1"),
				}},
			},
		}

		statusCode := http.StatusCreated
		server.RouteToHandler("POST", "/cni/add", ghttp.CombineHandlers(
			ghttp.VerifyHeaderKV("Content-Type", "application/json"),
			ghttp.RespondWithJSONEncodedPtr(&statusCode, &ipamResult),
		))
	})

	AfterEach(func() {
		server.Close()
	})

	Describe("ADD", func() {
		It("returns IPAM data", func() {
			var err error
			var cmd *exec.Cmd
			cmd, err = buildCNICmdLight("ADD", netConfig, containerNSPath, containerID)
			Expect(err).NotTo(HaveOccurred())
			session, err = gexec.Start(cmd, GinkgoWriter, GinkgoWriter)
			Expect(err).NotTo(HaveOccurred())
			Eventually(session, DEFAULT_TIMEOUT).Should(gexec.Exit(0))

			var result types.Result
			err = json.Unmarshal(session.Out.Contents(), &result)
			Expect(err).NotTo(HaveOccurred())

			Expect(result.IP4.Gateway.String()).To(Equal("192.168.1.1"))
			Expect(result.IP4.Routes).To(HaveLen(1))
			Expect(result.IP4.Routes[0].Dst.String()).To(Equal("192.168.0.0/16"))
		})

		Context("when the call to the daemon to register the container fails", func() {
			BeforeEach(func() {
				server.RouteToHandler("POST", "/cni/add", ghttp.RespondWith(http.StatusInternalServerError, nil))
			})

			It("returns an error", func() {
				var err error
				var cmd *exec.Cmd
				cmd, err = buildCNICmdLight("ADD", netConfig, containerNSPath, containerID)
				Expect(err).NotTo(HaveOccurred())
				session, err = gexec.Start(cmd, GinkgoWriter, GinkgoWriter)
				Expect(err).NotTo(HaveOccurred())
				Eventually(session, DEFAULT_TIMEOUT).Should(gexec.Exit(1))

				Expect(server.ReceivedRequests()).To(HaveLen(1))
				Expect(session.Out.Contents()).To(ContainSubstring("unexpected status code on ContainerUp: expected 201 but got 500"))
			})
		})

		Context("when daemon_base_url is not set", func() {
			BeforeEach(func() {
				netConfig.DaemonBaseURL = ""
			})

			It("exits with an error", func() {
				var err error
				var cmd *exec.Cmd
				cmd, err = buildCNICmdLight("ADD", netConfig, containerNSPath, containerID)
				Expect(err).NotTo(HaveOccurred())
				session, err = gexec.Start(cmd, GinkgoWriter, GinkgoWriter)
				Expect(err).NotTo(HaveOccurred())
				Eventually(session, DEFAULT_TIMEOUT).Should(gexec.Exit(1))

				Expect(session.Out.Contents()).To(ContainSubstring(`\"daemon_base_url\" field required.`))
			})
		})

		Context("when the network_id is missing", func() {
			BeforeEach(func() {
				netConfig.NetworkID = ""
			})

			It("exits with an error", func() {
				var err error
				var cmd *exec.Cmd
				cmd, err = buildCNICmdLight("ADD", netConfig, containerNSPath, containerID)
				Expect(err).NotTo(HaveOccurred())
				session, err = gexec.Start(cmd, GinkgoWriter, GinkgoWriter)
				Expect(err).NotTo(HaveOccurred())
				Eventually(session, DEFAULT_TIMEOUT).Should(gexec.Exit(1))

				Expect(session.Out.Contents()).To(ContainSubstring(`\"network_id\" field required.`))
			})
		})
	})
})
<commit_msg>Removes check for network_id in add payload<commit_after>package acceptance_test

import (
	"encoding/json"
	"net"
	"net/http"
	"os/exec"

	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"

	"github.com/appc/cni/pkg/types"
	"github.com/onsi/gomega/gexec"
	"github.com/onsi/gomega/ghttp"
)

type IPAM struct {
	Type   string              `json:"type,omitempty"`
	Subnet string              `json:"subnet,omitempty"`
	Routes []map[string]string `json:"routes,omitempty"`
}

type Config struct {
	Name          string `json:"name"`
	Type          string `json:"type"`
	NetworkID     string `json:"network_id"`
	DaemonBaseURL string `json:"daemon_base_url"`
}

const DEFAULT_TIMEOUT = "3s"

var _ = Describe("VXLAN ADD", func() {
	var (
		netConfig Config
		session   *gexec.Session
		server    *ghttp.Server

		containerID string

		containerNSPath string

		ipamResult types.Result
	)

	BeforeEach(func() {
		containerID = "guid-1"
		containerNSPath = "/some/container/namespace/path"

		server = ghttp.NewServer()
		serverURL := server.URL()

		netConfig = Config{
			Name:          "test-network",
			Type:          "vxlan",
			NetworkID:     "some-network-id",
			DaemonBaseURL: serverURL,
		}

		ipamResult = types.Result{
			IP4: &types.IPConfig{
				IP: net.IPNet{
					IP:   net.ParseIP("192.168.1.2"),
					Mask: net.CIDRMask(24, 32),
				},
				Gateway: net.ParseIP("192.168.1.1"),
				Routes: []types.Route{{
					Dst: net.IPNet{
						IP:   net.ParseIP("192.168.0.0"),
						Mask: net.CIDRMask(16, 32),
					},
					GW: net.ParseIP("192.168.1.1"),
				}},
			},
		}

		statusCode := http.StatusCreated
		server.RouteToHandler("POST", "/cni/add", ghttp.CombineHandlers(
			ghttp.VerifyHeaderKV("Content-Type", "application/json"),
			ghttp.RespondWithJSONEncodedPtr(&statusCode, &ipamResult),
		))
	})

	AfterEach(func() {
		server.Close()
	})

	Describe("ADD", func() {
		It("returns IPAM data", func() {
			var err error
			var cmd *exec.Cmd
			cmd, err = buildCNICmdLight("ADD", netConfig, containerNSPath, containerID)
			Expect(err).NotTo(HaveOccurred())
			session, err = gexec.Start(cmd, GinkgoWriter, GinkgoWriter)
			Expect(err).NotTo(HaveOccurred())
			Eventually(session, DEFAULT_TIMEOUT).Should(gexec.Exit(0))

			var result types.Result
			err = json.Unmarshal(session.Out.Contents(), &result)
			Expect(err).NotTo(HaveOccurred())

			Expect(result.IP4.Gateway.String()).To(Equal("192.168.1.1"))
			Expect(result.IP4.Routes).To(HaveLen(1))
			Expect(result.IP4.Routes[0].Dst.String()).To(Equal("192.168.0.0/16"))
		})

		Context("when the call to the daemon to register the container fails", func() {
			BeforeEach(func() {
				server.RouteToHandler("POST", "/cni/add", ghttp.RespondWith(http.StatusInternalServerError, nil))
			})

			It("returns an error", func() {
				var err error
				var cmd *exec.Cmd
				cmd, err = buildCNICmdLight("ADD", netConfig, containerNSPath, containerID)
				Expect(err).NotTo(HaveOccurred())
				session, err = gexec.Start(cmd, GinkgoWriter, GinkgoWriter)
				Expect(err).NotTo(HaveOccurred())
				Eventually(session, DEFAULT_TIMEOUT).Should(gexec.Exit(1))

				Expect(server.ReceivedRequests()).To(HaveLen(1))
				Expect(session.Out.Contents()).To(ContainSubstring("unexpected status code on ContainerUp: expected 201 but got 500"))
			})
		})

		Context("when daemon_base_url is not set", func() {
			BeforeEach(func() {
				netConfig.DaemonBaseURL = ""
			})

			It("exits with an error", func() {
				var err error
				var cmd *exec.Cmd
				cmd, err = buildCNICmdLight("ADD", netConfig, containerNSPath, containerID)
				Expect(err).NotTo(HaveOccurred())
				session, err = gexec.Start(cmd, GinkgoWriter, GinkgoWriter)
				Expect(err).NotTo(HaveOccurred())
				Eventually(session, DEFAULT_TIMEOUT).Should(gexec.Exit(1))

				Expect(session.Out.Contents()).To(ContainSubstring(`\"daemon_base_url\" field required.`))
			})
		})
	})
})
<|endoftext|>


<commit_before>// Package testserver starts and stops test servers if required
package testserver

import (
	"bytes"
	"fmt"
	"net"
	"os"
	"os/exec"
	"path/filepath"
	"regexp"
	"strings"
	"sync"
	"time"

	"github.com/pkg/errors"
	"github.com/rclone/rclone/fs"
	"github.com/rclone/rclone/fs/fspath"
)

var (
	once      sync.Once
	configDir string // where the config is stored
	// Note of running servers
	runningMu   sync.Mutex
	running     = map[string]int{}
	errNotFound = errors.New("command not found")
)

// Assume we are run somewhere within the rclone root
func findConfig() (string, error) {
	dir := filepath.Join("fstest", "testserver", "init.d")
	for i := 0; i < 5; i++ {
		fi, err := os.Stat(dir)
		if err == nil && fi.IsDir() {
			return filepath.Abs(dir)
		} else if !os.IsNotExist(err) {
			return "", err
		}
		dir = filepath.Join("..", dir)
	}
	return "", errors.New("couldn't find testserver config files - run from within rclone source")
}

// run the command returning the output and an error
func run(name, command string) (out []byte, err error) {
	cmdPath := filepath.Join(configDir, name)
	fi, err := os.Stat(cmdPath)
	if err != nil || fi.IsDir() {
		return nil, errNotFound
	}
	cmd := exec.Command(cmdPath, command)
	out, err = cmd.CombinedOutput()
	if err != nil {
		err = errors.Wrapf(err, "failed to run %s %s\n%s", cmdPath, command, string(out))
	}
	return out, err
}

// Check to see if the server is running
func isRunning(name string) bool {
	_, err := run(name, "status")
	return err == nil
}

// envKey returns the environment variable name to set name, key
func envKey(name, key string) string {
	return fmt.Sprintf("RCLONE_CONFIG_%s_%s", strings.ToUpper(name), strings.ToUpper(key))
}

// match a line of config var=value
var matchLine = regexp.MustCompile(`^([a-zA-Z_]+)=(.*)$`)

// Start the server and set its env vars
// Call with the mutex held
func start(name string) error {
	out, err := run(name, "start")
	if err != nil {
		return err
	}
	fs.Logf(name, "Starting server")
	// parse the output and set environment vars from it
	var connect string
	for _, line := range bytes.Split(out, []byte("\n")) {
		line = bytes.TrimSpace(line)
		part := matchLine.FindSubmatch(line)
		if part != nil {
			key, value := part[1], part[2]
			if string(key) == "_connect" {
				connect = string(value)
				continue
			}

			// fs.Debugf(name, "key = %q, envKey = %q, value = %q", key, envKey, value)
			err = os.Setenv(envKey(name, string(key)), string(value))
			if err != nil {
				return err
			}
		}
	}
	if connect == "" {
		return nil
	}
	// If we got a _connect value then try to connect to it
	const maxTries = 30
	for i := 1; i <= maxTries; i++ {
		fs.Debugf(name, "Attempting to connect to %q try %d/%d", connect, i, maxTries)
		conn, err := net.Dial("tcp", connect)
		if err == nil {
			_ = conn.Close()
			return nil
		}
		time.Sleep(time.Second)
	}
	return errors.Errorf("failed to connect to %q on %q", name, connect)
}

// Start starts the named test server which can be stopped by the
// function returned.
func Start(remoteName string) (fn func(), err error) {
	var name string
	name, _, err = fspath.Parse(remoteName)
	if err != nil {
		return nil, err
	}
	if name == "" {
		// don't start the local backend
		return func() {}, nil
	}

	// Make sure we know where the config is
	once.Do(func() {
		configDir, err = findConfig()
	})
	if err != nil {
		return nil, err
	}

	runningMu.Lock()
	defer runningMu.Unlock()

	if running[name] <= 0 {
		// if server isn't running check to see if this server has
		// been started already but not by us and stop it if so
		if os.Getenv(envKey(name, "type")) == "" && isRunning(name) {
			stop(name)
		}
		if !isRunning(name) {
			err = start(name)
			if err == errNotFound {
				// if no file found then don't start or stop
				return func() {}, nil
			} else if err != nil {
				return nil, err
			}
			running[name] = 0
		} else {
			running[name] = 1
		}
	}
	running[name]++

	return func() {
		runningMu.Lock()
		defer runningMu.Unlock()
		stop(name)
	}, nil

}

// Stops the named test server
// Call with the mutex held
func stop(name string) {
	running[name]--
	if running[name] <= 0 {
		_, err := run(name, "stop")
		if err != nil {
			fs.Errorf(name, "Failed to stop server: %v", err)
		}
		running[name] = 0
		fs.Logf(name, "Stopped server")
	}
}
<commit_msg>testserver: don't allow starting of an empty remote<commit_after>// Package testserver starts and stops test servers if required
package testserver

import (
	"bytes"
	"fmt"
	"net"
	"os"
	"os/exec"
	"path/filepath"
	"regexp"
	"strings"
	"sync"
	"time"

	"github.com/pkg/errors"
	"github.com/rclone/rclone/fs"
	"github.com/rclone/rclone/fs/fspath"
)

var (
	once      sync.Once
	configDir string // where the config is stored
	// Note of running servers
	runningMu   sync.Mutex
	running     = map[string]int{}
	errNotFound = errors.New("command not found")
)

// Assume we are run somewhere within the rclone root
func findConfig() (string, error) {
	dir := filepath.Join("fstest", "testserver", "init.d")
	for i := 0; i < 5; i++ {
		fi, err := os.Stat(dir)
		if err == nil && fi.IsDir() {
			return filepath.Abs(dir)
		} else if !os.IsNotExist(err) {
			return "", err
		}
		dir = filepath.Join("..", dir)
	}
	return "", errors.New("couldn't find testserver config files - run from within rclone source")
}

// run the command returning the output and an error
func run(name, command string) (out []byte, err error) {
	cmdPath := filepath.Join(configDir, name)
	fi, err := os.Stat(cmdPath)
	if err != nil || fi.IsDir() {
		return nil, errNotFound
	}
	cmd := exec.Command(cmdPath, command)
	out, err = cmd.CombinedOutput()
	if err != nil {
		err = errors.Wrapf(err, "failed to run %s %s\n%s", cmdPath, command, string(out))
	}
	return out, err
}

// Check to see if the server is running
func isRunning(name string) bool {
	_, err := run(name, "status")
	return err == nil
}

// envKey returns the environment variable name to set name, key
func envKey(name, key string) string {
	return fmt.Sprintf("RCLONE_CONFIG_%s_%s", strings.ToUpper(name), strings.ToUpper(key))
}

// match a line of config var=value
var matchLine = regexp.MustCompile(`^([a-zA-Z_]+)=(.*)$`)

// Start the server and set its env vars
// Call with the mutex held
func start(name string) error {
	out, err := run(name, "start")
	if err != nil {
		return err
	}
	fs.Logf(name, "Starting server")
	// parse the output and set environment vars from it
	var connect string
	for _, line := range bytes.Split(out, []byte("\n")) {
		line = bytes.TrimSpace(line)
		part := matchLine.FindSubmatch(line)
		if part != nil {
			key, value := part[1], part[2]
			if string(key) == "_connect" {
				connect = string(value)
				continue
			}

			// fs.Debugf(name, "key = %q, envKey = %q, value = %q", key, envKey, value)
			err = os.Setenv(envKey(name, string(key)), string(value))
			if err != nil {
				return err
			}
		}
	}
	if connect == "" {
		return nil
	}
	// If we got a _connect value then try to connect to it
	const maxTries = 30
	for i := 1; i <= maxTries; i++ {
		fs.Debugf(name, "Attempting to connect to %q try %d/%d", connect, i, maxTries)
		conn, err := net.Dial("tcp", connect)
		if err == nil {
			_ = conn.Close()
			return nil
		}
		time.Sleep(time.Second)
	}
	return errors.Errorf("failed to connect to %q on %q", name, connect)
}

// Start starts the named test server which can be stopped by the
// function returned.
func Start(remoteName string) (fn func(), err error) {
	if remoteName == "" {
		// don't start the local backend
		return func() {}, nil
	}
	var name string
	name, _, err = fspath.Parse(remoteName)
	if err != nil {
		return nil, err
	}
	if name == "" {
		// don't start the local backend
		return func() {}, nil
	}

	// Make sure we know where the config is
	once.Do(func() {
		configDir, err = findConfig()
	})
	if err != nil {
		return nil, err
	}

	runningMu.Lock()
	defer runningMu.Unlock()

	if running[name] <= 0 {
		// if server isn't running check to see if this server has
		// been started already but not by us and stop it if so
		if os.Getenv(envKey(name, "type")) == "" && isRunning(name) {
			stop(name)
		}
		if !isRunning(name) {
			err = start(name)
			if err == errNotFound {
				// if no file found then don't start or stop
				return func() {}, nil
			} else if err != nil {
				return nil, err
			}
			running[name] = 0
		} else {
			running[name] = 1
		}
	}
	running[name]++

	return func() {
		runningMu.Lock()
		defer runningMu.Unlock()
		stop(name)
	}, nil

}

// Stops the named test server
// Call with the mutex held
func stop(name string) {
	running[name]--
	if running[name] <= 0 {
		_, err := run(name, "stop")
		if err != nil {
			fs.Errorf(name, "Failed to stop server: %v", err)
		}
		running[name] = 0
		fs.Logf(name, "Stopped server")
	}
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"fmt"
	"io/ioutil"
	"log"
	"runtime"
	"time"
)

const (
	LOG_COMMIT_SUCCESS int = iota
	LOG_COMMIT_VALID_READ
	LOG_COMMIT_LOCK_WRITE
	LOG_COMMIT_REVALID_READ
	LOG_EXEC_VALID_READ
)

var log_transaction bool
var log_status [5]int32

func main() {
	runtime.GOMAXPROCS(runtime.NumCPU())

	// Flag initialization
	var printAST, printInst bool
	var bench int
	flag.BoolVar(&printAST, "ast", false, "Print abstract syntax tree structure")
	flag.BoolVar(&printInst, "bytecode", false, "Print comprehensive bytecode instructions")
	flag.BoolVar(&log_transaction, "log", false, "Log transaction status")
	flag.IntVar(&bench, "bench", 0, "Benchmark script execution speed (without parsing stage)")

	flag.Parse()

	if flag.NArg() != 1 {
		flag.Usage()
		log.Fatalf("FILE: the .rb file to execute")
	}

	file := flag.Args()[0]

	buffer, err := ioutil.ReadFile(file)
	if err != nil {
		log.Fatal(err)
	}

	p := &Leg{Buffer: string(buffer)}
	p.Init()
	if err := p.Parse(); err != nil {
		log.Fatal(err)
	}

	p.Execute()

	if printAST {
		Traverse(rootAST)
	}

	if bench > 0 {
		start := time.Now()
		for i := 0; i < bench; i++ {
			vm := initVM()
			vm.compile(rootAST)
			vm.execute()
		}

		if log_transaction {
			printTransactionLog()
		}

		total := float64(time.Since(start).Nanoseconds()) / float64(1000000000)
		fmt.Printf("Total time in %d iterations: %v s\n", bench, total)
		fmt.Printf("Average Time in %d iterations: %v s\n", bench, total/float64(bench))
		return
	}

	vm := initVM()

	vm.compile(rootAST)

	if printInst {
		printInstructions(vm.instList, true)
	}

	vm.execute()

	if log_transaction {
		printTransactionLog()
	}
}

func printInstructions(inst []Instruction, blocks bool) {
	BytecodeInString := []string{
		"BC_PUTSELF",
		"BC_PUTNIL",
		"BC_PUTOBJ",
		"BC_PUTTRUE",
		"BC_PUTFALSE",
		"BC_SETLOCAL",
		"BC_GETLOCAL",
		"BC_SETGLOBAL",
		"BC_GETGLOBAL",
		"BC_SETSYMBOL",
		"BC_GETSYMBOL",
		"BC_SETCONST",
		"BC_GETCONST",
		"BC_SETIVAR",
		"BC_GETIVAR",
		"BC_SETCVAR",
		"BC_GETCVAR",
		"BC_SEND",
		"BC_JUMP",
	}
	for _, v := range inst {
		fmt.Println(BytecodeInString[v.inst_type], v)
		fmt.Print("\t")
		fmt.Println(v.obj)
		if blocks && (v.inst_type == BC_PUTOBJ || v.inst_type == BC_INIT_THREAD) && v.obj.(*RObject).name == "RBlock" {
			printInstructions(v.obj.(*RObject).methods["def"].def, blocks)
		}
	}
}

func printTransactionLog() {
	total := int64(0)
	fmt.Println("\nTransaction Logging Status")
	fmt.Println("Success:", log_status[LOG_COMMIT_SUCCESS])
	fmt.Println("Fail:")
	fmt.Println("\tCommit")
	fmt.Println("\t\tREAD:", log_status[LOG_COMMIT_VALID_READ])
	fmt.Println("\t\tREAD (revalid):", log_status[LOG_COMMIT_REVALID_READ])
	fmt.Println("\t\tWRITE:", log_status[LOG_COMMIT_LOCK_WRITE])
	fmt.Println("\tExecution")
	fmt.Println("\t\tREAD:", log_status[LOG_EXEC_VALID_READ])

	for _, log_cnt := range log_status {
		total += int64(log_cnt)
	}

	fmt.Println("Total:", total)
}
<commit_msg>Update bytecode string array for printing<commit_after>package main

import (
	"flag"
	"fmt"
	"io/ioutil"
	"log"
	"runtime"
	"time"
)

const (
	LOG_COMMIT_SUCCESS int = iota
	LOG_COMMIT_VALID_READ
	LOG_COMMIT_LOCK_WRITE
	LOG_COMMIT_REVALID_READ
	LOG_EXEC_VALID_READ
)

var log_transaction bool
var log_status [5]int32

func main() {
	runtime.GOMAXPROCS(runtime.NumCPU())

	// Flag initialization
	var printAST, printInst bool
	var bench int
	flag.BoolVar(&printAST, "ast", false, "Print abstract syntax tree structure")
	flag.BoolVar(&printInst, "bytecode", false, "Print comprehensive bytecode instructions")
	flag.BoolVar(&log_transaction, "log", false, "Log transaction status")
	flag.IntVar(&bench, "bench", 0, "Benchmark script execution speed (without parsing stage)")

	flag.Parse()

	if flag.NArg() != 1 {
		flag.Usage()
		log.Fatalf("FILE: the .rb file to execute")
	}

	file := flag.Args()[0]

	buffer, err := ioutil.ReadFile(file)
	if err != nil {
		log.Fatal(err)
	}

	p := &Leg{Buffer: string(buffer)}
	p.Init()
	if err := p.Parse(); err != nil {
		log.Fatal(err)
	}

	p.Execute()

	if printAST {
		Traverse(rootAST)
	}

	if bench > 0 {
		start := time.Now()
		for i := 0; i < bench; i++ {
			vm := initVM()
			vm.compile(rootAST)
			vm.execute()
		}

		if log_transaction {
			printTransactionLog()
		}

		total := float64(time.Since(start).Nanoseconds()) / float64(1000000000)
		fmt.Printf("Total time in %d iterations: %v s\n", bench, total)
		fmt.Printf("Average Time in %d iterations: %v s\n", bench, total/float64(bench))
		return
	}

	vm := initVM()

	vm.compile(rootAST)

	if printInst {
		printInstructions(vm.instList, true)
	}

	vm.execute()

	if log_transaction {
		printTransactionLog()
	}
}

func printInstructions(inst []Instruction, blocks bool) {
	BytecodeInString := []string{
		"BC_PUTSELF",
		"BC_PUTNIL",
		"BC_PUTOBJ",
		"BC_PUTFIXNUM",
		"BC_PUTSTRING",
		"BC_PUTTRUE",
		"BC_PUTFALSE",
		"BC_SETLOCAL",
		"BC_GETLOCAL",
		"BC_SETGLOBAL",
		"BC_GETGLOBAL",
		"BC_SETSYMBOL",
		"BC_GETSYMBOL",
		"BC_SETCONST",
		"BC_GETCONST",
		"BC_SETIVAR",
		"BC_GETIVAR",
		"BC_SETCVAR",
		"BC_GETCVAR",
		"BC_SEND",
		"BC_JUMP",
		"BC_INIT_THREAD",
	}
	for _, v := range inst {
		fmt.Println(BytecodeInString[v.inst_type], v)
		fmt.Print("\t")
		fmt.Println(v.obj)
		if blocks && (v.inst_type == BC_PUTOBJ || v.inst_type == BC_INIT_THREAD) && v.obj.(*RObject).name == "RBlock" {
			printInstructions(v.obj.(*RObject).methods["def"].def, blocks)
		}
	}
}

func printTransactionLog() {
	total := int64(0)
	fmt.Println("\nTransaction Logging Status")
	fmt.Println("Success:", log_status[LOG_COMMIT_SUCCESS])
	fmt.Println("Fail:")
	fmt.Println("\tCommit")
	fmt.Println("\t\tREAD:", log_status[LOG_COMMIT_VALID_READ])
	fmt.Println("\t\tREAD (revalid):", log_status[LOG_COMMIT_REVALID_READ])
	fmt.Println("\t\tWRITE:", log_status[LOG_COMMIT_LOCK_WRITE])
	fmt.Println("\tExecution")
	fmt.Println("\t\tREAD:", log_status[LOG_EXEC_VALID_READ])

	for _, log_cnt := range log_status {
		total += int64(log_cnt)
	}

	fmt.Println("Total:", total)
}
<|endoftext|>


<commit_before>package aws

import (
	"fmt"
	"os"
	"testing"

	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/service/ec2"
	"github.com/hashicorp/terraform/helper/resource"
	"github.com/hashicorp/terraform/terraform"
)

func TestAccAWSVPCPeeringConnection_basic(t *testing.T) {
	var connection ec2.VpcPeeringConnection

	resource.Test(t, resource.TestCase{
		PreCheck: func() {
			testAccPreCheck(t)
			if os.Getenv("AWS_ACCOUNT_ID") == "" {
				t.Fatal("AWS_ACCOUNT_ID must be set")
			}
		},
		Providers:    testAccProviders,
		CheckDestroy: testAccCheckAWSVpcPeeringConnectionDestroy,
		Steps: []resource.TestStep{
			resource.TestStep{
				Config: testAccVpcPeeringConfig,
				Check: resource.ComposeTestCheckFunc(
					testAccCheckAWSVpcPeeringConnectionExists("aws_vpc_peering_connection.foo", &connection),
				),
			},
		},
	})
}

func TestAccAWSVPCPeeringConnection_tags(t *testing.T) {
	var connection ec2.VpcPeeringConnection
	peerId := os.Getenv("TF_PEER_ID")
	if peerId == "" {
		t.Fatalf("Error: TestAccAWSVPCPeeringConnection_tags requires a peer id to be set")
	}

	resource.Test(t, resource.TestCase{
		PreCheck:     func() { testAccPreCheck(t) },
		Providers:    testAccProviders,
		CheckDestroy: testAccCheckVpcDestroy,
		Steps: []resource.TestStep{
			resource.TestStep{
				Config: fmt.Sprintf(testAccVpcPeeringConfigTags, peerId),
				Check: resource.ComposeTestCheckFunc(
					testAccCheckAWSVpcPeeringConnectionExists("aws_vpc_peering_connection.foo", &connection),
					testAccCheckTags(&connection.Tags, "foo", "bar"),
				),
			},
		},
	})
}

func testAccCheckAWSVpcPeeringConnectionDestroy(s *terraform.State) error {
	conn := testAccProvider.Meta().(*AWSClient).ec2conn

	for _, rs := range s.RootModule().Resources {
		if rs.Type != "aws_vpc_peering_connection" {
			continue
		}

		describe, err := conn.DescribeVpcPeeringConnections(
			&ec2.DescribeVpcPeeringConnectionsInput{
				VpcPeeringConnectionIds: []*string{aws.String(rs.Primary.ID)},
			})

		if err == nil {
			if len(describe.VpcPeeringConnections) != 0 {
				return fmt.Errorf("vpc peering connection still exists")
			}
		}
	}

	return nil
}

func testAccCheckAWSVpcPeeringConnectionExists(n string, connection *ec2.VpcPeeringConnection) resource.TestCheckFunc {
	return func(s *terraform.State) error {
		rs, ok := s.RootModule().Resources[n]
		if !ok {
			return fmt.Errorf("Not found: %s", n)
		}

		if rs.Primary.ID == "" {
			return fmt.Errorf("No vpc peering connection id is set")
		}

		conn := testAccProvider.Meta().(*AWSClient).ec2conn
		resp, err := conn.DescribeVpcPeeringConnections(
			&ec2.DescribeVpcPeeringConnectionsInput{
				VpcPeeringConnectionIds: []*string{aws.String(rs.Primary.ID)},
			})
		if err != nil {
			return err
		}
		if len(resp.VpcPeeringConnections) == 0 {
			return fmt.Errorf("VPC peering connection not found")
		}

		*connection = *resp.VpcPeeringConnections[0]

		return nil
	}
}

const testAccVpcPeeringConfig = `
resource "aws_vpc" "foo" {
		cidr_block = "10.0.0.0/16"
}

resource "aws_vpc" "bar" {
		cidr_block = "10.1.0.0/16"
}

resource "aws_vpc_peering_connection" "foo" {
		vpc_id = "${aws_vpc.foo.id}"
		peer_vpc_id = "${aws_vpc.bar.id}"
		auto_accept = true
}
`

const testAccVpcPeeringConfigTags = `
resource "aws_vpc" "foo" {
		cidr_block = "10.0.0.0/16"
}

resource "aws_vpc" "bar" {
		cidr_block = "10.1.0.0/16"
}

resource "aws_vpc_peering_connection" "foo" {
		vpc_id = "${aws_vpc.foo.id}"
		peer_vpc_id = "${aws_vpc.bar.id}"
		peer_owner_id = "%s"
		tags {
			foo = "bar"
		}
}
`
<commit_msg>skip TestAccAWSVPCPeeringConnection_tags for now<commit_after>package aws

import (
	"fmt"
	"os"
	"testing"

	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/service/ec2"
	"github.com/hashicorp/terraform/helper/resource"
	"github.com/hashicorp/terraform/terraform"
)

func TestAccAWSVPCPeeringConnection_basic(t *testing.T) {
	var connection ec2.VpcPeeringConnection

	resource.Test(t, resource.TestCase{
		PreCheck: func() {
			testAccPreCheck(t)
			if os.Getenv("AWS_ACCOUNT_ID") == "" {
				t.Fatal("AWS_ACCOUNT_ID must be set")
			}
		},
		Providers:    testAccProviders,
		CheckDestroy: testAccCheckAWSVpcPeeringConnectionDestroy,
		Steps: []resource.TestStep{
			resource.TestStep{
				Config: testAccVpcPeeringConfig,
				Check: resource.ComposeTestCheckFunc(
					testAccCheckAWSVpcPeeringConnectionExists("aws_vpc_peering_connection.foo", &connection),
				),
			},
		},
	})
}

func TestAccAWSVPCPeeringConnection_tags(t *testing.T) {
	var connection ec2.VpcPeeringConnection
	peerId := os.Getenv("TF_PEER_ID")
	if peerId == "" {
		t.Skip("Error: TestAccAWSVPCPeeringConnection_tags requires a peer id to be set")
	}

	resource.Test(t, resource.TestCase{
		PreCheck:     func() { testAccPreCheck(t) },
		Providers:    testAccProviders,
		CheckDestroy: testAccCheckVpcDestroy,
		Steps: []resource.TestStep{
			resource.TestStep{
				Config: fmt.Sprintf(testAccVpcPeeringConfigTags, peerId),
				Check: resource.ComposeTestCheckFunc(
					testAccCheckAWSVpcPeeringConnectionExists("aws_vpc_peering_connection.foo", &connection),
					testAccCheckTags(&connection.Tags, "foo", "bar"),
				),
			},
		},
	})
}

func testAccCheckAWSVpcPeeringConnectionDestroy(s *terraform.State) error {
	conn := testAccProvider.Meta().(*AWSClient).ec2conn

	for _, rs := range s.RootModule().Resources {
		if rs.Type != "aws_vpc_peering_connection" {
			continue
		}

		describe, err := conn.DescribeVpcPeeringConnections(
			&ec2.DescribeVpcPeeringConnectionsInput{
				VpcPeeringConnectionIds: []*string{aws.String(rs.Primary.ID)},
			})

		if err == nil {
			if len(describe.VpcPeeringConnections) != 0 {
				return fmt.Errorf("vpc peering connection still exists")
			}
		}
	}

	return nil
}

func testAccCheckAWSVpcPeeringConnectionExists(n string, connection *ec2.VpcPeeringConnection) resource.TestCheckFunc {
	return func(s *terraform.State) error {
		rs, ok := s.RootModule().Resources[n]
		if !ok {
			return fmt.Errorf("Not found: %s", n)
		}

		if rs.Primary.ID == "" {
			return fmt.Errorf("No vpc peering connection id is set")
		}

		conn := testAccProvider.Meta().(*AWSClient).ec2conn
		resp, err := conn.DescribeVpcPeeringConnections(
			&ec2.DescribeVpcPeeringConnectionsInput{
				VpcPeeringConnectionIds: []*string{aws.String(rs.Primary.ID)},
			})
		if err != nil {
			return err
		}
		if len(resp.VpcPeeringConnections) == 0 {
			return fmt.Errorf("VPC peering connection not found")
		}

		*connection = *resp.VpcPeeringConnections[0]

		return nil
	}
}

const testAccVpcPeeringConfig = `
resource "aws_vpc" "foo" {
		cidr_block = "10.0.0.0/16"
}

resource "aws_vpc" "bar" {
		cidr_block = "10.1.0.0/16"
}

resource "aws_vpc_peering_connection" "foo" {
		vpc_id = "${aws_vpc.foo.id}"
		peer_vpc_id = "${aws_vpc.bar.id}"
		auto_accept = true
}
`

const testAccVpcPeeringConfigTags = `
resource "aws_vpc" "foo" {
		cidr_block = "10.0.0.0/16"
}

resource "aws_vpc" "bar" {
		cidr_block = "10.1.0.0/16"
}

resource "aws_vpc_peering_connection" "foo" {
		vpc_id = "${aws_vpc.foo.id}"
		peer_vpc_id = "${aws_vpc.bar.id}"
		peer_owner_id = "%s"
		tags {
			foo = "bar"
		}
}
`
<|endoftext|>


<commit_before><commit_msg>audio/internal/go2cpp: Better waiting condition<commit_after><|endoftext|>


<commit_before>package main

import (
	"errors"
	"log"
	"math/rand"
	"net/http"
	"net/url"
	"time"
)

const (
	_URL_REQUIRED_SCHEME               = "http"
	_URL_REQUIRED_HOST                 = "zakupki.gov.ru"
	_URL_REQUIRED_QUICK_SEARCH_PATH    = "/epz/order/orderCsvSettings/quickSearch/download.html"
	_URL_REQUIRED_EXTENDED_SEARCH_PATH = "/epz/order/orderCsvSettings/extendedSearch/download.html"
	_URL_REQUIRED_SORTING_TYPE         = "PUBLISH_DATE"
	_URL_REQUIRED_SORTING_DIRECTION    = "false"
)

var RandGen = rand.New(rand.NewSource(time.Now().UnixNano()))

var UserAgents = []string{
	"Mozilla/4.0 (compatible; MSIE 6.0; Windows 98)",
	"Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0; .NET CLR 1.0.3705)",
	"Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Maxthon)",
	"Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; bgft)",
	"Mozilla/4.5b1 [en] (X11; I; Linux 2.0.35 i586)",
	"Mozilla/5.0 (compatible; Konqueror/2.2.2; Linux 2.4.14-xfs; X11; i686)",
	"Mozilla/5.0 (Macintosh; U; PPC; en-US; rv:0.9.2) Gecko/20010726 Netscape6/6.1",
	"Mozilla/5.0 (Windows; U; Win98; en-US; rv:0.9.2) Gecko/20010726 Netscape6/6.1",
	"Mozilla/5.0 (X11; U; Linux 2.4.2-2 i586; en-US; m18) Gecko/20010131 Netscape6/6.01",
	"Mozilla/5.0 (X11; U; Linux i686; en-US; rv:0.9.3) Gecko/20010801",
	"Mozilla/5.0 (Windows; U; Windows NT 5.1; ru; rv:1.8.0.7) Gecko/20060909 Firefox/1.5.0.7",
	"Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.6) Gecko/20040413 Epiphany/1.2.1",
	"Opera/9.0 (Windows NT 5.1; U; en)",
	"Opera/8.51 (Windows NT 5.1; U; en)",
	"Opera/7.21 (Windows NT 5.1; U)",
	"Mozilla/4.0 (compatible; MSIE 5.01; Windows NT)",
	"Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1)",
	"Mozilla/5.0 (Windows; U; Windows NT 5.2; en-US; rv:1.8.0.6) Gecko/20060928 Firefox/1.5.0.6",
	"Opera/9.02 (Windows NT 5.1; U; en)",
	"Opera/8.54 (Windows NT 5.1; U; en)",
	"Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/37.0.2049.0 Safari/537.36",
	"Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/36.0.1985.67 Safari/537.36",
	"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/36.0.1944.0 Safari/537.36",
	"Mozilla/5.0 (compatible; MSIE 10.6; Windows NT 6.1; Trident/5.0; InfoPath.2; SLCC1; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729; .NET CLR 2.0.50727) 3gpp-gba UNTRUSTED/1.0",
	"Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; WOW64; Trident/6.0)",
	"Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; Trident/6.0)",
	"Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; Trident/5.0)",
	"Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; Trident/4.0; InfoPath.2; SV1; .NET CLR 2.0.50727; WOW64)",
	"Mozilla/5.0 (Windows; U; MSIE 9.0; WIndows NT 9.0; en-US))",
	"Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 7.1; Trident/5.0)",
	"Opera/9.80 (Windows NT 6.0) Presto/2.12.388 Version/12.14",
	"Mozilla/5.0 (Windows NT 6.0; rv:2.0) Gecko/20100101 Firefox/4.0 Opera 12.14",
	"Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.0) Opera 12.14",
	"Opera/12.80 (Windows NT 5.1; U; en) Presto/2.10.289 Version/12.02",
	"Opera/9.80 (Windows NT 6.1; U; es-ES) Presto/2.9.181 Version/12.00",
	"Opera/9.80 (Windows NT 5.1; U; zh-sg) Presto/2.9.181 Version/12.00",
	"Opera/12.0(Windows NT 5.2;U;en)Presto/22.9.168 Version/12.00",
	"Mozilla/5.0 (Windows NT 5.1; rv:31.0) Gecko/20100101 Firefox/31.0",
	"Mozilla/5.0 (Windows NT 6.1; WOW64; rv:29.0) Gecko/20120101 Firefox/29.0",
	"Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:25.0) Gecko/20100101 Firefox/29.0",
	"Mozilla/5.0 (X11; OpenBSD amd64; rv:28.0) Gecko/20100101 Firefox/28.0",
	"Mozilla/5.0 (X11; Linux x86_64; rv:28.0) Gecko/20100101 Firefox/28.0",
	"Mozilla/5.0 (Windows NT 6.1; rv:27.3) Gecko/20130101 Firefox/27.3",
	"Mozilla/5.0 (iPad; CPU OS 6_0 like Mac OS X) AppleWebKit/536.26 (KHTML, like Gecko) Version/6.0 Mobile/10A5355d Safari/8536.25",
	"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_6_8) AppleWebKit/537.13+ (KHTML, like Gecko) Version/5.1.7 Safari/534.57.2",
	"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_3) AppleWebKit/534.55.3 (KHTML, like Gecko) Version/5.1.3 Safari/534.53.10",
	"Mozilla/5.0 (Windows NT 6.3; WOW64; rv:24.0) Gecko/20100101 Thunderbird/24.4.0",
	"Mozilla/5.0 (Windows NT 6.1; WOW64; rv:24.0) Gecko/20100101 Thunderbird/24.4.0",
	"Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Thunderbird/24.3.0 Lightning/2.6.4",
	"Mozilla/5.0 (Windows NT 6.1; WOW64; rv:24.0) Gecko/20100101 Thunderbird/24.3.0",
}

func Load(rawurl string) (*http.Response, error) {
	if len(rawurl) == 0 {
		return nil, errors.New("Can't load: passed empty url string")
	}
	URL, err := url.Parse(rawurl)
	if err != nil {
		return nil, err
	}

	if !URL.IsAbs() {
		return nil, errors.New("Passed url isn't absolute")
	}
	if URL.Scheme != _URL_REQUIRED_SCHEME {
		return nil, errors.New("Invalid url scheme")
	}
	if URL.Host != _URL_REQUIRED_HOST {
		return nil, errors.New("Invalid url host")
	}
	if URL.Path != _URL_REQUIRED_QUICK_SEARCH_PATH {
		if URL.Path != _URL_REQUIRED_EXTENDED_SEARCH_PATH {
			return nil, errors.New("Invalid url path")
		}
	}

	// Param sortBy defines type of sorting
	if URL.Query().Get("sortBy") != _URL_REQUIRED_SORTING_TYPE {
		log.Println("Result will not sorted by publish date!")
	}
	// Param sortDirection defines sorting direction
	if URL.Query().Get("sortDirection") != _URL_REQUIRED_SORTING_DIRECTION {
		log.Println("Invalid sorting direction!")
	}
	// This app is useful if and only if orders will sorted descending
	// by publish date!

	return http.DefaultClient.Do(&http.Request{
		URL:   URL,
		Proto: "HTTP/1.1",
		Header: http.Header{
			"User-Agent": {UserAgents[RandGen.Intn(len(UserAgents))]},
		},
		Host: URL.Host,
	})
}
<commit_msg>fxd paths 2<commit_after>package main

import (
	"errors"
	"log"
	"math/rand"
	"net/http"
	"net/url"
	"time"
)

const (
	_URL_REQUIRED_SCHEME = "http"
	_URL_REQUIRED_HOST   = "zakupki.gov.ru"

	_URL_REQUIRED_QUICK_SEARCH_PATH    = "/epz/order/quicksearch/orderCsvSettings/quickSearch/download.html"
	_URL_REQUIRED_EXTENDED_SEARCH_PATH = "/epz/order/extendedsearch/orderCsvSettings/extendedSearch/download.html"
	_URL_REQUIRED_SORTING_TYPE         = "PUBLISH_DATE"
	_URL_REQUIRED_SORTING_DIRECTION    = "false"
)

var RandGen = rand.New(rand.NewSource(time.Now().UnixNano()))

var UserAgents = []string{
	"Mozilla/4.0 (compatible; MSIE 6.0; Windows 98)",
	"Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0; .NET CLR 1.0.3705)",
	"Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Maxthon)",
	"Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; bgft)",
	"Mozilla/4.5b1 [en] (X11; I; Linux 2.0.35 i586)",
	"Mozilla/5.0 (compatible; Konqueror/2.2.2; Linux 2.4.14-xfs; X11; i686)",
	"Mozilla/5.0 (Macintosh; U; PPC; en-US; rv:0.9.2) Gecko/20010726 Netscape6/6.1",
	"Mozilla/5.0 (Windows; U; Win98; en-US; rv:0.9.2) Gecko/20010726 Netscape6/6.1",
	"Mozilla/5.0 (X11; U; Linux 2.4.2-2 i586; en-US; m18) Gecko/20010131 Netscape6/6.01",
	"Mozilla/5.0 (X11; U; Linux i686; en-US; rv:0.9.3) Gecko/20010801",
	"Mozilla/5.0 (Windows; U; Windows NT 5.1; ru; rv:1.8.0.7) Gecko/20060909 Firefox/1.5.0.7",
	"Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.6) Gecko/20040413 Epiphany/1.2.1",
	"Opera/9.0 (Windows NT 5.1; U; en)",
	"Opera/8.51 (Windows NT 5.1; U; en)",
	"Opera/7.21 (Windows NT 5.1; U)",
	"Mozilla/4.0 (compatible; MSIE 5.01; Windows NT)",
	"Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1)",
	"Mozilla/5.0 (Windows; U; Windows NT 5.2; en-US; rv:1.8.0.6) Gecko/20060928 Firefox/1.5.0.6",
	"Opera/9.02 (Windows NT 5.1; U; en)",
	"Opera/8.54 (Windows NT 5.1; U; en)",
	"Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/37.0.2049.0 Safari/537.36",
	"Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/36.0.1985.67 Safari/537.36",
	"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/36.0.1944.0 Safari/537.36",
	"Mozilla/5.0 (compatible; MSIE 10.6; Windows NT 6.1; Trident/5.0; InfoPath.2; SLCC1; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729; .NET CLR 2.0.50727) 3gpp-gba UNTRUSTED/1.0",
	"Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; WOW64; Trident/6.0)",
	"Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; Trident/6.0)",
	"Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; Trident/5.0)",
	"Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; Trident/4.0; InfoPath.2; SV1; .NET CLR 2.0.50727; WOW64)",
	"Mozilla/5.0 (Windows; U; MSIE 9.0; WIndows NT 9.0; en-US))",
	"Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 7.1; Trident/5.0)",
	"Opera/9.80 (Windows NT 6.0) Presto/2.12.388 Version/12.14",
	"Mozilla/5.0 (Windows NT 6.0; rv:2.0) Gecko/20100101 Firefox/4.0 Opera 12.14",
	"Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.0) Opera 12.14",
	"Opera/12.80 (Windows NT 5.1; U; en) Presto/2.10.289 Version/12.02",
	"Opera/9.80 (Windows NT 6.1; U; es-ES) Presto/2.9.181 Version/12.00",
	"Opera/9.80 (Windows NT 5.1; U; zh-sg) Presto/2.9.181 Version/12.00",
	"Opera/12.0(Windows NT 5.2;U;en)Presto/22.9.168 Version/12.00",
	"Mozilla/5.0 (Windows NT 5.1; rv:31.0) Gecko/20100101 Firefox/31.0",
	"Mozilla/5.0 (Windows NT 6.1; WOW64; rv:29.0) Gecko/20120101 Firefox/29.0",
	"Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:25.0) Gecko/20100101 Firefox/29.0",
	"Mozilla/5.0 (X11; OpenBSD amd64; rv:28.0) Gecko/20100101 Firefox/28.0",
	"Mozilla/5.0 (X11; Linux x86_64; rv:28.0) Gecko/20100101 Firefox/28.0",
	"Mozilla/5.0 (Windows NT 6.1; rv:27.3) Gecko/20130101 Firefox/27.3",
	"Mozilla/5.0 (iPad; CPU OS 6_0 like Mac OS X) AppleWebKit/536.26 (KHTML, like Gecko) Version/6.0 Mobile/10A5355d Safari/8536.25",
	"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_6_8) AppleWebKit/537.13+ (KHTML, like Gecko) Version/5.1.7 Safari/534.57.2",
	"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_3) AppleWebKit/534.55.3 (KHTML, like Gecko) Version/5.1.3 Safari/534.53.10",
	"Mozilla/5.0 (Windows NT 6.3; WOW64; rv:24.0) Gecko/20100101 Thunderbird/24.4.0",
	"Mozilla/5.0 (Windows NT 6.1; WOW64; rv:24.0) Gecko/20100101 Thunderbird/24.4.0",
	"Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Thunderbird/24.3.0 Lightning/2.6.4",
	"Mozilla/5.0 (Windows NT 6.1; WOW64; rv:24.0) Gecko/20100101 Thunderbird/24.3.0",
}

func Load(rawurl string) (*http.Response, error) {
	if len(rawurl) == 0 {
		return nil, errors.New("Can't load: passed empty url string")
	}
	URL, err := url.Parse(rawurl)
	if err != nil {
		return nil, err
	}

	if !URL.IsAbs() {
		return nil, errors.New("Passed url isn't absolute")
	}
	if URL.Scheme != _URL_REQUIRED_SCHEME {
		return nil, errors.New("Invalid url scheme")
	}
	if URL.Host != _URL_REQUIRED_HOST {
		return nil, errors.New("Invalid url host")
	}
	if URL.Path != _URL_REQUIRED_QUICK_SEARCH_PATH {
		if URL.Path != _URL_REQUIRED_EXTENDED_SEARCH_PATH {
			return nil, errors.New("Invalid url path")
		}
	}

	// Param sortBy defines type of sorting
	if URL.Query().Get("sortBy") != _URL_REQUIRED_SORTING_TYPE {
		log.Println("Result will not sorted by publish date!")
	}
	// Param sortDirection defines sorting direction
	if URL.Query().Get("sortDirection") != _URL_REQUIRED_SORTING_DIRECTION {
		log.Println("Invalid sorting direction!")
	}
	// This app is useful if and only if orders will sorted descending
	// by publish date!

	return http.DefaultClient.Do(&http.Request{
		URL:   URL,
		Proto: "HTTP/1.1",
		Header: http.Header{
			"User-Agent": {UserAgents[RandGen.Intn(len(UserAgents))]},
		},
		Host: URL.Host,
	})
}
<|endoftext|>


<commit_before>package goakit

import (
	"fmt"
	"path/filepath"

	"goa.design/goa/codegen"
	httpcodegen "goa.design/goa/http/codegen"
	httpdesign "goa.design/goa/http/design"
)

// EncodeDecodeFiles produces a set of go-kit transport encoders and decoders
// that wrap the corresponding generated goa functions.
func EncodeDecodeFiles(genpkg string, root *httpdesign.RootExpr) []*codegen.File {
	fw := make([]*codegen.File, 2*len(root.HTTPServices))
	for i, r := range root.HTTPServices {
		fw[i] = serverEncodeDecode(genpkg, r)
	}
	for i, r := range root.HTTPServices {
		fw[i+len(root.HTTPServices)] = clientEncodeDecode(genpkg, r)
	}
	return fw
}

// serverEncodeDecode returns the file defining the go-kit HTTP server encoding
// and decoding logic.
func serverEncodeDecode(genpkg string, svc *httpdesign.ServiceExpr) *codegen.File {
	path := filepath.Join(codegen.Gendir, "http", codegen.SnakeCase(svc.Name()), "kitserver", "encode_decode.go")
	data := httpcodegen.HTTPServices.Get(svc.Name())
	title := fmt.Sprintf("%s go-kit HTTP server encoders and decoders", svc.Name())
	sections := []*codegen.SectionTemplate{
		codegen.Header(title, "server", []*codegen.ImportSpec{
			{Path: "context"},
			{Path: "net/http"},
			{Path: "strings"},
			{Path: "github.com/go-kit/kit/transport/http", Name: "kithttp"},
			{Path: "goa.design/goa", Name: "goa"},
			{Path: "goa.design/goa/http", Name: "goahttp"},
			{Path: genpkg + "/http/" + data.Service.Name + "/server"},
		}),
	}

	for _, e := range data.Endpoints {
		sections = append(sections, &codegen.SectionTemplate{
			Name:   "goakit-response-encoder",
			Source: responseEncoderT,
			Data:   e,
		})

		if e.Payload.Ref != "" {
			sections = append(sections, &codegen.SectionTemplate{
				Name:   "goakit-request-decoder",
				Source: requestDecoderT,
				Data:   e,
			})
		}

		if len(e.Errors) > 0 {
			sections = append(sections, &codegen.SectionTemplate{
				Name:   "goakit-error-encoder",
				Source: errorEncoderT,
				Data:   e,
			})
		}
	}

	return &codegen.File{Path: path, SectionTemplates: sections}
}

// clientEncodeDecode returns the file defining the go-kit HTTP client encoding
// and decoding logic.
func clientEncodeDecode(genpkg string, svc *httpdesign.ServiceExpr) *codegen.File {
	path := filepath.Join(codegen.Gendir, "http", codegen.SnakeCase(svc.Name()), "kitclient", "encode_decode.go")
	title := fmt.Sprintf("%s go-kit HTTP client encoders and decoders", svc.Name())
	data := httpcodegen.HTTPServices.Get(svc.Name())
	sections := []*codegen.SectionTemplate{
		codegen.Header(title, "client", []*codegen.ImportSpec{
			{Path: "context"},
			{Path: "net/http"},
			{Path: "strings"},
			{Path: "github.com/go-kit/kit/transport/http", Name: "kithttp"},
			{Path: "goa.design/goa", Name: "goa"},
			{Path: "goa.design/goa/http", Name: "goahttp"},
			{Path: genpkg + "/http/" + data.Service.Name + "/client"},
		}),
	}

	for _, e := range data.Endpoints {
		if e.RequestEncoder != "" {
			sections = append(sections, &codegen.SectionTemplate{
				Name:   "goakit-request-encoder",
				Source: requestEncoderT,
				Data:   e,
			})
		}
		if e.Result != nil || len(e.Errors) > 0 {
			sections = append(sections, &codegen.SectionTemplate{
				Name:   "goakit-response-decoder",
				Source: responseDecoderT,
				Data:   e,
			})
		}
	}

	return &codegen.File{Path: path, SectionTemplates: sections}
}

// input: EndpointData
const requestEncoderT = `{{ printf "%s returns a go-kit EncodeRequestFunc suitable for encoding %s %s requests." .RequestEncoder .ServiceName .Method.Name | comment }}
func {{ .RequestEncoder }}(encoder func(*http.Request) goahttp.Encoder) kithttp.EncodeRequestFunc {
	enc := client.{{ .RequestEncoder }}(encoder)
	return func(_ context.Context, r *http.Request, v interface{}) error {
		return enc(r, v)
	}
}
`

// input: EndpointData
const requestDecoderT = `{{ printf "%s returns a go-kit DecodeRequestFunc suitable for decoding %s %s requests." .RequestDecoder .ServiceName .Method.Name | comment }}
func {{ .RequestDecoder }}(mux goahttp.Muxer, decoder func(*http.Request) goahttp.Decoder) kithttp.DecodeRequestFunc {
	dec := server.{{ .RequestDecoder }}(mux, decoder)
	return func(ctx context.Context, r *http.Request) (interface{}, error) {
		r = r.WithContext(ctx)
		return dec(r)
	}
}
`

// input: EndpointData
const responseEncoderT = `{{ printf "%s returns a go-kit EncodeResponseFunc suitable for encoding %s %s responses." .ResponseEncoder .ServiceName .Method.Name | comment }}
 func {{ .ResponseEncoder }}(encoder func(context.Context, http.ResponseWriter) goahttp.Encoder) kithttp.EncodeResponseFunc {
 	return server.{{ .ResponseEncoder }}(encoder)
 }
`

// input: EndpointData
const errorEncoderT = `{{ printf "%s returns a go-kit EncodeResponseFunc suitable for encoding errors returned by the %s %s endpoint." .ErrorEncoder .ServiceName .Method.Name | comment }}
 func {{ .ErrorEncoder }}(encoder func(context.Context, http.ResponseWriter) goahttp.Encoder) kithttp.EncodeResponseFunc {
 	enc := server.{{ .ErrorEncoder }}(encoder)
	return func(ctx context.Context, w http.ResponseWriter, v interface{}) error {
		enc(ctx, w, v.(error))
		return nil
	}
}
`

// input: EndpointData
const responseDecoderT = `{{ printf "%s returns a go-kit DecodeResponseFunc suitable for decoding %s %s responses." .ResponseDecoder .ServiceName .Method.Name | comment }}
func {{ .ResponseDecoder }}(decoder func(*http.Response) goahttp.Decoder) kithttp.DecodeResponseFunc {
	dec := client.{{ .ResponseDecoder }}(decoder, false)
	return func(ctx context.Context, resp *http.Response) (interface{}, error) {
		return dec(resp)
	}
}
`
<commit_msg>Fix goakit error encoder<commit_after>package goakit

import (
	"fmt"
	"path/filepath"

	"goa.design/goa/codegen"
	httpcodegen "goa.design/goa/http/codegen"
	httpdesign "goa.design/goa/http/design"
)

// EncodeDecodeFiles produces a set of go-kit transport encoders and decoders
// that wrap the corresponding generated goa functions.
func EncodeDecodeFiles(genpkg string, root *httpdesign.RootExpr) []*codegen.File {
	fw := make([]*codegen.File, 2*len(root.HTTPServices))
	for i, r := range root.HTTPServices {
		fw[i] = serverEncodeDecode(genpkg, r)
	}
	for i, r := range root.HTTPServices {
		fw[i+len(root.HTTPServices)] = clientEncodeDecode(genpkg, r)
	}
	return fw
}

// serverEncodeDecode returns the file defining the go-kit HTTP server encoding
// and decoding logic.
func serverEncodeDecode(genpkg string, svc *httpdesign.ServiceExpr) *codegen.File {
	path := filepath.Join(codegen.Gendir, "http", codegen.SnakeCase(svc.Name()), "kitserver", "encode_decode.go")
	data := httpcodegen.HTTPServices.Get(svc.Name())
	title := fmt.Sprintf("%s go-kit HTTP server encoders and decoders", svc.Name())
	sections := []*codegen.SectionTemplate{
		codegen.Header(title, "server", []*codegen.ImportSpec{
			{Path: "context"},
			{Path: "net/http"},
			{Path: "strings"},
			{Path: "github.com/go-kit/kit/transport/http", Name: "kithttp"},
			{Path: "goa.design/goa", Name: "goa"},
			{Path: "goa.design/goa/http", Name: "goahttp"},
			{Path: genpkg + "/http/" + data.Service.Name + "/server"},
		}),
	}

	for _, e := range data.Endpoints {
		sections = append(sections, &codegen.SectionTemplate{
			Name:   "goakit-response-encoder",
			Source: responseEncoderT,
			Data:   e,
		})

		if e.Payload.Ref != "" {
			sections = append(sections, &codegen.SectionTemplate{
				Name:   "goakit-request-decoder",
				Source: requestDecoderT,
				Data:   e,
			})
		}

		if len(e.Errors) > 0 {
			sections = append(sections, &codegen.SectionTemplate{
				Name:   "goakit-error-encoder",
				Source: errorEncoderT,
				Data:   e,
			})
		}
	}

	return &codegen.File{Path: path, SectionTemplates: sections}
}

// clientEncodeDecode returns the file defining the go-kit HTTP client encoding
// and decoding logic.
func clientEncodeDecode(genpkg string, svc *httpdesign.ServiceExpr) *codegen.File {
	path := filepath.Join(codegen.Gendir, "http", codegen.SnakeCase(svc.Name()), "kitclient", "encode_decode.go")
	title := fmt.Sprintf("%s go-kit HTTP client encoders and decoders", svc.Name())
	data := httpcodegen.HTTPServices.Get(svc.Name())
	sections := []*codegen.SectionTemplate{
		codegen.Header(title, "client", []*codegen.ImportSpec{
			{Path: "context"},
			{Path: "net/http"},
			{Path: "strings"},
			{Path: "github.com/go-kit/kit/transport/http", Name: "kithttp"},
			{Path: "goa.design/goa", Name: "goa"},
			{Path: "goa.design/goa/http", Name: "goahttp"},
			{Path: genpkg + "/http/" + data.Service.Name + "/client"},
		}),
	}

	for _, e := range data.Endpoints {
		if e.RequestEncoder != "" {
			sections = append(sections, &codegen.SectionTemplate{
				Name:   "goakit-request-encoder",
				Source: requestEncoderT,
				Data:   e,
			})
		}
		if e.Result != nil || len(e.Errors) > 0 {
			sections = append(sections, &codegen.SectionTemplate{
				Name:   "goakit-response-decoder",
				Source: responseDecoderT,
				Data:   e,
			})
		}
	}

	return &codegen.File{Path: path, SectionTemplates: sections}
}

// input: EndpointData
const requestEncoderT = `{{ printf "%s returns a go-kit EncodeRequestFunc suitable for encoding %s %s requests." .RequestEncoder .ServiceName .Method.Name | comment }}
func {{ .RequestEncoder }}(encoder func(*http.Request) goahttp.Encoder) kithttp.EncodeRequestFunc {
	enc := client.{{ .RequestEncoder }}(encoder)
	return func(_ context.Context, r *http.Request, v interface{}) error {
		return enc(r, v)
	}
}
`

// input: EndpointData
const requestDecoderT = `{{ printf "%s returns a go-kit DecodeRequestFunc suitable for decoding %s %s requests." .RequestDecoder .ServiceName .Method.Name | comment }}
func {{ .RequestDecoder }}(mux goahttp.Muxer, decoder func(*http.Request) goahttp.Decoder) kithttp.DecodeRequestFunc {
	dec := server.{{ .RequestDecoder }}(mux, decoder)
	return func(ctx context.Context, r *http.Request) (interface{}, error) {
		r = r.WithContext(ctx)
		return dec(r)
	}
}
`

// input: EndpointData
const responseEncoderT = `{{ printf "%s returns a go-kit EncodeResponseFunc suitable for encoding %s %s responses." .ResponseEncoder .ServiceName .Method.Name | comment }}
 func {{ .ResponseEncoder }}(encoder func(context.Context, http.ResponseWriter) goahttp.Encoder) kithttp.EncodeResponseFunc {
 	return server.{{ .ResponseEncoder }}(encoder)
 }
`

// input: EndpointData
const errorEncoderT = `{{ printf "%s returns a go-kit EncodeResponseFunc suitable for encoding errors returned by the %s %s endpoint." .ErrorEncoder .ServiceName .Method.Name | comment }}
 func {{ .ErrorEncoder }}(encoder func(context.Context, http.ResponseWriter) goahttp.Encoder) kithttp.EncodeResponseFunc {
 	enc := server.{{ .ErrorEncoder }}(encoder)
	return func(ctx context.Context, v interface{}, w http.ResponseWriter) error {
		enc(ctx, w, v.(error))
		return nil
	}
}
`

// input: EndpointData
const responseDecoderT = `{{ printf "%s returns a go-kit DecodeResponseFunc suitable for decoding %s %s responses." .ResponseDecoder .ServiceName .Method.Name | comment }}
func {{ .ResponseDecoder }}(decoder func(*http.Response) goahttp.Decoder) kithttp.DecodeResponseFunc {
	dec := client.{{ .ResponseDecoder }}(decoder, false)
	return func(ctx context.Context, resp *http.Response) (interface{}, error) {
		return dec(resp)
	}
}
`
<|endoftext|>


<commit_before>package redis_test

import (
	"context"
	"fmt"
	"net"

	"github.com/go-redis/redis/v9"
)

type redisHook struct{}

var _ redis.Hook = redisHook{}

func (redisHook) DialHook(hook redis.DialHook) redis.DialHook {
	return func(ctx context.Context, network, addr string) (net.Conn, error) {
		fmt.Printf("dialing %s %s\n", network, addr)
		conn, err := hook(ctx, network, addr)
		fmt.Printf("finished dialing %s %s\n", network, addr)
		return conn, err
	}
}

func (redisHook) ProcessHook(hook redis.ProcessHook) redis.ProcessHook {
	return func(ctx context.Context, cmd redis.Cmder) error {
		fmt.Printf("starting processing: <%s>\n", cmd)
		err := hook(ctx, cmd)
		fmt.Printf("finished processing: <%s>\n", cmd)
		return err
	}
}

func (redisHook) ProcessPipelineHook(hook redis.ProcessPipelineHook) redis.ProcessPipelineHook {
	return func(ctx context.Context, cmds []redis.Cmder) error {
		fmt.Printf("pipeline starting processing: %v\n", cmds)
		err := hook(ctx, cmds)
		fmt.Printf("pipeline finished processing: %v\n", cmds)
		return err
	}
}

func Example_instrumentation() {
	rdb := redis.NewClient(&redis.Options{
		Addr: ":6379",
	})
	rdb.AddHook(redisHook{})

	rdb.Ping(ctx)
	// Output: starting processing: <ping: >
	// dialing tcp :6379
	// finished dialing tcp :6379
	// finished processing: <ping: PONG>
}

func ExamplePipeline_instrumentation() {
	rdb := redis.NewClient(&redis.Options{
		Addr: ":6379",
	})
	rdb.AddHook(redisHook{})

	rdb.Pipelined(ctx, func(pipe redis.Pipeliner) error {
		pipe.Ping(ctx)
		pipe.Ping(ctx)
		return nil
	})
	// Output: pipeline starting processing: [ping:  ping: ]
	// pipeline finished processing: [ping: PONG ping: PONG]
}

func ExampleClient_Watch_instrumentation() {
	rdb := redis.NewClient(&redis.Options{
		Addr: ":6379",
	})
	rdb.AddHook(redisHook{})

	rdb.Watch(ctx, func(tx *redis.Tx) error {
		tx.Ping(ctx)
		tx.Ping(ctx)
		return nil
	}, "foo")
	// Output:
	// starting processing: <watch foo: >
	// finished processing: <watch foo: OK>
	// starting processing: <ping: >
	// finished processing: <ping: PONG>
	// starting processing: <ping: >
	// finished processing: <ping: PONG>
	// starting processing: <unwatch: >
	// finished processing: <unwatch: OK>
}
<commit_msg>chore: fix examples<commit_after>package redis_test

import (
	"context"
	"fmt"
	"net"

	"github.com/go-redis/redis/v9"
)

type redisHook struct{}

var _ redis.Hook = redisHook{}

func (redisHook) DialHook(hook redis.DialHook) redis.DialHook {
	return func(ctx context.Context, network, addr string) (net.Conn, error) {
		fmt.Printf("dialing %s %s\n", network, addr)
		conn, err := hook(ctx, network, addr)
		fmt.Printf("finished dialing %s %s\n", network, addr)
		return conn, err
	}
}

func (redisHook) ProcessHook(hook redis.ProcessHook) redis.ProcessHook {
	return func(ctx context.Context, cmd redis.Cmder) error {
		fmt.Printf("starting processing: <%s>\n", cmd)
		err := hook(ctx, cmd)
		fmt.Printf("finished processing: <%s>\n", cmd)
		return err
	}
}

func (redisHook) ProcessPipelineHook(hook redis.ProcessPipelineHook) redis.ProcessPipelineHook {
	return func(ctx context.Context, cmds []redis.Cmder) error {
		fmt.Printf("pipeline starting processing: %v\n", cmds)
		err := hook(ctx, cmds)
		fmt.Printf("pipeline finished processing: %v\n", cmds)
		return err
	}
}

func Example_instrumentation() {
	rdb := redis.NewClient(&redis.Options{
		Addr: ":6379",
	})
	rdb.AddHook(redisHook{})

	rdb.Ping(ctx)
	// Output: starting processing: <ping: >
	// dialing tcp :6379
	// finished dialing tcp :6379
	// finished processing: <ping: PONG>
}

func ExamplePipeline_instrumentation() {
	rdb := redis.NewClient(&redis.Options{
		Addr: ":6379",
	})
	rdb.AddHook(redisHook{})

	rdb.Pipelined(ctx, func(pipe redis.Pipeliner) error {
		pipe.Ping(ctx)
		pipe.Ping(ctx)
		return nil
	})
	// Output: pipeline starting processing: [ping:  ping: ]
	// dialing tcp :6379
	// finished dialing tcp :6379
	// pipeline finished processing: [ping: PONG ping: PONG]
}

func ExampleClient_Watch_instrumentation() {
	rdb := redis.NewClient(&redis.Options{
		Addr: ":6379",
	})
	rdb.AddHook(redisHook{})

	rdb.Watch(ctx, func(tx *redis.Tx) error {
		tx.Ping(ctx)
		tx.Ping(ctx)
		return nil
	}, "foo")
	// Output:
	// starting processing: <watch foo: >
	// dialing tcp :6379
	// finished dialing tcp :6379
	// finished processing: <watch foo: OK>
	// starting processing: <ping: >
	// finished processing: <ping: PONG>
	// starting processing: <ping: >
	// finished processing: <ping: PONG>
	// starting processing: <unwatch: >
	// finished processing: <unwatch: OK>
}
<|endoftext|>


<commit_before>package zookeeper

import (
	"fmt"
	"net/url"
	"sync"
	"time"

	log "github.com/Sirupsen/logrus"
	"github.com/digitalocean/vulcan/scraper"
	"github.com/samuel/go-zookeeper/zk"

	"github.com/prometheus/common/model"
	pconfig "github.com/prometheus/prometheus/config"
	"github.com/prometheus/prometheus/retrieval/discovery/dns"
)

type PathTargeter struct {
	conn *zk.Conn
	path string

	done chan struct{}
	out  chan scraper.Job
	once sync.Once
}

type PathTargeterConfig struct {
	Conn *zk.Conn
	Path string
}

func NewPathTargeter(config *PathTargeterConfig) *PathTargeter {
	pt := &PathTargeter{
		conn: config.Conn,
		path: config.Path,

		done: make(chan struct{}),
		out:  make(chan scraper.Job),
	}
	go pt.run()
	return pt
}

func (pt PathTargeter) Targets() <-chan scraper.Job {
	return pt.out
}

func (pt PathTargeter) run() {
	defer close(pt.out)
	for {
		// escape
		select {
		case <-pt.done:
			return
		default:
		}

		log.WithField("path", pt.path).Info("getting value")
		b, _, ech, err := pt.conn.GetW(pt.path)
		if err != nil {
			log.WithError(err).Error("while getting path")
			time.Sleep(time.Second * 2) // TODO exponential backoff
			continue
		}
		jobs, err := pt.parseJobs(b)
		if err != nil {
			log.WithError(err).Error("while parsing value")
			time.Sleep(time.Second * 2) // TODO exponential backoff
			continue
		}
		for _, j := range jobs {
			pt.out <- j
		}

		// block
		select {
		case <-pt.done:
			return
		case <-ech:
		}
	}
}

func (pt PathTargeter) parseJobs(b []byte) ([]scraper.Job, error) {
	jobs := []scraper.Job{}
	c, err := pconfig.Load(string(b))
	if err != nil {
		return jobs, err
	}
	for _, sc := range c.ScrapeConfigs {
		j := scraper.Job{
			JobName: scraper.JobName(sc.JobName),
			Targets: map[scraper.Instance]scraper.Target{},
		}
		for _, tg := range sc.StaticConfigs {
			for _, t := range tg.Targets {
				inst := string(t[model.LabelName("__address__")])
				u, err := url.Parse(fmt.Sprintf("%s://%s%s", sc.Scheme, inst, sc.MetricsPath))
				if err != nil {
					log.WithError(err).Error("could not parse instance")
					continue
				}
				j.Targets[scraper.Instance(inst)] = scraper.NewHTTPTarget(&scraper.HTTPTargetConfig{
					Interval: time.Duration(sc.ScrapeInterval),
					URL:      *u,
				})
			}
		}
		jobs = append(jobs, j)

		dns.NewDiscovery(c.ScrapeConfigs[0].DNSSDConfigs[0])

	}
	return jobs, nil
}

func (pt PathTargeter) stop() {
	pt.once.Do(func() {
		close(pt.done)
		// drain
		for {
			select {
			case _, ok := <-pt.out:
				if !ok {
					return
				}
			}
		}
	})
}
<commit_msg>zookeeper: length check on scrape configs slice (#3)<commit_after>package zookeeper

import (
	"fmt"
	"net/url"
	"sync"
	"time"

	"github.com/digitalocean/vulcan/scraper"

	log "github.com/Sirupsen/logrus"
	"github.com/pkg/errors"
	"github.com/prometheus/common/model"
	pconfig "github.com/prometheus/prometheus/config"
	"github.com/prometheus/prometheus/retrieval/discovery/dns"
	"github.com/samuel/go-zookeeper/zk"
)

type PathTargeter struct {
	conn *zk.Conn
	path string

	done chan struct{}
	out  chan scraper.Job
	once sync.Once
}

type PathTargeterConfig struct {
	Conn *zk.Conn
	Path string
}

func NewPathTargeter(config *PathTargeterConfig) *PathTargeter {
	pt := &PathTargeter{
		conn: config.Conn,
		path: config.Path,

		done: make(chan struct{}),
		out:  make(chan scraper.Job),
	}
	go pt.run()
	return pt
}

func (pt PathTargeter) Targets() <-chan scraper.Job {
	return pt.out
}

func (pt PathTargeter) run() {
	defer close(pt.out)
	for {
		// escape
		select {
		case <-pt.done:
			return
		default:
		}

		log.WithField("path", pt.path).Info("getting value")
		b, _, ech, err := pt.conn.GetW(pt.path)
		if err != nil {
			log.WithError(err).Error("while getting path")
			time.Sleep(time.Second * 2) // TODO exponential backoff
			continue
		}
		jobs, err := pt.parseJobs(b)
		if err != nil {
			log.WithError(err).Error("while parsing value")
			time.Sleep(time.Second * 2) // TODO exponential backoff
			continue
		}
		for _, j := range jobs {
			pt.out <- j
		}

		// block
		select {
		case <-pt.done:
			return
		case <-ech:
		}
	}
}

func (pt PathTargeter) parseJobs(b []byte) ([]scraper.Job, error) {
	jobs := []scraper.Job{}
	c, err := pconfig.Load(string(b))
	if err != nil {
		return jobs, err
	}

	if len(c.ScrapeConfigs) < 1 {
		return jobs, errors.New("no scrape configs provided")
	}

	for _, sc := range c.ScrapeConfigs {
		j := scraper.Job{
			JobName: scraper.JobName(sc.JobName),
			Targets: map[scraper.Instance]scraper.Target{},
		}
		for _, tg := range sc.StaticConfigs {
			for _, t := range tg.Targets {
				inst := string(t[model.LabelName("__address__")])
				u, err := url.Parse(fmt.Sprintf("%s://%s%s", sc.Scheme, inst, sc.MetricsPath))
				if err != nil {
					log.WithError(err).Error("could not parse instance")
					continue
				}
				j.Targets[scraper.Instance(inst)] = scraper.NewHTTPTarget(&scraper.HTTPTargetConfig{
					Interval: time.Duration(sc.ScrapeInterval),
					URL:      *u,
				})
			}
		}
		jobs = append(jobs, j)

		dns.NewDiscovery(c.ScrapeConfigs[0].DNSSDConfigs[0])

	}
	return jobs, nil
}

func (pt PathTargeter) stop() {
	pt.once.Do(func() {
		close(pt.done)
		// drain
		for {
			select {
			case _, ok := <-pt.out:
				if !ok {
					return
				}
			}
		}
	})
}
<|endoftext|>


<commit_before>package api

import (
	"encoding/json"
	"fmt"
	"hound/config"
	"hound/index"
	"hound/searcher"
	"log"
	"net/http"
	"strconv"
	"strings"
	"time"
)

const (
	defaultLinesOfContext uint = 2
	maxLinesOfContext     uint = 20
)

type Stats struct {
	FilesOpened int
	Duration    int
}

func writeJson(w http.ResponseWriter, data interface{}) {
	w.Header().Set("Content-Type", "application/json;charset=utf-8")
	w.Header().Set("Access-Control-Allow", "*")
	if err := json.NewEncoder(w).Encode(data); err != nil {
		log.Panicf("Failed to encode JSON: %v\n", err)
	}
}

func writeError(w http.ResponseWriter, err error) {
	writeJson(w, map[string]interface{}{
		"Error": fmt.Sprint(err),
	})
}

type searchResponse struct {
	repo string
	res  *index.SearchResponse
	err  error
}

/**
 * Searches all repos in parallel.
 */
func searchAll(
	query string,
	opts *index.SearchOptions,
	repos []string,
	idx map[string]*searcher.Searcher,
	filesOpened *int,
	duration *int) (map[string]*index.SearchResponse, error) {

	startedAt := time.Now()

	n := len(repos)

	// use a buffered channel to avoid routine leaks on errs.
	ch := make(chan *searchResponse, n)
	for _, repo := range repos {
		go func(repo string) {
			fms, err := idx[repo].Search(query, opts)
			ch <- &searchResponse{repo, fms, err}
		}(repo)
	}

	res := map[string]*index.SearchResponse{}
	for i := 0; i < n; i++ {
		r := <-ch
		if r.err != nil {
			return nil, r.err
		}

		if r.res.Matches == nil {
			continue
		}

		res[r.repo] = r.res
		*filesOpened += r.res.FilesOpened
	}

	*duration = int(time.Now().Sub(startedAt).Seconds() * 1000)

	return res, nil
}

// Used for parsing flags from form values.
func parseAsBool(v string) bool {
	v = strings.ToLower(v)
	return v == "true" || v == "1" || v == "fosho"
}

func parseAsRepoList(v string, idx map[string]*searcher.Searcher) []string {
	v = strings.TrimSpace(strings.ToLower(v))
	var repos []string
	if v == "*" {
		for repo, _ := range idx {
			repos = append(repos, repo)
		}
		return repos
	}

	for _, repo := range strings.Split(v, ",") {
		if idx[repo] == nil {
			continue
		}
		repos = append(repos, repo)
	}
	return repos
}

func parseAsUintValue(sv string, min, max, def uint) uint {
	iv, err := strconv.ParseUint(sv, 10, 54)
	if err != nil {
		return def
	}
	if max != 0 && uint(iv) > max {
		return max
	}
	if min != 0 && uint(iv) < min {
		return max
	}
	return uint(iv)
}

func parseRangeInt(v string, i *int) {
	*i = 0
	if v == "" {
		return
	}

	vi, err := strconv.ParseUint(v, 10, 64)
	if err != nil {
		return
	}

	*i = int(vi)
}

func parseRangeValue(rv string) (int, int) {
	ix := strings.Index(rv, ":")
	if ix < 0 {
		return 0, 0
	}

	var b, e int
	parseRangeInt(rv[:ix], &b)
	parseRangeInt(rv[ix+1:], &e)
	return b, e
}

func Setup(m *http.ServeMux, idx map[string]*searcher.Searcher) {

	m.HandleFunc("/api/v1/repos", func(w http.ResponseWriter, r *http.Request) {
		res := map[string]*config.Repo{}
		for name, srch := range idx {
			res[name] = srch.Repo
		}

		writeJson(w, res)
	})

	m.HandleFunc("/api/v1/search", func(w http.ResponseWriter, r *http.Request) {
		var opt index.SearchOptions

		stats := parseAsBool(r.FormValue("stats"))
		repos := parseAsRepoList(r.FormValue("repos"), idx)
		query := r.FormValue("q")
		opt.Offset, opt.Limit = parseRangeValue(r.FormValue("rng"))
		opt.FileRegexp = r.FormValue("files")
		opt.IgnoreCase = parseAsBool(r.FormValue("i"))
		opt.LinesOfContext = parseAsUintValue(
			r.FormValue("ctx"),
			0,
			maxLinesOfContext,
			defaultLinesOfContext)

		var filesOpened int
		var durationMs int

		results, err := searchAll(query, &opt, repos, idx, &filesOpened, &durationMs)
		if err != nil {
			writeError(w, err)
			return
		}

		var res struct {
			Results map[string]*index.SearchResponse
			Stats   *Stats `json:",omitempty"`
		}

		res.Results = results
		if stats {
			res.Stats = &Stats{
				FilesOpened: filesOpened,
				Duration:    durationMs,
			}
		}

		writeJson(w, &res)
	})

	m.HandleFunc("/api/v1/excludes", func(w http.ResponseWriter, r *http.Request) {
		repo := r.FormValue("repo")
		res := idx[repo].GetExcludedFiles()
		w.Header().Set("Content-Type", "application/json;charset=utf-8")
		w.Header().Set("Access-Control-Allow", "*")
		fmt.Fprint(w, res)
	})
}
<commit_msg>Set correct CORS header in API endpoint.<commit_after>package api

import (
	"encoding/json"
	"fmt"
	"hound/config"
	"hound/index"
	"hound/searcher"
	"log"
	"net/http"
	"strconv"
	"strings"
	"time"
)

const (
	defaultLinesOfContext uint = 2
	maxLinesOfContext     uint = 20
)

type Stats struct {
	FilesOpened int
	Duration    int
}

func writeJson(w http.ResponseWriter, data interface{}) {
	w.Header().Set("Content-Type", "application/json;charset=utf-8")
	w.Header().Set("Access-Control-Allow-Origin", "*")
	if err := json.NewEncoder(w).Encode(data); err != nil {
		log.Panicf("Failed to encode JSON: %v\n", err)
	}
}

func writeError(w http.ResponseWriter, err error) {
	writeJson(w, map[string]interface{}{
		"Error": fmt.Sprint(err),
	})
}

type searchResponse struct {
	repo string
	res  *index.SearchResponse
	err  error
}

/**
 * Searches all repos in parallel.
 */
func searchAll(
	query string,
	opts *index.SearchOptions,
	repos []string,
	idx map[string]*searcher.Searcher,
	filesOpened *int,
	duration *int) (map[string]*index.SearchResponse, error) {

	startedAt := time.Now()

	n := len(repos)

	// use a buffered channel to avoid routine leaks on errs.
	ch := make(chan *searchResponse, n)
	for _, repo := range repos {
		go func(repo string) {
			fms, err := idx[repo].Search(query, opts)
			ch <- &searchResponse{repo, fms, err}
		}(repo)
	}

	res := map[string]*index.SearchResponse{}
	for i := 0; i < n; i++ {
		r := <-ch
		if r.err != nil {
			return nil, r.err
		}

		if r.res.Matches == nil {
			continue
		}

		res[r.repo] = r.res
		*filesOpened += r.res.FilesOpened
	}

	*duration = int(time.Now().Sub(startedAt).Seconds() * 1000)

	return res, nil
}

// Used for parsing flags from form values.
func parseAsBool(v string) bool {
	v = strings.ToLower(v)
	return v == "true" || v == "1" || v == "fosho"
}

func parseAsRepoList(v string, idx map[string]*searcher.Searcher) []string {
	v = strings.TrimSpace(strings.ToLower(v))
	var repos []string
	if v == "*" {
		for repo, _ := range idx {
			repos = append(repos, repo)
		}
		return repos
	}

	for _, repo := range strings.Split(v, ",") {
		if idx[repo] == nil {
			continue
		}
		repos = append(repos, repo)
	}
	return repos
}

func parseAsUintValue(sv string, min, max, def uint) uint {
	iv, err := strconv.ParseUint(sv, 10, 54)
	if err != nil {
		return def
	}
	if max != 0 && uint(iv) > max {
		return max
	}
	if min != 0 && uint(iv) < min {
		return max
	}
	return uint(iv)
}

func parseRangeInt(v string, i *int) {
	*i = 0
	if v == "" {
		return
	}

	vi, err := strconv.ParseUint(v, 10, 64)
	if err != nil {
		return
	}

	*i = int(vi)
}

func parseRangeValue(rv string) (int, int) {
	ix := strings.Index(rv, ":")
	if ix < 0 {
		return 0, 0
	}

	var b, e int
	parseRangeInt(rv[:ix], &b)
	parseRangeInt(rv[ix+1:], &e)
	return b, e
}

func Setup(m *http.ServeMux, idx map[string]*searcher.Searcher) {

	m.HandleFunc("/api/v1/repos", func(w http.ResponseWriter, r *http.Request) {
		res := map[string]*config.Repo{}
		for name, srch := range idx {
			res[name] = srch.Repo
		}

		writeJson(w, res)
	})

	m.HandleFunc("/api/v1/search", func(w http.ResponseWriter, r *http.Request) {
		var opt index.SearchOptions

		stats := parseAsBool(r.FormValue("stats"))
		repos := parseAsRepoList(r.FormValue("repos"), idx)
		query := r.FormValue("q")
		opt.Offset, opt.Limit = parseRangeValue(r.FormValue("rng"))
		opt.FileRegexp = r.FormValue("files")
		opt.IgnoreCase = parseAsBool(r.FormValue("i"))
		opt.LinesOfContext = parseAsUintValue(
			r.FormValue("ctx"),
			0,
			maxLinesOfContext,
			defaultLinesOfContext)

		var filesOpened int
		var durationMs int

		results, err := searchAll(query, &opt, repos, idx, &filesOpened, &durationMs)
		if err != nil {
			writeError(w, err)
			return
		}

		var res struct {
			Results map[string]*index.SearchResponse
			Stats   *Stats `json:",omitempty"`
		}

		res.Results = results
		if stats {
			res.Stats = &Stats{
				FilesOpened: filesOpened,
				Duration:    durationMs,
			}
		}

		writeJson(w, &res)
	})

	m.HandleFunc("/api/v1/excludes", func(w http.ResponseWriter, r *http.Request) {
		repo := r.FormValue("repo")
		res := idx[repo].GetExcludedFiles()
		w.Header().Set("Content-Type", "application/json;charset=utf-8")
		w.Header().Set("Access-Control-Allow", "*")
		fmt.Fprint(w, res)
	})
}
<|endoftext|>


<commit_before>package ast

import "github.com/Zac-Garby/pluto/token"

/* ExpressionStatement */
type ExpressionStatement struct {
	Tok  token.Token
	Expr Expression
}

func (_ ExpressionStatement) Stmt()              {}
func (n ExpressionStatement) Token() token.Token { return n.Tok }

/* BlockStatement */
type BlockStatement struct {
	Tok        token.Token
	Statements []Statement
}

func (_ BlockStatement) Stmt()              {}
func (n BlockStatement) Token() token.Token { return n.Tok }

/* FunctionDefinition */
type FunctionDefinition struct {
	Tok     token.Token
	Pattern []Expression
	Body    Statement
}

func (_ FunctionDefinition) Stmt()              {}
func (n FunctionDefinition) Token() token.Token { return n.Tok }

/* InitDefinition */
type InitDefinition struct {
	Tok     token.Token
	Pattern []Expression
	Body    Statement
}

func (_ InitDefinition) Stmt()              {}
func (n InitDefinition) Token() token.Token { return n.Tok }

/* ReturnStatement */
type ReturnStatement struct {
	Tok   token.Token
	Value Expression
}

func (_ ReturnStatement) Stmt()              {}
func (n ReturnStatement) Token() token.Token { return n.Tok }

/* NextStatement */
type NextStatement struct {
	Tok token.Token
}

func (_ NextStatement) Stmt()              {}
func (n NextStatement) Token() token.Token { return n.Tok }

/* BreakStatement */
type BreakStatement struct {
	Tok token.Token
}

func (_ BreakStatement) Stmt()              {}
func (n BreakStatement) Token() token.Token { return n.Tok }

/* ClassStatement */
type ClassStatement struct {
	Tok          token.Token
	Name, Parent Expression
	Methods      []Statement
}

func (_ ClassStatement) Stmt()              {}
func (n ClassStatement) Token() token.Token { return n.Tok }
<commit_msg>Define 'import' and 'use' AST nodes<commit_after>package ast

import "github.com/Zac-Garby/pluto/token"

/* ExpressionStatement */
type ExpressionStatement struct {
	Tok  token.Token
	Expr Expression
}

func (_ ExpressionStatement) Stmt()              {}
func (n ExpressionStatement) Token() token.Token { return n.Tok }

/* BlockStatement */
type BlockStatement struct {
	Tok        token.Token
	Statements []Statement
}

func (_ BlockStatement) Stmt()              {}
func (n BlockStatement) Token() token.Token { return n.Tok }

/* FunctionDefinition */
type FunctionDefinition struct {
	Tok     token.Token
	Pattern []Expression
	Body    Statement
}

func (_ FunctionDefinition) Stmt()              {}
func (n FunctionDefinition) Token() token.Token { return n.Tok }

/* InitDefinition */
type InitDefinition struct {
	Tok     token.Token
	Pattern []Expression
	Body    Statement
}

func (_ InitDefinition) Stmt()              {}
func (n InitDefinition) Token() token.Token { return n.Tok }

/* ReturnStatement */
type ReturnStatement struct {
	Tok   token.Token
	Value Expression
}

func (_ ReturnStatement) Stmt()              {}
func (n ReturnStatement) Token() token.Token { return n.Tok }

/* NextStatement */
type NextStatement struct {
	Tok token.Token
}

func (_ NextStatement) Stmt()              {}
func (n NextStatement) Token() token.Token { return n.Tok }

/* BreakStatement */
type BreakStatement struct {
	Tok token.Token
}

func (_ BreakStatement) Stmt()              {}
func (n BreakStatement) Token() token.Token { return n.Tok }

/* ClassStatement */
type ClassStatement struct {
	Tok          token.Token
	Name, Parent Expression
	Methods      []Statement
}

func (_ ClassStatement) Stmt()              {}
func (n ClassStatement) Token() token.Token { return n.Tok }

/* ImportStatement */
type ImportStatement struct {
	Tok     token.Token
	Package string
}

func (_ ImportStatement) Stmt()              {}
func (n ImportStatement) Token() token.Token { return n.Tok }

/* UseStatement */
type UseStatement struct {
	Tok     token.Token
	Package string
}

func (_ UseStatement) Stmt()              {}
func (n UseStatement) Token() token.Token { return n.Tok }
<|endoftext|>