<commit_before>package orc

import (
	"compress/flate"
	"encoding/binary"
	"fmt"
	"io"

	"github.com/golang/snappy"
)

// CompressionCodec is an interface that provides methods for creating
// an Encoder or Decoder of the CompressionCodec implementation.
type CompressionCodec interface {
	Encoder(w io.Writer) io.Writer
	Decoder(r io.Reader) io.Reader
}

// CompressionNone is a CompressionCodec that implements no compression.
type CompressionNone struct{}

// Encoder implements the CompressionCodec interface.
func (c CompressionNone) Encoder(w io.Writer) io.Writer {
	return w
}

// Decoder implements the CompressionCodec interface.
func (c CompressionNone) Decoder(r io.Reader) io.Reader {
	return r
}

type CompressionZlib struct {
	level    int
	strategy int
}

// Encoder implements the CompressionCodec interface. This is currently not implemented.
func (c CompressionZlib) Encoder(w io.Writer) io.Writer {
	return w
}

// Decoder implements the CompressionCodec interface.
func (c CompressionZlib) Decoder(r io.Reader) io.Reader {
	return &CompressionZlibDecoder{source: r}
}

// CompressionSnappy implements the CompressionCodec for Zlib compression.
type CompressionZlibDecoder struct {
	source      io.Reader
	decoded     io.Reader
	isOriginal  bool
	chunkLength int
	remaining   int64
}

func (c *CompressionZlibDecoder) readHeader() (int, error) {
	header := make([]byte, 4, 4)
	_, err := c.source.Read(header[:3])
	if err != nil {
		return 0, err
	}
	headerVal := binary.LittleEndian.Uint32(header)
	c.isOriginal = headerVal%1 == 1
	c.chunkLength = int(headerVal / 2)
	if !c.isOriginal {
		c.decoded = flate.NewReader(io.LimitReader(c.source, int64(c.chunkLength)))
	} else {
		c.decoded = io.LimitReader(c.source, int64(c.chunkLength))
	}
	return 0, nil
}

func (c *CompressionZlibDecoder) Read(p []byte) (int, error) {
	if c.decoded == nil {
		return c.readHeader()
	}
	n, err := c.decoded.Read(p)
	if err == io.EOF {
		c.decoded = nil
		return n, nil
	}
	return n, err
}

// CompressionSnappy implements the CompressionCodec for Snappy compression.
type CompressionSnappy struct{}

// Encoder implements the CompressionCodec interface. This is currently not implemented.
func (c CompressionSnappy) Encoder(w io.Writer) io.Writer {
	return w
}

// Decoder implements the CompressionCodec interface.
func (c CompressionSnappy) Decoder(r io.Reader) io.Reader {
	return &CompressionSnappyDecoder{source: r}
}

// CompressionSnappyDecoder implements the decoder for CompressionSnappy.
type CompressionSnappyDecoder struct {
	source      io.Reader
	decoded     io.Reader
	isOriginal  bool
	chunkLength int
	remaining   int64
}

func (c *CompressionSnappyDecoder) readHeader() (int, error) {
	header := make([]byte, 4, 4)
	_, err := c.source.Read(header[:3])
	if err != nil {
		return 0, err
	}
	headerVal := binary.LittleEndian.Uint32(header)
	c.isOriginal = headerVal%1 == 1
	c.chunkLength = int(headerVal / 2)
	fmt.Println(c.isOriginal, c.chunkLength)
	if !c.isOriginal {
		c.decoded = snappy.NewReader(io.LimitReader(c.source, int64(c.chunkLength)))
	} else {
		c.decoded = io.LimitReader(c.source, int64(c.chunkLength))
	}
	return 0, nil
}

func (c *CompressionSnappyDecoder) Read(p []byte) (int, error) {
	if c.decoded == nil {
		return c.readHeader()
	}
	n, err := c.decoded.Read(p)
	if err == io.EOF {
		c.decoded = nil
		return n, nil
	}
	return n, err
}
<commit_msg>compressioncodec: working implementation of snappy decoder<commit_after>package orc

import (
	"bytes"
	"compress/flate"
	"encoding/binary"
	"io"
	"io/ioutil"

	"github.com/golang/snappy"
)

// CompressionCodec is an interface that provides methods for creating
// an Encoder or Decoder of the CompressionCodec implementation.
type CompressionCodec interface {
	Encoder(w io.Writer) io.Writer
	Decoder(r io.Reader) io.Reader
}

// CompressionNone is a CompressionCodec that implements no compression.
type CompressionNone struct{}

// Encoder implements the CompressionCodec interface.
func (c CompressionNone) Encoder(w io.Writer) io.Writer {
	return w
}

// Decoder implements the CompressionCodec interface.
func (c CompressionNone) Decoder(r io.Reader) io.Reader {
	return r
}

type CompressionZlib struct {
	level    int
	strategy int
}

// Encoder implements the CompressionCodec interface. This is currently not implemented.
func (c CompressionZlib) Encoder(w io.Writer) io.Writer {
	return w
}

// Decoder implements the CompressionCodec interface.
func (c CompressionZlib) Decoder(r io.Reader) io.Reader {
	return &CompressionZlibDecoder{source: r}
}

// CompressionSnappy implements the CompressionCodec for Zlib compression.
type CompressionZlibDecoder struct {
	source      io.Reader
	decoded     io.Reader
	isOriginal  bool
	chunkLength int
	remaining   int64
}

func (c *CompressionZlibDecoder) readHeader() (int, error) {
	header := make([]byte, 4, 4)
	_, err := c.source.Read(header[:3])
	if err != nil {
		return 0, err
	}
	headerVal := binary.LittleEndian.Uint32(header)
	c.isOriginal = headerVal%2 == 1
	c.chunkLength = int(headerVal / 2)
	if !c.isOriginal {
		c.decoded = flate.NewReader(io.LimitReader(c.source, int64(c.chunkLength)))
	} else {
		c.decoded = io.LimitReader(c.source, int64(c.chunkLength))
	}
	return 0, nil
}

func (c *CompressionZlibDecoder) Read(p []byte) (int, error) {
	if c.decoded == nil {
		return c.readHeader()
	}
	n, err := c.decoded.Read(p)
	if err == io.EOF {
		c.decoded = nil
		return n, nil
	}
	return n, err
}

// CompressionSnappy implements the CompressionCodec for Snappy compression.
type CompressionSnappy struct{}

// Encoder implements the CompressionCodec interface. This is currently not implemented.
func (c CompressionSnappy) Encoder(w io.Writer) io.Writer {
	return w
}

// Decoder implements the CompressionCodec interface.
func (c CompressionSnappy) Decoder(r io.Reader) io.Reader {
	return &CompressionSnappyDecoder{source: r}
}

// CompressionSnappyDecoder implements the decoder for CompressionSnappy.
type CompressionSnappyDecoder struct {
	source      io.Reader
	decoded     io.Reader
	isOriginal  bool
	chunkLength int
	remaining   int64
}

func (c *CompressionSnappyDecoder) readHeader() (int, error) {
	header := make([]byte, 4, 4)
	_, err := c.source.Read(header[:3])
	if err != nil {
		return 0, err
	}
	headerVal := binary.LittleEndian.Uint32(header)
	c.isOriginal = headerVal%2 == 1
	c.chunkLength = int(headerVal / 2)
	if !c.isOriginal {
		// ORC does not use snappy's framing as implemented in the
		// github.com/golang/snappy Reader implementation. As a result
		// we have to read and decompress the entire chunk.
		// TODO: find reader implementation with optional framing.
		r := io.LimitReader(c.source, int64(c.chunkLength))
		src, err := ioutil.ReadAll(r)
		if err != nil {
			return 0, err
		}
		decodedBytes, err := snappy.Decode(nil, src)
		if err != nil {
			return 0, err
		}
		c.decoded = bytes.NewReader(decodedBytes)
	} else {
		c.decoded = io.LimitReader(c.source, int64(c.chunkLength))
	}
	return 0, nil
}

func (c *CompressionSnappyDecoder) Read(p []byte) (int, error) {
	if c.decoded == nil {
		return c.readHeader()
	}
	n, err := c.decoded.Read(p)
	if err == io.EOF || err == snappy.ErrCorrupt {
		c.decoded = nil
		return n, nil
	}
	return n, err
}
<|endoftext|>


<commit_before>package goutils

import (
	"math"
	"runtime"
)

type concurrencyLimit struct {
	lock chan (bool)
	size int
}

func NewConcurrencyLimit(limit int) concurrencyLimit {
	ob := concurrencyLimit{}
	ob.lock = make(chan bool, limit)
	ob.size = limit
	return ob
}

func NewConcurrencyLimitCPU() concurrencyLimit {
	return NewConcurrencyLimit(runtime.NumCPU())
}

func NewConcurrencyLimitCPUFactore(f float64) concurrencyLimit {
	t := float64(runtime.NumCPU()) * f
	t2 := math.Ceil(t)
	return NewConcurrencyLimit(int(t2))
}

func NewConcurrencyLimitOne() concurrencyLimit {
	return NewConcurrencyLimit(1)
}

func (l *concurrencyLimit) Use() {
	l.lock <- true
}

func (l *concurrencyLimit) Free() {
	<-l.lock
}

func (l *concurrencyLimit) Len() int {
	return len(l.lock)
}

func (l *concurrencyLimit) Size() int {
	return l.size
}

// usage: defer x.Limit()()
//                     ^ ^ double ()
func (l *concurrencyLimit) Limit() func() {
	l.Use()
	return func() {
		l.Free()
	}
}
<commit_msg>rename concurrencyLimit to ConcurrencyLimit<commit_after>package goutils

import (
	"math"
	"runtime"
)

type ConcurrencyLimit struct {
	lock chan (bool)
	size int
}

func NewConcurrencyLimit(limit int) ConcurrencyLimit {
	ob := ConcurrencyLimit{}
	ob.lock = make(chan bool, limit)
	ob.size = limit
	return ob
}

func NewConcurrencyLimitCPU() ConcurrencyLimit {
	return NewConcurrencyLimit(runtime.NumCPU())
}

func NewConcurrencyLimitCPUFactore(f float64) ConcurrencyLimit {
	t := float64(runtime.NumCPU()) * f
	t2 := math.Ceil(t)
	return NewConcurrencyLimit(int(t2))
}

func NewConcurrencyLimitOne() ConcurrencyLimit {
	return NewConcurrencyLimit(1)
}

func (l *ConcurrencyLimit) Use() {
	l.lock <- true
}

func (l *ConcurrencyLimit) Free() {
	<-l.lock
}

func (l *ConcurrencyLimit) Len() int {
	return len(l.lock)
}

func (l *ConcurrencyLimit) Size() int {
	return l.size
}

// usage: defer x.Limit()()
//                     ^ ^ double ()
func (l *ConcurrencyLimit) Limit() func() {
	l.Use()
	return func() {
		l.Free()
	}
}
<|endoftext|>


<commit_before>package app

import (
	"fmt"
	"net/url"
)

// Transformer is a function which receives a Handler and
// returns another handler, usually with some functionality
// added (e.g. requiring a signed in user, or adding a cache layer).
type Transformer func(Handler) Handler

// SignedIn returns a new Handler which requires a signed in
// user to be executed. If there's no signed in user, it returns
// a redirect to the handler named "sign-in", indicating the
// previous url in the "from" parameter. If there's no handler
// named "sign-in", it panics. It also adds "Cookie" to the Vary
// header, and "private" to the Cache-Control header.
func SignedIn(handler Handler) Handler {
	return func(ctx *Context) {
		h := ctx.Header()
		h.Add("Vary", "Cookie")
		h.Add("Cache-Control", "private")
		if ctx.User() == nil {
			signIn := ctx.MustReverse("sign-in")
			u, err := url.Parse(signIn)
			if err != nil {
				panic(err)
			}
			from := ctx.URL().String()
			u.RawQuery += fmt.Sprintf("from=%s", url.QueryEscape(from))
			ctx.Redirect(u.String(), false)
			return
		}
		handler(ctx)
	}
}

