<commit_before>package metrics

import (
	"fmt"
	"time"

	"github.com/pachyderm/pachyderm/src/client/pkg/uuid"
	"github.com/pachyderm/pachyderm/src/client/version"
	db "github.com/pachyderm/pachyderm/src/server/pfs/db"

	"github.com/dancannon/gorethink"
	"go.pedge.io/lion/proto"
	"golang.org/x/net/context"
	"google.golang.org/grpc/metadata"
	kube "k8s.io/kubernetes/pkg/client/unversioned"
)

type Reporter struct {
	clusterID  string
	kubeClient *kube.Client
	dbClient   *gorethink.Session
	pfsDbName  string
	ppsDbName  string
}

func NewReporter(clusterID string, kubeClient *kube.Client, address string, pfsDbName string, ppsDbName string) (*Reporter, error) {
	dbClient, err := db.DbConnect(address)
	if err != nil {
		return nil, fmt.Errorf("Error connected to DB when reporting metrics: %v\n", err)
	}
	return &Reporter{
		clusterID:  clusterID,
		kubeClient: kubeClient,
		dbClient:   dbClient,
		pfsDbName:  pfsDbName,
		ppsDbName:  ppsDbName,
	}, nil
}

// If we're not reporting metrics, incrementing should do nothing
var metricsEnabled = false

// Segment API allows for map[string]interface{} for a single user's traits
// But we only care about things that are countable for the moment
// map userID -> action name -> count
type countableActions map[string]interface{}
type countableUserActions map[string]countableActions

type incrementUserAction struct {
	action string
	user   string
}

var userActions = make(countableUserActions)
var incrementActionChannel = make(chan *incrementUserAction, 0)

//IncrementUserAction updates a counter per user per action for an API method by name
func IncrementUserAction(ctx context.Context, action string) {
	if !metricsEnabled {
		return
	}
	fmt.Printf("!!! trying to increment user actionw ctx: [%v]\n", ctx)
	md, ok := metadata.FromContext(ctx)
	fmt.Printf("!!! metadata: %v\n", md)
	if ok && md["userid"] != nil && len(md["userid"]) > 0 {
		userID := md["userid"][0]
		fmt.Printf("!!! incrementing user action: %v, %v\n", userID, action)
		incrementActionChannel <- &incrementUserAction{
			action: action,
			user:   userID,
		}
		fmt.Printf("!!! incremented user action!\n")
	}
}

func (r *Reporter) dbMetrics(metrics *Metrics) {
	cursor, err := gorethink.Object(
		"Repos",
		gorethink.DB(r.pfsDbName).Table("Repos").Count(),
		"Commits",
		gorethink.DB(r.pfsDbName).Table("Commits").Count(),
		"ArchivedCommits",
		gorethink.DB(r.pfsDbName).Table("Commits").Filter(
			map[string]interface{}{
				"Archived": true,
			},
		).Count(),
		"CancelledCommits",
		gorethink.DB(r.pfsDbName).Table("Commits").Filter(
			map[string]interface{}{
				"Cancelled": true,
			},
		).Count(),
		"Files",
		gorethink.DB(r.pfsDbName).Table("Diffs").Group("Path").Ungroup().Count(),
		"Jobs",
		gorethink.DB(r.ppsDbName).Table("JobInfos").Count(),
		"Pipelines",
		gorethink.DB(r.ppsDbName).Table("PipelineInfos").Count(),
	).Run(r.dbClient)
	if err != nil {
		protolion.Errorf("Error Fetching Metrics:%+v", err)
	}
	cursor.One(&metrics)
}

// ReportMetrics blocks and reports metrics every 15 seconds
func (r *Reporter) ReportMetrics() {
	metricsEnabled = true
	reportingTicker := time.NewTicker(time.Second * 15)
	for {
		select {
		case incrementAction := <-incrementActionChannel:
			fmt.Printf("incrementing action in map!\n")
			if userActions[incrementAction.user] == nil {
				userActions[incrementAction.user] = make(countableActions)
			}
			val, ok := userActions[incrementAction.user][incrementAction.action]
			if ok {
				userActions[incrementAction.user][incrementAction.action] = val.(uint64) + uint64(1)
			} else {
				userActions[incrementAction.user][incrementAction.action] = uint64(0)
			}
			break
		case <-reportingTicker.C:
			fmt.Printf("!!! TICK - reporting to segment\n")
			r.reportToSegment()
			fmt.Printf("!!! kicked off segment reporting\n")
		}
	}
}

func (r *Reporter) reportToSegment() {
	fmt.Printf("!!! Reporting to segment, user actions: [%v]\n", userActions)
	if len(userActions) > 0 {
		batchOfUserActions := make(countableUserActions)
		// copy the existing stats into a new object so we can make the segment
		// request asynchronously
		for user, actions := range userActions {
			singleUserActions := make(countableActions)
			for name, count := range actions {
				singleUserActions[name] = count
			}
			batchOfUserActions[user] = singleUserActions
			go identifyUser(user)
		}
		go r.reportUserMetrics(batchOfUserActions)
		userActions = make(countableUserActions)
	}
	go r.reportClusterMetrics()
}

func (r *Reporter) reportUserMetrics(batchOfUserActions countableUserActions) {
	if len(batchOfUserActions) > 0 {
		reportUserMetricsToSegment(batchOfUserActions)
	}
}

func (r *Reporter) reportClusterMetrics() {
	metrics := &Metrics{}
	r.dbMetrics(metrics)
	externalMetrics(r.kubeClient, metrics)
	metrics.ID = r.clusterID
	metrics.PodID = uuid.NewWithoutDashes()
	metrics.Version = version.PrettyPrintVersion(version.Version)
	reportClusterMetricsToSegment(metrics)
}
<commit_msg>Combine these lines since values initialize to 0<commit_after>package metrics

import (
	"fmt"
	"time"

	"github.com/pachyderm/pachyderm/src/client/pkg/uuid"
	"github.com/pachyderm/pachyderm/src/client/version"
	db "github.com/pachyderm/pachyderm/src/server/pfs/db"

	"github.com/dancannon/gorethink"
	"go.pedge.io/lion/proto"
	"golang.org/x/net/context"
	"google.golang.org/grpc/metadata"
	kube "k8s.io/kubernetes/pkg/client/unversioned"
)

type Reporter struct {
	clusterID  string
	kubeClient *kube.Client
	dbClient   *gorethink.Session
	pfsDbName  string
	ppsDbName  string
}

func NewReporter(clusterID string, kubeClient *kube.Client, address string, pfsDbName string, ppsDbName string) (*Reporter, error) {
	dbClient, err := db.DbConnect(address)
	if err != nil {
		return nil, fmt.Errorf("Error connected to DB when reporting metrics: %v\n", err)
	}
	return &Reporter{
		clusterID:  clusterID,
		kubeClient: kubeClient,
		dbClient:   dbClient,
		pfsDbName:  pfsDbName,
		ppsDbName:  ppsDbName,
	}, nil
}

// If we're not reporting metrics, incrementing should do nothing
var metricsEnabled = false

// Segment API allows for map[string]interface{} for a single user's traits
// But we only care about things that are countable for the moment
// map userID -> action name -> count
type countableActions map[string]interface{}
type countableUserActions map[string]countableActions

type incrementUserAction struct {
	action string
	user   string
}

var userActions = make(countableUserActions)
var incrementActionChannel = make(chan *incrementUserAction, 0)

//IncrementUserAction updates a counter per user per action for an API method by name
func IncrementUserAction(ctx context.Context, action string) {
	if !metricsEnabled {
		return
	}
	fmt.Printf("!!! trying to increment user actionw ctx: [%v]\n", ctx)
	md, ok := metadata.FromContext(ctx)
	fmt.Printf("!!! metadata: %v\n", md)
	if ok && md["userid"] != nil && len(md["userid"]) > 0 {
		userID := md["userid"][0]
		fmt.Printf("!!! incrementing user action: %v, %v\n", userID, action)
		incrementActionChannel <- &incrementUserAction{
			action: action,
			user:   userID,
		}
		fmt.Printf("!!! incremented user action!\n")
	}
}

func (r *Reporter) dbMetrics(metrics *Metrics) {
	cursor, err := gorethink.Object(
		"Repos",
		gorethink.DB(r.pfsDbName).Table("Repos").Count(),
		"Commits",
		gorethink.DB(r.pfsDbName).Table("Commits").Count(),
		"ArchivedCommits",
		gorethink.DB(r.pfsDbName).Table("Commits").Filter(
			map[string]interface{}{
				"Archived": true,
			},
		).Count(),
		"CancelledCommits",
		gorethink.DB(r.pfsDbName).Table("Commits").Filter(
			map[string]interface{}{
				"Cancelled": true,
			},
		).Count(),
		"Files",
		gorethink.DB(r.pfsDbName).Table("Diffs").Group("Path").Ungroup().Count(),
		"Jobs",
		gorethink.DB(r.ppsDbName).Table("JobInfos").Count(),
		"Pipelines",
		gorethink.DB(r.ppsDbName).Table("PipelineInfos").Count(),
	).Run(r.dbClient)
	if err != nil {
		protolion.Errorf("Error Fetching Metrics:%+v", err)
	}
	cursor.One(&metrics)
}

// ReportMetrics blocks and reports metrics every 15 seconds
func (r *Reporter) ReportMetrics() {
	metricsEnabled = true
	reportingTicker := time.NewTicker(time.Second * 15)
	for {
		select {
		case incrementAction := <-incrementActionChannel:
			fmt.Printf("incrementing action in map!\n")
			if userActions[incrementAction.user] == nil {
				userActions[incrementAction.user] = make(countableActions)
			}
			val, _ := userActions[incrementAction.user][incrementAction.action]
			userActions[incrementAction.user][incrementAction.action] = val.(uint64) + uint64(1)
			break
		case <-reportingTicker.C:
			fmt.Printf("!!! TICK - reporting to segment\n")
			r.reportToSegment()
			fmt.Printf("!!! kicked off segment reporting\n")
		}
	}
}

func (r *Reporter) reportToSegment() {
	fmt.Printf("!!! Reporting to segment, user actions: [%v]\n", userActions)
	if len(userActions) > 0 {
		batchOfUserActions := make(countableUserActions)
		// copy the existing stats into a new object so we can make the segment
		// request asynchronously
		for user, actions := range userActions {
			singleUserActions := make(countableActions)
			for name, count := range actions {
				singleUserActions[name] = count
			}
			batchOfUserActions[user] = singleUserActions
			go identifyUser(user)
		}
		go r.reportUserMetrics(batchOfUserActions)
		userActions = make(countableUserActions)
	}
	go r.reportClusterMetrics()
}

func (r *Reporter) reportUserMetrics(batchOfUserActions countableUserActions) {
	if len(batchOfUserActions) > 0 {
		reportUserMetricsToSegment(batchOfUserActions)
	}
}

func (r *Reporter) reportClusterMetrics() {
	metrics := &Metrics{}
	r.dbMetrics(metrics)
	externalMetrics(r.kubeClient, metrics)
	metrics.ID = r.clusterID
	metrics.PodID = uuid.NewWithoutDashes()
	metrics.Version = version.PrettyPrintVersion(version.Version)
	reportClusterMetricsToSegment(metrics)
}
<|endoftext|>


<commit_before>package leader

import (
	"context"
	"crypto/rand"
	"encoding/hex"
	"time"

	"chain/database/sql"
	"chain/log"
)

// Run runs as a goroutine, trying once every five seconds to become
// the leader for the core.  If it succeeds, then it calls the
// function lead (for generating or fetching blocks, and for
// expiring reservations) and enters a leadership-keepalive loop.
//
// Function lead is called when the local process becomes the leader.
// Its context is canceled when the process is deposed as leader.
//
// The Chain Core has up to a 10-second refractory period after
// shutdown, during which no process can become the new leader.
func Run(db *sql.DB, addr string, lead func(context.Context)) {
	ctx := context.Background()
	leaderKeyBytes := make([]byte, 32)
	_, err := rand.Read(leaderKeyBytes)
	if err != nil {
		log.Fatal(ctx, log.KeyError, err)
	}
	l := &leader{
		db:      db,
		key:     hex.EncodeToString(leaderKeyBytes),
		lead:    lead,
		address: addr,
	}
	log.Messagef(ctx, "Chose leaderKey: %s", l.key)

	update(ctx, l)
	for range time.Tick(5 * time.Second) {
		update(ctx, l)
	}
}

type leader struct {
	// config
	db      *sql.DB
	key     string
	lead    func(context.Context)
	address string

	// state
	leading bool
	cancel  func()
}

