<commit_before>// Copyright 2016, RadiantBlue Technologies, 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 systest

import (
	"bytes"
	"fmt"
	"io"
	"net/http"
	"strconv"
	"strings"
	"testing"
	"time"

	"github.com/stretchr/testify/assert"
	"github.com/stretchr/testify/suite"
	"github.com/venicegeo/pz-gocommon/gocommon"
	pzsyslog "github.com/venicegeo/pz-gocommon/syslog"
)

func sleep() {
	time.Sleep(1 * time.Second)
}

type LoggerTester struct {
	suite.Suite
	writer     pzsyslog.Writer
	httpWriter *pzsyslog.HttpWriter
	logger     *pzsyslog.Logger
	url        string
	apiKey     string
	apiServer  string
}

func (suite *LoggerTester) setupFixture() {
	t := suite.T()
	assert := assert.New(t)

	var err error

	suite.apiServer, err = piazza.GetApiServer()
	assert.NoError(err)

	i := strings.Index(suite.apiServer, ".")
	assert.NotEqual(1, i)
	host := "pz-logger" + suite.apiServer[i:]
	suite.url = "https://" + host

	suite.apiKey, err = piazza.GetApiKey(suite.apiServer)
	assert.NoError(err)

	suite.httpWriter, err = pzsyslog.NewHttpWriter(suite.url)
	suite.writer = suite.httpWriter
	assert.NoError(err)
	suite.logger = pzsyslog.NewLogger(suite.writer, "loggersystesterapp")
}

func (suite *LoggerTester) teardownFixture() {
}

func TestRunSuite(t *testing.T) {
	s := &LoggerTester{}
	suite.Run(t, s)
}

func (suite *LoggerTester) verifyMessageExists(expected *pzsyslog.Message) bool {
	t := suite.T()
	assert := assert.New(t)

	format := &piazza.JsonPagination{
		PerPage: 100,
		Page:    0,
		Order:   piazza.SortOrderDescending,
		SortBy:  "createdOn",
	}
	ms, _, err := suite.httpWriter.GetMessages(format, nil)
	fmt.Println("====\n", ms, "\n=====")
	assert.NoError(err)
	assert.Len(ms, format.PerPage)

	for _, m := range ms {
		if m.String() == expected.String() {
			return true
		}
	}
	return false
}

func (suite *LoggerTester) getVersion() (*piazza.Version, error) {
	h := &piazza.Http{BaseUrl: suite.url}

	jresp := h.PzGet("/version")
	if jresp.IsError() {
		return nil, jresp.ToError()
	}

	var version piazza.Version
	err := jresp.ExtractData(&version)
	if err != nil {
		return nil, err
	}

	return &version, nil
}

func (suite *LoggerTester) getStats(output interface{}) error {
	h := &piazza.Http{BaseUrl: suite.url}

	jresp := h.PzGet("/admin/stats")
	if jresp.IsError() {
		return jresp.ToError()
	}

	return jresp.ExtractData(output)
}

func (suite *LoggerTester) Test00Version() {
	t := suite.T()
	assert := assert.New(t)

	suite.setupFixture()
	defer suite.teardownFixture()

	version, err := suite.getVersion()
	assert.NoError(err)
	assert.EqualValues("1.0.0", version.Version)
}

func (suite *LoggerTester) Test01RawGet() {
	t := suite.T()
	assert := assert.New(t)

	suite.setupFixture()
	defer suite.teardownFixture()

	resp, err := http.Get(suite.url + "/message?perPage=13&page=&0")
	assert.NoError(err)
	assert.True(resp.ContentLength >= 0)
	if resp.ContentLength == -1 {
		assert.FailNow("bonk")
	}
	assert.True(resp.ContentLength > 0)

	raw := make([]byte, resp.ContentLength)
	_, err = io.ReadFull(resp.Body, raw)
	defer func() {
		err = resp.Body.Close()
		assert.NoError(err)
	}()
	if err != nil && err != io.EOF {
		assert.NoError(err)
	}

	assert.Equal(200, resp.StatusCode)
}

func (suite *LoggerTester) Test02RawPost() {
	t := suite.T()
	assert := assert.New(t)

	suite.setupFixture()
	defer suite.teardownFixture()

	jsn := `
	{
		"address":"XXX",
		"createdOn":"2016-07-22T16:44:58.065583138-04:00",
		"message":"XXX",
		"service":"XXX",
		"severity":"XXX"
	}`
	reader := bytes.NewReader([]byte(jsn))

	resp, err := http.Post(suite.url+"/message",
		piazza.ContentTypeJSON, reader)
	assert.NoError(err)

	raw := make([]byte, resp.ContentLength)
	_, err = io.ReadFull(resp.Body, raw)
	defer func() {
		err = resp.Body.Close()
		assert.NoError(err)
	}()
	if err != nil && err != io.EOF {
		assert.NoError(err)
	}

	//err = json.Unmarshal(raw, output)
	//assett.NoError(err)

	assert.Equal(200, resp.StatusCode)
}

func (suite *LoggerTester) Test03Get() {
	t := suite.T()
	assert := assert.New(t)

	suite.setupFixture()
	defer suite.teardownFixture()

	format := &piazza.JsonPagination{
		PerPage: 12,
		Page:    0,
		Order:   piazza.SortOrderAscending,
		SortBy:  "createdOn",
	}
	ms, _, err := suite.httpWriter.GetMessages(format, nil)
	assert.NoError(err)
	assert.Len(ms, format.PerPage)
}

func (suite *LoggerTester) Test04Post() {
	t := suite.T()
	assert := assert.New(t)

	suite.setupFixture()
	defer suite.teardownFixture()

	var err error

	key := time.Now().String()

	data := &pzsyslog.Message{
		Facility:    1,
		Version:     1,
		Process:     "pid1",
		Application: "log-tester",
		HostName:    "128.1.2.3",
		TimeStamp:   time.Now(),
		Severity:    pzsyslog.Notice,
		Message:     key,
	}

	err = suite.writer.Write(data)
	assert.NoError(err, "PostToMessages")

	sleep()

	assert.True(suite.verifyMessageExists(data))
}

func (suite *LoggerTester) xTest05PostHelpers() {
	t := suite.T()
	assert := assert.New(t)

	suite.setupFixture()
	defer suite.teardownFixture()

	uniq := time.Now().String()
	//TODO client.Info(uniq)

	sleep()

	{
		format := &piazza.JsonPagination{
			PerPage: 100,
			Page:    0,
			Order:   piazza.SortOrderDescending,
			SortBy:  "createdOn",
		}
		ms, _, err := suite.httpWriter.GetMessages(format, nil)
		assert.NoError(err)
		assert.True(len(ms) <= format.PerPage)

		ok := false
		for _, m := range ms {
			if m.Message == uniq {
				ok = true
				break
			}
		}
		assert.True(ok)
	}
}

func (suite *LoggerTester) Test06Admin() {
	t := suite.T()
	assert := assert.New(t)

	suite.setupFixture()
	defer suite.teardownFixture()

	output := map[string]interface{}{}
	err := suite.getStats(&output)
	assert.NoError(err)
	assert.NotZero(output["numMessages"])
}

func (suite *LoggerTester) Test07Pagination() {
	t := suite.T()
	assert := assert.New(t)

	suite.setupFixture()
	defer suite.teardownFixture()

	format := &piazza.JsonPagination{
		PerPage: 10,
		Page:    0,
		SortBy:  "createdOn",
		Order:   piazza.SortOrderAscending,
	}
	params := &piazza.HttpQueryParams{}

	// check per-page
	{
		format.PerPage = 17
		ms, _, err := suite.httpWriter.GetMessages(format, params)
		assert.NoError(err)
		assert.Len(ms, 17)
	}

	// check sort order
	{
		format.PerPage = 10
		format.Order = piazza.SortOrderAscending
		ms, _, err := suite.httpWriter.GetMessages(format, params)
		assert.NoError(err)
		last := len(ms) - 1
		assert.True(last <= 9)

		// we can't check "before", because two createdOn's might be the same
		isBefore := ms[0].TimeStamp.Before(ms[last].TimeStamp)
		isEqual := ms[0].TimeStamp.Equal(ms[last].TimeStamp)
		assert.True(isBefore || isEqual)

		format.Order = piazza.SortOrderDescending
		ms, _, err = suite.httpWriter.GetMessages(format, params)
		assert.NoError(err)
		last = len(ms) - 1
		assert.True(last <= 9)

		isAfter := ms[0].TimeStamp.After(ms[last].TimeStamp)
		isEqual = ms[0].TimeStamp.Equal(ms[last].TimeStamp)
		assert.True(isAfter || isEqual)
	}

	// check sort-by
	{
		format.Order = piazza.SortOrderAscending
		format.SortBy = "severity"
		format.PerPage = 100
		format.Page = 0
		ms, _, err := suite.httpWriter.GetMessages(format, params)
		if err != nil {
			panic(88)
		}
		assert.NoError(err)

		last := len(ms) - 1
		for i := 0; i < last; i++ {
			a, b := string(ms[i].Severity), string(ms[i+1].Severity)
			isBefore := (a <= b)
			assert.True(isBefore)
		}
	}
}

func (suite *LoggerTester) xTest08Params() {
	t := suite.T()
	assert := assert.New(t)

	suite.setupFixture()
	defer suite.teardownFixture()

	uniqService := strconv.Itoa(time.Now().Nanosecond())
	uniqDebug := strconv.Itoa(time.Now().Nanosecond() * 3)
	//uniqError := strconv.Itoa(time.Now().Nanosecond() * 5)
	//uniqFatal := strconv.Itoa(time.Now().Nanosecond() * 7)

	now := time.Now()
	sec3 := time.Second * 3
	tstart := now.Add(-sec3)

	//TODO client.Debug(uniqDebug)
	//TODO client.Error(uniqError)
	//TODO client.Fatal(uniqFatal)

	sleep()

	format := &piazza.JsonPagination{
		PerPage: 256,
		Page:    0,
		Order:   piazza.SortOrderDescending,
		SortBy:  "createdOn",
	}

	// test date range params
	{
		tend := now.Add(sec3)

		params := &piazza.HttpQueryParams{}
		params.AddTime("after", tstart)
		params.AddTime("before", tend)

		msgs, cnt, err := suite.httpWriter.GetMessages(format, params)

		assert.NoError(err)
		assert.True(cnt >= 3)
		assert.True(len(msgs) >= 3)
	}

	// test service param
	{
		params := &piazza.HttpQueryParams{}
		params.AddString("service", uniqService)

		msgs, _, err := suite.httpWriter.GetMessages(format, params)

		assert.NoError(err)
		assert.Len(msgs, 3)
	}

	// test contains param
	{
		params := &piazza.HttpQueryParams{}
		params.AddString("contains", uniqDebug)

		msgs, _, err := suite.httpWriter.GetMessages(format, params)

		assert.NoError(err)
		assert.True(len(msgs) == 1)
	}
}
<commit_msg>updated the systests — a few still failing, though<commit_after>// Copyright 2016, RadiantBlue Technologies, 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 systest

import (
	"bytes"
	"io"
	"net/http"
	"strconv"
	"strings"
	"testing"
	"time"

	"encoding/json"

	"github.com/stretchr/testify/assert"
	"github.com/stretchr/testify/suite"
	"github.com/venicegeo/pz-gocommon/gocommon"
	pzsyslog "github.com/venicegeo/pz-gocommon/syslog"
)

func sleep() {
	time.Sleep(1 * time.Second)
}

type LoggerTester struct {
	suite.Suite
	writer     pzsyslog.Writer
	httpWriter *pzsyslog.HttpWriter
	logger     *pzsyslog.Logger
	url        string
	apiKey     string
	apiServer  string
}

func (suite *LoggerTester) setupFixture() {
	t := suite.T()
	assert := assert.New(t)

	var err error

	suite.apiServer, err = piazza.GetApiServer()
	assert.NoError(err)

	i := strings.Index(suite.apiServer, ".")
	assert.NotEqual(1, i)
	host := "pz-logger" + suite.apiServer[i:]
	suite.url = "https://" + host

	suite.apiKey, err = piazza.GetApiKey(suite.apiServer)
	assert.NoError(err)

	suite.httpWriter, err = pzsyslog.NewHttpWriter(suite.url)
	suite.writer = suite.httpWriter
	assert.NoError(err)
	suite.logger = pzsyslog.NewLogger(suite.writer, "loggersystesterapp")
}

func (suite *LoggerTester) teardownFixture() {
}

func TestRunSuite(t *testing.T) {
	s := &LoggerTester{}
	suite.Run(t, s)
}

func (suite *LoggerTester) verifyMessageExists(expected *pzsyslog.Message) bool {
	t := suite.T()
	assert := assert.New(t)

	format := &piazza.JsonPagination{
		PerPage: 100,
		Page:    0,
		Order:   piazza.SortOrderDescending,
		SortBy:  "timeStamp",
	}
	ms, _, err := suite.httpWriter.GetMessages(format, nil)
	assert.NoError(err)
	assert.Len(ms, format.PerPage)

	for _, m := range ms {
		if m.Message == expected.Message {
			return true
		}
	}

	return false
}