// Anonymous returns a new handler which redirects signed in users
// to the previous page (or the root page if there's no referrer).
func Anonymous(handler Handler) Handler {
	return func(ctx *Context) {
		h := ctx.Header()
		h.Add("Vary", "Cookie")
		h.Add("Cache-Control", "private, must-revalidate")
		if ctx.User() != nil {
			ctx.RedirectBack()
			return
		}
		handler(ctx)
	}
}

// Headers returns a new Handler which adds the given headers
// to every response.
func Headers(handler Handler, headers Header) Handler {
	return func(ctx *Context) {
		h := ctx.Header()
		for k, v := range headers {
			for _, val := range v {
				h.Add(k, val)
			}
		}
		handler(ctx)
	}
}

// Vary returns a new Handler which adds the given
// values to the Vary header.
func Vary(handler Handler, values []string) Handler {
	return Headers(handler, Header{"Vary": values})
}

// Private returns a new Handler which adds the
// headers Vary: Cookie and Cache-Control: private.
func Private(handler Handler) Handler {
	return Headers(handler, Header{
		"Vary":          {"Cookie"},
		"Cache-Control": {"private"},
	})
}
<commit_msg>Use var rather than hardcoding from parameter name<commit_after>package app

import (
	"fmt"
	"net/url"
)

// Transformer is a function which receives a Handler and
// returns another handler, usually with some functionality
// added (e.g. requiring a signed in user, or adding a cache layer).
type Transformer func(Handler) Handler

// SignedIn returns a new Handler which requires a signed in
// user to be executed. If there's no signed in user, it returns
// a redirect to the handler named "sign-in", indicating the
// previous url in the "from" parameter. If there's no handler
// named "sign-in", it panics. It also adds "Cookie" to the Vary
// header, and "private" to the Cache-Control header.
func SignedIn(handler Handler) Handler {
	return func(ctx *Context) {
		h := ctx.Header()
		h.Add("Vary", "Cookie")
		h.Add("Cache-Control", "private")
		if ctx.User() == nil {
			signIn := ctx.MustReverse("sign-in")
			u, err := url.Parse(signIn)
			if err != nil {
				panic(err)
			}
			from := ctx.URL().String()
			u.RawQuery += fmt.Sprintf("%s=%s", SignInFromParameterName, url.QueryEscape(from))
			ctx.Redirect(u.String(), false)
			return
		}
		handler(ctx)
	}
}

// Anonymous returns a new handler which redirects signed in users
// to the previous page (or the root page if there's no referrer).
func Anonymous(handler Handler) Handler {
	return func(ctx *Context) {
		h := ctx.Header()
		h.Add("Vary", "Cookie")
		h.Add("Cache-Control", "private, must-revalidate")
		if ctx.User() != nil {
			ctx.RedirectBack()
			return
		}
		handler(ctx)
	}
}

// Headers returns a new Handler which adds the given headers
// to every response.
func Headers(handler Handler, headers Header) Handler {
	return func(ctx *Context) {
		h := ctx.Header()
		for k, v := range headers {
			for _, val := range v {
				h.Add(k, val)
			}
		}
		handler(ctx)
	}
}

// Vary returns a new Handler which adds the given
// values to the Vary header.
func Vary(handler Handler, values []string) Handler {
	return Headers(handler, Header{"Vary": values})
}

// Private returns a new Handler which adds the
// headers Vary: Cookie and Cache-Control: private.
func Private(handler Handler) Handler {
	return Headers(handler, Header{
		"Vary":          {"Cookie"},
		"Cache-Control": {"private"},
	})
}
<|endoftext|>


<commit_before>package nfs

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

type NFSClient struct {
	Path string
}

type FileNotExistError string

func (e FileNotExistError) Type() string { return "FileNotExistError" }

func (e FileNotExistError) Normal() bool { return true }

func (e FileNotExistError) Error() string { return "no such file or directory:" + string(e) }

func (this *NFSClient) Get() ([]byte, error) {
	resp, err := http.Get(this.Path)
	if err != nil {
		// handle error
		return nil, err
	}
	defer resp.Body.Close()
	if resp.StatusCode == 404 {
		return nil, FileNotExistError(this.Path)
	}
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return nil, err
	} else {
		return body, nil
	}
}
<commit_msg>fix bug: nfs read<commit_after>package nfs

import (
	"io/ioutil"
	"net/http"
	"strings"
	"strconv"
)

type NFSClient struct {
	Path string
}

type FileNotExistError string

func (e FileNotExistError) Type() string { return "FileNotExistError" }

func (e FileNotExistError) Normal() bool { return true }

func (e FileNotExistError) Error() string { return "no such file or directory:" + string(e) }

type HttpStatusError struct {
	path       string
	statusCode int
}

func (e *HttpStatusError) Type() string { return "HttpStatusError" }

func (e *HttpStatusError) Normal() bool { return true }

func (e *HttpStatusError) Error() string {
	return "http status error: " + strconv.Itoa(e.statusCode) + ", request path: " + string(e.path)
}

func (this *NFSClient) Get() (b []byte, e error) {
	if strings.Contains(this.Path, "http://") {
		b, e = this.httpGet(this.Path)
	} else {
		b, e = this.localGet(this.Path)
	}
	return
}

func (this *NFSClient) httpGet(path string) ([]byte, error) {
	resp, err := http.Get(path)
	if err != nil {
		// handle error
		return nil, err
	}
	defer resp.Body.Close()
	if resp.StatusCode == 404 {
		return nil, FileNotExistError(this.Path)
	}
	if resp.StatusCode != 200 {
		return nil, &HttpStatusError{path, resp.StatusCode}
	}
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return nil, err
	} else {
		return body, nil
	}
}

func (this *NFSClient) localGet(path string) ([]byte, error) {
	buff, err := ioutil.ReadFile(path)
	if err != nil {
		if strings.Contains(err.Error(), "no such file or directory") {
			return nil, FileNotExistError(path)
		} else {
			return nil, err
		}
	}
	return buff, nil
}
<|endoftext|>


<commit_before>/*
 *
 * Copyright 2016, Google Inc.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *
 *     * Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above
 * copyright notice, this list of conditions and the following disclaimer
 * in the documentation and/or other materials provided with the
 * distribution.
 *     * Neither the name of Google Inc. nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 */

package main

import (
	"math"
	"runtime"
	"sync"
	"time"

	"golang.org/x/net/context"
	"google.golang.org/grpc"
	"google.golang.org/grpc/benchmark"
	testpb "google.golang.org/grpc/benchmark/grpc_testing"
	"google.golang.org/grpc/benchmark/stats"
	"google.golang.org/grpc/codes"
	"google.golang.org/grpc/credentials"
	"google.golang.org/grpc/grpclog"
)

var (
	caFile = "benchmark/server/testdata/ca.pem"
)

type lockingHistogram struct {
	mu        sync.Mutex
	histogram *stats.Histogram
}

type benchmarkClient struct {
	closeConns        func()
	stop              chan bool
	lastResetTime     time.Time
	histogramOptions  stats.HistogramOptions
	lockingHistograms []lockingHistogram
}

func printClientConfig(config *testpb.ClientConfig) {
	// Some config options are ignored:
	// - client type:
	//     will always create sync client
	// - async client threads.
	// - core list
	grpclog.Printf(" * client type: %v (ignored, always creates sync client)", config.ClientType)
	grpclog.Printf(" * async client threads: %v (ignored)", config.AsyncClientThreads)
	grpclog.Printf(" * core list: %v (ignored)", config.CoreList)

	grpclog.Printf(" - security params: %v", config.SecurityParams)
	grpclog.Printf(" - core limit: %v", config.CoreLimit)
	grpclog.Printf(" - payload config: %v", config.PayloadConfig)
	grpclog.Printf(" - rpcs per chann: %v", config.OutstandingRpcsPerChannel)
	grpclog.Printf(" - channel number: %v", config.ClientChannels)
	grpclog.Printf(" - load params: %v", config.LoadParams)
	grpclog.Printf(" - rpc type: %v", config.RpcType)
	grpclog.Printf(" - histogram params: %v", config.HistogramParams)
	grpclog.Printf(" - server targets: %v", config.ServerTargets)
}

func setupClientEnv(config *testpb.ClientConfig) {
	// Use one cpu core by default.
	// TODO: Revisit this for the optimal default setup.
	if config.CoreLimit > 1 {
		runtime.GOMAXPROCS(int(config.CoreLimit))
	} else {
		runtime.GOMAXPROCS(1)
	}
}

// createConns creates connections according to given config.
// It returns the connections and corresponding function to close them.
// It returns non-nil error if there is anything wrong.
func createConns(config *testpb.ClientConfig) ([]*grpc.ClientConn, func(), error) {
	var opts []grpc.DialOption

	// Sanity check for client type.
	switch config.ClientType {
	case testpb.ClientType_SYNC_CLIENT:
	case testpb.ClientType_ASYNC_CLIENT:
	default:
		return nil, nil, grpc.Errorf(codes.InvalidArgument, "unknow client type: %v", config.ClientType)
	}

	// Check and set security options.
	if config.SecurityParams != nil {
		creds, err := credentials.NewClientTLSFromFile(abs(caFile), config.SecurityParams.ServerHostOverride)
		if err != nil {
			return nil, nil, grpc.Errorf(codes.InvalidArgument, "failed to create TLS credentials %v", err)
		}
		opts = append(opts, grpc.WithTransportCredentials(creds))
	} else {
		opts = append(opts, grpc.WithInsecure())
	}

	// Use byteBufCodec if it is required.
	if config.PayloadConfig != nil {
		switch config.PayloadConfig.Payload.(type) {
		case *testpb.PayloadConfig_BytebufParams:
			opts = append(opts, grpc.WithCodec(byteBufCodec{}))
		case *testpb.PayloadConfig_SimpleParams:
		default:
			return nil, nil, grpc.Errorf(codes.InvalidArgument, "unknow payload config: %v", config.PayloadConfig)
		}
	}

	// Create connections.
	connCount := int(config.ClientChannels)
	conns := make([]*grpc.ClientConn, connCount)
	for connIndex := 0; connIndex < connCount; connIndex++ {
		conns[connIndex] = benchmark.NewClientConn(config.ServerTargets[connIndex%len(config.ServerTargets)], opts...)
	}

	return conns, func() {
		for _, conn := range conns {
			conn.Close()
		}
	}, nil
}

func performRPCs(config *testpb.ClientConfig, conns []*grpc.ClientConn, bc *benchmarkClient) error {
	// Read payload size and type from config.
	var (
		payloadReqSize, payloadRespSize int
		payloadType                     string
	)
	if config.PayloadConfig != nil {
		switch c := config.PayloadConfig.Payload.(type) {
		case *testpb.PayloadConfig_BytebufParams:
			payloadReqSize = int(c.BytebufParams.ReqSize)
			payloadRespSize = int(c.BytebufParams.RespSize)
			payloadType = "bytebuf"
		case *testpb.PayloadConfig_SimpleParams:
			payloadReqSize = int(c.SimpleParams.ReqSize)
			payloadRespSize = int(c.SimpleParams.RespSize)
			payloadType = "protobuf"
		default:
			return grpc.Errorf(codes.InvalidArgument, "unknow payload config: %v", config.PayloadConfig)
		}
	}

	// TODO add open loop distribution.
	switch config.LoadParams.Load.(type) {
	case *testpb.LoadParams_ClosedLoop:
	case *testpb.LoadParams_Poisson:
		return grpc.Errorf(codes.Unimplemented, "unsupported load params: %v", config.LoadParams)
	default:
		return grpc.Errorf(codes.InvalidArgument, "unknown load params: %v", config.LoadParams)
	}

	rpcCountPerConn := int(config.OutstandingRpcsPerChannel)

	switch config.RpcType {
	case testpb.RpcType_UNARY:
		bc.doCloseLoopUnary(conns, rpcCountPerConn, payloadReqSize, payloadRespSize)
		// TODO open loop.
	case testpb.RpcType_STREAMING:
		bc.doCloseLoopStreaming(conns, rpcCountPerConn, payloadReqSize, payloadRespSize, payloadType)
		// TODO open loop.
	default:
		return grpc.Errorf(codes.InvalidArgument, "unknown rpc type: %v", config.RpcType)
	}

	return nil
}