func update(ctx context.Context, l *leader) {
	const (
		insertQ = `
			INSERT INTO leader (leader_key, leader_address, expiry) VALUES ($1, $2, CURRENT_TIMESTAMP + INTERVAL '10 seconds')
			ON CONFLICT (singleton) DO UPDATE SET leader_key = $1, leader_address = $2, expiry = CURRENT_TIMESTAMP + INTERVAL '10 seconds'
				WHERE leader.expiry < CURRENT_TIMESTAMP
		`
		updateQ = `
			UPDATE leader SET expiry = CURRENT_TIMESTAMP + INTERVAL '10 seconds'
				WHERE leader_key = $1
		`
	)

	if l.leading {
		res, err := l.db.Exec(ctx, updateQ, l.key, l.address)
		if err == nil {
			rowsAffected, err := res.RowsAffected()
			if err == nil && rowsAffected > 0 {
				// still leading
				return
			}
		}

		// Either the UPDATE affected no rows, or it (or RowsAffected)
		// produced an error.

		if err != nil {
			log.Error(ctx, err)
		}
		log.Messagef(ctx, "No longer core leader")
		l.cancel()
		l.leading = false
		l.cancel = nil
	} else {
		// Try to put this process's key into the leader table.  It
		// succeeds if the table's empty or the existing row (there can be
		// only one) is expired.  It fails otherwise.
		//
		// On success, this process's leadership expires in 10 seconds
		// unless it's renewed in the UPDATE query above.
		// That extends it for another 10 seconds.
		res, err := l.db.Exec(ctx, insertQ, l.key, l.address)
		if err != nil {
			log.Error(ctx, err)
			return
		}
		rowsAffected, err := res.RowsAffected()
		if err != nil {
			log.Error(ctx, err)
			return
		}

		if rowsAffected == 0 {
			return
		}

		log.Messagef(ctx, "I am the core leader")

		l.leading = true
		ctx, l.cancel = context.WithCancel(ctx)
		go l.lead(ctx)
	}
}
<commit_msg>bugfix: consistent column name<commit_after>package leader

import (
	"context"
	"crypto/rand"
	"encoding/hex"
	"time"

	"chain/database/sql"
	"chain/log"
)

// Run runs as a goroutine, trying once every five seconds to become
// the leader for the core.  If it succeeds, then it calls the
// function lead (for generating or fetching blocks, and for
// expiring reservations) and enters a leadership-keepalive loop.
//
// Function lead is called when the local process becomes the leader.
// Its context is canceled when the process is deposed as leader.
//
// The Chain Core has up to a 10-second refractory period after
// shutdown, during which no process can become the new leader.
func Run(db *sql.DB, addr string, lead func(context.Context)) {
	ctx := context.Background()
	leaderKeyBytes := make([]byte, 32)
	_, err := rand.Read(leaderKeyBytes)
	if err != nil {
		log.Fatal(ctx, log.KeyError, err)
	}
	l := &leader{
		db:      db,
		key:     hex.EncodeToString(leaderKeyBytes),
		lead:    lead,
		address: addr,
	}
	log.Messagef(ctx, "Chose leaderKey: %s", l.key)

	update(ctx, l)
	for range time.Tick(5 * time.Second) {
		update(ctx, l)
	}
}

type leader struct {
	// config
	db      *sql.DB
	key     string
	lead    func(context.Context)
	address string

	// state
	leading bool
	cancel  func()
}

func update(ctx context.Context, l *leader) {
	const (
		insertQ = `
			INSERT INTO leader (leader_key, address, expiry) VALUES ($1, $2, CURRENT_TIMESTAMP + INTERVAL '10 seconds')
			ON CONFLICT (singleton) DO UPDATE SET leader_key = $1, address = $2, expiry = CURRENT_TIMESTAMP + INTERVAL '10 seconds'
				WHERE leader.expiry < CURRENT_TIMESTAMP
		`
		updateQ = `
			UPDATE leader SET expiry = CURRENT_TIMESTAMP + INTERVAL '10 seconds'
				WHERE leader_key = $1
		`
	)

	if l.leading {
		res, err := l.db.Exec(ctx, updateQ, l.key, l.address)
		if err == nil {
			rowsAffected, err := res.RowsAffected()
			if err == nil && rowsAffected > 0 {
				// still leading
				return
			}
		}

		// Either the UPDATE affected no rows, or it (or RowsAffected)
		// produced an error.

		if err != nil {
			log.Error(ctx, err)
		}
		log.Messagef(ctx, "No longer core leader")
		l.cancel()
		l.leading = false
		l.cancel = nil
	} else {
		// Try to put this process's key into the leader table.  It
		// succeeds if the table's empty or the existing row (there can be
		// only one) is expired.  It fails otherwise.
		//
		// On success, this process's leadership expires in 10 seconds
		// unless it's renewed in the UPDATE query above.
		// That extends it for another 10 seconds.
		res, err := l.db.Exec(ctx, insertQ, l.key, l.address)
		if err != nil {
			log.Error(ctx, err)
			return
		}
		rowsAffected, err := res.RowsAffected()
		if err != nil {
			log.Error(ctx, err)
			return
		}

		if rowsAffected == 0 {
			return
		}

		log.Messagef(ctx, "I am the core leader")

		l.leading = true
		ctx, l.cancel = context.WithCancel(ctx)
		go l.lead(ctx)
	}
}
<|endoftext|>


<commit_before>package main

func main()
	var c1 c2 c2 chan int
	// START0 OMIT
	select {
	case v1 := <-c1:
		fmt.Printf("received %v from c1\n", v1)
	case v2 := <-c2:
		fmt.Printf("received %v from c2\n", v1)
	case c3 <- 23:
		fmt.Printf("sent %v to c3\n", 23)
	default:
		fmt.Printf("no one was ready to communicate\n")
	}
	// STOP0 OMIT
}
<commit_msg>      go.talk: Content fixes for GAE deployment.  appcfg.py wants to compile everything, and select.go has some errors in it preventing deploment. The part being cleaned-up here isn't present in the content of the presentation:<commit_after>package main

func main() {
	var c1, c2, c3 chan int
	// START0 OMIT
	select {
	case v1 := <-c1:
		fmt.Printf("received %v from c1\n", v1)
	case v2 := <-c2:
		fmt.Printf("received %v from c2\n", v1)
	case c3 <- 23:
		fmt.Printf("sent %v to c3\n", 23)
	default:
		fmt.Printf("no one was ready to communicate\n")
	}
	// STOP0 OMIT
}
<|endoftext|>


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

package trello

import "fmt"

type Label struct {
	ID      string `json:"id"`
	IDBoard string `json:"idBoard"`
	Name    string `json:"name"`
	Color   string `json:"color"`
	Uses    int    `json:"uses"`
}

func (c *Client) GetLabel(labelID string, args Arguments) (label *Label, err error) {
	path := fmt.Sprintf("labels/%s", labelID)
	err = c.Get(path, args, &label)
	return
}

func (b *Board) GetLabels(args Arguments) (labels []*Label, err error) {
	path := fmt.Sprintf("boards/%s/labels", b.ID)
	err = b.client.Get(path, args, &labels)
	return
}<commit_msg>Update label.go<commit_after>// Copyright © 2016 Aaron Longwell
//
// Use of this source code is governed by an MIT licese.
// Details in the LICENSE file.

package trello

import "fmt"

// Label represents a Trello label.
// Labels are defined per board, and can be applied to the cards on that board.
// https://developers.trello.com/reference/#label-object
type Label struct {
	ID      string `json:"id"`
	IDBoard string `json:"idBoard"`
	Name    string `json:"name"`
	Color   string `json:"color"`
	Uses    int    `json:"uses"`
}

// GetLabel takes a label id and Arguments and returns the matching label (per Trello member)
// or an error.
func (c *Client) GetLabel(labelID string, args Arguments) (label *Label, err error) {
	path := fmt.Sprintf("labels/%s", labelID)
	err = c.Get(path, args, &label)
	return
}

// GetLabels takes Arguments and returns a slice containing all labels of the receiver board or an error.
func (b *Board) GetLabels(args Arguments) (labels []*Label, err error) {
	path := fmt.Sprintf("boards/%s/labels", b.ID)
	err = b.client.Get(path, args, &labels)
	return
}
<|endoftext|>


<commit_before>package utp

/*
#include "utp.h"
#include <stdbool.h>

struct utp_process_udp_args {
	const byte *buf;
	size_t len;
	const struct sockaddr *sa;
	socklen_t sal;
};

void process_received_messages(utp_context *ctx, struct utp_process_udp_args *args, size_t argslen)
{
	bool gotUtp = false;
	size_t i;
	for (i = 0; i < argslen; i++) {
		struct utp_process_udp_args *a = &args[i];
		//if (!a->len) continue;
		if (utp_process_udp(ctx, a->buf, a->len, a->sa, a->sal)) {
			gotUtp = true;
		}
	}
	if (gotUtp) {
		utp_issue_deferred_acks(ctx);
		utp_check_timeouts(ctx);
	}
}
*/
import "C"
import (
	"context"
	"errors"
	"net"
	"runtime/pprof"
	"time"

	"github.com/anacrolix/missinggo/inproc"
	"github.com/anacrolix/mmsg"
)

type Socket struct {
	pc            net.PacketConn
	ctx           *C.utp_context
	backlog       chan *Conn
	closed        bool
	conns         map[*C.utp_socket]*Conn
	nonUtpReads   chan packet
	writeDeadline time.Time
	readDeadline  time.Time
}

var (
	_               net.PacketConn = (*Socket)(nil)
	_               net.Listener   = (*Socket)(nil)
	errSocketClosed                = errors.New("Socket closed")
)

type packet struct {
	b    []byte
	from net.Addr
}

func listenPacket(network, addr string) (pc net.PacketConn, err error) {
	if network == "inproc" {
		return inproc.ListenPacket(network, addr)
	}
	return net.ListenPacket(network, addr)
}

func NewSocket(network, addr string) (*Socket, error) {
	pc, err := listenPacket(network, addr)
	if err != nil {
		return nil, err
	}
	mu.Lock()
	defer mu.Unlock()
	ctx := C.utp_init(2)
	if ctx == nil {
		panic(ctx)
	}
	ctx.setCallbacks()
	if utpLogging {
		ctx.setOption(C.UTP_LOG_NORMAL, 1)
		ctx.setOption(C.UTP_LOG_MTU, 1)
		ctx.setOption(C.UTP_LOG_DEBUG, 1)
	}
	s := &Socket{
		pc:          pc,
		ctx:         ctx,
		backlog:     make(chan *Conn, 5),
		conns:       make(map[*C.utp_socket]*Conn),
		nonUtpReads: make(chan packet, 100),
	}
	libContextToSocket[ctx] = s
	go s.timeoutChecker()
	go s.packetReader()
	return s, nil
}

func (s *Socket) onLibSocketDestroyed(ls *C.utp_socket) {
	delete(s.conns, ls)
}

func (s *Socket) newConn(us *C.utp_socket) *Conn {
	c := &Conn{
		s:         s,
		us:        us,
		localAddr: s.pc.LocalAddr(),
	}
	c.cond.L = &mu
	s.conns[us] = c
	c.writeDeadlineTimer = time.AfterFunc(-1, c.cond.Broadcast)
	c.readDeadlineTimer = time.AfterFunc(-1, c.cond.Broadcast)
	return c
}

const maxNumBuffers = 16

func (s *Socket) packetReader() {
	mc := mmsg.NewConn(s.pc)
	// Increasing the messages increases the memory use, but also means we can
	// reduces utp_issue_deferred_acks and syscalls which should improve
	// efficiency. On the flip side, not all OSs implement batched reads.
	ms := make([]mmsg.Message, func() int {
		if mc.Err() == nil {
			return maxNumBuffers
		} else {
			return 1
		}
	}())
	for i := range ms {
		// The IPv4 UDP limit is allegedly about 64 KiB, and this message has
		// been seen on receiving on Windows with just 0x1000: wsarecvfrom: A
		// message sent on a datagram socket was larger than the internal
		// message buffer or some other network limit, or the buffer used to
		// receive a datagram into was smaller than the datagram itself.
		ms[i].Buffers = [][]byte{make([]byte, 0x10000)}
	}
	// Some crap OSs like Windoze will raise errors in Reads that don't
	// actually mean we should stop.
	consecutiveErrors := 0
	for {
		// In C, all the reads are processed and when it threatens to block,
		// we're supposed to call utp_issue_deferred_acks.
		n, err := mc.RecvMsgs(ms)
		if n == 1 {
			singleMsgRecvs.Add(1)
		}
		if n > 1 {
			multiMsgRecvs.Add(1)
		}
		if err != nil {
			mu.Lock()
			closed := s.closed
			mu.Unlock()
			if closed {
				// We don't care.
				return
			}
			// See https://github.com/anacrolix/torrent/issues/83. If we get
			// an endless stream of errors (such as the PacketConn being
			// Closed outside of our control, this work around may need to be
			// reconsidered.
			Logger.Printf("ignoring socket read error: %s", err)
			consecutiveErrors++
			if consecutiveErrors >= 100 {
				Logger.Print("too many consecutive errors, closing socket")
				s.Close()
				return
			}
			continue
		}
		consecutiveErrors = 0
		expMap.Add("successful mmsg receive calls", 1)
		expMap.Add("received messages", int64(n))
		s.processReceivedMessages(ms[:n])
	}
}