func (suite *LoggerTester) getVersion() (*piazza.Version, error) {
	h := &piazza.Http{BaseUrl: suite.url}

	jresp := h.PzGet("/version")
	if jresp.IsError() {
		return nil, jresp.ToError()
	}

	var version piazza.Version
	err := jresp.ExtractData(&version)
	if err != nil {
		return nil, err
	}

	return &version, nil
}

func (suite *LoggerTester) getStats(output interface{}) error {
	h := &piazza.Http{BaseUrl: suite.url}

	jresp := h.PzGet("/admin/stats")
	if jresp.IsError() {
		return jresp.ToError()
	}

	return jresp.ExtractData(output)
}

func (suite *LoggerTester) xTest00Version() {
	t := suite.T()
	assert := assert.New(t)

	suite.setupFixture()
	defer suite.teardownFixture()

	version, err := suite.getVersion()
	assert.NoError(err)
	assert.EqualValues("1.0.0", version.Version)
}

func (suite *LoggerTester) Test01RawGet() {
	t := suite.T()
	assert := assert.New(t)

	suite.setupFixture()
	defer suite.teardownFixture()

	resp, err := http.Get(suite.url + "/syslog")
	assert.NoError(err)
	assert.True(resp.ContentLength >= 0)
	if resp.ContentLength == -1 {
		assert.FailNow("bonk")
	}
	assert.True(resp.ContentLength > 0)

	raw := make([]byte, resp.ContentLength)
	_, err = io.ReadFull(resp.Body, raw)
	defer func() {
		err = resp.Body.Close()
		assert.NoError(err)
	}()
	if err != nil && err != io.EOF {
		assert.NoError(err)
	}

	assert.Equal(200, resp.StatusCode)
}

func (suite *LoggerTester) Test02RawPost() {
	t := suite.T()
	assert := assert.New(t)

	suite.setupFixture()
	defer suite.teardownFixture()

	mssg := pzsyslog.NewMessage()
	mssg.Severity = pzsyslog.Warning
	mssg.HostName = "example.com"
	mssg.Application = "testapp"
	mssg.Process = "0x0000"
	jsn, err := json.Marshal(mssg)
	reader := bytes.NewReader(jsn)

	resp, err := http.Post(suite.url+"/syslog",
		piazza.ContentTypeJSON, reader)
	assert.NoError(err)

	raw := make([]byte, resp.ContentLength)
	_, err = io.ReadFull(resp.Body, raw)
	defer func() {
		err = resp.Body.Close()
		assert.NoError(err)
	}()
	if err != nil && err != io.EOF {
		assert.NoError(err)
	}

	assert.Equal(200, resp.StatusCode)
}

func (suite *LoggerTester) Test03Get() {
	t := suite.T()
	assert := assert.New(t)

	suite.setupFixture()
	defer suite.teardownFixture()

	format := &piazza.JsonPagination{
		PerPage: 12,
		Page:    0,
		Order:   piazza.SortOrderAscending,
		SortBy:  "timeStamp",
	}
	ms, _, err := suite.httpWriter.GetMessages(format, nil)
	assert.NoError(err)
	assert.Len(ms, format.PerPage)
}

func (suite *LoggerTester) xTest04Post() {
	t := suite.T()
	assert := assert.New(t)

	suite.setupFixture()
	defer suite.teardownFixture()

	var err error

	key := "KEY KEY KEY " + time.Now().String()

	mssg := &pzsyslog.Message{
		Facility:    1,
		Version:     1,
		Process:     "pid1",
		Application: "log-tester",
		HostName:    "128.1.2.3",
		TimeStamp:   time.Now(),
		Severity:    pzsyslog.Notice,
		Message:     key,
	}

	err = suite.writer.Write(mssg)
	assert.NoError(err, "PostToMessages")

	for i := 0; i < 100; i++ {
		ok := suite.verifyMessageExists(mssg)
		assert.False(ok)
		sleep()
	}
}

func (suite *LoggerTester) xTest05PostHelpers() {
	t := suite.T()
	assert := assert.New(t)

	suite.setupFixture()
	defer suite.teardownFixture()

	uniq := time.Now().String()

	suite.logger.Info(uniq)

	sleep()
	sleep()
	sleep()

	{
		format := &piazza.JsonPagination{
			PerPage: 100,
			Page:    0,
			Order:   piazza.SortOrderDescending,
			SortBy:  "timeStamp",
		}
		ms, _, err := suite.httpWriter.GetMessages(format, nil)
		assert.NoError(err)
		assert.True(len(ms) <= format.PerPage)

		ok := false
		for _, m := range ms {
			if m.Message == uniq {
				ok = true
				break
			}
		}
		assert.True(ok)
	}
}

func (suite *LoggerTester) Test06Admin() {
	t := suite.T()
	assert := assert.New(t)

	suite.setupFixture()
	defer suite.teardownFixture()

	output := map[string]interface{}{}
	err := suite.getStats(&output)
	assert.NoError(err)
	assert.NotZero(output["numMessages"])
}

func (suite *LoggerTester) Test07Pagination() {
	t := suite.T()
	assert := assert.New(t)

	suite.setupFixture()
	defer suite.teardownFixture()

	format := &piazza.JsonPagination{
		PerPage: 10,
		Page:    0,
		SortBy:  "timeStamp",
		Order:   piazza.SortOrderAscending,
	}
	params := &piazza.HttpQueryParams{}

	// check per-page
	{
		format.PerPage = 17
		ms, _, err := suite.httpWriter.GetMessages(format, params)
		assert.NoError(err)
		assert.Len(ms, 17)
	}

	// check sort order
	{
		format.PerPage = 10
		format.Order = piazza.SortOrderAscending
		ms, _, err := suite.httpWriter.GetMessages(format, params)
		assert.NoError(err)
		last := len(ms) - 1
		assert.True(last <= 9)

		// we can't check "before", because two timeStamp's might be the same
		isBefore := ms[0].TimeStamp.Before(ms[last].TimeStamp)
		isEqual := ms[0].TimeStamp.Equal(ms[last].TimeStamp)
		assert.True(isBefore || isEqual)

		format.Order = piazza.SortOrderDescending
		ms, _, err = suite.httpWriter.GetMessages(format, params)
		assert.NoError(err)
		last = len(ms) - 1
		assert.True(last <= 9)

		isAfter := ms[0].TimeStamp.After(ms[last].TimeStamp)
		isEqual = ms[0].TimeStamp.Equal(ms[last].TimeStamp)
		assert.True(isAfter || isEqual)
	}

	// check sort-by
	{
		format.Order = piazza.SortOrderAscending
		format.SortBy = "severity"
		format.PerPage = 100
		format.Page = 0
		ms, _, err := suite.httpWriter.GetMessages(format, params)
		if err != nil {
			panic(88)
		}
		assert.NoError(err)

		last := len(ms) - 1
		for i := 0; i < last; i++ {
			a, b := string(ms[i].Severity), string(ms[i+1].Severity)
			isBefore := (a <= b)
			assert.True(isBefore)
		}
	}
}

func (suite *LoggerTester) xTest08Params() {
	t := suite.T()
	assert := assert.New(t)

	suite.setupFixture()
	defer suite.teardownFixture()

	uniqService := strconv.Itoa(time.Now().Nanosecond())
	uniqDebug := strconv.Itoa(time.Now().Nanosecond() * 3)
	//uniqError := strconv.Itoa(time.Now().Nanosecond() * 5)
	//uniqFatal := strconv.Itoa(time.Now().Nanosecond() * 7)

	now := time.Now()
	sec3 := time.Second * 3
	tstart := now.Add(-sec3)

	//TODO client.Debug(uniqDebug)
	//TODO client.Error(uniqError)
	//TODO client.Fatal(uniqFatal)

	sleep()

	format := &piazza.JsonPagination{
		PerPage: 256,
		Page:    0,
		Order:   piazza.SortOrderDescending,
		SortBy:  "timeStamp",
	}

	// test date range params
	{
		tend := now.Add(sec3)

		params := &piazza.HttpQueryParams{}
		params.AddTime("after", tstart)
		params.AddTime("before", tend)

		msgs, cnt, err := suite.httpWriter.GetMessages(format, params)

		assert.NoError(err)
		assert.True(cnt >= 3)
		assert.True(len(msgs) >= 3)
	}

	// test service param
	{
		params := &piazza.HttpQueryParams{}
		params.AddString("service", uniqService)

		msgs, _, err := suite.httpWriter.GetMessages(format, params)

		assert.NoError(err)
		assert.Len(msgs, 3)
	}

	// test contains param
	{
		params := &piazza.HttpQueryParams{}
		params.AddString("contains", uniqDebug)

		msgs, _, err := suite.httpWriter.GetMessages(format, params)

		assert.NoError(err)
		assert.True(len(msgs) == 1)
	}
}
<|endoftext|>


<commit_before>package mgo

import (
	. "launchpad.net/gocheck"
	"net"
)

type ServerSuite struct {
}

var _ = Suite(&ServerSuite{})

func (s *ServerSuite) TestCloseDuringConnect(c *C) {
	var server *mongoServer
	closeDial := func(addr net.Addr) (net.Conn, error) {
		// The first call to this will be during newServer, and
		// server will be nil. Once it returns, the second call
		// will be with a valid server, and we will Close it.
		if server != nil {
			server.Close()
		}
		return net.DialTCP("tcp", nil, addr.(*net.TCPAddr))
	}
	localhostServer, err := net.Listen("tcp", "localhost:0")
	c.Assert(err, IsNil)
	defer localhostServer.Close()
	go func() {
		// Accept a connection but don't do anything with it
		for {
			conn, err := localhostServer.Accept()
                        logf("got connection: %v", conn)
			if err != nil {
				return
			}
			conn.Close()
		}
	}()
	tcpaddr := localhostServer.Addr().(*net.TCPAddr)
	server = newServer(tcpaddr.String(), tcpaddr, make(chan bool), closeDial)
	c.Assert(server, NotNil)
	// It is possible for newServer to ping the remote host, and the
	// request returns immediately (because writing to the socket fails).
	// In which case pinger(loop=false) puts the closed socket back into
	// unused. We have to wait until readLoop gets a EOF and removes the
	// socket from the queue.
	for {
		server.RLock()
		count := len(server.unusedSockets)
		server.RUnlock()
		if count == 0 {
			break
		}
                logf("server had %d unused sockets waiting for 0", count)
	}
	conn, _, err := server.AcquireSocket(0)
	c.Check(err, Equals, errServerClosed)
	c.Assert(conn, IsNil)
}
<commit_msg>go fmt<commit_after>package mgo

import (
	. "launchpad.net/gocheck"
	"net"
)

type ServerSuite struct {
}

var _ = Suite(&ServerSuite{})

func (s *ServerSuite) TestCloseDuringConnect(c *C) {
	var server *mongoServer
	closeDial := func(addr net.Addr) (net.Conn, error) {
		// The first call to this will be during newServer, and
		// server will be nil. Once it returns, the second call
		// will be with a valid server, and we will Close it.
		if server != nil {
			server.Close()
		}
		return net.DialTCP("tcp", nil, addr.(*net.TCPAddr))
	}
	localhostServer, err := net.Listen("tcp", "localhost:0")
	c.Assert(err, IsNil)
	defer localhostServer.Close()
	go func() {
		// Accept a connection but don't do anything with it
		for {
			conn, err := localhostServer.Accept()
			logf("got connection: %v", conn)
			if err != nil {
				return
			}
			conn.Close()
		}
	}()
	tcpaddr := localhostServer.Addr().(*net.TCPAddr)
	server = newServer(tcpaddr.String(), tcpaddr, make(chan bool), closeDial)
	c.Assert(server, NotNil)
	// It is possible for newServer to ping the remote host, and the
	// request returns immediately (because writing to the socket fails).
	// In which case pinger(loop=false) puts the closed socket back into
	// unused. We have to wait until readLoop gets a EOF and removes the
	// socket from the queue.
	for {
		server.RLock()
		count := len(server.unusedSockets)
		server.RUnlock()
		if count == 0 {
			break
		}
		logf("server had %d unused sockets waiting for 0", count)
	}
	conn, _, err := server.AcquireSocket(0)
	c.Check(err, Equals, errServerClosed)
	c.Assert(conn, IsNil)
}
<|endoftext|>


<commit_before>package main

import (
	"testing"
	"io/ioutil"
)