func startBenchmarkClient(config *testpb.ClientConfig) (*benchmarkClient, error) {
	printClientConfig(config)

	// Set running environment like how many cores to use.
	setupClientEnv(config)

	conns, closeConns, err := createConns(config)
	if err != nil {
		return nil, err
	}

	rpcCountPerConn := int(config.OutstandingRpcsPerChannel)
	bc := &benchmarkClient{
		histogramOptions: stats.HistogramOptions{
			NumBuckets:     int(math.Log(config.HistogramParams.MaxPossible)/math.Log(1+config.HistogramParams.Resolution)) + 1,
			GrowthFactor:   config.HistogramParams.Resolution,
			BaseBucketSize: (1 + config.HistogramParams.Resolution),
			MinValue:       0,
		},
		lockingHistograms: make([]lockingHistogram, rpcCountPerConn*len(conns), rpcCountPerConn*len(conns)),

		stop:          make(chan bool),
		lastResetTime: time.Now(),
		closeConns:    closeConns,
	}

	if err = performRPCs(config, conns, bc); err != nil {
		// Close all connections if performRPCs failed.
		closeConns()
		return nil, err
	}

	return bc, nil
}

func (bc *benchmarkClient) doCloseLoopUnary(conns []*grpc.ClientConn, rpcCountPerConn int, reqSize int, respSize int) {
	for ic, conn := range conns {
		client := testpb.NewBenchmarkServiceClient(conn)
		// For each connection, create rpcCountPerConn goroutines to do rpc.
		for j := 0; j < rpcCountPerConn; j++ {
			// Create mutex and histogram for each goroutine.
			idx := ic*rpcCountPerConn + j
			bc.lockingHistograms[idx].histogram = stats.NewHistogram(bc.histogramOptions)
			// Start goroutine on the created mutex and histogram.
			go func(idx int) {
				// TODO: do warm up if necessary.
				// Now relying on worker client to reserve time to do warm up.
				// The worker client needs to wait for some time after client is created,
				// before starting benchmark.
				done := make(chan bool)
				for {
					go func() {
						start := time.Now()
						if err := benchmark.DoUnaryCall(client, reqSize, respSize); err != nil {
							select {
							case <-bc.stop:
							case done <- false:
							}
							return
						}
						elapse := time.Since(start)
						bc.lockingHistograms[idx].mu.Lock()
						bc.lockingHistograms[idx].histogram.Add(int64(elapse))
						bc.lockingHistograms[idx].mu.Unlock()
						select {
						case <-bc.stop:
						case done <- true:
						}
					}()
					select {
					case <-bc.stop:
						return
					case <-done:
					}
				}
			}(idx)
		}
	}
}

func (bc *benchmarkClient) doCloseLoopStreaming(conns []*grpc.ClientConn, rpcCountPerConn int, reqSize int, respSize int, payloadType string) {
	var doRPC func(testpb.BenchmarkService_StreamingCallClient, int, int) error
	if payloadType == "bytebuf" {
		doRPC = benchmark.DoByteBufStreamingRoundTrip
	} else {
		doRPC = benchmark.DoStreamingRoundTrip
	}
	for ic, conn := range conns {
		// For each connection, create rpcCountPerConn goroutines to do rpc.
		for j := 0; j < rpcCountPerConn; j++ {
			c := testpb.NewBenchmarkServiceClient(conn)
			stream, err := c.StreamingCall(context.Background())
			if err != nil {
				grpclog.Fatalf("%v.StreamingCall(_) = _, %v", c, err)
			}
			// Create mutex and histogram for each goroutine.
			idx := ic*rpcCountPerConn + j
			bc.lockingHistograms[idx].histogram = stats.NewHistogram(bc.histogramOptions)
			// Start goroutine on the created mutex and histogram.
			go func(idx int) {
				// TODO: do warm up if necessary.
				// Now relying on worker client to reserve time to do warm up.
				// The worker client needs to wait for some time after client is created,
				// before starting benchmark.
				done := make(chan bool)
				for {
					go func() {
						start := time.Now()
						if err := doRPC(stream, reqSize, respSize); err != nil {
							select {
							case <-bc.stop:
							case done <- false:
							}
							return
						}
						elapse := time.Since(start)
						bc.lockingHistograms[idx].mu.Lock()
						bc.lockingHistograms[idx].histogram.Add(int64(elapse))
						bc.lockingHistograms[idx].mu.Unlock()
						select {
						case <-bc.stop:
						case done <- true:
						}
					}()
					select {
					case <-bc.stop:
						return
					case <-done:
					}
				}
			}(idx)
		}
	}
}

// getStats returns the stats for benchmark client.
// It resets lastResetTime and all histograms if argument reset is true.
func (bc *benchmarkClient) getStats(reset bool) *testpb.ClientStats {
	var timeElapsed float64
	mergedHistogram := stats.NewHistogram(bc.histogramOptions)

	if reset {
		// Merging histogram may take some time.
		// Put all histograms aside and merge later.
		toMerge := make([]*stats.Histogram, len(bc.lockingHistograms))
		for i := range bc.lockingHistograms {
			bc.lockingHistograms[i].mu.Lock()
			toMerge[i] = bc.lockingHistograms[i].histogram
			bc.lockingHistograms[i].histogram = stats.NewHistogram(bc.histogramOptions)
			bc.lockingHistograms[i].mu.Unlock()
		}

		for i := 0; i < len(toMerge); i++ {
			mergedHistogram.Merge(toMerge[i])
		}

		timeElapsed = time.Since(bc.lastResetTime).Seconds()
		bc.lastResetTime = time.Now()
	} else {
		// Merge only, not reset.
		for i := range bc.lockingHistograms {
			bc.lockingHistograms[i].mu.Lock()
			mergedHistogram.Merge(bc.lockingHistograms[i].histogram)
			bc.lockingHistograms[i].mu.Unlock()
		}
		timeElapsed = time.Since(bc.lastResetTime).Seconds()
	}

	b := make([]uint32, len(mergedHistogram.Buckets))
	for i, v := range mergedHistogram.Buckets {
		b[i] = uint32(v.Count)
	}
	return &testpb.ClientStats{
		Latencies: &testpb.HistogramData{
			Bucket:       b,
			MinSeen:      float64(mergedHistogram.Min),
			MaxSeen:      float64(mergedHistogram.Max),
			Sum:          float64(mergedHistogram.Sum),
			SumOfSquares: float64(mergedHistogram.SumOfSquares),
			Count:        float64(mergedHistogram.Count),
		},
		TimeElapsed: timeElapsed,
		TimeUser:    0,
		TimeSystem:  0,
	}
}

func (bc *benchmarkClient) shutdown() {
	close(bc.stop)
	bc.closeConns()
}
<commit_msg>Specify cap of slices<commit_after>/*
 *
 * Copyright 2016, Google Inc.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *
 *     * Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above
 * copyright notice, this list of conditions and the following disclaimer
 * in the documentation and/or other materials provided with the
 * distribution.
 *     * Neither the name of Google Inc. nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 */

package main

import (
	"math"
	"runtime"
	"sync"
	"time"

	"golang.org/x/net/context"
	"google.golang.org/grpc"
	"google.golang.org/grpc/benchmark"
	testpb "google.golang.org/grpc/benchmark/grpc_testing"
	"google.golang.org/grpc/benchmark/stats"
	"google.golang.org/grpc/codes"
	"google.golang.org/grpc/credentials"
	"google.golang.org/grpc/grpclog"
)

var (
	caFile = "benchmark/server/testdata/ca.pem"
)

type lockingHistogram struct {
	mu        sync.Mutex
	histogram *stats.Histogram
}

type benchmarkClient struct {
	closeConns        func()
	stop              chan bool
	lastResetTime     time.Time
	histogramOptions  stats.HistogramOptions
	lockingHistograms []lockingHistogram
}

func printClientConfig(config *testpb.ClientConfig) {
	// Some config options are ignored:
	// - client type:
	//     will always create sync client
	// - async client threads.
	// - core list
	grpclog.Printf(" * client type: %v (ignored, always creates sync client)", config.ClientType)
	grpclog.Printf(" * async client threads: %v (ignored)", config.AsyncClientThreads)
	grpclog.Printf(" * core list: %v (ignored)", config.CoreList)

	grpclog.Printf(" - security params: %v", config.SecurityParams)
	grpclog.Printf(" - core limit: %v", config.CoreLimit)
	grpclog.Printf(" - payload config: %v", config.PayloadConfig)
	grpclog.Printf(" - rpcs per chann: %v", config.OutstandingRpcsPerChannel)
	grpclog.Printf(" - channel number: %v", config.ClientChannels)
	grpclog.Printf(" - load params: %v", config.LoadParams)
	grpclog.Printf(" - rpc type: %v", config.RpcType)
	grpclog.Printf(" - histogram params: %v", config.HistogramParams)
	grpclog.Printf(" - server targets: %v", config.ServerTargets)
}

func setupClientEnv(config *testpb.ClientConfig) {
	// Use one cpu core by default.
	// TODO: Revisit this for the optimal default setup.
	if config.CoreLimit > 1 {
		runtime.GOMAXPROCS(int(config.CoreLimit))
	} else {
		runtime.GOMAXPROCS(1)
	}
}

// createConns creates connections according to given config.
// It returns the connections and corresponding function to close them.
// It returns non-nil error if there is anything wrong.
func createConns(config *testpb.ClientConfig) ([]*grpc.ClientConn, func(), error) {
	var opts []grpc.DialOption

	// Sanity check for client type.
	switch config.ClientType {
	case testpb.ClientType_SYNC_CLIENT:
	case testpb.ClientType_ASYNC_CLIENT:
	default:
		return nil, nil, grpc.Errorf(codes.InvalidArgument, "unknow client type: %v", config.ClientType)
	}

	// Check and set security options.
	if config.SecurityParams != nil {
		creds, err := credentials.NewClientTLSFromFile(abs(caFile), config.SecurityParams.ServerHostOverride)
		if err != nil {
			return nil, nil, grpc.Errorf(codes.InvalidArgument, "failed to create TLS credentials %v", err)
		}
		opts = append(opts, grpc.WithTransportCredentials(creds))
	} else {
		opts = append(opts, grpc.WithInsecure())
	}

	// Use byteBufCodec if it is required.
	if config.PayloadConfig != nil {
		switch config.PayloadConfig.Payload.(type) {
		case *testpb.PayloadConfig_BytebufParams:
			opts = append(opts, grpc.WithCodec(byteBufCodec{}))
		case *testpb.PayloadConfig_SimpleParams:
		default:
			return nil, nil, grpc.Errorf(codes.InvalidArgument, "unknow payload config: %v", config.PayloadConfig)
		}
	}

	// Create connections.
	connCount := int(config.ClientChannels)
	conns := make([]*grpc.ClientConn, connCount, connCount)
	for connIndex := 0; connIndex < connCount; connIndex++ {
		conns[connIndex] = benchmark.NewClientConn(config.ServerTargets[connIndex%len(config.ServerTargets)], opts...)
	}

	return conns, func() {
		for _, conn := range conns {
			conn.Close()
		}
	}, nil
}

func performRPCs(config *testpb.ClientConfig, conns []*grpc.ClientConn, bc *benchmarkClient) error {
	// Read payload size and type from config.
	var (
		payloadReqSize, payloadRespSize int
		payloadType                     string
	)
	if config.PayloadConfig != nil {
		switch c := config.PayloadConfig.Payload.(type) {
		case *testpb.PayloadConfig_BytebufParams:
			payloadReqSize = int(c.BytebufParams.ReqSize)
			payloadRespSize = int(c.BytebufParams.RespSize)
			payloadType = "bytebuf"
		case *testpb.PayloadConfig_SimpleParams:
			payloadReqSize = int(c.SimpleParams.ReqSize)
			payloadRespSize = int(c.SimpleParams.RespSize)
			payloadType = "protobuf"
		default:
			return grpc.Errorf(codes.InvalidArgument, "unknow payload config: %v", config.PayloadConfig)
		}
	}

	// TODO add open loop distribution.
	switch config.LoadParams.Load.(type) {
	case *testpb.LoadParams_ClosedLoop:
	case *testpb.LoadParams_Poisson:
		return grpc.Errorf(codes.Unimplemented, "unsupported load params: %v", config.LoadParams)
	default:
		return grpc.Errorf(codes.InvalidArgument, "unknown load params: %v", config.LoadParams)
	}

	rpcCountPerConn := int(config.OutstandingRpcsPerChannel)

	switch config.RpcType {
	case testpb.RpcType_UNARY:
		bc.doCloseLoopUnary(conns, rpcCountPerConn, payloadReqSize, payloadRespSize)
		// TODO open loop.
	case testpb.RpcType_STREAMING:
		bc.doCloseLoopStreaming(conns, rpcCountPerConn, payloadReqSize, payloadRespSize, payloadType)
		// TODO open loop.
	default:
		return grpc.Errorf(codes.InvalidArgument, "unknown rpc type: %v", config.RpcType)
	}

	return nil
}