func (s *Socket) processReceivedMessages(ms []mmsg.Message) {
	mu.Lock()
	defer mu.Unlock()
	if s.closed {
		return
	}
	if processPacketsInC {
		var args [maxNumBuffers]C.struct_utp_process_udp_args
		for i, m := range ms {
			a := &args[i]
			a.buf = (*C.byte)(&m.Buffers[0][0])
			a.len = C.size_t(m.N)
			a.sa, a.sal = netAddrToLibSockaddr(m.Addr)
		}
		C.process_received_messages(s.ctx, &args[0], C.size_t(len(ms)))
	} else {
		gotUtp := false
		for _, m := range ms {
			gotUtp = s.processReceivedMessage(m.Buffers[0][:m.N], m.Addr) || gotUtp
		}
		if gotUtp {
			s.afterReceivingUtpMessages()
		}
	}
}

func (s *Socket) afterReceivingUtpMessages() {
	pprof.Do(context.Background(), pprof.Labels("go-libutp", "afterReceivingUtpMessages"), func(context.Context) {
		C.utp_issue_deferred_acks(s.ctx)
		// TODO: When is this done in C?
		C.utp_check_timeouts(s.ctx)
	})
}

func (s *Socket) processReceivedMessage(b []byte, addr net.Addr) (utp bool) {
	if s.utpProcessUdp(b, addr) {
		socketUtpPacketsReceived.Add(1)
		return true
	} else {
		s.onReadNonUtp(b, addr)
		return false
	}
}

// Process packet batches entirely from C, reducing CGO overhead. Currently
// requires GODEBUG=cgocheck=0.
const processPacketsInC = false

// Wraps libutp's utp_process_udp, returning relevant information.
func (s *Socket) utpProcessUdp(b []byte, addr net.Addr) (utp bool) {
	sa, sal := netAddrToLibSockaddr(addr)
	if len(b) == 0 {
		// The implementation of utp_process_udp rejects null buffers, and
		// anything smaller than the UTP header size. It's also prone to
		// assert on those, which we don't want to trigger.
		return false
	}
	if missinggo.AddrPort(addr) == 0 {
		return false
	}
	ret := C.utp_process_udp(s.ctx, (*C.byte)(&b[0]), C.size_t(len(b)), sa, sal)
	switch ret {
	case 1:
		return true
	case 0:
		return false
	default:
		panic(ret)
	}
}

func (s *Socket) timeoutChecker() {
	for {
		mu.Lock()
		if s.closed {
			mu.Unlock()
			return
		}
		// C.utp_issue_deferred_acks(s.ctx)
		C.utp_check_timeouts(s.ctx)
		mu.Unlock()
		time.Sleep(500 * time.Millisecond)
	}
}

func (s *Socket) Close() error {
	mu.Lock()
	defer mu.Unlock()
	return s.closeLocked()
}

func (s *Socket) closeLocked() error {
	if s.closed {
		return nil
	}
	// Calling this deletes the pointer. It must not be referred to after
	// this.
	C.utp_destroy(s.ctx)
	s.ctx = nil
	s.pc.Close()
	close(s.backlog)
	close(s.nonUtpReads)
	s.closed = true
	return nil
}

func (s *Socket) Addr() net.Addr {
	return s.pc.LocalAddr()
}

func (s *Socket) LocalAddr() net.Addr {
	return s.pc.LocalAddr()
}

func (s *Socket) Accept() (net.Conn, error) {
	nc, ok := <-s.backlog
	if !ok {
		return nil, errors.New("closed")
	}
	return nc, nil
}

func (s *Socket) Dial(addr string) (net.Conn, error) {
	return s.DialTimeout(addr, 0)
}

func (s *Socket) DialTimeout(addr string, timeout time.Duration) (net.Conn, error) {
	ctx := context.Background()
	if timeout != 0 {
		var cancel context.CancelFunc
		ctx, cancel = context.WithTimeout(ctx, timeout)
		defer cancel()
	}
	return s.DialContext(ctx, "", addr)
}

func (s *Socket) resolveAddr(network, addr string) (net.Addr, error) {
	if network == "" {
		network = s.Addr().Network()
	}
	return resolveAddr(network, addr)
}

func resolveAddr(network, addr string) (net.Addr, error) {
	switch network {
	case "inproc":
		return inproc.ResolveAddr(network, addr)
	default:
		return net.ResolveUDPAddr(network, addr)
	}
}

// Passing an empty network will use the network of the Socket's listener.
func (s *Socket) DialContext(ctx context.Context, network, addr string) (net.Conn, error) {
	c, err := s.NewConn()
	if err != nil {
		return nil, err
	}
	err = c.Connect(ctx, network, addr)
	if err != nil {
		c.Close()
		return nil, err
	}
	return c, nil
}

func (s *Socket) NewConn() (*Conn, error) {
	mu.Lock()
	defer mu.Unlock()
	if s.closed {
		return nil, errors.New("socket closed")
	}
	return s.newConn(C.utp_create_socket(s.ctx)), nil
}

func (s *Socket) pushBacklog(c *Conn) {
	select {
	case s.backlog <- c:
	default:
		c.close()
	}
}

func (s *Socket) ReadFrom(b []byte) (n int, addr net.Addr, err error) {
	p, ok := <-s.nonUtpReads
	if !ok {
		err = errors.New("closed")
		return
	}
	n = copy(b, p.b)
	addr = p.from
	return
}

func (s *Socket) onReadNonUtp(b []byte, from net.Addr) {
	socketNonUtpPacketsReceived.Add(1)
	select {
	case s.nonUtpReads <- packet{append([]byte(nil), b...), from}:
	default:
		// log.Printf("dropped non utp packet: no room in buffer")
		nonUtpPacketsDropped.Add(1)
	}
}

func (s *Socket) SetReadDeadline(t time.Time) error {
	panic("not implemented")
}

func (s *Socket) SetWriteDeadline(t time.Time) error {
	panic("not implemented")
}

func (s *Socket) SetDeadline(t time.Time) error {
	panic("not implemented")
}

func (s *Socket) WriteTo(b []byte, addr net.Addr) (int, error) {
	return s.pc.WriteTo(b, addr)
}

func (s *Socket) ReadBufferLen() int {
	mu.Lock()
	defer mu.Unlock()
	return int(C.utp_context_get_option(s.ctx, C.UTP_RCVBUF))
}

func (s *Socket) WriteBufferLen() int {
	mu.Lock()
	defer mu.Unlock()
	return int(C.utp_context_get_option(s.ctx, C.UTP_SNDBUF))
}

func (s *Socket) SetWriteBufferLen(len int) {
	mu.Lock()
	defer mu.Unlock()
	i := C.utp_context_set_option(s.ctx, C.UTP_SNDBUF, C.int(len))
	if i != 0 {
		panic(i)
	}
}

func (s *Socket) SetOption(opt Option, val int) int {
	mu.Lock()
	defer mu.Unlock()
	return int(C.utp_context_set_option(s.ctx, opt, C.int(val)))
}
<commit_msg>Add missing missinggo import<commit_after>package utp

/*
#include "utp.h"
#include <stdbool.h>

struct utp_process_udp_args {
	const byte *buf;
	size_t len;
	const struct sockaddr *sa;
	socklen_t sal;
};

void process_received_messages(utp_context *ctx, struct utp_process_udp_args *args, size_t argslen)
{
	bool gotUtp = false;
	size_t i;
	for (i = 0; i < argslen; i++) {
		struct utp_process_udp_args *a = &args[i];
		//if (!a->len) continue;
		if (utp_process_udp(ctx, a->buf, a->len, a->sa, a->sal)) {
			gotUtp = true;
		}
	}
	if (gotUtp) {
		utp_issue_deferred_acks(ctx);
		utp_check_timeouts(ctx);
	}
}
*/
import "C"
import (
	"context"
	"errors"
	"net"
	"runtime/pprof"
	"time"

	"github.com/anacrolix/missinggo"
	"github.com/anacrolix/missinggo/inproc"
	"github.com/anacrolix/mmsg"
)

type Socket struct {
	pc            net.PacketConn
	ctx           *C.utp_context
	backlog       chan *Conn
	closed        bool
	conns         map[*C.utp_socket]*Conn
	nonUtpReads   chan packet
	writeDeadline time.Time
	readDeadline  time.Time
}

var (
	_               net.PacketConn = (*Socket)(nil)
	_               net.Listener   = (*Socket)(nil)
	errSocketClosed                = errors.New("Socket closed")
)

type packet struct {
	b    []byte
	from net.Addr
}

func listenPacket(network, addr string) (pc net.PacketConn, err error) {
	if network == "inproc" {
		return inproc.ListenPacket(network, addr)
	}
	return net.ListenPacket(network, addr)
}

func NewSocket(network, addr string) (*Socket, error) {
	pc, err := listenPacket(network, addr)
	if err != nil {
		return nil, err
	}
	mu.Lock()
	defer mu.Unlock()
	ctx := C.utp_init(2)
	if ctx == nil {
		panic(ctx)
	}
	ctx.setCallbacks()
	if utpLogging {
		ctx.setOption(C.UTP_LOG_NORMAL, 1)
		ctx.setOption(C.UTP_LOG_MTU, 1)
		ctx.setOption(C.UTP_LOG_DEBUG, 1)
	}
	s := &Socket{
		pc:          pc,
		ctx:         ctx,
		backlog:     make(chan *Conn, 5),
		conns:       make(map[*C.utp_socket]*Conn),
		nonUtpReads: make(chan packet, 100),
	}
	libContextToSocket[ctx] = s
	go s.timeoutChecker()
	go s.packetReader()
	return s, nil
}

func (s *Socket) onLibSocketDestroyed(ls *C.utp_socket) {
	delete(s.conns, ls)
}

func (s *Socket) newConn(us *C.utp_socket) *Conn {
	c := &Conn{
		s:         s,
		us:        us,
		localAddr: s.pc.LocalAddr(),
	}
	c.cond.L = &mu
	s.conns[us] = c
	c.writeDeadlineTimer = time.AfterFunc(-1, c.cond.Broadcast)
	c.readDeadlineTimer = time.AfterFunc(-1, c.cond.Broadcast)
	return c
}

const maxNumBuffers = 16

func (s *Socket) packetReader() {
	mc := mmsg.NewConn(s.pc)
	// Increasing the messages increases the memory use, but also means we can
	// reduces utp_issue_deferred_acks and syscalls which should improve
	// efficiency. On the flip side, not all OSs implement batched reads.
	ms := make([]mmsg.Message, func() int {
		if mc.Err() == nil {
			return maxNumBuffers
		} else {
			return 1
		}
	}())
	for i := range ms {
		// The IPv4 UDP limit is allegedly about 64 KiB, and this message has
		// been seen on receiving on Windows with just 0x1000: wsarecvfrom: A
		// message sent on a datagram socket was larger than the internal
		// message buffer or some other network limit, or the buffer used to
		// receive a datagram into was smaller than the datagram itself.
		ms[i].Buffers = [][]byte{make([]byte, 0x10000)}
	}
	// Some crap OSs like Windoze will raise errors in Reads that don't
	// actually mean we should stop.
	consecutiveErrors := 0
	for {
		// In C, all the reads are processed and when it threatens to block,
		// we're supposed to call utp_issue_deferred_acks.
		n, err := mc.RecvMsgs(ms)
		if n == 1 {
			singleMsgRecvs.Add(1)
		}
		if n > 1 {
			multiMsgRecvs.Add(1)
		}
		if err != nil {
			mu.Lock()
			closed := s.closed
			mu.Unlock()
			if closed {
				// We don't care.
				return
			}
			// See https://github.com/anacrolix/torrent/issues/83. If we get
			// an endless stream of errors (such as the PacketConn being
			// Closed outside of our control, this work around may need to be
			// reconsidered.
			Logger.Printf("ignoring socket read error: %s", err)
			consecutiveErrors++
			if consecutiveErrors >= 100 {
				Logger.Print("too many consecutive errors, closing socket")
				s.Close()
				return
			}
			continue
		}
		consecutiveErrors = 0
		expMap.Add("successful mmsg receive calls", 1)
		expMap.Add("received messages", int64(n))
		s.processReceivedMessages(ms[:n])
	}
}

func (s *Socket) processReceivedMessages(ms []mmsg.Message) {
	mu.Lock()
	defer mu.Unlock()
	if s.closed {
		return
	}
	if processPacketsInC {
		var args [maxNumBuffers]C.struct_utp_process_udp_args
		for i, m := range ms {
			a := &args[i]
			a.buf = (*C.byte)(&m.Buffers[0][0])
			a.len = C.size_t(m.N)
			a.sa, a.sal = netAddrToLibSockaddr(m.Addr)
		}
		C.process_received_messages(s.ctx, &args[0], C.size_t(len(ms)))
	} else {
		gotUtp := false
		for _, m := range ms {
			gotUtp = s.processReceivedMessage(m.Buffers[0][:m.N], m.Addr) || gotUtp
		}
		if gotUtp {
			s.afterReceivingUtpMessages()
		}
	}
}