// TestValidPayload tests if we can create a proper object from
// a valid JSON payload.
func TestValidPayload(t *testing.T) {
	json := `[{
		"message" : {
		   "reqHost" : "www.example.com",
		   "respLen" : "276248",
		   "cliIP" : "123.123.123.123",
		   "status" : "503",
		   "bytes" : "123440",
		   "protoVer" : "1.1",
		   "respCT" : "text/html",
		   "UA" : "Mozilla%2f5.0%20(Macintosh%3b%20Intel%20Mac%20OS%20X%2010.9%3b%20rv%3a28.0)%20Gecko%2f20100101%20Firefox%2f28.0%20(FlipboardProxy%2f1.1%3b%20+http%3a%2f%2fflipboard.com%2fbrowserproxy)",
		   "reqMethod" : "POST",
		   "fwdHost" : "www.example.com",
		   "proto" : "http",
		   "reqPort" : "80",
		   "reqPath" : "%2f"
		},
		"netPerf" : {
		   "asnum" : "8523",
		   "downloadTime" : "1",
		   "edgeIP" : "165.254.92.141",
		   "lastByte" : "0",
		   "lastMileRTT" : "102",
		   "firstByte" : "0",
		   "cacheStatus" : "0"
		},
		"network" : {
		   "asnum" : "8523",
		   "edgeIP" : "165.254.92.141",
		   "networkType" : "",
		   "network" : ""
		},
		"cp" : "123456",
		"id" : "915cfea5570f824cc27112-a",
		"version" : "1.0",
		"start" : "1460634188.565",
		"type" : "cloud_monitor",
		"format" : "default",
		"respHdr" : {
		   "server" : "Microsoft-IIS/8.5",
		   "contEnc" : "identity"
		},
		"geo" : {
		   "lat" : "59.33",
		   "region" : "AB",
		   "long" : "18.05",
		   "country" : "DE",
		   "city" : "dummy"
		},
		"reqHdr" : {
		   "cookie" : "drbanan%3d1"
		}
	 }]`

	payloads, err := CreateObjects([]byte(json))
	if err != nil {
		t.Errorf("Error while trying to decode valid JSON payload: %s", err)
	}

	if len(payloads) != 1 {
		t.Errorf("Unexpected number of payloads in JSON: Should be 1, is %d", len(payloads))
	}

	payload := payloads[0]
	if payload.CP != "123456" {
		t.Errorf("CP not correct in payload. Should be 123456, is %s", payload.CP)
	}
	if payload.ID != "915cfea5570f824cc27112-a" {
		t.Errorf("ID not correct in payload. Should be 915cfea5570f824cc27112-a, is %s", payload.ID)
	}
	if payload.Geo.Country != "DE" {
		t.Errorf("Country not correct in payload. Should be DE, is %s", payload.Geo.Country)
	}
}

// TestMultiplePayloads tests if a correct number of payload objects are created.
func TestMultiplePayloads(t *testing.T) {
	dat, err:= ioutil.ReadFile("tests/payload.json")
	payloads, err := CreateObjects([]byte(dat))
	if err != nil {
		t.Errorf("Error while trying to decode valid JSON payload: %s", err)
	}
	// test custom number of payloads in JSON file
	if len(payloads) != 27 {
		t.Errorf("Unexpected number of payloads in JSON: Should be 7, is %d", len(payloads))
	}

	for i := 0; i < len(payloads); i++ {
		if payloads[i].CP != "123456" {
			t.Errorf("CP not correct in payload. Should be 123456, is %s", payloads[i].CP)
		}
	}

	// TODO test other fields
}
<commit_msg>Test chanaged<commit_after>package main

import (
	"io/ioutil"
	"testing"
)

// TestValidPayload tests if we can create a proper object from
// a valid JSON payload.
func TestValidPayload(t *testing.T) {
	json := `[{
		"message" : {
		   "reqHost" : "www.example.com",
		   "respLen" : "276248",
		   "cliIP" : "123.123.123.123",
		   "status" : "503",
		   "bytes" : "123440",
		   "protoVer" : "1.1",
		   "respCT" : "text/html",
		   "UA" : "Mozilla%2f5.0%20(Macintosh%3b%20Intel%20Mac%20OS%20X%2010.9%3b%20rv%3a28.0)%20Gecko%2f20100101%20Firefox%2f28.0%20(FlipboardProxy%2f1.1%3b%20+http%3a%2f%2fflipboard.com%2fbrowserproxy)",
		   "reqMethod" : "POST",
		   "fwdHost" : "www.example.com",
		   "proto" : "http",
		   "reqPort" : "80",
		   "reqPath" : "%2f"
		},
		"netPerf" : {
		   "asnum" : "8523",
		   "downloadTime" : "1",
		   "edgeIP" : "165.254.92.141",
		   "lastByte" : "0",
		   "lastMileRTT" : "102",
		   "firstByte" : "0",
		   "cacheStatus" : "0"
		},
		"network" : {
		   "asnum" : "8523",
		   "edgeIP" : "165.254.92.141",
		   "networkType" : "",
		   "network" : ""
		},
		"cp" : "123456",
		"id" : "915cfea5570f824cc27112-a",
		"version" : "1.0",
		"start" : "1460634188.565",
		"type" : "cloud_monitor",
		"format" : "default",
		"respHdr" : {
		   "server" : "Microsoft-IIS/8.5",
		   "contEnc" : "identity"
		},
		"geo" : {
		   "lat" : "59.33",
		   "region" : "AB",
		   "long" : "18.05",
		   "country" : "DE",
		   "city" : "dummy"
		},
		"reqHdr" : {
		   "cookie" : "drbanan%3d1"
		}
	 }]`

	payloads, err := CreateObjects([]byte(json))
	if err != nil {
		t.Errorf("Error while trying to decode valid JSON payload: %s", err)
	}

	if len(payloads) != 1 {
		t.Errorf("Unexpected number of payloads in JSON: Should be 1, is %d", len(payloads))
	}

	payload := payloads[0]
	if payload.CP != "123456" {
		t.Errorf("CP not correct in payload. Should be 123456, is %s", payload.CP)
	}
	if payload.ID != "915cfea5570f824cc27112-a" {
		t.Errorf("ID not correct in payload. Should be 915cfea5570f824cc27112-a, is %s", payload.ID)
	}
	if payload.Geo.Country != "DE" {
		t.Errorf("Country not correct in payload. Should be DE, is %s", payload.Geo.Country)
	}
}

// TestMultiplePayloads tests if a correct number of payload objects are created.
func TestMultiplePayloads(t *testing.T) {
	dat, err := ioutil.ReadFile("tests/payload.json")
	payloads, err := CreateObjects([]byte(dat))
	if err != nil {
		t.Errorf("Error while trying to decode valid JSON payload: %s", err)
	}
	// test custom number of payloads in JSON file
	if len(payloads) != 42 {
		t.Errorf("Unexpected number of payloads in JSON: Should be 7, is %d", len(payloads))
	}

	for i := 0; i < len(payloads); i++ {
		if payloads[i].CP != "123456" {
			t.Errorf("CP not correct in payload. Should be 123456, is %s", payloads[i].CP)
		}
	}

	// TODO test other fields
}
<|endoftext|>


<commit_before>package pgtype

import (
	"database/sql/driver"
	"encoding/binary"
	"encoding/json"
	"fmt"
	"strconv"
	"time"

	"github.com/jackc/pgx/v5/internal/pgio"
)

type DateScanner interface {
	ScanDate(v Date) error
}

type DateValuer interface {
	DateValue() (Date, error)
}

type Date struct {
	Time             time.Time
	InfinityModifier InfinityModifier
	Valid            bool
}

func (d *Date) ScanDate(v Date) error {
	*d = v
	return nil
}

func (d Date) DateValue() (Date, error) {
	return d, nil
}

const (
	negativeInfinityDayOffset = -2147483648
	infinityDayOffset         = 2147483647
)

// Scan implements the database/sql Scanner interface.
func (dst *Date) Scan(src any) error {
	if src == nil {
		*dst = Date{}
		return nil
	}

	switch src := src.(type) {
	case string:
		return scanPlanTextAnyToDateScanner{}.Scan([]byte(src), dst)
	case time.Time:
		*dst = Date{Time: src, Valid: true}
		return nil
	}

	return fmt.Errorf("cannot scan %T", src)
}

// Value implements the database/sql/driver Valuer interface.
func (src Date) Value() (driver.Value, error) {
	if !src.Valid {
		return nil, nil
	}

	if src.InfinityModifier != Finite {
		return src.InfinityModifier.String(), nil
	}
	return src.Time, nil
}

func (src Date) MarshalJSON() ([]byte, error) {
	if !src.Valid {
		return []byte("null"), nil
	}

	var s string

	switch src.InfinityModifier {
	case Finite:
		s = src.Time.Format("2006-01-02")
	case Infinity:
		s = "infinity"
	case NegativeInfinity:
		s = "-infinity"
	}

	return json.Marshal(s)
}

func (dst *Date) UnmarshalJSON(b []byte) error {
	var s *string
	err := json.Unmarshal(b, &s)
	if err != nil {
		return err
	}

	if s == nil {
		*dst = Date{}
		return nil
	}

	switch *s {
	case "infinity":
		*dst = Date{Valid: true, InfinityModifier: Infinity}
	case "-infinity":
		*dst = Date{Valid: true, InfinityModifier: -Infinity}
	default:
		t, err := time.ParseInLocation("2006-01-02", *s, time.UTC)
		if err != nil {
			return err
		}

		*dst = Date{Time: t, Valid: true}
	}

	return nil
}

type DateCodec struct{}

func (DateCodec) FormatSupported(format int16) bool {
	return format == TextFormatCode || format == BinaryFormatCode
}

func (DateCodec) PreferredFormat() int16 {
	return BinaryFormatCode
}

func (DateCodec) PlanEncode(m *Map, oid uint32, format int16, value any) EncodePlan {
	if _, ok := value.(DateValuer); !ok {
		return nil
	}

	switch format {
	case BinaryFormatCode:
		return encodePlanDateCodecBinary{}
	case TextFormatCode:
		return encodePlanDateCodecText{}
	}

	return nil
}

type encodePlanDateCodecBinary struct{}

func (encodePlanDateCodecBinary) Encode(value any, buf []byte) (newBuf []byte, err error) {
	date, err := value.(DateValuer).DateValue()
	if err != nil {
		return nil, err
	}

	if !date.Valid {
		return nil, nil
	}

	var daysSinceDateEpoch int32
	switch date.InfinityModifier {
	case Finite:
		tUnix := time.Date(date.Time.Year(), date.Time.Month(), date.Time.Day(), 0, 0, 0, 0, time.UTC).Unix()
		dateEpoch := time.Date(2000, 1, 1, 0, 0, 0, 0, time.UTC).Unix()

		secSinceDateEpoch := tUnix - dateEpoch
		daysSinceDateEpoch = int32(secSinceDateEpoch / 86400)
	case Infinity:
		daysSinceDateEpoch = infinityDayOffset
	case NegativeInfinity:
		daysSinceDateEpoch = negativeInfinityDayOffset
	}

	return pgio.AppendInt32(buf, daysSinceDateEpoch), nil
}

type encodePlanDateCodecText struct{}

func (encodePlanDateCodecText) Encode(value any, buf []byte) (newBuf []byte, err error) {
	date, err := value.(DateValuer).DateValue()
	if err != nil {
		return nil, err
	}

	if !date.Valid {
		return nil, nil
	}

	switch date.InfinityModifier {
	case Finite:
		// Year 0000 is 1 BC
		bc := false
		year := date.Time.Year()
		if year <= 0 {
			year = -year + 1
			bc = true
		}

		buf = strconv.AppendInt(buf, int64(year), 10)
		buf = append(buf, '-')
		buf = strconv.AppendInt(buf, int64(date.Time.Month()), 10)
		buf = append(buf, '-')
		buf = strconv.AppendInt(buf, int64(date.Time.Day()), 10)

		if bc {
			buf = append(buf, " BC"...)
		}
	case Infinity:
		buf = append(buf, "infinity"...)
	case NegativeInfinity:
		buf = append(buf, "-infinity"...)
	}

	return buf, nil
}

func (DateCodec) PlanScan(m *Map, oid uint32, format int16, target any) ScanPlan {

	switch format {
	case BinaryFormatCode:
		switch target.(type) {
		case DateScanner:
			return scanPlanBinaryDateToDateScanner{}
		}
	case TextFormatCode:
		switch target.(type) {
		case DateScanner:
			return scanPlanTextAnyToDateScanner{}
		}
	}

	return nil
}

type scanPlanBinaryDateToDateScanner struct{}

func (scanPlanBinaryDateToDateScanner) Scan(src []byte, dst any) error {
	scanner := (dst).(DateScanner)

	if src == nil {
		return scanner.ScanDate(Date{})
	}

	if len(src) != 4 {
		return fmt.Errorf("invalid length for date: %v", len(src))
	}

	dayOffset := int32(binary.BigEndian.Uint32(src))

	switch dayOffset {
	case infinityDayOffset:
		return scanner.ScanDate(Date{InfinityModifier: Infinity, Valid: true})
	case negativeInfinityDayOffset:
		return scanner.ScanDate(Date{InfinityModifier: -Infinity, Valid: true})
	default:
		t := time.Date(2000, 1, int(1+dayOffset), 0, 0, 0, 0, time.UTC)
		return scanner.ScanDate(Date{Time: t, Valid: true})
	}
}

type scanPlanTextAnyToDateScanner struct{}

func (scanPlanTextAnyToDateScanner) Scan(src []byte, dst any) error {
	scanner := (dst).(DateScanner)

	if src == nil {
		return scanner.ScanDate(Date{})
	}

	sbuf := string(src)
	switch sbuf {
	case "infinity":
		return scanner.ScanDate(Date{InfinityModifier: Infinity, Valid: true})
	case "-infinity":
		return scanner.ScanDate(Date{InfinityModifier: -Infinity, Valid: true})
	default:
		if len(sbuf) >= 10 {
			year, err := strconv.ParseInt(sbuf[0:4], 10, 32)
			if err != nil {
				return fmt.Errorf("cannot parse year: %v", err)
			}
			month, err := strconv.ParseInt(sbuf[5:7], 10, 32)
			if err != nil {
				return fmt.Errorf("cannot parse month: %v", err)
			}
			day, err := strconv.ParseInt(sbuf[8:10], 10, 32)
			if err != nil {
				return fmt.Errorf("cannot parse day: %v", err)
			}

			if len(sbuf) == 13 && sbuf[11:] == "BC" {
				year = -year + 1
			}

			t := time.Date(int(year), time.Month(month), int(day), 0, 0, 0, 0, time.UTC)
			return scanner.ScanDate(Date{Time: t, Valid: true})
		} else {
			return fmt.Errorf("date too short")
		}
	}
}