func startBenchmarkClient(config *testpb.ClientConfig) (*benchmarkClient, error) {
	printClientConfig(config)

	// Set running environment like how many cores to use.
	setupClientEnv(config)

	conns, closeConns, err := createConns(config)
	if err != nil {
		return nil, err
	}

	rpcCountPerConn := int(config.OutstandingRpcsPerChannel)
	bc := &benchmarkClient{
		histogramOptions: stats.HistogramOptions{
			NumBuckets:     int(math.Log(config.HistogramParams.MaxPossible)/math.Log(1+config.HistogramParams.Resolution)) + 1,
			GrowthFactor:   config.HistogramParams.Resolution,
			BaseBucketSize: (1 + config.HistogramParams.Resolution),
			MinValue:       0,
		},
		lockingHistograms: make([]lockingHistogram, rpcCountPerConn*len(conns), rpcCountPerConn*len(conns)),

		stop:          make(chan bool),
		lastResetTime: time.Now(),
		closeConns:    closeConns,
	}

	if err = performRPCs(config, conns, bc); err != nil {
		// Close all connections if performRPCs failed.
		closeConns()
		return nil, err
	}

	return bc, nil
}

func (bc *benchmarkClient) doCloseLoopUnary(conns []*grpc.ClientConn, rpcCountPerConn int, reqSize int, respSize int) {
	for ic, conn := range conns {
		client := testpb.NewBenchmarkServiceClient(conn)
		// For each connection, create rpcCountPerConn goroutines to do rpc.
		for j := 0; j < rpcCountPerConn; j++ {
			// Create mutex and histogram for each goroutine.
			idx := ic*rpcCountPerConn + j
			bc.lockingHistograms[idx].histogram = stats.NewHistogram(bc.histogramOptions)
			// Start goroutine on the created mutex and histogram.
			go func(idx int) {
				// TODO: do warm up if necessary.
				// Now relying on worker client to reserve time to do warm up.
				// The worker client needs to wait for some time after client is created,
				// before starting benchmark.
				done := make(chan bool)
				for {
					go func() {
						start := time.Now()
						if err := benchmark.DoUnaryCall(client, reqSize, respSize); err != nil {
							select {
							case <-bc.stop:
							case done <- false:
							}
							return
						}
						elapse := time.Since(start)
						bc.lockingHistograms[idx].mu.Lock()
						bc.lockingHistograms[idx].histogram.Add(int64(elapse))
						bc.lockingHistograms[idx].mu.Unlock()
						select {
						case <-bc.stop:
						case done <- true:
						}
					}()
					select {
					case <-bc.stop:
						return
					case <-done:
					}
				}
			}(idx)
		}
	}
}

func (bc *benchmarkClient) doCloseLoopStreaming(conns []*grpc.ClientConn, rpcCountPerConn int, reqSize int, respSize int, payloadType string) {
	var doRPC func(testpb.BenchmarkService_StreamingCallClient, int, int) error
	if payloadType == "bytebuf" {
		doRPC = benchmark.DoByteBufStreamingRoundTrip
	} else {
		doRPC = benchmark.DoStreamingRoundTrip
	}
	for ic, conn := range conns {
		// For each connection, create rpcCountPerConn goroutines to do rpc.
		for j := 0; j < rpcCountPerConn; j++ {
			c := testpb.NewBenchmarkServiceClient(conn)
			stream, err := c.StreamingCall(context.Background())
			if err != nil {
				grpclog.Fatalf("%v.StreamingCall(_) = _, %v", c, err)
			}
			// Create mutex and histogram for each goroutine.
			idx := ic*rpcCountPerConn + j
			bc.lockingHistograms[idx].histogram = stats.NewHistogram(bc.histogramOptions)
			// Start goroutine on the created mutex and histogram.
			go func(idx int) {
				// TODO: do warm up if necessary.
				// Now relying on worker client to reserve time to do warm up.
				// The worker client needs to wait for some time after client is created,
				// before starting benchmark.
				done := make(chan bool)
				for {
					go func() {
						start := time.Now()
						if err := doRPC(stream, reqSize, respSize); err != nil {
							select {
							case <-bc.stop:
							case done <- false:
							}
							return
						}
						elapse := time.Since(start)
						bc.lockingHistograms[idx].mu.Lock()
						bc.lockingHistograms[idx].histogram.Add(int64(elapse))
						bc.lockingHistograms[idx].mu.Unlock()
						select {
						case <-bc.stop:
						case done <- true:
						}
					}()
					select {
					case <-bc.stop:
						return
					case <-done:
					}
				}
			}(idx)
		}
	}
}

// getStats returns the stats for benchmark client.
// It resets lastResetTime and all histograms if argument reset is true.
func (bc *benchmarkClient) getStats(reset bool) *testpb.ClientStats {
	var timeElapsed float64
	mergedHistogram := stats.NewHistogram(bc.histogramOptions)

	if reset {
		// Merging histogram may take some time.
		// Put all histograms aside and merge later.
		toMerge := make([]*stats.Histogram, len(bc.lockingHistograms), len(bc.lockingHistograms))
		for i := range bc.lockingHistograms {
			bc.lockingHistograms[i].mu.Lock()
			toMerge[i] = bc.lockingHistograms[i].histogram
			bc.lockingHistograms[i].histogram = stats.NewHistogram(bc.histogramOptions)
			bc.lockingHistograms[i].mu.Unlock()
		}

		for i := 0; i < len(toMerge); i++ {
			mergedHistogram.Merge(toMerge[i])
		}

		timeElapsed = time.Since(bc.lastResetTime).Seconds()
		bc.lastResetTime = time.Now()
	} else {
		// Merge only, not reset.
		for i := range bc.lockingHistograms {
			bc.lockingHistograms[i].mu.Lock()
			mergedHistogram.Merge(bc.lockingHistograms[i].histogram)
			bc.lockingHistograms[i].mu.Unlock()
		}
		timeElapsed = time.Since(bc.lastResetTime).Seconds()
	}

	b := make([]uint32, len(mergedHistogram.Buckets), len(mergedHistogram.Buckets))
	for i, v := range mergedHistogram.Buckets {
		b[i] = uint32(v.Count)
	}
	return &testpb.ClientStats{
		Latencies: &testpb.HistogramData{
			Bucket:       b,
			MinSeen:      float64(mergedHistogram.Min),
			MaxSeen:      float64(mergedHistogram.Max),
			Sum:          float64(mergedHistogram.Sum),
			SumOfSquares: float64(mergedHistogram.SumOfSquares),
			Count:        float64(mergedHistogram.Count),
		},
		TimeElapsed: timeElapsed,
		TimeUser:    0,
		TimeSystem:  0,
	}
}

func (bc *benchmarkClient) shutdown() {
	close(bc.stop)
	bc.closeConns()
}
<|endoftext|>


<commit_before>package atom

import (
	"io"
	"io/ioutil"
	"os"
	"path"
)

// Truncater encapsulates everything that responds to Truncate(int64).
type Truncater interface {
	Truncate(int64) error
}

// File is a minimal file interface for atomic writes.
type File interface {
	io.Reader
	io.Writer
	io.Seeker
	io.Closer

	Truncater
}

// Open opens an atomic file for writing.
func Open(name string) (File, error) {
	tmp, err := ioutil.TempFile(path.Dir(name), ".jump")
	if err != nil {
		return nil, err
	}

	// Copy the contents of the input file, so we can read it from the temporary.
	if _, err := os.Stat(name); !os.IsNotExist(err) {
		file, err := os.OpenFile(name, os.O_RDWR, 0644)
		if err != nil {
			return nil, err
		}
		defer file.Close()

		_, err = io.Copy(tmp, file)
		if err != nil {
			return nil, err
		}

		_, err = tmp.Seek(0, 0)
		if err != nil {
			return nil, err
		}
	}

	return &file{to: name, tmp: tmp}, nil
}

type file struct {
	to    string
	tmp   *os.File
	dirty bool
}

func (f *file) Read(p []byte) (int, error) {
	return f.tmp.Read(p)
}

func (f *file) Write(p []byte) (int, error) {
	n, err := f.tmp.Write(p)
	if err != nil {
		f.dirty = true
	}

	return n, err
}

func (f *file) Seek(offset int64, whence int) (int64, error) {
	return f.tmp.Seek(offset, whence)
}

func (f *file) Truncate(n int64) error {
	return f.tmp.Truncate(n)
}

func (f *file) Close() error {
	if err := f.tmp.Close(); err != nil {
		return err
	}

	if f.dirty {
		return nil
	}

	return os.Rename(f.tmp.Name(), f.to)
}
<commit_msg>Add comment clarifying 'dirty' field in atom/file<commit_after>package atom

import (
	"io"
	"io/ioutil"
	"os"
	"path"
)

// Truncater encapsulates everything that responds to Truncate(int64).
type Truncater interface {
	Truncate(int64) error
}

// File is a minimal file interface for atomic writes.
type File interface {
	io.Reader
	io.Writer
	io.Seeker
	io.Closer

	Truncater
}

// Open opens an atomic file for writing.
func Open(name string) (File, error) {
	tmp, err := ioutil.TempFile(path.Dir(name), ".jump")
	if err != nil {
		return nil, err
	}

	// Copy the contents of the input file, so we can read it from the temporary.
	if _, err := os.Stat(name); !os.IsNotExist(err) {
		file, err := os.OpenFile(name, os.O_RDWR, 0644)
		if err != nil {
			return nil, err
		}
		defer file.Close()

		_, err = io.Copy(tmp, file)
		if err != nil {
			return nil, err
		}

		_, err = tmp.Seek(0, 0)
		if err != nil {
			return nil, err
		}
	}

	return &file{to: name, tmp: tmp}, nil
}

type file struct {
	to  string
	tmp *os.File
	// dirty indicates whether this tmpfile has experienced errors which mean it
	// should not be used to update the original.
	dirty bool
}

func (f *file) Read(p []byte) (int, error) {
	return f.tmp.Read(p)
}

func (f *file) Write(p []byte) (int, error) {
	n, err := f.tmp.Write(p)
	if err != nil {
		f.dirty = true
	}

	return n, err
}

func (f *file) Seek(offset int64, whence int) (int64, error) {
	return f.tmp.Seek(offset, whence)
}

func (f *file) Truncate(n int64) error {
	return f.tmp.Truncate(n)
}

func (f *file) Close() error {
	if err := f.tmp.Close(); err != nil {
		return err
	}

	if f.dirty {
		return nil
	}

	return os.Rename(f.tmp.Name(), f.to)
}
<|endoftext|>


<commit_before>package vegeta

import (
	"bufio"
	"bytes"
	"errors"
	"fmt"
	"io"
	"io/ioutil"
	"net/http"
	"net/url"
	"regexp"
	"strings"
	"sync"
	"sync/atomic"
)

// Target is an HTTP request blueprint.
type Target struct {
	Method string
	URL    string
	Body   []byte
	Header http.Header
}

// Request creates an *http.Request out of Target and returns it along with an
// error in case of failure.
func (t *Target) Request() (*http.Request, error) {
	req, err := http.NewRequest(t.Method, t.URL, bytes.NewBuffer(t.Body))
	if err != nil {
		return nil, err
	}
	for k, vs := range t.Header {
		req.Header[k] = make([]string, len(vs))
		copy(req.Header[k], vs)
	}
	if host := req.Header.Get("Host"); host != "" {
		req.Host = host
	}
	return req, nil
}

// ErrNoTargets is returned when not enough Targets are available.
var ErrNoTargets = errors.New("no targets to attack")

