<commit_before>// Copyright 2014 Hajime Hoshi
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package graphics

import (
	"fmt"

	"github.com/hajimehoshi/ebiten/internal/graphics/opengl"
)

type openGLState struct {
	indexBufferQuads opengl.Buffer
	programTexture   opengl.Program

	lastProgram                opengl.Program
	lastProjectionMatrix       []float32
	lastModelviewMatrix        []float32
	lastColorMatrix            []float32
	lastColorMatrixTranslation []float32
}

var theOpenGLState openGLState

const (
	indicesNum = 1 << 16
	MaxQuads   = indicesNum / 6
)

// unsafe.SizeOf can't be used because unsafe doesn't work with GopherJS.
const (
	int16Size   = 2
	float32Size = 4
)

func Initialize(c *opengl.Context) error {
	return theOpenGLState.initialize(c)
}

func Finalize(c *opengl.Context) error {
	return theOpenGLState.finalize(c)
}

func (s *openGLState) initialize(c *opengl.Context) error {
	var zeroProgram opengl.Program
	s.lastProgram = zeroProgram
	s.lastProjectionMatrix = nil
	s.lastModelviewMatrix = nil
	s.lastColorMatrix = nil
	s.lastColorMatrixTranslation = nil

	shaderVertexModelviewNative, err := c.NewShader(c.VertexShader, shader(c, shaderVertexModelview))
	if err != nil {
		panic(fmt.Sprintf("graphics: shader compiling error:\n%s", err))
	}
	defer c.DeleteShader(shaderVertexModelviewNative)

	shaderFragmentTextureNative, err := c.NewShader(c.FragmentShader, shader(c, shaderFragmentTexture))
	if err != nil {
		panic(fmt.Sprintf("graphics: shader compiling error:\n%s", err))
	}
	defer c.DeleteShader(shaderFragmentTextureNative)

	s.programTexture, err = c.NewProgram([]opengl.Shader{
		shaderVertexModelviewNative,
		shaderFragmentTextureNative,
	})
	if err != nil {
		return err
	}

	const stride = 8 // (2 [vertices] + 2 [texels]) * 2 [sizeof(int16)/bytes]
	c.NewBuffer(c.ArrayBuffer, 4*stride*MaxQuads, c.DynamicDraw)

	indices := make([]uint16, 6*MaxQuads)
	for i := uint16(0); i < MaxQuads; i++ {
		indices[6*i+0] = 4*i + 0
		indices[6*i+1] = 4*i + 1
		indices[6*i+2] = 4*i + 2
		indices[6*i+3] = 4*i + 1
		indices[6*i+4] = 4*i + 2
		indices[6*i+5] = 4*i + 3
	}
	s.indexBufferQuads = c.NewBuffer(c.ElementArrayBuffer, indices, c.StaticDraw)

	return nil
}

func (s *openGLState) finalize(c *opengl.Context) error {
	var zeroProgram opengl.Program
	s.lastProgram = zeroProgram
	s.lastProjectionMatrix = nil
	s.lastModelviewMatrix = nil
	s.lastColorMatrix = nil
	s.lastColorMatrixTranslation = nil
	c.DeleteBuffer(s.indexBufferQuads)
	c.DeleteProgram(s.programTexture)
	return nil
}

func areSameFloat32Array(a, b []float32) bool {
	if len(a) != len(b) {
		return false
	}
	for i := 0; i < len(a); i++ {
		if a[i] != b[i] {
			return false
		}
	}
	return true
}

type programContext struct {
	state            *openGLState
	program          opengl.Program
	context          *opengl.Context
	projectionMatrix []float32
	texture          opengl.Texture
	geoM             Matrix
	colorM           Matrix
}

func (p *programContext) begin() {
	c := p.context
	if p.state.lastProgram != p.program {
		c.UseProgram(p.program)
		var zeroProgram opengl.Program
		if p.state.lastProgram != zeroProgram {
			c.DisableVertexAttribArray(p.state.lastProgram, "tex_coord")
			c.DisableVertexAttribArray(p.state.lastProgram, "vertex")
		}
		c.EnableVertexAttribArray(p.program, "vertex")
		c.EnableVertexAttribArray(p.program, "tex_coord")
		c.VertexAttribPointer(p.program, "vertex", false, int16Size*4, 2, int16Size*0)
		c.VertexAttribPointer(p.program, "tex_coord", true, int16Size*4, 2, int16Size*2)

		p.state.lastProgram = p.state.programTexture
		p.state.lastProjectionMatrix = nil
		p.state.lastModelviewMatrix = nil
		p.state.lastColorMatrix = nil
		p.state.lastColorMatrixTranslation = nil
	}
	c.BindElementArrayBuffer(p.state.indexBufferQuads)

	if !areSameFloat32Array(p.state.lastProjectionMatrix, p.projectionMatrix) {
		c.UniformFloats(p.program, "projection_matrix", p.projectionMatrix)
		if p.state.lastProjectionMatrix == nil {
			p.state.lastProjectionMatrix = make([]float32, 16)
		}
		copy(p.state.lastProjectionMatrix, p.projectionMatrix)
	}

	ma := float32(p.geoM.Element(0, 0))
	mb := float32(p.geoM.Element(0, 1))
	mc := float32(p.geoM.Element(1, 0))
	md := float32(p.geoM.Element(1, 1))
	tx := float32(p.geoM.Element(0, 2))
	ty := float32(p.geoM.Element(1, 2))
	modelviewMatrix := []float32{
		ma, mc, 0, 0,
		mb, md, 0, 0,
		0, 0, 1, 0,
		tx, ty, 0, 1,
	}
	if !areSameFloat32Array(p.state.lastModelviewMatrix, modelviewMatrix) {
		c.UniformFloats(p.program, "modelview_matrix", modelviewMatrix)
		if p.state.lastModelviewMatrix == nil {
			p.state.lastModelviewMatrix = make([]float32, 16)
		}
		copy(p.state.lastModelviewMatrix, modelviewMatrix)
	}

	c.UniformInt(p.program, "texture", 0)

	e := [4][5]float32{}
	for i := 0; i < 4; i++ {
		for j := 0; j < 5; j++ {
			e[i][j] = float32(p.colorM.Element(i, j))
		}
	}

	colorMatrix := []float32{
		e[0][0], e[1][0], e[2][0], e[3][0],
		e[0][1], e[1][1], e[2][1], e[3][1],
		e[0][2], e[1][2], e[2][2], e[3][2],
		e[0][3], e[1][3], e[2][3], e[3][3],
	}
	if !areSameFloat32Array(p.state.lastColorMatrix, colorMatrix) {
		c.UniformFloats(p.program, "color_matrix", colorMatrix)
		if p.state.lastColorMatrix == nil {
			p.state.lastColorMatrix = make([]float32, 16)
		}
		copy(p.state.lastColorMatrix, colorMatrix)
	}
	colorMatrixTranslation := []float32{
		e[0][4], e[1][4], e[2][4], e[3][4],
	}
	if !areSameFloat32Array(p.state.lastColorMatrixTranslation, colorMatrixTranslation) {
		c.UniformFloats(p.program, "color_matrix_translation", colorMatrixTranslation)
		if p.state.lastColorMatrixTranslation == nil {
			p.state.lastColorMatrixTranslation = make([]float32, 4)
		}
		copy(p.state.lastColorMatrixTranslation, colorMatrixTranslation)
	}

	// We don't have to call gl.ActiveTexture here: GL_TEXTURE0 is the default active texture
	// See also: https://www.opengl.org/sdk/docs/man2/xhtml/glActiveTexture.xml
	c.BindTexture(p.texture)
}

func (p *programContext) end() {

}
<commit_msg>grahics: Reduce gl function calls<commit_after>// Copyright 2014 Hajime Hoshi
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package graphics

import (
	"fmt"

	"github.com/hajimehoshi/ebiten/internal/graphics/opengl"
)

type openGLState struct {
	indexBufferQuads opengl.Buffer
	programTexture   opengl.Program

	lastProgram                opengl.Program
	lastProjectionMatrix       []float32
	lastModelviewMatrix        []float32
	lastColorMatrix            []float32
	lastColorMatrixTranslation []float32
}

var theOpenGLState openGLState

const (
	indicesNum = 1 << 16
	MaxQuads   = indicesNum / 6
)

// unsafe.SizeOf can't be used because unsafe doesn't work with GopherJS.
const (
	int16Size   = 2
	float32Size = 4
)

func Initialize(c *opengl.Context) error {
	return theOpenGLState.initialize(c)
}

func Finalize(c *opengl.Context) error {
	return theOpenGLState.finalize(c)
}

func (s *openGLState) initialize(c *opengl.Context) error {
	var zeroProgram opengl.Program
	s.lastProgram = zeroProgram
	s.lastProjectionMatrix = nil
	s.lastModelviewMatrix = nil
	s.lastColorMatrix = nil
	s.lastColorMatrixTranslation = nil

	shaderVertexModelviewNative, err := c.NewShader(c.VertexShader, shader(c, shaderVertexModelview))
	if err != nil {
		panic(fmt.Sprintf("graphics: shader compiling error:\n%s", err))
	}
	defer c.DeleteShader(shaderVertexModelviewNative)

	shaderFragmentTextureNative, err := c.NewShader(c.FragmentShader, shader(c, shaderFragmentTexture))
	if err != nil {
		panic(fmt.Sprintf("graphics: shader compiling error:\n%s", err))
	}
	defer c.DeleteShader(shaderFragmentTextureNative)

	s.programTexture, err = c.NewProgram([]opengl.Shader{
		shaderVertexModelviewNative,
		shaderFragmentTextureNative,
	})
	if err != nil {
		return err
	}

	const stride = 8 // (2 [vertices] + 2 [texels]) * 2 [sizeof(int16)/bytes]
	c.NewBuffer(c.ArrayBuffer, 4*stride*MaxQuads, c.DynamicDraw)

	indices := make([]uint16, 6*MaxQuads)
	for i := uint16(0); i < MaxQuads; i++ {
		indices[6*i+0] = 4*i + 0
		indices[6*i+1] = 4*i + 1
		indices[6*i+2] = 4*i + 2
		indices[6*i+3] = 4*i + 1
		indices[6*i+4] = 4*i + 2
		indices[6*i+5] = 4*i + 3
	}
	s.indexBufferQuads = c.NewBuffer(c.ElementArrayBuffer, indices, c.StaticDraw)

	return nil
}

func (s *openGLState) finalize(c *opengl.Context) error {
	var zeroProgram opengl.Program
	s.lastProgram = zeroProgram
	s.lastProjectionMatrix = nil
	s.lastModelviewMatrix = nil
	s.lastColorMatrix = nil
	s.lastColorMatrixTranslation = nil
	c.DeleteBuffer(s.indexBufferQuads)
	c.DeleteProgram(s.programTexture)
	return nil
}

func areSameFloat32Array(a, b []float32) bool {
	if len(a) != len(b) {
		return false
	}
	for i := 0; i < len(a); i++ {
		if a[i] != b[i] {
			return false
		}
	}
	return true
}

type programContext struct {
	state            *openGLState
	program          opengl.Program
	context          *opengl.Context
	projectionMatrix []float32
	texture          opengl.Texture
	geoM             Matrix
	colorM           Matrix
}

func (p *programContext) begin() {
	c := p.context
	if p.state.lastProgram != p.program {
		c.UseProgram(p.program)
		var zeroProgram opengl.Program
		if p.state.lastProgram != zeroProgram {
			c.DisableVertexAttribArray(p.state.lastProgram, "tex_coord")
			c.DisableVertexAttribArray(p.state.lastProgram, "vertex")
		}
		c.EnableVertexAttribArray(p.program, "vertex")
		c.EnableVertexAttribArray(p.program, "tex_coord")
		c.VertexAttribPointer(p.program, "vertex", false, int16Size*4, 2, int16Size*0)
		c.VertexAttribPointer(p.program, "tex_coord", true, int16Size*4, 2, int16Size*2)

		p.state.lastProgram = p.state.programTexture
		p.state.lastProjectionMatrix = nil
		p.state.lastModelviewMatrix = nil
		p.state.lastColorMatrix = nil
		p.state.lastColorMatrixTranslation = nil
		c.BindElementArrayBuffer(p.state.indexBufferQuads)
		c.UniformInt(p.program, "texture", 0)
	}

	if !areSameFloat32Array(p.state.lastProjectionMatrix, p.projectionMatrix) {
		c.UniformFloats(p.program, "projection_matrix", p.projectionMatrix)
		if p.state.lastProjectionMatrix == nil {
			p.state.lastProjectionMatrix = make([]float32, 16)
		}
		copy(p.state.lastProjectionMatrix, p.projectionMatrix)
	}

	ma := float32(p.geoM.Element(0, 0))
	mb := float32(p.geoM.Element(0, 1))
	mc := float32(p.geoM.Element(1, 0))
	md := float32(p.geoM.Element(1, 1))
	tx := float32(p.geoM.Element(0, 2))
	ty := float32(p.geoM.Element(1, 2))
	modelviewMatrix := []float32{
		ma, mc, 0, 0,
		mb, md, 0, 0,
		0, 0, 1, 0,
		tx, ty, 0, 1,
	}
	if !areSameFloat32Array(p.state.lastModelviewMatrix, modelviewMatrix) {
		c.UniformFloats(p.program, "modelview_matrix", modelviewMatrix)
		if p.state.lastModelviewMatrix == nil {
			p.state.lastModelviewMatrix = make([]float32, 16)
		}
		copy(p.state.lastModelviewMatrix, modelviewMatrix)
	}

	e := [4][5]float32{}
	for i := 0; i < 4; i++ {
		for j := 0; j < 5; j++ {
			e[i][j] = float32(p.colorM.Element(i, j))
		}
	}

	colorMatrix := []float32{
		e[0][0], e[1][0], e[2][0], e[3][0],
		e[0][1], e[1][1], e[2][1], e[3][1],
		e[0][2], e[1][2], e[2][2], e[3][2],
		e[0][3], e[1][3], e[2][3], e[3][3],
	}
	if !areSameFloat32Array(p.state.lastColorMatrix, colorMatrix) {
		c.UniformFloats(p.program, "color_matrix", colorMatrix)
		if p.state.lastColorMatrix == nil {
			p.state.lastColorMatrix = make([]float32, 16)
		}
		copy(p.state.lastColorMatrix, colorMatrix)
	}
	colorMatrixTranslation := []float32{
		e[0][4], e[1][4], e[2][4], e[3][4],
	}
	if !areSameFloat32Array(p.state.lastColorMatrixTranslation, colorMatrixTranslation) {
		c.UniformFloats(p.program, "color_matrix_translation", colorMatrixTranslation)
		if p.state.lastColorMatrixTranslation == nil {
			p.state.lastColorMatrixTranslation = make([]float32, 4)
		}
		copy(p.state.lastColorMatrixTranslation, colorMatrixTranslation)
	}

	// We don't have to call gl.ActiveTexture here: GL_TEXTURE0 is the default active texture
	// See also: https://www.opengl.org/sdk/docs/man2/xhtml/glActiveTexture.xml
	c.BindTexture(p.texture)
}

