<commit_before>// This file was auto-generated by the veyron vdl tool.
// Source: wire.vdl

package pingpong

import (
	"veyron.io/veyron/veyron2/security"

	// The non-user imports are prefixed with "__" to prevent collisions.
	__veyron2 "veyron.io/veyron/veyron2"
	__context "veyron.io/veyron/veyron2/context"
	__ipc "veyron.io/veyron/veyron2/ipc"
	__vdlutil "veyron.io/veyron/veyron2/vdl/vdlutil"
	__wiretype "veyron.io/veyron/veyron2/wiretype"
)

// TODO(toddw): Remove this line once the new signature support is done.
// It corrects a bug where __wiretype is unused in VDL pacakges where only
// bootstrap types are used on interfaces.
const _ = __wiretype.TypeIDInvalid

// PingPongClientMethods is the client interface
// containing PingPong methods.
type PingPongClientMethods interface {
	Ping(ctx __context.T, message string, opts ...__ipc.CallOpt) (string, error)
}

// PingPongClientStub adds universal methods to PingPongClientMethods.
type PingPongClientStub interface {
	PingPongClientMethods
	__ipc.UniversalServiceMethods
}

// PingPongClient returns a client stub for PingPong.
func PingPongClient(name string, opts ...__ipc.BindOpt) PingPongClientStub {
	var client __ipc.Client
	for _, opt := range opts {
		if clientOpt, ok := opt.(__ipc.Client); ok {
			client = clientOpt
		}
	}
	return implPingPongClientStub{name, client}
}

type implPingPongClientStub struct {
	name   string
	client __ipc.Client
}

func (c implPingPongClientStub) c(ctx __context.T) __ipc.Client {
	if c.client != nil {
		return c.client
	}
	return __veyron2.RuntimeFromContext(ctx).Client()
}

func (c implPingPongClientStub) Ping(ctx __context.T, i0 string, opts ...__ipc.CallOpt) (o0 string, err error) {
	var call __ipc.Call
	if call, err = c.c(ctx).StartCall(ctx, c.name, "Ping", []interface{}{i0}, opts...); err != nil {
		return
	}
	if ierr := call.Finish(&o0, &err); ierr != nil {
		err = ierr
	}
	return
}

func (c implPingPongClientStub) Signature(ctx __context.T, opts ...__ipc.CallOpt) (o0 __ipc.ServiceSignature, err error) {
	var call __ipc.Call
	if call, err = c.c(ctx).StartCall(ctx, c.name, "Signature", nil, opts...); err != nil {
		return
	}
	if ierr := call.Finish(&o0, &err); ierr != nil {
		err = ierr
	}
	return
}

// PingPongServerMethods is the interface a server writer
// implements for PingPong.
type PingPongServerMethods interface {
	Ping(ctx __ipc.ServerContext, message string) (string, error)
}

// PingPongServerStubMethods is the server interface containing
// PingPong methods, as expected by ipc.Server.
// There is no difference between this interface and PingPongServerMethods
// since there are no streaming methods.
type PingPongServerStubMethods PingPongServerMethods

// PingPongServerStub adds universal methods to PingPongServerStubMethods.
type PingPongServerStub interface {
	PingPongServerStubMethods
	// Describe the PingPong interfaces.
	Describe__() []__ipc.InterfaceDesc
	// Signature will be replaced with Describe__.
	Signature(ctx __ipc.ServerContext) (__ipc.ServiceSignature, error)
}

// PingPongServer returns a server stub for PingPong.
// It converts an implementation of PingPongServerMethods into
// an object that may be used by ipc.Server.
func PingPongServer(impl PingPongServerMethods) PingPongServerStub {
	stub := implPingPongServerStub{
		impl: impl,
	}
	// Initialize GlobState; always check the stub itself first, to handle the
	// case where the user has the Glob method defined in their VDL source.
	if gs := __ipc.NewGlobState(stub); gs != nil {
		stub.gs = gs
	} else if gs := __ipc.NewGlobState(impl); gs != nil {
		stub.gs = gs
	}
	return stub
}

type implPingPongServerStub struct {
	impl PingPongServerMethods
	gs   *__ipc.GlobState
}

func (s implPingPongServerStub) Ping(ctx __ipc.ServerContext, i0 string) (string, error) {
	return s.impl.Ping(ctx, i0)
}

func (s implPingPongServerStub) VGlob() *__ipc.GlobState {
	return s.gs
}

func (s implPingPongServerStub) Describe__() []__ipc.InterfaceDesc {
	return []__ipc.InterfaceDesc{PingPongDesc}
}

// PingPongDesc describes the PingPong interface.
var PingPongDesc __ipc.InterfaceDesc = descPingPong

// descPingPong hides the desc to keep godoc clean.
var descPingPong = __ipc.InterfaceDesc{
	Name:    "PingPong",
	PkgPath: "veyron.io/playground/testdata/src/pingpong",
	Methods: []__ipc.MethodDesc{
		{
			Name: "Ping",
			InArgs: []__ipc.ArgDesc{
				{"message", ``}, // string
			},
			OutArgs: []__ipc.ArgDesc{
				{"", ``}, // string
				{"", ``}, // error
			},
			Tags: []__vdlutil.Any{security.Label(2)},
		},
	},
}

func (s implPingPongServerStub) Signature(ctx __ipc.ServerContext) (__ipc.ServiceSignature, error) {
	// TODO(toddw): Replace with new Describe__ implementation.
	result := __ipc.ServiceSignature{Methods: make(map[string]__ipc.MethodSignature)}
	result.Methods["Ping"] = __ipc.MethodSignature{
		InArgs: []__ipc.MethodArgument{
			{Name: "message", Type: 3},
		},
		OutArgs: []__ipc.MethodArgument{
			{Name: "", Type: 3},
			{Name: "", Type: 65},
		},
	}

	result.TypeDefs = []__vdlutil.Any{
		__wiretype.NamedPrimitiveType{Type: 0x1, Name: "error", Tags: []string(nil)}}

	return result, nil
}
<commit_msg>TBR playground: Fix VDL<commit_after>// This file was auto-generated by the veyron vdl tool.
// Source: wire.vdl

package pingpong

import (
	"veyron.io/veyron/veyron2/security"

	// The non-user imports are prefixed with "__" to prevent collisions.
	__veyron2 "veyron.io/veyron/veyron2"
	__context "veyron.io/veyron/veyron2/context"
	__ipc "veyron.io/veyron/veyron2/ipc"
	__vdlutil "veyron.io/veyron/veyron2/vdl/vdlutil"
	__wiretype "veyron.io/veyron/veyron2/wiretype"
)

// TODO(toddw): Remove this line once the new signature support is done.
// It corrects a bug where __wiretype is unused in VDL pacakges where only
// bootstrap types are used on interfaces.
const _ = __wiretype.TypeIDInvalid

// PingPongClientMethods is the client interface
// containing PingPong methods.
type PingPongClientMethods interface {
	Ping(ctx __context.T, message string, opts ...__ipc.CallOpt) (string, error)
}

// PingPongClientStub adds universal methods to PingPongClientMethods.
type PingPongClientStub interface {
	PingPongClientMethods
	__ipc.UniversalServiceMethods
}

// PingPongClient returns a client stub for PingPong.
func PingPongClient(name string, opts ...__ipc.BindOpt) PingPongClientStub {
	var client __ipc.Client
	for _, opt := range opts {
		if clientOpt, ok := opt.(__ipc.Client); ok {
			client = clientOpt
		}
	}
	return implPingPongClientStub{name, client}
}

type implPingPongClientStub struct {
	name   string
	client __ipc.Client
}

func (c implPingPongClientStub) c(ctx __context.T) __ipc.Client {
	if c.client != nil {
		return c.client
	}
	return __veyron2.RuntimeFromContext(ctx).Client()
}

func (c implPingPongClientStub) Ping(ctx __context.T, i0 string, opts ...__ipc.CallOpt) (o0 string, err error) {
	var call __ipc.Call
	if call, err = c.c(ctx).StartCall(ctx, c.name, "Ping", []interface{}{i0}, opts...); err != nil {
		return
	}
	if ierr := call.Finish(&o0, &err); ierr != nil {
		err = ierr
	}
	return
}

func (c implPingPongClientStub) Signature(ctx __context.T, opts ...__ipc.CallOpt) (o0 __ipc.ServiceSignature, err error) {
	var call __ipc.Call
	if call, err = c.c(ctx).StartCall(ctx, c.name, "Signature", nil, opts...); err != nil {
		return
	}
	if ierr := call.Finish(&o0, &err); ierr != nil {
		err = ierr
	}
	return
}

// PingPongServerMethods is the interface a server writer
// implements for PingPong.
type PingPongServerMethods interface {
	Ping(ctx __ipc.ServerContext, message string) (string, error)
}

// PingPongServerStubMethods is the server interface containing
// PingPong methods, as expected by ipc.Server.
// There is no difference between this interface and PingPongServerMethods
// since there are no streaming methods.
type PingPongServerStubMethods PingPongServerMethods

// PingPongServerStub adds universal methods to PingPongServerStubMethods.
type PingPongServerStub interface {
	PingPongServerStubMethods
	// Describe the PingPong interfaces.
	Describe__() []__ipc.InterfaceDesc
	// Signature will be replaced with Describe__.
	Signature(ctx __ipc.ServerContext) (__ipc.ServiceSignature, error)
}

// PingPongServer returns a server stub for PingPong.
// It converts an implementation of PingPongServerMethods into
// an object that may be used by ipc.Server.
func PingPongServer(impl PingPongServerMethods) PingPongServerStub {
	stub := implPingPongServerStub{
		impl: impl,
	}
	// Initialize GlobState; always check the stub itself first, to handle the
	// case where the user has the Glob method defined in their VDL source.
	if gs := __ipc.NewGlobState(stub); gs != nil {
		stub.gs = gs
	} else if gs := __ipc.NewGlobState(impl); gs != nil {
		stub.gs = gs
	}
	return stub
}

type implPingPongServerStub struct {
	impl PingPongServerMethods
	gs   *__ipc.GlobState
}

func (s implPingPongServerStub) Ping(ctx __ipc.ServerContext, i0 string) (string, error) {
	return s.impl.Ping(ctx, i0)
}

func (s implPingPongServerStub) Globber() *__ipc.GlobState {
	return s.gs
}

func (s implPingPongServerStub) Describe__() []__ipc.InterfaceDesc {
	return []__ipc.InterfaceDesc{PingPongDesc}
}

// PingPongDesc describes the PingPong interface.
var PingPongDesc __ipc.InterfaceDesc = descPingPong

// descPingPong hides the desc to keep godoc clean.
var descPingPong = __ipc.InterfaceDesc{
	Name:    "PingPong",
	PkgPath: "veyron.io/playground/testdata/src/pingpong",
	Methods: []__ipc.MethodDesc{
		{
			Name: "Ping",
			InArgs: []__ipc.ArgDesc{
				{"message", ``}, // string
			},
			OutArgs: []__ipc.ArgDesc{
				{"", ``}, // string
				{"", ``}, // error
			},
			Tags: []__vdlutil.Any{security.Label(2)},
		},
	},
}

func (s implPingPongServerStub) Signature(ctx __ipc.ServerContext) (__ipc.ServiceSignature, error) {
	// TODO(toddw): Replace with new Describe__ implementation.
	result := __ipc.ServiceSignature{Methods: make(map[string]__ipc.MethodSignature)}
	result.Methods["Ping"] = __ipc.MethodSignature{
		InArgs: []__ipc.MethodArgument{
			{Name: "message", Type: 3},
		},
		OutArgs: []__ipc.MethodArgument{
			{Name: "", Type: 3},
			{Name: "", Type: 65},
		},
	}

	result.TypeDefs = []__vdlutil.Any{
		__wiretype.NamedPrimitiveType{Type: 0x1, Name: "error", Tags: []string(nil)}}

	return result, nil
}
<|endoftext|>


<commit_before>package boomer

import (
	"time"
	"log"
)

type RequestStats struct {
	Entries              map[string]*StatsEntry
	Errors               map[string]*StatsError
	NumRequests          int64
	NumFailures          int64
	MaxRequests          int64
	LastRequestTimestamp int64
	StartTime            int64
}

func (this *RequestStats) get(name string, method string) (entry *StatsEntry) {
	entry, ok := this.Entries[name+method]
	if !ok {
		entry = &StatsEntry{
			Stats:         this,
			Name:          name,
			Method:        method,
			NumReqsPerSec: make(map[int64]int64),
			ResponseTimes: make(map[float64]int64),
		}
		entry.reset()
		this.Entries[name+method] = entry
	}
	entry, ok = this.Entries[name+method]
	if !ok {
		log.Fatal(ok, "entry is null, why?")
	}
	return entry
}

func (this *RequestStats) clearAll() {
	this.NumRequests = 0
	this.NumFailures = 0
	this.Entries = make(map[string]*StatsEntry)
	this.Errors = make(map[string]*StatsError)
	this.MaxRequests = 0
	this.LastRequestTimestamp = 0
	this.StartTime = 0
}

