<commit_before>// Copyright 2017 PingCAP, Inc.
//
// 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 expression

import (
	"fmt"
	"testing"

	"github.com/pingcap/tidb/parser/model"
	"github.com/pingcap/tidb/parser/mysql"
	"github.com/pingcap/tidb/types"
	"github.com/pingcap/tidb/util/chunk"
	"github.com/pingcap/tidb/util/mock"
	"github.com/stretchr/testify/require"
)

func TestColumn(t *testing.T) {
	t.Parallel()

	ctx := mock.NewContext()
	col := &Column{RetType: types.NewFieldType(mysql.TypeLonglong), UniqueID: 1}

	require.True(t, col.Equal(nil, col))
	require.False(t, col.Equal(nil, &Column{}))
	require.False(t, col.IsCorrelated())
	require.True(t, col.Equal(nil, col.Decorrelate(nil)))

	marshal, err := col.MarshalJSON()
	require.NoError(t, err)
	require.EqualValues(t, []byte{0x22, 0x43, 0x6f, 0x6c, 0x75, 0x6d, 0x6e, 0x23, 0x31, 0x22}, marshal)

	intDatum := types.NewIntDatum(1)
	corCol := &CorrelatedColumn{Column: *col, Data: &intDatum}
	invalidCorCol := &CorrelatedColumn{Column: Column{}}
	schema := NewSchema(&Column{UniqueID: 1})
	require.True(t, corCol.Equal(nil, corCol))
	require.False(t, corCol.Equal(nil, invalidCorCol))
	require.True(t, corCol.IsCorrelated())
	require.False(t, corCol.ConstItem(nil))
	require.True(t, corCol.Decorrelate(schema).Equal(nil, col))
	require.True(t, invalidCorCol.Decorrelate(schema).Equal(nil, invalidCorCol))

	intCorCol := &CorrelatedColumn{Column: Column{RetType: types.NewFieldType(mysql.TypeLonglong)},
		Data: &intDatum}
	intVal, isNull, err := intCorCol.EvalInt(ctx, chunk.Row{})
	require.Equal(t, int64(1), intVal)
	require.False(t, isNull)
	require.NoError(t, err)

	realDatum := types.NewFloat64Datum(1.2)
	realCorCol := &CorrelatedColumn{Column: Column{RetType: types.NewFieldType(mysql.TypeDouble)},
		Data: &realDatum}
	realVal, isNull, err := realCorCol.EvalReal(ctx, chunk.Row{})
	require.Equal(t, float64(1.2), realVal)
	require.False(t, isNull)
	require.NoError(t, err)

	decimalDatum := types.NewDecimalDatum(types.NewDecFromStringForTest("1.2"))
	decimalCorCol := &CorrelatedColumn{Column: Column{RetType: types.NewFieldType(mysql.TypeNewDecimal)},
		Data: &decimalDatum}
	decVal, isNull, err := decimalCorCol.EvalDecimal(ctx, chunk.Row{})
	require.Equal(t, 0, decVal.Compare(types.NewDecFromStringForTest("1.2")))
	require.False(t, isNull)
	require.NoError(t, err)

	stringDatum := types.NewStringDatum("abc")
	stringCorCol := &CorrelatedColumn{Column: Column{RetType: types.NewFieldType(mysql.TypeVarchar)},
		Data: &stringDatum}
	strVal, isNull, err := stringCorCol.EvalString(ctx, chunk.Row{})
	require.Equal(t, "abc", strVal)
	require.False(t, isNull)
	require.NoError(t, err)

	durationCorCol := &CorrelatedColumn{Column: Column{RetType: types.NewFieldType(mysql.TypeDuration)},
		Data: &durationDatum}
	durationVal, isNull, err := durationCorCol.EvalDuration(ctx, chunk.Row{})
	require.Equal(t, 0, durationVal.Compare(duration))
	require.False(t, isNull)
	require.NoError(t, err)

	timeDatum := types.NewTimeDatum(tm)
	timeCorCol := &CorrelatedColumn{Column: Column{RetType: types.NewFieldType(mysql.TypeDatetime)},
		Data: &timeDatum}
	timeVal, isNull, err := timeCorCol.EvalTime(ctx, chunk.Row{})
	require.Equal(t, 0, timeVal.Compare(tm))
	require.False(t, isNull)
	require.NoError(t, err)
}

func TestColumnHashCode(t *testing.T) {
	t.Parallel()

	col1 := &Column{
		UniqueID: 12,
	}
	require.EqualValues(t, []byte{0x1, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xc}, col1.HashCode(nil))

	col2 := &Column{
		UniqueID: 2,
	}
	require.EqualValues(t, []byte{0x1, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2}, col2.HashCode(nil))
}

func TestColumn2Expr(t *testing.T) {
	t.Parallel()

	cols := make([]*Column, 0, 5)
	for i := 0; i < 5; i++ {
		cols = append(cols, &Column{UniqueID: int64(i)})
	}

	exprs := Column2Exprs(cols)
	for i := range exprs {
		require.True(t, exprs[i].Equal(nil, cols[i]))
	}
}

func TestColInfo2Col(t *testing.T) {
	t.Parallel()

	col0, col1 := &Column{ID: 0}, &Column{ID: 1}
	cols := []*Column{col0, col1}
	colInfo := &model.ColumnInfo{ID: 0}
	res := ColInfo2Col(cols, colInfo)
	require.True(t, res.Equal(nil, col1))

	colInfo.ID = 3
	res = ColInfo2Col(cols, colInfo)
	require.Nil(t, res)
}

func TestIndexInfo2Cols(t *testing.T) {
	t.Parallel()

	col0 := &Column{UniqueID: 0, ID: 0, RetType: types.NewFieldType(mysql.TypeLonglong)}
	col1 := &Column{UniqueID: 1, ID: 1, RetType: types.NewFieldType(mysql.TypeLonglong)}
	colInfo0 := &model.ColumnInfo{ID: 0, Name: model.NewCIStr("0")}
	colInfo1 := &model.ColumnInfo{ID: 1, Name: model.NewCIStr("1")}
	indexCol0, indexCol1 := &model.IndexColumn{Name: model.NewCIStr("0")}, &model.IndexColumn{Name: model.NewCIStr("1")}
	indexInfo := &model.IndexInfo{Columns: []*model.IndexColumn{indexCol0, indexCol1}}

	cols := []*Column{col0}
	colInfos := []*model.ColumnInfo{colInfo0}
	resCols, lengths := IndexInfo2PrefixCols(colInfos, cols, indexInfo)
	require.Equal(t, 1, len(resCols))
	require.Equal(t, 1, len(lengths))
	require.True(t, resCols[0].Equal(nil, col0))

	cols = []*Column{col1}
	colInfos = []*model.ColumnInfo{colInfo1}
	resCols, lengths = IndexInfo2PrefixCols(colInfos, cols, indexInfo)
	require.Equal(t, 0, len(resCols))
	require.Equal(t, 0, len(lengths))

	cols = []*Column{col0, col1}
	colInfos = []*model.ColumnInfo{colInfo0, colInfo1}
	resCols, lengths = IndexInfo2PrefixCols(colInfos, cols, indexInfo)
	require.Equal(t, 2, len(resCols))
	require.Equal(t, 2, len(lengths))
	require.True(t, resCols[0].Equal(nil, col0))
	require.True(t, resCols[1].Equal(nil, col1))
}