func (p *programContext) end() {
}
<|endoftext|>


<commit_before>package protocol

import (
	"context"
	"fmt"
	"io"
	"strings"
	"sync"
	"time"

	"golang.org/x/tools/internal/jsonrpc2"
)

type loggingStream struct {
	stream jsonrpc2.Stream
	logMu  sync.Mutex
	log    io.Writer
}

// LoggingStream returns a stream that does LSP protocol logging too
func LoggingStream(str jsonrpc2.Stream, w io.Writer) jsonrpc2.Stream {
	return &loggingStream{stream: str, log: w}
}

func (s *loggingStream) Read(ctx context.Context) (jsonrpc2.Message, int64, error) {
	msg, count, err := s.stream.Read(ctx)
	if err == nil {
		s.logMu.Lock()
		defer s.logMu.Unlock()
		logCommon(s.log, msg, true)
	}
	return msg, count, err
}

func (s *loggingStream) Write(ctx context.Context, msg jsonrpc2.Message) (int64, error) {
	s.logMu.Lock()
	defer s.logMu.Unlock()
	logCommon(s.log, msg, false)
	count, err := s.stream.Write(ctx, msg)
	return count, err
}

type req struct {
	method string
	start  time.Time
}

type mapped struct {
	mu          sync.Mutex
	clientCalls map[string]req
	serverCalls map[string]req
}

var maps = &mapped{
	sync.Mutex{},
	make(map[string]req),
	make(map[string]req),
}

// these 4 methods are each used exactly once, but it seemed
// better to have the encapsulation rather than ad hoc mutex
// code in 4 places
func (m *mapped) client(id string) req {
	m.mu.Lock()
	defer m.mu.Unlock()
	v := m.clientCalls[id]
	delete(m.clientCalls, id)
	return v
}

func (m *mapped) server(id string) req {
	m.mu.Lock()
	defer m.mu.Unlock()
	v := m.serverCalls[id]
	delete(m.serverCalls, id)
	return v
}

func (m *mapped) setClient(id string, r req) {
	m.mu.Lock()
	defer m.mu.Unlock()
	m.clientCalls[id] = r
}

func (m *mapped) setServer(id string, r req) {
	m.mu.Lock()
	defer m.mu.Unlock()
	m.serverCalls[id] = r
}

const eor = "\r\n\r\n\r\n"

func logCommon(outfd io.Writer, msg jsonrpc2.Message, isRead bool) {
	direction, pastTense := "Received", "Received"
	get, set := maps.client, maps.setServer
	if isRead {
		direction, pastTense = "Sending", "Sent"
		get, set = maps.server, maps.setClient
	}
	if msg == nil || outfd == nil {
		return
	}
	tm := time.Now()
	tmfmt := tm.Format("15:04:05.000 PM")

	buf := strings.Builder{}
	fmt.Fprintf(&buf, "[Trace - %s] ", tmfmt) // common beginning
	switch msg := msg.(type) {
	case *jsonrpc2.Call:
		id := fmt.Sprint(msg.ID())
		fmt.Fprintf(&buf, "%s request '%s - (%s)'.\n", direction, msg.Method(), id)
		fmt.Fprintf(&buf, "Params: %s%s", msg.Params(), eor)
		set(id, req{method: msg.Method(), start: tm})
	case *jsonrpc2.Notification:
		fmt.Fprintf(&buf, "%s notification '%s'.\n", direction, msg.Method())
		fmt.Fprintf(&buf, "Params: %s%s", msg.Params(), eor)
	case *jsonrpc2.Response:
		id := fmt.Sprint(msg.ID())
		if err := msg.Err(); err != nil {
			fmt.Fprintf(outfd, "[Error - %s] %s #%s %s%s", pastTense, tmfmt, id, err, eor)
			return
		}
		cc := get(id)
		elapsed := tm.Sub(cc.start)
		fmt.Fprintf(&buf, "%s response '%s - (%s)' in %dms.\n",
			direction, cc.method, id, elapsed/time.Millisecond)
		fmt.Fprintf(&buf, "Result: %s%s", msg.Result(), eor)
	}
	outfd.Write([]byte(buf.String()))
}
<commit_msg>internal/jsonrpc2: move the lock into logCommon<commit_after>package protocol

import (
	"context"
	"fmt"
	"io"
	"strings"
	"sync"
	"time"

	"golang.org/x/tools/internal/jsonrpc2"
)

type loggingStream struct {
	stream jsonrpc2.Stream
	logMu  sync.Mutex
	log    io.Writer
}

// LoggingStream returns a stream that does LSP protocol logging too
func LoggingStream(str jsonrpc2.Stream, w io.Writer) jsonrpc2.Stream {
	return &loggingStream{stream: str, log: w}
}

func (s *loggingStream) Read(ctx context.Context) (jsonrpc2.Message, int64, error) {
	msg, count, err := s.stream.Read(ctx)
	if err == nil {
		s.logCommon(msg, true)
	}
	return msg, count, err
}

func (s *loggingStream) Write(ctx context.Context, msg jsonrpc2.Message) (int64, error) {
	s.logCommon(msg, false)
	count, err := s.stream.Write(ctx, msg)
	return count, err
}

type req struct {
	method string
	start  time.Time
}

type mapped struct {
	mu          sync.Mutex
	clientCalls map[string]req
	serverCalls map[string]req
}

var maps = &mapped{
	sync.Mutex{},
	make(map[string]req),
	make(map[string]req),
}

// these 4 methods are each used exactly once, but it seemed
// better to have the encapsulation rather than ad hoc mutex
// code in 4 places
func (m *mapped) client(id string) req {
	m.mu.Lock()
	defer m.mu.Unlock()
	v := m.clientCalls[id]
	delete(m.clientCalls, id)
	return v
}

func (m *mapped) server(id string) req {
	m.mu.Lock()
	defer m.mu.Unlock()
	v := m.serverCalls[id]
	delete(m.serverCalls, id)
	return v
}

func (m *mapped) setClient(id string, r req) {
	m.mu.Lock()
	defer m.mu.Unlock()
	m.clientCalls[id] = r
}

func (m *mapped) setServer(id string, r req) {
	m.mu.Lock()
	defer m.mu.Unlock()
	m.serverCalls[id] = r
}

const eor = "\r\n\r\n\r\n"

func (s *loggingStream) logCommon(msg jsonrpc2.Message, isRead bool) {
	s.logMu.Lock()
	defer s.logMu.Unlock()
	direction, pastTense := "Received", "Received"
	get, set := maps.client, maps.setServer
	if isRead {
		direction, pastTense = "Sending", "Sent"
		get, set = maps.server, maps.setClient
	}
	if msg == nil || s.log == nil {
		return
	}
	tm := time.Now()
	tmfmt := tm.Format("15:04:05.000 PM")

	buf := strings.Builder{}
	fmt.Fprintf(&buf, "[Trace - %s] ", tmfmt) // common beginning
	switch msg := msg.(type) {
	case *jsonrpc2.Call:
		id := fmt.Sprint(msg.ID())
		fmt.Fprintf(&buf, "%s request '%s - (%s)'.\n", direction, msg.Method(), id)
		fmt.Fprintf(&buf, "Params: %s%s", msg.Params(), eor)
		set(id, req{method: msg.Method(), start: tm})
	case *jsonrpc2.Notification:
		fmt.Fprintf(&buf, "%s notification '%s'.\n", direction, msg.Method())
		fmt.Fprintf(&buf, "Params: %s%s", msg.Params(), eor)
	case *jsonrpc2.Response:
		id := fmt.Sprint(msg.ID())
		if err := msg.Err(); err != nil {
			fmt.Fprintf(s.log, "[Error - %s] %s #%s %s%s", pastTense, tmfmt, id, err, eor)
			return
		}
		cc := get(id)
		elapsed := tm.Sub(cc.start)
		fmt.Fprintf(&buf, "%s response '%s - (%s)' in %dms.\n",
			direction, cc.method, id, elapsed/time.Millisecond)
		fmt.Fprintf(&buf, "Result: %s%s", msg.Result(), eor)
	}
	s.log.Write([]byte(buf.String()))
}
<|endoftext|>


<commit_before>package testutil

import (
	"io"

	"github.com/stretchr/testify/assert"
	"github.com/stretchr/testify/require"
)

// ErrorContains checks that the error is not nil, and contains the expected
// substring.
func ErrorContains(t require.TestingT, err error, expectedError string, msgAndArgs ...interface{}) {
	require.Error(t, err, msgAndArgs...)
	assert.Contains(t, err.Error(), expectedError, msgAndArgs...)
}

// DevZero acts like /dev/zero but in an OS-independent fashion.
var DevZero io.Reader = devZero{}

type devZero struct{}

func (d devZero) Read(p []byte) (n int, err error) {
	for i := 0; i < len(p); i++ {
		p[i] = '\x00'
	}
	return len(p), nil
}
<commit_msg>TestImportExtremelyLargeImageWorks: optimize DevZero<commit_after>package testutil

import (
	"io"

	"github.com/stretchr/testify/assert"
	"github.com/stretchr/testify/require"
)

// ErrorContains checks that the error is not nil, and contains the expected
// substring.
func ErrorContains(t require.TestingT, err error, expectedError string, msgAndArgs ...interface{}) {
	require.Error(t, err, msgAndArgs...)
	assert.Contains(t, err.Error(), expectedError, msgAndArgs...)
}

// DevZero acts like /dev/zero but in an OS-independent fashion.
var DevZero io.Reader = devZero{}

type devZero struct{}

func (d devZero) Read(p []byte) (n int, err error) {
	for i := range p {
		p[i] = 0
	}
	return len(p), nil
}
<|endoftext|>


<commit_before>// Copyright 2016 Factom Foundation
// Use of this source code is governed by the MIT
// license that can be found in the LICENSE file.

package factom

import (
	"encoding/json"
)

func GetReceipt(hash string) (*Receipt, error) {
	type receiptResponse struct {
		Receipt *Receipt `json:"receipt"`
	}

	params := hashRequest{Hash: hash}
	req := NewJSON2Request("receipt", APICounter(), params)
	resp, err := factomdRequest(req)
	if err != nil {
		return nil, err
	}
	if resp.Error != nil {
		return nil, resp.Error
	}

	rec := new(receiptResponse)
	if err := json.Unmarshal(resp.JSONResult(), rec); err != nil {
		return nil, err
	}

	return rec.Receipt, nil
}

type Receipt struct {
	Entry struct {
		Raw       string `json:"raw,omitempty"`
		EntryHash string `json:"entryhash,omitempty"`
		Json      string `json:"json,omitempty"`
	} `json:"entry,omitempty"`
	MerkleBranch []struct {
		Left  string `json:"left,omitempty"`
		Right string `json:"right,omitempty"`
		Top   string `json:"top,omitempty"`
	} `json:"merklebranch,omitempty"`
	EntryBlockKeyMR        string `json:"entryblockkeymr,omitempty"`
	DirectoryBlockKeyMR    string `json:"directoryblockkeymr,omitempty"`
	BitcoinTransactionHash string `json:"bitcointransactionhash,omitempty"`
	BitcoinBlockHash       string `json:"bitcoinblockhash,omitempty"`
}
<commit_msg>small code move for reciept<commit_after>// Copyright 2016 Factom Foundation
// Use of this source code is governed by the MIT
// license that can be found in the LICENSE file.

package factom

import (
	"encoding/json"
)