func (c DateCodec) DecodeDatabaseSQLValue(m *Map, oid uint32, format int16, src []byte) (driver.Value, error) {
	return codecDecodeToTextFormat(c, m, oid, format, src)
}

func (c DateCodec) DecodeValue(m *Map, oid uint32, format int16, src []byte) (any, error) {
	if src == nil {
		return nil, nil
	}

	var date Date
	err := codecScan(c, m, oid, format, src, &date)
	if err != nil {
		return nil, err
	}

	if date.Valid {
		switch date.InfinityModifier {
		case Finite:
			return date.Time, nil
		case Infinity:
			return "infinity", nil
		case NegativeInfinity:
			return "-infinity", nil
		}
	}

	return nil, nil
}
<commit_msg>Date text encoding includes leading zero for month and day<commit_after>package pgtype

import (
	"database/sql/driver"
	"encoding/binary"
	"encoding/json"
	"fmt"
	"strconv"
	"time"

	"github.com/jackc/pgx/v5/internal/pgio"
)

type DateScanner interface {
	ScanDate(v Date) error
}

type DateValuer interface {
	DateValue() (Date, error)
}

type Date struct {
	Time             time.Time
	InfinityModifier InfinityModifier
	Valid            bool
}

func (d *Date) ScanDate(v Date) error {
	*d = v
	return nil
}

func (d Date) DateValue() (Date, error) {
	return d, nil
}

const (
	negativeInfinityDayOffset = -2147483648
	infinityDayOffset         = 2147483647
)

// Scan implements the database/sql Scanner interface.
func (dst *Date) Scan(src any) error {
	if src == nil {
		*dst = Date{}
		return nil
	}

	switch src := src.(type) {
	case string:
		return scanPlanTextAnyToDateScanner{}.Scan([]byte(src), dst)
	case time.Time:
		*dst = Date{Time: src, Valid: true}
		return nil
	}

	return fmt.Errorf("cannot scan %T", src)
}

// Value implements the database/sql/driver Valuer interface.
func (src Date) Value() (driver.Value, error) {
	if !src.Valid {
		return nil, nil
	}

	if src.InfinityModifier != Finite {
		return src.InfinityModifier.String(), nil
	}
	return src.Time, nil
}

func (src Date) MarshalJSON() ([]byte, error) {
	if !src.Valid {
		return []byte("null"), nil
	}

	var s string

	switch src.InfinityModifier {
	case Finite:
		s = src.Time.Format("2006-01-02")
	case Infinity:
		s = "infinity"
	case NegativeInfinity:
		s = "-infinity"
	}

	return json.Marshal(s)
}

func (dst *Date) UnmarshalJSON(b []byte) error {
	var s *string
	err := json.Unmarshal(b, &s)
	if err != nil {
		return err
	}

	if s == nil {
		*dst = Date{}
		return nil
	}

	switch *s {
	case "infinity":
		*dst = Date{Valid: true, InfinityModifier: Infinity}
	case "-infinity":
		*dst = Date{Valid: true, InfinityModifier: -Infinity}
	default:
		t, err := time.ParseInLocation("2006-01-02", *s, time.UTC)
		if err != nil {
			return err
		}

		*dst = Date{Time: t, Valid: true}
	}

	return nil
}

type DateCodec struct{}

func (DateCodec) FormatSupported(format int16) bool {
	return format == TextFormatCode || format == BinaryFormatCode
}

func (DateCodec) PreferredFormat() int16 {
	return BinaryFormatCode
}

func (DateCodec) PlanEncode(m *Map, oid uint32, format int16, value any) EncodePlan {
	if _, ok := value.(DateValuer); !ok {
		return nil
	}

	switch format {
	case BinaryFormatCode:
		return encodePlanDateCodecBinary{}
	case TextFormatCode:
		return encodePlanDateCodecText{}
	}

	return nil
}

type encodePlanDateCodecBinary struct{}

func (encodePlanDateCodecBinary) Encode(value any, buf []byte) (newBuf []byte, err error) {
	date, err := value.(DateValuer).DateValue()
	if err != nil {
		return nil, err
	}

	if !date.Valid {
		return nil, nil
	}

	var daysSinceDateEpoch int32
	switch date.InfinityModifier {
	case Finite:
		tUnix := time.Date(date.Time.Year(), date.Time.Month(), date.Time.Day(), 0, 0, 0, 0, time.UTC).Unix()
		dateEpoch := time.Date(2000, 1, 1, 0, 0, 0, 0, time.UTC).Unix()

		secSinceDateEpoch := tUnix - dateEpoch
		daysSinceDateEpoch = int32(secSinceDateEpoch / 86400)
	case Infinity:
		daysSinceDateEpoch = infinityDayOffset
	case NegativeInfinity:
		daysSinceDateEpoch = negativeInfinityDayOffset
	}

	return pgio.AppendInt32(buf, daysSinceDateEpoch), nil
}

type encodePlanDateCodecText struct{}

func (encodePlanDateCodecText) Encode(value any, buf []byte) (newBuf []byte, err error) {
	date, err := value.(DateValuer).DateValue()
	if err != nil {
		return nil, err
	}

	if !date.Valid {
		return nil, nil
	}

	switch date.InfinityModifier {
	case Finite:
		// Year 0000 is 1 BC
		bc := false
		year := date.Time.Year()
		if year <= 0 {
			year = -year + 1
			bc = true
		}

		buf = strconv.AppendInt(buf, int64(year), 10)
		buf = append(buf, '-')
		if date.Time.Month() < 10 {
			buf = append(buf, '0')
		}
		buf = strconv.AppendInt(buf, int64(date.Time.Month()), 10)
		buf = append(buf, '-')
		if date.Time.Day() < 10 {
			buf = append(buf, '0')
		}
		buf = strconv.AppendInt(buf, int64(date.Time.Day()), 10)

		if bc {
			buf = append(buf, " BC"...)
		}
	case Infinity:
		buf = append(buf, "infinity"...)
	case NegativeInfinity:
		buf = append(buf, "-infinity"...)
	}

	return buf, nil
}

func (DateCodec) PlanScan(m *Map, oid uint32, format int16, target any) ScanPlan {

	switch format {
	case BinaryFormatCode:
		switch target.(type) {
		case DateScanner:
			return scanPlanBinaryDateToDateScanner{}
		}
	case TextFormatCode:
		switch target.(type) {
		case DateScanner:
			return scanPlanTextAnyToDateScanner{}
		}
	}

	return nil
}

type scanPlanBinaryDateToDateScanner struct{}

func (scanPlanBinaryDateToDateScanner) Scan(src []byte, dst any) error {
	scanner := (dst).(DateScanner)

	if src == nil {
		return scanner.ScanDate(Date{})
	}

	if len(src) != 4 {
		return fmt.Errorf("invalid length for date: %v", len(src))
	}

	dayOffset := int32(binary.BigEndian.Uint32(src))

	switch dayOffset {
	case infinityDayOffset:
		return scanner.ScanDate(Date{InfinityModifier: Infinity, Valid: true})
	case negativeInfinityDayOffset:
		return scanner.ScanDate(Date{InfinityModifier: -Infinity, Valid: true})
	default:
		t := time.Date(2000, 1, int(1+dayOffset), 0, 0, 0, 0, time.UTC)
		return scanner.ScanDate(Date{Time: t, Valid: true})
	}
}

type scanPlanTextAnyToDateScanner struct{}

func (scanPlanTextAnyToDateScanner) Scan(src []byte, dst any) error {
	scanner := (dst).(DateScanner)

	if src == nil {
		return scanner.ScanDate(Date{})
	}

	sbuf := string(src)
	switch sbuf {
	case "infinity":
		return scanner.ScanDate(Date{InfinityModifier: Infinity, Valid: true})
	case "-infinity":
		return scanner.ScanDate(Date{InfinityModifier: -Infinity, Valid: true})
	default:
		if len(sbuf) >= 10 {
			year, err := strconv.ParseInt(sbuf[0:4], 10, 32)
			if err != nil {
				return fmt.Errorf("cannot parse year: %v", err)
			}
			month, err := strconv.ParseInt(sbuf[5:7], 10, 32)
			if err != nil {
				return fmt.Errorf("cannot parse month: %v", err)
			}
			day, err := strconv.ParseInt(sbuf[8:10], 10, 32)
			if err != nil {
				return fmt.Errorf("cannot parse day: %v", err)
			}

			if len(sbuf) == 13 && sbuf[11:] == "BC" {
				year = -year + 1
			}

			t := time.Date(int(year), time.Month(month), int(day), 0, 0, 0, 0, time.UTC)
			return scanner.ScanDate(Date{Time: t, Valid: true})
		} else {
			return fmt.Errorf("date too short")
		}
	}
}

func (c DateCodec) DecodeDatabaseSQLValue(m *Map, oid uint32, format int16, src []byte) (driver.Value, error) {
	return codecDecodeToTextFormat(c, m, oid, format, src)
}

func (c DateCodec) DecodeValue(m *Map, oid uint32, format int16, src []byte) (any, error) {
	if src == nil {
		return nil, nil
	}

	var date Date
	err := codecScan(c, m, oid, format, src, &date)
	if err != nil {
		return nil, err
	}

	if date.Valid {
		switch date.InfinityModifier {
		case Finite:
			return date.Time, nil
		case Infinity:
			return "infinity", nil
		case NegativeInfinity:
			return "-infinity", nil
		}
	}

	return nil, nil
}
<|endoftext|>


<commit_before>package api

import (
	"encoding/json"
	"os"
	"path/filepath"
	"regexp"

	"github.com/ClusterHQ/dvol/pkg/datalayer"
)

/*
User
 | "dvol checkout -b foo"
 v
CLI
 | "what is the current active volume?", "oh, it's 'bar'"
 | "create branch 'foo' from active volume 'bar'"
 v
internal API
 | "create variant from snapshot at tip of volume bar"
 v
DataLayer

*/

/*

A dvol volume is:

* a forest of snapshots (aka commits, immutable snapshots of the volume at a certain point in time), with inherited branch labels
* a set of writeable working copies (writeable paths which get mounted into the container), one per branch

*/

const MAX_NAME_LENGTH int = 40

func ValidName(name string) bool {
	var validNameRegex = regexp.MustCompile(`^[a-zA-Z]+[a-zA-Z0-9-]*$`)
	return validNameRegex.MatchString(name) && len(name) <= MAX_NAME_LENGTH
}

type DvolAPI struct {
	basePath string
	dl       *datalayer.DataLayer
}

func NewDvolAPI(basePath string) *DvolAPI {
	dl := &datalayer.DataLayer{BasePath: basePath}
	return &DvolAPI{basePath, dl}
}

func (dvol *DvolAPI) CreateVolume(volumeName string) error {
	err := dvol.dl.CreateVolume(volumeName)
	if err != nil {
		return err
	}
	return dvol.setActiveVolume(volumeName)
}

func (dvol *DvolAPI) RemoveVolume(volumeName string) error {
	return dvol.dl.RemoveVolume(volumeName)
}

func (dvol *DvolAPI) setActiveVolume(volumeName string) error {
	currentVolumeJsonPath := filepath.FromSlash(dvol.basePath + "/current_volume.json")
	currentVolumeContent := map[string]string{
		"current_volume": volumeName,
	}
	// Create or update this file
	file, err := os.Create(currentVolumeJsonPath)
	if err != nil {
		return err
	}
	defer file.Close()
	encoder := json.NewEncoder(file)
	encoder.Encode(currentVolumeContent)
	return nil
}

func (dvol *DvolAPI) CreateVariant(volumeName, variantName string) error {
	return dvol.dl.CreateVariant(volumeName, variantName)
}

func (dvol *DvolAPI) setActiveVariant(volumeName, variantName string) error {
	return nil
}

func (dvol *DvolAPI) CheckoutBranch(branchName string) error {
	return nil
}

func (dvol *DvolAPI) ActiveVolume() (string, error) {
	currentVolumeJsonPath := filepath.FromSlash(dvol.basePath + "/current_volume.json")
	file, err := os.Open(currentVolumeJsonPath)
	if err != nil {
		return "", err
	}
	defer file.Close()
	decoder := json.NewDecoder(file)
	var store map[string]interface{}
	err = decoder.Decode(&store)
	if err != nil {
		return "", err
	}
	return store["current_volume"].(string), nil
}

func (dvol *DvolAPI) VolumeExists(volumeName string) bool {
	volumePath := filepath.FromSlash(dvol.basePath + "/" + volumeName)
	_, err := os.Stat(volumePath)
	return err == nil
}

func (dvol *DvolAPI) SwitchVolume(volumeName string) error {
	return dvol.setActiveVolume(volumeName)
}
<commit_msg>Comment about swappable datalayer implementations<commit_after>package api