func TestColHybird(t *testing.T) {
	t.Parallel()

	ctx := mock.NewContext()

	// bit
	ft := types.NewFieldType(mysql.TypeBit)
	col := &Column{RetType: ft, Index: 0}
	input := chunk.New([]*types.FieldType{ft}, 1024, 1024)
	for i := 0; i < 1024; i++ {
		num, err := types.ParseBitStr(fmt.Sprintf("0b%b", i))
		require.NoError(t, err)
		input.AppendBytes(0, num)
	}
	result := chunk.NewColumn(types.NewFieldType(mysql.TypeLonglong), 1024)
	require.Nil(t, col.VecEvalInt(ctx, input, result))

	it := chunk.NewIterator4Chunk(input)
	for row, i := it.Begin(), 0; row != it.End(); row, i = it.Next(), i+1 {
		v, _, err := col.EvalInt(ctx, row)
		require.NoError(t, err)
		require.Equal(t, result.GetInt64(i), v)
	}

	// use a container which has the different field type with bit
	result = chunk.NewColumn(types.NewFieldType(mysql.TypeString), 1024)
	require.Nil(t, col.VecEvalInt(ctx, input, result))
	for row, i := it.Begin(), 0; row != it.End(); row, i = it.Next(), i+1 {
		v, _, err := col.EvalInt(ctx, row)
		require.NoError(t, err)
		require.Equal(t, result.GetInt64(i), v)
	}

	// enum
	ft = types.NewFieldType(mysql.TypeEnum)
	col.RetType = ft
	input = chunk.New([]*types.FieldType{ft}, 1024, 1024)
	for i := 0; i < 1024; i++ {
		input.AppendEnum(0, types.Enum{Name: fmt.Sprintf("%v", i), Value: uint64(i)})
	}
	result = chunk.NewColumn(types.NewFieldType(mysql.TypeString), 1024)
	require.Nil(t, col.VecEvalString(ctx, input, result))

	it = chunk.NewIterator4Chunk(input)
	for row, i := it.Begin(), 0; row != it.End(); row, i = it.Next(), i+1 {
		v, _, err := col.EvalString(ctx, row)
		require.NoError(t, err)
		require.Equal(t, result.GetString(i), v)
	}

	// set
	ft = types.NewFieldType(mysql.TypeSet)
	col.RetType = ft
	input = chunk.New([]*types.FieldType{ft}, 1024, 1024)
	for i := 0; i < 1024; i++ {
		input.AppendSet(0, types.Set{Name: fmt.Sprintf("%v", i), Value: uint64(i)})
	}
	result = chunk.NewColumn(types.NewFieldType(mysql.TypeString), 1024)
	require.Nil(t, col.VecEvalString(ctx, input, result))

	it = chunk.NewIterator4Chunk(input)
	for row, i := it.Begin(), 0; row != it.End(); row, i = it.Next(), i+1 {
		v, _, err := col.EvalString(ctx, row)
		require.NoError(t, err)
		require.Equal(t, result.GetString(i), v)
	}
}
<commit_msg>expression: migrate test-infra to testify for expression/column_test.… (#29198)<commit_after>// Copyright 2017 PingCAP, Inc.
//
// 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 expression

import (
	"fmt"
	"testing"

	"github.com/pingcap/tidb/parser/model"
	"github.com/pingcap/tidb/parser/mysql"
	"github.com/pingcap/tidb/types"
	"github.com/pingcap/tidb/util/chunk"
	"github.com/pingcap/tidb/util/mock"
	"github.com/stretchr/testify/require"
)

func TestColumn(t *testing.T) {
	t.Parallel()

	ctx := mock.NewContext()
	col := &Column{RetType: types.NewFieldType(mysql.TypeLonglong), UniqueID: 1}

	require.True(t, col.Equal(nil, col))
	require.False(t, col.Equal(nil, &Column{}))
	require.False(t, col.IsCorrelated())
	require.True(t, col.Equal(nil, col.Decorrelate(nil)))

	marshal, err := col.MarshalJSON()
	require.NoError(t, err)
	require.EqualValues(t, []byte{0x22, 0x43, 0x6f, 0x6c, 0x75, 0x6d, 0x6e, 0x23, 0x31, 0x22}, marshal)

	intDatum := types.NewIntDatum(1)
	corCol := &CorrelatedColumn{Column: *col, Data: &intDatum}
	invalidCorCol := &CorrelatedColumn{Column: Column{}}
	schema := NewSchema(&Column{UniqueID: 1})
	require.True(t, corCol.Equal(nil, corCol))
	require.False(t, corCol.Equal(nil, invalidCorCol))
	require.True(t, corCol.IsCorrelated())
	require.False(t, corCol.ConstItem(nil))
	require.True(t, corCol.Decorrelate(schema).Equal(nil, col))
	require.True(t, invalidCorCol.Decorrelate(schema).Equal(nil, invalidCorCol))

	intCorCol := &CorrelatedColumn{Column: Column{RetType: types.NewFieldType(mysql.TypeLonglong)},
		Data: &intDatum}
	intVal, isNull, err := intCorCol.EvalInt(ctx, chunk.Row{})
	require.Equal(t, int64(1), intVal)
	require.False(t, isNull)
	require.NoError(t, err)

	realDatum := types.NewFloat64Datum(1.2)
	realCorCol := &CorrelatedColumn{Column: Column{RetType: types.NewFieldType(mysql.TypeDouble)},
		Data: &realDatum}
	realVal, isNull, err := realCorCol.EvalReal(ctx, chunk.Row{})
	require.Equal(t, float64(1.2), realVal)
	require.False(t, isNull)
	require.NoError(t, err)

	decimalDatum := types.NewDecimalDatum(types.NewDecFromStringForTest("1.2"))
	decimalCorCol := &CorrelatedColumn{Column: Column{RetType: types.NewFieldType(mysql.TypeNewDecimal)},
		Data: &decimalDatum}
	decVal, isNull, err := decimalCorCol.EvalDecimal(ctx, chunk.Row{})
	require.Zero(t, decVal.Compare(types.NewDecFromStringForTest("1.2")))
	require.False(t, isNull)
	require.NoError(t, err)

	stringDatum := types.NewStringDatum("abc")
	stringCorCol := &CorrelatedColumn{Column: Column{RetType: types.NewFieldType(mysql.TypeVarchar)},
		Data: &stringDatum}
	strVal, isNull, err := stringCorCol.EvalString(ctx, chunk.Row{})
	require.Equal(t, "abc", strVal)
	require.False(t, isNull)
	require.NoError(t, err)

	durationCorCol := &CorrelatedColumn{Column: Column{RetType: types.NewFieldType(mysql.TypeDuration)},
		Data: &durationDatum}
	durationVal, isNull, err := durationCorCol.EvalDuration(ctx, chunk.Row{})
	require.Zero(t, durationVal.Compare(duration))
	require.False(t, isNull)
	require.NoError(t, err)

	timeDatum := types.NewTimeDatum(tm)
	timeCorCol := &CorrelatedColumn{Column: Column{RetType: types.NewFieldType(mysql.TypeDatetime)},
		Data: &timeDatum}
	timeVal, isNull, err := timeCorCol.EvalTime(ctx, chunk.Row{})
	require.Zero(t, timeVal.Compare(tm))
	require.False(t, isNull)
	require.NoError(t, err)
}

func TestColumnHashCode(t *testing.T) {
	t.Parallel()

	col1 := &Column{
		UniqueID: 12,
	}
	require.EqualValues(t, []byte{0x1, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xc}, col1.HashCode(nil))

	col2 := &Column{
		UniqueID: 2,
	}
	require.EqualValues(t, []byte{0x1, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2}, col2.HashCode(nil))
}

func TestColumn2Expr(t *testing.T) {
	t.Parallel()

	cols := make([]*Column, 0, 5)
	for i := 0; i < 5; i++ {
		cols = append(cols, &Column{UniqueID: int64(i)})
	}

	exprs := Column2Exprs(cols)
	for i := range exprs {
		require.True(t, exprs[i].Equal(nil, cols[i]))
	}
}

func TestColInfo2Col(t *testing.T) {
	t.Parallel()

	col0, col1 := &Column{ID: 0}, &Column{ID: 1}
	cols := []*Column{col0, col1}
	colInfo := &model.ColumnInfo{ID: 0}
	res := ColInfo2Col(cols, colInfo)
	require.True(t, res.Equal(nil, col1))

	colInfo.ID = 3
	res = ColInfo2Col(cols, colInfo)
	require.Nil(t, res)
}

func TestIndexInfo2Cols(t *testing.T) {
	t.Parallel()

	col0 := &Column{UniqueID: 0, ID: 0, RetType: types.NewFieldType(mysql.TypeLonglong)}
	col1 := &Column{UniqueID: 1, ID: 1, RetType: types.NewFieldType(mysql.TypeLonglong)}
	colInfo0 := &model.ColumnInfo{ID: 0, Name: model.NewCIStr("0")}
	colInfo1 := &model.ColumnInfo{ID: 1, Name: model.NewCIStr("1")}
	indexCol0, indexCol1 := &model.IndexColumn{Name: model.NewCIStr("0")}, &model.IndexColumn{Name: model.NewCIStr("1")}
	indexInfo := &model.IndexInfo{Columns: []*model.IndexColumn{indexCol0, indexCol1}}

	cols := []*Column{col0}
	colInfos := []*model.ColumnInfo{colInfo0}
	resCols, lengths := IndexInfo2PrefixCols(colInfos, cols, indexInfo)
	require.Len(t, resCols, 1)
	require.Len(t, lengths, 1)
	require.True(t, resCols[0].Equal(nil, col0))

	cols = []*Column{col1}
	colInfos = []*model.ColumnInfo{colInfo1}
	resCols, lengths = IndexInfo2PrefixCols(colInfos, cols, indexInfo)
	require.Len(t, resCols, 0)
	require.Len(t, lengths, 0)

	cols = []*Column{col0, col1}
	colInfos = []*model.ColumnInfo{colInfo0, colInfo1}
	resCols, lengths = IndexInfo2PrefixCols(colInfos, cols, indexInfo)
	require.Len(t, resCols, 2)
	require.Len(t, lengths, 2)
	require.True(t, resCols[0].Equal(nil, col0))
	require.True(t, resCols[1].Equal(nil, col1))
}

func TestColHybird(t *testing.T) {
	t.Parallel()

	ctx := mock.NewContext()

	// bit
	ft := types.NewFieldType(mysql.TypeBit)
	col := &Column{RetType: ft, Index: 0}
	input := chunk.New([]*types.FieldType{ft}, 1024, 1024)
	for i := 0; i < 1024; i++ {
		num, err := types.ParseBitStr(fmt.Sprintf("0b%b", i))
		require.NoError(t, err)
		input.AppendBytes(0, num)
	}
	result := chunk.NewColumn(types.NewFieldType(mysql.TypeLonglong), 1024)
	require.Nil(t, col.VecEvalInt(ctx, input, result))

	it := chunk.NewIterator4Chunk(input)
	for row, i := it.Begin(), 0; row != it.End(); row, i = it.Next(), i+1 {
		v, _, err := col.EvalInt(ctx, row)
		require.NoError(t, err)
		require.Equal(t, result.GetInt64(i), v)
	}

	// use a container which has the different field type with bit
	result = chunk.NewColumn(types.NewFieldType(mysql.TypeString), 1024)
	require.Nil(t, col.VecEvalInt(ctx, input, result))
	for row, i := it.Begin(), 0; row != it.End(); row, i = it.Next(), i+1 {
		v, _, err := col.EvalInt(ctx, row)
		require.NoError(t, err)
		require.Equal(t, result.GetInt64(i), v)
	}

	// enum
	ft = types.NewFieldType(mysql.TypeEnum)
	col.RetType = ft
	input = chunk.New([]*types.FieldType{ft}, 1024, 1024)
	for i := 0; i < 1024; i++ {
		input.AppendEnum(0, types.Enum{Name: fmt.Sprintf("%v", i), Value: uint64(i)})
	}
	result = chunk.NewColumn(types.NewFieldType(mysql.TypeString), 1024)
	require.Nil(t, col.VecEvalString(ctx, input, result))

	it = chunk.NewIterator4Chunk(input)
	for row, i := it.Begin(), 0; row != it.End(); row, i = it.Next(), i+1 {
		v, _, err := col.EvalString(ctx, row)
		require.NoError(t, err)
		require.Equal(t, result.GetString(i), v)
	}

	// set
	ft = types.NewFieldType(mysql.TypeSet)
	col.RetType = ft
	input = chunk.New([]*types.FieldType{ft}, 1024, 1024)
	for i := 0; i < 1024; i++ {
		input.AppendSet(0, types.Set{Name: fmt.Sprintf("%v", i), Value: uint64(i)})
	}
	result = chunk.NewColumn(types.NewFieldType(mysql.TypeString), 1024)
	require.Nil(t, col.VecEvalString(ctx, input, result))

	it = chunk.NewIterator4Chunk(input)
	for row, i := it.Begin(), 0; row != it.End(); row, i = it.Next(), i+1 {
		v, _, err := col.EvalString(ctx, row)
		require.NoError(t, err)
		require.Equal(t, result.GetString(i), v)
	}
}
<|endoftext|>


<commit_before>package kite

import (
	"errors"
	"fmt"
	"koding/newkite/dnode"
	"koding/newkite/dnode/rpc"
	"koding/newkite/kodingkey"
	"koding/newkite/token"
)

// kiteMethod implements dnode.Handler.
type kiteMethod struct {
	kite    *Kite
	method  string
	handler HandlerFunc
}

// WrapArgs is called before a Callback is sent to remote in order to wrap arguments.
func (m kiteMethod) WrapArgs(args []interface{}, tr dnode.Transport) []interface{} {
	return []interface{}{&callOptionsOut{
		WithArgs: args,
		CallOptions: CallOptions{
			Kite: m.kite.Kite,
		},
	}}
}

// Call is called when a method is received from remote.
func (m kiteMethod) Call(method string, args *dnode.Partial, tr dnode.Transport) {
	request, responseCallback, err := m.kite.parseRequest(method, args, tr, true)
	if err != nil {
		m.kite.Log.Notice("Did not understand request: %s", err)
		return
	}

	result, err := m.handler(request)
	if responseCallback == nil {
		return
	}

	if err != nil {
		err = responseCallback(err.Error(), result)
	} else {
		err = responseCallback(nil, result)
	}

	if err != nil {
		m.kite.Log.Error(err.Error())
	}
}

type HandlerFunc func(*Request) (response interface{}, err error)

// HandleFunc registers a handler to run when a method call is received from a Kite.
func (k *Kite) HandleFunc(method string, handler HandlerFunc) {
	k.server.Handle(method, kiteMethod{k, method, handler})
}

type Request struct {
	Method         string
	Args           *dnode.Partial
	LocalKite      *Kite
	RemoteKite     *RemoteKite
	Username       string
	Authentication *callAuthentication
	RemoteAddr     string
}

type Callback func(r *Request)

func (c Callback) MarshalJSON() ([]byte, error) {
	return []byte(`"[Function]"`), nil
}

func (c Callback) WrapArgs(args []interface{}, tr dnode.Transport) []interface{} {
	return []interface{}{&callOptionsOut{
		WithArgs: args,
		CallOptions: CallOptions{
			Kite: tr.Properties()["localKite"].(*Kite).Kite,
		},
	}}
}

// Call is called when a callback method call is received from remote.
func (c Callback) Call(method string, args *dnode.Partial, tr dnode.Transport) {
	k := tr.Properties()["localKite"].(*Kite)
	req, _, err := k.parseRequest(method, args, tr, false)
	if err != nil {
		k.Log.Notice("Did not understand callback message: %s", err)
		return
	}

	c(req)
}

// parseRequest is used to read a dnode message.
// It is called when a method or callback is received.
func (k *Kite) parseRequest(method string, arguments *dnode.Partial, tr dnode.Transport, authenticate bool) (
	request *Request, response dnode.Function, err error) {

	// Parse dnode method arguments [options, response]
	args, err := arguments.Slice()
	if err != nil {
		return
	}
	if len(args) != 1 && len(args) != 2 {
		return nil, nil, errors.New("Invalid number of arguments")
	}

	// Parse options argument
	var options CallOptions
	if err = args[0].Unmarshal(&options); err != nil {
		return
	}

	// Parse response callback if present
	if len(args) > 1 && args[1] != nil {
		if err = args[1].Unmarshal(&response); err != nil {
			return
		}
	}

	// Trust the Kite if we have initiated the connection.
	// Otherwise try to authenticate the user.
	// RemoteAddr() returns "" if this is an outgoing connection.
	// Also we do not need to authenticate requests when a callback method is received.
	if authenticate && tr.RemoteAddr() != "" {
		if err = k.authenticateUser(&options); err != nil {
			return
		}
	}

	// Properties about the client...
	properties := tr.Properties()

	// Create a new RemoteKite instance to pass it to the handler, so
	// the handler can call methods on the other site on the same connection.
	if properties["remoteKite"] == nil {
		// Do not create a new RemoteKite on every request,
		// cache it in Transport.Properties().
		client := tr.(*rpc.Client) // We only have a dnode/rpc.Client for now.
		remoteKite := k.newRemoteKiteWithClient(options.Kite, options.Authentication, client)
		properties["remoteKite"] = remoteKite

		// Notify Kite.OnConnect handlers.
		k.notifyRemoteKiteConnected(remoteKite)
	}

	request = &Request{
		Method:         method,
		Args:           options.WithArgs,
		LocalKite:      k,
		RemoteKite:     properties["remoteKite"].(*RemoteKite),
		RemoteAddr:     tr.RemoteAddr(),
		Username:       options.Kite.Username, // authenticateUser() sets it.
		Authentication: &options.Authentication,
	}

	return
}

// authenticateUser tries to authenticate the user by selecting appropriate
// authenticator function.
func (k *Kite) authenticateUser(options *CallOptions) error {
	f := k.Authenticators[options.Authentication.Type]
	if f == nil {
		return fmt.Errorf("Unknown authentication type: %s", options.Authentication.Type)
	}

	return f(options)
}

// AuthenticateFromToken is the default Authenticator for Kite.
func (k *Kite) AuthenticateFromToken(options *CallOptions) error {
	key, err := kodingkey.FromString(k.KodingKey)
	if err != nil {
		return fmt.Errorf("Invalid Koding Key: %s", k.KodingKey)
	}

	tkn, err := token.DecryptString(options.Authentication.Key, key)
	if err != nil {
		return fmt.Errorf("Invalid token: %s", options.Authentication.Key)
	}

	if !tkn.IsValid(k.ID) {
		return fmt.Errorf("Invalid token: %s", tkn)
	}

	options.Kite.Username = tkn.Username

	return nil
}

// AuthenticateFromToken authenticates user from Koding Key.
// Kontrol makes requests with a Koding Key.
func (k *Kite) AuthenticateFromKodingKey(options *CallOptions) error {
	if options.Authentication.Key != k.KodingKey {
		return fmt.Errorf("Invalid Koding Key")
	}

	// Set the username if missing.
	if options.Kite.Username == "" && k.Username != "" {
		options.Kite.Username = k.Username
	}

	return nil
}
<commit_msg>kite: fix argument name<commit_after>package kite

import (
	"errors"
	"fmt"
	"koding/newkite/dnode"
	"koding/newkite/dnode/rpc"
	"koding/newkite/kodingkey"
	"koding/newkite/token"
)

// kiteMethod implements dnode.Handler.
type kiteMethod struct {
	kite    *Kite
	method  string
	handler HandlerFunc
}

// WrapArgs is called before a Callback is sent to remote in order to wrap arguments.
func (m kiteMethod) WrapArgs(args []interface{}, tr dnode.Transport) []interface{} {
	return []interface{}{&callOptionsOut{
		WithArgs: args,
		CallOptions: CallOptions{
			Kite: m.kite.Kite,
		},
	}}
}

// Call is called when a method is received from remote.
func (m kiteMethod) Call(method string, args *dnode.Partial, tr dnode.Transport) {
	request, responseCallback, err := m.kite.parseRequest(method, args, tr, true)
	if err != nil {
		m.kite.Log.Notice("Did not understand request: %s", err)
		return
	}

	result, err := m.handler(request)
	if responseCallback == nil {
		return
	}

	if err != nil {
		err = responseCallback(err.Error(), result)
	} else {
		err = responseCallback(nil, result)
	}

	if err != nil {
		m.kite.Log.Error(err.Error())
	}
}

type HandlerFunc func(*Request) (result interface{}, err error)

// HandleFunc registers a handler to run when a method call is received from a Kite.
func (k *Kite) HandleFunc(method string, handler HandlerFunc) {
	k.server.Handle(method, kiteMethod{k, method, handler})
}

type Request struct {
	Method         string
	Args           *dnode.Partial
	LocalKite      *Kite
	RemoteKite     *RemoteKite
	Username       string
	Authentication *callAuthentication
	RemoteAddr     string
}

type Callback func(r *Request)

func (c Callback) MarshalJSON() ([]byte, error) {
	return []byte(`"[Function]"`), nil
}

func (c Callback) WrapArgs(args []interface{}, tr dnode.Transport) []interface{} {
	return []interface{}{&callOptionsOut{
		WithArgs: args,
		CallOptions: CallOptions{
			Kite: tr.Properties()["localKite"].(*Kite).Kite,
		},
	}}
}

// Call is called when a callback method call is received from remote.
func (c Callback) Call(method string, args *dnode.Partial, tr dnode.Transport) {
	k := tr.Properties()["localKite"].(*Kite)
	req, _, err := k.parseRequest(method, args, tr, false)
	if err != nil {
		k.Log.Notice("Did not understand callback message: %s", err)
		return
	}

	c(req)
}

// parseRequest is used to read a dnode message.
// It is called when a method or callback is received.
func (k *Kite) parseRequest(method string, arguments *dnode.Partial, tr dnode.Transport, authenticate bool) (
	request *Request, response dnode.Function, err error) {

	// Parse dnode method arguments [options, response]
	args, err := arguments.Slice()
	if err != nil {
		return
	}
	if len(args) != 1 && len(args) != 2 {
		return nil, nil, errors.New("Invalid number of arguments")
	}

	// Parse options argument
	var options CallOptions
	if err = args[0].Unmarshal(&options); err != nil {
		return
	}

	// Parse response callback if present
	if len(args) > 1 && args[1] != nil {
		if err = args[1].Unmarshal(&response); err != nil {
			return
		}
	}

	// Trust the Kite if we have initiated the connection.
	// Otherwise try to authenticate the user.
	// RemoteAddr() returns "" if this is an outgoing connection.
	// Also we do not need to authenticate requests when a callback method is received.
	if authenticate && tr.RemoteAddr() != "" {
		if err = k.authenticateUser(&options); err != nil {
			return
		}
	}

	// Properties about the client...
	properties := tr.Properties()

	// Create a new RemoteKite instance to pass it to the handler, so
	// the handler can call methods on the other site on the same connection.
	if properties["remoteKite"] == nil {
		// Do not create a new RemoteKite on every request,
		// cache it in Transport.Properties().
		client := tr.(*rpc.Client) // We only have a dnode/rpc.Client for now.
		remoteKite := k.newRemoteKiteWithClient(options.Kite, options.Authentication, client)
		properties["remoteKite"] = remoteKite

		// Notify Kite.OnConnect handlers.
		k.notifyRemoteKiteConnected(remoteKite)
	}

	request = &Request{
		Method:         method,
		Args:           options.WithArgs,
		LocalKite:      k,
		RemoteKite:     properties["remoteKite"].(*RemoteKite),
		RemoteAddr:     tr.RemoteAddr(),
		Username:       options.Kite.Username, // authenticateUser() sets it.
		Authentication: &options.Authentication,
	}

	return
}

// authenticateUser tries to authenticate the user by selecting appropriate
// authenticator function.
func (k *Kite) authenticateUser(options *CallOptions) error {
	f := k.Authenticators[options.Authentication.Type]
	if f == nil {
		return fmt.Errorf("Unknown authentication type: %s", options.Authentication.Type)
	}

	return f(options)
}

// AuthenticateFromToken is the default Authenticator for Kite.
func (k *Kite) AuthenticateFromToken(options *CallOptions) error {
	key, err := kodingkey.FromString(k.KodingKey)
	if err != nil {
		return fmt.Errorf("Invalid Koding Key: %s", k.KodingKey)
	}

	tkn, err := token.DecryptString(options.Authentication.Key, key)
	if err != nil {
		return fmt.Errorf("Invalid token: %s", options.Authentication.Key)
	}

	if !tkn.IsValid(k.ID) {
		return fmt.Errorf("Invalid token: %s", tkn)
	}

	options.Kite.Username = tkn.Username

	return nil
}

// AuthenticateFromToken authenticates user from Koding Key.
// Kontrol makes requests with a Koding Key.
func (k *Kite) AuthenticateFromKodingKey(options *CallOptions) error {
	if options.Authentication.Key != k.KodingKey {
		return fmt.Errorf("Invalid Koding Key")
	}

	// Set the username if missing.
	if options.Kite.Username == "" && k.Username != "" {
		options.Kite.Username = k.Username
	}

	return nil
}
<|endoftext|>


<commit_before>// Copyright 2018, OpenCensus Authors
//
// 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 httptrace contains OpenCensus tracing integrations with net/http.
package httptrace

import (
	"net/http"
	"strings"

	"go.opencensus.io/trace"
	"go.opencensus.io/trace/propagation"
)

// TODO(jbd): Add godoc examples.

type transport struct {
	base        http.RoundTripper
	propogators []propagation.HTTPFormat
}

// RoundTrip creates a trace.Span and inserts it into the outgoing request's headers.
// The created span can follow a parent span, if a parent is presented in
// the request's context.
func (t *transport) RoundTrip(req *http.Request) (*http.Response, error) {
	name := "Sent" + strings.Replace(req.URL.String(), req.URL.Scheme, ".", -1)
	// TODO(jbd): Discuss whether we want to prefix
	// outgoing requests with Sent.
	ctx := trace.StartSpan(req.Context(), name)
	req = req.WithContext(ctx)

	span := trace.FromContext(ctx)
	for _, p := range t.propogators {
		p.ToRequest(span.SpanContext(), req)
	}

	resp, err := t.base.RoundTrip(req)

	// TODO(jbd): Add status and attributes.
	trace.EndSpan(ctx)
	return resp, err
}

// CancelRequest cancels an in-flight request by closing its connection.
func (t *transport) CancelRequest(req *http.Request) {
	type canceler interface {
		CancelRequest(*http.Request)
	}
	if cr, ok := t.base.(canceler); ok {
		cr.CancelRequest(req)
	}
}

// NewTransport returns an http.RoundTripper that traces the outgoing requests.
//
// All the requests are done by the given base roundtripper. If nil is given,
// http.DefaultTransport is used. If its base HTTP RoundTripper implements CancelRequest,
// the returned round tripper will be cancelable.
//
// Traces are propagated via the provided HTTP propagation mechanisms.
func NewTransport(base http.RoundTripper, p ...propagation.HTTPFormat) http.RoundTripper {
	if base == nil {
		base = http.DefaultTransport
	}
	return &transport{base: base, propogators: p}
}

// NewHandler returns a http.Handler from the given handler
// that is aware of the incoming request's span.
// The span can be extracted from the incoming request in handler
// functions from incoming request's context:
//
//    span := trace.FromContext(r.Context())
//
// The span will be automatically ended by the handler.
//
// Incoming propagation mechanism is determined by the given HTTP propagators.
func NewHandler(base http.Handler, p ...propagation.HTTPFormat) http.Handler {
	return &handler{handler: base, propogators: p}
}

type handler struct {
	handler     http.Handler
	propogators []propagation.HTTPFormat
}

func (h *handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	name := "Recv" + strings.Replace(r.URL.String(), r.URL.Scheme, ".", -1)

	var (
		sc trace.SpanContext
		ok bool
	)

	ctx := r.Context()
	for _, p := range h.propogators {
		sc, ok = p.FromRequest(r)
		if ok {
			break
		}
	}
	if ok {
		ctx = trace.StartSpanWithRemoteParent(ctx, name, sc, trace.StartSpanOptions{})
	} else {
		ctx = trace.StartSpan(ctx, name)
	}
	defer trace.EndSpan(ctx)

	// TODO(jbd): Add status and attributes.
	r = r.WithContext(ctx)
	h.handler.ServeHTTP(w, r)
}
<commit_msg>Rename args and fields after HTTPFormat (#311)<commit_after>// Copyright 2018, OpenCensus Authors
//
// 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 httptrace contains OpenCensus tracing integrations with net/http.
package httptrace

import (
	"net/http"
	"strings"

	"go.opencensus.io/trace"
	"go.opencensus.io/trace/propagation"
)

// TODO(jbd): Add godoc examples.

type transport struct {
	base    http.RoundTripper
	formats []propagation.HTTPFormat
}

// RoundTrip creates a trace.Span and inserts it into the outgoing request's headers.
// The created span can follow a parent span, if a parent is presented in
// the request's context.
func (t *transport) RoundTrip(req *http.Request) (*http.Response, error) {
	name := "Sent" + strings.Replace(req.URL.String(), req.URL.Scheme, ".", -1)
	// TODO(jbd): Discuss whether we want to prefix
	// outgoing requests with Sent.
	ctx := trace.StartSpan(req.Context(), name)
	req = req.WithContext(ctx)

	span := trace.FromContext(ctx)
	for _, f := range t.formats {
		f.ToRequest(span.SpanContext(), req)
	}

	resp, err := t.base.RoundTrip(req)

	// TODO(jbd): Add status and attributes.
	trace.EndSpan(ctx)
	return resp, err
}

// CancelRequest cancels an in-flight request by closing its connection.
func (t *transport) CancelRequest(req *http.Request) {
	type canceler interface {
		CancelRequest(*http.Request)
	}
	if cr, ok := t.base.(canceler); ok {
		cr.CancelRequest(req)
	}
}

// NewTransport returns an http.RoundTripper that traces the outgoing requests.
//
// All the requests are done by the given base roundtripper. If nil is given,
// http.DefaultTransport is used. If its base HTTP RoundTripper implements CancelRequest,
// the returned round tripper will be cancelable.
//
// Traces are propagated via the provided HTTP propagation mechanisms.
func NewTransport(base http.RoundTripper, format ...propagation.HTTPFormat) http.RoundTripper {
	if base == nil {
		base = http.DefaultTransport
	}
	return &transport{base: base, formats: format}
}

// NewHandler returns a http.Handler from the given handler
// that is aware of the incoming request's span.
// The span can be extracted from the incoming request in handler
// functions from incoming request's context:
//
//    span := trace.FromContext(r.Context())
//
// The span will be automatically ended by the handler.
//
// Incoming propagation mechanism is determined by the given HTTP propagators.
func NewHandler(base http.Handler, format ...propagation.HTTPFormat) http.Handler {
	return &handler{handler: base, formats: format}
}

type handler struct {
	handler http.Handler
	formats []propagation.HTTPFormat
}

func (h *handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	name := "Recv" + strings.Replace(r.URL.String(), r.URL.Scheme, ".", -1)

	var (
		sc trace.SpanContext
		ok bool
	)

	ctx := r.Context()
	for _, f := range h.formats {
		sc, ok = f.FromRequest(r)
		if ok {
			break
		}
	}
	if ok {
		ctx = trace.StartSpanWithRemoteParent(ctx, name, sc, trace.StartSpanOptions{})
	} else {
		ctx = trace.StartSpan(ctx, name)
	}
	defer trace.EndSpan(ctx)

	// TODO(jbd): Add status and attributes.
	r = r.WithContext(ctx)
	h.handler.ServeHTTP(w, r)
}
<|endoftext|>


<commit_before>package lint

import (
	"regexp"
	"strings"
)

// RuleInfo stores information of a rule.
type RuleInfo struct {
	Name        RuleName   // rule name in the set.
	Description string     // a short description of this rule.
	URI         string     // a link to a document for more details.
	FileTypes   []FileType // types of files that this rule targets to.
	Category    Category   // category of problems this rule produces.
	Status      Status     // status of this rule, either enabled, disabled, or deprecated.

	noPositional struct{} // Prevent positional composite literal instantiation
}

// FileType defines a file type that a rule is targeting to.
type FileType string

const (
	// ProtoFile indicates that the targeted file is a protobuf-definition file.
	ProtoFile FileType = "proto-file"
)

// Category defines the category of the findings produced by a rule.
type Category string

const (
	// Error indicates that in the API, something will cause errors.
	Error Category = "error"
	// Warning indicates that in the API, something can be do better.
	Warning Category = "warning"
	// DefaultCategory denotes the default value of Category
	DefaultCategory Category = Warning
)

// Status defines whether a rule is enabled, disabled or deprecated.
type Status string

const (
	// Enabled indicates that a rule should be enabled.
	Enabled Status = "enabled"
	// Disabled indicates that a rule should be disabled.
	Disabled Status = "disabled"
	// Deprecated indicates that a rule should be deprecated.
	Deprecated Status = "Deprecated"
	// DefaultStatus denotes the default value of Status.
	DefaultStatus Status = Disabled
)

// RuleName is an identifier for a rule. Allowed characters include a-z, A-Z, 0-9, -, _. The
// namespace separator :: is allowed between RuleName segments (for example, my_namespace::my_rule).
type RuleName string

const nameSeparator string = "::"

var ruleNameValidator = regexp.MustCompile("^([a-zA-Z0-9-_]+(::)?)+[a-zA-Z0-9-_]+$")

func NewRuleName(segments ...string) RuleName {
	return RuleName(strings.Join(segments, nameSeparator))
}

func (r RuleName) IsValid() bool {
	return r != "" && ruleNameValidator.Match([]byte(r))
}

func (r RuleName) WithPrefix(prefix RuleName) RuleName {
	if prefix == "" {
		return r
	}

	return RuleName(string(prefix) + nameSeparator + string(r))
}
<commit_msg>Added comments<commit_after>package lint

import (
	"regexp"
	"strings"
)

// RuleInfo stores information of a rule.
type RuleInfo struct {
	Name        RuleName   // rule name in the set.
	Description string     // a short description of this rule.
	URI         string     // a link to a document for more details.
	FileTypes   []FileType // types of files that this rule targets to.
	Category    Category   // category of problems this rule produces.
	Status      Status     // status of this rule, either enabled, disabled, or deprecated.

	noPositional struct{} // Prevent positional composite literal instantiation
}

// FileType defines a file type that a rule is targeting to.
type FileType string

const (
	// ProtoFile indicates that the targeted file is a protobuf-definition file.
	ProtoFile FileType = "proto-file"
)

// Category defines the category of the findings produced by a rule.
type Category string

const (
	// Error indicates that in the API, something will cause errors.
	Error Category = "error"
	// Warning indicates that in the API, something can be do better.
	Warning Category = "warning"
	// DefaultCategory denotes the default value of Category
	DefaultCategory Category = Warning
)

// Status defines whether a rule is enabled, disabled or deprecated.
type Status string

const (
	// Enabled indicates that a rule should be enabled.
	Enabled Status = "enabled"
	// Disabled indicates that a rule should be disabled.
	Disabled Status = "disabled"
	// Deprecated indicates that a rule should be deprecated.
	Deprecated Status = "Deprecated"
	// DefaultStatus denotes the default value of Status.
	DefaultStatus Status = Disabled
)

// RuleName is an identifier for a rule. Allowed characters include a-z, A-Z, 0-9, -, _. The
// namespace separator :: is allowed between RuleName segments (for example, my_namespace::my_rule).
type RuleName string

const nameSeparator string = "::"

var ruleNameValidator = regexp.MustCompile("^([a-zA-Z0-9-_]+(::)?)+[a-zA-Z0-9-_]+$")

// NewRuleName creates a RuleName from segments. It will join the segments with the "::" separator.
func NewRuleName(segments ...string) RuleName {
	return RuleName(strings.Join(segments, nameSeparator))
}

// IsValid checks if a RuleName is syntactically valid
func (r RuleName) IsValid() bool {
	return r != "" && ruleNameValidator.Match([]byte(r))
}

// WithPrefix prepends a prefix to the RuleName, separating it with ::
func (r RuleName) WithPrefix(prefix RuleName) RuleName {
	if prefix == "" {
		return r
	}

	return RuleName(string(prefix) + nameSeparator + string(r))
}
<|endoftext|>


<commit_before>package brightbox

import (
	"time"
)

type LoadBalancer struct {
	Resource
	Name        string
	Status      string
	CreatedAt   *time.Time `json:"created_at"`
	DeletedAt   *time.Time `json:"deleted_at"`
	Locked      bool
	Account     Account
	Nodes       []Server
	CloudIPs    []CloudIP `json:"cloud_ips"`
	Policy      string
	BufferSize  int `json:"buffer_size"`
	Listeners   []LoadBalancerListener
	Healthcheck LoadBalancerHealthCheck
	Certificate *LoadBalancerCertificate
}

type LoadBalancerCertificate struct {
	ExpiresAt time.Time `json:"expires_at"`
	ValidFrom time.Time `json:"valid_from"`
	SslV3     bool      `json:"sslv3"`
	Issuer    string    `json:"issuer"`
	Subject   string    `json:"subject"`
}

type LoadBalancerHealthCheck struct {
	Type          string `json:"type"`
	Port          int    `json:"port"`
	Request       string `json:"request,omitempty"`
	Interval      int    `json:"interval,omitempty"`
	Timeout       int    `json:"timeout,omitempty"`
	ThresholdUp   int    `json:"threshold_up,omitempty"`
	ThresholdDown int    `json:"threshold_down,omitempty"`
}

type LoadBalancerListener struct {
	Protocol string `json:"protocol"`
	In       int    `json:"in"`
	Out      int    `json:"out"`
	Timeout  int    `json:"timeout,omitempty"`
}

func (c *Client) LoadBalancers() ([]LoadBalancer, error) {
	var lbs []LoadBalancer
	_, err := c.MakeApiRequest("GET", "/1.0/load_balancers", nil, &lbs)
	if err != nil {
		return nil, err
	}
	return lbs, err
}

func (c *Client) LoadBalancer(identifier string) (*LoadBalancer, error) {
	lb := new(LoadBalancer)
	_, err := c.MakeApiRequest("GET", "/1.0/load_balancers/"+identifier, nil, lb)
	if err != nil {
		return nil, err
	}
	return lb, err
}
<commit_msg>LoadBalancer docs<commit_after>package brightbox

import (
	"time"
)

// LoadBalancer represents a Load Balancer
// https://api.gb1.brightbox.com/1.0/#load_balancer
type LoadBalancer struct {
	Resource
	Name        string
	Status      string
	CreatedAt   *time.Time `json:"created_at"`
	DeletedAt   *time.Time `json:"deleted_at"`
	Locked      bool
	Account     Account
	Nodes       []Server
	CloudIPs    []CloudIP `json:"cloud_ips"`
	Policy      string
	BufferSize  int `json:"buffer_size"`
	Listeners   []LoadBalancerListener
	Healthcheck LoadBalancerHealthCheck
	Certificate *LoadBalancerCertificate
}

// LoadBalancerCertificate represents a certificate on a LoadBalancer
type LoadBalancerCertificate struct {
	ExpiresAt time.Time `json:"expires_at"`
	ValidFrom time.Time `json:"valid_from"`
	SslV3     bool      `json:"sslv3"`
	Issuer    string    `json:"issuer"`
	Subject   string    `json:"subject"`
}

// LoadBalancerHealthCheck represents a health check on a LoadBalancer
type LoadBalancerHealthCheck struct {
	Type          string `json:"type"`
	Port          int    `json:"port"`
	Request       string `json:"request,omitempty"`
	Interval      int    `json:"interval,omitempty"`
	Timeout       int    `json:"timeout,omitempty"`
	ThresholdUp   int    `json:"threshold_up,omitempty"`
	ThresholdDown int    `json:"threshold_down,omitempty"`
}

// LoadBalancerListener represents a listener on a LoadBalancer
type LoadBalancerListener struct {
	Protocol string `json:"protocol"`
	In       int    `json:"in"`
	Out      int    `json:"out"`
	Timeout  int    `json:"timeout,omitempty"`
}

// LoadBalancers retrieves a list of all load balancers
func (c *Client) LoadBalancers() ([]LoadBalancer, error) {
	var lbs []LoadBalancer
	_, err := c.MakeApiRequest("GET", "/1.0/load_balancers", nil, &lbs)
	if err != nil {
		return nil, err
	}
	return lbs, err
}

// LoadBalancer retrieves a detailed view of one load balancer
func (c *Client) LoadBalancer(identifier string) (*LoadBalancer, error) {
	lb := new(LoadBalancer)
	_, err := c.MakeApiRequest("GET", "/1.0/load_balancers/"+identifier, nil, lb)
	if err != nil {
		return nil, err
	}
	return lb, err
}
<|endoftext|>


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

// Package language implements BCP 47 language tags and related functionality.
//
// The Tag type, which is used to represent languages, is agnostic to the
// meaning of its subtags. Tags are not fully canonicalized to preserve
// information that may be valuable in certain contexts. As a consequence, two
// different tags may represent identical languages.
//
// Initializing language- or locale-specific components usually consists of
// two steps. The first step is to select a display language based on the
// preferred languages of the user and the languages supported by an application.
// The second step is to create the language-specific services based on
// this selection. Each is discussed in more details below.
//
// Matching preferred against supported languages
//
// An application may support various languages. This list is typically limited
// by the languages for which there exists translations of the user interface.
// Similarly, a user may provide a list of preferred languages which is limited
// by the languages understood by this user.
// An application should use a Matcher to find the best supported language based
// on the user's preferred list.
// Matchers are aware of the intricacies of equivalence between languages.
// The default Matcher implementation takes into account things such as
// deprecated subtags, legacy tags, and mutual intelligibility between scripts
// and languages.
//
// A Matcher for English, Australian English, Danish, and standard Mandarin can
// be defined as follows:
//
//		var matcher = language.NewMatcher([]language.Tag{
//			language.English,   // The first language is used as fallback.
// 			language.MustParse("en-AU"),
//			language.Danish,
//			language.Chinese,
//		})
//
// The following code selects the best match for someone speaking Spanish and
// Norwegian:
//
// 		preferred := []language.Tag{ language.Spanish, language.Norwegian }
//		tag, _, _ := matcher.Match(preferred...)
//
// In this case, the best match is Danish, as Danish is sufficiently a match to
// Norwegian to not have to fall back to the default.
// See ParseAcceptLanguage on how to handle the Accept-Language HTTP header.
//
// Selecting language-specific services
//
// One should always use the Tag returned by the Matcher to create an instance
// of any of the language-specific services provided by the text repository.
// This prevents the mixing of languages, such as having a different language for
// messages and display names, as well as improper casing or sorting order for
// the selected language.
// Using the returned Tag also allows user-defined settings, such as collation
// order or numbering system to be transparently passed as options.
//
// If you have language-specific data in your application, however, it will in
// most cases suffice to use the index returned by the matcher to identify
// the user language.
// The following loop provides an alternative in case this is not sufficient:
//
// 		supported := map[language.Tag]data{
//			language.English:            enData,
// 			language.MustParse("en-AU"): enAUData,
//			language.Danish:             daData,
//			language.Chinese:            zhData,
// 		}
//		tag, _, _ := matcher.Match(preferred...)
//		for ; tag != language.Und; tag = tag.Parent() {
//			if v, ok := supported[tag]; ok {
//				return v
//			}
//		}
// 		return enData // should not reach here
//
// Repeatedly taking the Parent of the tag returned by Match will eventually
// match one of the tags used to initialize the Matcher.
//
// Canonicalization
//
// By default, only legacy and deprecated tags are converted into their
// canonical equivalent. All other information is preserved. This approach makes
// the confidence scores more accurate and allows matchers to distinguish
// between variants that are otherwise lost.
//
// As a consequence, two tags that should be treated as identical according to
// BCP 47 or CLDR, like "en-Latn" and "en", will be represented differently. The
// Matchers will handle such distinctions, though, and are aware of the
// equivalence relations. The CanonType type can be used to alter the
// canonicalization form.
//
// References
//
// BCP 47 - Tags for Identifying Languages
// http://tools.ietf.org/html/bcp47
package language // import "golang.org/x/text/language"
<commit_msg>language: simplify docs<commit_after>// Copyright 2017 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// Package language implements BCP 47 language tags and related functionality.
//
// The most important function of package language is to match a list of
// user-preferred languages to a list of supported languages.
// It alleviates the developer of dealing with the complexity of this process
// and provides the user with the best experience
// (see https://blog.golang.org/matchlang).
//
//
// Matching preferred against supported languages
//
// A Matcher for an application that supports English, Australian English,
// Danish, and standard Mandarin can be created as follows:
//
//    var matcher = language.NewMatcher([]language.Tag{
//        language.English,   // The first language is used as fallback.
//        language.MustParse("en-AU"),
//        language.Danish,
//        language.Chinese,
//    })
//
// This list of supported languages is typically implied by the languages for
// which there exists translations of the user interface.
//
// User-preferred languages usually come as a comma-separated list of BCP 47
// language tags.
// The MatchString finds best matches for such strings:
//
//    handler(w http.ResponseWriter, r *http.Request) {
//        lang, _ := r.Cookie("lang")
//        accept := r.Header.Get("Accept-Language")
//        tag, _ := language.MatchStrings(matcher, lang.String(), accept)
//
//        // tag should now be used for the initialization of any
//        // locale-specific service.
//    }
//
// The Matcher's Match method can be used to match Tags directly.
//
// Matchers are aware of the intricacies of equivalence between languages, such
// as deprecated subtags, legacy tags, macro languages, mutual
// intelligibility between scripts and languages, and transparently passing
// BCP 47 user configuration.
// For instance, it will know that a reader of Bokmål Danish can read Norwegian
// and will know that Cantonese ("yue") is a good match for "zh-HK".
//
//
// Using match results
//
// To guarantee a consistent user experience to the user it is important to
// use the same language tag for the selection of any locale-specific services.
// For example, it is utterly confusing to substitute spelled-out numbers
// or dates in one language in text of another language.
// More subtly confusing is using the wrong sorting order or casing
// algorithm for a certain language.
//
//    All the packages in x/text that provide locale-specific services
//    (e.g. collate, cases) should be initialized with the tag that was
//    obtained at the start of an interaction with the user.
//
// Note that Tag that is returned by Match and MatchString may differ from any
// of the supported languages, as it may contain carried over settings from
// the user tags.
// This may be inconvenient when your application has some additional
// locale-specific data for your supported languages.
// Match and MatchString both return the index of the matched supported tag
// to simplify associating such data with the matched tag.
//
//
// Canonicalization
//
// If one uses the Matcher to compare languages one does not need to
// worry about canonicalization.
//
// The meaning of a Tag varies per application. The language package
// therefore delays canonicalization and preserves information as much
// as possible. The Matcher, however, will always take into account that
// two different tags may represent the same language.
//
// By default, only legacy and deprecated tags are converted into their
// canonical equivalent. All other information is preserved. This approach makes
// the confidence scores more accurate and allows matchers to distinguish
// between variants that are otherwise lost.
//
// As a consequence, two tags that should be treated as identical according to
// BCP 47 or CLDR, like "en-Latn" and "en", will be represented differently. The
// Matcher handles such distinctions, though, and is aware of the
// equivalence relations. The CanonType type can be used to alter the
// canonicalization form.
//
// References
//
// BCP 47 - Tags for Identifying Languages http://tools.ietf.org/html/bcp47
//
package language // import "golang.org/x/text/language"

// TODO: explanation on how to match languages for your own locale-specific
// service.
<|endoftext|>


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

// Master election algorithm which uses Doozer as a lock server to
// determine whether or not a process is master.
package masterelection

import (
	"net"
	"sync"

	"github.com/ha/doozer"
)

// Interface for notifying the caller about changes in the master state.
type MasterElectionEventReceiver interface {
	// BecomeMaster() will be invoked when the process has been elected as
	// master. If an error is returned by BecomeMaster(), a new master
	// election will be forced.
	BecomeMaster() error

	// BecomeSlave() will be invoked every time the master election is lost.
	// It may also be invoked right before BecomeMaster() in case a master
	// election is forced. The name of the new master will be passed as
	// a host:port pair.
	//
	// It will also be inoked even if the process is already a slave, but
	// another master election has taken place. Due to this property,
	// BecomeSlave() may be used to receive notifications about changes
	// of the master.
	BecomeSlave(new_master string)

	// This callback will be invoked to report non-fatal errors in the
	// master election process to the client.
	ElectionError(err error)

	// This callback will be invoked to report fatal errors in the master
	// election process to the client.
	ElectionFatal(err error)
}

// Client for the master election procedure using a Doozer lock server.
// This can be used both in participating mode, where the process can become
// master, or in passive mode, where the current master may be discovered
// through the API and master elections may be forced, but the process will
// not participate in master elections and thus never itself become master.
type MasterElectionClient struct {
	conn          *doozer.Conn
	participating bool
	own_addr      net.Addr
	old_rev       int64
	cb            MasterElectionEventReceiver
	path          string
	wg            sync.WaitGroup
}

// Create a new master election client for the elections with the given
// "name". The host and port of the master will be set to "addr".
// If "participating" is set to true, the client will participate in master
// elections, otherwise the client will just listen for changes of the
// current master.
//
// All notifications of being a master or slave will be done on the
// specified "callback".
func NewMasterElectionClient(conn *doozer.Conn, name string, addr net.Addr,
	participating bool, callback MasterElectionEventReceiver) (
	*MasterElectionClient, error) {
	var ret *MasterElectionClient = &MasterElectionClient{
		cb:            callback,
		conn:          conn,
		participating: participating,
		own_addr:      addr,
		path:          "/ns/service/master/" + name,
	}

	ret.init()
	return ret, nil
}

// This is essentially the main loop of the master election process.
// Changes to the master election file are detected and reported.
// If we want to be eligible as masters, participation in master
// elections will also take place here.
func (m *MasterElectionClient) init() {
	var data []byte
	var err error

	m.wg.Add(1)

	data, m.old_rev, err = m.conn.Get(m.path, nil)
	if err == doozer.ErrNoEnt || m.old_rev == 0 {
		m.old_rev, err = m.conn.Rev()
		if err != nil {
			m.cb.ElectionFatal(err)
			return
		} else if m.participating {
			// There's no master, we'll have to find one.
			m.runMasterElection()
		}
	} else if err != nil {
		m.cb.ElectionFatal(err)
		return
	} else {
		m.old_rev += 1
		m.cb.BecomeSlave(string(data))
	}

	go m.run()
}

func (m *MasterElectionClient) run() {
	defer m.wg.Done()
	for {
		var ev doozer.Event
		var err error

		ev, err = m.conn.Wait(m.path, m.old_rev)
		if err != nil {
			m.cb.ElectionError(err)
			continue
		}

		// Make sure our path matches exactly
		if ev.Path != m.path {
			m.old_rev = ev.Rev + 1
			continue
		}

		if ev.IsDel() && m.participating {
			// Master election has been forced.
			m.runMasterElection()
		} else if ev.IsSet() {
			var master = string(ev.Body)

			if m.own_addr.String() != master {
				// We're just receiving a master update.
				m.cb.BecomeSlave(string(ev.Body))
			}
		}

		// Update our idea of the revision.
		m.old_rev = ev.Rev + 1
	}
}

// Attempt to be elected as a master.
func (m *MasterElectionClient) runMasterElection() {
	var new_master []byte
	var rev int64
	var err error

	rev, err = m.conn.Set(m.path, m.old_rev, []byte(m.own_addr.String()))
	if err == nil {
		err = m.cb.BecomeMaster()
		if err != nil {
			m.old_rev = rev + 1

			// We failed to become master, so we must force a new election.
			m.ForceMasterElection()
			return
		}

		// We are now a new master!
		m.old_rev = rev + 1
		return
	} else if err != doozer.ErrTooLate && err != doozer.ErrOldRev {
		m.cb.ElectionError(err)
	}

	// Let's do a read-current.
	new_master, rev, err = m.conn.Get(m.path, nil)
	if err != nil {
		m.cb.ElectionError(err)
		return
	}
	m.old_rev = rev + 1
	m.cb.BecomeSlave(string(new_master))
}

// Force a master election to take place right now.
func (m *MasterElectionClient) ForceMasterElection() error {
	var err error = m.conn.Del(m.path, m.old_rev)
	if err != nil && err != doozer.ErrTooLate && err != doozer.ErrOldRev {
		m.cb.ElectionError(err)
	}
	return err
}

// Wait synchronously for the master election to exit (basically never).
func (m *MasterElectionClient) SyncWait() {
	m.wg.Wait()
}
<commit_msg>Add methods for figuring out the current master.<commit_after>/**
 * (c) 2014, Caoimhe Chaos <caoimhechaos@protonmail.com>,
 *	     Ancient Solutions. All rights reserved.
 *
 * Redistribution and use in source  and binary forms, with or without
 * modification, are permitted  provided that the following conditions
 * are met:
 *
 * * Redistributions of  source code  must retain the  above copyright
 *   notice, this list of conditions and the following disclaimer.
 * * Redistributions in binary form must reproduce the above copyright
 *   notice, this  list of conditions and the  following disclaimer in
 *   the  documentation  and/or  other  materials  provided  with  the
 *   distribution.
 * * Neither  the  name  of  Ancient Solutions  nor  the  name  of its
 *   contributors may  be used to endorse or  promote products derived
 *   from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS"  AND ANY EXPRESS  OR IMPLIED WARRANTIES  OF MERCHANTABILITY
 * AND FITNESS  FOR A PARTICULAR  PURPOSE ARE DISCLAIMED. IN  NO EVENT
 * SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
 * INDIRECT, INCIDENTAL, SPECIAL,  EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED  TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE,  DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 * STRICT  LIABILITY,  OR  TORT  (INCLUDING NEGLIGENCE  OR  OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
 * OF THE POSSIBILITY OF SUCH DAMAGE.
 */

// Master election algorithm which uses Doozer as a lock server to
// determine whether or not a process is master.
package masterelection

import (
	"net"
	"sync"

	"github.com/ha/doozer"
)

// Interface for notifying the caller about changes in the master state.
type MasterElectionEventReceiver interface {
	// BecomeMaster() will be invoked when the process has been elected as
	// master. If an error is returned by BecomeMaster(), a new master
	// election will be forced.
	BecomeMaster() error

	// BecomeSlave() will be invoked every time the master election is lost.
	// It may also be invoked right before BecomeMaster() in case a master
	// election is forced. The name of the new master will be passed as
	// a host:port pair.
	//
	// It will also be inoked even if the process is already a slave, but
	// another master election has taken place. Due to this property,
	// BecomeSlave() may be used to receive notifications about changes
	// of the master.
	BecomeSlave(new_master string)

	// This callback will be invoked to report non-fatal errors in the
	// master election process to the client.
	ElectionError(err error)

	// This callback will be invoked to report fatal errors in the master
	// election process to the client.
	ElectionFatal(err error)
}

// Client for the master election procedure using a Doozer lock server.
// This can be used both in participating mode, where the process can become
// master, or in passive mode, where the current master may be discovered
// through the API and master elections may be forced, but the process will
// not participate in master elections and thus never itself become master.
type MasterElectionClient struct {
	conn          *doozer.Conn
	participating bool
	own_addr      net.Addr
	old_rev       int64
	cb            MasterElectionEventReceiver
	path          string
	master        string
	wg            sync.WaitGroup
}

// Create a new master election client for the elections with the given
// "name". The host and port of the master will be set to "addr".
// If "participating" is set to true, the client will participate in master
// elections, otherwise the client will just listen for changes of the
// current master.
//
// All notifications of being a master or slave will be done on the
// specified "callback".
func NewMasterElectionClient(conn *doozer.Conn, name string, addr net.Addr,
	participating bool, callback MasterElectionEventReceiver) (
	*MasterElectionClient, error) {
	var ret *MasterElectionClient = &MasterElectionClient{
		cb:            callback,
		conn:          conn,
		participating: participating,
		own_addr:      addr,
		path:          "/ns/service/master/" + name,
	}

	ret.init()
	return ret, nil
}

// This is essentially the main loop of the master election process.
// Changes to the master election file are detected and reported.
// If we want to be eligible as masters, participation in master
// elections will also take place here.
func (m *MasterElectionClient) init() {
	var data []byte
	var err error

	m.wg.Add(1)

	data, m.old_rev, err = m.conn.Get(m.path, nil)
	if err == doozer.ErrNoEnt || m.old_rev == 0 {
		m.old_rev, err = m.conn.Rev()
		if err != nil {
			m.cb.ElectionFatal(err)
			return
		} else if m.participating {
			// There's no master, we'll have to find one.
			m.runMasterElection()
		}
	} else if err != nil {
		m.cb.ElectionFatal(err)
		return
	} else {
		m.old_rev += 1
		m.master = string(data)
		m.cb.BecomeSlave(m.master)
	}

	go m.run()
}

func (m *MasterElectionClient) run() {
	defer m.wg.Done()
	for {
		var ev doozer.Event
		var err error

		ev, err = m.conn.Wait(m.path, m.old_rev)
		if err != nil {
			m.cb.ElectionError(err)
			continue
		}

		// Make sure our path matches exactly
		if ev.Path != m.path {
			m.old_rev = ev.Rev + 1
			continue
		}

		if ev.IsDel() && m.participating {
			// Master election has been forced.
			m.runMasterElection()
		} else if ev.IsSet() {
			var master = string(ev.Body)

			if m.own_addr.String() != master {
				// We're just receiving a master update.
				m.master = string(ev.Body)
				m.cb.BecomeSlave(m.master)
			}
		}

		// Update our idea of the revision.
		m.old_rev = ev.Rev + 1
	}
}

// Attempt to be elected as a master.
func (m *MasterElectionClient) runMasterElection() {
	var new_master []byte
	var rev int64
	var err error

	rev, err = m.conn.Set(m.path, m.old_rev, []byte(m.own_addr.String()))
	if err == nil {
		err = m.cb.BecomeMaster()
		if err != nil {
			m.old_rev = rev + 1

			// We failed to become master, so we must force a new election.
			m.ForceMasterElection()
			return
		}

		// We are now a new master!
		m.old_rev = rev + 1
		return
	} else if err != doozer.ErrTooLate && err != doozer.ErrOldRev {
		m.cb.ElectionError(err)
	}

	// Let's do a read-current.
	new_master, rev, err = m.conn.Get(m.path, nil)
	if err != nil {
		m.cb.ElectionError(err)
		return
	}
	m.old_rev = rev + 1
	m.master = string(new_master)
	m.cb.BecomeSlave(m.master)
}

// Force a master election to take place right now.
func (m *MasterElectionClient) ForceMasterElection() error {
	var err error = m.conn.Del(m.path, m.old_rev)
	if err != nil && err != doozer.ErrTooLate && err != doozer.ErrOldRev {
		m.cb.ElectionError(err)
	}
	return err
}

// Get what we think is currently the master. This is a very cheap
// operation which only reads local state.
//
// Please note that there is no guarantee that the data will still be
// valid at the time it is used.
func (m *MasterElectionClient) GetCurrentMaster() string {
	return m.master
}

// Force a read of the current master from Doozer. This will not update
// the internal state as that would confuse the notion of whether we're
// currently the master or a slave. This operation is rather expensive
// and GetCurrentMaster should be preferred when possible.
//
// Please note that there is no guarantee that the data will still be
// valid at the time it is used.
func (m *MasterElectionClient) ReadCurrentMaster() (string, error) {
	var data []byte
	var err error

	data, _, err = m.conn.Get(m.path, nil)
	return string(data), err
}

// Wait synchronously for the master election to exit (basically never).
func (m *MasterElectionClient) SyncWait() {
	m.wg.Wait()
}
<|endoftext|>


<commit_before>package meta

import (
	"fmt"
	"sort"
	"strconv"
	"strings"
)

const (
	componentMake = iota
	componentModel
	componentType
	componentNumber
	componentSubsource
	componentDip
	componentAzimuth
	componentTypes
	componentSamplingRate
	componentResponse
	componentLast
)

type Component struct {
	Make         string
	Model        string
	Type         string
	Number       int
	Subsource    string
	Dip          float64
	Azimuth      float64
	Types        string
	SamplingRate float64
	Response     string

	number       string
	dip          string
	azimuth      string
	samplingRate string
}

// Less compares Component structs suitable for sorting.
func (c Component) Less(comp Component) bool {

	switch {
	case strings.ToLower(c.Make) < strings.ToLower(comp.Make):
		return true
	case strings.ToLower(c.Make) > strings.ToLower(comp.Make):
		return false
	case strings.ToLower(c.Model) < strings.ToLower(comp.Model):
		return true
	case strings.ToLower(c.Model) > strings.ToLower(comp.Model):
		return false
	case c.Number < comp.Number:
		return true
	case c.Number > comp.Number:
		return false
	case c.SamplingRate < comp.SamplingRate:
		return true
	default:
		return false
	}
}

type ComponentList []Component

func (s ComponentList) Len() int           { return len(s) }
func (s ComponentList) Swap(i, j int)      { s[i], s[j] = s[j], s[i] }
func (s ComponentList) Less(i, j int) bool { return s[i].Less(s[j]) }

func (s ComponentList) encode() [][]string {
	data := [][]string{{
		"Make",
		"Model",
		"Type",
		"Number",
		"Subsource",
		"Dip",
		"Azimuth",
		"Types",
		"Sampling Rate",
		"Response",
	}}

	for _, v := range s {
		data = append(data, []string{
			strings.TrimSpace(v.Make),
			strings.TrimSpace(v.Model),
			strings.TrimSpace(v.Type),
			strings.TrimSpace(v.number),
			strings.TrimSpace(v.Subsource),
			strings.TrimSpace(v.dip),
			strings.TrimSpace(v.azimuth),
			strings.TrimSpace(v.Types),
			strings.TrimSpace(v.samplingRate),
			strings.TrimSpace(v.Response),
		})
	}
	return data
}
func (s *ComponentList) decode(data [][]string) error {
	var components []Component

	if !(len(data) > 1) {
		return nil
	}

	for _, d := range data[1:] {
		if len(d) != componentLast {
			return fmt.Errorf("incorrect pin of installed component fields")
		}

		var number int
		if s := strings.TrimSpace(d[componentNumber]); s != "" {
			v, err := strconv.Atoi(s)
			if err != nil {
				return err
			}
			number = v
		}

		var dip float64
		if s := strings.TrimSpace(d[componentDip]); s != "" {
			v, err := strconv.ParseFloat(s, 64)
			if err != nil {
				return err
			}
			dip = v
		}

		var azimuth float64
		if s := strings.TrimSpace(d[componentAzimuth]); s != "" {
			v, err := strconv.ParseFloat(d[componentAzimuth], 64)
			if err != nil {
				return err
			}
			azimuth = v
		}

		var samplingRate float64
		if s := strings.TrimSpace(d[componentSamplingRate]); s != "" {
			v, err := strconv.ParseFloat(d[componentSamplingRate], 64)
			if err != nil {
				return err
			}
			if v < 0.0 {
				v = -1.0 / v
			}
			samplingRate = v
		}

		components = append(components, Component{
			Make:         strings.TrimSpace(d[componentMake]),
			Model:        strings.TrimSpace(d[componentModel]),
			Type:         strings.TrimSpace(d[componentType]),
			Number:       number,
			Subsource:    strings.TrimSpace(d[componentSubsource]),
			Dip:          dip,
			Azimuth:      azimuth,
			Types:        strings.TrimSpace(d[componentTypes]),
			SamplingRate: samplingRate,
			Response:     strings.TrimSpace(d[componentResponse]),

			number:       strings.TrimSpace(d[componentNumber]),
			dip:          strings.TrimSpace(d[componentDip]),
			azimuth:      strings.TrimSpace(d[componentAzimuth]),
			samplingRate: strings.TrimSpace(d[componentSamplingRate]),
		})
	}

	*s = ComponentList(components)

	return nil
}

func LoadComponents(path string) ([]Component, error) {
	var s []Component

	if err := LoadList(path, (*ComponentList)(&s)); err != nil {
		return nil, err
	}

	sort.Sort(ComponentList(s))

	return s, nil
}
<commit_msg>fixed float parsing<commit_after>package meta

import (
	"fmt"
	"sort"
	"strconv"
	"strings"
)

const (
	componentMake = iota
	componentModel
	componentType
	componentNumber
	componentSubsource
	componentDip
	componentAzimuth
	componentTypes
	componentSamplingRate
	componentResponse
	componentLast
)

type Component struct {
	Make         string
	Model        string
	Type         string
	Number       int
	Subsource    string
	Dip          float64
	Azimuth      float64
	Types        string
	SamplingRate float64
	Response     string

	number       string
	dip          string
	azimuth      string
	samplingRate string
}

// Less compares Component structs suitable for sorting.
func (c Component) Less(comp Component) bool {

	switch {
	case strings.ToLower(c.Make) < strings.ToLower(comp.Make):
		return true
	case strings.ToLower(c.Make) > strings.ToLower(comp.Make):
		return false
	case strings.ToLower(c.Model) < strings.ToLower(comp.Model):
		return true
	case strings.ToLower(c.Model) > strings.ToLower(comp.Model):
		return false
	case c.Number < comp.Number:
		return true
	case c.Number > comp.Number:
		return false
	case c.SamplingRate < comp.SamplingRate:
		return true
	default:
		return false
	}
}

type ComponentList []Component

func (s ComponentList) Len() int           { return len(s) }
func (s ComponentList) Swap(i, j int)      { s[i], s[j] = s[j], s[i] }
func (s ComponentList) Less(i, j int) bool { return s[i].Less(s[j]) }

func (s ComponentList) encode() [][]string {
	data := [][]string{{
		"Make",
		"Model",
		"Type",
		"Number",
		"Subsource",
		"Dip",
		"Azimuth",
		"Types",
		"Sampling Rate",
		"Response",
	}}

	for _, v := range s {
		data = append(data, []string{
			strings.TrimSpace(v.Make),
			strings.TrimSpace(v.Model),
			strings.TrimSpace(v.Type),
			strings.TrimSpace(v.number),
			strings.TrimSpace(v.Subsource),
			strings.TrimSpace(v.dip),
			strings.TrimSpace(v.azimuth),
			strings.TrimSpace(v.Types),
			strings.TrimSpace(v.samplingRate),
			strings.TrimSpace(v.Response),
		})
	}
	return data
}
func (s *ComponentList) decode(data [][]string) error {
	var components []Component

	if !(len(data) > 1) {
		return nil
	}

	for _, d := range data[1:] {
		if len(d) != componentLast {
			return fmt.Errorf("incorrect pin of installed component fields")
		}

		var number int
		if s := strings.TrimSpace(d[componentNumber]); s != "" {
			v, err := strconv.Atoi(s)
			if err != nil {
				return err
			}
			number = v
		}

		var dip float64
		if s := strings.TrimSpace(d[componentDip]); s != "" {
			v, err := strconv.ParseFloat(s, 64)
			if err != nil {
				return err
			}
			dip = v
		}

		var azimuth float64
		if s := strings.TrimSpace(d[componentAzimuth]); s != "" {
			v, err := strconv.ParseFloat(s, 64)
			if err != nil {
				return err
			}
			azimuth = v
		}

		var samplingRate float64
		if s := strings.TrimSpace(d[componentSamplingRate]); s != "" {
			v, err := strconv.ParseFloat(s, 64)
			if err != nil {
				return err
			}
			if v < 0.0 {
				v = -1.0 / v
			}
			samplingRate = v
		}

		components = append(components, Component{
			Make:         strings.TrimSpace(d[componentMake]),
			Model:        strings.TrimSpace(d[componentModel]),
			Type:         strings.TrimSpace(d[componentType]),
			Number:       number,
			Subsource:    strings.TrimSpace(d[componentSubsource]),
			Dip:          dip,
			Azimuth:      azimuth,
			Types:        strings.TrimSpace(d[componentTypes]),
			SamplingRate: samplingRate,
			Response:     strings.TrimSpace(d[componentResponse]),

			number:       strings.TrimSpace(d[componentNumber]),
			dip:          strings.TrimSpace(d[componentDip]),
			azimuth:      strings.TrimSpace(d[componentAzimuth]),
			samplingRate: strings.TrimSpace(d[componentSamplingRate]),
		})
	}

	*s = ComponentList(components)

	return nil
}

func LoadComponents(path string) ([]Component, error) {
	var s []Component

	if err := LoadList(path, (*ComponentList)(&s)); err != nil {
		return nil, err
	}

	sort.Sort(ComponentList(s))

	return s, nil
}
<|endoftext|>


<commit_before>package golog

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

type LevelLogger interface {
	FailNow()
	Log(level int, vals ...interface{})
	Logf(level int, f string, vals ...interface{})
	Logc(level int, closure func() string)
}

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

func NoLocation(skip int) *LogLocation { return nil }

func FullLocation(skip int) *LogLocation {
	pc, file, line, ok := runtime.Caller(skip + 1)
	if !ok {
		return nil
	} else {
		funcParts := strings.SplitN(runtime.FuncForPC(pc).Name(), ".", 2)
		return &LogLocation{
			Package: funcParts[0],
			File: path.Base(file),
			Function: funcParts[1],
			Line: line,
		}
	}

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

func NewLevelLogger(l Logger, locFunc func(int) *LogLocation) LevelLogger {
	return &levelLoggerImpl{l, locFunc}
}

var DefaultLevelLogger LevelLogger = &levelLoggerImpl{DefaultLogger, NoLocation}

func (l *levelLoggerImpl) makeLogClosure(level int, msg func() string) func() *LogMessage {
	// Evaluate this early.
	ns := time.Nanoseconds()
	// TODO Be less brittle.
	// Skip over makeLogClosure, logCommon, and Log
	location := l.getLocation(3)

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

func (l *levelLoggerImpl) logCommon(level int, closure func() string) {
	l.Logger.Log(level, l.makeLogClosure(level, closure))
}

func (l *levelLoggerImpl) Log(level int, msg ...interface{}) {
	l.logCommon(level, func() string { return fmt.Sprint(msg...) })
}

func (l *levelLoggerImpl) Logf(level int, f string, msg ...interface{}) {
	l.logCommon(level, func() string { return fmt.Sprintf(f, msg...) })
}

func (l *levelLoggerImpl) Logc(level int, closure func() string) {
	l.logCommon(level, closure)
}
<commit_msg>Add TODO<commit_after>package golog

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

type LevelLogger interface {
	FailNow()
	Log(level int, vals ...interface{})
	Logf(level int, f string, vals ...interface{})
	Logc(level int, closure func() string)
}

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

func NoLocation(skip int) *LogLocation { return nil }

func FullLocation(skip int) *LogLocation {
	pc, file, line, ok := runtime.Caller(skip + 1)
	if !ok {
		return nil
	} else {
		// TODO Make sure this is compiler agnostic.
		funcParts := strings.SplitN(runtime.FuncForPC(pc).Name(), ".", 2)
		return &LogLocation{
			Package: funcParts[0],
			File: path.Base(file),
			Function: funcParts[1],
			Line: line,
		}
	}

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

func NewLevelLogger(l Logger, locFunc func(int) *LogLocation) LevelLogger {
	return &levelLoggerImpl{l, locFunc}
}

var DefaultLevelLogger LevelLogger = &levelLoggerImpl{DefaultLogger, NoLocation}

func (l *levelLoggerImpl) makeLogClosure(level int, msg func() string) func() *LogMessage {
	// Evaluate this early.
	ns := time.Nanoseconds()
	// TODO Be less brittle.
	// Skip over makeLogClosure, logCommon, and Log
	location := l.getLocation(3)

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

func (l *levelLoggerImpl) logCommon(level int, closure func() string) {
	l.Logger.Log(level, l.makeLogClosure(level, closure))
}

func (l *levelLoggerImpl) Log(level int, msg ...interface{}) {
	l.logCommon(level, func() string { return fmt.Sprint(msg...) })
}

func (l *levelLoggerImpl) Logf(level int, f string, msg ...interface{}) {
	l.logCommon(level, func() string { return fmt.Sprintf(f, msg...) })
}

func (l *levelLoggerImpl) Logc(level int, closure func() string) {
	l.logCommon(level, closure)
}
<|endoftext|>


<commit_before>package lfs

import (
	"fmt"
	"net/url"
	"path"
	"regexp"
	"strings"
)

const EndpointUrlUnknown = "<unknown>"

// An Endpoint describes how to access a Git LFS server.
type Endpoint struct {
	Url            string
	SshUserAndHost string
	SshPath        string
	SshPort        string
}

// NewEndpointFromCloneURL creates an Endpoint from a git clone URL by appending
// "[.git]/info/lfs".
func NewEndpointFromCloneURL(url string) Endpoint {
	e := NewEndpoint(url)
	if e.Url == EndpointUrlUnknown {
		return e
	}

	// When using main remote URL for HTTP, append info/lfs
	if path.Ext(url) == ".git" {
		e.Url += "/info/lfs"
	} else {
		e.Url += ".git/info/lfs"
	}
	return e
}

// NewEndpoint initializes a new Endpoint for a given URL.
func NewEndpoint(rawurl string) Endpoint {
	var endpoint Endpoint
	// Check for SSH URLs
	// Support ssh://user@host.com/path/to/repo and user@host.com:path/to/repo
	u, err := url.Parse(rawurl)
	if err == nil {
		u = processBareSshUrl(u)
		switch u.Scheme {
		case "ssh":
			endpoint = endpointFromSshUrl(u)
		case "http", "https":
			endpoint = endpointFromHttpUrl(u)
		default:
			// Just passthrough to preserve
			endpoint = Endpoint{Url: rawurl}
		}
	}

	return endpoint
}

// For ease of processing, sanitise a bare Git SSH URL into a ssh:// URL
func processBareSshUrl(u *url.URL) *url.URL {
	if u.Scheme != "" || u.Path == "" {
		return u
	}
	// This might be a bare SSH URL
	// Turn it into ssh:// for simplicity of extraction later
	parts := strings.Split(u.Path, ":")
	if len(parts) > 1 {
		// Treat presence of ':' as a bare URL
		var newPath string
		if len(parts) > 2 { // port included; really should only ever be 3 parts
			newPath = fmt.Sprintf("%v:%v", parts[0], strings.Join(parts[1:], "/"))
		} else {
			newPath = strings.Join(parts, "/")
		}
		newrawurl := fmt.Sprintf("ssh://%v", newPath)
		newu, err := url.Parse(newrawurl)
		if err == nil {
			return newu
		}
	}
	return u
}

// Construct a new endpoint from a SSH URL (sanitised to ssh://)
func endpointFromSshUrl(u *url.URL) Endpoint {
	if u.Scheme != "ssh" {
		return Endpoint{Url: EndpointUrlUnknown}
	}
	var host string
	var endpoint Endpoint
	// Pull out port now, we need it separately for SSH
	regex := regexp.MustCompile(`^([^\:]+)(?:\:(\d+))?$`)
	if match := regex.FindStringSubmatch(u.Host); match != nil {
		host = match[1]
		if u.User != nil && u.User.Username() != "" {
			endpoint.SshUserAndHost = fmt.Sprintf("%s@%s", u.User.Username(), host)
		} else {
			endpoint.SshUserAndHost = host
		}
		if len(match) > 2 {
			endpoint.SshPort = match[2]
		}
	} else {
		endpoint.Url = EndpointUrlUnknown
		return endpoint
	}

	// u.Path includes a preceding '/', strip off manually
	// rooted paths in the URL will be '//path/to/blah'
	// this is just how Go's URL parsing works
	if strings.HasPrefix(u.Path, "/") {
		endpoint.SshPath = u.Path[1:]
	} else {
		endpoint.SshPath = u.Path
	}
	// Fallback URL for using HTTPS while still using SSH for git
	// u.Host includes host & port so can't use SSH port
	endpoint.Url = fmt.Sprintf("https://%s%s", host, u.Path)

	return endpoint
}

// Construct a new endpoint from a HTTP URL
func endpointFromHttpUrl(u *url.URL) Endpoint {
	// just pass this straight through
	return Endpoint{Url: u.String()}
}

func ObjectUrl(endpoint Endpoint, oid string) (*url.URL, error) {
	u, err := url.Parse(endpoint.Url)
	if err != nil {
		return nil, err
	}

	u.Path = path.Join(u.Path, "objects")
	if len(oid) > 0 {
		u.Path = path.Join(u.Path, oid)
	}
	return u, nil
}
<commit_msg>ンンンン ン<commit_after>package lfs

import (
	"fmt"
	"net/url"
	"path"
	"regexp"
	"strings"
)

const EndpointUrlUnknown = "<unknown>"

// An Endpoint describes how to access a Git LFS server.
type Endpoint struct {
	Url            string
	SshUserAndHost string
	SshPath        string
	SshPort        string
}

// NewEndpointFromCloneURL creates an Endpoint from a git clone URL by appending
// "[.git]/info/lfs".
func NewEndpointFromCloneURL(url string) Endpoint {
	e := NewEndpoint(url)
	if e.Url == EndpointUrlUnknown {
		return e
	}

	// When using main remote URL for HTTP, append info/lfs
	if path.Ext(url) == ".git" {
		e.Url += "/info/lfs"
	} else {
		e.Url += ".git/info/lfs"
	}
	return e
}

// NewEndpoint initializes a new Endpoint for a given URL.
func NewEndpoint(rawurl string) Endpoint {
	var endpoint Endpoint
	// Check for SSH URLs
	// Support ssh://user@host.com/path/to/repo and user@host.com:path/to/repo
	u, err := url.Parse(rawurl)
	if err == nil {
		u = processBareSshUrl(u)
		switch u.Scheme {
		case "ssh":
			endpoint = endpointFromSshUrl(u)
		case "http", "https":
			endpoint = endpointFromHttpUrl(u)
		default:
			// Just passthrough to preserve
			endpoint = Endpoint{Url: rawurl}
		}
	} else {
		endpoint = Endpoint{Url: EndpointUrlUnknown}
	}

	return endpoint
}

// For ease of processing, sanitise a bare Git SSH URL into a ssh:// URL
func processBareSshUrl(u *url.URL) *url.URL {
	if u.Scheme != "" || u.Path == "" {
		return u
	}
	// This might be a bare SSH URL
	// Turn it into ssh:// for simplicity of extraction later
	parts := strings.Split(u.Path, ":")
	if len(parts) > 1 {
		// Treat presence of ':' as a bare URL
		var newPath string
		if len(parts) > 2 { // port included; really should only ever be 3 parts
			newPath = fmt.Sprintf("%v:%v", parts[0], strings.Join(parts[1:], "/"))
		} else {
			newPath = strings.Join(parts, "/")
		}
		newrawurl := fmt.Sprintf("ssh://%v", newPath)
		newu, err := url.Parse(newrawurl)
		if err == nil {
			return newu
		}
	}
	return u
}

// Construct a new endpoint from a SSH URL (sanitised to ssh://)
func endpointFromSshUrl(u *url.URL) Endpoint {
	if u.Scheme != "ssh" {
		return Endpoint{Url: EndpointUrlUnknown}
	}
	var host string
	var endpoint Endpoint
	// Pull out port now, we need it separately for SSH
	regex := regexp.MustCompile(`^([^\:]+)(?:\:(\d+))?$`)
	if match := regex.FindStringSubmatch(u.Host); match != nil {
		host = match[1]
		if u.User != nil && u.User.Username() != "" {
			endpoint.SshUserAndHost = fmt.Sprintf("%s@%s", u.User.Username(), host)
		} else {
			endpoint.SshUserAndHost = host
		}
		if len(match) > 2 {
			endpoint.SshPort = match[2]
		}
	} else {
		endpoint.Url = EndpointUrlUnknown
		return endpoint
	}

	// u.Path includes a preceding '/', strip off manually
	// rooted paths in the URL will be '//path/to/blah'
	// this is just how Go's URL parsing works
	if strings.HasPrefix(u.Path, "/") {
		endpoint.SshPath = u.Path[1:]
	} else {
		endpoint.SshPath = u.Path
	}
	// Fallback URL for using HTTPS while still using SSH for git
	// u.Host includes host & port so can't use SSH port
	endpoint.Url = fmt.Sprintf("https://%s%s", host, u.Path)

	return endpoint
}

// Construct a new endpoint from a HTTP URL
func endpointFromHttpUrl(u *url.URL) Endpoint {
	// just pass this straight through
	return Endpoint{Url: u.String()}
}

func ObjectUrl(endpoint Endpoint, oid string) (*url.URL, error) {
	u, err := url.Parse(endpoint.Url)
	if err != nil {
		return nil, err
	}

	u.Path = path.Join(u.Path, "objects")
	if len(oid) > 0 {
		u.Path = path.Join(u.Path, oid)
	}
	return u, nil
}
<|endoftext|>