type Receipt struct {
	Entry struct {
		Raw       string `json:"raw,omitempty"`
		EntryHash string `json:"entryhash,omitempty"`
		Json      string `json:"json,omitempty"`
	} `json:"entry,omitempty"`
	MerkleBranch []struct {
		Left  string `json:"left,omitempty"`
		Right string `json:"right,omitempty"`
		Top   string `json:"top,omitempty"`
	} `json:"merklebranch,omitempty"`
	EntryBlockKeyMR        string `json:"entryblockkeymr,omitempty"`
	DirectoryBlockKeyMR    string `json:"directoryblockkeymr,omitempty"`
	BitcoinTransactionHash string `json:"bitcointransactionhash,omitempty"`
	BitcoinBlockHash       string `json:"bitcoinblockhash,omitempty"`
}

func GetReceipt(hash string) (*Receipt, error) {
	type receiptResponse struct {
		Receipt *Receipt `json:"receipt"`
	}

	params := hashRequest{Hash: hash}
	req := NewJSON2Request("receipt", APICounter(), params)
	resp, err := factomdRequest(req)
	if err != nil {
		return nil, err
	}
	if resp.Error != nil {
		return nil, resp.Error
	}

	rec := new(receiptResponse)
	if err := json.Unmarshal(resp.JSONResult(), rec); err != nil {
		return nil, err
	}

	return rec.Receipt, nil
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"log"
	_ "net/http/httputil"
	"os"

	"github.com/olivere/elastic"
)

var cmdReindex = &Command{
	Run:   runReindex,
	Usage: "reindex [-v] [-bulk=<n>] [-shards=<n>] [-replicas=<n>] <source> <target>",
	Short: "reindex one index to another index",
	Long: `
The reindex command takes the documents from the source index
and bulk imports them to the specified target index.

This is quite handy if you want to change the settings of an
index and won't lose any data.

You can also copy indices from one cluster to another by using the -source
and -target options.

Use the -v flag to print progress.

Example:

  $ es reindex -v twitter twitter-snapshot
  $ es reindex -v -source=http://cluster1:9200 -target=http://cluster2:9200 twitter twitter-snapshot
`,
	ApiUrl: "http://www.elasticsearch.org/guide/reference/api/bulk.html",
}

var (
	sourceURL, targetURL string
	bulkSize             int
	shards, replicas     int
)

func init() {
	cmdReindex.Flag.BoolVar(&verbose, "v", false, "verbose")
	cmdReindex.Flag.StringVar(&sourceURL, "source", "", "URL of source cluster")
	cmdReindex.Flag.StringVar(&targetURL, "target", "", "URL of target cluster")
	cmdReindex.Flag.IntVar(&bulkSize, "bulk", 1000, "bulk size")
	cmdReindex.Flag.IntVar(&shards, "shards", -1, "number of shards for target index")
	cmdReindex.Flag.IntVar(&replicas, "replicas", -1, "number of replicas for target index")
}

func runReindex(cmd *Command, args []string) {
	if len(args) < 2 {
		cmd.printUsage()
		os.Exit(1)
	}

	sourceIndex := args[0]
	targetIndex := args[1]

	if sourceURL == "" {
		sourceURL = esUrl
	}
	if targetURL == "" {
		targetURL = esUrl
	}

	// Get a client
	sourceClient, err := elastic.NewClient(elastic.SetURL(sourceURL))
	if err != nil {
		log.Fatalf("%v", err)
	}
	targetClient := sourceClient
	if sourceURL != targetURL {
		targetClient, err = elastic.NewClient(elastic.SetURL(targetURL))
		if err != nil {
			log.Fatalf("%v", err)
		}
	}

	// Check if source index exists. Stop if it doesn't.
	exists, err := sourceClient.IndexExists(sourceIndex).Do()
	if err != nil {
		log.Fatalf("%v", err)
	}
	if !exists {
		os.Exit(0)
	}

	// Progress callback
	progress := func(current, total int64) {
		if verbose {
			var percent int64
			if total > 0 {
				percent = 100 * current / total
			}
			fmt.Fprintf(os.Stderr, "Reindexing %9d of %9d (%3d%%)\r", current, total, percent)
		}
	}

	// Use the Elastic Reindexer
	ix := elastic.NewReindexer(sourceClient, sourceIndex, elastic.CopyToTargetIndex(targetIndex))
	ix = ix.TargetClient(targetClient)
	if bulkSize > 0 {
		ix = ix.BulkSize(bulkSize)
	}
	ix = ix.Shards(shards)
	ix = ix.Replicas(replicas)
	ix = ix.Scroll("5m")
	ix = ix.Progress(progress)
	ix = ix.StatsOnly(true)
	res, err := ix.Do()
	if err != nil {
		log.Fatalf("%v", err)
	}

	fmt.Fprintf(os.Stderr, "%d successful and %d failed request(s)\n", res.Success, res.Failed)
}
<commit_msg>Update Reindexer to latest Elastic version (2)<commit_after>package main

import (
	"fmt"
	"log"
	_ "net/http/httputil"
	"os"

	"github.com/olivere/elastic"
)

var cmdReindex = &Command{
	Run:   runReindex,
	Usage: "reindex [-v] [-bulk=<n>] [-shards=<n>] [-replicas=<n>] <source> <target>",
	Short: "reindex one index to another index",
	Long: `
The reindex command takes the documents from the source index
and bulk imports them to the specified target index.

This is quite handy if you want to change the settings of an
index and won't lose any data.

You can also copy indices from one cluster to another by using the -source
and -target options.

Use the -v flag to print progress.

Example:

  $ es reindex -v twitter twitter-snapshot
  $ es reindex -v -source=http://cluster1:9200 -target=http://cluster2:9200 twitter twitter-snapshot
`,
	ApiUrl: "http://www.elasticsearch.org/guide/reference/api/bulk.html",
}

var (
	sourceURL, targetURL string
	bulkSize             int
	shards, replicas     int
)

func init() {
	cmdReindex.Flag.BoolVar(&verbose, "v", false, "verbose")
	cmdReindex.Flag.StringVar(&sourceURL, "source", "", "URL of source cluster")
	cmdReindex.Flag.StringVar(&targetURL, "target", "", "URL of target cluster")
	cmdReindex.Flag.IntVar(&bulkSize, "bulk", 1000, "bulk size")
	cmdReindex.Flag.IntVar(&shards, "shards", -1, "number of shards for target index")
	cmdReindex.Flag.IntVar(&replicas, "replicas", -1, "number of replicas for target index")
}

func runReindex(cmd *Command, args []string) {
	if len(args) < 2 {
		cmd.printUsage()
		os.Exit(1)
	}

	sourceIndex := args[0]
	targetIndex := args[1]

	if sourceURL == "" {
		sourceURL = esUrl
	}
	if targetURL == "" {
		targetURL = esUrl
	}

	// Get a client
	sourceClient, err := elastic.NewClient(elastic.SetURL(sourceURL))
	if err != nil {
		log.Fatalf("%v", err)
	}
	targetClient := sourceClient
	if sourceURL != targetURL {
		targetClient, err = elastic.NewClient(elastic.SetURL(targetURL))
		if err != nil {
			log.Fatalf("%v", err)
		}
	}

	// Check if source index exists. Stop if it doesn't.
	exists, err := sourceClient.IndexExists(sourceIndex).Do()
	if err != nil {
		log.Fatalf("%v", err)
	}
	if !exists {
		os.Exit(0)
	}

	// Check if the target index exists. If it doesn't, create it with
	// the number of shards/replicas specified.
	exists, err = targetClient.IndexExists(targetIndex).Do()
	if err != nil {
		log.Fatalf("%v", err)
	}
	if !exists {
		settings := make(map[string]interface{})
		if shards > 0 || replicas >= 0 {
			ixs := make(map[string]interface{})
			if shards > 0 {
				ixs["number_of_shards"] = shards
			}
			if replicas >= 0 {
				ixs["number_of_replicas"] = replicas
			}
			settings["index"] = ixs
		}
		_, err = targetClient.CreateIndex(targetIndex).BodyJson(settings).Do()
		if err != nil {
			log.Fatalf("%v", err)
		}
	} else if shards > 0 || replicas >= 0 {
		fmt.Fprint(os.Stderr, "Shards and/or replicas will not be changed on an existing index\n")
	}

	// Progress callback
	progress := func(current, total int64) {
		if verbose {
			var percent int64
			if total > 0 {
				percent = 100 * current / total
			}
			fmt.Fprintf(os.Stderr, "Reindexing %9d of %9d (%3d%%)\r", current, total, percent)
		}
	}

	// Use the Elastic Reindexer
	ix := elastic.NewReindexer(sourceClient, sourceIndex, elastic.CopyToTargetIndex(targetIndex))
	ix = ix.TargetClient(targetClient)
	if bulkSize > 0 {
		ix = ix.BulkSize(bulkSize)
	}
	ix = ix.Scroll("5m")
	ix = ix.Progress(progress)
	ix = ix.StatsOnly(true)
	res, err := ix.Do()
	if err != nil {
		log.Fatalf("%v", err)
	}

	fmt.Fprintf(os.Stderr, "%d successful and %d failed request(s)\n", res.Success, res.Failed)
}
<|endoftext|>


<commit_before>package src

import (
	"errors"
	"fmt"
	"io/ioutil"
	"os"
	"os/exec"
	"time"

	log "github.com/Sirupsen/logrus"
)

type ShellExecutor struct {
}

func (s *ShellExecutor) Run(config RunnerConfig, build Build) error {
	builds_dir := "tmp/builds"
	if len(config.BuildsDir) != 0 {
		builds_dir = c.BuildsDir
	}

	// generate build script
	script_file := build.Generate(builds_dir)
	if script_file == nil {
		return errors.New("Failed to generate build script")
	}
	defer os.Remove(*script_file)
	log.Debugln(config.ShortDescription(), build.Id, "Generated build script:", *script_file)

	// create build log
	build_log, err := ioutil.TempFile("", "build_log")
	if err != nil {
		return errors.New("Failed to create build log file")
	}
	defer build_log.Close()
	defer os.Remove(build_log.Name())
	build.BuildLog = build_log.Name()
	log.Debugln(config.ShortDescription(), build.Id, "Created build log:", build_log.Name())

	shell_script := config.ShellScript
	if len(shell_script) == 0 {
		shell_script = "setsid"
	}

	// create execution command
	cmd := exec.Command(shell_script, *script_file)
	if cmd == nil {
		return errors.New("Failed to generate execution command")
	}

	cmd.Env = []string{
		"CI_SERVER=yes",
		"CI_SERVER_NAME=GitLab CI",
		"CI_SERVER_VERSION=",
		"CI_SERVER_REVISION=",

		fmt.Sprintf("CI_BUILD_REF=%s", build.Sha),
		fmt.Sprintf("CI_BUILD_BEFORE_SHA=%s", build.BeforeSha),
		fmt.Sprintf("CI_BUILD_REF_NAME=%s", build.RefName),
		fmt.Sprintf("CI_BUILD_ID=%d", build.Id),
		fmt.Sprintf("CI_BUILD_REPO=%s", build.RepoURL),

		fmt.Sprintf("CI_PROJECT_ID=%d", build.ProjectId),

		"RUBYLIB=",
		"RUBYOPT=",
		"BNDLE_BIN_PATH=",
		"BUNDLE_GEMFILE=",
	}

	// cmd.Stdin = ioutil.
	cmd.Stdout = build_log
	cmd.Stderr = build_log

	// Start process
	err = cmd.Start()
	if err != nil {
		return errors.New("Failed to start process")
	}
	log.Debugln(config.ShortDescription(), build.Id, "Started build process")

	// Wait for process to exit
	command_finish := make(chan error, 1)
	go func() {
		command_finish <- cmd.Wait()
	}()

	// Update build log
	abort := make(chan bool, 1)
	finishBuildLog := make(chan bool)
	go build.WatchTrace(config, abort, finishBuildLog)

	if build.Timeout <= 0 {
		build.Timeout = DEFAULT_TIMEOUT
	}

	var buildState BuildState
	var buildMessage string

	// Wait for signals: abort, timeout or finish
	log.Debugln(config.ShortDescription(), build.Id, "Waiting for signals...")
	select {
	case <-abort:
		log.Println(config.ShortDescription(), build.Id, "Build got aborted.")
		buildState = Failed

	case <-time.After(time.Duration(build.Timeout) * time.Second):
		log.Println(config.ShortDescription(), build.Id, "Build timedout.")
		// command timeout
		if err := cmd.Process.Kill(); err != nil {
		}
		buildState = Failed
		buildMessage = fmt.Sprintf("\nCI Timeout. Execution took longer then %d seconds", build.Timeout)

	case err := <-command_finish:
		// command finished
		if err != nil {
			log.Println(config.ShortDescription(), build.Id, "Build failed with", err)
			buildState = Failed
			buildMessage = fmt.Sprintf("\nBuild failed with %s", err.Error())
		} else {
			log.Println(config.ShortDescription(), build.Id, "Build succeeded.")
			buildState = Success
		}
	}

	// wait for update log routine to finish
	log.Debugln(config.ShortDescription(), build.Id, "Waiting for build log updater to finish")
	finishBuildLog <- true
	log.Debugln(config.ShortDescription(), build.Id, "Build log updater finished.")

	// Send final build state to server
	go build.FinishBuild(config, buildState, buildMessage)
	return nil
}
<commit_msg>Fixed shell<commit_after>package src

import (
	"errors"
	"fmt"
	"io/ioutil"
	"os"
	"os/exec"
	"time"

	log "github.com/Sirupsen/logrus"
)

type ShellExecutor struct {
}