type StatsEntry struct {
	Stats                *RequestStats
	Name                 string
	Method               string
	NumRequests          int64
	NumFailures          int64
	TotalResponseTime    float64
	MinResponseTime      float64
	MaxResponseTime      float64
	NumReqsPerSec        map[int64]int64
	ResponseTimes        map[float64]int64
	TotalContentLength   int64
	StartTime            int64
	LastRequestTimestamp int64
}

func (this *StatsEntry) reset() {
	this.StartTime = int64(time.Now().Unix())
	this.NumRequests = 0
	this.NumFailures = 0
	this.TotalResponseTime = 0
	this.ResponseTimes = make(map[float64]int64)
	this.MinResponseTime = 0
	this.MaxResponseTime = 0
	this.LastRequestTimestamp = int64(time.Now().Unix())
	this.NumReqsPerSec = make(map[int64]int64)
	this.TotalContentLength = 0
}

func (this *StatsEntry) log(responseTime float64, contentLength int64) {

	this.NumRequests += 1

	this.logTimeOfRequest()
	this.logResponseTime(responseTime)

	this.TotalContentLength += contentLength

}

func (this *StatsEntry) logTimeOfRequest() {

	now := int64(time.Now().Unix())

	_, ok := this.NumReqsPerSec[now]
	if !ok {
		this.NumReqsPerSec[now] = 0
	} else {
		this.NumReqsPerSec[now] += 1
	}

	this.LastRequestTimestamp = now

}

func (this *StatsEntry) logResponseTime(responseTime float64) {
	this.TotalResponseTime += responseTime

	if this.MinResponseTime == 0 {
		this.MinResponseTime = responseTime
	}

	if responseTime < this.MinResponseTime {
		this.MinResponseTime = responseTime
	}

	if responseTime > this.MaxResponseTime {
		this.MaxResponseTime = responseTime
	}

	roundedResponseTime := float64(0)

	if responseTime < 100 {
		roundedResponseTime = responseTime
	} else if responseTime < 1000 {
		roundedResponseTime = float64(Round(responseTime, .5, -1))
	} else if responseTime < 10000 {
		roundedResponseTime = float64(Round(responseTime, .5, -2))
	} else {
		roundedResponseTime = float64(Round(responseTime, .5, -3))
	}

	_, ok := this.ResponseTimes[roundedResponseTime]
	if !ok {
		this.ResponseTimes[roundedResponseTime] = 0
	} else {
		this.ResponseTimes[roundedResponseTime] += 1
	}

}

func (this *StatsEntry) logError(err string) {
	this.NumFailures += 1
	key := MD5(this.Method, this.Name, err)
	entry, ok := this.Stats.Errors[key]
	if !ok {
		entry = &StatsError{
			Name:   this.Name,
			Method: this.Method,
			Error:  err,
		}
		this.Stats.Errors[key] = entry
	}
	entry.occured()
}

func (this *StatsEntry) serialize() map[string]interface{} {
	result := make(map[string]interface{})
	result["name"] = this.Name
	result["method"] = this.Method
	result["last_request_timestamp"] = this.LastRequestTimestamp
	result["start_time"] = this.StartTime
	result["num_requests"] = this.NumRequests
	result["num_failures"] = this.NumFailures
	result["total_response_time"] = this.TotalResponseTime
	result["max_response_time"] = this.MaxResponseTime
	result["min_response_time"] = this.MinResponseTime
	result["total_content_length"] = this.TotalContentLength
	result["response_times"] = this.ResponseTimes
	result["num_reqs_per_sec"] = this.NumReqsPerSec
	return result
}

func (this *StatsEntry) getStrippedReport() map[string]interface{} {
	report := this.serialize()
	this.reset()
	return report
}

type StatsError struct {
	Name       string
	Method     string
	Error      string
	Occurences int64
}

func (this *StatsError) occured() {
	this.Occurences += 1
}

func (this *StatsError) toMap() map[string]interface{} {
	m := make(map[string]interface{})
	m["method"] = this.Method
	m["name"] = this.Name
	m["error"] = this.Error
	m["occurences"] = this.Occurences
	return m
}

func reportToMasterHandler(data *map[string]interface{}) {
	entries := make([]interface{}, 0, len(stats.Entries))
	for _, v := range stats.Entries {
		if !(v.NumRequests == 0 && v.NumFailures == 0) {
			entries = append(entries, v.getStrippedReport())
		}
	}

	errors := make(map[string]map[string]interface{})
	for k, v := range stats.Errors {
		errors[k] = v.toMap()
	}

	(*data)["stats"] = entries
	(*data)["errors"] = errors
	stats.Entries = make(map[string]*StatsEntry)
	stats.Errors = make(map[string]*StatsError)
}

type RequestSuccess struct {
	requestType    string
	name           string
	responseTime   float64
	responseLength int64
}

type RequestFailure struct {
	requestType  string
	name         string
	responseTime float64
	error        string
}

var stats = new(RequestStats)
var RequestSuccessChannel = make(chan *RequestSuccess, 100)
var RequestFailureChannel = make(chan *RequestFailure, 100)
var ClearStatsChannel = make(chan bool)

func init() {
	Events.Subscribe("boomer:report_to_master", reportToMasterHandler)
	stats.Entries = make(map[string]*StatsEntry)
	stats.Errors = make(map[string]*StatsError)
	go func() {
		for {
			select {
			case m := <-RequestSuccessChannel:
				stats.get(m.name, m.requestType).log(m.responseTime, m.responseLength)
			case n := <-RequestFailureChannel:
				stats.get(n.name, n.requestType).logError(n.error)
			case <-ClearStatsChannel:
				stats.clearAll()
			}
		}
	}()
}
<commit_msg>FIX: nil pointer dereference<commit_after>package boomer

import (
	"time"
	"log"
)

type RequestStats struct {
	Entries              map[string]*StatsEntry
	Errors               map[string]*StatsError
	NumRequests          int64
	NumFailures          int64
	MaxRequests          int64
	LastRequestTimestamp int64
	StartTime            int64
}

func (this *RequestStats) get(name string, method string) (entry *StatsEntry) {
	entry, ok := this.Entries[name+method]
	if !ok {
		newEntry := &StatsEntry{
			Stats:         this,
			Name:          name,
			Method:        method,
			NumReqsPerSec: make(map[int64]int64),
			ResponseTimes: make(map[float64]int64),
		}
		newEntry.reset()
		this.Entries[name+method] = newEntry
		return newEntry
	} else {
		return entry
	}

}

func (this *RequestStats) clearAll() {
	this.NumRequests = 0
	this.NumFailures = 0
	this.Entries = make(map[string]*StatsEntry)
	this.Errors = make(map[string]*StatsError)
	this.MaxRequests = 0
	this.LastRequestTimestamp = 0
	this.StartTime = 0
}

type StatsEntry struct {
	Stats                *RequestStats
	Name                 string
	Method               string
	NumRequests          int64
	NumFailures          int64
	TotalResponseTime    float64
	MinResponseTime      float64
	MaxResponseTime      float64
	NumReqsPerSec        map[int64]int64
	ResponseTimes        map[float64]int64
	TotalContentLength   int64
	StartTime            int64
	LastRequestTimestamp int64
}

func (this *StatsEntry) reset() {
	this.StartTime = int64(time.Now().Unix())
	this.NumRequests = 0
	this.NumFailures = 0
	this.TotalResponseTime = 0
	this.ResponseTimes = make(map[float64]int64)
	this.MinResponseTime = 0
	this.MaxResponseTime = 0
	this.LastRequestTimestamp = int64(time.Now().Unix())
	this.NumReqsPerSec = make(map[int64]int64)
	this.TotalContentLength = 0
}

func (this *StatsEntry) log(responseTime float64, contentLength int64) {

	this.NumRequests += 1

	this.logTimeOfRequest()
	this.logResponseTime(responseTime)

	this.TotalContentLength += contentLength

}

func (this *StatsEntry) logTimeOfRequest() {

	now := int64(time.Now().Unix())

	_, ok := this.NumReqsPerSec[now]
	if !ok {
		this.NumReqsPerSec[now] = 0
	} else {
		this.NumReqsPerSec[now] += 1
	}

	this.LastRequestTimestamp = now

}

func (this *StatsEntry) logResponseTime(responseTime float64) {
	this.TotalResponseTime += responseTime

	if this.MinResponseTime == 0 {
		this.MinResponseTime = responseTime
	}

	if responseTime < this.MinResponseTime {
		this.MinResponseTime = responseTime
	}

	if responseTime > this.MaxResponseTime {
		this.MaxResponseTime = responseTime
	}

	roundedResponseTime := float64(0)

	if responseTime < 100 {
		roundedResponseTime = responseTime
	} else if responseTime < 1000 {
		roundedResponseTime = float64(Round(responseTime, .5, -1))
	} else if responseTime < 10000 {
		roundedResponseTime = float64(Round(responseTime, .5, -2))
	} else {
		roundedResponseTime = float64(Round(responseTime, .5, -3))
	}

	_, ok := this.ResponseTimes[roundedResponseTime]
	if !ok {
		this.ResponseTimes[roundedResponseTime] = 0
	} else {
		this.ResponseTimes[roundedResponseTime] += 1
	}

}

func (this *StatsEntry) logError(err string) {
	this.NumFailures += 1
	key := MD5(this.Method, this.Name, err)
	entry, ok := this.Stats.Errors[key]
	if !ok {
		entry = &StatsError{
			Name:   this.Name,
			Method: this.Method,
			Error:  err,
		}
		this.Stats.Errors[key] = entry
	}
	entry.occured()
}

func (this *StatsEntry) serialize() map[string]interface{} {
	result := make(map[string]interface{})
	result["name"] = this.Name
	result["method"] = this.Method
	result["last_request_timestamp"] = this.LastRequestTimestamp
	result["start_time"] = this.StartTime
	result["num_requests"] = this.NumRequests
	result["num_failures"] = this.NumFailures
	result["total_response_time"] = this.TotalResponseTime
	result["max_response_time"] = this.MaxResponseTime
	result["min_response_time"] = this.MinResponseTime
	result["total_content_length"] = this.TotalContentLength
	result["response_times"] = this.ResponseTimes
	result["num_reqs_per_sec"] = this.NumReqsPerSec
	return result
}

func (this *StatsEntry) getStrippedReport() map[string]interface{} {
	report := this.serialize()
	this.reset()
	return report
}

type StatsError struct {
	Name       string
	Method     string
	Error      string
	Occurences int64
}

func (this *StatsError) occured() {
	this.Occurences += 1
}

func (this *StatsError) toMap() map[string]interface{} {
	m := make(map[string]interface{})
	m["method"] = this.Method
	m["name"] = this.Name
	m["error"] = this.Error
	m["occurences"] = this.Occurences
	return m
}

func reportToMasterHandler(data *map[string]interface{}) {
	entries := make([]interface{}, 0, len(stats.Entries))
	for _, v := range stats.Entries {
		if !(v.NumRequests == 0 && v.NumFailures == 0) {
			entries = append(entries, v.getStrippedReport())
		}
	}

	errors := make(map[string]map[string]interface{})
	for k, v := range stats.Errors {
		errors[k] = v.toMap()
	}

	(*data)["stats"] = entries
	(*data)["errors"] = errors
	stats.Entries = make(map[string]*StatsEntry)
	stats.Errors = make(map[string]*StatsError)
}

type RequestSuccess struct {
	requestType    string
	name           string
	responseTime   float64
	responseLength int64
}

type RequestFailure struct {
	requestType  string
	name         string
	responseTime float64
	error        string
}

var stats = new(RequestStats)
var RequestSuccessChannel = make(chan *RequestSuccess, 100)
var RequestFailureChannel = make(chan *RequestFailure, 100)
var ClearStatsChannel = make(chan bool)

func init() {
	Events.Subscribe("boomer:report_to_master", reportToMasterHandler)
	stats.Entries = make(map[string]*StatsEntry)
	stats.Errors = make(map[string]*StatsError)
	go func() {
		for {
			select {
			case m := <-RequestSuccessChannel:
				entry := stats.get(m.name, m.requestType)
				if entry == nil {
					log.Fatal("entry is nil, WTF?")
				}
				entry.log(m.responseTime, m.responseLength)
			case n := <-RequestFailureChannel:
				stats.get(n.name, n.requestType).logError(n.error)
			case <-ClearStatsChannel:
				stats.clearAll()
			}
		}
	}()
}
<|endoftext|>


<commit_before>// Package store automatically configures a database to store structured information in an sql database
package store

import (
	"database/sql"
	"errors"
	"reflect"
	"strings"
	"sync"
)

const (
	add = iota
	get
	update
	remove
	getPage
	count
)

type field struct {
	isStruct bool
	pos      int
	name     string
}

type typeInfo struct {
	primary    int
	fields     []field
	statements []*sql.Stmt
}

type Store struct {
	db    *sql.DB
	types map[string]typeInfo
	mutex sync.Mutex
}

func New(driverName, dataSourceName string) (*Store, error) {
	db, err := sql.Open(driverName, dataSourceName)
	if err != nil {
		return nil, err
	}
	return &Store{
		db:    db,
		types: make(map[string]typeInfo),
	}, nil
}

func (s *Store) Close() error {
	err := s.db.Close()
	s.db = nil
	return err
}

func isPointerStruct(i interface{}) bool {
	t := reflect.TypeOf(i)
	return t.Kind() == reflect.Ptr && t.Elem().Kind() == reflect.Struct
}