func (s *Socket) afterReceivingUtpMessages() {
	pprof.Do(context.Background(), pprof.Labels("go-libutp", "afterReceivingUtpMessages"), func(context.Context) {
		C.utp_issue_deferred_acks(s.ctx)
		// TODO: When is this done in C?
		C.utp_check_timeouts(s.ctx)
	})
}

func (s *Socket) processReceivedMessage(b []byte, addr net.Addr) (utp bool) {
	if s.utpProcessUdp(b, addr) {
		socketUtpPacketsReceived.Add(1)
		return true
	} else {
		s.onReadNonUtp(b, addr)
		return false
	}
}

// Process packet batches entirely from C, reducing CGO overhead. Currently
// requires GODEBUG=cgocheck=0.
const processPacketsInC = false

// Wraps libutp's utp_process_udp, returning relevant information.
func (s *Socket) utpProcessUdp(b []byte, addr net.Addr) (utp bool) {
	sa, sal := netAddrToLibSockaddr(addr)
	if len(b) == 0 {
		// The implementation of utp_process_udp rejects null buffers, and
		// anything smaller than the UTP header size. It's also prone to
		// assert on those, which we don't want to trigger.
		return false
	}
	if missinggo.AddrPort(addr) == 0 {
		return false
	}
	ret := C.utp_process_udp(s.ctx, (*C.byte)(&b[0]), C.size_t(len(b)), sa, sal)
	switch ret {
	case 1:
		return true
	case 0:
		return false
	default:
		panic(ret)
	}
}

func (s *Socket) timeoutChecker() {
	for {
		mu.Lock()
		if s.closed {
			mu.Unlock()
			return
		}
		// C.utp_issue_deferred_acks(s.ctx)
		C.utp_check_timeouts(s.ctx)
		mu.Unlock()
		time.Sleep(500 * time.Millisecond)
	}
}

func (s *Socket) Close() error {
	mu.Lock()
	defer mu.Unlock()
	return s.closeLocked()
}

func (s *Socket) closeLocked() error {
	if s.closed {
		return nil
	}
	// Calling this deletes the pointer. It must not be referred to after
	// this.
	C.utp_destroy(s.ctx)
	s.ctx = nil
	s.pc.Close()
	close(s.backlog)
	close(s.nonUtpReads)
	s.closed = true
	return nil
}

func (s *Socket) Addr() net.Addr {
	return s.pc.LocalAddr()
}

func (s *Socket) LocalAddr() net.Addr {
	return s.pc.LocalAddr()
}

func (s *Socket) Accept() (net.Conn, error) {
	nc, ok := <-s.backlog
	if !ok {
		return nil, errors.New("closed")
	}
	return nc, nil
}

func (s *Socket) Dial(addr string) (net.Conn, error) {
	return s.DialTimeout(addr, 0)
}

func (s *Socket) DialTimeout(addr string, timeout time.Duration) (net.Conn, error) {
	ctx := context.Background()
	if timeout != 0 {
		var cancel context.CancelFunc
		ctx, cancel = context.WithTimeout(ctx, timeout)
		defer cancel()
	}
	return s.DialContext(ctx, "", addr)
}

func (s *Socket) resolveAddr(network, addr string) (net.Addr, error) {
	if network == "" {
		network = s.Addr().Network()
	}
	return resolveAddr(network, addr)
}

func resolveAddr(network, addr string) (net.Addr, error) {
	switch network {
	case "inproc":
		return inproc.ResolveAddr(network, addr)
	default:
		return net.ResolveUDPAddr(network, addr)
	}
}

// Passing an empty network will use the network of the Socket's listener.
func (s *Socket) DialContext(ctx context.Context, network, addr string) (net.Conn, error) {
	c, err := s.NewConn()
	if err != nil {
		return nil, err
	}
	err = c.Connect(ctx, network, addr)
	if err != nil {
		c.Close()
		return nil, err
	}
	return c, nil
}

func (s *Socket) NewConn() (*Conn, error) {
	mu.Lock()
	defer mu.Unlock()
	if s.closed {
		return nil, errors.New("socket closed")
	}
	return s.newConn(C.utp_create_socket(s.ctx)), nil
}

func (s *Socket) pushBacklog(c *Conn) {
	select {
	case s.backlog <- c:
	default:
		c.close()
	}
}

func (s *Socket) ReadFrom(b []byte) (n int, addr net.Addr, err error) {
	p, ok := <-s.nonUtpReads
	if !ok {
		err = errors.New("closed")
		return
	}
	n = copy(b, p.b)
	addr = p.from
	return
}

func (s *Socket) onReadNonUtp(b []byte, from net.Addr) {
	socketNonUtpPacketsReceived.Add(1)
	select {
	case s.nonUtpReads <- packet{append([]byte(nil), b...), from}:
	default:
		// log.Printf("dropped non utp packet: no room in buffer")
		nonUtpPacketsDropped.Add(1)
	}
}

func (s *Socket) SetReadDeadline(t time.Time) error {
	panic("not implemented")
}

func (s *Socket) SetWriteDeadline(t time.Time) error {
	panic("not implemented")
}

func (s *Socket) SetDeadline(t time.Time) error {
	panic("not implemented")
}

func (s *Socket) WriteTo(b []byte, addr net.Addr) (int, error) {
	return s.pc.WriteTo(b, addr)
}

func (s *Socket) ReadBufferLen() int {
	mu.Lock()
	defer mu.Unlock()
	return int(C.utp_context_get_option(s.ctx, C.UTP_RCVBUF))
}

func (s *Socket) WriteBufferLen() int {
	mu.Lock()
	defer mu.Unlock()
	return int(C.utp_context_get_option(s.ctx, C.UTP_SNDBUF))
}

func (s *Socket) SetWriteBufferLen(len int) {
	mu.Lock()
	defer mu.Unlock()
	i := C.utp_context_set_option(s.ctx, C.UTP_SNDBUF, C.int(len))
	if i != 0 {
		panic(i)
	}
}

func (s *Socket) SetOption(opt Option, val int) int {
	mu.Lock()
	defer mu.Unlock()
	return int(C.utp_context_set_option(s.ctx, opt, C.int(val)))
}
<|endoftext|>


<commit_before>package golog

import (
	"fmt"
	"path"
	"runtime"
	"strings"
	"time"
)

// A LocationLogger wraps useful methods for outputting strings by creating
// a LogMessage with the relevant metadata.
// TODO(awreece) Split into multiple interfaces!
type LocationLogger interface {
	LogDepth(level int, closure func() string, depth int)
	Log(int, ...interface{})
	Logf(int, string, ...interface{})
	Logc(int, func() string)
	FailNow()
	SetMinLogLevel(int)
}

type locationLoggerImpl struct {
	Logger
	// TODO(awreece) comment this
	// Skip 0 refers to the function calling getLocation.
	getLocation func(skip int) *LogLocation
}

// Return a nil LogLocation.
func NoLocation(skip int) *LogLocation { return nil }

// Walks up the stack skip frames and returns the LogLocation for that frame.
// TODO(awreece) Provide a arg to select which fields to produce?
func FullLocation(skip int) *LogLocation {
	pc, file, line, ok := runtime.Caller(skip + 1)
	if !ok {
		return nil
	} else {
		// TODO(awreece) Make sure this is compiler agnostic.
		funcParts := strings.SplitN(runtime.FuncForPC(pc).Name(), ".", 2)
		return &LogLocation{
			Package:  funcParts[0],
			File:     path.Base(file),
			Function: funcParts[1],
			Line:     line,
		}
	}

	panic("Flow never reaches here, this mollifies the compiler")
}

// Returns a new LocationLogger wrapping the associated logger, and using
// the provided function to generate LogLocations. The locFunc should walk
// up the stack skip frames and generate the LogLocation for that function
// call. For example:
//	log := NewLocationLogger(NewDefaultLogger(), NoLocation)
func NewLocationLogger(l Logger, locFunc func(int) *LogLocation) LocationLogger {
	return &locationLoggerImpl{l, locFunc}
}

// Returns a LocationLogger wrapping the DefaultLogger. Note - calls to
// SetMinLogLevel will affect all DefaultLoggers.
func NewDefaultLocationLoger() LocationLogger {
	return NewLocationLogger(NewDefaultLogger(), FullLocation)
}

func (l *locationLoggerImpl) makeLogClosure(level int, msg func() string, skip int) func() *LogMessage {
	// Evaluate this early.
	ns := time.Nanoseconds()
	location := l.getLocation(skip + 1)

	return func() *LogMessage {
		return &LogMessage{
			Level:       level,
			Message:     msg(),
			Nanoseconds: ns,
			Location:    location,
		}
	}
}

func (l *locationLoggerImpl) LogDepth(level int, closure func() string, depth int) {
	l.Logger.Log(level, l.makeLogClosure(level, closure, depth+1))
}

func printClosure(msg ...interface{}) func() string {
	return func() string {
		return fmt.Sprint(msg...)
	}
}

func printfClosure(format string, vals ...interface{}) func() string {
	return func() string {
		return fmt.Sprintf(format, vals...)
	}
}

func (l *locationLoggerImpl) Log(level int, msg ...interface{}) {
	l.LogDepth(level, printClosure(msg...), 1)
}

func (l *locationLoggerImpl) Logf(level int, format string, msg ...interface{}) {
	l.LogDepth(level, printfClosure(format, msg...), 1)
}

func (l *locationLoggerImpl) Logc(level int, closure func() string) {
	l.LogDepth(level, closure, 1)
}
<commit_msg>Comment closure code<commit_after>package golog

import (
	"fmt"
	"path"
	"runtime"
	"strings"
	"time"
)

// A LocationLogger wraps useful methods for outputting strings by creating
// a LogMessage with the relevant metadata.
// TODO(awreece) Split into multiple interfaces!
type LocationLogger interface {
	LogDepth(level int, closure func() string, depth int)
	Log(int, ...interface{})
	Logf(int, string, ...interface{})
	Logc(int, func() string)
	FailNow()
	SetMinLogLevel(int)
}

type locationLoggerImpl struct {
	Logger
	// TODO(awreece) comment this
	// Skip 0 refers to the function calling getLocation.
	getLocation func(skip int) *LogLocation
}

// Return a nil LogLocation.
func NoLocation(skip int) *LogLocation { return nil }

// Walks up the stack skip frames and returns the LogLocation for that frame.
// TODO(awreece) Provide a arg to select which fields to produce?
func FullLocation(skip int) *LogLocation {
	pc, file, line, ok := runtime.Caller(skip + 1)
	if !ok {
		return nil
	} else {
		// TODO(awreece) Make sure this is compiler agnostic.
		funcParts := strings.SplitN(runtime.FuncForPC(pc).Name(), ".", 2)
		return &LogLocation{
			Package:  funcParts[0],
			File:     path.Base(file),
			Function: funcParts[1],
			Line:     line,
		}
	}

	panic("Flow never reaches here, this mollifies the compiler")
}

// Returns a new LocationLogger wrapping the associated logger, and using
// the provided function to generate LogLocations. The locFunc should walk
// up the stack skip frames and generate the LogLocation for that function
// call. For example:
//	log := NewLocationLogger(NewDefaultLogger(), NoLocation)
func NewLocationLogger(l Logger, locFunc func(int) *LogLocation) LocationLogger {
	return &locationLoggerImpl{l, locFunc}
}

// Returns a LocationLogger wrapping the DefaultLogger. Note - calls to
// SetMinLogLevel will affect all DefaultLoggers.
func NewDefaultLocationLoger() LocationLogger {
	return NewLocationLogger(NewDefaultLogger(), FullLocation)
}

func (l *locationLoggerImpl) makeLogClosure(level int, msg func() string, skip int) func() *LogMessage {
	// Evaluate this early.
	ns := time.Nanoseconds()
	location := l.getLocation(skip + 1)

	return func() *LogMessage {
		return &LogMessage{
			Level:       level,
			Message:     msg(),
			Nanoseconds: ns,
			Location:    location,
		}
	}
}

func (l *locationLoggerImpl) LogDepth(level int, closure func() string, depth int) {
	l.Logger.Log(level, l.makeLogClosure(level, closure, depth+1))
}

// Returns a closure that formats the message via a call to fmt.Sprint.
func printClosure(msg ...interface{}) func() string {
	return func() string {
		return fmt.Sprint(msg...)
	}
}

// Returns a closure that formats the message via a call to fmt.Sprintf.
func printfClosure(format string, vals ...interface{}) func() string {
	return func() string {
		return fmt.Sprintf(format, vals...)
	}
}

func (l *locationLoggerImpl) Log(level int, msg ...interface{}) {
	l.LogDepth(level, printClosure(msg...), 1)
}

func (l *locationLoggerImpl) Logf(level int, format string, msg ...interface{}) {
	l.LogDepth(level, printfClosure(format, msg...), 1)
}

func (l *locationLoggerImpl) Logc(level int, closure func() string) {
	l.LogDepth(level, closure, 1)
}
<|endoftext|>


<commit_before>package log

import (
	"crypto/rand"
	"encoding/base64"
	"encoding/json"
	"fmt"
	"io"
	"net"
	"net/http"
	"time"

	"github.com/goadesign/goa"

	"context"
)