func (s *ShellExecutor) Run(config RunnerConfig, build Build) error {
	builds_dir := "tmp/builds"
	if len(config.BuildsDir) != 0 {
		builds_dir = config.BuildsDir
	}

	// generate build script
	script_file := build.Generate(builds_dir)
	if script_file == nil {
		return errors.New("Failed to generate build script")
	}
	defer os.Remove(*script_file)
	log.Debugln(config.ShortDescription(), build.Id, "Generated build script:", *script_file)

	// create build log
	build_log, err := ioutil.TempFile("", "build_log")
	if err != nil {
		return errors.New("Failed to create build log file")
	}
	defer build_log.Close()
	defer os.Remove(build_log.Name())
	build.BuildLog = build_log.Name()
	log.Debugln(config.ShortDescription(), build.Id, "Created build log:", build_log.Name())

	shell_script := config.ShellScript
	if len(shell_script) == 0 {
		shell_script = "setsid"
	}

	// create execution command
	cmd := exec.Command(shell_script, *script_file)
	if cmd == nil {
		return errors.New("Failed to generate execution command")
	}

	cmd.Env = []string{
		"CI_SERVER=yes",
		"CI_SERVER_NAME=GitLab CI",
		"CI_SERVER_VERSION=",
		"CI_SERVER_REVISION=",

		fmt.Sprintf("CI_BUILD_REF=%s", build.Sha),
		fmt.Sprintf("CI_BUILD_BEFORE_SHA=%s", build.BeforeSha),
		fmt.Sprintf("CI_BUILD_REF_NAME=%s", build.RefName),
		fmt.Sprintf("CI_BUILD_ID=%d", build.Id),
		fmt.Sprintf("CI_BUILD_REPO=%s", build.RepoURL),

		fmt.Sprintf("CI_PROJECT_ID=%d", build.ProjectId),

		"RUBYLIB=",
		"RUBYOPT=",
		"BNDLE_BIN_PATH=",
		"BUNDLE_GEMFILE=",
	}

	// cmd.Stdin = ioutil.
	cmd.Stdout = build_log
	cmd.Stderr = build_log

	// Start process
	err = cmd.Start()
	if err != nil {
		return errors.New("Failed to start process")
	}
	log.Debugln(config.ShortDescription(), build.Id, "Started build process")

	// Wait for process to exit
	command_finish := make(chan error, 1)
	go func() {
		command_finish <- cmd.Wait()
	}()

	// Update build log
	abort := make(chan bool, 1)
	finishBuildLog := make(chan bool)
	go build.WatchTrace(config, abort, finishBuildLog)

	if build.Timeout <= 0 {
		build.Timeout = DEFAULT_TIMEOUT
	}

	var buildState BuildState
	var buildMessage string

	// Wait for signals: abort, timeout or finish
	log.Debugln(config.ShortDescription(), build.Id, "Waiting for signals...")
	select {
	case <-abort:
		log.Println(config.ShortDescription(), build.Id, "Build got aborted.")
		buildState = Failed

	case <-time.After(time.Duration(build.Timeout) * time.Second):
		log.Println(config.ShortDescription(), build.Id, "Build timedout.")
		// command timeout
		if err := cmd.Process.Kill(); err != nil {
		}
		buildState = Failed
		buildMessage = fmt.Sprintf("\nCI Timeout. Execution took longer then %d seconds", build.Timeout)

	case err := <-command_finish:
		// command finished
		if err != nil {
			log.Println(config.ShortDescription(), build.Id, "Build failed with", err)
			buildState = Failed
			buildMessage = fmt.Sprintf("\nBuild failed with %s", err.Error())
		} else {
			log.Println(config.ShortDescription(), build.Id, "Build succeeded.")
			buildState = Success
		}
	}

	// wait for update log routine to finish
	log.Debugln(config.ShortDescription(), build.Id, "Waiting for build log updater to finish")
	finishBuildLog <- true
	log.Debugln(config.ShortDescription(), build.Id, "Build log updater finished.")

	// Send final build state to server
	go build.FinishBuild(config, buildState, buildMessage)
	return nil
}
<|endoftext|>


<commit_before>// Package banner provides banner information
package banner

import (
	"fmt"
)

// Println print out banner information
func Println() {
	b := `
================================================
                          _    ___
                _ __ _  _| |  / __|
               | '  \ || | |_| (_ |
               |_|_|_\_, |____\___|
                      |__/

                 My Looking Glass
                  http://mylg.io
================== myLG v0.1.5 =================
	`
	fmt.Println(b)
}
<commit_msg>bump version to 0.1.6<commit_after>// Package banner provides banner information
package banner

import (
	"fmt"
)

// Println print out banner information
func Println() {
	b := `
=================================================
                          _    ___
                _ __ _  _| |  / __|
               | '  \ || | |_| (_ |
               |_|_|_\_, |____\___|
                      |__/

                 My Looking Glass
                  http://mylg.io
================== myLG v0.1.6 ==================
	`
	fmt.Println(b)
}
<|endoftext|>


<commit_before>package capnp

import (
	"bytes"
)

// A Ptr is a reference to a Cap'n Proto struct, list, or interface.
// The zero value is a null pointer.
type Ptr struct {
	seg        *Segment
	off        address
	lenOrCap   uint32
	size       ObjectSize
	depthLimit uint
	flags      ptrFlags
}

// Struct converts p to a Struct. If p does not hold a Struct pointer,
// the zero value is returned.
func (p Ptr) Struct() Struct {
	if p.flags.ptrType() != structPtrType {
		return Struct{}
	}
	return Struct{
		seg:        p.seg,
		off:        p.off,
		size:       p.size,
		flags:      p.flags.structFlags(),
		depthLimit: p.depthLimit,
	}
}

// StructDefault attempts to convert p into a struct, reading the
// default value from def if p is not a struct.
func (p Ptr) StructDefault(def []byte) (Struct, error) {
	s := p.Struct()
	if s.seg == nil {
		if def == nil {
			return Struct{}, nil
		}
		defp, err := unmarshalDefault(def)
		if err != nil {
			return Struct{}, err
		}
		return defp.Struct(), nil
	}
	return s, nil
}

// List converts p to a List. If p does not hold a List pointer,
// the zero value is returned.
func (p Ptr) List() List {
	if p.flags.ptrType() != listPtrType {
		return List{}
	}
	return List{
		seg:        p.seg,
		off:        p.off,
		length:     int32(p.lenOrCap),
		size:       p.size,
		flags:      p.flags.listFlags(),
		depthLimit: p.depthLimit,
	}
}

// ListDefault attempts to convert p into a list, reading the default
// value from def if p is not a list.
func (p Ptr) ListDefault(def []byte) (List, error) {
	l := p.List()
	if l.seg == nil {
		if def == nil {
			return List{}, nil
		}
		defp, err := unmarshalDefault(def)
		if err != nil {
			return List{}, err
		}
		return defp.List(), nil
	}
	return l, nil
}

// Interface converts p to an Interface. If p does not hold a List
// pointer, the zero value is returned.
func (p Ptr) Interface() Interface {
	if p.flags.ptrType() != interfacePtrType {
		return Interface{}
	}
	return Interface{
		seg: p.seg,
		cap: CapabilityID(p.lenOrCap),
	}
}

// Text attempts to convert p into Text, returning an empty string if
// p is not a valid 1-byte list pointer.
func (p Ptr) Text() string {
	b, ok := p.text()
	if !ok {
		return ""
	}
	return string(b)
}

// TextDefault attempts to convert p into Text, returning def if p is
// not a valid 1-byte list pointer.
func (p Ptr) TextDefault(def string) string {
	b, ok := p.text()
	if !ok {
		return def
	}
	return string(b)
}

// TextBytes attempts to convert p into Text, returning nil if p is not
// a valid 1-byte list pointer.  It returns a slice directly into the
// segment.
func (p Ptr) TextBytes() []byte {
	b, ok := p.text()
	if !ok {
		return nil
	}
	return b
}

// TextBytesDefault attempts to convert p into Text, returning def if p
// is not a valid 1-byte list pointer.  It returns a slice directly into
// the segment.
func (p Ptr) TextBytesDefault(def string) []byte {
	b, ok := p.text()
	if !ok {
		return []byte(def)
	}
	return b
}

func (p Ptr) text() (b []byte, ok bool) {
	if !isOneByteList(p) {
		return nil, false
	}
	l := p.List()
	b = l.seg.slice(l.off, Size(l.length))
	if len(b) == 0 || b[len(b)-1] != 0 {
		// Text must be null-terminated.
		return nil, false
	}
	return b[:len(b)-1 : len(b)], true
}

// Data attempts to convert p into Data, returning nil if p is not a
// valid 1-byte list pointer.
func (p Ptr) Data() []byte {
	return p.DataDefault(nil)
}

// DataDefault attempts to convert p into Data, returning def if p is
// not a valid 1-byte list pointer.
func (p Ptr) DataDefault(def []byte) []byte {
	if !isOneByteList(p) {
		return def
	}
	l := p.List()
	b := l.seg.slice(l.off, Size(l.length))
	if b == nil {
		return def
	}
	return b
}

// IsValid reports whether p is valid.
func (p Ptr) IsValid() bool {
	return p.seg != nil
}

// Segment returns the segment that the referenced data is stored in
// or nil if the pointer is invalid.
func (p Ptr) Segment() *Segment {
	return p.seg
}

// Message returns the message the referenced data is stored in or nil
// if the pointer is invalid.
func (p Ptr) Message() *Message {
	if p.seg == nil {
		return nil
	}
	return p.seg.msg
}

// Default returns p if it is valid, otherwise it unmarshals def.
func (p Ptr) Default(def []byte) (Ptr, error) {
	if !p.IsValid() {
		return unmarshalDefault(def)
	}
	return p, nil
}

// SamePtr reports whether p and q refer to the same object.
func SamePtr(p, q Ptr) bool {
	return p.seg == q.seg && p.off == q.off
}

func unmarshalDefault(def []byte) (Ptr, error) {
	msg, err := Unmarshal(def)
	if err != nil {
		return Ptr{}, annotate(err).errorf("read default")
	}
	p, err := msg.Root()
	if err != nil {
		return Ptr{}, annotate(err).errorf("read default")
	}
	return p, nil
}

type ptrFlags uint8

const interfacePtrFlag ptrFlags = interfacePtrType << 6

func structPtrFlag(f structFlags) ptrFlags {
	return structPtrType<<6 | ptrFlags(f)&ptrLowerMask
}

func listPtrFlag(f listFlags) ptrFlags {
	return listPtrType<<6 | ptrFlags(f)&ptrLowerMask
}

const (
	structPtrType = iota
	listPtrType
	interfacePtrType
)

func (f ptrFlags) ptrType() int {
	return int(f >> 6)
}

const ptrLowerMask ptrFlags = 0x3f

func (f ptrFlags) listFlags() listFlags {
	return listFlags(f & ptrLowerMask)
}

func (f ptrFlags) structFlags() structFlags {
	return structFlags(f & ptrLowerMask)
}

func isZeroFilled(b []byte) bool {
	for _, bb := range b {
		if bb != 0 {
			return false
		}
	}
	return true
}

// Equal returns true iff p1 and p2 are equal.
//
// Equality is defined to be:
//
//	- Two structs are equal iff all of their fields are equal.  If one
//	  struct has more fields than the other, the extra fields must all be
//		zero.
//	- Two lists are equal iff they have the same length and their
//	  corresponding elements are equal.  If one list is a list of
//	  primitives and the other is a list of structs, then the list of
//	  primitives is treated as if it was a list of structs with the
//	  element value as the sole field.
//	- Two interfaces are equal iff they point to a capability created by
//	  the same call to NewClient or they are referring to the same
//	  capability table index in the same message.  The latter is
//	  significant when the message's capability table has not been
//	  populated.
//	- Two null pointers are equal.
//	- All other combinations of things are not equal.
func Equal(p1, p2 Ptr) (bool, error) {
	if !p1.IsValid() && !p2.IsValid() {
		return true, nil
	}
	if !p1.IsValid() || !p2.IsValid() {
		return false, nil
	}
	pt := p1.flags.ptrType()
	if pt != p2.flags.ptrType() {
		return false, nil
	}
	switch pt {
	case structPtrType:
		s1, s2 := p1.Struct(), p2.Struct()
		data1 := s1.seg.slice(s1.off, s1.size.DataSize)
		data2 := s2.seg.slice(s2.off, s2.size.DataSize)
		switch {
		case len(data1) < len(data2):
			if !bytes.Equal(data1, data2[:len(data1)]) {
				return false, nil
			}
			if !isZeroFilled(data2[len(data1):]) {
				return false, nil
			}
		case len(data1) > len(data2):
			if !bytes.Equal(data1[:len(data2)], data2) {
				return false, nil
			}
			if !isZeroFilled(data1[len(data2):]) {
				return false, nil
			}
		default:
			if !bytes.Equal(data1, data2) {
				return false, nil
			}
		}
		n := int(s1.size.PointerCount)
		if n2 := int(s2.size.PointerCount); n2 < n {
			n = n2
		}
		for i := 0; i < n; i++ {
			sp1, err := s1.Ptr(uint16(i))
			if err != nil {
				return false, annotate(err).errorf("equal")
			}
			sp2, err := s2.Ptr(uint16(i))
			if err != nil {
				return false, annotate(err).errorf("equal")
			}
			if ok, err := Equal(sp1, sp2); !ok || err != nil {
				return false, err
			}
		}
		for i := n; i < int(s1.size.PointerCount); i++ {
			if s1.HasPtr(uint16(i)) {
				return false, nil
			}
		}
		for i := n; i < int(s2.size.PointerCount); i++ {
			if s2.HasPtr(uint16(i)) {
				return false, nil
			}
		}
		return true, nil
	case listPtrType:
		l1, l2 := p1.List(), p2.List()
		if l1.Len() != l2.Len() {
			return false, nil
		}
		if l1.flags&isCompositeList == 0 && l2.flags&isCompositeList == 0 && l1.size != l2.size {
			return false, nil
		}
		if l1.size.PointerCount == 0 && l2.size.PointerCount == 0 && l1.size.DataSize == l2.size.DataSize {
			// Optimization: pure data lists can be compared bytewise.
			sz, _ := l1.size.totalSize().times(l1.length) // both list bounds have been validated
			return bytes.Equal(l1.seg.slice(l1.off, sz), l2.seg.slice(l2.off, sz)), nil
		}
		for i := 0; i < l1.Len(); i++ {
			e1, e2 := l1.Struct(i), l2.Struct(i)
			if ok, err := Equal(e1.ToPtr(), e2.ToPtr()); err != nil {
				return false, annotate(err).errorf("equal: list element %d", i)
			} else if !ok {
				return false, nil
			}
		}
		return true, nil
	case interfacePtrType:
		i1, i2 := p1.Interface(), p2.Interface()
		if i1.Message() == i2.Message() {
			if i1.Capability() == i2.Capability() {
				return true, nil
			}
			ntab := len(i1.Message().CapTable)
			if int64(i1.Capability()) >= int64(ntab) || int64(i2.Capability()) >= int64(ntab) {
				return false, nil
			}
		}
		return i1.Client().IsSame(i2.Client()), nil
	default:
		panic("unreachable")
	}
}
<commit_msg>Run go fmt -s against pointer.go<commit_after>package capnp