func (s *Store) Register(i interface{}) error {
	if s.db == nil {
		return DBClosed
	} else if !isPointerStruct(i) {
		return NoPointerStruct
	}
	s.mutex.Lock()
	defer s.mutex.Unlock()
	return s.defineType(i)
}

func (s *Store) defineType(i interface{}) error {
	name := typeName(i)
	if _, ok := s.types[name]; ok {
		return nil
	}

	s.types[name] = typeInfo{}

	v := reflect.ValueOf(i).Elem()
	numFields := v.Type().NumField()
	fields := make([]field, 0, numFields)
	id := 0
	idType := 0

	for n := 0; n < numFields; n++ {
		f := v.Type().Field(n)
		if f.PkgPath != "" { // not exported
			continue
		}
		fieldName := f.Name
		if fn := f.Tag.Get("store"); fn != "" {
			fieldName = fn
		}
		if fieldName == "-" { // Skip field
			continue
		}
		tmp := strings.ToLower(fieldName)
		for _, tf := range fields {
			if strings.ToLower(tf.name) == tmp {
				return DuplicateColumn
			}
		}
		isPointer := f.Type.Kind() == reflect.Ptr
		var iface interface{}
		if isPointer {
			iface = v.Field(n).Interface()
		} else {
			iface = v.Field(n).Addr().Interface()
		}
		isStruct := false
		if isPointerStruct(iface) {
			s.defineType(iface)
			isStruct = true
		} else if !isValidType(iface) {
			continue
		}
		if isValidKeyType(iface) {
			if idType < 3 && f.Tag.Get("key") == "1" {
				idType = 3
				id = len(fields)
			} else if idType < 2 && strings.ToLower(fieldName) == "id" {
				idType = 2
				id = len(fields)
			} else if idType < 1 {
				idType = 1
				id = len(fields)
			}
		}
		fields = append(fields, field{
			isStruct,
			n,
			fieldName,
		})
	}
	if idType == 0 {
		return NoKey
	}
	s.types[name] = typeInfo{
		primary: id,
	}

	// create statements
	var (
		sqlVars, sqlParams, setSQLParams, tableVars string
		doneFirst, doneFirstNonKey                  bool
	)

	for pos, f := range fields {
		if doneFirst {
			tableVars += ", "
		} else {
			doneFirst = true
		}
		if pos != id {
			if doneFirstNonKey {
				sqlVars += ", "
				setSQLParams += ", "
				sqlParams += ", "
			} else {
				doneFirstNonKey = true
			}
		}
		var varType string
		if f.isStruct {
			varType = "INTEGER"
		} else {
			varType = getType(i, f.pos)
		}
		tableVars += "[" + f.name + "] " + varType
		if pos == id {
			tableVars += " PRIMARY KEY AUTOINCREMENT"
		} else {
			sqlVars += "[" + f.name + "]"
			setSQLParams += "[" + f.name + "] = ?"
			sqlParams += "?"
		}
	}

	statements := make([]*sql.Stmt, 6)

	sql := "CREATE TABLE IF NOT EXISTS [" + name + "](" + tableVars + ");"
	_, err := s.db.Exec(sql)
	if err != nil {
		return err
	}

	sql = "INSERT INTO [" + name + "] (" + sqlVars + ") VALUES (" + sqlParams + ");"
	stmt, err := s.db.Prepare(sql)
	if err != nil {
		return err
	}
	statements[add] = stmt

	sql = "SELECT " + sqlVars + " FROM [" + name + "] WHERE [" + fields[id].name + "] = ? LIMIT 1;"
	stmt, err = s.db.Prepare(sql)
	if err != nil {
		return err
	}
	statements[get] = stmt

	sql = "UPDATE [" + name + "] SET " + setSQLParams + " WHERE [" + fields[id].name + "] = ?;"
	stmt, err = s.db.Prepare(sql)
	if err != nil {
		return err
	}
	statements[update] = stmt

	sql = "DELETE FROM [" + name + "] WHERE [" + fields[id].name + "] = ?;"
	stmt, err = s.db.Prepare(sql)
	if err != nil {
		return err
	}
	statements[remove] = stmt

	sql = "SELECT " + sqlVars + ", [" + fields[id].name + "] FROM [" + name + "] ORDER BY [" + fields[id].name + "] LIMIT ? OFFSET ?;"
	stmt, err = s.db.Prepare(sql)
	if err != nil {
		return err
	}
	statements[getPage] = stmt

	sql = "SELECT COUNT(1) FROM [" + name + "];"
	stmt, err = s.db.Prepare(sql)
	if err != nil {
		return err
	}
	statements[count] = stmt

	s.types[name] = typeInfo{
		primary:    id,
		fields:     fields,
		statements: statements,
	}
	return nil
}

func (s *Store) Set(is ...interface{}) error {
	var toSet []interface{}
	for _, i := range is {
		t, ok := s.types[typeName(i)]
		if !ok {
			return UnregisteredType
		}
		toSet = toSet[:0]
		err := s.Set(i, &t, &toSet)
		if err != nil {
			return err
		}
	}
	return nil
}

func (s *Store) set(i interface{}, t *typeInfo, toSet *[]interface{}) error {
	for _, oi := range *toSet {
		if oi == i {
			return nil
		}
	}
	(*toSet) = append(*toSet, i)
	id := t.GetID(i)
	isUpdate := id != 0
	vars := make([]interface{}, 0, len(t.fields))
	for pos, f := range t.fields {
		if pos == t.primary {
			continue
		}
		if f.isStruct {
			ni := getFieldPointer(i, f.pos)
			nt := s.types[typeName(ni)]
			err := s.Set(ni, &nt, toSet)
			if err != nil {
				return err
			}
			vars = append(vars, getField(ni, nt.fields[nt.primary].pos))
		} else {
			vars = append(vars, getField(i, f.pos))
		}
	}
	if isUpdate {
		vars = append(vars, id)
		_, err := t.statements[update].Exec(vars...)
		return err
	}
	r, err := t.statements[add].Exec(vars...)
	if err != nil {
		return err
	}
	lid, err := r.LastInsertId()
	if err != nil {
		return err
	}
	t.SetID(i, lid)
	return nil
}

func (s *Store) Get(is ...interface{}) error {
	for _, i := range is {
		t, ok := s.types[typeName(i)]
		if !ok {
			return UnregisteredType
		}
		id := t.GetID(i)
		if id == 0 {
			continue
		}
		vars := make([]interface{}, 0, len(t.fields))
		var toGet []interface{}
		for pos, f := range t.fields {
			if pos == t.primary {
				continue
			}
			if f.isStruct {
				ni := getFieldPointer(i, f.pos)
				nt := s.types[typeName(ni)]
				toGet = append(toGet, ni)
				vars = append(vars, getFieldPointer(ni, nt.fields[nt.primary].pos))
			} else {
				vars = append(vars, getFieldPointer(i, f.pos))
			}
		}
		row := t.statements[get].QueryRow(id)
		err := row.Scan(vars...)
		if err != nil {
			return err
		}
		if len(toGet) > 0 {
			if err = s.Get(toGet...); err != nil {
				return err
			}
		}
	}
	return nil
}

func (s *Store) Remove(is ...interface{}) error {
	for _, i := range is {
		t, ok := s.types[typeName(i)]
		if !ok {
			return UnregisteredType
		}
		_, err := t.statements[remove].Exec(t.GetID(i))
		if err != nil {
			return err
		}
	}
	return nil
}

func (s *Store) Count(i interface{}) (int, error) {
	s.mutex.Lock()
	defer s.mutex.Unlock()
	if !isPointerStruct(i) {
		return 0, NoPointerStruct
	}
	name := typeName(i)
	stmt := s.types[name].statements[count]
	res, err := stmt.Query()
	if err != nil {
		return 0, err
	}
	num := 0
	err = res.Scan(&num)
	return num, err
}

// Errors

var (
	DBClosed         = errors.New("database already closed")
	NoPointerStruct  = errors.New("given variable is not a pointer to a struct")
	NoKey            = errors.New("could not determine key")
	DuplicateColumn  = errors.New("duplicate column name found")
	UnregisteredType = errors.New("type not registered")
)
<commit_msg>Added locks<commit_after>// Package store automatically configures a database to store structured information in an sql database
package store

import (
	"database/sql"
	"errors"
	"reflect"
	"strings"
	"sync"
)

const (
	add = iota
	get
	update
	remove
	getPage
	count
)

type field struct {
	isStruct bool
	pos      int
	name     string
}

type typeInfo struct {
	primary    int
	fields     []field
	statements []*sql.Stmt
}

type Store struct {
	db    *sql.DB
	types map[string]typeInfo
	mutex sync.Mutex
}

func New(driverName, dataSourceName string) (*Store, error) {
	db, err := sql.Open(driverName, dataSourceName)
	if err != nil {
		return nil, err
	}
	return &Store{
		db:    db,
		types: make(map[string]typeInfo),
	}, nil
}

func (s *Store) Close() error {
	err := s.db.Close()
	s.db = nil
	return err
}

func isPointerStruct(i interface{}) bool {
	t := reflect.TypeOf(i)
	return t.Kind() == reflect.Ptr && t.Elem().Kind() == reflect.Struct
}

func (s *Store) Register(i interface{}) error {
	if s.db == nil {
		return DBClosed
	} else if !isPointerStruct(i) {
		return NoPointerStruct
	}
	s.mutex.Lock()
	defer s.mutex.Unlock()
	return s.defineType(i)
}

func (s *Store) defineType(i interface{}) error {
	name := typeName(i)
	if _, ok := s.types[name]; ok {
		return nil
	}

	s.types[name] = typeInfo{}

	v := reflect.ValueOf(i).Elem()
	numFields := v.Type().NumField()
	fields := make([]field, 0, numFields)
	id := 0
	idType := 0

	for n := 0; n < numFields; n++ {
		f := v.Type().Field(n)
		if f.PkgPath != "" { // not exported
			continue
		}
		fieldName := f.Name
		if fn := f.Tag.Get("store"); fn != "" {
			fieldName = fn
		}
		if fieldName == "-" { // Skip field
			continue
		}
		tmp := strings.ToLower(fieldName)
		for _, tf := range fields {
			if strings.ToLower(tf.name) == tmp {
				return DuplicateColumn
			}
		}
		isPointer := f.Type.Kind() == reflect.Ptr
		var iface interface{}
		if isPointer {
			iface = v.Field(n).Interface()
		} else {
			iface = v.Field(n).Addr().Interface()
		}
		isStruct := false
		if isPointerStruct(iface) {
			s.defineType(iface)
			isStruct = true
		} else if !isValidType(iface) {
			continue
		}
		if isValidKeyType(iface) {
			if idType < 3 && f.Tag.Get("key") == "1" {
				idType = 3
				id = len(fields)
			} else if idType < 2 && strings.ToLower(fieldName) == "id" {
				idType = 2
				id = len(fields)
			} else if idType < 1 {
				idType = 1
				id = len(fields)
			}
		}
		fields = append(fields, field{
			isStruct,
			n,
			fieldName,
		})
	}
	if idType == 0 {
		return NoKey
	}
	s.types[name] = typeInfo{
		primary: id,
	}

	// create statements
	var (
		sqlVars, sqlParams, setSQLParams, tableVars string
		doneFirst, doneFirstNonKey                  bool
	)

	for pos, f := range fields {
		if doneFirst {
			tableVars += ", "
		} else {
			doneFirst = true
		}
		if pos != id {
			if doneFirstNonKey {
				sqlVars += ", "
				setSQLParams += ", "
				sqlParams += ", "
			} else {
				doneFirstNonKey = true
			}
		}
		var varType string
		if f.isStruct {
			varType = "INTEGER"
		} else {
			varType = getType(i, f.pos)
		}
		tableVars += "[" + f.name + "] " + varType
		if pos == id {
			tableVars += " PRIMARY KEY AUTOINCREMENT"
		} else {
			sqlVars += "[" + f.name + "]"
			setSQLParams += "[" + f.name + "] = ?"
			sqlParams += "?"
		}
	}

	statements := make([]*sql.Stmt, 6)

	sql := "CREATE TABLE IF NOT EXISTS [" + name + "](" + tableVars + ");"
	_, err := s.db.Exec(sql)
	if err != nil {
		return err
	}

	sql = "INSERT INTO [" + name + "] (" + sqlVars + ") VALUES (" + sqlParams + ");"
	stmt, err := s.db.Prepare(sql)
	if err != nil {
		return err
	}
	statements[add] = stmt

	sql = "SELECT " + sqlVars + " FROM [" + name + "] WHERE [" + fields[id].name + "] = ? LIMIT 1;"
	stmt, err = s.db.Prepare(sql)
	if err != nil {
		return err
	}
	statements[get] = stmt

	sql = "UPDATE [" + name + "] SET " + setSQLParams + " WHERE [" + fields[id].name + "] = ?;"
	stmt, err = s.db.Prepare(sql)
	if err != nil {
		return err
	}
	statements[update] = stmt

	sql = "DELETE FROM [" + name + "] WHERE [" + fields[id].name + "] = ?;"
	stmt, err = s.db.Prepare(sql)
	if err != nil {
		return err
	}
	statements[remove] = stmt

	sql = "SELECT " + sqlVars + ", [" + fields[id].name + "] FROM [" + name + "] ORDER BY [" + fields[id].name + "] LIMIT ? OFFSET ?;"
	stmt, err = s.db.Prepare(sql)
	if err != nil {
		return err
	}
	statements[getPage] = stmt

	sql = "SELECT COUNT(1) FROM [" + name + "];"
	stmt, err = s.db.Prepare(sql)
	if err != nil {
		return err
	}
	statements[count] = stmt

	s.types[name] = typeInfo{
		primary:    id,
		fields:     fields,
		statements: statements,
	}
	return nil
}