type middlewareKey int

const (
	// ReqIDKey is the context key used by the goa RequestID middleware to store the request ID value.
	reqIDKey middlewareKey = iota + 1
)

// LogRequest creates a request logger for the goa middleware.
// This goa middleware is aware of the RequestID middleware and identity id
// if registered after it leverages the request and identity ID for logging.
// If verbose is true then the middlware logs the request and response bodies.
func LogRequest(verbose bool) goa.Middleware {
	return func(h goa.Handler) goa.Handler {
		return func(ctx context.Context, rw http.ResponseWriter, req *http.Request) error {
			reqID := ctx.Value(reqIDKey)
			if reqID == nil {
				reqID = shortID()
			}
			ctx = goa.WithLogContext(ctx, "req_id", reqID)

			startedAt := time.Now()
			r := goa.ContextRequest(ctx)

			reqStartedProperties := map[string]interface{}{
				r.Method: r.URL.String(),
				"from":   from(req),
				"ctrl":   goa.ContextController(ctx),
				"action": goa.ContextAction(ctx),
			}

			identityID, err := extractIdentityID(ctx)
			if err == nil {
				reqStartedProperties["identity_id"] = identityID
			}

			Info(ctx, reqStartedProperties, "request started")

			if verbose {
				if len(r.Header) > 0 {
					properties := make(map[string]interface{}, len(r.Header))
					for k, v := range r.Header {
						properties[string(k)] = v
					}
					Info(ctx, properties, "request headers")
				}
				if len(r.Params) > 0 {
					properties := make(map[string]interface{}, len(r.Params))
					for k, v := range r.Params {
						properties[string(k)] = v
					}
					Info(ctx, properties, "request params")
				}
				if r.ContentLength > 0 {
					if mp, ok := r.Payload.(map[string]interface{}); ok {
						properties := make(map[string]interface{}, len(mp))
						for k, v := range mp {
							properties[string(k)] = v
						}
						Info(ctx, properties, "request payload")
					} else {
						// Not the most efficient but this is used for debugging
						js, err := json.Marshal(r.Payload)
						if err != nil {
							js = []byte("<invalid JSON>")
						}
						Info(ctx, map[string]interface{}{"raw": string(js)}, "payload")
					}
				}
			}
			err = h(ctx, rw, req)
			resp := goa.ContextResponse(ctx)

			timeInMilli := time.Since(startedAt).Seconds() * 1e3
			reqCompletedProperties := map[string]interface{}{
				"status": resp.Status,
				"bytes":  resp.Length,
				"time":   fmt.Sprintf("%vms", timeInMilli),
				"ctrl":   goa.ContextController(ctx),
				"action": goa.ContextAction(ctx),
			}
			if code := resp.ErrorCode; code != "" {
				reqCompletedProperties["error"] = code
			}
			if identityID != "" {
				reqCompletedProperties["identity_id"] = identityID
			}
			Info(ctx, reqCompletedProperties, "completed")

			return err
		}
	}
}

// shortID produces a "unique" 6 bytes long string.
// Do not use as a reliable way to get unique IDs, instead use for things like logging.
func shortID() string {
	b := make([]byte, 6)
	io.ReadFull(rand.Reader, b)
	return base64.StdEncoding.EncodeToString(b)
}