import (
	"bytes"
)

// A Ptr is a reference to a Cap'n Proto struct, list, or interface.
// The zero value is a null pointer.
type Ptr struct {
	seg        *Segment
	off        address
	lenOrCap   uint32
	size       ObjectSize
	depthLimit uint
	flags      ptrFlags
}

// Struct converts p to a Struct. If p does not hold a Struct pointer,
// the zero value is returned.
func (p Ptr) Struct() Struct {
	if p.flags.ptrType() != structPtrType {
		return Struct{}
	}
	return Struct{
		seg:        p.seg,
		off:        p.off,
		size:       p.size,
		flags:      p.flags.structFlags(),
		depthLimit: p.depthLimit,
	}
}

// StructDefault attempts to convert p into a struct, reading the
// default value from def if p is not a struct.
func (p Ptr) StructDefault(def []byte) (Struct, error) {
	s := p.Struct()
	if s.seg == nil {
		if def == nil {
			return Struct{}, nil
		}
		defp, err := unmarshalDefault(def)
		if err != nil {
			return Struct{}, err
		}
		return defp.Struct(), nil
	}
	return s, nil
}

// List converts p to a List. If p does not hold a List pointer,
// the zero value is returned.
func (p Ptr) List() List {
	if p.flags.ptrType() != listPtrType {
		return List{}
	}
	return List{
		seg:        p.seg,
		off:        p.off,
		length:     int32(p.lenOrCap),
		size:       p.size,
		flags:      p.flags.listFlags(),
		depthLimit: p.depthLimit,
	}
}

// ListDefault attempts to convert p into a list, reading the default
// value from def if p is not a list.
func (p Ptr) ListDefault(def []byte) (List, error) {
	l := p.List()
	if l.seg == nil {
		if def == nil {
			return List{}, nil
		}
		defp, err := unmarshalDefault(def)
		if err != nil {
			return List{}, err
		}
		return defp.List(), nil
	}
	return l, nil
}

// Interface converts p to an Interface. If p does not hold a List
// pointer, the zero value is returned.
func (p Ptr) Interface() Interface {
	if p.flags.ptrType() != interfacePtrType {
		return Interface{}
	}
	return Interface{
		seg: p.seg,
		cap: CapabilityID(p.lenOrCap),
	}
}

// Text attempts to convert p into Text, returning an empty string if
// p is not a valid 1-byte list pointer.
func (p Ptr) Text() string {
	b, ok := p.text()
	if !ok {
		return ""
	}
	return string(b)
}

// TextDefault attempts to convert p into Text, returning def if p is
// not a valid 1-byte list pointer.
func (p Ptr) TextDefault(def string) string {
	b, ok := p.text()
	if !ok {
		return def
	}
	return string(b)
}

// TextBytes attempts to convert p into Text, returning nil if p is not
// a valid 1-byte list pointer.  It returns a slice directly into the
// segment.
func (p Ptr) TextBytes() []byte {
	b, ok := p.text()
	if !ok {
		return nil
	}
	return b
}

// TextBytesDefault attempts to convert p into Text, returning def if p
// is not a valid 1-byte list pointer.  It returns a slice directly into
// the segment.
func (p Ptr) TextBytesDefault(def string) []byte {
	b, ok := p.text()
	if !ok {
		return []byte(def)
	}
	return b
}

func (p Ptr) text() (b []byte, ok bool) {
	if !isOneByteList(p) {
		return nil, false
	}
	l := p.List()
	b = l.seg.slice(l.off, Size(l.length))
	if len(b) == 0 || b[len(b)-1] != 0 {
		// Text must be null-terminated.
		return nil, false
	}
	return b[: len(b)-1 : len(b)], true
}

// Data attempts to convert p into Data, returning nil if p is not a
// valid 1-byte list pointer.
func (p Ptr) Data() []byte {
	return p.DataDefault(nil)
}

// DataDefault attempts to convert p into Data, returning def if p is
// not a valid 1-byte list pointer.
func (p Ptr) DataDefault(def []byte) []byte {
	if !isOneByteList(p) {
		return def
	}
	l := p.List()
	b := l.seg.slice(l.off, Size(l.length))
	if b == nil {
		return def
	}
	return b
}

// IsValid reports whether p is valid.
func (p Ptr) IsValid() bool {
	return p.seg != nil
}

// Segment returns the segment that the referenced data is stored in
// or nil if the pointer is invalid.
func (p Ptr) Segment() *Segment {
	return p.seg
}

// Message returns the message the referenced data is stored in or nil
// if the pointer is invalid.
func (p Ptr) Message() *Message {
	if p.seg == nil {
		return nil
	}
	return p.seg.msg
}

// Default returns p if it is valid, otherwise it unmarshals def.
func (p Ptr) Default(def []byte) (Ptr, error) {
	if !p.IsValid() {
		return unmarshalDefault(def)
	}
	return p, nil
}

// SamePtr reports whether p and q refer to the same object.
func SamePtr(p, q Ptr) bool {
	return p.seg == q.seg && p.off == q.off
}

func unmarshalDefault(def []byte) (Ptr, error) {
	msg, err := Unmarshal(def)
	if err != nil {
		return Ptr{}, annotate(err).errorf("read default")
	}
	p, err := msg.Root()
	if err != nil {
		return Ptr{}, annotate(err).errorf("read default")
	}
	return p, nil
}

type ptrFlags uint8

const interfacePtrFlag ptrFlags = interfacePtrType << 6

func structPtrFlag(f structFlags) ptrFlags {
	return structPtrType<<6 | ptrFlags(f)&ptrLowerMask
}

func listPtrFlag(f listFlags) ptrFlags {
	return listPtrType<<6 | ptrFlags(f)&ptrLowerMask
}

const (
	structPtrType = iota
	listPtrType
	interfacePtrType
)

func (f ptrFlags) ptrType() int {
	return int(f >> 6)
}

const ptrLowerMask ptrFlags = 0x3f

func (f ptrFlags) listFlags() listFlags {
	return listFlags(f & ptrLowerMask)
}

func (f ptrFlags) structFlags() structFlags {
	return structFlags(f & ptrLowerMask)
}

func isZeroFilled(b []byte) bool {
	for _, bb := range b {
		if bb != 0 {
			return false
		}
	}
	return true
}

// Equal returns true iff p1 and p2 are equal.
//
// Equality is defined to be:
//
//	- Two structs are equal iff all of their fields are equal.  If one
//	  struct has more fields than the other, the extra fields must all be
//		zero.
//	- Two lists are equal iff they have the same length and their
//	  corresponding elements are equal.  If one list is a list of
//	  primitives and the other is a list of structs, then the list of
//	  primitives is treated as if it was a list of structs with the
//	  element value as the sole field.
//	- Two interfaces are equal iff they point to a capability created by
//	  the same call to NewClient or they are referring to the same
//	  capability table index in the same message.  The latter is
//	  significant when the message's capability table has not been
//	  populated.
//	- Two null pointers are equal.
//	- All other combinations of things are not equal.
func Equal(p1, p2 Ptr) (bool, error) {
	if !p1.IsValid() && !p2.IsValid() {
		return true, nil
	}
	if !p1.IsValid() || !p2.IsValid() {
		return false, nil
	}
	pt := p1.flags.ptrType()
	if pt != p2.flags.ptrType() {
		return false, nil
	}
	switch pt {
	case structPtrType:
		s1, s2 := p1.Struct(), p2.Struct()
		data1 := s1.seg.slice(s1.off, s1.size.DataSize)
		data2 := s2.seg.slice(s2.off, s2.size.DataSize)
		switch {
		case len(data1) < len(data2):
			if !bytes.Equal(data1, data2[:len(data1)]) {
				return false, nil
			}
			if !isZeroFilled(data2[len(data1):]) {
				return false, nil
			}
		case len(data1) > len(data2):
			if !bytes.Equal(data1[:len(data2)], data2) {
				return false, nil
			}
			if !isZeroFilled(data1[len(data2):]) {
				return false, nil
			}
		default:
			if !bytes.Equal(data1, data2) {
				return false, nil
			}
		}
		n := int(s1.size.PointerCount)
		if n2 := int(s2.size.PointerCount); n2 < n {
			n = n2
		}
		for i := 0; i < n; i++ {
			sp1, err := s1.Ptr(uint16(i))
			if err != nil {
				return false, annotate(err).errorf("equal")
			}
			sp2, err := s2.Ptr(uint16(i))
			if err != nil {
				return false, annotate(err).errorf("equal")
			}
			if ok, err := Equal(sp1, sp2); !ok || err != nil {
				return false, err
			}
		}
		for i := n; i < int(s1.size.PointerCount); i++ {
			if s1.HasPtr(uint16(i)) {
				return false, nil
			}
		}
		for i := n; i < int(s2.size.PointerCount); i++ {
			if s2.HasPtr(uint16(i)) {
				return false, nil
			}
		}
		return true, nil
	case listPtrType:
		l1, l2 := p1.List(), p2.List()
		if l1.Len() != l2.Len() {
			return false, nil
		}
		if l1.flags&isCompositeList == 0 && l2.flags&isCompositeList == 0 && l1.size != l2.size {
			return false, nil
		}
		if l1.size.PointerCount == 0 && l2.size.PointerCount == 0 && l1.size.DataSize == l2.size.DataSize {
			// Optimization: pure data lists can be compared bytewise.
			sz, _ := l1.size.totalSize().times(l1.length) // both list bounds have been validated
			return bytes.Equal(l1.seg.slice(l1.off, sz), l2.seg.slice(l2.off, sz)), nil
		}
		for i := 0; i < l1.Len(); i++ {
			e1, e2 := l1.Struct(i), l2.Struct(i)
			if ok, err := Equal(e1.ToPtr(), e2.ToPtr()); err != nil {
				return false, annotate(err).errorf("equal: list element %d", i)
			} else if !ok {
				return false, nil
			}
		}
		return true, nil
	case interfacePtrType:
		i1, i2 := p1.Interface(), p2.Interface()
		if i1.Message() == i2.Message() {
			if i1.Capability() == i2.Capability() {
				return true, nil
			}
			ntab := len(i1.Message().CapTable)
			if int64(i1.Capability()) >= int64(ntab) || int64(i2.Capability()) >= int64(ntab) {
				return false, nil
			}
		}
		return i1.Client().IsSame(i2.Client()), nil
	default:
		panic("unreachable")
	}
}
<|endoftext|>


<commit_before>package geom

// A Polygon represents a polygon as a collection of LinearRings. The first
// LinearRing is the outer boundary. Subsequent LinearRings are inner
// boundaries (holes).
type Polygon struct {
	geom2
}

// NewPolygon returns a new, empty, Polygon.
func NewPolygon(layout Layout) *Polygon {
	return NewPolygonFlat(layout, nil, nil)
}

// NewPolygonFlat returns a new Polygon with the given flat coordinates.
func NewPolygonFlat(layout Layout, flatCoords []float64, ends []int) *Polygon {
	p := new(Polygon)
	p.layout = layout
	p.stride = layout.Stride()
	p.flatCoords = flatCoords
	p.ends = ends
	return p
}

// Area returns the area.
func (p *Polygon) Area() float64 {
	return doubleArea2(p.flatCoords, 0, p.ends, p.stride) / 2
}

// Clone returns a deep copy.
func (p *Polygon) Clone() *Polygon {
	return deriveClonePolygon(p)
}

// Empty returns false.
func (p *Polygon) Empty() bool {
	return false
}

// Length returns the perimter.
func (p *Polygon) Length() float64 {
	return length2(p.flatCoords, 0, p.ends, p.stride)
}

// LinearRing returns the ith LinearRing.
func (p *Polygon) LinearRing(i int) *LinearRing {
	offset := 0
	if i > 0 {
		offset = p.ends[i-1]
	}
	return NewLinearRingFlat(p.layout, p.flatCoords[offset:p.ends[i]])
}