func (s *Store) Set(is ...interface{}) error {
	s.mutex.Lock()
	defer s.mutex.Unlock()
	var toSet []interface{}
	for _, i := range is {
		t, ok := s.types[typeName(i)]
		if !ok {
			return UnregisteredType
		}
		toSet = toSet[:0]
		err := s.Set(i, &t, &toSet)
		if err != nil {
			return err
		}
	}
	return nil
}

func (s *Store) set(i interface{}, t *typeInfo, toSet *[]interface{}) error {
	for _, oi := range *toSet {
		if oi == i {
			return nil
		}
	}
	(*toSet) = append(*toSet, i)
	id := t.GetID(i)
	isUpdate := id != 0
	vars := make([]interface{}, 0, len(t.fields))
	for pos, f := range t.fields {
		if pos == t.primary {
			continue
		}
		if f.isStruct {
			ni := getFieldPointer(i, f.pos)
			nt := s.types[typeName(ni)]
			err := s.Set(ni, &nt, toSet)
			if err != nil {
				return err
			}
			vars = append(vars, getField(ni, nt.fields[nt.primary].pos))
		} else {
			vars = append(vars, getField(i, f.pos))
		}
	}
	if isUpdate {
		vars = append(vars, id)
		_, err := t.statements[update].Exec(vars...)
		return err
	}
	r, err := t.statements[add].Exec(vars...)
	if err != nil {
		return err
	}
	lid, err := r.LastInsertId()
	if err != nil {
		return err
	}
	t.SetID(i, lid)
	return nil
}

func (s *Store) Get(is ...interface{}) error {
	s.mutex.Lock()
	defer s.mutex.Unlock()
	return s.get(is...)
}
func (s *Store) get(is ...interface{}) error {
	for _, i := range is {
		t, ok := s.types[typeName(i)]
		if !ok {
			return UnregisteredType
		}
		id := t.GetID(i)
		if id == 0 {
			continue
		}
		vars := make([]interface{}, 0, len(t.fields))
		var toGet []interface{}
		for pos, f := range t.fields {
			if pos == t.primary {
				continue
			}
			if f.isStruct {
				ni := getFieldPointer(i, f.pos)
				nt := s.types[typeName(ni)]
				toGet = append(toGet, ni)
				vars = append(vars, getFieldPointer(ni, nt.fields[nt.primary].pos))
			} else {
				vars = append(vars, getFieldPointer(i, f.pos))
			}
		}
		row := t.statements[get].QueryRow(id)
		err := row.Scan(vars...)
		if err != nil {
			return err
		}
		if len(toGet) > 0 {
			if err = s.get(toGet...); err != nil {
				return err
			}
		}
	}
	return nil
}

func (s *Store) Remove(is ...interface{}) error {
	s.mutex.Lock()
	defer s.mutex.Unlock()
	for _, i := range is {
		t, ok := s.types[typeName(i)]
		if !ok {
			return UnregisteredType
		}
		_, err := t.statements[remove].Exec(t.GetID(i))
		if err != nil {
			return err
		}
	}
	return nil
}

func (s *Store) Count(i interface{}) (int, error) {
	s.mutex.Lock()
	defer s.mutex.Unlock()
	if !isPointerStruct(i) {
		return 0, NoPointerStruct
	}
	name := typeName(i)
	stmt := s.types[name].statements[count]
	res, err := stmt.Query()
	if err != nil {
		return 0, err
	}
	num := 0
	err = res.Scan(&num)
	return num, err
}

// Errors

var (
	DBClosed         = errors.New("database already closed")
	NoPointerStruct  = errors.New("given variable is not a pointer to a struct")
	NoKey            = errors.New("could not determine key")
	DuplicateColumn  = errors.New("duplicate column name found")
	UnregisteredType = errors.New("type not registered")
)
<|endoftext|>


<commit_before>package dbr