// from makes a best effort to compute the request client IP.
func from(req *http.Request) string {
	if f := req.Header.Get("X-Forwarded-For"); f != "" {
		return f
	}
	f := req.RemoteAddr
	ip, _, err := net.SplitHostPort(f)
	if err != nil {
		return f
	}
	return ip
}
<commit_msg>Update to log duration without unit for plotting (#1560)<commit_after>package log

import (
	"crypto/rand"
	"encoding/base64"
	"encoding/json"
	"io"
	"net"
	"net/http"
	"time"

	"github.com/goadesign/goa"

	"context"
)

type middlewareKey int

const (
	// ReqIDKey is the context key used by the goa RequestID middleware to store the request ID value.
	reqIDKey middlewareKey = iota + 1
)

// LogRequest creates a request logger for the goa middleware.
// This goa middleware is aware of the RequestID middleware and identity id
// if registered after it leverages the request and identity ID for logging.
// If verbose is true then the middlware logs the request and response bodies.
func LogRequest(verbose bool) goa.Middleware {
	return func(h goa.Handler) goa.Handler {
		return func(ctx context.Context, rw http.ResponseWriter, req *http.Request) error {
			reqID := ctx.Value(reqIDKey)
			if reqID == nil {
				reqID = shortID()
			}
			ctx = goa.WithLogContext(ctx, "req_id", reqID)

			startedAt := time.Now()
			r := goa.ContextRequest(ctx)

			reqStartedProperties := map[string]interface{}{
				r.Method: r.URL.String(),
				"from":   from(req),
				"ctrl":   goa.ContextController(ctx),
				"action": goa.ContextAction(ctx),
			}

			identityID, err := extractIdentityID(ctx)
			if err == nil {
				reqStartedProperties["identity_id"] = identityID
			}

			Info(ctx, reqStartedProperties, "request started")

			if verbose {
				if len(r.Header) > 0 {
					properties := make(map[string]interface{}, len(r.Header))
					for k, v := range r.Header {
						properties[string(k)] = v
					}
					Info(ctx, properties, "request headers")
				}
				if len(r.Params) > 0 {
					properties := make(map[string]interface{}, len(r.Params))
					for k, v := range r.Params {
						properties[string(k)] = v
					}
					Info(ctx, properties, "request params")
				}
				if r.ContentLength > 0 {
					if mp, ok := r.Payload.(map[string]interface{}); ok {
						properties := make(map[string]interface{}, len(mp))
						for k, v := range mp {
							properties[string(k)] = v
						}
						Info(ctx, properties, "request payload")
					} else {
						// Not the most efficient but this is used for debugging
						js, err := json.Marshal(r.Payload)
						if err != nil {
							js = []byte("<invalid JSON>")
						}
						Info(ctx, map[string]interface{}{"raw": string(js)}, "payload")
					}
				}
			}
			err = h(ctx, rw, req)
			resp := goa.ContextResponse(ctx)

			timeInMilli := time.Since(startedAt).Seconds() * 1e3
			reqCompletedProperties := map[string]interface{}{
				"status":        resp.Status,
				"bytes":         resp.Length,
				"duration":      timeInMilli,
				"duration_unit": "ms",
				"ctrl":          goa.ContextController(ctx),
				"action":        goa.ContextAction(ctx),
			}
			if code := resp.ErrorCode; code != "" {
				reqCompletedProperties["error"] = code
			}
			if identityID != "" {
				reqCompletedProperties["identity_id"] = identityID
			}
			Info(ctx, reqCompletedProperties, "completed")

			return err
		}
	}
}

// shortID produces a "unique" 6 bytes long string.
// Do not use as a reliable way to get unique IDs, instead use for things like logging.
func shortID() string {
	b := make([]byte, 6)
	io.ReadFull(rand.Reader, b)
	return base64.StdEncoding.EncodeToString(b)
}

// from makes a best effort to compute the request client IP.
func from(req *http.Request) string {
	if f := req.Header.Get("X-Forwarded-For"); f != "" {
		return f
	}
	f := req.RemoteAddr
	ip, _, err := net.SplitHostPort(f)
	if err != nil {
		return f
	}
	return ip
}
<|endoftext|>


<commit_before>package logging

import (
	"fmt"
	"strings"

	log "github.com/Sirupsen/logrus"
)

// Formatter is the struct used in the logging package.
type Formatter struct {
}

// Format builds the log desired log format.
func (c *Formatter) Format(entry *log.Entry) ([]byte, error) {
	return []byte(fmt.Sprintf("[%s] %s\n", strings.ToUpper(entry.Level.String()), entry.Message)), nil
}

func init() {
	log.SetFormatter(&Formatter{})
}

// SetLevel sets the log level.
// Accepted levels are panic, fatal, error, warn, info and debug.
func SetLevel(level string) {
	lvl, err := log.ParseLevel(level)
	if err != nil {
		Fatal(fmt.Sprintf(`not a valid level: "%s"`, level))
	}
	log.SetLevel(lvl)
}

// Debug logs a message with severity DEBUG.
func Debug(format string, v ...interface{}) {
	log.Debug(fmt.Sprintf(format, v...))
}

// Info logs a message with severity INFO.
func Info(format string, v ...interface{}) {
	log.Info(fmt.Sprintf(format, v...))
}

// Warning logs a message with severity WARNING.
func Warning(format string, v ...interface{}) {
	log.Warning(fmt.Sprintf(format, v...))
}

// Error logs a message with severity ERROR.
func Error(format string, v ...interface{}) {
	log.Error(fmt.Sprintf(format, v...))
}

// Fatal logs a message with severity ERROR which is then followed by a call
// to os.Exit().
func Fatal(format string, v ...interface{}) {
	log.Fatal(fmt.Sprintf(format, v...))
}
<commit_msg>added timestamp to logs<commit_after>package logging

import (
	"fmt"
	"strings"

	log "github.com/Sirupsen/logrus"
)

// Formatter is the struct used in the logging package.
type Formatter struct {
}

// Format builds the log desired log format.
func (c *Formatter) Format(entry *log.Entry) ([]byte, error) {
	return []byte(fmt.Sprintf("%s [%s] %s\n", entry.Time.Format("2006/01/02 15:04:05 MST"), strings.ToUpper(entry.Level.String()), entry.Message)), nil
}

func init() {
	log.SetFormatter(&Formatter{})
}

// SetLevel sets the log level.
// Accepted levels are panic, fatal, error, warn, info and debug.
func SetLevel(level string) {
	lvl, err := log.ParseLevel(level)
	if err != nil {
		Fatal(fmt.Sprintf(`not a valid level: "%s"`, level))
	}
	log.SetLevel(lvl)
}

// Debug logs a message with severity DEBUG.
func Debug(format string, v ...interface{}) {
	log.Debug(fmt.Sprintf(format, v...))
}

// Info logs a message with severity INFO.
func Info(format string, v ...interface{}) {
	log.Info(fmt.Sprintf(format, v...))
}

// Warning logs a message with severity WARNING.
func Warning(format string, v ...interface{}) {
	log.Warning(fmt.Sprintf(format, v...))
}

// Error logs a message with severity ERROR.
func Error(format string, v ...interface{}) {
	log.Error(fmt.Sprintf(format, v...))
}

// Fatal logs a message with severity ERROR which is then followed by a call
// to os.Exit().
func Fatal(format string, v ...interface{}) {
	log.Fatal(fmt.Sprintf(format, v...))
}
<|endoftext|>


<commit_before>package spec

import "github.com/opencontainers/runtime-spec/specs-go"

var (
	PrivilegedContainerNamespaces = []specs.LinuxNamespace{
		{Type: specs.PIDNamespace},
		{Type: specs.IPCNamespace},
		{Type: specs.UTSNamespace},
		{Type: specs.MountNamespace},
		{Type: specs.NetworkNamespace},
	}

	UnprivilegedContainerNamespaces = append(PrivilegedContainerNamespaces,
		specs.LinuxNamespace{Type: specs.UserNamespace},
	)
)

func OciNamespaces(privileged bool) []specs.LinuxNamespace {
	if !privileged {
		return UnprivilegedContainerNamespaces
	}

	return PrivilegedContainerNamespaces
}
<commit_msg>use cgroup_namespaces for non-privileged containers<commit_after>package spec

import "github.com/opencontainers/runtime-spec/specs-go"

var (
	PrivilegedContainerNamespaces = []specs.LinuxNamespace{
		{Type: specs.PIDNamespace},
		{Type: specs.IPCNamespace},
		{Type: specs.UTSNamespace},
		{Type: specs.MountNamespace},
		{Type: specs.NetworkNamespace},
	}

	UnprivilegedContainerNamespaces = append(PrivilegedContainerNamespaces,
		specs.LinuxNamespace{Type: specs.UserNamespace},
		specs.LinuxNamespace{Type: specs.CgroupNamespace},
	)
)

func OciNamespaces(privileged bool) []specs.LinuxNamespace {
	if !privileged {
		return UnprivilegedContainerNamespaces
	}

	return PrivilegedContainerNamespaces
}
<|endoftext|>


<commit_before>package gosql

const (
	LimitKeyLimit string = "%l"
	LimitKeySkip         = "%s"
	LimitKeyPage         = "%p"
)

func IsLimitKey(str string) bool {
	switch str {
	case LimitKeyLimit, LimitKeySkip, LimitKeyPage:
		return true
	}
	return false
}

type ILimit interface {
	IsLimited() bool
}

type LimitRoot struct {
	Values []ILimit
}

func (l *LimitRoot) IsLimited() bool {
	return false
}

type LimitValue struct {
	Key   string
	Value int
}

func (l *LimitValue) IsLimited() bool {
	switch l.Key {
	case LimitKeyLimit:
		return l.Value > 0
	case LimitKeySkip:
		return true
	case LimitKeyPage:
		return l.Value >= 0
	}
	return false
}

type IRuleLimit interface {
	SetDefaultLimit(int) IRuleLimit
	SetMaxLimit(int) IRuleLimit
	Limit(int) int
}

type RuleLimit struct {
	defaultLimit int
	maxLimit     int
}

func (l *RuleLimit) SetDefaultLimit(lmt int) IRuleLimit {
	if lmt >= 0 {
		if lmt > l.maxLimit {
			l.SetMaxLimit(lmt)
		}
		l.defaultLimit = lmt
	}
	return l
}

func (l *RuleLimit) SetMaxLimit(lmt int) IRuleLimit {
	if lmt >= 0 {
		if lmt < l.defaultLimit {
			l.SetDefaultLimit(lmt)
		}
		l.maxLimit = lmt
	}
	return l
}

func (l *RuleLimit) Limit(lmt int) int {
	if lmt >= 1 {
		if lmt > l.maxLimit {
			return l.maxLimit
		}
		return lmt
	}
	return l.defaultLimit
}
<commit_msg>fix: limit<commit_after>package gosql

const (
	LimitKeyLimit string = "%l"
	LimitKeySkip         = "%s"
	LimitKeyPage         = "%p"
)

func IsLimitKey(str string) bool {
	switch str {
	case LimitKeyLimit, LimitKeySkip, LimitKeyPage:
		return true
	}
	return false
}

type ILimit interface {
	IsLimited() bool
}

type LimitRoot struct {
	Values []ILimit
}

func (l *LimitRoot) IsLimited() bool {
	return false
}

type LimitValue struct {
	Key   string
	Value int
}

func (l *LimitValue) IsLimited() bool {
	switch l.Key {
	case LimitKeyLimit:
		return l.Value > 0
	case LimitKeySkip:
		return true
	case LimitKeyPage:
		return l.Value >= 0
	}
	return false
}

type LimitValueSet struct {
	Limit int
	Skip  int
	Page  int
}

func (l *LimitValueSet) IsLimited() bool {
	return l.Limit > 0 && (l.Skip+l.Limit*l.Page) >= 0
}

type IRuleLimit interface {
	SetDefaultLimit(int) IRuleLimit
	SetMaxLimit(int) IRuleLimit
	GetLimit(int) int
}

type RuleLimit struct {
	defaultLimit int
	maxLimit     int
}

func (l *RuleLimit) SetDefaultLimit(lmt int) IRuleLimit {
	if lmt >= 0 {
		if lmt > l.maxLimit {
			l.SetMaxLimit(lmt)
		}
		l.defaultLimit = lmt
	}
	return l
}

func (l *RuleLimit) SetMaxLimit(lmt int) IRuleLimit {
	if lmt >= 0 {
		if lmt < l.defaultLimit {
			l.SetDefaultLimit(lmt)
		}
		l.maxLimit = lmt
	}
	return l
}

func (l *RuleLimit) GetLimit(lmt int) int {
	if lmt >= 1 {
		if lmt > l.maxLimit {
			return l.maxLimit
		}
		return lmt
	}
	return l.defaultLimit
}
<|endoftext|>


<commit_before>package main

import (
	"net/http"
	"time"
)

// Limiter is used to create limiting handlers. All handlers share the created limit
type Limiter struct {
	timeout time.Duration
	max     uint
	channel chan struct{}
}

// LimiterHandler is used to wrap an http.Handler with a request limit
type LimiterHandler struct {
	handler http.Handler
	limiter *Limiter
}

// New creates a new Limit Handler creator.  When max is reached, new requests may
// wait up until timeout. a 503 is returned if the timeout is reachd
func New(timeout time.Duration, max uint) *Limiter {
	l := &Limiter{
		timeout: timeout,
		max:     max,
		channel: make(chan struct{}, max),
	}

	for i := 0; i < max; i++ {
		l.channel <- struct{}{}
	}

	return l
}

// Handler wraps an http.Handler with a limiting handler
func (l *Limiter) Handler(h http.Handler) http.Handler {
	return &LimiterHandler{
		handler: h,
		limiter: l,
	}
}

// ServeHTTP will attempt to "reserve" a slot and wait up to timeout to do so.
// Will return a 503 error.
func (h *LimiterHandler) ServeHTTP(w ResponseWriter, r *Request) {
	select {
	case <-h.limiter.channel:
		defer func(l *Limiter) {
			l.channel <- struct{}{}
		}(h.limiter)
		h.handler(w, r)
	case <-time.After(h.limiter.timeout):
		http.Error(w, "max concurreny", 503)
	}
}
<commit_msg>change package<commit_after>package limit

import (
	"net/http"
	"time"
)

// Limiter is used to create limiting handlers. All handlers share the created limit
type Limiter struct {
	timeout time.Duration
	max     uint
	channel chan struct{}
}

// LimiterHandler is used to wrap an http.Handler with a request limit
type LimiterHandler struct {
	handler http.Handler
	limiter *Limiter
}

// New creates a new Limit Handler creator.  When max is reached, new requests may
// wait up until timeout. a 503 is returned if the timeout is reachd
func New(timeout time.Duration, max uint) *Limiter {
	l := &Limiter{
		timeout: timeout,
		max:     max,
		channel: make(chan struct{}, max),
	}

	for i := 0; i < max; i++ {
		l.channel <- struct{}{}
	}

	return l
}

// Handler wraps an http.Handler with a limiting handler
func (l *Limiter) Handler(h http.Handler) http.Handler {
	return &LimiterHandler{
		handler: h,
		limiter: l,
	}
}

// ServeHTTP will attempt to "reserve" a slot and wait up to timeout to do so.
// Will return a 503 error.
func (h *LimiterHandler) ServeHTTP(w ResponseWriter, r *Request) {
	select {
	case <-h.limiter.channel:
		defer func(l *Limiter) {
			l.channel <- struct{}{}
		}(h.limiter)
		h.handler(w, r)
	case <-time.After(h.limiter.timeout):
		http.Error(w, "max concurreny", 503)
	}
}
<|endoftext|>


<commit_before>// Package memio implements Read, Write, Seek, Close and other io methods for a byte slice.
package memio

import (
	"bytes"
	"io"
)

const (
	seekSet = iota
	seekCurr
	seekEnd
)

// Closed is an error returned when trying to perform an operation after using Close().
type Closed struct{}

func (Closed) Error() string {
	return "operation not permitted when closed"
}

// ReadMem holds a byte slice that can be used for many io interfaces
type ReadMem struct {
	*bytes.Reader
}

// Open uses a byte slice for reading. Implements io.Reader, io.Seeker,
// io.Closer, io.ReaderAt, io.ByteReader and io.WriterTo.
func Open(data []byte) *ReadMem {
	return &ReadMem{bytes.NewReader(data)}
}

func (ReadMem) Close() error {
	return nil
}

// WriteMem holds a pointer to a byte slice and allows numerous io interfaces
// to be used with it.
type WriteMem struct {
	data *[]byte
	pos  int
}

// Create uses a byte slice for writing. Implements io.Writer, io.Seeker,
// io.Closer, io.WriterAt, io.ByteWriter and io.ReaderFrom.
func Create(data *[]byte) *WriteMem {
	return &WriteMem{data, 0}
}

// Write is an implementation of the io.Writer interface
func (b *WriteMem) Write(p []byte) (int, error) {
	if b.data == nil {
		return 0, &Closed{}
	}
	b.setSize(b.pos + len(p))
	n := copy((*b.data)[b.pos:], p)
	b.pos += n
	return n, nil
}

// WriteAt is an implementation of the io.WriterAt interface
func (b *WriteMem) WriteAt(p []byte, off int64) (int, error) {
	if b.data == nil {
		return 0, &Closed{}
	}
	b.setSize(int(off) + len(p))
	return copy((*b.data)[off:], p), nil
}

// WriteByte is an implementation of the io.WriteByte interface
func (b *WriteMem) WriteByte(c byte) error {
	if b.data == nil {
		return &Closed{}
	}
	b.setSize(b.pos + 1)
	(*b.data)[b.pos] = c
	b.pos++
	return nil
}

// ReadFrom is an implamentation of the io.ReaderFrom interface
func (b *WriteMem) ReadFrom(f io.Reader) (int64, error) {
	if b.data == nil {
		return 0, &Closed{}
	}
	var (
		c   int64
		n   int
		err error
	)
	buf := make([]byte, 1024)
	for {
		n, err = f.Read(buf)
		if n > 0 {
			c += int64(n)
			b.setSize(b.pos + n)
			copy((*b.data)[b.pos:], buf[:n])
			b.pos += n
		}
		if err != nil {
			if err == io.EOF {
				err = nil
			}
			break
		}
	}
	return c, err
}

// Seek is an implementation of the io.Seeker interface
func (b *WriteMem) Seek(offset int64, whence int) (int64, error) {
	if b.data == nil {
		return 0, &Closed{}
	}
	switch whence {
	case seekSet:
		b.pos = int(offset)
	case seekCurr:
		b.pos += int(offset)
	case seekEnd:
		b.pos = len(*b.data) - int(offset)
	}
	if b.pos < 0 {
		b.pos = 0
	}
	return int64(b.pos), nil
}

// Close is and implementation of the io.Closer interface
func (b *WriteMem) Close() error {
	b.data = nil
	return nil
}

func (b *WriteMem) setSize(end int) {
	if end > len(*b.data) {
		if end < cap(*b.data) {
			*b.data = (*b.data)[:end]
		} else {
			var newData []byte
			if len(*b.data) < 512 {
				newData = make([]byte, end, end<<1)
			} else {
				newData = make([]byte, end, end+(end>>2))
			}
			copy(newData, *b.data)
			*b.data = newData
		}
	}
}
<commit_msg>Spelling fix and Closed is now returned as a value<commit_after>// Package memio implements Read, Write, Seek, Close and other io methods for a byte slice.
package memio

import (
	"bytes"
	"io"
)

const (
	seekSet = iota
	seekCurr
	seekEnd
)

// Closed is an error returned when trying to perform an operation after using Close().
type Closed struct{}

func (Closed) Error() string {
	return "operation not permitted when closed"
}

// ReadMem holds a byte slice that can be used for many io interfaces
type ReadMem struct {
	*bytes.Reader
}

// Open uses a byte slice for reading. Implements io.Reader, io.Seeker,
// io.Closer, io.ReaderAt, io.ByteReader and io.WriterTo.
func Open(data []byte) *ReadMem {
	return &ReadMem{bytes.NewReader(data)}
}

func (ReadMem) Close() error {
	return nil
}

// WriteMem holds a pointer to a byte slice and allows numerous io interfaces
// to be used with it.
type WriteMem struct {
	data *[]byte
	pos  int
}

// Create uses a byte slice for writing. Implements io.Writer, io.Seeker,
// io.Closer, io.WriterAt, io.ByteWriter and io.ReaderFrom.
func Create(data *[]byte) *WriteMem {
	return &WriteMem{data, 0}
}

// Write is an implementation of the io.Writer interface
func (b *WriteMem) Write(p []byte) (int, error) {
	if b.data == nil {
		return 0, Closed{}
	}
	b.setSize(b.pos + len(p))
	n := copy((*b.data)[b.pos:], p)
	b.pos += n
	return n, nil
}

// WriteAt is an implementation of the io.WriterAt interface
func (b *WriteMem) WriteAt(p []byte, off int64) (int, error) {
	if b.data == nil {
		return 0, Closed{}
	}
	b.setSize(int(off) + len(p))
	return copy((*b.data)[off:], p), nil
}

// WriteByte is an implementation of the io.WriteByte interface
func (b *WriteMem) WriteByte(c byte) error {
	if b.data == nil {
		return Closed{}
	}
	b.setSize(b.pos + 1)
	(*b.data)[b.pos] = c
	b.pos++
	return nil
}

// ReadFrom is an implementation of the io.ReaderFrom interface
func (b *WriteMem) ReadFrom(f io.Reader) (int64, error) {
	if b.data == nil {
		return 0, Closed{}
	}
	var (
		c   int64
		n   int
		err error
	)
	buf := make([]byte, 1024)
	for {
		n, err = f.Read(buf)
		if n > 0 {
			c += int64(n)
			b.setSize(b.pos + n)
			copy((*b.data)[b.pos:], buf[:n])
			b.pos += n
		}
		if err != nil {
			if err == io.EOF {
				err = nil
			}
			break
		}
	}
	return c, err
}

// Seek is an implementation of the io.Seeker interface
func (b *WriteMem) Seek(offset int64, whence int) (int64, error) {
	if b.data == nil {
		return 0, Closed{}
	}
	switch whence {
	case seekSet:
		b.pos = int(offset)
	case seekCurr:
		b.pos += int(offset)
	case seekEnd:
		b.pos = len(*b.data) - int(offset)
	}
	if b.pos < 0 {
		b.pos = 0
	}
	return int64(b.pos), nil
}

// Close is and implementation of the io.Closer interface
func (b *WriteMem) Close() error {
	b.data = nil
	return nil
}

func (b *WriteMem) setSize(end int) {
	if end > len(*b.data) {
		if end < cap(*b.data) {
			*b.data = (*b.data)[:end]
		} else {
			var newData []byte
			if len(*b.data) < 512 {
				newData = make([]byte, end, end<<1)
			} else {
				newData = make([]byte, end, end+(end>>2))
			}
			copy(newData, *b.data)
			*b.data = newData
		}
	}
}
<|endoftext|>


<commit_before>package jira

import (
	"github.com/coryb/oreo"
	logging "gopkg.in/op/go-logging.v1"
)

var log = logging.MustGetLogger("jira")

const VERSION = "1.0.19"

type Jira struct {
	Endpoint string     `json:"endpoint,omitempty" yaml:"endpoint,omitempty"`
	UA       HttpClient `json:"-" yaml:"-"`
}

func NewJira(endpoint string) *Jira {
	return &Jira{
		Endpoint: endpoint,
		UA:       oreo.New(),
	}
}
<commit_msg>version bump<commit_after>package jira

import (
	"github.com/coryb/oreo"
	logging "gopkg.in/op/go-logging.v1"
)

var log = logging.MustGetLogger("jira")

const VERSION = "1.0.20"

type Jira struct {
	Endpoint string     `json:"endpoint,omitempty" yaml:"endpoint,omitempty"`
	UA       HttpClient `json:"-" yaml:"-"`
}

func NewJira(endpoint string) *Jira {
	return &Jira{
		Endpoint: endpoint,
		UA:       oreo.New(),
	}
}
<|endoftext|>


<commit_before>package jirachat

import (
	"encoding/json"
	"io/ioutil"
	"net/http"
)

const jira_img = "https://dujrsrsgsd3nh.cloudfront.net/img/emoticons/jira-1350074257.png"

// This is a json response for a JIRA webhook (more or less) according to
//https://developer.atlassian.com/display/JIRADEV/JIRA+Webhooks+Overview
type JIRAWebevent struct {
	Id           int           `json:"id,omitempty"`
	Timestamp    int           `json:"timestamp,omitempty"`
	Issue        JIRAIssue     `json:"issue"`
	User         JIRAUser      `json:"user"`
	Changelog    JIRAChangelog `json:"changelog"`
	Comment      JIRAComment   `json:"comment"`
	WebhookEvent string        `json:"webhookEvent"`
}

type JIRAIssue struct {
	Expand string         `json:"expand"`
	Id     string         `json:"id"`
	Self   string         `json:"self"`
	Key    string         `json:"key"`
	Fields IssueFieldData `json:"fields"`
}

type JIRAUser struct {
	Self         string            `json:"self"`
	Name         string            `json:"name"`
	EmailAddress string            `json:"emailAddress"`
	AvatarUrls   map[string]string `json:"avatarUrls"`
	DisplayName  string            `json:"displayName"`
	Active       string            `json:"active"`
}

// Some of the ChangeLogItems may through unmarshal errors but they don't seem
// to cause any major issues
type JIRAChangelog struct {
	Items []ChangleLogItems `json:"items,omitempty"`
	Id    int               `json:"id,omitempty"`
}

type ChangleLogItems struct {
	ToString   string `json:"toString"`
	To         string `json:"to"`
	FromString string `json:"fromString"`
	From       string `json:"from"`
	FieldType  string `json:fieldtype"`
	Field      string `json:"field"`
}

type JIRAComment struct {
	Self         string   `json:"self"`
	Id           string   `json:"id"`
	Author       JIRAUser `json:"author"`
	Body         string   `json:"body"`
	UpdateAuthor JIRAUser `json:"updateAuthor"`
	Created      string   `json:"created"`
	Updated      string   `json:"updated"`
}

type IssueFieldData struct {
	Summary     string `json:"summary"`
	Created     string `json:"created"`
	Description string `json:"description"`
	Priority    string `json:"priority"`
	Assignee    string `json:"assignee"`
}

// For the avatars, use getter methods because the names start with numbers
func (j *JIRAUser) SmallAvatar() string {
	return j.AvatarUrls["16x16"]
}
func (j *JIRAUser) LargeAvatar() string {
	return j.AvatarUrls["48x48"]
}

//TODO add JIRAIssue.Fields.labels function(s)

// Parse the request body as a JIRA webhook event
// Returns a new JiraWebEvent object or error
func Parse(r *http.Request) (JIRAWebevent, error) {
	body, err := ioutil.ReadAll(r.Body)
	if err != nil {
		panic(err)
	}

	var event JIRAWebevent

	// This will generate a error unmarshaling some of the data but
	// is is safe to ignore.
	err = json.Unmarshal(body, &event)
	return event, err
}
<commit_msg>json received field ACTIVE is boolean now, not a string like their docs says<commit_after>package jirachat

import (
	"encoding/json"
	"io/ioutil"
	"net/http"
)

const jira_img = "https://dujrsrsgsd3nh.cloudfront.net/img/emoticons/jira-1350074257.png"

// This is a json response for a JIRA webhook (more or less) according to
//https://developer.atlassian.com/display/JIRADEV/JIRA+Webhooks+Overview
type JIRAWebevent struct {
	Id           int           `json:"id,omitempty"`
	Timestamp    int           `json:"timestamp,omitempty"`
	Issue        JIRAIssue     `json:"issue"`
	User         JIRAUser      `json:"user"`
	Changelog    JIRAChangelog `json:"changelog"`
	Comment      JIRAComment   `json:"comment"`
	WebhookEvent string        `json:"webhookEvent"`
}

type JIRAIssue struct {
	Expand string         `json:"expand"`
	Id     string         `json:"id"`
	Self   string         `json:"self"`
	Key    string         `json:"key"`
	Fields IssueFieldData `json:"fields"`
}

type JIRAUser struct {
	Self         string            `json:"self"`
	Name         string            `json:"name"`
	EmailAddress string            `json:"emailAddress"`
	AvatarUrls   map[string]string `json:"avatarUrls"`
	DisplayName  string            `json:"displayName"`
	Active       bool              `json:"active"`
}

// Some of the ChangeLogItems may through unmarshal errors but they don't seem
// to cause any major issues
type JIRAChangelog struct {
	Items []ChangleLogItems `json:"items,omitempty"`
	Id    int               `json:"id,omitempty"`
}

type ChangleLogItems struct {
	ToString   string `json:"toString"`
	To         string `json:"to"`
	FromString string `json:"fromString"`
	From       string `json:"from"`
	FieldType  string `json:fieldtype"`
	Field      string `json:"field"`
}

type JIRAComment struct {
	Self         string   `json:"self"`
	Id           string   `json:"id"`
	Author       JIRAUser `json:"author"`
	Body         string   `json:"body"`
	UpdateAuthor JIRAUser `json:"updateAuthor"`
	Created      string   `json:"created"`
	Updated      string   `json:"updated"`
}

type IssueFieldData struct {
	Summary     string `json:"summary"`
	Created     string `json:"created"`
	Description string `json:"description"`
	Priority    string `json:"priority"`
	Assignee    string `json:"assignee"`
}

// For the avatars, use getter methods because the names start with numbers
func (j *JIRAUser) SmallAvatar() string {
	return j.AvatarUrls["16x16"]
}
func (j *JIRAUser) LargeAvatar() string {
	return j.AvatarUrls["48x48"]
}

//TODO add JIRAIssue.Fields.labels function(s)

// Parse the request body as a JIRA webhook event
// Returns a new JiraWebEvent object or error
func Parse(r *http.Request) (JIRAWebevent, error) {
	body, err := ioutil.ReadAll(r.Body)
	if err != nil {
		panic(err)
	}

	var event JIRAWebevent

	// This will generate a error unmarshaling some of the data but
	// is is safe to ignore.
	err = json.Unmarshal(body, &event)
	return event, err
}
<|endoftext|>


<commit_before>// json.go provides types & functions for json unmarshalling

package types

import (
	"fmt"
	"github.com/pkg/errors"
	"time"
)

// parseDateTime parses a time formatted under iso-date-time as indicated in the Navitia api.
// This is simply parsing a date formatted under the standard ISO 8601.
func parseDateTime(datetime string) (time.Time, error) {
	res, err := time.Parse(DateTimeFormat, datetime)
	if err != nil {
		err = errors.Wrap(err, "parseDateTime: error while parsing datetime")
	}
	return res, err
}

// UnmarshalError is returned when unmarshalling fails
// It implements both error and github.com/pkg/errors's causer
type UnmarshalError struct {
	// JSON Key where failure occured
	Key string

	// Name of the key in package
	Name string

	// Value associated with the key
	Value interface{}

	// Message of the error
	Message string

	// Underlying error
	Underlying error
}

// Cause implements github.com/pkg/error's causer
func (err UnmarshalError) Cause() error {
	return err.Underlying
}

// Error implements error
func (err UnmarshalError) Error() string {
	msg := fmt.Sprintf("Unmarshalling %s (json: \"%s\") with value \"%v\" failed", err.Name, err.Key, err.Value)
	if err.Message != "" {
		msg += ": " + err.Message
	}
	if err.Underlying != nil {
		msg += " [" + err.Cause().Error() + "]"
	}
	return msg
}

// unmarshalErr creates a new UnmarshalError
func unmarshalErr(underlyingErr error, name string, key string, value interface{}, message string) error {
	return UnmarshalError{
		Key:        key,
		Name:       name,
		Value:      value,
		Message:    message,
		Underlying: underlyingErr,
	}
}
<commit_msg>Add proper error handling and upgrade behavior or parseDateTime<commit_after>// json.go provides types & functions for json unmarshalling

package types

import (
	"fmt"
	"github.com/pkg/errors"
	"time"
)

// parseDateTime parses a time formatted under iso-date-time as indicated in the Navitia api.
// This is simply parsing a date formatted under the standard ISO 8601.
// If the given string is empty (i.e ""), then the zero value of time.Time will be returned
func parseDateTime(datetime string) (time.Time, error) {
	// If there's no datetime given, just return the zero value
	if datetime == "" {
		return time.Time{}, nil
	}

	res, err := time.Parse(DateTimeFormat, datetime)
	if err != nil {
		err = errors.Wrap(err, "parseDateTime: error while parsing datetime")
	}
	return res, err
}

// UnmarshalError is returned when unmarshalling fails
// It implements both error and github.com/pkg/errors's causer
type UnmarshalError struct {
	// JSON Key where failure occured
	Key string

	// Name of the key in package
	Name string

	// Value associated with the key
	Value interface{}

	// Message of the error
	Message string

	// Underlying error
	Underlying error
}

// Cause implements github.com/pkg/error's causer
func (err UnmarshalError) Cause() error {
	return err.Underlying
}

// Error implements error
func (err UnmarshalError) Error() string {
	msg := fmt.Sprintf("Unmarshalling %s (json: \"%s\") with value \"%v\" failed", err.Name, err.Key, err.Value)
	if err.Message != "" {
		msg += ": " + err.Message
	}
	if err.Underlying != nil {
		msg += " [" + err.Cause().Error() + "]"
	}
	return msg
}

// unmarshalErr creates a new UnmarshalError
func unmarshalErr(underlyingErr error, name string, key string, value interface{}, message string) error {
	return UnmarshalError{
		Key:        key,
		Name:       name,
		Value:      value,
		Message:    message,
		Underlying: underlyingErr,
	}
}
<|endoftext|>


<commit_before>package config

import (
	"encoding/json"
)

// parse json string
type JSON struct {
	raw []byte
}

func (j *JSON) SetRawString(raw string) {
	j.raw = []byte(raw)
}

func (j *JSON) SetRawBytes(raw []byte) {
	j.raw = raw
}

func (j *JSON) Get(data interface{}) error {
	return json.Unmarshal(j.raw, data)
}
<commit_msg>implement "Set" method of json provider.<commit_after>package config

import (
	"encoding/json"
	"os"
)

// parse json string
type JSON struct {
	raw []byte
}

func (j *JSON) SetRawString(raw string) {
	j.raw = []byte(raw)
}

func (j *JSON) SetRawBytes(raw []byte) {
	j.raw = raw
}

func (j *JSON) Get(data interface{}) error {
	return json.Unmarshal(j.raw, data)
}

func (j *JSON) Set(data interface{}) (int, error) {
	// open file
	fp, fperr := os.OpenFile(filepath, os.O_WRONLY|os.O_TRUNC|os.O_CREATE, os.ModePerm)
	defer fp.Close()
	if fperr != nil {
		return 0, fperr
	}

	// encode
	bytes, err := json.MarshalIndent(&data, "", "    ")
	if err != nil {
		return 0, err
	}
	bytes = append(bytes, '\n')

	// write
	return fp.Write(bytes)
}
<|endoftext|>


<commit_before>// Package jsql provides glue between database/sql and json.
package jsql

import (
	"bytes"
	"database/sql"
	"encoding/json"
	"fmt"
	"io"
	"log"
	"mime"
	"net/http"
	"regexp"

	"github.com/gorilla/mux"
)

const jsonContentType = "application/json;charset=UTF-8"

var reVars = regexp.MustCompile(`\${([^}]+)}`)

// PositionalQueryVars controls wether
// the generated query strings will use '?'
// or $1, $2... syntax.
var PositionalQueryVars = true

// TODO(lvd) less simplistic parsing of query.  worry about quoting etc.
func rewrite(q string) (qq string, varnames []string) {
	idx := reVars.FindAllStringSubmatchIndex(q, -1)
	l := 0
	var pos = map[string]int{}
	var b bytes.Buffer
	for _, v := range idx {
		b.WriteString(q[l:v[0]])
		l = v[1]
		name := q[v[2]:v[3]]
		if PositionalQueryVars {
			if _, ok := pos[name]; !ok {
				varnames = append(varnames, name)
				pos[name] = len(varnames)
			}
			b.WriteString(fmt.Sprintf("$%d", pos[name]))
		} else {
			varnames = append(varnames, name)
			b.WriteString("?")
		}
	}
	b.WriteString(q[l:])

	log.Println(b.String(), varnames)

	return b.String(), varnames
}

// TODO:make Q send records on a channel, and provide json/bson as encoders
// then have the Handler switch returned encoding depending on http headers

// A queryfunc is the type of function generated by Q.
// It executes a query substituting arguments from the provided args map,
// and writes a JSON array of objects to the provided writer.
// It returns the number of array elements written and any error that may have occured.
//
// If w is an http.ResponseWriter (has a Header() http.Header method), then it will set
// the Content-Type header to application/json;charset=UTF-8 before the first write.
//
// If n == 0, nothing, not even the opening bracket, will have been written to w,
// and the header will not have been set, meaning it is not too late to call e.g.
//
//    http.Error(w, err.Error(), http.StatusInternalError)
//
// otherwise the error will have to be tacked on to the already produced output or
// reported out of band.  If any elements have been written the queryfunc will
// always generate a proper closing bracket.
type QueryFunc func(args map[string]interface{}, w io.Writer) (n int, err error)

// Q builds a function that can execute the query on a database given
// a map of parameters, and writes the result as json to a writer.
//
// The query must be of the form 'SELECT foo FROM bar WHERE x = ${varname}'
// that is, any query accepted by the driver that will provide db,
// but with the normal '$1, $2...' parameters replace by ${varname}.
//
// The generated function will extract the corresponding values from the args map
// and supply them to the db.Stmt.Execute method in the correct order.
// The query will be rewritten to use $1, $2 .. etc.
//
// The generated json will be an array of objects, one per row where
// each row object has keys named after the columns in the SQL query.
//
func Q(db *sql.DB, query string) (QueryFunc, error) {
	q, argn := rewrite(query)
	stmt, err := db.Prepare(q)
	if err != nil {
		return nil, err
	}
	return func(args map[string]interface{}, w io.Writer) (n int, err error) {
		var argv []interface{}
		for _, v := range argn {
			argv = append(argv, args[v])
		}
		rows, err := stmt.Query(argv...)
		if err != nil {
			return 0, err
		}
		defer rows.Close()
		retn, err := rows.Columns()
		if err != nil {
			return 0, err
		}

		var (
			retv  = make([]interface{}, len(retn))
			retvv = make([]interface{}, len(retn))
			retm  = make(map[string]interface{})
		)
		for i := range retv {
			retvv[i] = &retv[i]
			retm[retn[i]] = &retv[i]
		}
		for rows.Next() {
			if err := rows.Scan(retvv...); err != nil {
				return n, err
			}
			// convert []byte to strings, because json uuencodes []byte
			for i, v := range retv {
				if vv, ok := v.([]byte); ok {
					retv[i] = string(vv)
				}
			}

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

			if n == 0 {
				if rw, ok := w.(http.ResponseWriter); ok {
					rw.Header().Set("Content-type", jsonContentType)
				}
				w.Write([]byte("[\n"))
				defer w.Write([]byte("\n]"))
			} else {
				w.Write([]byte(",\n"))
			}

			w.Write(b)
			n++
		}

		return n, rows.Err()
	}, nil
}

// Handler is a convenience wrapper around MkHandler
// that will die on error.
func Handler(db *sql.DB, query string) http.Handler {
	h, err := MkHandler(db, query)
	if err != nil {
		log.Panicf("MkHandler(%q): %v", query, err)
	}
	return h
}

// MkHandler produces a http.Handler that takes arguments from
// the request, and runs Q, producing a nice error message if needed.
//
// The arguments are taken from the request's formvalues or any
// input json object, depending on the requests content type, merged with
// the "github.com/gorilla/mux".Vars(r), which take precedence
// in case of name conflicts.
func MkHandler(db *sql.DB, query string) (http.Handler, error) {
	_, names := rewrite(query)

	qf, err := Q(db, query)
	if err != nil {
		return nil, err
	}

	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		args := make(map[string]interface{})

		var jsonargs map[string]interface{}
		if r.Method == "POST" || r.Method == "PUT" {
			ct := r.Header.Get("Content-Type")
			if ct == "" {
				ct = "application/octet-stream"
			}
			ct, _, err = mime.ParseMediaType(ct)
			if ct == "application/json" {
				defer r.Body.Close()
				if err := json.NewDecoder(io.LimitReader(r.Body, 128<<10)).Decode(&jsonargs); err != nil {
					if err != io.EOF { // empty body is allowed
						http.Error(w, fmt.Sprintf("Can't decode json request: %v", err), http.StatusBadRequest)
						return
					}
				}
			}
		}
		muxargs := mux.Vars(r)
		// TODO harden against malicious input
		// for now we just rely on precedence: muxargs trum the others
		// but this still allows arbitrary values to end up in the query parameters
		for _, n := range names {
			if v, ok := muxargs[n]; ok {
				args[n] = v
				continue
			}
			if v := r.FormValue(n); v != "" {
				args[n] = v
				continue
			}
			if v, ok := jsonargs[n]; ok {
				args[n] = v
				continue
			}
		}
		// TBD: what if not all names set? can postgres $n deal with nil?
		n, err := qf(args, w)
		if err != nil {
			if n == 0 {
				http.Error(w, err.Error(), http.StatusInternalServerError)
				return
			}
			log.Print(r.Method, r.URL, ": ", err)
		}
	}), nil
}
<commit_msg>stray log statement<commit_after>// Package jsql provides glue between database/sql and json.
package jsql