// MustSetCoords sets the coordinates and panics on any error.
func (p *Polygon) MustSetCoords(coords [][]Coord) *Polygon {
	Must(p.SetCoords(coords))
	return p
}

// NumLinearRings returns the number of LinearRings.
func (p *Polygon) NumLinearRings() int {
	return len(p.ends)
}

// Push appends a LinearRing.
func (p *Polygon) Push(lr *LinearRing) error {
	if lr.layout != p.layout {
		return ErrLayoutMismatch{Got: lr.layout, Want: p.layout}
	}
	p.flatCoords = append(p.flatCoords, lr.flatCoords...)
	p.ends = append(p.ends, len(p.flatCoords))
	return nil
}

// SetCoords sets the coordinates.
func (p *Polygon) SetCoords(coords [][]Coord) (*Polygon, error) {
	if err := p.setCoords(coords); err != nil {
		return nil, err
	}
	return p, nil
}

// SetSRID sets the SRID of p.
func (p *Polygon) SetSRID(srid int) *Polygon {
	p.srid = srid
	return p
}

// Swap swaps the values of p and p2.
func (p *Polygon) Swap(p2 *Polygon) {
	*p, *p2 = *p2, *p
}
<commit_msg>Use g as receiver name in Polygon<commit_after>package geom

// A Polygon represents a polygon as a collection of LinearRings. The first
// LinearRing is the outer boundary. Subsequent LinearRings are inner
// boundaries (holes).
type Polygon struct {
	geom2
}

// NewPolygon returns a new, empty, Polygon.
func NewPolygon(layout Layout) *Polygon {
	return NewPolygonFlat(layout, nil, nil)
}

// NewPolygonFlat returns a new Polygon with the given flat coordinates.
func NewPolygonFlat(layout Layout, flatCoords []float64, ends []int) *Polygon {
	g := new(Polygon)
	g.layout = layout
	g.stride = layout.Stride()
	g.flatCoords = flatCoords
	g.ends = ends
	return g
}

// Area returns the area.
func (g *Polygon) Area() float64 {
	return doubleArea2(g.flatCoords, 0, g.ends, g.stride) / 2
}

// Clone returns a deep copy.
func (g *Polygon) Clone() *Polygon {
	return deriveClonePolygon(g)
}

// Empty returns false.
func (g *Polygon) Empty() bool {
	return false
}

// Length returns the perimter.
func (g *Polygon) Length() float64 {
	return length2(g.flatCoords, 0, g.ends, g.stride)
}

// LinearRing returns the ith LinearRing.
func (g *Polygon) LinearRing(i int) *LinearRing {
	offset := 0
	if i > 0 {
		offset = g.ends[i-1]
	}
	return NewLinearRingFlat(g.layout, g.flatCoords[offset:g.ends[i]])
}

// MustSetCoords sets the coordinates and panics on any error.
func (g *Polygon) MustSetCoords(coords [][]Coord) *Polygon {
	Must(g.SetCoords(coords))
	return g
}

// NumLinearRings returns the number of LinearRings.
func (g *Polygon) NumLinearRings() int {
	return len(g.ends)
}

// Push appends a LinearRing.
func (g *Polygon) Push(lr *LinearRing) error {
	if lr.layout != g.layout {
		return ErrLayoutMismatch{Got: lr.layout, Want: g.layout}
	}
	g.flatCoords = append(g.flatCoords, lr.flatCoords...)
	g.ends = append(g.ends, len(g.flatCoords))
	return nil
}

// SetCoords sets the coordinates.
func (g *Polygon) SetCoords(coords [][]Coord) (*Polygon, error) {
	if err := g.setCoords(coords); err != nil {
		return nil, err
	}
	return g, nil
}

// SetSRID sets the SRID of g.
func (g *Polygon) SetSRID(srid int) *Polygon {
	g.srid = srid
	return g
}

// Swap swaps the values of g and g2.
func (g *Polygon) Swap(g2 *Polygon) {
	*g, *g2 = *g2, *g
}
<|endoftext|>


<commit_before>package styx

import (
	"os"
	"path"
	"strings"
	"time"

	"golang.org/x/net/context"

	"aqwari.net/net/styx/internal/styxfile"
	"aqwari.net/net/styx/internal/sys"
	"aqwari.net/net/styx/styxproto"
)

// A Request is a request by a client to perform an operation
// on a file or set of files. Types of requests may range from
// checking if a file exists (Twalk) to opening a file (Topen)
// to changing a file's name (Twstat).
type Request interface {
	// The context.Context interface is used to implement cancellation and
	// request timeouts. If an operation is going to take a long time to
	// complete, you can allow for the client to cancel the request by receiving
	// on the channel returned by Done().
	context.Context

	// If a request is invalid, not allowed, or cannot be completed properly
	// for some other reason, its Rerror method should be used to respond
	// to it.
	Rerror(format string, args ...interface{})

	// Path returns the Path of the file being operated on.
	Path() string

	// For the programmer's convenience, each request type has a default
	// response. Programmers can choose to ignore requests of a given
	// type and have the styx package send default responses to them.
	// In most cases, the default response is to send an error that the user
	// has insufficient permissions or the file in question does not exist.
	defaultResponse()
}

// common fields among all requests. Some may be nil for
// certain requests.
type reqInfo struct {
	context.Context
	tag     uint16
	fid     uint32
	session *Session
	msg     styxproto.Msg
	path    string
}

// Path returns the absolute path of the file being operated on.
func (info reqInfo) Path() string {
	return info.path
}

func (info reqInfo) Rerror(format string, args ...interface{}) {
	defer info.session.conn.clearTag(info.tag)
	info.session.conn.Rerror(info.tag, format, args...)
}

func newReqInfo(cx context.Context, s *Session, msg fcall, filepath string) reqInfo {
	return reqInfo{
		session: s,
		tag:     msg.Tag(),
		fid:     msg.Fid(),
		Context: cx,
		msg:     msg,
		path:    filepath,
	}
}

func qidType(mode os.FileMode) uint8 {
	var qtype uint8
	if mode&os.ModeDir != 0 {
		qtype = styxproto.QTDIR
	}
	if mode&os.ModeAppend != 0 {
		qtype |= styxproto.QTAPPEND
	}
	if mode&os.ModeExclusive != 0 {
		qtype |= styxproto.QTEXCL
	}
	if mode&os.ModeTemporary != 0 {
		qtype |= styxproto.QTTMP
	}
	return qtype
}

func fileMode(perm uint32) os.FileMode {
	var mode os.FileMode
	if perm&styxproto.DMDIR != 0 {
		mode = os.ModeDir
	}
	if perm&styxproto.DMAPPEND != 0 {
		mode |= os.ModeAppend
	}
	if perm&styxproto.DMEXCL != 0 {
		mode |= os.ModeExclusive
	}
	if perm&styxproto.DMTMP != 0 {
		mode |= os.ModeTemporary
	}
	mode |= (os.FileMode(perm) & os.ModePerm)
	return mode
}

func modePerm(mode os.FileMode) uint32 {
	var perm uint32
	if mode&os.ModeDir != 0 {
		perm |= styxproto.DMDIR
	}
	if mode&os.ModeAppend != 0 {
		perm |= styxproto.DMAPPEND
	}
	if mode&os.ModeExclusive != 0 {
		perm |= styxproto.DMEXCL
	}
	if mode&os.ModeTemporary != 0 {
		perm |= styxproto.DMTMP
	}
	return perm | uint32(mode&os.ModePerm)
}

// A Topen message is sent when a client wants to open a file for writing.
// The Ropen method should be called to provide the opened file.
type Topen struct {
	Flag int // the mode to open the file in
	reqInfo
}

func (t Topen) Ropen(rwc interface{}, mode os.FileMode) {
	defer t.session.conn.clearTag(t.tag)
	var (
		file file
		f    styxfile.Interface
		err  error
	)
	if dir, ok := rwc.(Directory); ok && mode.IsDir() {
		f = styxfile.NewDir(dir, t.Path(), t.session.conn.qidpool)
	} else {
		f, err = styxfile.New(rwc)
	}

	if err != nil {
		t.session.conn.srv.logf("%s open %s failed: %s", t.path, err)

		// Don't want to expose too many implementation details
		// to clients.
		t.Rerror("open failed")
		return
	}
	t.session.files.Update(t.fid, &file, func() {
		file.rwc = f
	})
	qid := t.session.conn.qid(t.Path(), qidType(mode))
	t.session.conn.Ropen(t.tag, qid, 0)
}

func (t Topen) defaultResponse() {
	t.Rerror("permission denied")
}

// A Twalk message is sent when a client wants to check that a given
// file exists. Call its Rwalk method to answer.
type Twalk struct {
	newfid  uint32
	newpath string
	// We have to keep the original path around to give
	// the client the correct sequence of qids.
	dirtypath string
	reqInfo
}

// Path returns the absolute path of the directory the client
// is walking to. The path is normalized; all '..' sequences,
// double slashes, etc are removed.
func (t Twalk) Path() string {
	return t.newpath
}

// NOTE(droyo) This API needs some more thought. An Rwalk
// gives back the Qids for the path from the Twalk's fid, to
// the final element in nwelem. We're not taking info for the
// intermediates from the user, instead assuming QTDIR.
// Is that correct in every case?

func (t Twalk) Rwalk(exists bool, mode os.FileMode) {
	defer t.session.conn.clearTag(t.tag)
	if !exists {
		t.defaultResponse()
		return
	}

	t.session.files.Put(t.newfid, file{name: t.newpath})
	t.session.conn.sessionFid.Put(t.newfid, t.session)
	t.session.IncRef()

	qtype := qidType(mode)
	wqid := make([]styxproto.Qid, strings.Count(t.newpath, "/")+1)
	wqid[len(wqid)-1] = t.session.conn.qid(t.newpath, qtype)
	dir, _ := path.Split(t.newpath)
	for i := len(wqid) - 2; i >= 0; i-- {
		wqid[i] = t.session.conn.qid(dir, styxproto.QTDIR)
		if wqid[i].Type()&styxproto.QTDIR == 0 {
			t.Rerror("not a directory: %q", dir)
			return
		}
		dir, _ = path.Split(dir)
	}
	if err := t.session.conn.Rwalk(t.tag, wqid...); err != nil {
		panic(err)
	}
}

func (t Twalk) defaultResponse() {
	t.Rerror("no such file or directory")
}

// A Tstat message is sent when a client wants metadata about a file.
type Tstat struct {
	reqInfo
}

func (t Tstat) Rstat(info os.FileInfo) {
	defer t.session.conn.clearTag(t.tag)
	buf := make([]byte, styxproto.MaxStatLen)
	uid, gid, muid := sys.FileOwner(info)
	stat, _, err := styxproto.NewStat(buf,
		info.Name(), // name
		uid,
		gid,
		muid,
	)
	if err != nil {
		// should never happen
		panic(err)
	}
	stat.SetLength(info.Size())
	stat.SetMode(modePerm(info.Mode()))
	stat.SetAtime(uint32(info.ModTime().Unix())) // TODO: get atime
	stat.SetMtime(uint32(info.ModTime().Unix()))
	stat.SetQid(t.session.conn.qid(t.Path(), qidType(info.Mode())))
	t.session.conn.Rstat(t.tag, stat)
}

func (t Tstat) defaultResponse() {
	t.Rerror("permission denied")
}

// A Tcreate message is sent when a client wants to create a new file
// and open it with the provided Mode. The Path method of a Tcreate
// message returns the absolute path of the containing directory. A user
// must have write permissions in the directory to create a file.
type Tcreate struct {
	Name string      // name of the file to create
	Perm os.FileMode // permissions and file type to create
	Flag int         // flags to open the new file with
	reqInfo
}

func (t Tcreate) Rcreate(rwc interface{}) {
	defer t.session.conn.clearTag(t.tag)
	var (
		f   styxfile.Interface
		err error
	)
	if dir, ok := rwc.(Directory); t.Perm.IsDir() && ok {
		f = styxfile.NewDir(dir, path.Join(t.Path(), t.Name), t.session.conn.qidpool)
	} else {
		f, err = styxfile.New(rwc)
	}
	if err != nil {
		t.session.conn.srv.logf("create %s failed: %s", t.Name, err)
		t.Rerror("create failed")
		return
	}
	file := file{name: path.Join(t.Path(), t.Name), rwc: f}

	// fid for parent directory is now the fid for the new file,
	// so there is no increase in references to this session.
	t.session.files.Put(t.fid, file)

	qtype := qidType(t.Perm)
	qid := t.session.conn.qid(file.name, qtype)
	t.session.conn.Rcreate(t.tag, qid, 0)
}

func (t Tcreate) defaultResponse() {
	t.Rerror("permission denied")
}

// A Tremove message is sent when a client wants to delete a file
// from the server.
type Tremove struct {
	reqInfo
}

func (t Tremove) Rremove() {
	defer t.session.conn.clearTag(t.tag)
	t.session.conn.sessionFid.Del(t.fid)
	t.session.files.Del(t.fid)
	t.session.conn.qidpool.Del(t.Path())
	t.session.conn.Rremove(t.tag)
	if !t.session.DecRef() {
		t.session.close()
	}
}

func (t Tremove) defaultResponse() {
	t.Rerror("permission denied")
}