// Targeter is a generator function which returns a new Target
// or an error on every invocation. It is safe for concurrent use.
type Targeter func() (*Target, error)

// NewStaticTargeter returns a Targeter which round-robins over the passed
// Targets.
func NewStaticTargeter(tgts ...*Target) Targeter {
	i := int64(-1)
	return func() (*Target, error) {
		return tgts[atomic.AddInt64(&i, 1)%int64(len(tgts))], nil
	}
}

// NewEagerTargeter eagerly reads all Targets out of the provided io.Reader and
// returns a NewStaticTargeter with them.
//
// body will be set as the Target's body if no body is provided.
// hdr will be merged with the each Target's headers.
func NewEagerTargeter(src io.Reader, body []byte, header http.Header) (Targeter, error) {
	var (
		sc   = NewLazyTargeter(src, body, header)
		tgts []*Target
		tgt  *Target
		err  error
	)
	for {
		if tgt, err = sc(); err == ErrNoTargets {
			break
		} else if err != nil {
			return nil, err
		}
		tgts = append(tgts, tgt)
	}
	if len(tgts) == 0 {
		return nil, ErrNoTargets
	}
	return NewStaticTargeter(tgts...), nil
}

// NewLazyTargeter returns a new Targeter that lazily scans Targets from the
// provided io.Reader on every invocation.
//
// body will be set as the Target's body if no body is provided.
// hdr will be merged with the each Target's headers.
func NewLazyTargeter(src io.Reader, body []byte, hdr http.Header) Targeter {
	var mu sync.Mutex
	sc := peekingScanner{src: bufio.NewScanner(src)}
	return func() (*Target, error) {
		mu.Lock()
		defer mu.Unlock()

		if !sc.Scan() {
			return nil, ErrNoTargets
		}
		tgt := Target{Body: body, Header: http.Header{}}
		for k, vs := range hdr {
			tgt.Header[k] = vs
		}
		line := strings.TrimSpace(sc.Text())
		tokens := strings.SplitN(line, " ", 2)
		if len(tokens) < 2 {
			return nil, fmt.Errorf("bad target: %s", line)
		}
		switch tokens[0] {
		case "HEAD", "GET", "PUT", "POST", "PATCH", "OPTIONS":
			tgt.Method = tokens[0]
		default:
			return nil, fmt.Errorf("bad method: %s", tokens[0])
		}
		if _, err := url.ParseRequestURI(tokens[1]); err != nil {
			return nil, fmt.Errorf("bad URL: %s", tokens[1])
		}
		tgt.URL = tokens[1]
		line = strings.TrimSpace(sc.Peek())
		if line == "" || startsWithHttpMethod(line) {
			return &tgt, nil
		}
		for sc.Scan() {
			if line = strings.TrimSpace(sc.Text()); line == "" {
				break
			} else if strings.HasPrefix(line, "@") {
				var err error
				if tgt.Body, err = ioutil.ReadFile(line[1:]); err != nil {
					return nil, fmt.Errorf("bad body: %s", err)
				}
				break
			}
			tokens = strings.SplitN(line, ":", 2)
			if len(tokens) < 2 {
				return nil, fmt.Errorf("bad header: %s", line)
			}
			for i := range tokens {
				if tokens[i] = strings.TrimSpace(tokens[i]); tokens[i] == "" {
					return nil, fmt.Errorf("bad header: %s", line)
				}
			}
			tgt.Header.Add(tokens[0], tokens[1])
		}
		if err := sc.Err(); err != nil {
			return nil, ErrNoTargets
		}
		return &tgt, nil
	}
}

var httpMethodChecker, _ = regexp.Compile("^(HEAD|GET|PUT|POST|PATCH|OPTIONS) ")

func startsWithHttpMethod(t string) bool {
	return httpMethodChecker.MatchString(t)
}

// Wrap a Scanner so we can cheat and look at the next value and react accordingly,
// but still have it be around the next time we Scan() + Text()
type peekingScanner struct {
	src    *bufio.Scanner
	peeked string
}

func (s *peekingScanner) Err() error {
	return s.src.Err()
}

func (s *peekingScanner) Peek() string {
	if !s.src.Scan() {
		return ""
	}
	s.peeked = s.src.Text()
	return s.peeked
}

func (s *peekingScanner) Scan() bool {
	if s.peeked == "" {
		return s.src.Scan()
	}
	return true
}

func (s *peekingScanner) Text() string {
	if s.peeked == "" {
		return s.src.Text()
	}
	t := s.peeked
	s.peeked = ""
	return t
}
<commit_msg>Use regexp.MustCompile<commit_after>package vegeta

import (
	"bufio"
	"bytes"
	"errors"
	"fmt"
	"io"
	"io/ioutil"
	"net/http"
	"net/url"
	"regexp"
	"strings"
	"sync"
	"sync/atomic"
)

// Target is an HTTP request blueprint.
type Target struct {
	Method string
	URL    string
	Body   []byte
	Header http.Header
}

// Request creates an *http.Request out of Target and returns it along with an
// error in case of failure.
func (t *Target) Request() (*http.Request, error) {
	req, err := http.NewRequest(t.Method, t.URL, bytes.NewBuffer(t.Body))
	if err != nil {
		return nil, err
	}
	for k, vs := range t.Header {
		req.Header[k] = make([]string, len(vs))
		copy(req.Header[k], vs)
	}
	if host := req.Header.Get("Host"); host != "" {
		req.Host = host
	}
	return req, nil
}

// ErrNoTargets is returned when not enough Targets are available.
var ErrNoTargets = errors.New("no targets to attack")

// Targeter is a generator function which returns a new Target
// or an error on every invocation. It is safe for concurrent use.
type Targeter func() (*Target, error)

// NewStaticTargeter returns a Targeter which round-robins over the passed
// Targets.
func NewStaticTargeter(tgts ...*Target) Targeter {
	i := int64(-1)
	return func() (*Target, error) {
		return tgts[atomic.AddInt64(&i, 1)%int64(len(tgts))], nil
	}
}

// NewEagerTargeter eagerly reads all Targets out of the provided io.Reader and
// returns a NewStaticTargeter with them.
//
// body will be set as the Target's body if no body is provided.
// hdr will be merged with the each Target's headers.
func NewEagerTargeter(src io.Reader, body []byte, header http.Header) (Targeter, error) {
	var (
		sc   = NewLazyTargeter(src, body, header)
		tgts []*Target
		tgt  *Target
		err  error
	)
	for {
		if tgt, err = sc(); err == ErrNoTargets {
			break
		} else if err != nil {
			return nil, err
		}
		tgts = append(tgts, tgt)
	}
	if len(tgts) == 0 {
		return nil, ErrNoTargets
	}
	return NewStaticTargeter(tgts...), nil
}

// NewLazyTargeter returns a new Targeter that lazily scans Targets from the
// provided io.Reader on every invocation.
//
// body will be set as the Target's body if no body is provided.
// hdr will be merged with the each Target's headers.
func NewLazyTargeter(src io.Reader, body []byte, hdr http.Header) Targeter {
	var mu sync.Mutex
	sc := peekingScanner{src: bufio.NewScanner(src)}
	return func() (*Target, error) {
		mu.Lock()
		defer mu.Unlock()

		if !sc.Scan() {
			return nil, ErrNoTargets
		}
		tgt := Target{Body: body, Header: http.Header{}}
		for k, vs := range hdr {
			tgt.Header[k] = vs
		}
		line := strings.TrimSpace(sc.Text())
		tokens := strings.SplitN(line, " ", 2)
		if len(tokens) < 2 {
			return nil, fmt.Errorf("bad target: %s", line)
		}
		switch tokens[0] {
		case "HEAD", "GET", "PUT", "POST", "PATCH", "OPTIONS":
			tgt.Method = tokens[0]
		default:
			return nil, fmt.Errorf("bad method: %s", tokens[0])
		}
		if _, err := url.ParseRequestURI(tokens[1]); err != nil {
			return nil, fmt.Errorf("bad URL: %s", tokens[1])
		}
		tgt.URL = tokens[1]
		line = strings.TrimSpace(sc.Peek())
		if line == "" || startsWithHTTPMethod(line) {
			return &tgt, nil
		}
		for sc.Scan() {
			if line = strings.TrimSpace(sc.Text()); line == "" {
				break
			} else if strings.HasPrefix(line, "@") {
				var err error
				if tgt.Body, err = ioutil.ReadFile(line[1:]); err != nil {
					return nil, fmt.Errorf("bad body: %s", err)
				}
				break
			}
			tokens = strings.SplitN(line, ":", 2)
			if len(tokens) < 2 {
				return nil, fmt.Errorf("bad header: %s", line)
			}
			for i := range tokens {
				if tokens[i] = strings.TrimSpace(tokens[i]); tokens[i] == "" {
					return nil, fmt.Errorf("bad header: %s", line)
				}
			}
			tgt.Header.Add(tokens[0], tokens[1])
		}
		if err := sc.Err(); err != nil {
			return nil, ErrNoTargets
		}
		return &tgt, nil
	}
}

var httpMethodChecker = regexp.MustCompile("^(HEAD|GET|PUT|POST|PATCH|OPTIONS) ")

func startsWithHTTPMethod(t string) bool {
	return httpMethodChecker.MatchString(t)
}

// Wrap a Scanner so we can cheat and look at the next value and react accordingly,
// but still have it be around the next time we Scan() + Text()
type peekingScanner struct {
	src    *bufio.Scanner
	peeked string
}

func (s *peekingScanner) Err() error {
	return s.src.Err()
}

func (s *peekingScanner) Peek() string {
	if !s.src.Scan() {
		return ""
	}
	s.peeked = s.src.Text()
	return s.peeked
}

func (s *peekingScanner) Scan() bool {
	if s.peeked == "" {
		return s.src.Scan()
	}
	return true
}

func (s *peekingScanner) Text() string {
	if s.peeked == "" {
		return s.src.Text()
	}
	t := s.peeked
	s.peeked = ""
	return t
}
<|endoftext|>


<commit_before>// This will be removed or reworked in the final version.
// Stat submission for the closed beta.
package main

import (
	"encoding/json"
	"github.com/urfave/cli"
	"github.com/valyala/fasthttp"
	"time"
)

type Invocation struct {
	Args  []string `json:"args"`
	Flags struct {
		Type     string        `json:"type"`
		VUs      []string      `json:"vus"`
		Duration time.Duration `json:"duration"`
		Verbose  bool          `json:"verbose"`
		Quiet    bool          `json:"quiet"`
		Format   string        `json:"format"`
		Interval time.Duration `json:"interval"`
		Out      []string      `json:"out"`
		Raw      bool          `json:"raw"`
		Select   []string      `json:"select"`
		Exclude  []string      `json:"exclude"`
		GroupBy  []string      `json:"group_by"`
	} `json:"flags"`
	Error string `json:"error"`
}

func (i *Invocation) PopulateWithContext(cc *cli.Context) {
	i.Args = []string(cc.Args())
	i.Flags.Type = cc.GlobalString("type")
	i.Flags.VUs = cc.GlobalStringSlice("vus")
	i.Flags.Duration = cc.GlobalDuration("duration")
	i.Flags.Verbose = cc.GlobalBool("verbose")
	i.Flags.Quiet = cc.GlobalBool("quiet")
	i.Flags.Format = cc.GlobalString("format")
	i.Flags.Interval = cc.GlobalDuration("interval")
	i.Flags.Out = cc.GlobalStringSlice("out")
	i.Flags.Raw = cc.GlobalBool("raw")
	i.Flags.Select = cc.GlobalStringSlice("select")
	i.Flags.Exclude = cc.GlobalStringSlice("exclude")
	i.Flags.GroupBy = cc.GlobalStringSlice("group-by")
}

func (i *Invocation) Submit(url string) error {
	body, err := json.Marshal(i)
	if err != nil {
		return err
	}

	req := fasthttp.AcquireRequest()
	defer fasthttp.ReleaseRequest(req)

	req.SetRequestURI(url + "/invoked")
	req.Header.SetMethod("POST")
	req.Header.SetContentType("text/json")
	req.SetBody(body)

	if err := fasthttp.Do(req, nil); err != nil {
		return err
	}

	return nil
}
<commit_msg>[feat] Collect plan + tags too<commit_after>// This will be removed or reworked in the final version.
// Stat submission for the closed beta.
package main