import (
	"bytes"
	"database/sql"
	"encoding/json"
	"fmt"
	"io"
	"log"
	"mime"
	"net/http"
	"regexp"

	"github.com/gorilla/mux"
)

const jsonContentType = "application/json;charset=UTF-8"

var reVars = regexp.MustCompile(`\${([^}]+)}`)

// PositionalQueryVars controls wether
// the generated query strings will use '?'
// or $1, $2... syntax.
var PositionalQueryVars = true

// TODO(lvd) less simplistic parsing of query.  worry about quoting etc.
func rewrite(q string) (qq string, varnames []string) {
	idx := reVars.FindAllStringSubmatchIndex(q, -1)
	l := 0
	var pos = map[string]int{}
	var b bytes.Buffer
	for _, v := range idx {
		b.WriteString(q[l:v[0]])
		l = v[1]
		name := q[v[2]:v[3]]
		if PositionalQueryVars {
			if _, ok := pos[name]; !ok {
				varnames = append(varnames, name)
				pos[name] = len(varnames)
			}
			b.WriteString(fmt.Sprintf("$%d", pos[name]))
		} else {
			varnames = append(varnames, name)
			b.WriteString("?")
		}
	}
	b.WriteString(q[l:])
	return b.String(), varnames
}

// TODO:make Q send records on a channel, and provide json/bson as encoders
// then have the Handler switch returned encoding depending on http headers