import (
	"encoding/json"
	"os"
	"path/filepath"
	"regexp"

	"github.com/ClusterHQ/dvol/pkg/datalayer"
)

/*
User
 | "dvol checkout -b foo"
 v
CLI
 | "what is the current active volume?", "oh, it's 'bar'"
 | "create branch 'foo' from active volume 'bar'"
 v
internal API
 | "create variant from snapshot at tip of volume bar"
 v
DataLayer (swappable for another implementation)

*/

/*

A dvol volume is:

* a forest of snapshots (aka commits, immutable snapshots of the volume at a certain point in time), with inherited branch labels
* a set of writeable working copies (writeable paths which get mounted into the container), one per branch

*/

const MAX_NAME_LENGTH int = 40

func ValidName(name string) bool {
	var validNameRegex = regexp.MustCompile(`^[a-zA-Z]+[a-zA-Z0-9-]*$`)
	return validNameRegex.MatchString(name) && len(name) <= MAX_NAME_LENGTH
}

type DvolAPI struct {
	basePath string
	dl       *datalayer.DataLayer
}

func NewDvolAPI(basePath string) *DvolAPI {
	dl := &datalayer.DataLayer{BasePath: basePath}
	return &DvolAPI{basePath, dl}
}

func (dvol *DvolAPI) CreateVolume(volumeName string) error {
	err := dvol.dl.CreateVolume(volumeName)
	if err != nil {
		return err
	}
	return dvol.setActiveVolume(volumeName)
}

func (dvol *DvolAPI) RemoveVolume(volumeName string) error {
	return dvol.dl.RemoveVolume(volumeName)
}

func (dvol *DvolAPI) setActiveVolume(volumeName string) error {
	currentVolumeJsonPath := filepath.FromSlash(dvol.basePath + "/current_volume.json")
	currentVolumeContent := map[string]string{
		"current_volume": volumeName,
	}
	// Create or update this file
	file, err := os.Create(currentVolumeJsonPath)
	if err != nil {
		return err
	}
	defer file.Close()
	encoder := json.NewEncoder(file)
	encoder.Encode(currentVolumeContent)
	return nil
}

func (dvol *DvolAPI) CreateVariant(volumeName, variantName string) error {
	return dvol.dl.CreateVariant(volumeName, variantName)
}

func (dvol *DvolAPI) setActiveVariant(volumeName, variantName string) error {
	return nil
}

func (dvol *DvolAPI) CheckoutBranch(branchName string) error {
	return nil
}

func (dvol *DvolAPI) ActiveVolume() (string, error) {
	currentVolumeJsonPath := filepath.FromSlash(dvol.basePath + "/current_volume.json")
	file, err := os.Open(currentVolumeJsonPath)
	if err != nil {
		return "", err
	}
	defer file.Close()
	decoder := json.NewDecoder(file)
	var store map[string]interface{}
	err = decoder.Decode(&store)
	if err != nil {
		return "", err
	}
	return store["current_volume"].(string), nil
}

func (dvol *DvolAPI) VolumeExists(volumeName string) bool {
	volumePath := filepath.FromSlash(dvol.basePath + "/" + volumeName)
	_, err := os.Stat(volumePath)
	return err == nil
}

func (dvol *DvolAPI) SwitchVolume(volumeName string) error {
	return dvol.setActiveVolume(volumeName)
}
<|endoftext|>