import (
	"bytes"
	"database/sql"
	"encoding/json"
	"time"

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

//
// Your app can use these Null types instead of the defaults. The sole benefit you get is a MarshalJSON method that is not retarded.
//

// NullString is a type that can be null or a string
type NullString struct {
	sql.NullString
}

// NullFloat64 is a type that can be null or a float64
type NullFloat64 struct {
	sql.NullFloat64
}

// NullInt64 is a type that can be null or an int
type NullInt64 struct {
	sql.NullInt64
}

// NullTime is a type that can be null or a time
type NullTime struct {
	mysql.NullTime
}

// NullBool is a type that can be null or a bool
type NullBool struct {
	sql.NullBool
}

var nullString = []byte("null")

// MarshalJSON correctly serializes a NullString to JSON
func (n *NullString) MarshalJSON() ([]byte, error) {
	if n.Valid {
		j, e := json.Marshal(n.String)
		return j, e
	}
	return nullString, nil
}

// MarshalJSON correctly serializes a NullInt64 to JSON
func (n *NullInt64) MarshalJSON() ([]byte, error) {
	if n.Valid {
		j, e := json.Marshal(n.Int64)
		return j, e
	}
	return nullString, nil
}

// MarshalJSON correctly serializes a NullFloat64 to JSON
func (n *NullFloat64) MarshalJSON() ([]byte, error) {
	if n.Valid {
		j, e := json.Marshal(n.Float64)
		return j, e
	}
	return nullString, nil
}

// MarshalJSON correctly serializes a NullTime to JSON
func (n *NullTime) MarshalJSON() ([]byte, error) {
	if n.Valid {
		j, e := json.Marshal(n.Time)
		return j, e
	}
	return nullString, nil
}

// MarshalJSON correctly serializes a NullBool to JSON
func (n *NullBool) MarshalJSON() ([]byte, error) {
	if n.Valid {
		j, e := json.Marshal(n.Bool)
		return j, e
	}
	return nullString, nil
}

// UnmarshalJSON correctly deserializes a NullString from JSON
func (n *NullString) UnmarshalJSON(b []byte) error {
	var s interface{}
	if err := json.Unmarshal(b, &s); err != nil {
		return err
	}
	return n.Scan(s)
}

// UnmarshalJSON correctly deserializes a NullInt64 from JSON
func (n *NullInt64) UnmarshalJSON(b []byte) error {
	var s interface{}
	if err := json.Unmarshal(b, &s); err != nil {
		return err
	}
	return n.Scan(s)
}

// UnmarshalJSON correctly deserializes a NullFloat64 from JSON
func (n *NullFloat64) UnmarshalJSON(b []byte) error {
	var s interface{}
	if err := json.Unmarshal(b, &s); err != nil {
		return err
	}
	return n.Scan(s)
}

// UnmarshalJSON correctly deserializes a NullTime from JSON
func (n *NullTime) UnmarshalJSON(b []byte) error {
	// scan for null
	if bytes.Equal(b, nullString) {
		return n.Scan(nil)
	}
	// scan for JSON timestamp
	var t time.Time
	if err := json.Unmarshal(b, &t); err != nil {
		return err
	}
	return n.Scan(t)
}

// UnmarshalJSON correctly deserializes a NullBool from JSON
func (n *NullBool) UnmarshalJSON(b []byte) error {
	var s interface{}
	if err := json.Unmarshal(b, &s); err != nil {
		return err
	}
	return n.Scan(s)
}
<commit_msg>Added fix for parsing int number from JSON that is  bigger then 6 digits and represented by NullInt64 type<commit_after>package dbr

import (
	"bytes"
	"database/sql"
	"encoding/json"
	"time"

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

//
// Your app can use these Null types instead of the defaults. The sole benefit you get is a MarshalJSON method that is not retarded.
//

// NullString is a type that can be null or a string
type NullString struct {
	sql.NullString
}

// NullFloat64 is a type that can be null or a float64
type NullFloat64 struct {
	sql.NullFloat64
}

// NullInt64 is a type that can be null or an int
type NullInt64 struct {
	sql.NullInt64
}

// NullTime is a type that can be null or a time
type NullTime struct {
	mysql.NullTime
}

// NullBool is a type that can be null or a bool
type NullBool struct {
	sql.NullBool
}

var nullString = []byte("null")

// MarshalJSON correctly serializes a NullString to JSON
func (n *NullString) MarshalJSON() ([]byte, error) {
	if n.Valid {
		j, e := json.Marshal(n.String)
		return j, e
	}
	return nullString, nil
}

// MarshalJSON correctly serializes a NullInt64 to JSON
func (n *NullInt64) MarshalJSON() ([]byte, error) {
	if n.Valid {
		j, e := json.Marshal(n.Int64)
		return j, e
	}
	return nullString, nil
}

// MarshalJSON correctly serializes a NullFloat64 to JSON
func (n *NullFloat64) MarshalJSON() ([]byte, error) {
	if n.Valid {
		j, e := json.Marshal(n.Float64)
		return j, e
	}
	return nullString, nil
}

// MarshalJSON correctly serializes a NullTime to JSON
func (n *NullTime) MarshalJSON() ([]byte, error) {
	if n.Valid {
		j, e := json.Marshal(n.Time)
		return j, e
	}
	return nullString, nil
}

// MarshalJSON correctly serializes a NullBool to JSON
func (n *NullBool) MarshalJSON() ([]byte, error) {
	if n.Valid {
		j, e := json.Marshal(n.Bool)
		return j, e
	}
	return nullString, nil
}

// UnmarshalJSON correctly deserializes a NullString from JSON
func (n *NullString) UnmarshalJSON(b []byte) error {
	var s interface{}
	if err := json.Unmarshal(b, &s); err != nil {
		return err
	}
	return n.Scan(s)
}

// UnmarshalJSON correctly deserializes a NullInt64 from JSON
func (n *NullInt64) UnmarshalJSON(b []byte) error {
	var s int64
	if err := json.Unmarshal(b, &s); err != nil {
		return err
	}
	return n.Scan(s)
}

// UnmarshalJSON correctly deserializes a NullFloat64 from JSON
func (n *NullFloat64) UnmarshalJSON(b []byte) error {
	var s interface{}
	if err := json.Unmarshal(b, &s); err != nil {
		return err
	}
	return n.Scan(s)
}

// UnmarshalJSON correctly deserializes a NullTime from JSON
func (n *NullTime) UnmarshalJSON(b []byte) error {
	// scan for null
	if bytes.Equal(b, nullString) {
		return n.Scan(nil)
	}
	// scan for JSON timestamp
	var t time.Time
	if err := json.Unmarshal(b, &t); err != nil {
		return err
	}
	return n.Scan(t)
}

// UnmarshalJSON correctly deserializes a NullBool from JSON
func (n *NullBool) UnmarshalJSON(b []byte) error {
	var s interface{}
	if err := json.Unmarshal(b, &s); err != nil {
		return err
	}
	return n.Scan(s)
}
<|endoftext|>


<commit_before><commit_msg>utils.go/getParentAndBase fix<commit_after><|endoftext|>


<commit_before><commit_msg>Added CLIOnly global which means one can set it via the CLI but not via the user cfg file or env (eg: --globs and --version don't make much sense beyond the CLI use for instance).<commit_after><|endoftext|>


<commit_before><commit_msg>watch: update binary in case of deletion<commit_after><|endoftext|>


<commit_before>// Package pages provides a data structure for a web pages.
package pages

import (
	"bytes"
	"encoding/base64"
	"errors"
	"fmt"
	"log"
	"net/http"
	"net/url"
	"path"

	"github.com/ChristianSiegert/go-packages/forms"
	"github.com/ChristianSiegert/go-packages/html"
	"github.com/ChristianSiegert/go-packages/i18n/languages"
	"github.com/ChristianSiegert/go-packages/sessions"
)

// FlashTypeError is the flash type used for error messages.
var FlashTypeError = "error"

// ReloadTemplates is a flag for whether NewPage and MustNewPage should reload
// templates on every request. Reloading templates is useful to see changes
// without recompiling. In production, reloading should be disabled.
var ReloadTemplates = false

// TemplateEmpty is used when Page.ServeEmpty is called.
var TemplateEmpty *Template

// TemplateError is used when Page.Error is called.
var TemplateError *Template

// TemplateNotFound is used when Page.ServeNotFound is called.
var TemplateNotFound *Template

// SignInURL is the URL to the page that users are redirected to when
// Page.RequireSignIn is called. If a %s placeholder is present in
// SignInURL.Path, it is replaced by the page’s language code. E.g.
// “/%s/sign-in” becomes “/en/sign-in” if the page’s language code is “en”.
var SignInURL = &url.URL{
	Path: "/%s/sign-in",
}

// Page represents a web page.
type Page struct {
	// Breadcrumbs manages navigation breadcrumbs.
	Breadcrumbs *Breadcrumbs

	Data map[string]interface{}

	// Form is an instance of *forms.Form bound to the request.
	Form *forms.Form

	Language *languages.Language

	// Name of the page. Useful in the root template, e.g. to style the
	// navigation link of the current page.
	Name string

	request *http.Request

	Session sessions.Session

	Template *Template

	// Title of the page that templates can use to populate the HTML <title>
	// element.
	Title string

	writer http.ResponseWriter
}

// NewPage returns a new page.
func NewPage(writer http.ResponseWriter, request *http.Request, tpl *Template) (*Page, error) {
	ctx := request.Context()

	language, err := languages.FromContext(ctx)
	if err != nil {
		return nil, err
	}

	session, err := sessions.FromContext(ctx)
	if err != nil {
		return nil, err
	}

	form, err := forms.New(request)
	if err != nil {
		return nil, err
	}

	page := &Page{
		Breadcrumbs: &Breadcrumbs{},
		Data:        make(map[string]interface{}),
		Form:        form,
		Language:    language,
		request:     request,
		Session:     session,
		Template:    tpl,
		writer:      writer,
	}

	return page, nil
}

// MustNewPage calls NewPage. It panics on error.
func MustNewPage(writer http.ResponseWriter, request *http.Request, tpl *Template) *Page {
	page, err := NewPage(writer, request, tpl)
	if err != nil {
		panic("pages.MustNewPage: " + err.Error())
	}
	return page
}

// FlashAll returns all flashes, removes them from session and saves the session
// if necessary.
func (p *Page) FlashAll() []sessions.Flash {
	flashes := p.Session.Flashes().GetAll()

	if len(flashes) > 0 {
		p.Session.Flashes().RemoveAll()

		if p.Session.IsStored() {
			if err := p.Session.Save(p.writer); err != nil {
				log.Printf("pages.Page.FlashAll: Saving session failed: %s", err)
			}
		}
	}

	return flashes
}

// Redirect redirects the client.
func (p *Page) Redirect(url string, code int) {
	http.Redirect(p.writer, p.request, url, code)
}

// RequireSignIn redirects users to the sign-in page specified by SignInURL.
// If SignInURL.RawQuery is empty, the query parameters “r” (referrer) and “t”
// (title of the referrer page) are appended. This allows the sign-in page to
// display a message that page <title> is access restricted, and after
// successful authentication, users can be redirected to <referrer>, the page
// they came from.
func (p *Page) RequireSignIn(pageTitle string) {
	u := &url.URL{
		Scheme:   SignInURL.Scheme,
		Opaque:   SignInURL.Opaque,
		User:     SignInURL.User,
		Host:     SignInURL.Host,
		Path:     fmt.Sprintf(SignInURL.Path, p.Language.Code()),
		Fragment: SignInURL.Fragment,
	}

	if SignInURL.RawQuery == "" {
		query := &url.Values{}
		query.Add("r", p.request.URL.Path)
		query.Add("t", base64.URLEncoding.EncodeToString([]byte(pageTitle))) // TODO: Sign or encrypt parameter to prevent tempering by users
		u.RawQuery = query.Encode()
	}

	p.Redirect(u.String(), http.StatusSeeOther)
}

// Error serves an error page with a generic error message. Err is not displayed
// to the user but written to the error log.
func (p *Page) Error(err error) {
	log.Println(err.Error())

	if TemplateError == nil {
		log.Println("pages.Page.Error: No error template provided.")
		http.Error(p.writer, "Internal Server Error", http.StatusInternalServerError)
		return
	}

	buffer := bytes.NewBuffer([]byte{})

	p.Data = map[string]interface{}{
		"Error":          err,
		"IsDevAppServer": true,
	}

	if ReloadTemplates {
		if err := p.Template.Reload(); err != nil {
			log.Printf("pages.Page.Error: Reloading template failed: %s\n", p.Template.paths)
			http.Error(p.writer, "Internal Server Error", http.StatusInternalServerError)
		}
	}

	templateName := path.Base(TemplateError.paths[0])
	if err := TemplateError.template.ExecuteTemplate(buffer, templateName, p); err != nil {
		log.Printf("pages.Page.Error: Executing template failed: %s\n", err)
		http.Error(p.writer, "Internal Server Error", http.StatusInternalServerError)
		return
	}

	b := html.RemoveWhitespace(buffer.Bytes())

	if _, err := bytes.NewBuffer(b).WriteTo(p.writer); err != nil {
		log.Printf("pages.Page.Error: Writing template to buffer failed: %s\n", err)
		http.Error(p.writer, "Internal Server Error", http.StatusInternalServerError)
	}
}

// Serve serves the root template specified by RootTemplatePath with the content
// template specified by p.Template. HTML comments and whitespace are stripped.
// If p.Template is nil, an empty content template is embedded.
func (p *Page) Serve() {
	buffer := bytes.NewBuffer([]byte{})

	if p.Template == nil {
		p.Template = TemplateEmpty
	}

	// If still nil
	if p.Template == nil {
		p.Error(errors.New("pages.Page.Serve: no template provided"))
		return
	}

	if ReloadTemplates {
		if err := p.Template.Reload(); err != nil {
			p.Error(err)
		}
	}

	templateName := path.Base(p.Template.paths[0])
	if err := p.Template.template.ExecuteTemplate(buffer, templateName, p); err != nil {
		p.Error(err)
		return
	}

	b := html.RemoveWhitespace(buffer.Bytes())

	if _, err := bytes.NewBuffer(b).WriteTo(p.writer); err != nil {
		p.Error(err)
	}
}

// ServeEmpty serves the root template without content template.
func (p *Page) ServeEmpty() {
	p.Template = TemplateEmpty
	p.Serve()
}

// ServeNotFound serves a page that tells the user the requested page does not
// exist.
func (p *Page) ServeNotFound() {
	if TemplateNotFound == nil {
		http.Error(p.writer, p.T("err_404_not_found"), http.StatusNotFound)
		return
	}

	p.writer.WriteHeader(http.StatusNotFound)
	p.Template = TemplateNotFound
	p.Title = p.T("err_404_not_found")
	p.Serve()
}

// ServeUnauthorized serves a page that tells the user the requested page cannot
// be accessed due to insufficient access rights.
func (p *Page) ServeUnauthorized() {
	p.Session.Flashes().AddNew(p.T("err_401_unauthorized"), FlashTypeError)
	p.writer.WriteHeader(http.StatusUnauthorized)
	p.ServeEmpty()
}

// ServeWithError is similar to Serve, but additionally an error flash message
// is displayed to the user saying that an internal problem occurred. Err is not
// displayed but written to the error log. This method is useful if the user
// should be informed of a problem while the state, e.g. a filled in form, is
// preserved.
func (p *Page) ServeWithError(err error) {
	log.Println(err.Error())
	p.Session.Flashes().AddNew(p.T("err_505_internal_server_error"), FlashTypeError)
	p.Serve()
}

// T returns the translation associated with translationID. If p.Language
// is nil, translationID is returned.
func (p *Page) T(translationID string, templateData ...map[string]interface{}) string {
	if p.Language == nil {
		return translationID
	}
	return p.Language.T(translationID, templateData...)
}

// Error serves a new page using the TemplateError template.
func Error(writer http.ResponseWriter, request *http.Request, err error) {
	page := MustNewPage(writer, request, TemplateError)
	page.Error(err)
}
<commit_msg>Added variable pages.Log whose function can be overwritten to use a custom logger.<commit_after>// Package pages provides a data structure for a web pages.
package pages

import (
	"bytes"
	"encoding/base64"
	"errors"
	"fmt"
	"log"
	"net/http"
	"net/url"
	"path"

	"github.com/ChristianSiegert/go-packages/forms"
	"github.com/ChristianSiegert/go-packages/html"
	"github.com/ChristianSiegert/go-packages/i18n/languages"
	"github.com/ChristianSiegert/go-packages/sessions"
)

// FlashTypeError is the flash type used for error messages.
var FlashTypeError = "error"

// Log logs errors. The function can be replaced to use a custom logger.
var Log = func(err error) {
	log.Println(err)
}

// ReloadTemplates is a flag for whether NewPage and MustNewPage should reload
// templates on every request. Reloading templates is useful to see changes
// without recompiling. In production, reloading should be disabled.
var ReloadTemplates = false

// TemplateEmpty is used when Page.ServeEmpty is called.
var TemplateEmpty *Template

// TemplateError is used when Page.Error is called.
var TemplateError *Template

// TemplateNotFound is used when Page.ServeNotFound is called.
var TemplateNotFound *Template

// SignInURL is the URL to the page that users are redirected to when
// Page.RequireSignIn is called. If a %s placeholder is present in
// SignInURL.Path, it is replaced by the page’s language code. E.g.
// “/%s/sign-in” becomes “/en/sign-in” if the page’s language code is “en”.
var SignInURL = &url.URL{
	Path: "/%s/sign-in",
}

// Page represents a web page.
type Page struct {
	// Breadcrumbs manages navigation breadcrumbs.
	Breadcrumbs *Breadcrumbs

	Data map[string]interface{}

	// Form is an instance of *forms.Form bound to the request.
	Form *forms.Form

	Language *languages.Language

	// Name of the page. Useful in the root template, e.g. to style the
	// navigation link of the current page.
	Name string

	request *http.Request

	Session sessions.Session

	Template *Template

	// Title of the page that templates can use to populate the HTML <title>
	// element.
	Title string

	writer http.ResponseWriter
}

// NewPage returns a new page.
func NewPage(writer http.ResponseWriter, request *http.Request, tpl *Template) (*Page, error) {
	ctx := request.Context()

	language, err := languages.FromContext(ctx)
	if err != nil {
		return nil, err
	}

	session, err := sessions.FromContext(ctx)
	if err != nil {
		return nil, err
	}

	form, err := forms.New(request)
	if err != nil {
		return nil, err
	}

	page := &Page{
		Breadcrumbs: &Breadcrumbs{},
		Data:        make(map[string]interface{}),
		Form:        form,
		Language:    language,
		request:     request,
		Session:     session,
		Template:    tpl,
		writer:      writer,
	}

	return page, nil
}

// MustNewPage calls NewPage. It panics on error.
func MustNewPage(writer http.ResponseWriter, request *http.Request, tpl *Template) *Page {
	page, err := NewPage(writer, request, tpl)
	if err != nil {
		panic("pages.MustNewPage: " + err.Error())
	}
	return page
}

// FlashAll returns all flashes, removes them from session and saves the session
// if necessary.
func (p *Page) FlashAll() []sessions.Flash {
	flashes := p.Session.Flashes().GetAll()

	if len(flashes) > 0 {
		p.Session.Flashes().RemoveAll()

		if p.Session.IsStored() {
			if err := p.Session.Save(p.writer); err != nil {
				Log(fmt.Errorf("pages.Page.FlashAll: saving session failed: %s", err))
			}
		}
	}

	return flashes
}

// Redirect redirects the client.
func (p *Page) Redirect(url string, code int) {
	http.Redirect(p.writer, p.request, url, code)
}

// RequireSignIn redirects users to the sign-in page specified by SignInURL.
// If SignInURL.RawQuery is empty, the query parameters “r” (referrer) and “t”
// (title of the referrer page) are appended. This allows the sign-in page to
// display a message that page <title> is access restricted, and after
// successful authentication, users can be redirected to <referrer>, the page
// they came from.
func (p *Page) RequireSignIn(pageTitle string) {
	u := &url.URL{
		Scheme:   SignInURL.Scheme,
		Opaque:   SignInURL.Opaque,
		User:     SignInURL.User,
		Host:     SignInURL.Host,
		Path:     fmt.Sprintf(SignInURL.Path, p.Language.Code()),
		Fragment: SignInURL.Fragment,
	}

	if SignInURL.RawQuery == "" {
		query := &url.Values{}
		query.Add("r", p.request.URL.Path)
		query.Add("t", base64.URLEncoding.EncodeToString([]byte(pageTitle))) // TODO: Sign or encrypt parameter to prevent tempering by users
		u.RawQuery = query.Encode()
	}

	p.Redirect(u.String(), http.StatusSeeOther)
}

// Error serves an error page with a generic error message. Err is not displayed
// to the user but written to the error log.
func (p *Page) Error(err error) {
	Log(err)

	if TemplateError == nil {
		Log(errors.New("pages.Page.Error: no error template provided"))
		http.Error(p.writer, "Internal Server Error", http.StatusInternalServerError)
		return
	}

	buffer := bytes.NewBuffer([]byte{})

	p.Data = map[string]interface{}{
		"Error":          err,
		"IsDevAppServer": true,
	}

	if ReloadTemplates {
		if err := p.Template.Reload(); err != nil {
			Log(fmt.Errorf("pages.Page.Error: reloading template failed: %s", p.Template.paths))
			http.Error(p.writer, "Internal Server Error", http.StatusInternalServerError)
		}
	}

	templateName := path.Base(TemplateError.paths[0])
	if err := TemplateError.template.ExecuteTemplate(buffer, templateName, p); err != nil {
		Log(fmt.Errorf("pages.Page.Error: executing template failed: %s", err))
		http.Error(p.writer, "Internal Server Error", http.StatusInternalServerError)
		return
	}

	b := html.RemoveWhitespace(buffer.Bytes())

	if _, err := bytes.NewBuffer(b).WriteTo(p.writer); err != nil {
		Log(fmt.Errorf("pages.Page.Error: writing template to buffer failed: %s", err))
		http.Error(p.writer, "Internal Server Error", http.StatusInternalServerError)
	}
}

// Serve serves the root template specified by RootTemplatePath with the content
// template specified by p.Template. HTML comments and whitespace are stripped.
// If p.Template is nil, an empty content template is embedded.
func (p *Page) Serve() {
	buffer := bytes.NewBuffer([]byte{})

	if p.Template == nil {
		p.Template = TemplateEmpty
	}

	// If still nil
	if p.Template == nil {
		p.Error(errors.New("pages.Page.Serve: no template provided"))
		return
	}

	if ReloadTemplates {
		if err := p.Template.Reload(); err != nil {
			p.Error(err)
		}
	}

	templateName := path.Base(p.Template.paths[0])
	if err := p.Template.template.ExecuteTemplate(buffer, templateName, p); err != nil {
		p.Error(err)
		return
	}

	b := html.RemoveWhitespace(buffer.Bytes())

	if _, err := bytes.NewBuffer(b).WriteTo(p.writer); err != nil {
		p.Error(err)
	}
}

// ServeEmpty serves the root template without content template.
func (p *Page) ServeEmpty() {
	p.Template = TemplateEmpty
	p.Serve()
}

// ServeNotFound serves a page that tells the user the requested page does not
// exist.
func (p *Page) ServeNotFound() {
	if TemplateNotFound == nil {
		http.Error(p.writer, p.T("err_404_not_found"), http.StatusNotFound)
		return
	}

	p.writer.WriteHeader(http.StatusNotFound)
	p.Template = TemplateNotFound
	p.Title = p.T("err_404_not_found")
	p.Serve()
}

// ServeUnauthorized serves a page that tells the user the requested page cannot
// be accessed due to insufficient access rights.
func (p *Page) ServeUnauthorized() {
	p.Session.Flashes().AddNew(p.T("err_401_unauthorized"), FlashTypeError)
	p.writer.WriteHeader(http.StatusUnauthorized)
	p.ServeEmpty()
}

// ServeWithError is similar to Serve, but additionally an error flash message
// is displayed to the user saying that an internal problem occurred. Err is not
// displayed but written to the error log. This method is useful if the user
// should be informed of a problem while the state, e.g. a filled in form, is
// preserved.
func (p *Page) ServeWithError(err error) {
	Log(err)
	p.Session.Flashes().AddNew(p.T("err_505_internal_server_error"), FlashTypeError)
	p.Serve()
}

// T returns the translation associated with translationID. If p.Language
// is nil, translationID is returned.
func (p *Page) T(translationID string, templateData ...map[string]interface{}) string {
	if p.Language == nil {
		return translationID
	}
	return p.Language.T(translationID, templateData...)
}

// Error serves a new page using the TemplateError template.
func Error(writer http.ResponseWriter, request *http.Request, err error) {
	page := MustNewPage(writer, request, TemplateError)
	page.Error(err)
}
<|endoftext|>


<commit_before>// package shell implements a remote API interface for a running ipfs daemon
package shell

import (
	"bufio"
	"encoding/json"
	"errors"
	"fmt"
	"io"
	"io/ioutil"
	gohttp "net/http"
	"os"

	files "github.com/whyrusleeping/go-multipart-files"
	tar "github.com/whyrusleeping/tar-utils"
)

type Shell struct {
	url     string
	httpcli *gohttp.Client
}

func NewShell(url string) *Shell {
	return &Shell{
		url: url,
		httpcli: &gohttp.Client{
			Transport: &gohttp.Transport{
				DisableKeepAlives: true,
			},
		},
	}
}

func (s *Shell) newRequest(command string, args ...string) *Request {
	return NewRequest(s.url, command, args...)
}

type IdOutput struct {
	ID              string
	PublicKey       string
	Addresses       []string
	AgentVersion    string
	ProtocolVersion string
}

// ID gets information about a given peer.  Arguments:
//
// peer: peer.ID of the node to look up.  If no peer is specified,
//   return information about the local peer.
func (s *Shell) ID(peer ...string) (*IdOutput, error) {
	if len(peer) > 1 {
		return nil, fmt.Errorf("Too many peer arguments")
	}

	resp, err := NewRequest(s.url, "id", peer...).Send(s.httpcli)
	if err != nil {
		return nil, err
	}

	defer resp.Close()
	if resp.Error != nil {
		return nil, resp.Error
	}

	decoder := json.NewDecoder(resp.Output)
	out := new(IdOutput)
	err = decoder.Decode(out)
	if err != nil {
		return nil, err
	}

	return out, nil
}

// Cat the content at the given path. Callers need to drain and close the returned reader after usage.
func (s *Shell) Cat(path string) (io.ReadCloser, error) {
	resp, err := NewRequest(s.url, "cat", path).Send(s.httpcli)
	if err != nil {
		return nil, err
	}
	if resp.Error != nil {
		return nil, resp.Error
	}

	return resp.Output, nil
}

type object struct {
	Hash string
}

// Add a file to ipfs from the given reader, returns the hash of the added file
func (s *Shell) Add(r io.Reader) (string, error) {
	var rc io.ReadCloser
	if rclose, ok := r.(io.ReadCloser); ok {
		rc = rclose
	} else {
		rc = ioutil.NopCloser(r)
	}

	// handler expects an array of files
	fr := files.NewReaderFile("", "", rc, nil)
	slf := files.NewSliceFile("", "", []files.File{fr})
	fileReader := files.NewMultiFileReader(slf, true)

	req := NewRequest(s.url, "add")
	req.Body = fileReader

	resp, err := req.Send(s.httpcli)
	if err != nil {
		return "", err
	}
	defer resp.Close()
	if resp.Error != nil {
		return "", resp.Error
	}

	var out object
	err = json.NewDecoder(resp.Output).Decode(&out)
	if err != nil {
		return "", err
	}

	return out.Hash, nil
}

func (s *Shell) AddLink(target string) (string, error) {
	link := files.NewLinkFile("", "", target, nil)
	slf := files.NewSliceFile("", "", []files.File{link})
	reader := files.NewMultiFileReader(slf, true)

	req := s.newRequest("add")
	req.Body = reader

	resp, err := req.Send(s.httpcli)
	if err != nil {
		return "", err
	}
	defer resp.Close()
	if resp.Error != nil {
		return "", resp.Error
	}

	var out object
	err = json.NewDecoder(resp.Output).Decode(&out)
	if err != nil {
		return "", err
	}

	return out.Hash, nil
}

// AddDir adds a directory recursively with all of the files under it
func (s *Shell) AddDir(dir string) (string, error) {
	stat, err := os.Lstat(dir)
	if err != nil {
		return "", err
	}

	sf, err := files.NewSerialFile("", dir, stat)
	if err != nil {
		return "", err
	}
	slf := files.NewSliceFile("", dir, []files.File{sf})
	reader := files.NewMultiFileReader(slf, true)

	req := NewRequest(s.url, "add")
	req.Opts["r"] = "true"
	req.Body = reader

	resp, err := req.Send(s.httpcli)
	if err != nil {
		return "", err
	}
	defer resp.Close()
	if resp.Error != nil {
		return "", resp.Error
	}

	dec := json.NewDecoder(resp.Output)
	var final string
	for {
		var out object
		err = dec.Decode(&out)
		if err != nil {
			if err == io.EOF {
				break
			}
			return "", err
		}
		final = out.Hash
	}

	if final == "" {
		return "", errors.New("no results received")
	}

	return final, nil
}

const (
	TRaw = iota
	TDirectory
	TFile
	TMetadata
	TSymlink
)

// List entries at the given path
func (s *Shell) List(path string) ([]*LsLink, error) {
	resp, err := NewRequest(s.url, "ls", path).Send(s.httpcli)
	if err != nil {
		return nil, err
	}
	defer resp.Close()

	if resp.Error != nil {
		return nil, resp.Error
	}

	var out struct{ Objects []LsObject }
	err = json.NewDecoder(resp.Output).Decode(&out)
	if err != nil {
		return nil, err
	}

	return out.Objects[0].Links, nil
}

type LsLink struct {
	Hash string
	Name string
	Size uint64
	Type int
}

type LsObject struct {
	Links []*LsLink
	LsLink
}

// Pin the given path
func (s *Shell) Pin(path string) error {
	req := NewRequest(s.url, "pin/add", path)
	req.Opts["r"] = "true"

	resp, err := req.Send(s.httpcli)
	if err != nil {
		return err
	}
	defer resp.Close()
	if resp.Error != nil {
		return resp.Error
	}

	return nil
}

// Unpin the given path
func (s *Shell) Unpin(path string) error {
	req := NewRequest(s.url, "pin/rm", path)
	req.Opts["r"] = "true"

	resp, err := req.Send(s.httpcli)
	if err != nil {
		return err
	}
	defer resp.Close()
	if resp.Error != nil {
		return resp.Error
	}

	return nil
}

type PeerInfo struct {
	Addrs []string
	ID    string
}

func (s *Shell) FindPeer(peer string) (*PeerInfo, error) {
	resp, err := s.newRequest("dht/findpeer", peer).Send(s.httpcli)
	if err != nil {
		return nil, err
	}
	defer resp.Close()

	if resp.Error != nil {
		return nil, resp.Error
	}

	str := struct{ Responses []PeerInfo }{}
	err = json.NewDecoder(resp.Output).Decode(&str)
	if err != nil {
		return nil, err
	}

	if len(str.Responses) == 0 {
		return nil, errors.New("peer not found")
	}

	return &str.Responses[0], nil
}

func (s *Shell) Refs(hash string, recursive bool) (<-chan string, error) {
	req := s.newRequest("refs", hash)
	if recursive {
		req.Opts["r"] = "true"
	}

	resp, err := req.Send(s.httpcli)
	if err != nil {
		return nil, err
	}

	if resp.Error != nil {
		return nil, resp.Error
	}

	out := make(chan string)
	go func() {
		defer resp.Close()
		scan := bufio.NewScanner(resp.Output)
		for scan.Scan() {
			if len(scan.Text()) > 0 {
				out <- scan.Text()
			}
		}
		close(out)
	}()

	return out, nil
}

func (s *Shell) Patch(root, action string, args ...string) (string, error) {
	cmdargs := append([]string{root, action}, args...)
	resp, err := s.newRequest("object/patch", cmdargs...).Send(s.httpcli)
	if err != nil {
		return "", err
	}
	defer resp.Close()

	if resp.Error != nil {
		return "", resp.Error
	}

	dec := json.NewDecoder(resp.Output)
	var out object
	err = dec.Decode(&out)
	if err != nil {
		return "", err
	}

	return out.Hash, nil
}

func (s *Shell) PatchLink(root, path, childhash string, create bool) (string, error) {
	cmdargs := []string{root, "add-link", path, childhash}

	req := s.newRequest("object/patch", cmdargs...)
	if create {
		req.Opts["create"] = "true"
	}

	resp, err := req.Send(s.httpcli)
	if err != nil {
		return "", err
	}
	defer resp.Close()

	if resp.Error != nil {
		return "", resp.Error
	}

	var out object
	err = json.NewDecoder(resp.Output).Decode(&out)
	if err != nil {
		return "", err
	}

	return out.Hash, nil
}

func (s *Shell) Get(hash, outdir string) error {
	resp, err := s.newRequest("get", hash).Send(s.httpcli)
	if err != nil {
		return err
	}
	defer resp.Close()

	if resp.Error != nil {
		return resp.Error
	}

	extractor := &tar.Extractor{Path: outdir}
	return extractor.Extract(resp.Output)
}

func (s *Shell) NewObject(template string) (string, error) {
	args := []string{}
	if template != "" {
		args = []string{template}
	}

	resp, err := s.newRequest("object/new", args...).Send(s.httpcli)
	if err != nil {
		return "", err
	}
	defer resp.Close()

	if resp.Error != nil {
		return "", resp.Error
	}

	var out object
	err = json.NewDecoder(resp.Output).Decode(&out)
	if err != nil {
		return "", err
	}

	return out.Hash, nil
}

func (s *Shell) ResolvePath(path string) (string, error) {
	resp, err := s.newRequest("object/stat", path).Send(s.httpcli)
	if err != nil {
		return "", err
	}
	defer resp.Close()

	if resp.Error != nil {
		return "", resp.Error
	}

	var out object
	err = json.NewDecoder(resp.Output).Decode(&out)
	if err != nil {
		return "", err
	}

	return out.Hash, nil
}

// returns ipfs version and commit sha
func (s *Shell) Version() (string, string, error) {
	resp, err := s.newRequest("version").Send(s.httpcli)
	if err != nil {
		return "", "", err
	}

	defer resp.Close()
	if resp.Error != nil {
		return "", "", resp.Error
	}

	ver := struct {
		Version string
		Commit  string
	}{}

	err = json.NewDecoder(resp.Output).Decode(&ver)
	if err != nil {
		return "", "", err
	}

	return ver.Version, ver.Commit, nil
}

func (s *Shell) IsUp() bool {
	_, err := s.ID()
	return err == nil
}

func (s *Shell) BlockStat(path string) (string, int, error) {
	resp, err := s.newRequest("block/stat", path).Send(s.httpcli)
	if err != nil {
		return "", 0, err
	}
	defer resp.Close()

	if resp.Error != nil {
		return "", 0, resp.Error
	}

	var inf struct {
		Key  string
		Size int
	}

	err = json.NewDecoder(resp.Output).Decode(&inf)
	if err != nil {
		return "", 0, err
	}

	return inf.Key, inf.Size, nil
}
<commit_msg>use version for shell IsUp check<commit_after>// package shell implements a remote API interface for a running ipfs daemon
package shell

import (
	"bufio"
	"encoding/json"
	"errors"
	"fmt"
	"io"
	"io/ioutil"
	gohttp "net/http"
	"os"

	files "github.com/whyrusleeping/go-multipart-files"
	tar "github.com/whyrusleeping/tar-utils"
)

type Shell struct {
	url     string
	httpcli *gohttp.Client
}

func NewShell(url string) *Shell {
	return &Shell{
		url: url,
		httpcli: &gohttp.Client{
			Transport: &gohttp.Transport{
				DisableKeepAlives: true,
			},
		},
	}
}

func (s *Shell) newRequest(command string, args ...string) *Request {
	return NewRequest(s.url, command, args...)
}

type IdOutput struct {
	ID              string
	PublicKey       string
	Addresses       []string
	AgentVersion    string
	ProtocolVersion string
}

// ID gets information about a given peer.  Arguments:
//
// peer: peer.ID of the node to look up.  If no peer is specified,
//   return information about the local peer.
func (s *Shell) ID(peer ...string) (*IdOutput, error) {
	if len(peer) > 1 {
		return nil, fmt.Errorf("Too many peer arguments")
	}

	resp, err := NewRequest(s.url, "id", peer...).Send(s.httpcli)
	if err != nil {
		return nil, err
	}

	defer resp.Close()
	if resp.Error != nil {
		return nil, resp.Error
	}

	decoder := json.NewDecoder(resp.Output)
	out := new(IdOutput)
	err = decoder.Decode(out)
	if err != nil {
		return nil, err
	}

	return out, nil
}

// Cat the content at the given path. Callers need to drain and close the returned reader after usage.
func (s *Shell) Cat(path string) (io.ReadCloser, error) {
	resp, err := NewRequest(s.url, "cat", path).Send(s.httpcli)
	if err != nil {
		return nil, err
	}
	if resp.Error != nil {
		return nil, resp.Error
	}

	return resp.Output, nil
}

type object struct {
	Hash string
}

// Add a file to ipfs from the given reader, returns the hash of the added file
func (s *Shell) Add(r io.Reader) (string, error) {
	var rc io.ReadCloser
	if rclose, ok := r.(io.ReadCloser); ok {
		rc = rclose
	} else {
		rc = ioutil.NopCloser(r)
	}

	// handler expects an array of files
	fr := files.NewReaderFile("", "", rc, nil)
	slf := files.NewSliceFile("", "", []files.File{fr})
	fileReader := files.NewMultiFileReader(slf, true)

	req := NewRequest(s.url, "add")
	req.Body = fileReader

	resp, err := req.Send(s.httpcli)
	if err != nil {
		return "", err
	}
	defer resp.Close()
	if resp.Error != nil {
		return "", resp.Error
	}

	var out object
	err = json.NewDecoder(resp.Output).Decode(&out)
	if err != nil {
		return "", err
	}

	return out.Hash, nil
}

func (s *Shell) AddLink(target string) (string, error) {
	link := files.NewLinkFile("", "", target, nil)
	slf := files.NewSliceFile("", "", []files.File{link})
	reader := files.NewMultiFileReader(slf, true)

	req := s.newRequest("add")
	req.Body = reader

	resp, err := req.Send(s.httpcli)
	if err != nil {
		return "", err
	}
	defer resp.Close()
	if resp.Error != nil {
		return "", resp.Error
	}

	var out object
	err = json.NewDecoder(resp.Output).Decode(&out)
	if err != nil {
		return "", err
	}

	return out.Hash, nil
}

// AddDir adds a directory recursively with all of the files under it
func (s *Shell) AddDir(dir string) (string, error) {
	stat, err := os.Lstat(dir)
	if err != nil {
		return "", err
	}

	sf, err := files.NewSerialFile("", dir, stat)
	if err != nil {
		return "", err
	}
	slf := files.NewSliceFile("", dir, []files.File{sf})
	reader := files.NewMultiFileReader(slf, true)

	req := NewRequest(s.url, "add")
	req.Opts["r"] = "true"
	req.Body = reader

	resp, err := req.Send(s.httpcli)
	if err != nil {
		return "", err
	}
	defer resp.Close()
	if resp.Error != nil {
		return "", resp.Error
	}

	dec := json.NewDecoder(resp.Output)
	var final string
	for {
		var out object
		err = dec.Decode(&out)
		if err != nil {
			if err == io.EOF {
				break
			}
			return "", err
		}
		final = out.Hash
	}

	if final == "" {
		return "", errors.New("no results received")
	}

	return final, nil
}

const (
	TRaw = iota
	TDirectory
	TFile
	TMetadata
	TSymlink
)

// List entries at the given path
func (s *Shell) List(path string) ([]*LsLink, error) {
	resp, err := NewRequest(s.url, "ls", path).Send(s.httpcli)
	if err != nil {
		return nil, err
	}
	defer resp.Close()

	if resp.Error != nil {
		return nil, resp.Error
	}

	var out struct{ Objects []LsObject }
	err = json.NewDecoder(resp.Output).Decode(&out)
	if err != nil {
		return nil, err
	}

	return out.Objects[0].Links, nil
}

type LsLink struct {
	Hash string
	Name string
	Size uint64
	Type int
}

type LsObject struct {
	Links []*LsLink
	LsLink
}

// Pin the given path
func (s *Shell) Pin(path string) error {
	req := NewRequest(s.url, "pin/add", path)
	req.Opts["r"] = "true"

	resp, err := req.Send(s.httpcli)
	if err != nil {
		return err
	}
	defer resp.Close()
	if resp.Error != nil {
		return resp.Error
	}

	return nil
}

// Unpin the given path
func (s *Shell) Unpin(path string) error {
	req := NewRequest(s.url, "pin/rm", path)
	req.Opts["r"] = "true"

	resp, err := req.Send(s.httpcli)
	if err != nil {
		return err
	}
	defer resp.Close()
	if resp.Error != nil {
		return resp.Error
	}

	return nil
}

type PeerInfo struct {
	Addrs []string
	ID    string
}

func (s *Shell) FindPeer(peer string) (*PeerInfo, error) {
	resp, err := s.newRequest("dht/findpeer", peer).Send(s.httpcli)
	if err != nil {
		return nil, err
	}
	defer resp.Close()

	if resp.Error != nil {
		return nil, resp.Error
	}

	str := struct{ Responses []PeerInfo }{}
	err = json.NewDecoder(resp.Output).Decode(&str)
	if err != nil {
		return nil, err
	}

	if len(str.Responses) == 0 {
		return nil, errors.New("peer not found")
	}

	return &str.Responses[0], nil
}

func (s *Shell) Refs(hash string, recursive bool) (<-chan string, error) {
	req := s.newRequest("refs", hash)
	if recursive {
		req.Opts["r"] = "true"
	}

	resp, err := req.Send(s.httpcli)
	if err != nil {
		return nil, err
	}

	if resp.Error != nil {
		return nil, resp.Error
	}

	out := make(chan string)
	go func() {
		defer resp.Close()
		scan := bufio.NewScanner(resp.Output)
		for scan.Scan() {
			if len(scan.Text()) > 0 {
				out <- scan.Text()
			}
		}
		close(out)
	}()

	return out, nil
}

func (s *Shell) Patch(root, action string, args ...string) (string, error) {
	cmdargs := append([]string{root, action}, args...)
	resp, err := s.newRequest("object/patch", cmdargs...).Send(s.httpcli)
	if err != nil {
		return "", err
	}
	defer resp.Close()

	if resp.Error != nil {
		return "", resp.Error
	}

	dec := json.NewDecoder(resp.Output)
	var out object
	err = dec.Decode(&out)
	if err != nil {
		return "", err
	}

	return out.Hash, nil
}

func (s *Shell) PatchLink(root, path, childhash string, create bool) (string, error) {
	cmdargs := []string{root, "add-link", path, childhash}

	req := s.newRequest("object/patch", cmdargs...)
	if create {
		req.Opts["create"] = "true"
	}

	resp, err := req.Send(s.httpcli)
	if err != nil {
		return "", err
	}
	defer resp.Close()

	if resp.Error != nil {
		return "", resp.Error
	}

	var out object
	err = json.NewDecoder(resp.Output).Decode(&out)
	if err != nil {
		return "", err
	}

	return out.Hash, nil
}

func (s *Shell) Get(hash, outdir string) error {
	resp, err := s.newRequest("get", hash).Send(s.httpcli)
	if err != nil {
		return err
	}
	defer resp.Close()

	if resp.Error != nil {
		return resp.Error
	}

	extractor := &tar.Extractor{Path: outdir}
	return extractor.Extract(resp.Output)
}

func (s *Shell) NewObject(template string) (string, error) {
	args := []string{}
	if template != "" {
		args = []string{template}
	}

	resp, err := s.newRequest("object/new", args...).Send(s.httpcli)
	if err != nil {
		return "", err
	}
	defer resp.Close()

	if resp.Error != nil {
		return "", resp.Error
	}

	var out object
	err = json.NewDecoder(resp.Output).Decode(&out)
	if err != nil {
		return "", err
	}

	return out.Hash, nil
}

func (s *Shell) ResolvePath(path string) (string, error) {
	resp, err := s.newRequest("object/stat", path).Send(s.httpcli)
	if err != nil {
		return "", err
	}
	defer resp.Close()

	if resp.Error != nil {
		return "", resp.Error
	}

	var out object
	err = json.NewDecoder(resp.Output).Decode(&out)
	if err != nil {
		return "", err
	}

	return out.Hash, nil
}

// returns ipfs version and commit sha
func (s *Shell) Version() (string, string, error) {
	resp, err := s.newRequest("version").Send(s.httpcli)
	if err != nil {
		return "", "", err
	}

	defer resp.Close()
	if resp.Error != nil {
		return "", "", resp.Error
	}

	ver := struct {
		Version string
		Commit  string
	}{}

	err = json.NewDecoder(resp.Output).Decode(&ver)
	if err != nil {
		return "", "", err
	}

	return ver.Version, ver.Commit, nil
}

func (s *Shell) IsUp() bool {
	_, _, err := s.Version()
	return err == nil
}

func (s *Shell) BlockStat(path string) (string, int, error) {
	resp, err := s.newRequest("block/stat", path).Send(s.httpcli)
	if err != nil {
		return "", 0, err
	}
	defer resp.Close()

	if resp.Error != nil {
		return "", 0, resp.Error
	}

	var inf struct {
		Key  string
		Size int
	}

	err = json.NewDecoder(resp.Output).Decode(&inf)
	if err != nil {
		return "", 0, err
	}

	return inf.Key, inf.Size, nil
}
<|endoftext|>


<commit_before>package slack

import (
	"encoding/json"
	"errors"
	"io"
	"io/ioutil"
	"net/http"
	"net/url"

	"golang.org/x/net/websocket"
)

const (
	API_BASE = "https://slack.com/api/"
)

type Credentials struct {
	HookToken   string
	Bot         Bot
	SlackbotUrl string
	Commands    map[string]string
}

type Message struct {
	Type        string       `json:"type"`
	SubType     string       `json:"subtype"`
	Channel     string       `json:"channel"`
	User        string       `json:"user"`
	Text        string       `json:"text"`
	Ts          string       `json:"ts"`
	File        FileObject   `json:"file"`
	Attachments []Attachment `json:"attachments"`
}

type FileObject struct {
	Mimetype   string `json:"mimetype"`
	Filetype   string `json:"filetype"`
	PrettyType string `json:"pretty_type"`
}

type Attachment struct {
	Fallback   string   `json:"fallback"`
	Color      string   `json:"color"`
	Pretext    string   `json:"pretext"`
	AuthorName string   `json:"author_name"`
	Title      string   `json:"title"`
	TitleLink  string   `json:"title_link"`
	Text       string   `json:"text"`
	Fields     []Field  `json:"fields"`
	MrkdwnIn   []string `json:"mrkdwn_in"`
}

type Field struct {
	Title string `json:"title"`
	Value string `json:"value"`
	Short bool   `json:"short"`
}

type Bot struct {
	Token  string `json:"token"`
	UserId string `json:"user_id"`
	User   string `json:"user"`
	Client *http.Client
}

func NewBot(token string) *Bot {
	return &Bot{Token: token}
}

func (b Bot) WithClient(c *http.Client) Bot {
	b.Client = c
	return b
}

func (b Bot) PostForm(endpoint string, data url.Values) (respJson map[string]interface{}, err error) {
	data.Add("token", b.Token)
	if _, ok := data["as_user"]; !ok {
		data.Add("as_user", "true")
	}

	if b.Client == nil {
		b.Client = http.DefaultClient
	}
	resp, err := b.Client.PostForm(API_BASE+endpoint, data)
	if err != nil {
		return
	}
	respJson, err = asJson(resp)
	if err != nil {
		return
	}
	if !respJson["ok"].(bool) {
		err = errors.New(respJson["error"].(string))
	}
	return
}

func asJson(resp *http.Response) (map[string]interface{}, error) {
	defer resp.Body.Close()
	m := make(map[string]interface{})
	dec := json.NewDecoder(resp.Body)
	for {
		if err := dec.Decode(&m); err == io.EOF {
			return m, nil
		} else if err != nil {
			return nil, err
		}
	}
}

func (b Bot) ChatPostMessage(data url.Values) (err error) {
	_, err = b.PostForm("chat.postMessage", data)
	return
}

func (b Bot) UsersGetPresence(user string) (presence string, err error) {
	resp, err := b.PostForm("users.getPresence", url.Values{"user": {user}})
	if err != nil {
		return
	} else {
		presence = resp["presence"].(string)
		return
	}
}

// for presence now
func (b Bot) UsersList(presence string) (present []string, err error) {
	resp, err := b.PostForm("users.list", url.Values{"presence": {presence}})
	if err != nil {
		return
	}
	members := resp["members"].([]interface{})
	present = make([]string, 0)
	for i := range members {
		m := members[i].(map[string]interface{})
		if p, ok := m["presence"]; ok {
			if p == "active" {
				present = append(present, m["id"].(string))
			}
		}
	}
	return
}

// Calls rtm.start API, return websocket url and bot id
func RtmStart(token string) (wsurl string, err error) {
	resp, err := http.PostForm(API_BASE+"rtm.start", url.Values{"token": {token}})
	if err != nil {
		return
	}
	respRtmStart, err := asJson(resp)
	if err != nil {
		return
	}
	wsurl = respRtmStart["url"].(string)
	return
}

func RtmReceive(ws *websocket.Conn) (m Message, err error) {
	err = websocket.JSON.Receive(ws, &m)
	return
}

func RtmSend(ws *websocket.Conn, m Message) error {
	return websocket.JSON.Send(ws, m)
}

func LoadCredentials(filename string) (credentials Credentials, err error) {
	f, err := ioutil.ReadFile(filename)
	if err != nil {
		return
	}
	err = json.Unmarshal(f, &credentials)
	return
}

func ValidateCommand(handler http.Handler, commands map[string]string) http.HandlerFunc {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		command := r.PostFormValue("command")
		token := r.PostFormValue("token")
		if t, ok := commands[command]; ok && t == token {
			handler.ServeHTTP(w, r)
		} else {
			w.WriteHeader(400)
		}
	})
}
<commit_msg>add get<commit_after>package slack

import (
	"encoding/json"
	"errors"
	"io"
	"io/ioutil"
	"net/http"
	"net/url"

	"golang.org/x/net/websocket"
)

const (
	API_BASE = "https://slack.com/api/"
)

type Credentials struct {
	HookToken   string
	Bot         Bot
	SlackbotUrl string
	Commands    map[string]string
}

type Message struct {
	Type        string       `json:"type"`
	SubType     string       `json:"subtype"`
	Channel     string       `json:"channel"`
	User        string       `json:"user"`
	Text        string       `json:"text"`
	Ts          string       `json:"ts"`
	File        FileObject   `json:"file"`
	Attachments []Attachment `json:"attachments"`
}

type FileObject struct {
	Mimetype   string `json:"mimetype"`
	Filetype   string `json:"filetype"`
	PrettyType string `json:"pretty_type"`
}

type Attachment struct {
	Fallback   string   `json:"fallback"`
	Color      string   `json:"color"`
	Pretext    string   `json:"pretext"`
	AuthorName string   `json:"author_name"`
	Title      string   `json:"title"`
	TitleLink  string   `json:"title_link"`
	Text       string   `json:"text"`
	Fields     []Field  `json:"fields"`
	MrkdwnIn   []string `json:"mrkdwn_in"`
}

type Field struct {
	Title string `json:"title"`
	Value string `json:"value"`
	Short bool   `json:"short"`
}

type Bot struct {
	Token  string `json:"token"`
	UserId string `json:"user_id"`
	User   string `json:"user"`
	Client *http.Client
}

func NewBot(token string) *Bot {
	return &Bot{Token: token}
}

func (b *Bot) WithClient(c *http.Client) *Bot {
	b.Client = c
	return b
}

func (b Bot) PostForm(endpoint string, data url.Values) (respJson map[string]interface{}, err error) {
	data.Add("token", b.Token)
	if _, ok := data["as_user"]; !ok {
		data.Add("as_user", "true")
	}

	if b.Client == nil {
		b.Client = http.DefaultClient
	}
	resp, err := b.Client.PostForm(API_BASE+endpoint, data)
	if err != nil {
		return
	}
	respJson, err = asJson(resp)
	if err != nil {
		return
	}
	if !respJson["ok"].(bool) {
		err = errors.New(respJson["error"].(string))
	}
	return
}

func (b *Bot) Get(endpoint string, params url.Values) (*http.Response, error) {
	params.Set("token", b.Token)
	if b.Client == nil {
		b.Client = http.DefaultClient
	}
	return b.Client.Get(API_BASE + endpoint + "?" + params.Encode())
}

func asJson(resp *http.Response) (map[string]interface{}, error) {
	defer resp.Body.Close()
	m := make(map[string]interface{})
	dec := json.NewDecoder(resp.Body)
	for {
		if err := dec.Decode(&m); err == io.EOF {
			return m, nil
		} else if err != nil {
			return nil, err
		}
	}
}

func (b Bot) ChatPostMessage(data url.Values) (err error) {
	_, err = b.PostForm("chat.postMessage", data)
	return
}

func (b Bot) UsersGetPresence(user string) (presence string, err error) {
	resp, err := b.PostForm("users.getPresence", url.Values{"user": {user}})
	if err != nil {
		return
	} else {
		presence = resp["presence"].(string)
		return
	}
}

// for presence now
func (b Bot) UsersList(presence string) (present []string, err error) {
	resp, err := b.PostForm("users.list", url.Values{"presence": {presence}})
	if err != nil {
		return
	}
	members := resp["members"].([]interface{})
	present = make([]string, 0)
	for i := range members {
		m := members[i].(map[string]interface{})
		if p, ok := m["presence"]; ok {
			if p == "active" {
				present = append(present, m["id"].(string))
			}
		}
	}
	return
}

// Calls rtm.start API, return websocket url and bot id
func RtmStart(token string) (wsurl string, err error) {
	resp, err := http.PostForm(API_BASE+"rtm.start", url.Values{"token": {token}})
	if err != nil {
		return
	}
	respRtmStart, err := asJson(resp)
	if err != nil {
		return
	}
	wsurl = respRtmStart["url"].(string)
	return
}

func RtmReceive(ws *websocket.Conn) (m Message, err error) {
	err = websocket.JSON.Receive(ws, &m)
	return
}

func RtmSend(ws *websocket.Conn, m Message) error {
	return websocket.JSON.Send(ws, m)
}

func LoadCredentials(filename string) (credentials Credentials, err error) {
	f, err := ioutil.ReadFile(filename)
	if err != nil {
		return
	}
	err = json.Unmarshal(f, &credentials)
	return
}

func ValidateCommand(handler http.Handler, commands map[string]string) http.HandlerFunc {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		command := r.PostFormValue("command")
		token := r.PostFormValue("token")
		if t, ok := commands[command]; ok && t == token {
			handler.ServeHTTP(w, r)
		} else {
			w.WriteHeader(400)
		}
	})
}
<|endoftext|>