// A Twstat message is sent when a client wants to update the
// metadata about a file on the server.
type Twstat struct {
	Stat os.FileInfo
	reqInfo
}

func (t Twstat) Rwstat() {
	defer t.session.conn.clearTag(t.tag)
	t.session.conn.Rwstat(t.tag)
}

func (t Twstat) defaultResponse() {
	t.Rerror("permission denied")
}

// Make a Stat look like an os.FileInfo
type statInfo styxproto.Stat

func (s statInfo) Name() string { return string(styxproto.Stat(s).Name()) }
func (s statInfo) Size() int64  { return styxproto.Stat(s).Length() }

func (s statInfo) Mode() os.FileMode {
	return fileMode(styxproto.Stat(s).Mode())
}

func (s statInfo) ModTime() time.Time {
	return time.Unix(int64(styxproto.Stat(s).Mtime()), 0)
}

func (s statInfo) IsDir() bool {
	return styxproto.Stat(s).Mode()&styxproto.DMDIR != 0
}

func (s statInfo) Sys() interface{} {
	return styxproto.Stat(s)
}
<commit_msg>Generate the correct wqid array even on convoluted Twalk messages<commit_after>package styx

import (
	"os"
	"path"
	"strings"
	"time"

	"golang.org/x/net/context"

	"aqwari.net/net/styx/internal/styxfile"
	"aqwari.net/net/styx/internal/sys"
	"aqwari.net/net/styx/styxproto"
)

// A Request is a request by a client to perform an operation
// on a file or set of files. Types of requests may range from
// checking if a file exists (Twalk) to opening a file (Topen)
// to changing a file's name (Twstat).
type Request interface {
	// The context.Context interface is used to implement cancellation and
	// request timeouts. If an operation is going to take a long time to
	// complete, you can allow for the client to cancel the request by receiving
	// on the channel returned by Done().
	context.Context

	// If a request is invalid, not allowed, or cannot be completed properly
	// for some other reason, its Rerror method should be used to respond
	// to it.
	Rerror(format string, args ...interface{})

	// Path returns the Path of the file being operated on.
	Path() string

	// For the programmer's convenience, each request type has a default
	// response. Programmers can choose to ignore requests of a given
	// type and have the styx package send default responses to them.
	// In most cases, the default response is to send an error that the user
	// has insufficient permissions or the file in question does not exist.
	defaultResponse()
}

// common fields among all requests. Some may be nil for
// certain requests.
type reqInfo struct {
	context.Context
	tag     uint16
	fid     uint32
	session *Session
	msg     styxproto.Msg
	path    string
}

// Path returns the absolute path of the file being operated on.
func (info reqInfo) Path() string {
	return info.path
}

func (info reqInfo) Rerror(format string, args ...interface{}) {
	defer info.session.conn.clearTag(info.tag)
	info.session.conn.Rerror(info.tag, format, args...)
}

func newReqInfo(cx context.Context, s *Session, msg fcall, filepath string) reqInfo {
	return reqInfo{
		session: s,
		tag:     msg.Tag(),
		fid:     msg.Fid(),
		Context: cx,
		msg:     msg,
		path:    filepath,
	}
}

func qidType(mode os.FileMode) uint8 {
	var qtype uint8
	if mode&os.ModeDir != 0 {
		qtype = styxproto.QTDIR
	}
	if mode&os.ModeAppend != 0 {
		qtype |= styxproto.QTAPPEND
	}
	if mode&os.ModeExclusive != 0 {
		qtype |= styxproto.QTEXCL
	}
	if mode&os.ModeTemporary != 0 {
		qtype |= styxproto.QTTMP
	}
	return qtype
}

func fileMode(perm uint32) os.FileMode {
	var mode os.FileMode
	if perm&styxproto.DMDIR != 0 {
		mode = os.ModeDir
	}
	if perm&styxproto.DMAPPEND != 0 {
		mode |= os.ModeAppend
	}
	if perm&styxproto.DMEXCL != 0 {
		mode |= os.ModeExclusive
	}
	if perm&styxproto.DMTMP != 0 {
		mode |= os.ModeTemporary
	}
	mode |= (os.FileMode(perm) & os.ModePerm)
	return mode
}

func modePerm(mode os.FileMode) uint32 {
	var perm uint32
	if mode&os.ModeDir != 0 {
		perm |= styxproto.DMDIR
	}
	if mode&os.ModeAppend != 0 {
		perm |= styxproto.DMAPPEND
	}
	if mode&os.ModeExclusive != 0 {
		perm |= styxproto.DMEXCL
	}
	if mode&os.ModeTemporary != 0 {
		perm |= styxproto.DMTMP
	}
	return perm | uint32(mode&os.ModePerm)
}

// A Topen message is sent when a client wants to open a file for writing.
// The Ropen method should be called to provide the opened file.
type Topen struct {
	Flag int // the mode to open the file in
	reqInfo
}

func (t Topen) Ropen(rwc interface{}, mode os.FileMode) {
	defer t.session.conn.clearTag(t.tag)
	var (
		file file
		f    styxfile.Interface
		err  error
	)
	if dir, ok := rwc.(Directory); ok && mode.IsDir() {
		f = styxfile.NewDir(dir, t.Path(), t.session.conn.qidpool)
	} else {
		f, err = styxfile.New(rwc)
	}

	if err != nil {
		t.session.conn.srv.logf("%s open %s failed: %s", t.path, err)

		// Don't want to expose too many implementation details
		// to clients.
		t.Rerror("open failed")
		return
	}
	t.session.files.Update(t.fid, &file, func() {
		file.rwc = f
	})
	qid := t.session.conn.qid(t.Path(), qidType(mode))
	t.session.conn.Ropen(t.tag, qid, 0)
}

func (t Topen) defaultResponse() {
	t.Rerror("permission denied")
}

// A Twalk message is sent when a client wants to check that a given
// file exists. Call its Rwalk method to answer.
type Twalk struct {
	newfid  uint32
	newpath string
	// We have to keep the original path around to give
	// the client the correct sequence of qids.
	dirtypath string
	reqInfo
}

// Path returns the absolute path of the directory the client
// is walking to. The path is normalized; all '..' sequences,
// double slashes, etc are removed.
func (t Twalk) Path() string {
	return t.newpath
}

// NOTE(droyo) This API needs some more thought. An Rwalk
// gives back the Qids for the path from the Twalk's fid, to
// the final element in nwelem. We're not taking info for the
// intermediates from the user, instead assuming QTDIR.
// Is that correct in every case?

func (t Twalk) Rwalk(exists bool, mode os.FileMode) {
	defer t.session.conn.clearTag(t.tag)
	if !exists {
		t.defaultResponse()
		return
	}

	t.session.files.Put(t.newfid, file{name: t.newpath})
	t.session.conn.sessionFid.Put(t.newfid, t.session)
	t.session.IncRef()

	qtype := qidType(mode)
	wqid := make([]styxproto.Qid, strings.Count(t.dirtypath, "/")+1)
	wqid[len(wqid)-1] = t.session.conn.qid(t.newpath, qtype)
	dir, _ := path.Split(t.dirtypath)
	for i := len(wqid) - 2; i >= 0; i-- {
		wqid[i] = t.session.conn.qid(path.Clean(dir), styxproto.QTDIR)
		if wqid[i].Type()&styxproto.QTDIR == 0 {
			t.Rerror("not a directory: %q", dir)
			return
		}
		dir, _ = path.Split(dir)
	}
	if err := t.session.conn.Rwalk(t.tag, wqid...); err != nil {
		panic(err)
	}
}

func (t Twalk) defaultResponse() {
	t.Rerror("no such file or directory")
}

// A Tstat message is sent when a client wants metadata about a file.
type Tstat struct {
	reqInfo
}

func (t Tstat) Rstat(info os.FileInfo) {
	defer t.session.conn.clearTag(t.tag)
	buf := make([]byte, styxproto.MaxStatLen)
	uid, gid, muid := sys.FileOwner(info)
	stat, _, err := styxproto.NewStat(buf,
		info.Name(), // name
		uid,
		gid,
		muid,
	)
	if err != nil {
		// should never happen
		panic(err)
	}
	stat.SetLength(info.Size())
	stat.SetMode(modePerm(info.Mode()))
	stat.SetAtime(uint32(info.ModTime().Unix())) // TODO: get atime
	stat.SetMtime(uint32(info.ModTime().Unix()))
	stat.SetQid(t.session.conn.qid(t.Path(), qidType(info.Mode())))
	t.session.conn.Rstat(t.tag, stat)
}

func (t Tstat) defaultResponse() {
	t.Rerror("permission denied")
}

// A Tcreate message is sent when a client wants to create a new file
// and open it with the provided Mode. The Path method of a Tcreate
// message returns the absolute path of the containing directory. A user
// must have write permissions in the directory to create a file.
type Tcreate struct {
	Name string      // name of the file to create
	Perm os.FileMode // permissions and file type to create
	Flag int         // flags to open the new file with
	reqInfo
}

func (t Tcreate) Rcreate(rwc interface{}) {
	defer t.session.conn.clearTag(t.tag)
	var (
		f   styxfile.Interface
		err error
	)
	if dir, ok := rwc.(Directory); t.Perm.IsDir() && ok {
		f = styxfile.NewDir(dir, path.Join(t.Path(), t.Name), t.session.conn.qidpool)
	} else {
		f, err = styxfile.New(rwc)
	}
	if err != nil {
		t.session.conn.srv.logf("create %s failed: %s", t.Name, err)
		t.Rerror("create failed")
		return
	}
	file := file{name: path.Join(t.Path(), t.Name), rwc: f}

	// fid for parent directory is now the fid for the new file,
	// so there is no increase in references to this session.
	t.session.files.Put(t.fid, file)

	qtype := qidType(t.Perm)
	qid := t.session.conn.qid(file.name, qtype)
	t.session.conn.Rcreate(t.tag, qid, 0)
}

func (t Tcreate) defaultResponse() {
	t.Rerror("permission denied")
}

// A Tremove message is sent when a client wants to delete a file
// from the server.
type Tremove struct {
	reqInfo
}

func (t Tremove) Rremove() {
	defer t.session.conn.clearTag(t.tag)
	t.session.conn.sessionFid.Del(t.fid)
	t.session.files.Del(t.fid)
	t.session.conn.qidpool.Del(t.Path())
	t.session.conn.Rremove(t.tag)
	if !t.session.DecRef() {
		t.session.close()
	}
}

func (t Tremove) defaultResponse() {
	t.Rerror("permission denied")
}

// A Twstat message is sent when a client wants to update the
// metadata about a file on the server.
type Twstat struct {
	Stat os.FileInfo
	reqInfo
}

func (t Twstat) Rwstat() {
	defer t.session.conn.clearTag(t.tag)
	t.session.conn.Rwstat(t.tag)
}

func (t Twstat) defaultResponse() {
	t.Rerror("permission denied")
}

// Make a Stat look like an os.FileInfo
type statInfo styxproto.Stat

func (s statInfo) Name() string { return string(styxproto.Stat(s).Name()) }
func (s statInfo) Size() int64  { return styxproto.Stat(s).Length() }

func (s statInfo) Mode() os.FileMode {
	return fileMode(styxproto.Stat(s).Mode())
}

func (s statInfo) ModTime() time.Time {
	return time.Unix(int64(styxproto.Stat(s).Mtime()), 0)
}

func (s statInfo) IsDir() bool {
	return styxproto.Stat(s).Mode()&styxproto.DMDIR != 0
}

func (s statInfo) Sys() interface{} {
	return styxproto.Stat(s)
}
<|endoftext|>


<commit_before>package gorequest

/**
 * TODO: document
 */

import (
	r "gorequest/request"
)

/**
 * Single entry point into the API. A Request instance can only be created
 * using a RequestBuilder instance, and this is the only public RequestBuilder
 * constructor.
 */
var NewRequestBuilder r.RequestBuilderConstructor = r.NewRequestBuilder
<commit_msg>Use fully qualified package name.<commit_after>package gorequest

/**
 * TODO: document
 */

import (
	r "github.com/mscheker/gorequest/request"
)

/**
 * Single entry point into the API. A Request instance can only be created
 * using a RequestBuilder instance, and this is the only public RequestBuilder
 * constructor.
 */
var NewRequestBuilder r.RequestBuilderConstructor = r.NewRequestBuilder
<|endoftext|>


<commit_before>package guber

import (
	"bytes"
	"encoding/json"
	"errors"
	"fmt"
	"io/ioutil"
	"net/http"
	"path"
	"strings"
)

type Error404 struct{}

func (e *Error404) Error() string {
	return "Resource not found"
}

type Request struct {
	client    *RealClient
	method    string
	headers   map[string]string
	basePath  string
	query     string
	path      string
	resource  string
	namespace string
	name      string
	body      []byte

	err          error
	response     *http.Response
	responseBody []byte
}

// Implement Stringer interface
func (r *Request) String() string {
	obj := struct {
		Method       string
		Headers      map[string]string
		URL          string
		Status       int
		RequestBody  string
		ResponseBody string
	}{
		r.method,
		r.headers,
		r.url(),
		r.response.StatusCode,
		string(r.body),
		string(r.responseBody),
	}
	out, err := json.MarshalIndent(obj, "", "  ")
	if err != nil {
		panic(err)
	}
	return string(out)
}

func (r *Request) error(err error) {
	if err != nil && r.err == nil {
		r.err = err
	}
}