// A queryfunc is the type of function generated by Q.
// It executes a query substituting arguments from the provided args map,
// and writes a JSON array of objects to the provided writer.
// It returns the number of array elements written and any error that may have occured.
//
// If w is an http.ResponseWriter (has a Header() http.Header method), then it will set
// the Content-Type header to application/json;charset=UTF-8 before the first write.
//
// If n == 0, nothing, not even the opening bracket, will have been written to w,
// and the header will not have been set, meaning it is not too late to call e.g.
//
//    http.Error(w, err.Error(), http.StatusInternalError)
//
// otherwise the error will have to be tacked on to the already produced output or
// reported out of band.  If any elements have been written the queryfunc will
// always generate a proper closing bracket.
type QueryFunc func(args map[string]interface{}, w io.Writer) (n int, err error)

// Q builds a function that can execute the query on a database given
// a map of parameters, and writes the result as json to a writer.
//
// The query must be of the form 'SELECT foo FROM bar WHERE x = ${varname}'
// that is, any query accepted by the driver that will provide db,
// but with the normal '$1, $2...' parameters replace by ${varname}.
//
// The generated function will extract the corresponding values from the args map
// and supply them to the db.Stmt.Execute method in the correct order.
// The query will be rewritten to use $1, $2 .. etc.
//
// The generated json will be an array of objects, one per row where
// each row object has keys named after the columns in the SQL query.
//
func Q(db *sql.DB, query string) (QueryFunc, error) {
	q, argn := rewrite(query)
	stmt, err := db.Prepare(q)
	if err != nil {
		return nil, err
	}
	return func(args map[string]interface{}, w io.Writer) (n int, err error) {
		var argv []interface{}
		for _, v := range argn {
			argv = append(argv, args[v])
		}
		rows, err := stmt.Query(argv...)
		if err != nil {
			return 0, err
		}
		defer rows.Close()
		retn, err := rows.Columns()
		if err != nil {
			return 0, err
		}

		var (
			retv  = make([]interface{}, len(retn))
			retvv = make([]interface{}, len(retn))
			retm  = make(map[string]interface{})
		)
		for i := range retv {
			retvv[i] = &retv[i]
			retm[retn[i]] = &retv[i]
		}
		for rows.Next() {
			if err := rows.Scan(retvv...); err != nil {
				return n, err
			}
			// convert []byte to strings, because json uuencodes []byte
			for i, v := range retv {
				if vv, ok := v.([]byte); ok {
					retv[i] = string(vv)
				}
			}

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

			if n == 0 {
				if rw, ok := w.(http.ResponseWriter); ok {
					rw.Header().Set("Content-type", jsonContentType)
				}
				w.Write([]byte("[\n"))
				defer w.Write([]byte("\n]"))
			} else {
				w.Write([]byte(",\n"))
			}

			w.Write(b)
			n++
		}

		return n, rows.Err()
	}, nil
}

// Handler is a convenience wrapper around MkHandler
// that will die on error.
func Handler(db *sql.DB, query string) http.Handler {
	h, err := MkHandler(db, query)
	if err != nil {
		log.Panicf("MkHandler(%q): %v", query, err)
	}
	return h
}

// MkHandler produces a http.Handler that takes arguments from
// the request, and runs Q, producing a nice error message if needed.
//
// The arguments are taken from the request's formvalues or any
// input json object, depending on the requests content type, merged with
// the "github.com/gorilla/mux".Vars(r), which take precedence
// in case of name conflicts.
func MkHandler(db *sql.DB, query string) (http.Handler, error) {
	_, names := rewrite(query)

	qf, err := Q(db, query)
	if err != nil {
		return nil, err
	}

	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		args := make(map[string]interface{})

		var jsonargs map[string]interface{}
		if r.Method == "POST" || r.Method == "PUT" {
			ct := r.Header.Get("Content-Type")
			if ct == "" {
				ct = "application/octet-stream"
			}
			ct, _, err = mime.ParseMediaType(ct)
			if ct == "application/json" {
				defer r.Body.Close()
				if err := json.NewDecoder(io.LimitReader(r.Body, 128<<10)).Decode(&jsonargs); err != nil {
					if err != io.EOF { // empty body is allowed
						http.Error(w, fmt.Sprintf("Can't decode json request: %v", err), http.StatusBadRequest)
						return
					}
				}
			}
		}
		muxargs := mux.Vars(r)
		// TODO harden against malicious input
		// for now we just rely on precedence: muxargs trum the others
		// but this still allows arbitrary values to end up in the query parameters
		for _, n := range names {
			if v, ok := muxargs[n]; ok {
				args[n] = v
				continue
			}
			if v := r.FormValue(n); v != "" {
				args[n] = v
				continue
			}
			if v, ok := jsonargs[n]; ok {
				args[n] = v
				continue
			}
		}
		// TBD: what if not all names set? can postgres $n deal with nil?
		n, err := qf(args, w)
		if err != nil {
			if n == 0 {
				http.Error(w, err.Error(), http.StatusInternalServerError)
				return
			}
			log.Print(r.Method, r.URL, ": ", err)
		}
	}), nil
}
<|endoftext|>


<commit_before>package main

type Greetor interface {
	Greet() string
}

type Person struct {
	greeting string
}

func NewGreeter(greeting string) Greetor {
	return &Person{greeting: greeting}
}

func (person *Person) Greet() string {
	return person.greeting
}
<commit_msg>typo:  Change Greetor to Greeter<commit_after>package main

type Greeter interface {
	Greet() string
}

type Person struct {
	greeting string
}

func NewGreeter(greeting string) Greeter {
	return &Person{greeting: greeting}
}

func (person *Person) Greet() string {
	return person.greeting
}
<|endoftext|>