<commit_before>/*
Copyright 2014 Google Inc. All rights reserved.

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 api

import (
	"errors"
	"fmt"
	"regexp"

	"github.com/GoogleCloudPlatform/kubernetes/pkg/api/meta"
	"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
)

var ErrNilObject = errors.New("Can't reference a nil object")

var versionFromSelfLink = regexp.MustCompile("/api/([^/]*)/")

// GetReference returns an ObjectReference which refers to the given
// object, or an error if the object doesn't follow the conventions
// that would allow this.
func GetReference(obj runtime.Object) (*ObjectReference, error) {
	if obj == nil {
		return nil, ErrNilObject
	}
	meta, err := meta.Accessor(obj)
	if err != nil {
		return nil, err
	}
	_, kind, err := Scheme.ObjectVersionAndKind(obj)
	if err != nil {
		return nil, err
	}
	version := versionFromSelfLink.FindStringSubmatch(meta.SelfLink())
	if len(version) < 2 {
		return nil, fmt.Errorf("unexpected self link format: %v", meta.SelfLink())
	}
	return &ObjectReference{
		Kind:            kind,
		APIVersion:      version[1],
		Name:            meta.Name(),
		Namespace:       meta.Namespace(),
		UID:             meta.UID(),
		ResourceVersion: meta.ResourceVersion(),
	}, nil
}
<commit_msg>Allow ObjectReferences to be passed to Eventf<commit_after>/*
Copyright 2014 Google Inc. All rights reserved.

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 api

import (
	"errors"
	"fmt"
	"regexp"

	"github.com/GoogleCloudPlatform/kubernetes/pkg/api/meta"
	"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
)

var ErrNilObject = errors.New("Can't reference a nil object")

var versionFromSelfLink = regexp.MustCompile("/api/([^/]*)/")

// GetReference returns an ObjectReference which refers to the given
// object, or an error if the object doesn't follow the conventions
// that would allow this.
func GetReference(obj runtime.Object) (*ObjectReference, error) {
	if obj == nil {
		return nil, ErrNilObject
	}
	if ref, ok := obj.(*ObjectReference); ok {
		// Don't make a reference to a reference.
		return ref, nil
	}
	meta, err := meta.Accessor(obj)
	if err != nil {
		return nil, err
	}
	_, kind, err := Scheme.ObjectVersionAndKind(obj)
	if err != nil {
		return nil, err
	}
	version := versionFromSelfLink.FindStringSubmatch(meta.SelfLink())
	if len(version) < 2 {
		return nil, fmt.Errorf("unexpected self link format: %v", meta.SelfLink())
	}
	return &ObjectReference{
		Kind:            kind,
		APIVersion:      version[1],
		Name:            meta.Name(),
		Namespace:       meta.Namespace(),
		UID:             meta.UID(),
		ResourceVersion: meta.ResourceVersion(),
	}, nil
}

// Allow clients to preemptively get a reference to an API object and pass it to places that
// intend only to get a reference to that object. This simplifies the event recording interface.
func (*ObjectReference) IsAnAPIObject() {}
<|endoftext|>


<commit_before>// Copyright 2016 The Gosl 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 plt

import (
	"github.com/cpmech/gosl/io"
)

// AutoScale rescales plot area
func AutoScale(P [][]float64) {
	if len(P) < 1 {
		return
	}
	xmin, ymin := P[0][0], P[0][1]
	xmax, ymax := xmin, ymin
	for _, p := range P {
		if p[0] < xmin {
			xmin = p[0]
		}
		if p[1] < ymin {
			ymin = p[1]
		}
		if p[0] > xmax {
			xmax = p[0]
		}
		if p[1] > ymax {
			ymax = p[1]
		}
	}
	io.Ff(&bufferPy, "plt.axis([%g, %g, %g, %g])\n", xmin, xmax, ymin, ymax)
}

// Arrow adds arrow to plot
//   styles:
//     Curve           -        None
//     CurveB          ->       head_length=0.4,head_width=0.2
//     BracketB        -[       widthB=1.0,lengthB=0.2,angleB=None
//     CurveFilledB    -|>      head_length=0.4,head_width=0.2
//     CurveA          <-       head_length=0.4,head_width=0.2
//     CurveAB         <->      head_length=0.4,head_width=0.2
//     CurveFilledA    <|-      head_length=0.4,head_width=0.2
//     CurveFilledAB   <|-|>    head_length=0.4,head_width=0.2
//     BracketA        ]-       widthA=1.0,lengthA=0.2,angleA=None
//     BracketAB       ]-[      widthA=1.0,lengthA=0.2,angleA=None,widthB=1.0,lengthB=0.2,angleB=None
//     Fancy           fancy    head_length=0.4,head_width=0.4,tail_width=0.4
//     Simple          simple   head_length=0.5,head_width=0.5,tail_width=0.2
//     Wedge           wedge    tail_width=0.3,shrink_factor=0.5
//     BarAB           |-|      widthA=1.0,angleA=None,widthB=1.0,angleB=None
func Arrow(xi, yi, xf, yf float64, args *A) {
	style := "simple"
	scale := 20.0
	if args.Style != "" {
		style = args.Style
	}
	if args.Scale > 0 {
		scale = args.Scale
	}
	uid := genUID()
	io.Ff(&bufferPy, "pc%d = pat.FancyArrowPatch((%g,%g),(%g,%g),shrinkA=0,shrinkB=0,path_effects=[pff.Stroke(joinstyle='miter')],arrowstyle='%s',mutation_scale=%g", uid, xi, yi, xf, yf, style, scale)
	updateBufferAndClose(&bufferPy, args, false, false)
	io.Ff(&bufferPy, "plt.gca().add_patch(pc%d)\n", uid)
}

// Circle adds circle to plot
func Circle(xc, yc, r float64, args *A) {
	uid := genUID()
	io.Ff(&bufferPy, "pc%d = pat.Circle((%g,%g), %g", uid, xc, yc, r)
	updateBufferAndClose(&bufferPy, args, false, false)
	io.Ff(&bufferPy, "plt.gca().add_patch(pc%d)\n", uid)
}

// Arc adds arc to plot
//  minAlpha and maxAlpha are in degrees
func Arc(xc, yc, r, minAlpha, maxAlpha float64, args *A) {
	uid := genUID()
	r2 := 2.0 * r
	io.Ff(&bufferPy, "pc%d = pat.Arc((%g,%g),%g,%g,angle=0,theta1=%g,theta2=%g", uid, xc, yc, r2, r2, minAlpha, maxAlpha)
	updateBufferAndClose(&bufferPy, args, false, false)
	io.Ff(&bufferPy, "plt.gca().add_patch(pc%d)\n", uid)
}

// Polyline draws a polyline. P[npts][2]
func Polyline(P [][]float64, args *A) {
	if len(P) < 1 {
		return
	}
	uid := genUID()
	io.Ff(&bufferPy, "dat%d = [[pth.Path.MOVETO, [%g, %g]]", uid, P[0][0], P[0][1])
	for _, p := range P {
		io.Ff(&bufferPy, ", [pth.Path.LINETO, [%g, %g]]", p[0], p[1])
	}
	closed := true
	if args != nil {
		closed = args.Closed
	}
	if closed {
		io.Ff(&bufferPy, ", [pth.Path.CLOSEPOLY, [0, 0]]")
	}
	io.Ff(&bufferPy, "]\n")
	io.Ff(&bufferPy, "commands%d, vertices%d = zip(*dat%d)\n", uid, uid, uid)
	io.Ff(&bufferPy, "ph%d = pth.Path(vertices%d, commands%d)\n", uid, uid, uid)
	io.Ff(&bufferPy, "pc%d = pat.PathPatch(ph%d", uid, uid)
	updateBufferAndClose(&bufferPy, args, false, false)
	io.Ff(&bufferPy, "plt.gca().add_patch(pc%d)\n", uid)
}

// Polygon3d draws a polygon in 3D. P[npts][3]
func Polygon3d(P [][]float64, args *A) {
	if len(P) < 1 {
		return
	}
	if args == nil {
		args = &A{Fc: "#5294ed", Ec: "#ffec4f"}
	}
	createAxes3d()
	uid := genUID()
	io.Ff(&bufferPy, "verts%d = [[", uid)
	for i, p := range P {
		if i > 0 {
			io.Ff(&bufferPy, ",")
		}
		io.Ff(&bufferPy, "(")
		for j, x := range p {
			if j > 0 {
				io.Ff(&bufferPy, ",")
			}
			io.Ff(&bufferPy, "%g", x)
		}
		io.Ff(&bufferPy, ")")
	}
	io.Ff(&bufferPy, "]]\n")
	io.Ff(&bufferPy, "poly%d = m3d.art3d.Poly3DCollection(verts%d", uid, uid)
	updateBufferAndClose(&bufferPy, args, false, false)
	io.Ff(&bufferPy, "plt.gca().add_collection3d(poly%d)\n", uid)
}

// Box draws box
//   NOTE: args.Wire and args.Ls are used to draw a wire around the edges of the box
func Box(xmin, xmax, ymin, ymax, zmin, zmax float64, args *A) {
	if args == nil {
		args = &A{Fc: "#5294ed", Ec: "#ffec4f", Lw: 3}
	}
	createAxes3d()
	uid := genUID()
	io.Ff(&bufferPy, "verts%d = [\n", uid)
	io.Ff(&bufferPy, "    [(%g,%g,%g),(%g,%g,%g),(%g,%g,%g),(%g,%g,%g)],\n", xmin, ymin, zmin, xmin, ymax, zmin, xmin, ymax, zmax, xmin, ymin, zmax)
	io.Ff(&bufferPy, "    [(%g,%g,%g),(%g,%g,%g),(%g,%g,%g),(%g,%g,%g)],\n", xmax, ymin, zmin, xmax, ymax, zmin, xmax, ymax, zmax, xmax, ymin, zmax)
	io.Ff(&bufferPy, "    [(%g,%g,%g),(%g,%g,%g),(%g,%g,%g),(%g,%g,%g)],\n", xmin, ymin, zmin, xmin, ymin, zmax, xmax, ymin, zmax, xmax, ymin, zmin)
	io.Ff(&bufferPy, "    [(%g,%g,%g),(%g,%g,%g),(%g,%g,%g),(%g,%g,%g)],\n", xmin, ymax, zmin, xmin, ymax, zmax, xmax, ymax, zmax, xmax, ymax, zmin)
	io.Ff(&bufferPy, "    [(%g,%g,%g),(%g,%g,%g),(%g,%g,%g),(%g,%g,%g)],\n", xmin, ymin, zmin, xmin, ymax, zmin, xmax, ymax, zmin, xmax, ymin, zmin)
	io.Ff(&bufferPy, "    [(%g,%g,%g),(%g,%g,%g),(%g,%g,%g),(%g,%g,%g)]\n", xmin, ymin, zmax, xmin, ymax, zmax, xmax, ymax, zmax, xmax, ymin, zmax)
	io.Ff(&bufferPy, "]\n")
	io.Ff(&bufferPy, "poly%d = m3d.art3d.Poly3DCollection(verts%d\n", uid, uid)
	updateBufferAndClose(&bufferPy, args, false, false)
	io.Ff(&bufferPy, "plt.gca().add_collection3d(poly%d)\n", uid)
	if args.Wire {
		ls := "--"
		if args.Ls != "" {
			ls = args.Ls
		}
		io.Ff(&bufferPy, "verts%d.append([(%g,%g,%g),(%g,%g,%g)])\n", uid, xmin, ymin, zmin, xmax, ymin, zmin)
		io.Ff(&bufferPy, "plt.gca().add_collection3d(m3d.art3d.Line3DCollection(verts%d, colors='k', linewidth=0.7, linestyles='%s'))\n", uid, ls)
	}
}
<commit_msg>Fix Arrow command in case args is nil<commit_after>// Copyright 2016 The Gosl 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 plt

import (
	"github.com/cpmech/gosl/io"
)

// AutoScale rescales plot area
func AutoScale(P [][]float64) {
	if len(P) < 1 {
		return
	}
	xmin, ymin := P[0][0], P[0][1]
	xmax, ymax := xmin, ymin
	for _, p := range P {
		if p[0] < xmin {
			xmin = p[0]
		}
		if p[1] < ymin {
			ymin = p[1]
		}
		if p[0] > xmax {
			xmax = p[0]
		}
		if p[1] > ymax {
			ymax = p[1]
		}
	}
	io.Ff(&bufferPy, "plt.axis([%g, %g, %g, %g])\n", xmin, xmax, ymin, ymax)
}

// Arrow adds arrow to plot
//   styles:
//     Curve           -        None
//     CurveB          ->       head_length=0.4,head_width=0.2
//     BracketB        -[       widthB=1.0,lengthB=0.2,angleB=None
//     CurveFilledB    -|>      head_length=0.4,head_width=0.2
//     CurveA          <-       head_length=0.4,head_width=0.2
//     CurveAB         <->      head_length=0.4,head_width=0.2
//     CurveFilledA    <|-      head_length=0.4,head_width=0.2
//     CurveFilledAB   <|-|>    head_length=0.4,head_width=0.2
//     BracketA        ]-       widthA=1.0,lengthA=0.2,angleA=None
//     BracketAB       ]-[      widthA=1.0,lengthA=0.2,angleA=None,widthB=1.0,lengthB=0.2,angleB=None
//     Fancy           fancy    head_length=0.4,head_width=0.4,tail_width=0.4
//     Simple          simple   head_length=0.5,head_width=0.5,tail_width=0.2
//     Wedge           wedge    tail_width=0.3,shrink_factor=0.5
//     BarAB           |-|      widthA=1.0,angleA=None,widthB=1.0,angleB=None
func Arrow(xi, yi, xf, yf float64, args *A) {
	if args == nil {
		args = &A{C: "orange"}
	}
	style := "simple"
	scale := 20.0
	if args.Style != "" {
		style = args.Style
	}
	if args.Scale > 0 {
		scale = args.Scale
	}
	uid := genUID()
	io.Ff(&bufferPy, "pc%d = pat.FancyArrowPatch((%g,%g),(%g,%g),shrinkA=0,shrinkB=0,path_effects=[pff.Stroke(joinstyle='miter')],arrowstyle='%s',mutation_scale=%g", uid, xi, yi, xf, yf, style, scale)
	updateBufferAndClose(&bufferPy, args, false, false)
	io.Ff(&bufferPy, "plt.gca().add_patch(pc%d)\n", uid)
}

// Circle adds circle to plot
func Circle(xc, yc, r float64, args *A) {
	uid := genUID()
	io.Ff(&bufferPy, "pc%d = pat.Circle((%g,%g), %g", uid, xc, yc, r)
	updateBufferAndClose(&bufferPy, args, false, false)
	io.Ff(&bufferPy, "plt.gca().add_patch(pc%d)\n", uid)
}

// Arc adds arc to plot
//  minAlpha and maxAlpha are in degrees
func Arc(xc, yc, r, minAlpha, maxAlpha float64, args *A) {
	uid := genUID()
	r2 := 2.0 * r
	io.Ff(&bufferPy, "pc%d = pat.Arc((%g,%g),%g,%g,angle=0,theta1=%g,theta2=%g", uid, xc, yc, r2, r2, minAlpha, maxAlpha)
	updateBufferAndClose(&bufferPy, args, false, false)
	io.Ff(&bufferPy, "plt.gca().add_patch(pc%d)\n", uid)
}

// Polyline draws a polyline. P[npts][2]
func Polyline(P [][]float64, args *A) {
	if len(P) < 1 {
		return
	}
	uid := genUID()
	io.Ff(&bufferPy, "dat%d = [[pth.Path.MOVETO, [%g, %g]]", uid, P[0][0], P[0][1])
	for _, p := range P {
		io.Ff(&bufferPy, ", [pth.Path.LINETO, [%g, %g]]", p[0], p[1])
	}
	closed := true
	if args != nil {
		closed = args.Closed
	}
	if closed {
		io.Ff(&bufferPy, ", [pth.Path.CLOSEPOLY, [0, 0]]")
	}
	io.Ff(&bufferPy, "]\n")
	io.Ff(&bufferPy, "commands%d, vertices%d = zip(*dat%d)\n", uid, uid, uid)
	io.Ff(&bufferPy, "ph%d = pth.Path(vertices%d, commands%d)\n", uid, uid, uid)
	io.Ff(&bufferPy, "pc%d = pat.PathPatch(ph%d", uid, uid)
	updateBufferAndClose(&bufferPy, args, false, false)
	io.Ff(&bufferPy, "plt.gca().add_patch(pc%d)\n", uid)
}

// Polygon3d draws a polygon in 3D. P[npts][3]
func Polygon3d(P [][]float64, args *A) {
	if len(P) < 1 {
		return
	}
	if args == nil {
		args = &A{Fc: "#5294ed", Ec: "#ffec4f"}
	}
	createAxes3d()
	uid := genUID()
	io.Ff(&bufferPy, "verts%d = [[", uid)
	for i, p := range P {
		if i > 0 {
			io.Ff(&bufferPy, ",")
		}
		io.Ff(&bufferPy, "(")
		for j, x := range p {
			if j > 0 {
				io.Ff(&bufferPy, ",")
			}
			io.Ff(&bufferPy, "%g", x)
		}
		io.Ff(&bufferPy, ")")
	}
	io.Ff(&bufferPy, "]]\n")
	io.Ff(&bufferPy, "poly%d = m3d.art3d.Poly3DCollection(verts%d", uid, uid)
	updateBufferAndClose(&bufferPy, args, false, false)
	io.Ff(&bufferPy, "plt.gca().add_collection3d(poly%d)\n", uid)
}

// Box draws box
//   NOTE: args.Wire and args.Ls are used to draw a wire around the edges of the box
func Box(xmin, xmax, ymin, ymax, zmin, zmax float64, args *A) {
	if args == nil {
		args = &A{Fc: "#5294ed", Ec: "#ffec4f", Lw: 3}
	}
	createAxes3d()
	uid := genUID()
	io.Ff(&bufferPy, "verts%d = [\n", uid)
	io.Ff(&bufferPy, "    [(%g,%g,%g),(%g,%g,%g),(%g,%g,%g),(%g,%g,%g)],\n", xmin, ymin, zmin, xmin, ymax, zmin, xmin, ymax, zmax, xmin, ymin, zmax)
	io.Ff(&bufferPy, "    [(%g,%g,%g),(%g,%g,%g),(%g,%g,%g),(%g,%g,%g)],\n", xmax, ymin, zmin, xmax, ymax, zmin, xmax, ymax, zmax, xmax, ymin, zmax)
	io.Ff(&bufferPy, "    [(%g,%g,%g),(%g,%g,%g),(%g,%g,%g),(%g,%g,%g)],\n", xmin, ymin, zmin, xmin, ymin, zmax, xmax, ymin, zmax, xmax, ymin, zmin)
	io.Ff(&bufferPy, "    [(%g,%g,%g),(%g,%g,%g),(%g,%g,%g),(%g,%g,%g)],\n", xmin, ymax, zmin, xmin, ymax, zmax, xmax, ymax, zmax, xmax, ymax, zmin)
	io.Ff(&bufferPy, "    [(%g,%g,%g),(%g,%g,%g),(%g,%g,%g),(%g,%g,%g)],\n", xmin, ymin, zmin, xmin, ymax, zmin, xmax, ymax, zmin, xmax, ymin, zmin)
	io.Ff(&bufferPy, "    [(%g,%g,%g),(%g,%g,%g),(%g,%g,%g),(%g,%g,%g)]\n", xmin, ymin, zmax, xmin, ymax, zmax, xmax, ymax, zmax, xmax, ymin, zmax)
	io.Ff(&bufferPy, "]\n")
	io.Ff(&bufferPy, "poly%d = m3d.art3d.Poly3DCollection(verts%d\n", uid, uid)
	updateBufferAndClose(&bufferPy, args, false, false)
	io.Ff(&bufferPy, "plt.gca().add_collection3d(poly%d)\n", uid)
	if args.Wire {
		ls := "--"
		if args.Ls != "" {
			ls = args.Ls
		}
		io.Ff(&bufferPy, "verts%d.append([(%g,%g,%g),(%g,%g,%g)])\n", uid, xmin, ymin, zmin, xmax, ymin, zmin)
		io.Ff(&bufferPy, "plt.gca().add_collection3d(m3d.art3d.Line3DCollection(verts%d, colors='k', linewidth=0.7, linestyles='%s'))\n", uid, ls)
	}
}
<|endoftext|>


<commit_before>package main

import (
	"bufio"
	"fmt"
	"net/http"
)

// synthesizeResponse calls middleware to populate response data, nothing gets pass proxy
func synthesizeResponse(req *http.Request, middleware string) *http.Response {

	b := bufio.NewScanner(req.Body)

	bodyStr := b.Text()

	request := requestDetails{
		Path:        req.URL.Path,
		Method:      req.Method,
		Destination: req.Host,
		Query:       req.URL.RawQuery,
		Body:        bodyStr,
		RemoteAddr:  req.RemoteAddr,
		Headers:     req.Header,
	}
	payload := Payload{Request: request}

	c := NewConstructor(req, payload)

	err := c.ApplyMiddleware(middleware)

	if err != nil {
		var errorPayload Payload
		errorPayload.Response.Status = 503
		errorPayload.Response.Body = fmt.Sprintf("Middleware error: %s", err.Error())
		c.payload = errorPayload
	}

	response := c.reconstructResponse()
	return response

}
<commit_msg>handle case when middleware not provided<commit_after>package main

import (
	"bufio"
	"fmt"
	"net/http"
)

// synthesizeResponse calls middleware to populate response data, nothing gets pass proxy
func synthesizeResponse(req *http.Request, middleware string) *http.Response {

	b := bufio.NewScanner(req.Body)

	bodyStr := b.Text()

	request := requestDetails{
		Path:        req.URL.Path,
		Method:      req.Method,
		Destination: req.Host,
		Query:       req.URL.RawQuery,
		Body:        bodyStr,
		RemoteAddr:  req.RemoteAddr,
		Headers:     req.Header,
	}
	payload := Payload{Request: request}

	c := NewConstructor(req, payload)

	if middleware != "" {
		err := c.ApplyMiddleware(middleware)
		if err != nil {
			var errorPayload Payload
			errorPayload.Response.Status = 503
			errorPayload.Response.Body = fmt.Sprintf("Middleware error: %s", err.Error())
			c.payload = errorPayload
		}
	} else {
		c.payload.Response.Body = "Precondition failed: middleware not provided."
		c.payload.Response.Status = 428
	}

	response := c.reconstructResponse()
	return response

}
<|endoftext|>


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

package sqlgen

import (
	"fmt"
	"reflect"
	"strings"
)

func Select(obj interface{}, args...[]string) string {
	t := reflect.TypeOf(obj).Elem()
	var sql string

	if len(args) != 0 {
		sql = fmt.Sprintf("select %s from %s", strings.Join(args[0], ", "), t.Name())
	} else {
		fieldNames := fieldNames(t)
		sql = fmt.Sprintf("select %s from %s", strings.Join(fieldNames, ", "), t.Name())
	}

	return strings.ToLower(sql)
}

func Insert(obj interface{}) string {
	t := reflect.TypeOf(obj).Elem()
	fieldNames := fieldNames(t)

	qm := make([]string, len(fieldNames))
	for i := 0; i < len(qm); i++ {
		qm[i] = "?"
	}

	sql := fmt.Sprintf("insert into %s (%s) values (%s)", t.Name(), strings.Join(fieldNames, ", "), strings.Join(qm, ", "))
	return strings.ToLower(sql)
}

func Delete(obj interface{}, filters []string) string {
	t := reflect.TypeOf(obj).Elem()

	filter_array := preparedFields(filters)
	filter_sql := strings.Join(filter_array, " and ")

	sql := fmt.Sprintf("delete from %s where ", t.Name())
	sql = strings.ToLower(sql)
	sql = sql + filter_sql
	return sql
}

// obj is the struct to be updated in the database
// uFields are the fields that are gonna be update
// fFields are the fields that are gonna be used as filter
// to the where clause
func Update(obj interface{}, uFields, fFields []string) string {
	t := reflect.TypeOf(obj).Elem()

	fieldsAndValues := preparedFields(uFields)
	filters := preparedFields(fFields)

	sql := fmt.Sprintf("update %s set %s where %s", strings.ToLower(t.Name()), strings.Join(fieldsAndValues, ", "), strings.Join(filters, " and "))

	return sql
}

// Receives a slice of fields an returns a slice with fields in the
// form of field=? that represents a placeholder to be replace for a value
func preparedFields(fields []string) []string {
	preparedFields := make([]string, len(fields))

	for i, v := range fields {
		preparedFields[i] = fmt.Sprintf(`%s=?`, strings.ToLower(v))
	}

	return preparedFields
}

func fieldNames(t reflect.Type) []string {
	fieldNames := make([]string, t.NumField())

	for i := 0; i < t.NumField(); i++ {
		fieldNames[i] = t.Field(i).Name
	}

	return fieldNames
}
<commit_msg>sqlgen: formatting code (gofmt)<commit_after>// Copyright 2012 Cobrateam members. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package sqlgen

import (
	"fmt"
	"reflect"
	"strings"
)

func Select(obj interface{}, args ...[]string) string {
	t := reflect.TypeOf(obj).Elem()
	var sql string

	if len(args) != 0 {
		sql = fmt.Sprintf("select %s from %s", strings.Join(args[0], ", "), t.Name())
	} else {
		fieldNames := fieldNames(t)
		sql = fmt.Sprintf("select %s from %s", strings.Join(fieldNames, ", "), t.Name())
	}

	return strings.ToLower(sql)
}

func Insert(obj interface{}) string {
	t := reflect.TypeOf(obj).Elem()
	fieldNames := fieldNames(t)

	qm := make([]string, len(fieldNames))
	for i := 0; i < len(qm); i++ {
		qm[i] = "?"
	}

	sql := fmt.Sprintf("insert into %s (%s) values (%s)", t.Name(), strings.Join(fieldNames, ", "), strings.Join(qm, ", "))
	return strings.ToLower(sql)
}

func Delete(obj interface{}, filters []string) string {
	t := reflect.TypeOf(obj).Elem()

	filter_array := preparedFields(filters)
	filter_sql := strings.Join(filter_array, " and ")

	sql := fmt.Sprintf("delete from %s where ", t.Name())
	sql = strings.ToLower(sql)
	sql = sql + filter_sql
	return sql
}

// obj is the struct to be updated in the database
// uFields are the fields that are gonna be update
// fFields are the fields that are gonna be used as filter
// to the where clause
func Update(obj interface{}, uFields, fFields []string) string {
	t := reflect.TypeOf(obj).Elem()

	fieldsAndValues := preparedFields(uFields)
	filters := preparedFields(fFields)

	sql := fmt.Sprintf("update %s set %s where %s", strings.ToLower(t.Name()), strings.Join(fieldsAndValues, ", "), strings.Join(filters, " and "))

	return sql
}

// Receives a slice of fields an returns a slice with fields in the
// form of field=? that represents a placeholder to be replace for a value
func preparedFields(fields []string) []string {
	preparedFields := make([]string, len(fields))

	for i, v := range fields {
		preparedFields[i] = fmt.Sprintf(`%s=?`, strings.ToLower(v))
	}

	return preparedFields
}

func fieldNames(t reflect.Type) []string {
	fieldNames := make([]string, t.NumField())

	for i := 0; i < t.NumField(); i++ {
		fieldNames[i] = t.Field(i).Name
	}

	return fieldNames
}
<|endoftext|>


<commit_before>// Copyright (c) 2017 The btcsuite developers
// Use of this source code is governed by an ISC
// license that can be found in the LICENSE file.

package indexers

import (
	"errors"

	"github.com/roasbeef/btcd/blockchain"
	"github.com/roasbeef/btcd/chaincfg"
	"github.com/roasbeef/btcd/chaincfg/chainhash"
	"github.com/roasbeef/btcd/database"
	"github.com/roasbeef/btcd/wire"
	"github.com/roasbeef/btcutil"
	"github.com/roasbeef/btcutil/gcs"
	"github.com/roasbeef/btcutil/gcs/builder"
)

const (
	// cfIndexName is the human-readable name for the index.
	cfIndexName = "committed filter index"
)

// Committed filters come in two flavours: basic and extended. They are
// generated and dropped in pairs, and both are indexed by a block's hash.
// Besides holding different content, they also live in different buckets.
var (
	// cfIndexParentBucketKey is the name of the parent bucket used to house
	// the index. The rest of the buckets live below this bucket.
	cfIndexParentBucketKey = []byte("cfindexparentbucket")

	// cfIndexKeys is an array of db bucket names used to house indexes of
	// block hashes to cfilters.
	cfIndexKeys = [][]byte{
		[]byte("cf0byhashidx"),
		[]byte("cf1byhashidx"),
	}

	// cfHeaderKeys is an array of db bucket names used to house indexes of
	// block hashes to cf headers.
	cfHeaderKeys = [][]byte{
		[]byte("cf0headerbyhashidx"),
		[]byte("cf1headerbyhashidx"),
	}

	maxFilterType = uint8(len(cfHeaderKeys) - 1)
)

// dbFetchFilterIdxEntry retrieves a data blob from the filter index database.
// An entry's absence is not considered an error.
func dbFetchFilterIdxEntry(dbTx database.Tx, key []byte, h *chainhash.Hash) ([]byte, error) {
	idx := dbTx.Metadata().Bucket(cfIndexParentBucketKey).Bucket(key)
	return idx.Get(h[:]), nil
}

// dbStoreFilterIdxEntry stores a data blob in the filter index database.
func dbStoreFilterIdxEntry(dbTx database.Tx, key []byte, h *chainhash.Hash, f []byte) error {
	idx := dbTx.Metadata().Bucket(cfIndexParentBucketKey).Bucket(key)
	return idx.Put(h[:], f)
}

// dbDeleteFilterIdxEntry deletes a data blob from the filter index database.
func dbDeleteFilterIdxEntry(dbTx database.Tx, key []byte, h *chainhash.Hash) error {
	idx := dbTx.Metadata().Bucket(cfIndexParentBucketKey).Bucket(key)
	return idx.Delete(h[:])
}

// CfIndex implements a committed filter (cf) by hash index.
type CfIndex struct {
	db          database.DB
	chainParams *chaincfg.Params
}

// Ensure the CfIndex type implements the Indexer interface.
var _ Indexer = (*CfIndex)(nil)

// Init initializes the hash-based cf index. This is part of the Indexer
// interface.
func (idx *CfIndex) Init() error {
	return nil // Nothing to do.
}

// Key returns the database key to use for the index as a byte slice. This is
// part of the Indexer interface.
func (idx *CfIndex) Key() []byte {
	return cfIndexParentBucketKey
}

// Name returns the human-readable name of the index. This is part of the
// Indexer interface.
func (idx *CfIndex) Name() string {
	return cfIndexName
}

// Create is invoked when the indexer manager determines the index needs to
// be created for the first time. It creates buckets for the two hash-based cf
// indexes (simple, extended).
func (idx *CfIndex) Create(dbTx database.Tx) error {
	meta := dbTx.Metadata()

	cfIndexParentBucket, err := meta.CreateBucket(cfIndexParentBucketKey)
	if err != nil {
		return err
	}

	for _, bucketName := range cfIndexKeys {
		_, err = cfIndexParentBucket.CreateBucket(bucketName)
		if err != nil {
			return err
		}
	}

	for _, bucketName := range cfHeaderKeys {
		_, err = cfIndexParentBucket.CreateBucket(bucketName)
		if err != nil {
			return err
		}
	}

	firstHeader := make([]byte, chainhash.HashSize)
	err = dbStoreFilterIdxEntry(
		dbTx,
		cfHeaderKeys[wire.GCSFilterRegular],
		&idx.chainParams.GenesisBlock.Header.PrevBlock,
		firstHeader,
	)
	if err != nil {
		return err
	}

	return dbStoreFilterIdxEntry(
		dbTx,
		cfHeaderKeys[wire.GCSFilterExtended],
		&idx.chainParams.GenesisBlock.Header.PrevBlock,
		firstHeader,
	)
}

// storeFilter stores a given filter, and performs the steps needed to
// generate the filter's header.
func storeFilter(dbTx database.Tx, block *btcutil.Block, f *gcs.Filter,
	filterType wire.FilterType) error {
	if uint8(filterType) > maxFilterType {
		return errors.New("unsupported filter type")
	}

	// Figure out which buckets to use.
	fkey := cfIndexKeys[filterType]
	hkey := cfHeaderKeys[filterType]

	// Start by storing the filter.
	h := block.Hash()
	filterBytes, err := f.NBytes()
	if err != nil {
		return err
	}
	err = dbStoreFilterIdxEntry(dbTx, fkey, h, filterBytes)
	if err != nil {
		return err
	}

	// Then fetch the previous block's filter header.
	ph := &block.MsgBlock().Header.PrevBlock
	pfh, err := dbFetchFilterIdxEntry(dbTx, hkey, ph)
	if err != nil {
		return err
	}

	// Construct the new block's filter header, and store it.
	prevHeader, err := chainhash.NewHash(pfh)
	if err != nil {
		return err
	}
	fh, err := builder.MakeHeaderForFilter(f, *prevHeader)
	if err != nil {
		return err
	}
	return dbStoreFilterIdxEntry(dbTx, hkey, h, fh[:])
}

// ConnectBlock is invoked by the index manager when a new block has been
// connected to the main chain. This indexer adds a hash-to-cf mapping for
// every passed block. This is part of the Indexer interface.
func (idx *CfIndex) ConnectBlock(dbTx database.Tx, block *btcutil.Block,
	view *blockchain.UtxoViewpoint) error {

	f, err := builder.BuildBasicFilter(block.MsgBlock())
	if err != nil {
		return err
	}

	if err := storeFilter(dbTx, block, f,
		wire.GCSFilterRegular); err != nil {
		return err
	}

	f, err = builder.BuildExtFilter(block.MsgBlock())
	if err != nil {
		return err
	}

	return storeFilter(dbTx, block, f, wire.GCSFilterExtended)
}

// DisconnectBlock is invoked by the index manager when a block has been
// disconnected from the main chain.  This indexer removes the hash-to-cf
// mapping for every passed block. This is part of the Indexer interface.
func (idx *CfIndex) DisconnectBlock(dbTx database.Tx, block *btcutil.Block,
	view *blockchain.UtxoViewpoint) error {

	for _, key := range cfIndexKeys {
		err := dbDeleteFilterIdxEntry(dbTx, key, block.Hash())
		if err != nil {
			return err
		}
	}

	for _, key := range cfHeaderKeys {
		err := dbDeleteFilterIdxEntry(dbTx, key, block.Hash())
		if err != nil {
			return err
		}
	}

	return nil
}

// entryByBlockHash fetches a filter index entry of a particular type
// (eg. filter, filter header, etc) for a filter type and block hash.
func (idx *CfIndex) entryByBlockHash(filterTypeKeys [][]byte,
	filterType wire.FilterType, h *chainhash.Hash) ([]byte, error) {

	if uint8(filterType) > maxFilterType {
		return nil, errors.New("unsupported filter type")
	}
	key := filterTypeKeys[filterType]

	var entry []byte
	err := idx.db.View(func(dbTx database.Tx) error {
		var err error
		entry, err = dbFetchFilterIdxEntry(dbTx, key, h)
		return err
	})
	return entry, err
}

// FilterByBlockHash returns the serialized contents of a block's basic or
// extended committed filter.
func (idx *CfIndex) FilterByBlockHash(h *chainhash.Hash,
	filterType wire.FilterType) ([]byte, error) {
	return idx.entryByBlockHash(cfIndexKeys, filterType, h)
}

// FilterHeaderByBlockHash returns the serialized contents of a block's basic
// or extended committed filter header.
func (idx *CfIndex) FilterHeaderByBlockHash(h *chainhash.Hash,
	filterType wire.FilterType) ([]byte, error) {
	return idx.entryByBlockHash(cfHeaderKeys, filterType, h)
}

// NewCfIndex returns a new instance of an indexer that is used to create a
// mapping of the hashes of all blocks in the blockchain to their respective
// committed filters.
//
// It implements the Indexer interface which plugs into the IndexManager that
// in turn is used by the blockchain package. This allows the index to be
// seamlessly maintained along with the chain.
func NewCfIndex(db database.DB, chainParams *chaincfg.Params) *CfIndex {
	return &CfIndex{db: db, chainParams: chainParams}
}

// DropCfIndex drops the CF index from the provided database if exists.
func DropCfIndex(db database.DB, interrupt <-chan struct{}) error {
	return dropIndex(db, cfIndexParentBucketKey, cfIndexName, interrupt)
}
<commit_msg>blockchain/indexers: Store filter hashes with cfindex.<commit_after>// Copyright (c) 2017 The btcsuite developers
// Use of this source code is governed by an ISC
// license that can be found in the LICENSE file.

package indexers

import (
	"errors"

	"github.com/roasbeef/btcd/blockchain"
	"github.com/roasbeef/btcd/chaincfg"
	"github.com/roasbeef/btcd/chaincfg/chainhash"
	"github.com/roasbeef/btcd/database"
	"github.com/roasbeef/btcd/wire"
	"github.com/roasbeef/btcutil"
	"github.com/roasbeef/btcutil/gcs"
	"github.com/roasbeef/btcutil/gcs/builder"
)

const (
	// cfIndexName is the human-readable name for the index.
	cfIndexName = "committed filter index"
)

// Committed filters come in two flavours: basic and extended. They are
// generated and dropped in pairs, and both are indexed by a block's hash.
// Besides holding different content, they also live in different buckets.
var (
	// cfIndexParentBucketKey is the name of the parent bucket used to house
	// the index. The rest of the buckets live below this bucket.
	cfIndexParentBucketKey = []byte("cfindexparentbucket")

	// cfIndexKeys is an array of db bucket names used to house indexes of
	// block hashes to cfilters.
	cfIndexKeys = [][]byte{
		[]byte("cf0byhashidx"),
		[]byte("cf1byhashidx"),
	}

	// cfHeaderKeys is an array of db bucket names used to house indexes of
	// block hashes to cf headers.
	cfHeaderKeys = [][]byte{
		[]byte("cf0headerbyhashidx"),
		[]byte("cf1headerbyhashidx"),
	}

	// cfHashKeys is an array of db bucket names used to house indexes of
	// block hashes to cf hashes.
	cfHashKeys = [][]byte{
		[]byte("cf0hashbyhashidx"),
		[]byte("cf1hashbyhashidx"),
	}

	maxFilterType = uint8(len(cfHeaderKeys) - 1)

	// zeroHash is the chainhash.Hash value of all zero bytes, defined here for
	// convenience.
	zeroHash chainhash.Hash
)

// dbFetchFilterIdxEntry retrieves a data blob from the filter index database.
// An entry's absence is not considered an error.
func dbFetchFilterIdxEntry(dbTx database.Tx, key []byte, h *chainhash.Hash) ([]byte, error) {
	idx := dbTx.Metadata().Bucket(cfIndexParentBucketKey).Bucket(key)
	return idx.Get(h[:]), nil
}

// dbStoreFilterIdxEntry stores a data blob in the filter index database.
func dbStoreFilterIdxEntry(dbTx database.Tx, key []byte, h *chainhash.Hash, f []byte) error {
	idx := dbTx.Metadata().Bucket(cfIndexParentBucketKey).Bucket(key)
	return idx.Put(h[:], f)
}

// dbDeleteFilterIdxEntry deletes a data blob from the filter index database.
func dbDeleteFilterIdxEntry(dbTx database.Tx, key []byte, h *chainhash.Hash) error {
	idx := dbTx.Metadata().Bucket(cfIndexParentBucketKey).Bucket(key)
	return idx.Delete(h[:])
}

// CfIndex implements a committed filter (cf) by hash index.
type CfIndex struct {
	db          database.DB
	chainParams *chaincfg.Params
}

// Ensure the CfIndex type implements the Indexer interface.
var _ Indexer = (*CfIndex)(nil)

// Init initializes the hash-based cf index. This is part of the Indexer
// interface.
func (idx *CfIndex) Init() error {
	return nil // Nothing to do.
}

// Key returns the database key to use for the index as a byte slice. This is
// part of the Indexer interface.
func (idx *CfIndex) Key() []byte {
	return cfIndexParentBucketKey
}

// Name returns the human-readable name of the index. This is part of the
// Indexer interface.
func (idx *CfIndex) Name() string {
	return cfIndexName
}

// Create is invoked when the indexer manager determines the index needs to
// be created for the first time. It creates buckets for the two hash-based cf
// indexes (simple, extended).
func (idx *CfIndex) Create(dbTx database.Tx) error {
	meta := dbTx.Metadata()

	cfIndexParentBucket, err := meta.CreateBucket(cfIndexParentBucketKey)
	if err != nil {
		return err
	}

	for _, bucketName := range cfIndexKeys {
		_, err = cfIndexParentBucket.CreateBucket(bucketName)
		if err != nil {
			return err
		}
	}

	for _, bucketName := range cfHeaderKeys {
		_, err = cfIndexParentBucket.CreateBucket(bucketName)
		if err != nil {
			return err
		}
	}

	for _, bucketName := range cfHashKeys {
		_, err = cfIndexParentBucket.CreateBucket(bucketName)
		if err != nil {
			return err
		}
	}

	return nil
}

// storeFilter stores a given filter, and performs the steps needed to
// generate the filter's header.
func storeFilter(dbTx database.Tx, block *btcutil.Block, f *gcs.Filter,
	filterType wire.FilterType) error {
	if uint8(filterType) > maxFilterType {
		return errors.New("unsupported filter type")
	}

	// Figure out which buckets to use.
	fkey := cfIndexKeys[filterType]
	hkey := cfHeaderKeys[filterType]
	hashkey := cfHashKeys[filterType]

	// Start by storing the filter.
	h := block.Hash()
	filterBytes, err := f.NBytes()
	if err != nil {
		return err
	}
	err = dbStoreFilterIdxEntry(dbTx, fkey, h, filterBytes)
	if err != nil {
		return err
	}

	// Next store the filter hash.
	filterHash, err := builder.GetFilterHash(f)
	if err != nil {
		return err
	}
	err = dbStoreFilterIdxEntry(dbTx, hashkey, h, filterHash[:])
	if err != nil {
		return err
	}

	// Then fetch the previous block's filter header.
	var prevHeader *chainhash.Hash
	ph := &block.MsgBlock().Header.PrevBlock
	if ph.IsEqual(&zeroHash) {
		prevHeader = &zeroHash
	} else {
		pfh, err := dbFetchFilterIdxEntry(dbTx, hkey, ph)
		if err != nil {
			return err
		}

		// Construct the new block's filter header, and store it.
		prevHeader, err = chainhash.NewHash(pfh)
		if err != nil {
			return err
		}
	}

	fh, err := builder.MakeHeaderForFilter(f, *prevHeader)
	if err != nil {
		return err
	}
	return dbStoreFilterIdxEntry(dbTx, hkey, h, fh[:])
}

// ConnectBlock is invoked by the index manager when a new block has been
// connected to the main chain. This indexer adds a hash-to-cf mapping for
// every passed block. This is part of the Indexer interface.
func (idx *CfIndex) ConnectBlock(dbTx database.Tx, block *btcutil.Block,
	view *blockchain.UtxoViewpoint) error {

	f, err := builder.BuildBasicFilter(block.MsgBlock())
	if err != nil {
		return err
	}

	err = storeFilter(dbTx, block, f, wire.GCSFilterRegular)
	if err != nil {
		return err
	}

	f, err = builder.BuildExtFilter(block.MsgBlock())
	if err != nil {
		return err
	}

	return storeFilter(dbTx, block, f, wire.GCSFilterExtended)
}

// DisconnectBlock is invoked by the index manager when a block has been
// disconnected from the main chain.  This indexer removes the hash-to-cf
// mapping for every passed block. This is part of the Indexer interface.
func (idx *CfIndex) DisconnectBlock(dbTx database.Tx, block *btcutil.Block,
	view *blockchain.UtxoViewpoint) error {

	for _, key := range cfIndexKeys {
		err := dbDeleteFilterIdxEntry(dbTx, key, block.Hash())
		if err != nil {
			return err
		}
	}

	for _, key := range cfHeaderKeys {
		err := dbDeleteFilterIdxEntry(dbTx, key, block.Hash())
		if err != nil {
			return err
		}
	}

	for _, key := range cfHashKeys {
		err := dbDeleteFilterIdxEntry(dbTx, key, block.Hash())
		if err != nil {
			return err
		}
	}

	return nil
}

// entryByBlockHash fetches a filter index entry of a particular type
// (eg. filter, filter header, etc) for a filter type and block hash.
func (idx *CfIndex) entryByBlockHash(filterTypeKeys [][]byte,
	filterType wire.FilterType, h *chainhash.Hash) ([]byte, error) {

	if uint8(filterType) > maxFilterType {
		return nil, errors.New("unsupported filter type")
	}
	key := filterTypeKeys[filterType]

	var entry []byte
	err := idx.db.View(func(dbTx database.Tx) error {
		var err error
		entry, err = dbFetchFilterIdxEntry(dbTx, key, h)
		return err
	})
	return entry, err
}

// FilterByBlockHash returns the serialized contents of a block's basic or
// extended committed filter.
func (idx *CfIndex) FilterByBlockHash(h *chainhash.Hash,
	filterType wire.FilterType) ([]byte, error) {
	return idx.entryByBlockHash(cfIndexKeys, filterType, h)
}

// FilterHeaderByBlockHash returns the serialized contents of a block's basic
// or extended committed filter header.
func (idx *CfIndex) FilterHeaderByBlockHash(h *chainhash.Hash,
	filterType wire.FilterType) ([]byte, error) {
	return idx.entryByBlockHash(cfHeaderKeys, filterType, h)
}

// FilterHeaderByBlockHash returns the serialized contents of a block's basic
// or extended committed filter hash.
func (idx *CfIndex) FilterHashByBlockHash(h *chainhash.Hash,
	filterType wire.FilterType) ([]byte, error) {
	return idx.entryByBlockHash(cfHashKeys, filterType, h)
}

// NewCfIndex returns a new instance of an indexer that is used to create a
// mapping of the hashes of all blocks in the blockchain to their respective
// committed filters.
//
// It implements the Indexer interface which plugs into the IndexManager that
// in turn is used by the blockchain package. This allows the index to be
// seamlessly maintained along with the chain.
func NewCfIndex(db database.DB, chainParams *chaincfg.Params) *CfIndex {
	return &CfIndex{db: db, chainParams: chainParams}
}

// DropCfIndex drops the CF index from the provided database if exists.
func DropCfIndex(db database.DB, interrupt <-chan struct{}) error {
	return dropIndex(db, cfIndexParentBucketKey, cfIndexName, interrupt)
}
<|endoftext|>


<commit_before>package i18n

// T returns the given string translated into the language
// returned by lang.
func T(str string, lang Languager) string {
	return Tc("", str, lang)
}

// Tn translates the given string into the language returned
// by lang. The string will have different forms for singular
// and plural forms. The chosen form will depend on the n
// parameter and the target language. If there's no translation,
// the singular form will be returned iff n = 1.
func Tn(singular string, plural string, n int, lang Languager) string {
	return Tnc("", singular, plural, n, lang)
}

// Tc works like T, but accepts an additional context argument, to allow
// differentiating strings with the same singular form but different
// translation depending on the context.
func Tc(context string, str string, lang Languager) string {
	return str
}

// Tnc works like Tn, but accepts an additional context argument, to allow
// differentiating strings with the same singular form but different
// translation depending on the context. See the documentation for Tn for
// information about which form (singular or plural) is chosen.
func Tnc(context string, singular string, plural string, n int, lang Languager) string {
	if n == 1 {
		return singular
	}
	return plural
}
<commit_msg>Implement the actual calls to translation tables.<commit_after>package i18n

import (
	"gnd.la/i18n/table"
)

// T returns the given string translated into the language
// returned by lang.
func T(str string, lang Languager) string {
	return Tc("", str, lang)
}

// Tn translates the given string into the language returned
// by lang. The string will have different forms for singular
// and plural forms. The chosen form will depend on the n
// parameter and the target language. If there's no translation,
// the singular form will be returned iff n = 1.
func Tn(singular string, plural string, n int, lang Languager) string {
	return Tnc("", singular, plural, n, lang)
}

// Tc works like T, but accepts an additional context argument, to allow
// differentiating strings with the same singular form but different
// translation depending on the context.
func Tc(context string, str string, lang Languager) string {
	if translations := table.Get(lang.Language()); translations != nil {
		return translations.Singular(context, str)
	}
	return str
}

// Tnc works like Tn, but accepts an additional context argument, to allow
// differentiating strings with the same singular form but different
// translation depending on the context. See the documentation for Tn for
// information about which form (singular or plural) is chosen.
func Tnc(context string, singular string, plural string, n int, lang Languager) string {
	if translations := table.Get(lang.Language()); translations != nil {
		return translations.Plural(context, singular, plural, n)
	}
	if n == 1 {
		return singular
	}
	return plural
}
<|endoftext|>