<commit_before>package sequence

// Sobol represents a Sobol sequence. The maximal number of dimensions is 21201,
// and the maximal number of points is 2^32.
//
// https://en.wikipedia.org/wiki/Sobol_sequence
type Sobol struct {
	dimensions uint
	offset     uint
	cursor     []uint32
}

// NewSobol returns a new Sobol sequence.
func NewSobol(dimensions uint, scramble int64) *Sobol {
	cursor := make([]uint32, dimensions)
	for i := range cursor {
		cursor[i] = uint32(scramble)
	}

	return &Sobol{
		dimensions: dimensions,
		cursor:     cursor,
	}
}

// Next advances the sequence and returns the traversed points.
func (s *Sobol) Next(points uint) []float64 {
	const (
		bits = 32
		size = 1 << bits
	)

	dimensions, offset, cursor := s.dimensions, s.offset, s.cursor

	data := make([]float64, points*dimensions)
	for i := uint(0); i < points; i++ {
		k := uint(0)
		for j := offset + i; j&1 != 0; j >>= 1 {
			k++
		}
		for j := uint(0); j < dimensions; j++ {
			data[i*dimensions+j] = float64(cursor[j]) / size
			cursor[j] ^= sobolData[j*bits+k]
		}
	}

	s.offset += points

	return data
}
<commit_msg>Inline a const<commit_after>package sequence