import (
	"encoding/json"
	"github.com/urfave/cli"
	"github.com/valyala/fasthttp"
	"time"
)

type Invocation struct {
	Args  []string `json:"args"`
	Flags struct {
		Plan     bool          `json:"plan"`
		Type     string        `json:"type"`
		VUs      []string      `json:"vus"`
		Duration time.Duration `json:"duration"`
		Verbose  bool          `json:"verbose"`
		Quiet    bool          `json:"quiet"`
		Format   string        `json:"format"`
		Interval time.Duration `json:"interval"`
		Out      []string      `json:"out"`
		Raw      bool          `json:"raw"`
		Select   []string      `json:"select"`
		Exclude  []string      `json:"exclude"`
		GroupBy  []string      `json:"group_by"`
		Tag      []string      `json:"tag"`
	} `json:"flags"`
	Error string `json:"error"`
}

func (i *Invocation) PopulateWithContext(cc *cli.Context) {
	i.Args = []string(cc.Args())
	i.Flags.Plan = cc.GlobalBool("plan")
	i.Flags.Type = cc.GlobalString("type")
	i.Flags.VUs = cc.GlobalStringSlice("vus")
	i.Flags.Duration = cc.GlobalDuration("duration")
	i.Flags.Verbose = cc.GlobalBool("verbose")
	i.Flags.Quiet = cc.GlobalBool("quiet")
	i.Flags.Format = cc.GlobalString("format")
	i.Flags.Interval = cc.GlobalDuration("interval")
	i.Flags.Out = cc.GlobalStringSlice("out")
	i.Flags.Raw = cc.GlobalBool("raw")
	i.Flags.Select = cc.GlobalStringSlice("select")
	i.Flags.Exclude = cc.GlobalStringSlice("exclude")
	i.Flags.GroupBy = cc.GlobalStringSlice("group-by")
	i.Flags.Tag = cc.GlobalStringSlice("tag")
}

func (i *Invocation) Submit(url string) error {
	body, err := json.Marshal(i)
	if err != nil {
		return err
	}

	req := fasthttp.AcquireRequest()
	defer fasthttp.ReleaseRequest(req)

	req.SetRequestURI(url + "/invoked")
	req.Header.SetMethod("POST")
	req.Header.SetContentType("text/json")
	req.SetBody(body)

	if err := fasthttp.Do(req, nil); err != nil {
		return err
	}

	return nil
}
<|endoftext|>


<commit_before>package bh1750

import (
	"github.com/explicite/i2c/driver"
	"time"
)

const (
	// ADDR ≦ 0.3VCC
	AddrL = 0x23

	// ADDR ≧ 0.7VCC
	AddrH = 0x5c

	// No active state.
	PowerDown = 0x00

	// Waiting for measurement command.
	PowerOn = 0x01

	// Reset Data register value. Reset command is not acceptable in Power Down mode.
	Reset = 0x07

	// Start measurement at 1lx resolution. Measurement Time is typically 120ms.
	ConHRes1lx = 0x10

	// Start measurement at 0.5lx resolution. Measurement Time is typically 120ms.
	ConHRes05lx = 0x11

	// Start measurement at 4lx resolution. Measurement Time is typically 16ms.
	ConLRes4lx = 0x13

	// Start measurement at 1lx resolution. Measurement Time is typically 120ms.
	// It is automatically set to Power Down mode after measurement.
	OtHRes1lx = 0x20

	// Start measurement at 0.5lx resolution. Measurement Time is typically 120ms.
	// It is automatically set to Power Down mode after measurement.
	OtHRes05lx = 0x21

	// Start measurement at 4lx resolution. Measurement Time is typically 16ms.
	// It is automatically set to Power Down mode after measurement.
	OtLRes4lx = 0x23

	// 20ms for safety time margine in measurement.
	Stm = 20 * time.Millisecond
)

// Map of timeouts for measurement type.
var timeout = map[byte]time.Duration{
	ConHRes1lx:  120*time.Millisecond + Stm,
	ConHRes05lx: 120*time.Millisecond + Stm,
	ConLRes4lx:  16*time.Millisecond + Stm,
	OtHRes1lx:   120*time.Millisecond + Stm,
	OtHRes05lx:  120*time.Millisecond + Stm,
	OtLRes4lx:   16*time.Millisecond + Stm,
}

type BH1750 struct{ driver.Driver }

func (b *BH1750) Init(addr byte, bus byte) error {
	return b.Load(addr, bus)
}

func (b *BH1750) Lux(mode byte) (float32, error) {
	b.Write(mode, 0x00)
	time.Sleep(timeout[mode])
	buf := make([]byte, 0x02)
	var err error
	buf, err = b.Read(mode, 0x02)

	if err != nil {
		return 0, err
	}

	return float32((uint8(buf[1]) + (uint8(buf[0] >> 8)))) / 1.2, nil
}

func (b *BH1750) Active() error {
	return b.On()
}

func (b *BH1750) Deactive() error {
	return b.Off()
}
<commit_msg>bh1750 type for go vet<commit_after>package bh1750

import (
	"github.com/explicite/i2c/driver"
	"time"
)

const (
	// ADDR ≦ 0.3VCC
	AddrL = 0x23

	// ADDR ≧ 0.7VCC
	AddrH = 0x5c

	// No active state.
	PowerDown = 0x00

	// Waiting for measurement command.
	PowerOn = 0x01

	// Reset Data register value. Reset command is not acceptable in Power Down mode.
	Reset = 0x07

	// Start measurement at 1lx resolution. Measurement Time is typically 120ms.
	ConHRes1lx = 0x10

	// Start measurement at 0.5lx resolution. Measurement Time is typically 120ms.
	ConHRes05lx = 0x11

	// Start measurement at 4lx resolution. Measurement Time is typically 16ms.
	ConLRes4lx = 0x13

	// Start measurement at 1lx resolution. Measurement Time is typically 120ms.
	// It is automatically set to Power Down mode after measurement.
	OtHRes1lx = 0x20

	// Start measurement at 0.5lx resolution. Measurement Time is typically 120ms.
	// It is automatically set to Power Down mode after measurement.
	OtHRes05lx = 0x21

	// Start measurement at 4lx resolution. Measurement Time is typically 16ms.
	// It is automatically set to Power Down mode after measurement.
	OtLRes4lx = 0x23

	// 20ms for safety time margine in measurement.
	Stm = 20 * time.Millisecond
)

// Map of timeouts for measurement type.
var timeout = map[byte]time.Duration{
	ConHRes1lx:  120*time.Millisecond + Stm,
	ConHRes05lx: 120*time.Millisecond + Stm,
	ConLRes4lx:  16*time.Millisecond + Stm,
	OtHRes1lx:   120*time.Millisecond + Stm,
	OtHRes05lx:  120*time.Millisecond + Stm,
	OtLRes4lx:   16*time.Millisecond + Stm,
}

type BH1750 struct{ driver.Driver }

func (b *BH1750) Init(addr byte, bus byte) error {
	return b.Load(addr, bus)
}

func (b *BH1750) Lux(mode byte) (float32, error) {
	b.Write(mode, 0x00)
	time.Sleep(timeout[mode])
	buf := make([]byte, 0x02)
	var err error
	buf, err = b.Read(mode, 0x02)

	if err != nil {
		return 0, err
	}

	return float32((int(buf[1]) + (int(buf[0] >> 8)))) / 1.2, nil
}

func (b *BH1750) Active() error {
	return b.On()
}

func (b *BH1750) Deactive() error {
	return b.Off()
}
<|endoftext|>


<commit_before>package vmx

import (
	"context"
	"fmt"
	"log"
	"path/filepath"

	vmwcommon "github.com/hashicorp/packer/builder/vmware/common"
	"github.com/hashicorp/packer/helper/multistep"
	"github.com/hashicorp/packer/packer"
)

// StepCloneVMX takes a VMX file and clones the VM into the output directory.
type StepCloneVMX struct {
	OutputDir string
	Path      string
	VMName    string
}

func (s *StepCloneVMX) Run(_ context.Context, state multistep.StateBag) multistep.StepAction {
	driver := state.Get("driver").(vmwcommon.Driver)
	ui := state.Get("ui").(packer.Ui)

	// initially we need to stash the path to the original .vmx file
	vmxPath := filepath.Join(s.OutputDir, s.VMName+".vmx")

	// so first, let's clone the source path to the vmxPath
	ui.Say("Cloning source VM...")
	log.Printf("Cloning from: %s", s.Path)
	log.Printf("Cloning to: %s", vmxPath)
	if err := driver.Clone(vmxPath, s.Path); err != nil {
		state.Put("error", err)
		return multistep.ActionHalt
	}
	ui.Say(fmt.Sprintf("Successfully cloned source VM to: %s", vmxPath))

	// now we read the .vmx so we can determine what else to stash
	vmxData, err := vmwcommon.ReadVMX(vmxPath)
	if err != nil {
		state.Put("error", err)
		return multistep.ActionHalt
	}

	// figure out the disk filename by walking through all device types
	var diskName string
	if _, ok := vmxData["scsi0:0.filename"]; ok {
		diskName = vmxData["scsi0:0.filename"]
	}
	if _, ok := vmxData["sata0:0.filename"]; ok {
		diskName = vmxData["sata0:0.filename"]
	}
	if _, ok := vmxData["ide0:0.filename"]; ok {
		diskName = vmxData["ide0:0.filename"]
	}
	if diskName == "" {
		err := fmt.Errorf("Root disk filename could not be found!")
		state.Put("error", err)
		return multistep.ActionHalt
	}
	log.Printf("Found root disk filename: %s", diskName)

	// determine the network type by reading out of the .vmx
	var networkType string
	if _, ok := vmxData["ethernet0.connectiontype"]; ok {
		networkType = vmxData["ethernet0.connectiontype"]
		log.Printf("Discovered the network type: %s", networkType)
	}
	if networkType == "" {
		networkType = "nat"
		log.Printf("Defaulting to network type: %s", networkType)
	}
	ui.Say(fmt.Sprintf("Using network type: %s", networkType))

	// we were able to find everything, so stash it in our state.
	state.Put("vmx_path", vmxPath)
	state.Put("full_disk_path", filepath.Join(s.OutputDir, diskName))
	state.Put("vmnetwork", networkType)

	return multistep.ActionContinue
}

func (s *StepCloneVMX) Cleanup(state multistep.StateBag) {
}
<commit_msg>Fix error on compaction step of vmx build. Support compacting multi-disk vm<commit_after>package vmx

import (
	"context"
	"fmt"
	"log"
	"path/filepath"

	vmwcommon "github.com/hashicorp/packer/builder/vmware/common"
	"github.com/hashicorp/packer/helper/multistep"
	"github.com/hashicorp/packer/packer"
)

// StepCloneVMX takes a VMX file and clones the VM into the output directory.
type StepCloneVMX struct {
	OutputDir string
	Path      string
	VMName    string
}

type vmxAdapter struct {
	// The string portion of the address used in the vmx file
	strAddr string
	// Max address for adapter, controller, or controller channel
	aAddrMax int
	// Max address for device or channel supported by adapter
	dAddrMax int
}

const (
	// VMware Configuration Maximums - Virtual Hardware Versions 13/14
	//
	// Specifying the max numbers for the adapter/controller:bus/channel
	// *address* as opposed to specifying the maximums as per the VMware
	// documentation allows consistent (inclusive) treatment when looping
	// over each adapter/controller type
	//
	// SCSI - Address range: scsi0:0 to scsi3:15
	scsiAddrName       = "scsi" // String part of address used in the vmx file
	maxSCSIAdapterAddr = 3      // Max 4 adapters
	maxSCSIDeviceAddr  = 15     // Max 15 devices per adapter; ID 7 is the HBA
	// SATA - Address range: sata0:0 to scsi3:29
	sataAddrName       = "sata" // String part of address used in the vmx file
	maxSATAAdapterAddr = 3      // Max 4 controllers
	maxSATADeviceAddr  = 29     // Max 30 devices per controller
	// NVMe - Address range: nvme0:0 to nvme3:14
	nvmeAddrName       = "nvme" // String part of address used in the vmx file
	maxNVMeAdapterAddr = 3      // Max 4 adapters
	maxNVMeDeviceAddr  = 14     // Max 15 devices per adapter
	// IDE - Address range: ide0:0 to ide1:1
	ideAddrName       = "ide" // String part of address used in the vmx file
	maxIDEAdapterAddr = 1     // One controller with primary/secondary channels
	maxIDEDeviceAddr  = 1     // Each channel supports master and slave
)