func (r *Request) url() string {
	resourcePath := path.Join(r.resource, r.name, r.path)

	if r.namespace != "" {
		resourcePath = path.Join("namespaces", r.namespace, resourcePath)
	}
	if r.query != "" {
		resourcePath += "?" + r.query
	}
	return "https://" + path.Join(r.client.Host, r.basePath, resourcePath)
}

func (r *Request) Collection(c Collection) *Request {
	m := c.Meta()
	r.basePath = path.Join(m.DomainName, m.APIGroup, m.APIVersion)
	r.resource = m.APIName
	return r
}

func (r *Request) Namespace(namespace string) *Request {
	r.namespace = namespace
	return r
}

func (r *Request) Name(name string) *Request {
	r.name = name
	return r
}

func (r *Request) Entity(e Entity) *Request {
	body, err := json.Marshal(e)
	r.body = body
	r.error(err)
	return r
}

func (r *Request) Query(q *QueryParams) *Request {
	if q == nil {
		return r
	}

	var segments []string
	if ls := q.LabelSelector; ls != "" {
		segments = append(segments, "labelSelector="+ls)
	}
	if fs := q.FieldSelector; fs != "" {
		segments = append(segments, "fieldSelector="+fs)
	}
	r.query = strings.Join(segments, "&")

	return r
}

func (r *Request) Path(path string) *Request {
	r.path = path
	return r
}

func (r *Request) Do() *Request {
	req, err := http.NewRequest(r.method, r.url(), bytes.NewBuffer(r.body))
	if err != nil {
		panic(err) // TODO
	}

	req.SetBasicAuth(r.client.Username, r.client.Password)
	r.error(err)

	for k, v := range r.headers {
		req.Header.Set(k, v)
	}

	resp, err := r.client.http.Do(req)
	r.error(err)

	// TODO
	if resp != nil {
		r.response = resp

		r.readBody()

		if resp.StatusCode == 404 {
			r.error(new(Error404))
		} else if status := resp.Status; status[:2] != "20" {
			r.error(fmt.Errorf("Status: %s, Body: %s", status, string(r.responseBody)))
		}

		Log.Debug(r)
	}

	return r
}

func (r *Request) readBody() {
	if r.response == nil {
		r.error(errors.New("Response is nil"))
		return
	}
	defer r.response.Body.Close()
	body, err := ioutil.ReadAll(r.response.Body)
	r.responseBody = body
	r.error(err)
}

func (r *Request) Body() (string, error) {
	return string(r.responseBody), r.err
}

// The exit point for a Request (where error is pooped out)
func (r *Request) Into(e Entity) error {
	if r.responseBody != nil {
		json.Unmarshal(r.responseBody, e)
	}
	return r.err
}
<commit_msg>Add Error409 for resource creation conflict<commit_after>package guber

import (
	"bytes"
	"encoding/json"
	"errors"
	"fmt"
	"io/ioutil"
	"net/http"
	"path"
	"strings"
)

type Error404 struct{}

func (e *Error404) Error() string {
	return "Resource not found"
}

type Error409 struct{}

func (e *Error409) Error() string {
	return "Resource already exists"
}

type Request struct {
	client    *RealClient
	method    string
	headers   map[string]string
	basePath  string
	query     string
	path      string
	resource  string
	namespace string
	name      string
	body      []byte

	err          error
	response     *http.Response
	responseBody []byte
}

// Implement Stringer interface
func (r *Request) String() string {
	obj := struct {
		Method       string
		Headers      map[string]string
		URL          string
		Status       int
		RequestBody  string
		ResponseBody string
	}{
		r.method,
		r.headers,
		r.url(),
		r.response.StatusCode,
		string(r.body),
		string(r.responseBody),
	}
	out, err := json.MarshalIndent(obj, "", "  ")
	if err != nil {
		panic(err)
	}
	return string(out)
}

func (r *Request) error(err error) {
	if err != nil && r.err == nil {
		r.err = err
	}
}

func (r *Request) url() string {
	resourcePath := path.Join(r.resource, r.name, r.path)

	if r.namespace != "" {
		resourcePath = path.Join("namespaces", r.namespace, resourcePath)
	}
	if r.query != "" {
		resourcePath += "?" + r.query
	}
	return "https://" + path.Join(r.client.Host, r.basePath, resourcePath)
}

func (r *Request) Collection(c Collection) *Request {
	m := c.Meta()
	r.basePath = path.Join(m.DomainName, m.APIGroup, m.APIVersion)
	r.resource = m.APIName
	return r
}

func (r *Request) Namespace(namespace string) *Request {
	r.namespace = namespace
	return r
}

func (r *Request) Name(name string) *Request {
	r.name = name
	return r
}

func (r *Request) Entity(e Entity) *Request {
	body, err := json.Marshal(e)
	r.body = body
	r.error(err)
	return r
}

func (r *Request) Query(q *QueryParams) *Request {
	if q == nil {
		return r
	}

	var segments []string
	if ls := q.LabelSelector; ls != "" {
		segments = append(segments, "labelSelector="+ls)
	}
	if fs := q.FieldSelector; fs != "" {
		segments = append(segments, "fieldSelector="+fs)
	}
	r.query = strings.Join(segments, "&")

	return r
}

func (r *Request) Path(path string) *Request {
	r.path = path
	return r
}

func (r *Request) Do() *Request {
	req, err := http.NewRequest(r.method, r.url(), bytes.NewBuffer(r.body))
	if err != nil {
		panic(err) // TODO
	}

	req.SetBasicAuth(r.client.Username, r.client.Password)
	r.error(err)

	for k, v := range r.headers {
		req.Header.Set(k, v)
	}

	resp, err := r.client.http.Do(req)
	r.error(err)

	// TODO
	if resp != nil {
		r.response = resp

		r.readBody()

		if resp.StatusCode == 404 {
			r.error(new(Error404))
		} else if resp.StatusCode == 409 {
			r.error(new(Error409))
		} else if status := resp.Status; status[:2] != "20" {
			r.error(fmt.Errorf("Status: %s, Body: %s", status, string(r.responseBody)))
		}

		Log.Debug(r)
	}

	return r
}

func (r *Request) readBody() {
	if r.response == nil {
		r.error(errors.New("Response is nil"))
		return
	}
	defer r.response.Body.Close()
	body, err := ioutil.ReadAll(r.response.Body)
	r.responseBody = body
	r.error(err)
}

func (r *Request) Body() (string, error) {
	return string(r.responseBody), r.err
}

// The exit point for a Request (where error is pooped out)
func (r *Request) Into(e Entity) error {
	if r.responseBody != nil {
		json.Unmarshal(r.responseBody, e)
	}
	return r.err
}
<|endoftext|>


<commit_before>package main

import (
	"sync"
	"time"

	"github.com/grafana/grafana/pkg/log"
)

type AggMetrics struct {
	store Store
	sync.RWMutex
	Metrics        map[string]*AggMetric
	chunkSpan      uint32
	numChunks      uint32
	aggSettings    []aggSetting // for now we apply the same settings to all AggMetrics. later we may want to have different settings.
	chunkMaxStale  uint32
	metricMaxStale uint32
	ttl            uint32
	gcInterval     time.Duration
}

var totalPoints chan int

func init() {
	// measurements can lag a bit, that's ok
	totalPoints = make(chan int, 1000)
}

func NewAggMetrics(store Store, chunkSpan, numChunks, chunkMaxStale, metricMaxStale uint32, ttl uint32, gcInterval time.Duration, aggSettings []aggSetting) *AggMetrics {
	ms := AggMetrics{
		store:          store,
		Metrics:        make(map[string]*AggMetric),
		chunkSpan:      chunkSpan,
		numChunks:      numChunks,
		aggSettings:    aggSettings,
		chunkMaxStale:  chunkMaxStale,
		metricMaxStale: metricMaxStale,
		ttl:            ttl,
		gcInterval:     gcInterval,
	}

	go ms.stats()
	go ms.GC()
	return &ms
}

// periodically scan chunks and close any that have not received data in a while
// TODO instrument occurences and duration of GC
func (ms *AggMetrics) GC() {
	for {
		unix := time.Duration(time.Now().UnixNano())
		period := time.Duration(ms.gcInterval) * time.Second
		diff := period - (unix % period)
		time.Sleep(diff + time.Minute)
		log.Info("checking for stale chunks that need persisting.")
		now := uint32(time.Now().Unix())
		chunkMinTs := now - (now % ms.chunkSpan) - uint32(ms.chunkMaxStale)
		metricMinTs := now - (now % ms.chunkSpan) - uint32(ms.metricMaxStale)

		// as this is the only goroutine that can delete from ms.Metrics
		// we only need to lock long enough to get the list of actives metrics.
		// it doesnt matter if new metrics are added while we iterate this list.
		ms.RLock()
		keys := make([]string, 0, len(ms.Metrics))
		for k := range ms.Metrics {
			keys = append(keys, k)
		}
		ms.RUnlock()
		for _, key := range keys {
			gcMetric.Inc(1)
			ms.RLock()
			a := ms.Metrics[key]
			ms.RUnlock()
			if stale := a.GC(chunkMinTs, metricMinTs); stale {
				log.Info("metric %s is stale. Purging data from memory.", key)
				ms.Lock()
				delete(ms.Metrics, key)
				ms.Unlock()
			}
		}

	}
}

func (ms *AggMetrics) stats() {
	for range time.Tick(time.Duration(1) * time.Second) {
		ms.RLock()
		metricsActive.Value(int64(len(ms.Metrics)))
		ms.RUnlock()
	}
}

func (ms *AggMetrics) Get(key string) (Metric, bool) {
	ms.RLock()
	m, ok := ms.Metrics[key]
	ms.RUnlock()
	return m, ok
}

func (ms *AggMetrics) GetOrCreate(key string) Metric {
	ms.Lock()
	m, ok := ms.Metrics[key]
	if !ok {
		m = NewAggMetric(ms.store, key, ms.chunkSpan, ms.numChunks, ms.ttl, ms.aggSettings...)
		ms.Metrics[key] = m
	}
	ms.Unlock()
	return m
}
<commit_msg>bugfix: gcInterval was already a duration, so don't multiply by 10^9<commit_after>package main

import (
	"sync"
	"time"

	"github.com/grafana/grafana/pkg/log"
)

type AggMetrics struct {
	store Store
	sync.RWMutex
	Metrics        map[string]*AggMetric
	chunkSpan      uint32
	numChunks      uint32
	aggSettings    []aggSetting // for now we apply the same settings to all AggMetrics. later we may want to have different settings.
	chunkMaxStale  uint32
	metricMaxStale uint32
	ttl            uint32
	gcInterval     time.Duration
}

var totalPoints chan int

func init() {
	// measurements can lag a bit, that's ok
	totalPoints = make(chan int, 1000)
}

func NewAggMetrics(store Store, chunkSpan, numChunks, chunkMaxStale, metricMaxStale uint32, ttl uint32, gcInterval time.Duration, aggSettings []aggSetting) *AggMetrics {
	ms := AggMetrics{
		store:          store,
		Metrics:        make(map[string]*AggMetric),
		chunkSpan:      chunkSpan,
		numChunks:      numChunks,
		aggSettings:    aggSettings,
		chunkMaxStale:  chunkMaxStale,
		metricMaxStale: metricMaxStale,
		ttl:            ttl,
		gcInterval:     gcInterval,
	}

	go ms.stats()
	go ms.GC()
	return &ms
}

// periodically scan chunks and close any that have not received data in a while
// TODO instrument occurences and duration of GC
func (ms *AggMetrics) GC() {
	for {
		unix := time.Duration(time.Now().UnixNano())
		diff := ms.gcInterval - (unix % ms.gcInterval)
		time.Sleep(diff + time.Minute)
		log.Info("checking for stale chunks that need persisting.")
		now := uint32(time.Now().Unix())
		chunkMinTs := now - (now % ms.chunkSpan) - uint32(ms.chunkMaxStale)
		metricMinTs := now - (now % ms.chunkSpan) - uint32(ms.metricMaxStale)

		// as this is the only goroutine that can delete from ms.Metrics
		// we only need to lock long enough to get the list of actives metrics.
		// it doesnt matter if new metrics are added while we iterate this list.
		ms.RLock()
		keys := make([]string, 0, len(ms.Metrics))
		for k := range ms.Metrics {
			keys = append(keys, k)
		}
		ms.RUnlock()
		for _, key := range keys {
			gcMetric.Inc(1)
			ms.RLock()
			a := ms.Metrics[key]
			ms.RUnlock()
			if stale := a.GC(chunkMinTs, metricMinTs); stale {
				log.Info("metric %s is stale. Purging data from memory.", key)
				ms.Lock()
				delete(ms.Metrics, key)
				ms.Unlock()
			}
		}

	}
}

func (ms *AggMetrics) stats() {
	for range time.Tick(time.Duration(1) * time.Second) {
		ms.RLock()
		metricsActive.Value(int64(len(ms.Metrics)))
		ms.RUnlock()
	}
}

func (ms *AggMetrics) Get(key string) (Metric, bool) {
	ms.RLock()
	m, ok := ms.Metrics[key]
	ms.RUnlock()
	return m, ok
}

func (ms *AggMetrics) GetOrCreate(key string) Metric {
	ms.Lock()
	m, ok := ms.Metrics[key]
	if !ok {
		m = NewAggMetric(ms.store, key, ms.chunkSpan, ms.numChunks, ms.ttl, ms.aggSettings...)
		ms.Metrics[key] = m
	}
	ms.Unlock()
	return m
}
<|endoftext|>