// Sobol represents a Sobol sequence. The maximal number of dimensions is 21201,
// and the maximal number of points is 2^32.
//
// https://en.wikipedia.org/wiki/Sobol_sequence
type Sobol struct {
	dimensions uint
	offset     uint
	cursor     []uint32
}

// NewSobol returns a new Sobol sequence.
func NewSobol(dimensions uint, scramble int64) *Sobol {
	cursor := make([]uint32, dimensions)
	for i := range cursor {
		cursor[i] = uint32(scramble)
	}

	return &Sobol{
		dimensions: dimensions,
		cursor:     cursor,
	}
}

// Next advances the sequence and returns the traversed points.
func (s *Sobol) Next(points uint) []float64 {
	const (
		bits = 32
	)

	dimensions, offset, cursor := s.dimensions, s.offset, s.cursor

	data := make([]float64, points*dimensions)
	for i := uint(0); i < points; i++ {
		k := uint(0)
		for j := offset + i; j&1 != 0; j >>= 1 {
			k++
		}
		for j := uint(0); j < dimensions; j++ {
			data[i*dimensions+j] = float64(cursor[j]) / (1 << bits)
			cursor[j] ^= sobolData[j*bits+k]
		}
	}

	s.offset += points

	return data
}
<|endoftext|>


<commit_before>package honeybadger