var (
	scsiAdapter = vmxAdapter{
		strAddr:  scsiAddrName,
		aAddrMax: maxSCSIAdapterAddr,
		dAddrMax: maxSCSIDeviceAddr,
	}
	sataAdapter = vmxAdapter{
		strAddr:  sataAddrName,
		aAddrMax: maxSATAAdapterAddr,
		dAddrMax: maxSATADeviceAddr,
	}
	nvmeAdapter = vmxAdapter{
		strAddr:  nvmeAddrName,
		aAddrMax: maxNVMeAdapterAddr,
		dAddrMax: maxNVMeDeviceAddr,
	}
	ideAdapter = vmxAdapter{
		strAddr:  ideAddrName,
		aAddrMax: maxIDEAdapterAddr,
		dAddrMax: maxIDEDeviceAddr,
	}
)

func (s *StepCloneVMX) Run(_ context.Context, state multistep.StateBag) multistep.StepAction {
	driver := state.Get("driver").(vmwcommon.Driver)
	ui := state.Get("ui").(packer.Ui)

	// Set the path we want for the new .vmx file and clone
	vmxPath := filepath.Join(s.OutputDir, s.VMName+".vmx")
	ui.Say("Cloning source VM...")
	log.Printf("Cloning from: %s", s.Path)
	log.Printf("Cloning to: %s", vmxPath)
	if err := driver.Clone(vmxPath, s.Path); err != nil {
		state.Put("error", err)
		return multistep.ActionHalt
	}

	// Read in the machine configuration from the cloned VMX file
	//
	// * The main driver needs the path to the vmx (set above) and the
	// network type so that it can work out things like IP's and MAC
	// addresses
	// * The disk compaction step needs the paths to all attached disks
	vmxData, err := vmwcommon.ReadVMX(vmxPath)
	if err != nil {
		state.Put("error", err)
		return multistep.ActionHalt
	}

	// Search across all adapter types to get the filenames of attached disks
	allDiskAdapters := []vmxAdapter{
		scsiAdapter,
		sataAdapter,
		nvmeAdapter,
		ideAdapter,
	}
	var diskFilenames []string
	for _, adapter := range allDiskAdapters {
		diskFilenames = append(diskFilenames, getAttachedDisks(adapter, vmxData)...)
	}

	// Write out the relative, host filesystem paths to the disks
	var diskFullPaths []string
	for _, diskFilename := range diskFilenames {
		log.Printf("Found attached disk with filename: %s", diskFilename)
		diskFullPaths = append(diskFullPaths, filepath.Join(s.OutputDir, diskFilename))
	}

	if len(diskFullPaths) == 0 {
		state.Put("error", fmt.Errorf("Could not enumerate disk info from the vmx file"))
		return multistep.ActionHalt
	}

	// Determine the network type by reading out of the .vmx
	var networkType string
	if _, ok := vmxData["ethernet0.connectiontype"]; ok {
		networkType = vmxData["ethernet0.connectiontype"]
		log.Printf("Discovered the network type: %s", networkType)
	}
	if networkType == "" {
		networkType = "nat"
		log.Printf("Defaulting to network type: %s", networkType)
	}

	// Stash all required information in our state bag
	state.Put("vmx_path", vmxPath)
	// What disks get assigned to what key doesn't actually matter here
	// since it's unimportant to the way the disk compaction step works
	state.Put("full_disk_path", diskFullPaths[0])
	state.Put("additional_disk_paths", diskFullPaths[1:])
	state.Put("vmnetwork", networkType)

	return multistep.ActionContinue
}

func (s *StepCloneVMX) Cleanup(state multistep.StateBag) {
}

func getAttachedDisks(a vmxAdapter, data map[string]string) (attachedDisks []string) {
	// Loop over possible adapter, controller or controller channel
	for x := 0; x <= a.aAddrMax; x++ {
		// Loop over possible addresses for attached devices
		for y := 0; y <= a.dAddrMax; y++ {
			address := fmt.Sprintf("%s%d:%d.filename", a.strAddr, x, y)
			if device, _ := data[address]; filepath.Ext(device) == ".vmdk" {
				attachedDisks = append(attachedDisks, device)
			}
		}
	}
	return
}
<|endoftext|>


<commit_before>package main

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"os"
)

//Licenselist holds short and long names of licenses
type Licenselist []struct {
	Short string `json:"short"`
	Long  string `json:"long"`
}

//Licenseinfo holds information of licenses
type Licenseinfo []struct {
	Name        string `json:"name"`
	Title       string `json:"title"`
	Category    string `json:"category"`
	Source      string `json:"source"`
	Description string `json:"description"`
	Tags        struct {
		Required  []string `json:"required"`
		Permitted []string `json:"permitted"`
		Forbidden []string `json:"forbidden"`
	} `json:"tags"`
}

func check(e error) {
	if e != nil {
		panic(e)
	}
}

func help() {
	helptext := `licensethis - Choose an OSS license for your project with ease.

Usage:
licensethis help
licensethis list
licensethis info <license-name>
licensethis generate <license-name>

Commands:
help		Show this help text.
list		Show a list of all available OSS licenses.
info		Show more information for a license.
generate	Generate LICENSE.txt file in current folder after asking for author name.

Examples:
licensethis help		Show this help text.
licensethis info mit		Show more information for MIT license.
licensethis generate mit	Geneate MIT license text file in current directory.`

	fmt.Printf("%v\n", helptext)
}

func info(licensename string) {
	//fmt.Printf("%v\n", licensename[0])
	fmt.Println(licensename)
	// file, e := ioutil.ReadFile("licenses.json")
	// if e != nil {
	// 	log.Fatal(e)
	// }
	// var jsontype map[string][]map[string]interface{}
	// err := json.Unmarshal(file, &jsontype)
	// if err != nil {
	// 	log.Fatal(err)
	// }
	// //fmt.Printf("Results: %v \n", jsontype["licenses"])
	// for i := range jsontype["licenses"] {
	// 	item := jsontype["licenses"][i]
	// 	//fmt.Printf("%v\n",item["name"])
	// 	if item["name"] == licensename[0] {
	// 		fmt.Printf("%v\n%v\n%v", item["name"], item["version"], item["text"])
	// 	}
	// }
}

func list() {
	gopath := os.Getenv("GOPATH")
	licensethispath := gopath + "/src/github.com/hasit/licensethis/"
	listfilepath := licensethispath + "/licenselist.json"
	file, err := ioutil.ReadFile(listfilepath)
	check(err)

	var licenselist Licenselist
	e := json.Unmarshal(file, &licenselist)
	check(e)

	fmt.Println("List of all available OSS licenses:")
	for i := range licenselist {
		fmt.Printf("%v - %v\n", licenselist[i].Short, licenselist[i].Long)
	}
}

func generate(licensename string) {
	fmt.Println(licensename)
}

// !!---FUTURE---!!
//might have to look into a way to accept more than one license name for `info`.
func parseArgs(args []string) {
	if len(args) == 1 {
		switch args[0] {
		case "help":
			help()
		case "list":
			list()
		default:
			fmt.Println("Incorrect usage!")
			fmt.Println("Type `licensethis help` for help on proper usage.")
		}
	} else if len(args) == 2 {
		switch args[0] {
		case "info":
			info(args[1])
		case "generate":
			generate(args[1])
		default:
			fmt.Println("Incorrect usage!")
			fmt.Println("Type `licensethis help` for help on proper usage.")
		}
	} else {
		fmt.Println("Incorrect usage!")
		fmt.Println("Type `licensethis help` for help on proper usage.")
	}
}

func main() {
	args := os.Args[1:]
	parseArgs(args)
}
<commit_msg>modular function for getting path of any file<commit_after>package main

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"os"
)

//Licenselist holds short and long names of licenses
type Licenselist []struct {
	Short string `json:"short"`
	Long  string `json:"long"`
}

//Licenseinfo holds information of licenses
type Licenseinfo []struct {
	Name        string `json:"name"`
	Title       string `json:"title"`
	Category    string `json:"category"`
	Source      string `json:"source"`
	Description string `json:"description"`
	Tags        struct {
		Required  []string `json:"required"`
		Permitted []string `json:"permitted"`
		Forbidden []string `json:"forbidden"`
	} `json:"tags"`
}

func check(e error) {
	if e != nil {
		panic(e)
	}
}

func getfilepath(filename string) string {
	gopath := os.Getenv("GOPATH")
	licensethispath := gopath + "/src/github.com/hasit/licensethis/"
	filepath := licensethispath + filename

	return filepath
}

func help() {
	helptext := `licensethis - Choose an OSS license for your project with ease.

Usage:
licensethis help
licensethis list
licensethis info <license-name>
licensethis generate <license-name>

Commands:
help		Show this help text.
list		Show a list of all available OSS licenses.
info		Show more information for a license.
generate	Generate LICENSE.txt file in current folder after asking for author name.

Examples:
licensethis help		Show this help text.
licensethis info mit		Show more information for MIT license.
licensethis generate mit	Geneate MIT license text file in current directory.`

	fmt.Printf("%v\n", helptext)
}

func list() {
	listfilepath := getfilepath("licenselist.json")
	file, err1 := ioutil.ReadFile(listfilepath)
	check(err1)

	var licenselist Licenselist
	err2 := json.Unmarshal(file, &licenselist)
	check(err2)

	fmt.Println("List of all available OSS licenses:")
	for i := range licenselist {
		fmt.Printf("%d. %v - %v\n", i, licenselist[i].Short, licenselist[i].Long)
	}
}

func info(licensename string) {
	//fmt.Printf("%v\n", licensename[0])
	fmt.Println(licensename)
	// file, e := ioutil.ReadFile("licenses.json")
	// if e != nil {
	// 	log.Fatal(e)
	// }
	// var jsontype map[string][]map[string]interface{}
	// err := json.Unmarshal(file, &jsontype)
	// if err != nil {
	// 	log.Fatal(err)
	// }
	// //fmt.Printf("Results: %v \n", jsontype["licenses"])
	// for i := range jsontype["licenses"] {
	// 	item := jsontype["licenses"][i]
	// 	//fmt.Printf("%v\n",item["name"])
	// 	if item["name"] == licensename[0] {
	// 		fmt.Printf("%v\n%v\n%v", item["name"], item["version"], item["text"])
	// 	}
	// }
}

func generate(licensename string) {
	fmt.Println(licensename)
}

// !!---FUTURE---!!
//might have to look into a way to accept more than one license name for `info`.
func parseArgs(args []string) {
	if len(args) == 1 {
		switch args[0] {
		case "help":
			help()
		case "list":
			list()
		default:
			fmt.Println("Incorrect usage!")
			fmt.Println("Type `licensethis help` for help on proper usage.")
		}
	} else if len(args) == 2 {
		switch args[0] {
		case "info":
			info(args[1])
		case "generate":
			generate(args[1])
		default:
			fmt.Println("Incorrect usage!")
			fmt.Println("Type `licensethis help` for help on proper usage.")
		}
	} else {
		fmt.Println("Incorrect usage!")
		fmt.Println("Type `licensethis help` for help on proper usage.")
	}
}

func main() {
	args := os.Args[1:]
	parseArgs(args)
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"os"
	"os/exec"
	"runtime"
)

//UserInfo stores information of user
type UserInfo struct {
	First string
	Last  string
}

//Check checks for errors
func check(e error) {
	if e != nil {
		panic(e)
	}
}

//printHelp opens project page (http://hasit.github.io/licensethis/) in the default browser.
func printHelp() {
	var err error
	switch runtime.GOOS {
	case "linux":
		err = exec.Command("xdg-open", "http://hasit.github.io/licensethis/").Start()
		check(err)
	case "windows", "darwin":
		err = exec.Command("open", "http://hasit.github.io/licensethis/").Start()
		check(err)
	default:
		err = fmt.Errorf("unsupported platform")
		check(err)
	}
}