import (
	"code.google.com/p/go-uuid/uuid"
	"encoding/json"
)

type hash map[string]interface{}

type Notice struct {
	APIKey       string
	Error        error
	Token        string
	ErrorMessage string
	Hostname     string
	Env          string
}

func (n *Notice) asJSON() *hash {
	return &hash{
		"api_key": n.APIKey,
		"notifier": &hash{
			"name":    "honeybadger",
			"url":     "https://github.com/honeybadger-io/honeybadger-go",
			"version": "0.0.0",
		},
		"error": &hash{
			"token":     n.Token,
			"message":   n.ErrorMessage,
			"backtrace": []map[string]interface{}{},
		},
		"server": &hash{
			"environment_name": n.Env,
			"hostname":         n.Hostname,
		},
	}
}

func (n *Notice) toJSON() []byte {
	if out, err := json.Marshal(n.asJSON()); err == nil {
		return out
	} else {
		panic(err)
	}
}

func newNotice(config *Config, err error) *Notice {
	notice := Notice{
		APIKey:       config.APIKey,
		Error:        err,
		Token:        uuid.NewRandom().String(),
		ErrorMessage: err.Error(),
		Env:          config.Env,
		Hostname:     config.Hostname,
	}

	return &notice
}
<commit_msg>Add backtrace.<commit_after>package honeybadger

import (
	"code.google.com/p/go-uuid/uuid"
	"encoding/json"
	"runtime"
	"strconv"
)

const MaxFrames = 20

type Frame struct {
	Number string `json:"number"`
	File   string `json:"file"`
	Method string `json:"method"`
}

type hash map[string]interface{}

type Notice struct {
	APIKey       string
	Error        error
	Token        string
	ErrorMessage string
	Hostname     string
	Env          string
	Backtrace    []*Frame
}

func (n *Notice) asJSON() *hash {
	return &hash{
		"api_key": n.APIKey,
		"notifier": &hash{
			"name":    "honeybadger",
			"url":     "https://github.com/honeybadger-io/honeybadger-go",
			"version": "0.0.0",
		},
		"error": &hash{
			"token":     n.Token,
			"message":   n.ErrorMessage,
			"backtrace": n.Backtrace,
		},
		"server": &hash{
			"environment_name": n.Env,
			"hostname":         n.Hostname,
		},
	}
}

func (n *Notice) toJSON() []byte {
	if out, err := json.Marshal(n.asJSON()); err == nil {
		return out
	} else {
		panic(err)
	}
}

func generateStack() (frames []*Frame) {
	stack := make([]uintptr, MaxFrames)
	length := runtime.Callers(4, stack[:])
	for _, pc := range stack[:length] {
		f := runtime.FuncForPC(pc)
		if f == nil {
			continue
		}
		file, line := f.FileLine(pc)
		frame := &Frame{
			File:   file,
			Number: strconv.Itoa(line),
			Method: f.Name(),
		}
		frames = append(frames, frame)
	}

	return
}

func newNotice(config *Config, err error) *Notice {
	notice := Notice{
		APIKey:       config.APIKey,
		Error:        err,
		Token:        uuid.NewRandom().String(),
		ErrorMessage: err.Error(),
		Env:          config.Env,
		Hostname:     config.Hostname,
		Backtrace:    generateStack(),
	}

	return &notice
}
<|endoftext|>