func userConfig() {
	first := os.Getenv("FIRSTNAME")
	last := os.Getenv("LASTNAME")

	//if first != nil; last != nil {
	fmt.Printf("First: %v\n", first)
	fmt.Printf("Last: %v\n", last)
	//}
}

//parseArgs parses command line arguments and calls appropriate functions.
func parseArgs(args []string) {
	if len(args) != 0 {
		switch args[0] {
		case "help":
			printHelp()
		case "config":
			userConfig()
		case "info":
			fmt.Println("info")
		case "list":
			fmt.Println("list")
		case "generate":
			fmt.Println("generate")
		default:
			fmt.Println("Incorrect usage!")
			fmt.Println("Type `licensethis help` for help on proper usage.")
		}
	} else {
		fmt.Println("Incorrect usage!")
		fmt.Println("Type `licensethis help` for help on proper usage.")
	}
}

func main() {
	args := os.Args[1:]

	parseArgs(args)
}
<commit_msg>help : Replace redirect to gh readme with stdout text<commit_after>package main

import (
	"fmt"
	"os"
)

//UserInfo stores information of user
type UserInfo struct {
	First string
	Last  string
}

//Check checks for errors
func check(e error) {
	if e != nil {
		panic(e)
	}
}

//printHelp opens project page (http://hasit.github.io/licensethis/) in the default browser.
func printHelp() {
	helptext:=`
# licensethis
Add an OSS license to your project.

### SYNOPSIS

licensethis <option> <license-name>
licensethis help
licensethis config
licensethis list
licensethis info license-name
licensethis generate license-name

DESCRIPTION

licensethis lets you add an OSS license to your project with ease.

OPTIONS

These options let you do a variety of things.

  * help
	Open project page in the default browser. This provides more information on usage of licensethis with detailed information about each option.
  * config
	Configure user's full name for generating license files. User will be prompted to enter their full name for the first time. This information is stored in a JSON file at *~/.config/licensethis/user.json*.
  * list
	List all OSS licenses available on *http://choosealicense.com/*. This only prints a list of licenses with no more information. This could serve as a quick preview of all available licenses to choose from.
  * info license-name
	Get more information for <license-name>. This prints a synopsis of the license, tags (required, permitted, forbidden) associated to the license and a link to *http://choosealicense.com/licenses/<license-name>*.
  * generate license-name
	Generate <license-name> license for your project. This generates a LICENSE.txt file in your current directory with YEAR and FULLNAME already filled in. It picks up the name from config file automatically.

## CONTRIBUTORS
* Hasit Mistry
	Personal: [hasit.github.io](http://hasit.github.io/)
	Github: [hasit](https://github.com/hasit)
* Anuj Deshpande
	Personal: [anujdeshpande.com](http://www.anujdeshpande.com/)
	Github: [anujdeshpande](https://github.com/anujdeshpande/)`
	fmt.Printf("%v",helptext)
}

func userConfig() {
	first := os.Getenv("FIRSTNAME")
	last := os.Getenv("LASTNAME")

	//if first != nil; last != nil {
	fmt.Printf("First: %v\n", first)
	fmt.Printf("Last: %v\n", last)
	//}
}

//parseArgs parses command line arguments and calls appropriate functions.
func parseArgs(args []string) {
	if len(args) != 0 {
		switch args[0] {
		case "help":
			printHelp()
		case "config":
			userConfig()
		case "info":
			fmt.Println("info")
		case "list":
			fmt.Println("list")
		case "generate":
			fmt.Println("generate")
		default:
			fmt.Println("Incorrect usage!")
			fmt.Println("Type `licensethis help` for help on proper usage.")
		}
	} else {
		fmt.Println("Incorrect usage!")
		fmt.Println("Type `licensethis help` for help on proper usage.")
	}
}

func main() {
	args := os.Args[1:]

	parseArgs(args)
}
<|endoftext|>


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

// This package implements a basic LISP interpretor for embedding in a go program for scripting.
// This file implements data elements.

package golisp

// Cxr

func WalkList(d *Data, path string) *Data {
	c := d
	for index := len(path) - 1; index >= 0; index-- {
		if c == nil {
			return nil
		}
		if !PairP(c) && !AlistP(c) && !DottedPairP(c) {
			return nil
		}
		switch path[index] {
		case 'a':
			c = Car(c)
		case 'd':
			c = Cdr(c)
		default:
			c = nil
		}
	}
	return c
}

func Car(d *Data) *Data {
	if d == nil {
		return nil
	}

	if PairP(d) || AlistP(d) || DottedPairP(d) {
		return d.Car
	}

	return nil
}

func Cdr(d *Data) *Data {
	if d == nil {
		return nil
	}

	if PairP(d) || AlistP(d) || DottedPairP(d) {
		return d.Cdr
	}

	return nil
}

// Cxxr

func Caar(d *Data) *Data {
	return WalkList(d, "aa")
}

func Cadr(d *Data) *Data {
	return WalkList(d, "ad")
}

func Cdar(d *Data) *Data {
	return WalkList(d, "da")
}

func Cddr(d *Data) *Data {
	return WalkList(d, "dd")
}

// nth

func Nth(d *Data, n int) *Data {
	if d == nil || n < 1 || n > Length(d) {
		return nil
	}

	var c *Data = d
	for i := n; i > 1; c, i = Cdr(c), i-1 {
	}
	return Car(c)
}

func First(d *Data) *Data {
	return Nth(d, 1)
}

func Second(d *Data) *Data {
	return Nth(d, 2)
}

func Third(d *Data) *Data {
	return Nth(d, 3)
}

func Fourth(d *Data) *Data {
	return Nth(d, 4)
}

func Fifth(d *Data) *Data {
	return Nth(d, 5)
}

func Sixth(d *Data) *Data {
	return Nth(d, 6)
}

func Seventh(d *Data) *Data {
	return Nth(d, 7)
}

func Eighth(d *Data) *Data {
	return Nth(d, 8)
}

func Ninth(d *Data) *Data {
	return Nth(d, 9)
}

func Tenth(d *Data) *Data {
	return Nth(d, 10)
}
<commit_msg>Added Cxxxr functions back<commit_after>// Copyright 2014 SteelSeries ApS.  All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// This package implements a basic LISP interpretor for embedding in a go program for scripting.
// This file implements data elements.

package golisp

// Cxr

func WalkList(d *Data, path string) *Data {
	c := d
	for index := len(path) - 1; index >= 0; index-- {
		if c == nil {
			return nil
		}
		if !PairP(c) && !AlistP(c) && !DottedPairP(c) {
			return nil
		}
		switch path[index] {
		case 'a':
			c = Car(c)
		case 'd':
			c = Cdr(c)
		default:
			c = nil
		}
	}
	return c
}

func Car(d *Data) *Data {
	if d == nil {
		return nil
	}

	if PairP(d) || AlistP(d) || DottedPairP(d) {
		return d.Car
	}

	return nil
}

func Cdr(d *Data) *Data {
	if d == nil {
		return nil
	}

	if PairP(d) || AlistP(d) || DottedPairP(d) {
		return d.Cdr
	}

	return nil
}

// Cxxr

func Caar(d *Data) *Data {
	return WalkList(d, "aa")
}

func Cadr(d *Data) *Data {
	return WalkList(d, "ad")
}

func Cdar(d *Data) *Data {
	return WalkList(d, "da")
}

func Cddr(d *Data) *Data {
	return WalkList(d, "dd")
}

// Cxxxr

func Caaar(d *Data) *Data {
	return WalkList(d, "aaa")
}

func Caadr(d *Data) *Data {
	return WalkList(d, "aad")
}

func Cadar(d *Data) *Data {
	return WalkList(d, "ada")
}

func Caddr(d *Data) *Data {
	return WalkList(d, "add")
}

func Cdaar(d *Data) *Data {
	return WalkList(d, "daa")
}

func Cdadr(d *Data) *Data {
	return WalkList(d, "dad")
}

func Cddar(d *Data) *Data {
	return WalkList(d, "dda")
}

func Cdddr(d *Data) *Data {
	return WalkList(d, "ddd")
}

// nth

func Nth(d *Data, n int) *Data {
	if d == nil || n < 1 || n > Length(d) {
		return nil
	}

	var c *Data = d
	for i := n; i > 1; c, i = Cdr(c), i-1 {
	}
	return Car(c)
}

func First(d *Data) *Data {
	return Nth(d, 1)
}

func Second(d *Data) *Data {
	return Nth(d, 2)
}

func Third(d *Data) *Data {
	return Nth(d, 3)
}

func Fourth(d *Data) *Data {
	return Nth(d, 4)
}

func Fifth(d *Data) *Data {
	return Nth(d, 5)
}

func Sixth(d *Data) *Data {
	return Nth(d, 6)
}

func Seventh(d *Data) *Data {
	return Nth(d, 7)
}

func Eighth(d *Data) *Data {
	return Nth(d, 8)
}

func Ninth(d *Data) *Data {
	return Nth(d, 9)
}

func Tenth(d *Data) *Data {
	return Nth(d, 10)
}
<|endoftext|>


<commit_before>// compile

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

// This file contains the code snippets included in "Error Handling and Go."

package main

import (
	"net/http"
	"text/template"
)

type appError struct {
	Error   error
	Message string
	Code    int
}

// STOP OMIT

type appHandler func(http.ResponseWriter, *http.Request) *appError

func (fn appHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	if e := fn(w, r); e != nil { // e is *appError, not os.Error.
		c := appengine.NewContext(r)
		c.Errorf("%v", e.Error)
		http.Error(w, e.Message, e.Code)
	}
}

// STOP OMIT

func viewRecord(w http.ResponseWriter, r *http.Request) *appError {
	c := appengine.NewContext(r)
	key := datastore.NewKey(c, "Record", r.FormValue("id"), 0, nil)
	record := new(Record)
	if err := datastore.Get(c, key, record); err != nil {
		return &appError{err, "Record not found", 404}
	}
	if err := viewTemplate.Execute(w, record); err != nil {
		return &appError{err, "Can't display record", 500}
	}
	return nil
}

// STOP OMIT

func init() {
	http.Handle("/view", appHandler(viewRecord))
}

type ap struct{}

func (ap) NewContext(*http.Request) *ctx { return nil }

type ctx struct{}

func (*ctx) Errorf(string, ...interface{}) {}

var appengine ap

type ds struct{}

func (ds) NewKey(*ctx, string, string, int, *int) string { return "" }
func (ds) Get(*ctx, string, *Record) error               { return nil }

var datastore ds

type Record struct{}

var viewTemplate *template.Template

func main() {}
<commit_msg>doc/articles/error_handling: no more os.Error<commit_after>// compile

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

// This file contains the code snippets included in "Error Handling and Go."

package main

import (
	"net/http"
	"text/template"
)

type appError struct {
	Error   error
	Message string
	Code    int
}

// STOP OMIT

type appHandler func(http.ResponseWriter, *http.Request) *appError

func (fn appHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	if e := fn(w, r); e != nil { // e is *appError, not error.
		c := appengine.NewContext(r)
		c.Errorf("%v", e.Error)
		http.Error(w, e.Message, e.Code)
	}
}

// STOP OMIT

func viewRecord(w http.ResponseWriter, r *http.Request) *appError {
	c := appengine.NewContext(r)
	key := datastore.NewKey(c, "Record", r.FormValue("id"), 0, nil)
	record := new(Record)
	if err := datastore.Get(c, key, record); err != nil {
		return &appError{err, "Record not found", 404}
	}
	if err := viewTemplate.Execute(w, record); err != nil {
		return &appError{err, "Can't display record", 500}
	}
	return nil
}

// STOP OMIT

func init() {
	http.Handle("/view", appHandler(viewRecord))
}

type ap struct{}

func (ap) NewContext(*http.Request) *ctx { return nil }

type ctx struct{}

func (*ctx) Errorf(string, ...interface{}) {}

var appengine ap

type ds struct{}

func (ds) NewKey(*ctx, string, string, int, *int) string { return "" }
func (ds) Get(*ctx, string, *Record) error               { return nil }

var datastore ds

type Record struct{}

var viewTemplate *template.Template

func main() {}
<|endoftext|>