<commit_before>//  Copyright (c) 2012 Couchbase, 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 rest

import (
	"crypto/sha1"
	"encoding/json"
	"fmt"
	"io"
	"io/ioutil"
	"net/http"
	"os"
	"runtime/pprof"
	"strconv"

	"github.com/couchbaselabs/sync_gateway/base"
	"github.com/couchbaselabs/sync_gateway/db"
)

const VersionString = "Couchbase Sync Gateway/0.59"

// HTTP handler for the root ("/")
func (h *handler) handleRoot() error {
	response := map[string]interface{}{
		"couchdb": "welcome",
		"version": VersionString,
	}
	if h.privs == adminPrivs {
		response["ADMIN"] = true
	}
	h.writeJSON(response)
	return nil
}

func (h *handler) handleAllDbs() error {
	h.writeJSON(h.server.AllDatabaseNames())
	return nil
}

func (h *handler) handleCompact() error {
	revsDeleted, err := h.db.Compact()
	if err != nil {
		return err
	}
	h.writeJSON(db.Body{"revs": revsDeleted})
	return nil
}

func (h *handler) handleVacuum() error {
	attsDeleted, err := db.VacuumAttachments(h.db.Bucket)
	if err != nil {
		return err
	}
	h.writeJSON(db.Body{"atts": attsDeleted})
	return nil
}

func (h *handler) instanceStartTime() json.Number {
	return json.Number(strconv.FormatInt(h.db.StartTime.UnixNano()/1000, 10))
}

func (h *handler) handleGetDB() error {
	if h.rq.Method == "HEAD" {
		return nil
	}
	lastSeq := h.db.LastSequence()
	response := db.Body{
		"db_name":              h.db.Name,
		"doc_count":            h.db.DocCount(),
		"update_seq":           lastSeq,
		"committed_update_seq": lastSeq,
		"instance_start_time":  h.instanceStartTime(),
		"compact_running":      false, // TODO: Implement this
		"purge_seq":            0,     // TODO: Should track this value
		"disk_format_version":  0,     // Probably meaningless, but add for compatibility
	}
	h.writeJSON(response)
	return nil
}

func (h *handler) handleEFC() error { // Handles _ensure_full_commit.
	// no-op. CouchDB's replicator sends this, so don't barf. Status must be 201.
	h.writeJSONStatus(http.StatusCreated, db.Body{
		"ok": true,
		"instance_start_time":  h.instanceStartTime(),
	})
	return nil
}

func (h *handler) handleDesign() error {
	// we serve this content here so that CouchDB 1.2 has something to
	// hash into the replication-id, to correspond to our filter.
	filter := "ok"
	if h.db.DatabaseContext.ChannelMapper != nil {
		hash := sha1.New()
		io.WriteString(hash, h.db.DatabaseContext.ChannelMapper.Function())
		filter = fmt.Sprint(hash.Sum(nil))
	}
	h.writeJSON(db.Body{"filters": db.Body{"bychannel": filter}})
	return nil
}

// ADMIN API to turn Go CPU profiling on/off
func (h *handler) handleProfiling() error {
	var params struct {
		File string `json:"file"`
	}
	body, err := ioutil.ReadAll(h.rq.Body)
	if err != nil {
		return err
	}
	if len(body) > 0 {
		if err = json.Unmarshal(body, &params); err != nil {
			return err
		}
	}

	if params.File != "" {
		base.Log("Profiling to %s ...", params.File)
		f, err := os.Create(params.File)
		if err != nil {
			return err
		}
		pprof.StartCPUProfile(f)
	} else {
		base.Log("...ending profile.")
		pprof.StopCPUProfile()
	}
	return nil
}
<commit_msg>Bumped version to 0.79<commit_after>//  Copyright (c) 2012 Couchbase, 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 rest

import (
	"crypto/sha1"
	"encoding/json"
	"fmt"
	"io"
	"io/ioutil"
	"net/http"
	"os"
	"runtime/pprof"
	"strconv"

	"github.com/couchbaselabs/sync_gateway/base"
	"github.com/couchbaselabs/sync_gateway/db"
)

const VersionString = "Couchbase Sync Gateway/0.79"

// HTTP handler for the root ("/")
func (h *handler) handleRoot() error {
	response := map[string]interface{}{
		"couchdb": "welcome",
		"version": VersionString,
	}
	if h.privs == adminPrivs {
		response["ADMIN"] = true
	}
	h.writeJSON(response)
	return nil
}

func (h *handler) handleAllDbs() error {
	h.writeJSON(h.server.AllDatabaseNames())
	return nil
}

func (h *handler) handleCompact() error {
	revsDeleted, err := h.db.Compact()
	if err != nil {
		return err
	}
	h.writeJSON(db.Body{"revs": revsDeleted})
	return nil
}

func (h *handler) handleVacuum() error {
	attsDeleted, err := db.VacuumAttachments(h.db.Bucket)
	if err != nil {
		return err
	}
	h.writeJSON(db.Body{"atts": attsDeleted})
	return nil
}

func (h *handler) instanceStartTime() json.Number {
	return json.Number(strconv.FormatInt(h.db.StartTime.UnixNano()/1000, 10))
}

func (h *handler) handleGetDB() error {
	if h.rq.Method == "HEAD" {
		return nil
	}
	lastSeq := h.db.LastSequence()
	response := db.Body{
		"db_name":              h.db.Name,
		"doc_count":            h.db.DocCount(),
		"update_seq":           lastSeq,
		"committed_update_seq": lastSeq,
		"instance_start_time":  h.instanceStartTime(),
		"compact_running":      false, // TODO: Implement this
		"purge_seq":            0,     // TODO: Should track this value
		"disk_format_version":  0,     // Probably meaningless, but add for compatibility
	}
	h.writeJSON(response)
	return nil
}

func (h *handler) handleEFC() error { // Handles _ensure_full_commit.
	// no-op. CouchDB's replicator sends this, so don't barf. Status must be 201.
	h.writeJSONStatus(http.StatusCreated, db.Body{
		"ok": true,
		"instance_start_time": h.instanceStartTime(),
	})
	return nil
}

func (h *handler) handleDesign() error {
	// we serve this content here so that CouchDB 1.2 has something to
	// hash into the replication-id, to correspond to our filter.
	filter := "ok"
	if h.db.DatabaseContext.ChannelMapper != nil {
		hash := sha1.New()
		io.WriteString(hash, h.db.DatabaseContext.ChannelMapper.Function())
		filter = fmt.Sprint(hash.Sum(nil))
	}
	h.writeJSON(db.Body{"filters": db.Body{"bychannel": filter}})
	return nil
}

// ADMIN API to turn Go CPU profiling on/off
func (h *handler) handleProfiling() error {
	var params struct {
		File string `json:"file"`
	}
	body, err := ioutil.ReadAll(h.rq.Body)
	if err != nil {
		return err
	}
	if len(body) > 0 {
		if err = json.Unmarshal(body, &params); err != nil {
			return err
		}
	}

	if params.File != "" {
		base.Log("Profiling to %s ...", params.File)
		f, err := os.Create(params.File)
		if err != nil {
			return err
		}
		pprof.StartCPUProfile(f)
	} else {
		base.Log("...ending profile.")
		pprof.StopCPUProfile()
	}
	return nil
}
<|endoftext|>


<commit_before>// Copyright 2014 Canonical Ltd.
// Licensed under the AGPLv3, see LICENCE file for details.

package api_test

import (
	"io"
	"net"

	gc "launchpad.net/gocheck"

	jujutesting "launchpad.net/juju-core/juju/testing"
	"launchpad.net/juju-core/state/api"
	"launchpad.net/juju-core/utils/parallel"
)

type apiclientSuite struct {
	jujutesting.JujuConnSuite
}

var _ = gc.Suite(&apiclientSuite{})

func (s *apiclientSuite) TestOpenPrefersLocalhostIfPresent(c *gc.C) {
	// Create a socket that proxies to the API server though our localhost address.
	info := s.APIInfo(c)
	serverAddr := info.Addrs[0]
	server, err := net.Dial("tcp", serverAddr)
	c.Assert(err, gc.IsNil)
	defer server.Close()
	listener, err := net.Listen("tcp", "localhost:26104")
	c.Assert(err, gc.IsNil)
	defer listener.Close()
	go func() {
		for {
			client, err := listener.Accept()
			if err != nil {
				return
			}
			go io.Copy(client, server)
			go io.Copy(server, client)
		}
	}()

	// Check that we are using our working address to connect
	info.Addrs = []string{"fakeAddress:1", "fakeAddress:1", "localhost:26104"}
	st, err := api.Open(info, api.DialOpts{})
	c.Assert(err, gc.IsNil)
	defer st.Close()
	c.Assert(st.Addr(), gc.Equals, "localhost:26104")
}

func (s *apiclientSuite) TestOpenMultiple(c *gc.C) {
	// Create a socket that proxies to the API server.
	info := s.APIInfo(c)
	serverAddr := info.Addrs[0]
	server, err := net.Dial("tcp", serverAddr)
	c.Assert(err, gc.IsNil)
	defer server.Close()
	listener, err := net.Listen("tcp", "127.0.0.1:0")
	c.Assert(err, gc.IsNil)
	defer listener.Close()
	go func() {
		for {
			client, err := listener.Accept()
			if err != nil {
				return
			}
			go io.Copy(client, server)
			go io.Copy(server, client)
		}
	}()

	// Check that we can use the proxy to connect.
	proxyAddr := listener.Addr().String()
	info.Addrs = []string{proxyAddr}
	st, err := api.Open(info, api.DialOpts{})
	c.Assert(err, gc.IsNil)
	defer st.Close()
	c.Assert(st.Addr(), gc.Equals, proxyAddr)

	// Now break Addrs[0], and ensure that Addrs[1]
	// is successfully connected to.
	info.Addrs = []string{proxyAddr, serverAddr}
	listener.Close()
	st, err = api.Open(info, api.DialOpts{})
	c.Assert(err, gc.IsNil)
	defer st.Close()
	c.Assert(st.Addr(), gc.Equals, serverAddr)
}

func (s *apiclientSuite) TestOpenMultipleError(c *gc.C) {
	listener, err := net.Listen("tcp", "127.0.0.1:0")
	c.Assert(err, gc.IsNil)
	defer listener.Close()
	go func() {
		for {
			client, err := listener.Accept()
			if err != nil {
				return
			}
			client.Close()
		}
	}()
	info := s.APIInfo(c)
	addr := listener.Addr().String()
	info.Addrs = []string{addr, addr, addr}
	_, err = api.Open(info, api.DialOpts{})
	c.Assert(err, gc.ErrorMatches, `timed out connecting to "wss://.*/"`)
}

func (s *apiclientSuite) TestDialWebsocketStopped(c *gc.C) {
	stopped := make(chan struct{})
	f := api.NewWebsocketDialer(nil, api.DialOpts{})
	close(stopped)
	result, err := f(stopped)
	c.Assert(err, gc.Equals, parallel.ErrStopped)
	c.Assert(result, gc.IsNil)
}
<commit_msg>Changed tests to avoid hardcoded ports<commit_after>// Copyright 2014 Canonical Ltd.
// Licensed under the AGPLv3, see LICENCE file for details.

package api_test

import (
	"fmt"
	"io"
	"net"
	"strconv"

	gc "launchpad.net/gocheck"

	jujutesting "launchpad.net/juju-core/juju/testing"
	"launchpad.net/juju-core/state/api"
	"launchpad.net/juju-core/utils/parallel"
)

type apiclientSuite struct {
	jujutesting.JujuConnSuite
}

var _ = gc.Suite(&apiclientSuite{})

func (s *apiclientSuite) TestOpenPrefersLocalhostIfPresent(c *gc.C) {
	// Create a socket that proxies to the API server though our localhost address.
	info := s.APIInfo(c)
	serverAddr := info.Addrs[0]
	server, err := net.Dial("tcp", serverAddr)
	c.Assert(err, gc.IsNil)
	defer server.Close()
	listener, err := net.Listen("tcp", "localhost:0")
	c.Assert(err, gc.IsNil)
	defer listener.Close()
	go func() {
		for {
			client, err := listener.Accept()
			if err != nil {
				return
			}
			go io.Copy(client, server)
			go io.Copy(server, client)
		}
	}()

	// Check that we are using our working address to connect
	listenerAddress := listener.Addr().String()
	_, port, err := net.SplitHostPort(listenerAddress)
	c.Check(err, gc.IsNil)
	portNum, err := strconv.Atoi(port)
	c.Check(err, gc.IsNil)
	expectedHostPort := fmt.Sprintf("localhost:%d", portNum)
	info.Addrs = []string{"fakeAddress:1", "fakeAddress:1", expectedHostPort}
	st, err := api.Open(info, api.DialOpts{})
	c.Assert(err, gc.IsNil)
	defer st.Close()
	c.Assert(st.Addr(), gc.Equals, expectedHostPort)
}

func (s *apiclientSuite) TestOpenMultiple(c *gc.C) {
	// Create a socket that proxies to the API server.
	info := s.APIInfo(c)
	serverAddr := info.Addrs[0]
	server, err := net.Dial("tcp", serverAddr)
	c.Assert(err, gc.IsNil)
	defer server.Close()
	listener, err := net.Listen("tcp", "127.0.0.1:0")
	c.Assert(err, gc.IsNil)
	defer listener.Close()
	go func() {
		for {
			client, err := listener.Accept()
			if err != nil {
				return
			}
			go io.Copy(client, server)
			go io.Copy(server, client)
		}
	}()

	// Check that we can use the proxy to connect.
	proxyAddr := listener.Addr().String()
	info.Addrs = []string{proxyAddr}
	st, err := api.Open(info, api.DialOpts{})
	c.Assert(err, gc.IsNil)
	defer st.Close()
	c.Assert(st.Addr(), gc.Equals, proxyAddr)

	// Now break Addrs[0], and ensure that Addrs[1]
	// is successfully connected to.
	info.Addrs = []string{proxyAddr, serverAddr}
	listener.Close()
	st, err = api.Open(info, api.DialOpts{})
	c.Assert(err, gc.IsNil)
	defer st.Close()
	c.Assert(st.Addr(), gc.Equals, serverAddr)
}

func (s *apiclientSuite) TestOpenMultipleError(c *gc.C) {
	listener, err := net.Listen("tcp", "127.0.0.1:0")
	c.Assert(err, gc.IsNil)
	defer listener.Close()
	go func() {
		for {
			client, err := listener.Accept()
			if err != nil {
				return
			}
			client.Close()
		}
	}()
	info := s.APIInfo(c)
	addr := listener.Addr().String()
	info.Addrs = []string{addr, addr, addr}
	_, err = api.Open(info, api.DialOpts{})
	c.Assert(err, gc.ErrorMatches, `timed out connecting to "wss://.*/"`)
}

func (s *apiclientSuite) TestDialWebsocketStopped(c *gc.C) {
	stopped := make(chan struct{})
	f := api.NewWebsocketDialer(nil, api.DialOpts{})
	close(stopped)
	result, err := f(stopped)
	c.Assert(err, gc.Equals, parallel.ErrStopped)
	c.Assert(result, gc.IsNil)
}
<|endoftext|>


<commit_before>// Copyright 2012, 2013 Canonical Ltd.
// Licensed under the AGPLv3, see LICENCE file for details.

package state_test

import (
	"fmt"
	"strings"

	"github.com/juju/errors"
	"github.com/juju/names"
	jc "github.com/juju/testing/checkers"
	jujutxn "github.com/juju/txn"
	"github.com/juju/utils"
	"github.com/juju/utils/set"
	"github.com/juju/version"
	gc "gopkg.in/check.v1"
	"gopkg.in/juju/blobstore.v2"
	"gopkg.in/mgo.v2"

	"github.com/juju/juju/state"
	"github.com/juju/juju/state/binarystorage"
	"github.com/juju/juju/testing"
	"github.com/juju/juju/tools"
)

type tooler interface {
	lifer
	AgentTools() (*tools.Tools, error)
	SetAgentVersion(v version.Binary) error
	Refresh() error
}

func testAgentTools(c *gc.C, obj tooler, agent string) {
	// object starts with zero'd tools.
	t, err := obj.AgentTools()
	c.Assert(t, gc.IsNil)
	c.Assert(err, jc.Satisfies, errors.IsNotFound)

	err = obj.SetAgentVersion(version.Binary{})
	c.Assert(err, gc.ErrorMatches, fmt.Sprintf("cannot set agent version for %s: empty series or arch", agent))

	v2 := version.MustParseBinary("7.8.9-quantal-amd64")
	err = obj.SetAgentVersion(v2)
	c.Assert(err, jc.ErrorIsNil)
	t3, err := obj.AgentTools()
	c.Assert(err, jc.ErrorIsNil)
	c.Assert(t3.Version, gc.DeepEquals, v2)
	err = obj.Refresh()
	c.Assert(err, jc.ErrorIsNil)
	t3, err = obj.AgentTools()
	c.Assert(err, jc.ErrorIsNil)
	c.Assert(t3.Version, gc.DeepEquals, v2)

	testWhenDying(c, obj, noErr, deadErr, func() error {
		return obj.SetAgentVersion(v2)
	})
}

type binaryStorageSuite struct {
	ConnSuite

	controllerUUID string
	modelUUID      string
	st             *state.State
}

var _ = gc.Suite(&binaryStorageSuite{})

func (s *binaryStorageSuite) SetUpTest(c *gc.C) {
	s.ConnSuite.SetUpTest(c)

	// Store the controller UUID.
	model, err := s.State.ControllerModel()
	c.Assert(err, jc.ErrorIsNil)
	s.controllerUUID = model.UUID()

	// Create a new model and store its UUID.
	s.modelUUID = utils.MustNewUUID().String()
	cfg := testing.CustomModelConfig(c, testing.Attrs{
		"name": "new-model",
		"uuid": s.modelUUID,
	})
	_, s.st, err = s.State.NewModel(cfg, names.NewLocalUserTag("test-admin"))
	c.Assert(err, jc.ErrorIsNil)
	s.AddCleanup(func(*gc.C) {
		s.st.Close()
	})
}

type storageOpener func() (binarystorage.StorageCloser, error)

func (s *binaryStorageSuite) TestToolsStorage(c *gc.C) {
	s.testStorage(c, "toolsmetadata", s.State.ToolsStorage)
}

func (s *binaryStorageSuite) TestToolsStorageParams(c *gc.C) {
	s.testStorageParams(c, "toolsmetadata", s.modelUUID, s.st.ToolsStorage)
}

func (s *binaryStorageSuite) TestGUIArchiveStorage(c *gc.C) {
	s.testStorage(c, "guimetadata", s.State.GUIStorage)
}

func (s *binaryStorageSuite) TestGUIArchiveStorageParams(c *gc.C) {
	s.testStorageParams(c, "guimetadata", s.controllerUUID, s.st.GUIStorage)
}

func (s *binaryStorageSuite) testStorage(c *gc.C, collName string, openStorage storageOpener) {
	session := s.State.MongoSession()
	collectionNames, err := session.DB("juju").CollectionNames()
	c.Assert(err, jc.ErrorIsNil)
	nameSet := set.NewStrings(collectionNames...)
	c.Assert(nameSet.Contains(collName), jc.IsFalse)

	storage, err := openStorage()
	c.Assert(err, jc.ErrorIsNil)
	defer func() {
		err := storage.Close()
		c.Assert(err, jc.ErrorIsNil)
	}()

	err = storage.Add(strings.NewReader(""), binarystorage.Metadata{})
	c.Assert(err, jc.ErrorIsNil)

	collectionNames, err = session.DB("juju").CollectionNames()
	c.Assert(err, jc.ErrorIsNil)
	nameSet = set.NewStrings(collectionNames...)
	c.Assert(nameSet.Contains(collName), jc.IsTrue)
}

func (s *binaryStorageSuite) testStorageParams(c *gc.C, collName, uuid string, openStorage storageOpener) {
	var called bool
	s.PatchValue(state.BinarystorageNew, func(
		modelUUID string,
		managedStorage blobstore.ManagedStorage,
		metadataCollection *mgo.Collection,
		runner jujutxn.Runner,
	) binarystorage.Storage {
		called = true
		c.Assert(modelUUID, gc.Equals, uuid)
		c.Assert(managedStorage, gc.NotNil)
		c.Assert(metadataCollection.Name, gc.Equals, collName)
		c.Assert(runner, gc.NotNil)
		return nil
	})

	storage, err := openStorage()
	c.Assert(err, jc.ErrorIsNil)
	storage.Close()
	c.Assert(called, jc.IsTrue)
}
<commit_msg>state: adjust binarystorage tests to match model-migration changes<commit_after>// Copyright 2012, 2013 Canonical Ltd.
// Licensed under the AGPLv3, see LICENCE file for details.

package state_test

import (
	"fmt"
	"strings"

	"github.com/juju/errors"
	"github.com/juju/names"
	jc "github.com/juju/testing/checkers"
	jujutxn "github.com/juju/txn"
	"github.com/juju/utils"
	"github.com/juju/utils/set"
	"github.com/juju/version"
	gc "gopkg.in/check.v1"
	"gopkg.in/juju/blobstore.v2"
	"gopkg.in/mgo.v2"

	"github.com/juju/juju/state"
	"github.com/juju/juju/state/binarystorage"
	"github.com/juju/juju/testing"
	"github.com/juju/juju/tools"
)

type tooler interface {
	lifer
	AgentTools() (*tools.Tools, error)
	SetAgentVersion(v version.Binary) error
	Refresh() error
}

func testAgentTools(c *gc.C, obj tooler, agent string) {
	// object starts with zero'd tools.
	t, err := obj.AgentTools()
	c.Assert(t, gc.IsNil)
	c.Assert(err, jc.Satisfies, errors.IsNotFound)

	err = obj.SetAgentVersion(version.Binary{})
	c.Assert(err, gc.ErrorMatches, fmt.Sprintf("cannot set agent version for %s: empty series or arch", agent))

	v2 := version.MustParseBinary("7.8.9-quantal-amd64")
	err = obj.SetAgentVersion(v2)
	c.Assert(err, jc.ErrorIsNil)
	t3, err := obj.AgentTools()
	c.Assert(err, jc.ErrorIsNil)
	c.Assert(t3.Version, gc.DeepEquals, v2)
	err = obj.Refresh()
	c.Assert(err, jc.ErrorIsNil)
	t3, err = obj.AgentTools()
	c.Assert(err, jc.ErrorIsNil)
	c.Assert(t3.Version, gc.DeepEquals, v2)

	testWhenDying(c, obj, noErr, deadErr, func() error {
		return obj.SetAgentVersion(v2)
	})
}

type binaryStorageSuite struct {
	ConnSuite

	controllerUUID string
	modelUUID      string
	st             *state.State
}

var _ = gc.Suite(&binaryStorageSuite{})

func (s *binaryStorageSuite) SetUpTest(c *gc.C) {
	s.ConnSuite.SetUpTest(c)

	// Store the controller UUID.
	model, err := s.State.ControllerModel()
	c.Assert(err, jc.ErrorIsNil)
	s.controllerUUID = model.UUID()

	// Create a new model and store its UUID.
	s.modelUUID = utils.MustNewUUID().String()
	cfg := testing.CustomModelConfig(c, testing.Attrs{
		"name": "new-model",
		"uuid": s.modelUUID,
	})
	_, s.st, err = s.State.NewModel(state.ModelArgs{
		Config: cfg,
		Owner:  names.NewLocalUserTag("test-admin"),
	})
	c.Assert(err, jc.ErrorIsNil)
	s.AddCleanup(func(*gc.C) {
		s.st.Close()
	})
}

type storageOpener func() (binarystorage.StorageCloser, error)

func (s *binaryStorageSuite) TestToolsStorage(c *gc.C) {
	s.testStorage(c, "toolsmetadata", s.State.ToolsStorage)
}

func (s *binaryStorageSuite) TestToolsStorageParams(c *gc.C) {
	s.testStorageParams(c, "toolsmetadata", s.modelUUID, s.st.ToolsStorage)
}

func (s *binaryStorageSuite) TestGUIArchiveStorage(c *gc.C) {
	s.testStorage(c, "guimetadata", s.State.GUIStorage)
}

func (s *binaryStorageSuite) TestGUIArchiveStorageParams(c *gc.C) {
	s.testStorageParams(c, "guimetadata", s.controllerUUID, s.st.GUIStorage)
}

func (s *binaryStorageSuite) testStorage(c *gc.C, collName string, openStorage storageOpener) {
	session := s.State.MongoSession()
	collectionNames, err := session.DB("juju").CollectionNames()
	c.Assert(err, jc.ErrorIsNil)
	nameSet := set.NewStrings(collectionNames...)
	c.Assert(nameSet.Contains(collName), jc.IsFalse)

	storage, err := openStorage()
	c.Assert(err, jc.ErrorIsNil)
	defer func() {
		err := storage.Close()
		c.Assert(err, jc.ErrorIsNil)
	}()

	err = storage.Add(strings.NewReader(""), binarystorage.Metadata{})
	c.Assert(err, jc.ErrorIsNil)

	collectionNames, err = session.DB("juju").CollectionNames()
	c.Assert(err, jc.ErrorIsNil)
	nameSet = set.NewStrings(collectionNames...)
	c.Assert(nameSet.Contains(collName), jc.IsTrue)
}

func (s *binaryStorageSuite) testStorageParams(c *gc.C, collName, uuid string, openStorage storageOpener) {
	var called bool
	s.PatchValue(state.BinarystorageNew, func(
		modelUUID string,
		managedStorage blobstore.ManagedStorage,
		metadataCollection *mgo.Collection,
		runner jujutxn.Runner,
	) binarystorage.Storage {
		called = true
		c.Assert(modelUUID, gc.Equals, uuid)
		c.Assert(managedStorage, gc.NotNil)
		c.Assert(metadataCollection.Name, gc.Equals, collName)
		c.Assert(runner, gc.NotNil)
		return nil
	})

	storage, err := openStorage()
	c.Assert(err, jc.ErrorIsNil)
	storage.Close()
	c.Assert(called, jc.IsTrue)
}
<|endoftext|>


<commit_before>package connect

import (
	"crypto/tls"
	"io/ioutil"
	"net/http"
	"strconv"
	"time"

	"github.com/subutai-io/base/agent/config"
	"github.com/subutai-io/base/agent/log"
)

type mhost struct {
	Ipv4 string
	Url  string
	Port string
}

var instance *mhost

//return existing instance
//if dne create new one
func Instance() *mhost {
	if instance == nil {
		instance = new(mhost)
		instance.Url = config.Management.RestPublicKey
		instance.Ipv4 = config.Management.Host
		instance.Port = config.Management.Port
		instance.Url = config.Management.RestToken
	}
	return instance
}

func (m *mhost) GetToken() string {
	tr := &http.Transport{TLSClientConfig: &tls.Config{InsecureSkipVerify: true}}
	client := &http.Client{Transport: tr, Timeout: time.Second * 5}
	resp, err := client.Get("https://" + m.Ipv4 + ":" + m.Port + m.Url + "?username=" + config.Management.Login + "&password=" + config.Management.Password)
	if log.Check(log.WarnLevel, "Getting security token", err) {
		return ""
	}
	defer resp.Body.Close()

	token, _ := ioutil.ReadAll(resp.Body)
	return string(token)
}

func (m *mhost) GetKey() *Key {
	tr := &http.Transport{TLSClientConfig: &tls.Config{InsecureSkipVerify: true}}
	client := &http.Client{Transport: tr, Timeout: time.Second * 5}
	url := m.URL()
	resp, err := client.Get(url)
	if log.Check(log.WarnLevel, "Getting Management host Public Key", err) {
		return nil
	}
	defer resp.Body.Close()

	if resp.StatusCode != 200 {
		log.Warn("Failed to fetch PK from Management Server. Status Code " + strconv.Itoa(resp.StatusCode) + " url " + url)
		return nil
	}

	key, err := ioutil.ReadAll(resp.Body)
	log.Check(log.WarnLevel, "Getting MH Key", err)
	target := new(Key)
	target.Key = string(key)

	return target
}

func (m *mhost) URL() string {
	url := "https://" + m.Ipv4 + ":" + m.Port + config.Management.RestPublicKey + "?sptoken="
	token := m.GetToken()
	if len(token) == 168 {
		return url + token
	}
	return url
}
<commit_msg>Removed duplicate function.<commit_after>package connect

import (
	"crypto/tls"
	"io/ioutil"
	"net/http"
	"strconv"
	"time"

	"github.com/subutai-io/base/agent/config"
	"github.com/subutai-io/base/agent/lib/gpg"
	"github.com/subutai-io/base/agent/log"
)

type mhost struct {
	Ipv4 string
	Url  string
	Port string
}

var instance *mhost

//return existing instance
//if dne create new one
func Instance() *mhost {
	if instance == nil {
		instance = new(mhost)
		instance.Url = config.Management.RestPublicKey
		instance.Ipv4 = config.Management.Host
		instance.Port = config.Management.Port
		instance.Url = config.Management.RestToken
	}
	return instance
}

func (m *mhost) GetKey() *Key {
	tr := &http.Transport{TLSClientConfig: &tls.Config{InsecureSkipVerify: true}}
	client := &http.Client{Transport: tr, Timeout: time.Second * 5}
	url := m.URL()
	resp, err := client.Get(url)
	if log.Check(log.WarnLevel, "Getting Management host Public Key", err) {
		return nil
	}
	defer resp.Body.Close()

	if resp.StatusCode != 200 {
		log.Warn("Failed to fetch PK from Management Server. Status Code " + strconv.Itoa(resp.StatusCode) + " url " + url)
		return nil
	}

	key, err := ioutil.ReadAll(resp.Body)
	log.Check(log.WarnLevel, "Getting MH Key", err)
	target := new(Key)
	target.Key = string(key)

	return target
}

func (m *mhost) URL() string {
	url := "https://" + m.Ipv4 + ":" + m.Port + config.Management.RestPublicKey + "?sptoken="
	token := gpg.GetToken()
	if len(token) == 168 {
		return url + token
	}
	return url
}
<|endoftext|>


<commit_before>/*
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements.  See the NOTICE file
distributed with this work for additional information
regarding copyright ownership.  The ASF licenses this file
to you 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 ledger

import (
	"flag"
	"github.com/op/go-logging"
	"github.com/openblockchain/obc-peer/openchain/db"
	"github.com/openblockchain/obc-peer/openchain/ledger/testutil"
	"github.com/openblockchain/obc-peer/openchain/util"
	"github.com/openblockchain/obc-peer/protos"
	"github.com/tecbot/gorocksdb"
	"strconv"
	"testing"
)

func BenchmarkDB(b *testing.B) {
	b.Logf("testParams:%q", testParams)
	flags := flag.NewFlagSet("testParams", flag.ExitOnError)
	kvSize := flags.Int("KVSize", 1000, "size of the key-value")
	toPopulateDB := flags.Bool("PopulateDB", false, "Run in populate DB mode")
	maxKeySuffix := flags.Int("MaxKeySuffix", 1, "the keys are appended with _1, _2,.. upto MaxKeySuffix")
	keyPrefix := flags.String("KeyPrefix", "Key_", "The generated workload will have keys such as KeyPrefix_1, KeyPrefix_2, and so on")
	flags.Parse(testParams)
	if *toPopulateDB {
		b.ResetTimer()
		populateDB(b, *kvSize, *maxKeySuffix, *keyPrefix)
		return
	}

	dbWrapper := db.NewTestDBWrapper()
	randNumGen := testutil.NewTestRandomNumberGenerator(*maxKeySuffix)
	b.ResetTimer()
	for i := 0; i < b.N; i++ {
		key := []byte(*keyPrefix + strconv.Itoa(randNumGen.Next()))
		value := dbWrapper.GetFromDB(b, key)
		b.SetBytes(int64(len(value)))
	}
}

func BenchmarkLedgerSingleKeyTransaction(b *testing.B) {
	b.Logf("testParams:%q", testParams)
	flags := flag.NewFlagSet("testParams", flag.ExitOnError)
	key := flags.String("Key", "key", "key name")
	kvSize := flags.Int("KVSize", 1000, "size of the key-value")
	batchSize := flags.Int("BatchSize", 100, "size of the key-value")
	numBatches := flags.Int("NumBatches", 100, "number of batches")
	flags.Parse(testParams)

	b.Logf(`Running test with params: key=%s, kvSize=%d, batchSize=%d, numBatches=%d`, *key, *kvSize, *batchSize, *numBatches)
	testutil.SetLogLevel(logging.ERROR, "indexes")
	testutil.SetLogLevel(logging.ERROR, "ledger")
	testutil.SetLogLevel(logging.ERROR, "state")
	testutil.SetLogLevel(logging.ERROR, "statemgmt")
	testutil.SetLogLevel(logging.ERROR, "buckettree")
	testutil.SetLogLevel(logging.ERROR, "db")

	ledgerTestWrapper := createFreshDBAndTestLedgerWrapper(b)
	ledger := ledgerTestWrapper.ledger

	chaincode := "chaincodeId"
	value := testutil.ConstructRandomBytes(b, *kvSize-(len(chaincode)+len(*key)))
	tx := constructDummyTx(b)
	serializedBytes, _ := tx.Bytes()
	b.Logf("Size of serialized bytes for tx = %d", len(serializedBytes))
	b.ResetTimer()
	for n := 0; n < b.N; n++ {
		for i := 0; i < *numBatches; i++ {
			ledger.BeginTxBatch(1)
			// execute one batch
			var transactions []*protos.Transaction
			for j := 0; j < *batchSize; j++ {
				ledger.TxBegin("txUuid")
				_, err := ledger.GetState(chaincode, *key, true)
				if err != nil {
					b.Fatalf("Error in getting state: %s", err)
				}
				ledger.SetState(chaincode, *key, value)
				ledger.TxFinished("txUuid", true)
				transactions = append(transactions, tx)
			}
			ledger.CommitTxBatch(1, transactions, nil, []byte("proof"))
		}
	}
	b.StopTimer()

	//varify value persisted
	value, _ = ledger.GetState(chaincode, *key, true)
	size := ledger.GetBlockchainSize()
	b.Logf("Value size=%d, Blockchain height=%d", len(value), size)
}

func populateDB(tb testing.TB, kvSize int, totalKeys int, keyPrefix string) {
	dbWrapper := db.NewTestDBWrapper()
	dbWrapper.CreateFreshDB(tb)
	batch := gorocksdb.NewWriteBatch()
	for i := 0; i < totalKeys; i++ {
		key := []byte(keyPrefix + strconv.Itoa(i))
		value := testutil.ConstructRandomBytes(tb, kvSize-len(key))
		batch.Put(key, value)
		if i%1000 == 0 {
			dbWrapper.WriteToDB(tb, batch)
			batch = gorocksdb.NewWriteBatch()
		}
	}
	dbWrapper.CloseDB(tb)
}

func constructDummyTx(tb testing.TB) *protos.Transaction {
	uuid := util.GenerateUUID()
	tx, err := protos.NewTransaction(protos.ChaincodeID{Path: "dummyChaincodeId"}, uuid, "dummyFunction", []string{"dummyParamValue1, dummyParamValue2"})
	testutil.AssertNil(tb, err)
	return tx
}
<commit_msg>benchmark test changes<commit_after>/*
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements.  See the NOTICE file
distributed with this work for additional information
regarding copyright ownership.  The ASF licenses this file
to you 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 ledger

import (
	"flag"
	"github.com/op/go-logging"
	"github.com/openblockchain/obc-peer/openchain/db"
	"github.com/openblockchain/obc-peer/openchain/ledger/testutil"
	"github.com/openblockchain/obc-peer/openchain/util"
	"github.com/openblockchain/obc-peer/protos"
	"github.com/tecbot/gorocksdb"
	"strconv"
	"testing"
)

func BenchmarkDB(b *testing.B) {
	b.Logf("testParams:%q", testParams)
	flags := flag.NewFlagSet("testParams", flag.ExitOnError)
	kvSize := flags.Int("KVSize", 1000, "size of the key-value")
	toPopulateDB := flags.Bool("PopulateDB", false, "Run in populate DB mode")
	maxKeySuffix := flags.Int("MaxKeySuffix", 1, "the keys are appended with _1, _2,.. upto MaxKeySuffix")
	keyPrefix := flags.String("KeyPrefix", "Key_", "The generated workload will have keys such as KeyPrefix_1, KeyPrefix_2, and so on")
	flags.Parse(testParams)
	if *toPopulateDB {
		b.ResetTimer()
		populateDB(b, *kvSize, *maxKeySuffix, *keyPrefix)
		return
	}

	dbWrapper := db.NewTestDBWrapper()
	randNumGen := testutil.NewTestRandomNumberGenerator(*maxKeySuffix)
	b.ResetTimer()
	for i := 0; i < b.N; i++ {
		key := []byte(*keyPrefix + strconv.Itoa(randNumGen.Next()))
		value := dbWrapper.GetFromDB(b, key)
		b.SetBytes(int64(len(value)))
	}
}

func BenchmarkLedgerSingleKeyTransaction(b *testing.B) {
	b.Logf("testParams:%q", testParams)
	flags := flag.NewFlagSet("testParams", flag.ExitOnError)
	key := flags.String("Key", "key", "key name")
	kvSize := flags.Int("KVSize", 1000, "size of the key-value")
	batchSize := flags.Int("BatchSize", 100, "size of the key-value")
	numBatches := flags.Int("NumBatches", 100, "number of batches")
	numWritesToLedger := flags.Int("NumWritesToLedger", 4, "size of the key-value")
	flags.Parse(testParams)

	b.Logf(`Running test with params: key=%s, kvSize=%d, batchSize=%d, numBatches=%d, NumWritesToLedger=%d`,
		*key, *kvSize, *batchSize, *numBatches, *numWritesToLedger)

	testutil.SetLogLevel(logging.ERROR, "indexes")
	testutil.SetLogLevel(logging.ERROR, "ledger")
	testutil.SetLogLevel(logging.ERROR, "state")
	testutil.SetLogLevel(logging.ERROR, "statemgmt")
	testutil.SetLogLevel(logging.ERROR, "buckettree")
	testutil.SetLogLevel(logging.ERROR, "db")

	ledgerTestWrapper := createFreshDBAndTestLedgerWrapper(b)
	ledger := ledgerTestWrapper.ledger

	chaincode := "chaincodeId"
	value := testutil.ConstructRandomBytes(b, *kvSize-(len(chaincode)+len(*key)))
	tx := constructDummyTx(b)
	serializedBytes, _ := tx.Bytes()
	b.Logf("Size of serialized bytes for tx = %d", len(serializedBytes))
	b.ResetTimer()
	for n := 0; n < b.N; n++ {
		for i := 0; i < *numBatches; i++ {
			ledger.BeginTxBatch(1)
			// execute one batch
			var transactions []*protos.Transaction
			for j := 0; j < *batchSize; j++ {
				ledger.TxBegin("txUuid")
				_, err := ledger.GetState(chaincode, *key, true)
				if err != nil {
					b.Fatalf("Error in getting state: %s", err)
				}
				for l := 0; l < *numWritesToLedger; l++ {
					ledger.SetState(chaincode, *key, value)
				}
				ledger.TxFinished("txUuid", true)
				transactions = append(transactions, tx)
			}
			ledger.CommitTxBatch(1, transactions, nil, []byte("proof"))
		}
	}
	b.StopTimer()

	//varify value persisted
	value, _ = ledger.GetState(chaincode, *key, true)
	size := ledger.GetBlockchainSize()
	b.Logf("Value size=%d, Blockchain height=%d", len(value), size)
}

func populateDB(tb testing.TB, kvSize int, totalKeys int, keyPrefix string) {
	dbWrapper := db.NewTestDBWrapper()
	dbWrapper.CreateFreshDB(tb)
	batch := gorocksdb.NewWriteBatch()
	for i := 0; i < totalKeys; i++ {
		key := []byte(keyPrefix + strconv.Itoa(i))
		value := testutil.ConstructRandomBytes(tb, kvSize-len(key))
		batch.Put(key, value)
		if i%1000 == 0 {
			dbWrapper.WriteToDB(tb, batch)
			batch = gorocksdb.NewWriteBatch()
		}
	}
	dbWrapper.CloseDB(tb)
}

func constructDummyTx(tb testing.TB) *protos.Transaction {
	uuid := util.GenerateUUID()
	tx, err := protos.NewTransaction(protos.ChaincodeID{Path: "dummyChaincodeId"}, uuid, "dummyFunction", []string{"dummyParamValue1, dummyParamValue2"})
	testutil.AssertNil(tb, err)
	return tx
}
<|endoftext|>


<commit_before>// Copyright 2019 The SQLFlow Authors. 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 sql

import (
	"fmt"
	"strings"

	"github.com/asaskevich/govalidator"
)

var attributeRegions = map[string]string{
	"model":   "",
	"train":   "",
	"eval":    "",
	"predict": "",
	"engine":  "",
}

// ValidateAttributes validates the attributes are legal.
func ValidateAttributes(attrs map[string]*attribute) error {
	for k, v := range attrs {
		keyParts := strings.Split(k, ".")
		if len(keyParts) != 2 {
			return fmt.Errorf("Attributes should have only 2 parts, got %d in %s", len(keyParts), k)
		}
		keyRegion := keyParts[0]
		if _, ok := attributeRegions[keyRegion]; !ok {
			return fmt.Errorf("Unsupported WITH attribute region: %s", keyRegion)
		}
		// test the value is of supported type:
		// string, int, float, []int, []float
		if stringAttr, ok := v.Value.(string); ok {
			if govalidator.IsInt(stringAttr) {
				return nil
			} else if govalidator.IsFloat(stringAttr) {
				return nil
			} else if govalidator.IsJSON(stringAttr) {
				// test if json object like [1,2,3]
				return nil
			} else if govalidator.IsASCII(stringAttr) {
				// NOTE: should avoid this checking is ascii
				return nil
			} else {
				return fmt.Errorf("Not supported attribute value: %s", stringAttr)
			}
		} else if _, ok := v.Value.([]interface{}); ok {
			// a list attribute
			return nil
		} else {
			return fmt.Errorf("Attribute value is not string type, %v", v.Value)
		}
	}
	return nil
}
<commit_msg>Fix random failure on TestValidateAttribute (#692)<commit_after>// Copyright 2019 The SQLFlow Authors. 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 sql

import (
	"fmt"
	"strings"

	"github.com/asaskevich/govalidator"
)

var attributeRegions = map[string]string{
	"model":   "",
	"train":   "",
	"eval":    "",
	"predict": "",
	"engine":  "",
}

// ValidateAttributes validates the attributes are legal.
func ValidateAttributes(attrs map[string]*attribute) error {
	for k, v := range attrs {
		keyParts := strings.Split(k, ".")
		if len(keyParts) != 2 {
			return fmt.Errorf("attributes should of format first_part.second_part, got %s", k)
		}
		keyRegion := keyParts[0]
		if _, ok := attributeRegions[keyRegion]; !ok {
			return fmt.Errorf("unsupported WITH attribute region: %s", keyRegion)
		}
		// test the value is of supported type:
		// string, int, float, []int
		switch value := v.Value.(type) {
		case string:
			if govalidator.IsInt(value) || govalidator.IsFloat(value) || govalidator.IsJSON(value) || govalidator.IsASCII(value) {
				continue
			}
			return fmt.Errorf("not supported attribute value: %s", value)
		case []int, []interface{}:
			continue
		default:
			return fmt.Errorf("unrecognize attribute %v with type %T", value, value)
		}
	}
	return nil
}
<|endoftext|>


<commit_before>package oraclegen

import (
	"errors"
	"fmt"
	"strings"

	"github.com/rbastic/dyndao/object"
	"github.com/rbastic/dyndao/schema"
)

// BindingUpdate generates the SQL for a given UPDATE statement for oracle with binding parameter values
func (g Generator) BindingUpdate(sch *schema.Schema, obj *object.Object) (string, []interface{}, []interface{}, error) {
	schTable := sch.GetTable(obj.Type)
	if schTable == nil {
		return "", nil, nil, errors.New("BindingUpdate: Table map unavailable for table " + obj.Type)
	}

	fieldsMap := schTable.Fields
	if fieldsMap == nil {
		return "", nil, nil, errors.New("BindingUpdate: Field map unavailable for table " + obj.Type)
	}

	whereClause, bindWhere, err := renderUpdateWhereClause(schTable, fieldsMap, obj)
	if err != nil {
		return "", nil, nil, err
	}

	bindArgs := make([]interface{}, len(obj.KV)-1)
	// TODO: - 1 for Oracle because we expect an identity field
	newValuesAry := make([]string, len(obj.KV)-1)
	i := 0

	if len(obj.ChangedFields) > 0 {
		for k := range obj.ChangedFields {
			f := fieldsMap[k]
			if f.IsIdentity {
				continue
			}
			newValuesAry[i] = fmt.Sprintf("%s = %s%d", f.Name, renderBindingUpdateValue(f), i)
			bindArgs[i] = obj.KV[k]

			i++
		}
	} else {
		for k, v := range obj.KV {
			f := fieldsMap[k]
			if f.IsIdentity {
				continue
			}
			newValuesAry[i] = fmt.Sprintf("%s = %s%d", f.Name, renderBindingUpdateValue(f), i)
			bindArgs[i] = v

			i++
		}
	}

	tableName := schema.GetTableName(schTable.Name, obj.Type)
	sqlStr := fmt.Sprintf("UPDATE %s SET %s WHERE %s", tableName, strings.Join(newValuesAry, ","), whereClause)
	return sqlStr, bindArgs, bindWhere, nil
}

func renderBindingUpdateValue(f *schema.Field) string {
	return ":" + f.Name
}
<commit_msg>fix UPDATE handling, should handle NULLs now, etc.<commit_after>package oraclegen

import (
	"errors"
	"fmt"
	"strings"

	"github.com/rbastic/dyndao/object"
	"github.com/rbastic/dyndao/schema"
)

// BindingUpdate generates the SQL for a given UPDATE statement for oracle with binding parameter values
func (g Generator) BindingUpdate(sch *schema.Schema, obj *object.Object) (string, []interface{}, []interface{}, error) {
	schTbl := sch.GetTable(obj.Type)
	if schTbl == nil {
		return "", nil, nil, errors.New("BindingUpdate: Table map unavailable for table " + obj.Type)
	}

	fieldsMap := schTbl.Fields
	if fieldsMap == nil {
		return "", nil, nil, errors.New("BindingUpdate: Field map unavailable for table " + obj.Type)
	}

	whereClause, bindWhere, err := renderUpdateWhereClause(schTbl, fieldsMap, obj)
	if err != nil {
		return "", nil, nil, err
	}

	i := 0

	var bindArgs []interface{}
	var newValuesAry []string

	// If some things have changed, then only use fields that we're sure have changed
	if len(obj.ChangedFields) > 0 {
		bindArgs = make([]interface{}, len(obj.ChangedFields))
		newValuesAry = make([]string, len(obj.ChangedFields))

		for k := range obj.ChangedFields {
			f := schTbl.GetField(k)
			if f.IsIdentity {
				continue
			}
			v := obj.KV[k]
			if v == nil {
				newValuesAry[i] = fmt.Sprintf("%s = NULL", f.Name)
				bindArgs[i] = nil
			} else {
				newValuesAry[i] = fmt.Sprintf("%s = %s%d", f.Name, renderBindingUpdateValue(f), i)
				bindArgs[i] = v
			}
			i++
		}
	} else {
		// An update where it's not explicitly clear that anything has changed should
		// just set every field we have available.
		bindArgs = make([]interface{}, len(obj.KV)-1)
		// TODO: -1 for Oracle because we expect an identity field
		newValuesAry = make([]string, len(obj.KV)-1)

		for k, v := range obj.KV {
			f := schTbl.GetField(k)
			if f.IsIdentity {
				continue
			}
			if v == nil {
				newValuesAry[i] = fmt.Sprintf("%s = NULL", f.Name)
				bindArgs[i] = nil
			} else {
				newValuesAry[i] = fmt.Sprintf("%s = %s%d", f.Name, renderBindingUpdateValue(f), i)
				bindArgs[i] = v
			}

			i++
		}
	}
	bindArgs = removeNilsIfNeeded(bindArgs)

	tableName := schema.GetTableName(schTbl.Name, obj.Type)
	sqlStr := fmt.Sprintf("UPDATE %s SET %s WHERE %s", tableName, strings.Join(newValuesAry, ","), whereClause)
	return sqlStr, bindArgs, bindWhere, nil
}

func renderBindingUpdateValue(f *schema.Field) string {
	return ":" + f.Name
}
<|endoftext|>


<commit_before>package polly

import (
	_ "errors"
	_ "flag"
	_ "os"
	_ "fmt"
	"github.com/go-ole/go-ole"
	"github.com/go-ole/go-ole/oleutil"
)

var (
	CLSID_FilterGraph = ole.NewGUID("{E436EBB3-524F-11CE-9F53-0020AF0BA770}")

	IID_IGraphBuilder = ole.NewGUID("{56A868A9-0AD4-11CE-B03A-0020AF0BA770}")

	IID_IMediaControl = ole.NewGUID("{56A868B1-0AD4-11CE-B03A-0020AF0BA770}")

	IID_IMediaEvent   = ole.NewGUID("{56a868b6-0ad4-11ce-b03a-0020af0ba770}")

	INFINITE = int(-1)
)

func Play(filename string) (err error) {
	connection := &ole.Connection{nil}

	err = connection.Initialize()
	if err != nil {
		return
	}
	defer connection.Uninitialize()

	pGraphBuilder, err := ole.CreateInstance(CLSID_FilterGraph, IID_IGraphBuilder)
	if err != nil {
		return
	}

	pMediaControl,err := pGraphBuilder.QueryInterface(IID_IMediaControl)
	if err != nil {
		return
	}

	pMediaEvent,err := pGraphBuilder.QueryInterface(IID_IMediaEvent)
	if err != nil {
		return
	}

	_ = oleutil.MustCallMethod(pMediaControl, "RenderFile", filename)

	_ = oleutil.MustCallMethod(pMediaControl, "Run")

	for ev := 0; ev == 0; {
		_ = oleutil.MustCallMethod(pMediaEvent, "WaitForCompletion", INFINITE, &ev)
	}

	pMediaControl.Release()
	pMediaControl.Release()
	pGraphBuilder.Release()

	return
}
<commit_msg>Add CoUninitialize() method<commit_after>package polly

import (
	_ "errors"
	_ "flag"
	_ "os"
	_ "fmt"
	"github.com/go-ole/go-ole"
	"github.com/go-ole/go-ole/oleutil"
)

var (
	CLSID_FilterGraph = ole.NewGUID("{E436EBB3-524F-11CE-9F53-0020AF0BA770}")

	IID_IGraphBuilder = ole.NewGUID("{56A868A9-0AD4-11CE-B03A-0020AF0BA770}")

	IID_IMediaControl = ole.NewGUID("{56A868B1-0AD4-11CE-B03A-0020AF0BA770}")

	IID_IMediaEvent   = ole.NewGUID("{56a868b6-0ad4-11ce-b03a-0020af0ba770}")

	INFINITE = int(-1)
)

func Play(filename string) (err error) {
	connection := &ole.Connection{nil}

	err = connection.Initialize()
	if err != nil {
		return
	}
	defer connection.Uninitialize()

	pGraphBuilder, err := ole.CreateInstance(CLSID_FilterGraph, IID_IGraphBuilder)
	if err != nil {
		return
	}

	pMediaControl,err := pGraphBuilder.QueryInterface(IID_IMediaControl)
	if err != nil {
		return
	}

	pMediaEvent,err := pGraphBuilder.QueryInterface(IID_IMediaEvent)
	if err != nil {
		return
	}

	_ = oleutil.MustCallMethod(pMediaControl, "RenderFile", filename)

	_ = oleutil.MustCallMethod(pMediaControl, "Run")

	for ev := 0; ev == 0; {
		_ = oleutil.MustCallMethod(pMediaEvent, "WaitForCompletion", INFINITE, &ev)
	}

	pMediaControl.Release()
	pMediaControl.Release()
	pGraphBuilder.Release()

	ole.CoUninitialize()

	return
}
<|endoftext|>


<commit_before>// +build ignore

/*
Copyright 2013 Brandon Philips

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.
*/

// This program builds a project and is a copy of path.go. See
// github.com/philips/path.go
//
// $ go run path.go
//
// See the README file for more details.
package main

import (
	"fmt"
	"io"
	"io/ioutil"
	"log"
	"os"
	"os/exec"
	"path"
	"path/filepath"
	"strings"
)

const (
	DefaultThirdParty = "third_party"
)

// thirdPartyDir creates a string path to the third_party directory based on
// the current working directory.
func thirdPartyDir() string {
	root, err := os.Getwd()
	if err != nil {
		log.Fatalf("Failed to get the current working directory: %v", err)
	}
	return path.Join(root, DefaultThirdParty)
}

func srcDir() string {
	return path.Join(thirdPartyDir(), "src")
}

// binDir creates a string path to the GOBIN directory based on the current
// working directory.
func binDir() string {
	root, err := os.Getwd()
	if err != nil {
		log.Fatalf("Failed to get the current working directory: %v", err)
	}
	return path.Join(root, "bin")
}

// runEnv execs a command like a shell script piping everything to the parent's
// stderr/stdout and uses the given environment.
func runEnv(env []string, name string, arg ...string) {
	cmd := exec.Command(name, arg...)

	cmd.Env = env

	stdout, err := cmd.StdoutPipe()
	if err != nil {
		fmt.Fprintf(os.Stderr, err.Error())
		os.Exit(1)
	}
	stderr, err := cmd.StderrPipe()
	if err != nil {
		fmt.Fprintf(os.Stderr, err.Error())
		os.Exit(1)
	}
	err = cmd.Start()
	if err != nil {
		fmt.Fprintf(os.Stderr, err.Error())
		os.Exit(1)
	}
	go io.Copy(os.Stdout, stdout)
	go io.Copy(os.Stderr, stderr)
	cmd.Wait()
}

// run calls runEnv with the GOPATH third_party packages.
func run(name string, arg ...string) {
	env := append(os.Environ(),
		"GOPATH="+thirdPartyDir(),
		"GOBIN="+binDir(),
	)

	runEnv(env, name, arg...)
}

// setupProject does the initial setup of the third_party src directory
// including setting up the symlink to the cwd from the src directory.
func setupProject(pkg string) {
	root, err := os.Getwd()
	if err != nil {
		log.Fatalf("Failed to get the current working directory: %v", err)
	}

	src := path.Join(thirdPartyDir(), "src", pkg)
	srcdir := path.Dir(src)

	os.MkdirAll(srcdir, 0755)

	rel, err := filepath.Rel(srcdir, root)
	if err != nil {
		log.Fatalf("creating relative third party path: %v", err)
	}

	err = os.Symlink(rel, src)
	if err != nil && os.IsExist(err) == false {
		log.Fatalf("creating project third party symlink: %v", err)
	}
}

// commit grabs the commit id from hg or git as a string.
func commit(dir string) string {
	base := path.Base(dir)
	switch base {
	case ".git":
		return commitGit(dir)
	case ".hg":
		return commitHg(dir)
	default:
		return ""
	}
}

// commitGit returns the current HEAD commit hash for a given git dir.
func commitGit(dir string) string {
	out, err := exec.Command("git", "--git-dir="+dir, "rev-parse", "HEAD").Output()
	if err != nil {
		return ""
	}
	return string(out)
}

// commitHg returns the current HEAD commit hash for a given git dir.
func commitHg(dir string) string {
	out, err := exec.Command("hg", "id", "-i", "-R", dir).Output()
	if err != nil {
		return ""
	}
	return string(out)
}

// removeVcs removes a .git or .hg directory from the given root if it exists.
func removeVcs(root string) (bool, string) {
	for _, v := range []string{".git", ".hg"} {
		r := path.Join(root, v)
		info, err := os.Stat(r)

		if err != nil {
			continue
		}

		// We didn't find it, next!
		if info.IsDir() == false {
			continue
		}

		// We found it, grab the commit and remove the directory
		c := commit(r)
		err = os.RemoveAll(r)
		if err != nil {
			log.Fatalf("removeVcs: %v", err)
		}
		return true, c
	}

	return false, ""
}

// bump takes care of grabbing a package, getting the package git hash and
// removing all of the version control stuff.
func bump(pkg string) {
	tpd := thirdPartyDir()

	temp, _ := ioutil.TempDir(tpd, "bump")
	defer os.RemoveAll(temp)

	env := append(os.Environ(),
		"GOPATH="+temp,
	)

	runEnv(env, "go", "get", "-u", "-d", pkg)

	for {
		root := path.Join(temp, "src", pkg) // the temp installation root
		home := path.Join(tpd, "src", pkg)  // where the package will end up

		ok, c := removeVcs(root)
		if ok {
			// Create the path leading up to the package
			err := os.MkdirAll(path.Dir(home), 0755)
			if err != nil {
				log.Fatalf("bump: %v", err)
			}

			// Remove anything that might have been there
			err = os.RemoveAll(home)
			if err != nil {
				log.Fatalf("bump: %v", err)
			}

			// Finally move the package
			err = os.Rename(root, home)
			if err != nil {
				log.Fatalf("bump: %v", err)
			}

			fmt.Printf("%s %s\n", pkg, strings.TrimSpace(c))
			break
		}

		// Pop off and try to find this directory!
		pkg = path.Dir(pkg)
		if pkg == "." {
			return
		}
	}
}

// validPkg uses go list to decide if the given path is a valid go package.
// This is used by the bumpAll walk to bump all of the existing packages.
func validPkg(pkg string) bool {
	env := append(os.Environ(),
		"GOPATH="+thirdPartyDir(),
	)
	cmd := exec.Command("go", "list", pkg)
	cmd.Env = env

	out, err := cmd.Output()
	if err != nil {
		return false
	}

	if pkg == strings.TrimSpace(string(out)) {
		return true
	}

	return false
}

// bumpWalk walks the third_party directory and bumps all of the packages that it finds.
func bumpWalk(path string, info os.FileInfo, err error) error {
	if err != nil {
		return nil
	}

	// go packages are always directories
	if info.IsDir() == false {
		return nil
	}

	parts := strings.Split(path, srcDir()+"/")
	if len(parts) == 1 {
		return nil
	}

	pkg := parts[1]

	if validPkg(pkg) == false {
		return nil
	}

	bump(pkg)

	return nil
}

func bumpAll() {
	err := filepath.Walk(srcDir(), bumpWalk)
	if err != nil {
		log.Fatalf(err.Error())
	}
}

func main() {
	log.SetFlags(0)

	if len(os.Args) <= 1 {
		log.Fatalf("No commnad")
	}

	cmd := os.Args[1]

	if cmd == "setup" && len(os.Args) > 2 {
		setupProject(os.Args[2])
		return
	}

	if cmd == "bump" && len(os.Args) > 2 {
		bump(os.Args[2])
		return
	}

	if cmd == "bump-all" && len(os.Args) > 1 {
		bumpAll()
		return
	}

	run("go", os.Args[1:]...)
}
<commit_msg>bump(third_party): bump to the latest master<commit_after>// +build ignore

/*
Copyright 2013 Brandon Philips

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.
*/

// This program builds a project and is a copy of third_party.go. See
// github.com/philips/third_party.go
//
// $ go run third_party.go
//
// See the README file for more details.
package main

import (
	"fmt"
	"io"
	"io/ioutil"
	"log"
	"os"
	"os/exec"
	"path"
	"path/filepath"
	"strings"
)

const (
	DefaultThirdParty = "third_party"
)

// thirdPartyDir creates a string path to the third_party directory based on
// the current working directory.
func thirdPartyDir() string {
	root, err := os.Getwd()
	if err != nil {
		log.Fatalf("Failed to get the current working directory: %v", err)
	}
	return path.Join(root, DefaultThirdParty)
}

func srcDir() string {
	return path.Join(thirdPartyDir(), "src")
}

// binDir creates a string path to the GOBIN directory based on the current
// working directory.
func binDir() string {
	root, err := os.Getwd()
	if err != nil {
		log.Fatalf("Failed to get the current working directory: %v", err)
	}
	return path.Join(root, "bin")
}

// run execs a command like a shell script piping everything to the parent's
// stderr/stdout and uses the given environment.
func run(name string, arg ...string) *os.ProcessState {
	cmd := exec.Command(name, arg...)

	stdout, err := cmd.StdoutPipe()
	if err != nil {
		fmt.Fprintf(os.Stderr, err.Error())
		os.Exit(1)
	}
	stderr, err := cmd.StderrPipe()
	if err != nil {
		fmt.Fprintf(os.Stderr, err.Error())
		os.Exit(1)
	}
	err = cmd.Start()
	if err != nil {
		fmt.Fprintf(os.Stderr, err.Error())
		os.Exit(1)
	}
	go io.Copy(os.Stdout, stdout)
	go io.Copy(os.Stderr, stderr)
	cmd.Wait()

	return cmd.ProcessState
}

// setupProject does the initial setup of the third_party src directory
// including setting up the symlink to the cwd from the src directory.
func setupProject(pkg string) {
	root, err := os.Getwd()
	if err != nil {
		log.Fatalf("Failed to get the current working directory: %v", err)
	}

	src := path.Join(thirdPartyDir(), "src", pkg)
	srcdir := path.Dir(src)

	os.MkdirAll(srcdir, 0755)

	rel, err := filepath.Rel(srcdir, root)
	if err != nil {
		log.Fatalf("creating relative third party path: %v", err)
	}

	err = os.Symlink(rel, src)
	if err != nil && os.IsExist(err) == false {
		log.Fatalf("creating project third party symlink: %v", err)
	}
}

func getVc(root string) versionControl {
	for _, v := range []string{".git", ".hg"} {
		r := path.Join(root, v)
		info, err := os.Stat(r)

		if err != nil || !info.IsDir() {
			continue
		}

		base := path.Base(r)
		switch base {
		case ".git":
			return vcGit(r)
		case ".hg":
			return vcHg(r)
		}
	}
	return new(vcNoop)
}

type versionControl interface {
	commit() string
	update(string) error
}

//  Performs noops on all VC operations.
type vcNoop struct{}

func (v *vcNoop) commit() string {
	return ""
}

func (v *vcNoop) update(dir string) error {
	return nil
}

type vcHg string

// vcHg.commit returns the current HEAD commit hash for a given hg dir.
func (v vcHg) commit() string {
	out, err := exec.Command("hg", "id", "-i", "-R", string(v)).Output()
	if err != nil {
		return ""
	}
	return string(out)
}

// vcHg.udpate updates the given hg dir to ref.
func (v vcHg) update(ref string) error {
	_, err := exec.Command("hg",
		"update",
		"-r", ref,
		"-R", string(v),
		"--cwd", path.Dir(string(v)),
	).Output()
	if err != nil {
		return err
	}
	return nil
}

type vcGit string

// vcGit.commit returns the current HEAD commit hash for a given git dir.
func (v vcGit) commit() string {
	out, err := exec.Command("git", "--git-dir="+string(v), "rev-parse", "HEAD").Output()
	if err != nil {
		return ""
	}
	return string(out)
}

// vcHg.udpate updates the given git dir to ref.
func (v vcGit) update(ref string) error {
	_, err := exec.Command("git",
		"--work-tree="+path.Dir(string(v)),
		"--git-dir="+string(v),
		"reset", "--hard", ref,
	).Output()
	if err != nil {
		return err
	}
	return nil
}

// commit grabs the commit id from hg or git as a string.
func commit(dir string) string {
	return getVc(dir).commit()
}

// removeVcs removes a .git or .hg directory from the given root if it exists.
func removeVcs(root string) (bool, string) {
	for _, v := range []string{".git", ".hg"} {
		r := path.Join(root, v)
		info, err := os.Stat(r)

		if err != nil {
			continue
		}

		// We didn't find it, next!
		if info.IsDir() == false {
			continue
		}

		// We found it, grab the commit and remove the directory
		c := commit(root)
		err = os.RemoveAll(r)
		if err != nil {
			log.Fatalf("removeVcs: %v", err)
		}
		return true, c
	}

	return false, ""
}

// bump takes care of grabbing a package, getting the package git hash and
// removing all of the version control stuff.
func bump(pkg, version string) {
	tpd := thirdPartyDir()

	temp, err := ioutil.TempDir(tpd, "bump")
	if err != nil {
		log.Fatalf("bump: %v", err)
	}
	defer os.RemoveAll(temp)

	os.Setenv("GOPATH", temp)
	run("go", "get", "-u", "-d", pkg)

	for {
		root := path.Join(temp, "src", pkg) // the temp installation root
		home := path.Join(tpd, "src", pkg)  // where the package will end up

		if version != "" {
			err := getVc(root).update(version)
			if err != nil {
				log.Fatalf("bump: %v", err)
			}
		}

		ok, c := removeVcs(root)
		if ok {
			// Create the path leading up to the package
			err := os.MkdirAll(path.Dir(home), 0755)
			if err != nil {
				log.Fatalf("bump: %v", err)
			}

			// Remove anything that might have been there
			err = os.RemoveAll(home)
			if err != nil {
				log.Fatalf("bump: %v", err)
			}

			// Finally move the package
			err = os.Rename(root, home)
			if err != nil {
				log.Fatalf("bump: %v", err)
			}

			fmt.Printf("%s %s\n", pkg, strings.TrimSpace(c))
			break
		}

		// Pop off and try to find this directory!
		pkg = path.Dir(pkg)
		if pkg == "." {
			return
		}
	}
}

// validPkg uses go list to decide if the given path is a valid go package.
// This is used by the bumpAll walk to bump all of the existing packages.
func validPkg(pkg string) bool {
	env := append(os.Environ(),
	)
	cmd := exec.Command("go", "list", pkg)
	cmd.Env = env

	out, err := cmd.Output()
	if err != nil {
		return false
	}

	if pkg == strings.TrimSpace(string(out)) {
		return true
	}

	return false
}

// bumpWalk walks the third_party directory and bumps all of the packages that it finds.
func bumpWalk(path string, info os.FileInfo, err error) error {
	if err != nil {
		return nil
	}

	// go packages are always directories
	if info.IsDir() == false {
		return nil
	}

	parts := strings.Split(path, srcDir()+"/")
	if len(parts) == 1 {
		return nil
	}

	pkg := parts[1]

	if validPkg(pkg) == false {
		return nil
	}

	bump(pkg, "")

	return nil
}

func bumpAll() {
	err := filepath.Walk(srcDir(), bumpWalk)
	if err != nil {
		log.Fatalf(err.Error())
	}
}

func main() {
	log.SetFlags(0)

	// third_party manages GOPATH, no one else
	os.Setenv("GOPATH", thirdPartyDir())
	os.Setenv("GOBIN", binDir())

	if len(os.Args) <= 1 {
		log.Fatalf("No command")
	}

	cmd := os.Args[1]

	if cmd == "setup" && len(os.Args) > 2 {
		setupProject(os.Args[2])
		return
	}

	if cmd == "bump" && len(os.Args) > 2 {
		ref := ""
		if len(os.Args) > 3 {
			ref = os.Args[3]
		}

		bump(os.Args[2], ref)
		return
	}

	if cmd == "bump-all" && len(os.Args) > 1 {
		bumpAll()
		return
	}

	ps := run("go", os.Args[1:]...)

	if ps.Success() == false {
		os.Exit(1)
	}
}
<|endoftext|>


<commit_before>package main

import (
	"bytes"
	"net/http"
	"net/http/httptest"
	"strconv"
	"strings"
)

const (
	// Highlight of errors in the code
	preHighlight  = ""
	postHighlight = ""

	// Syntax highlighting theme for errors
	//errorTheme = "default"

	hiBackgroundColor = "#23252b"
)

// HTML to be added for enabling highlighting.
func highlightHTML(theme string) string {
	return `<script src="//cdn.rawgit.com/google/code-prettify/master/loader/run_prettify.js?skin=` + theme + `"></script>`
}

func highlightHTMLcode(htmlbody string) string {
	// Change
<code to
<code
	htmlbody = strings.Replace(htmlbody, "
<code", "

<code", -1)
	htmlbody = strings.Replace(htmlbody, "
", "

", -1)
	return htmlbody
}

// Write the contents of a ResponseRecorder to a ResponseWriter
func writeRecorder(w http.ResponseWriter, recorder *httptest.ResponseRecorder) {
	for key, values := range recorder.HeaderMap {
		for _, value := range values {
			w.Header().Set(key, value)
		}
	}
	recorder.Body.WriteTo(w)
	recorder.Flush()
}

// Discards the HTTP headers and returns the recorder body as a string
func recorderToString(recorder *httptest.ResponseRecorder) string {
	var buf bytes.Buffer
	recorder.Body.WriteTo(&buf)
	recorder.Flush()
	return buf.String()
}

// Return an informative error page to the user
// Takes a ResponseWriter, title (can be empty), filename, filebytes, errormessage and
// programming/scripting/template language (i.e. "lua". Can be empty).
func prettyError(w http.ResponseWriter, req *http.Request, filename string, filebytes []byte, errormessage, lang string) {

	// HTTP status
	//w.WriteHeader(http.StatusInternalServerError)
	w.WriteHeader(http.StatusOK)

	// HTTP content type
	w.Header().Set("Content-Type", "text/html; encoding=UTF-8")

	var (
		// If there is code to be displayed
		code string
		err  error
	)

	// The line that the error refers to, for the case of Lua
	linenr := -1

	if len(filebytes) > 0 {
		if lang == "lua" {
			// If the first line of the error message has two colons, see if the second field is a number
			fields := strings.SplitN(errormessage, ":", 3)
			if len(fields) > 2 {
				// Extract the line number from the error message, if possible
				numberfield := fields[1]
				if strings.Contains(numberfield, "(") {
					numberfield = strings.Split(numberfield, "(")[0]
				}
				linenr, err = strconv.Atoi(numberfield)
				// Subtract one to make it a slice index instead of human-friendly line number
				linenr--
				// Set linenumber to -1 if the conversion failed
				if err != nil {
					linenr = -1
				}
			}
		} else if lang == "amber" {
			// If the error contains "- Line: ", extract the line number
			if strings.Contains(errormessage, "- Line: ") {
				fields := strings.SplitN(errormessage, "- Line: ", 2)
				if strings.Contains(fields[1], ",") {
					numberfields := strings.SplitN(fields[1], ",", 2)
					linenr, err = strconv.Atoi(strings.TrimSpace(numberfields[0]))
					// Subtract one to make it a slice index instead of human-friendly line number
					linenr--
					// Set linenumber to -1 if the conversion failed
					if err != nil {
						linenr = -1
					}
				}
			}
		}

		// Escape any HTML in the code, so that the pretty printer is not confused
		filebytes = bytes.Replace(filebytes, []byte("<"), []byte("<"), everyInstance)

		// Modify the line that is to be highlighted
		bytelines := bytes.Split(filebytes, []byte("\n"))
		if (linenr >= 0) && (linenr < len(bytelines)) {
			bytelines[linenr] = []byte(preHighlight + string(bytelines[linenr]) + postHighlight)
		}

		// Build a string from the bytelines slice
		code = string(bytes.Join(bytelines, []byte("\n")))
	}

	// Set an appropriate title
	title := "Error"
	if lang == "gcss" {
		title = "GCSS Error"
	} else if lang == "html" {
		title = "HTML Error"
	} else if lang != "" {
		title = strings.Title(lang) + " Error"
	}

	// Set the highlight class
	langclass := lang

	// Turn off highlighting for some languages
	switch lang {
	case "", "amber", "gcss":
		langclass = "nohighlight"
	}

	// Highlighting for the error message
	errorclass := "json" // "nohighlight"

	// Inform the user of the error
	htmldata := []byte(`<!doctype html>

    <title>` + title + `</title>
	<link href='//fonts.googleapis.com/css?family=Lato:300' rel='stylesheet' type='text/css'>

` + title + `

    Contents of ` + filename + `:

<code class="` + langclass + `">` + code + `

    Error message:

<code style="color: #A00000;" class="` + errorclass + `">` + strings.TrimSpace(errormessage) + `

	` + versionString + `

`)

	if autoRefreshMode {
		// Insert JavaScript for refreshing the page into the generated HTML
		htmldata = insertAutoRefresh(req, htmldata)
	}

	w.Write(htmldata)
}
<commit_msg>Tiny adjustment<commit_after>package main

import (
	"bytes"
	"net/http"
	"net/http/httptest"
	"strconv"
	"strings"
)

const (
	// Highlight of errors in the code
	preHighlight  = ""
	postHighlight = ""

	// Syntax highlighting theme for errors
	//errorTheme = "default"

	hiBackgroundColor = "#202228"
)

// HTML to be added for enabling highlighting.
func highlightHTML(theme string) string {
	return `<script src="//cdn.rawgit.com/google/code-prettify/master/loader/run_prettify.js?skin=` + theme + `"></script>`
}

func highlightHTMLcode(htmlbody string) string {
	// Change
<code to
<code
	htmlbody = strings.Replace(htmlbody, "
<code", "

<code", -1)
	htmlbody = strings.Replace(htmlbody, "
", "

", -1)
	return htmlbody
}

// Write the contents of a ResponseRecorder to a ResponseWriter
func writeRecorder(w http.ResponseWriter, recorder *httptest.ResponseRecorder) {
	for key, values := range recorder.HeaderMap {
		for _, value := range values {
			w.Header().Set(key, value)
		}
	}
	recorder.Body.WriteTo(w)
	recorder.Flush()
}

// Discards the HTTP headers and returns the recorder body as a string
func recorderToString(recorder *httptest.ResponseRecorder) string {
	var buf bytes.Buffer
	recorder.Body.WriteTo(&buf)
	recorder.Flush()
	return buf.String()
}

// Return an informative error page to the user
// Takes a ResponseWriter, title (can be empty), filename, filebytes, errormessage and
// programming/scripting/template language (i.e. "lua". Can be empty).
func prettyError(w http.ResponseWriter, req *http.Request, filename string, filebytes []byte, errormessage, lang string) {

	// HTTP status
	//w.WriteHeader(http.StatusInternalServerError)
	w.WriteHeader(http.StatusOK)

	// HTTP content type
	w.Header().Set("Content-Type", "text/html; encoding=UTF-8")

	var (
		// If there is code to be displayed
		code string
		err  error
	)

	// The line that the error refers to, for the case of Lua
	linenr := -1

	if len(filebytes) > 0 {
		if lang == "lua" {
			// If the first line of the error message has two colons, see if the second field is a number
			fields := strings.SplitN(errormessage, ":", 3)
			if len(fields) > 2 {
				// Extract the line number from the error message, if possible
				numberfield := fields[1]
				if strings.Contains(numberfield, "(") {
					numberfield = strings.Split(numberfield, "(")[0]
				}
				linenr, err = strconv.Atoi(numberfield)
				// Subtract one to make it a slice index instead of human-friendly line number
				linenr--
				// Set linenumber to -1 if the conversion failed
				if err != nil {
					linenr = -1
				}
			}
		} else if lang == "amber" {
			// If the error contains "- Line: ", extract the line number
			if strings.Contains(errormessage, "- Line: ") {
				fields := strings.SplitN(errormessage, "- Line: ", 2)
				if strings.Contains(fields[1], ",") {
					numberfields := strings.SplitN(fields[1], ",", 2)
					linenr, err = strconv.Atoi(strings.TrimSpace(numberfields[0]))
					// Subtract one to make it a slice index instead of human-friendly line number
					linenr--
					// Set linenumber to -1 if the conversion failed
					if err != nil {
						linenr = -1
					}
				}
			}
		}

		// Escape any HTML in the code, so that the pretty printer is not confused
		filebytes = bytes.Replace(filebytes, []byte("<"), []byte("<"), everyInstance)

		// Modify the line that is to be highlighted
		bytelines := bytes.Split(filebytes, []byte("\n"))
		if (linenr >= 0) && (linenr < len(bytelines)) {
			bytelines[linenr] = []byte(preHighlight + string(bytelines[linenr]) + postHighlight)
		}

		// Build a string from the bytelines slice
		code = string(bytes.Join(bytelines, []byte("\n")))
	}

	// Set an appropriate title
	title := "Error"
	if lang == "gcss" {
		title = "GCSS Error"
	} else if lang == "html" {
		title = "HTML Error"
	} else if lang != "" {
		title = strings.Title(lang) + " Error"
	}

	// Set the highlight class
	langclass := lang

	// Turn off highlighting for some languages
	switch lang {
	case "", "amber", "gcss":
		langclass = "nohighlight"
	}

	// Highlighting for the error message
	errorclass := "json" // "nohighlight"

	// Inform the user of the error
	htmldata := []byte(`<!doctype html>

    <title>` + title + `</title>
	<link href='//fonts.googleapis.com/css?family=Lato:300' rel='stylesheet' type='text/css'>

` + title + `

    Contents of ` + filename + `:

<code class="` + langclass + `">` + code + `

    Error message:

<code style="color: #A00000;" class="` + errorclass + `">` + strings.TrimSpace(errormessage) + `

	` + versionString + `

`)

	if autoRefreshMode {
		// Insert JavaScript for refreshing the page into the generated HTML
		htmldata = insertAutoRefresh(req, htmldata)
	}

	w.Write(htmldata)
}
<|endoftext|>


<commit_before>// (c) Copyright IBM Corp. 2021
// (c) Copyright Instana Inc. 2016

package instana

import (
	"errors"
	"net/http"
	"strings"

	"github.com/instana/go-sensor/w3ctrace"
	ot "github.com/opentracing/opentracing-go"
)

// Instana header constants
const (
	// FieldT Trace ID header
	FieldT = "x-instana-t"
	// FieldS Span ID header
	FieldS = "x-instana-s"
	// FieldL Level header
	FieldL = "x-instana-l"
	// FieldB OT Baggage header
	FieldB = "x-instana-b-"
	// FieldSynthetic if set to 1, marks the call as synthetic, e.g.
	// a healthcheck request
	FieldSynthetic = "x-instana-synthetic"
)

func injectTraceContext(sc SpanContext, opaqueCarrier interface{}) error {
	roCarrier, ok := opaqueCarrier.(ot.TextMapReader)
	if !ok {
		return ot.ErrInvalidCarrier
	}

	// Handle pre-existing case-sensitive keys
	exstfieldT := FieldT
	exstfieldS := FieldS
	exstfieldL := FieldL
	exstfieldB := FieldB

	roCarrier.ForeachKey(func(k, v string) error {
		switch strings.ToLower(k) {
		case FieldT:
			exstfieldT = k
		case FieldS:
			exstfieldS = k
		case FieldL:
			exstfieldL = k
		default:
			if strings.HasPrefix(strings.ToLower(k), FieldB) {
				exstfieldB = string([]rune(k)[:len(FieldB)])
			}
		}
		return nil
	})

	carrier, ok := opaqueCarrier.(ot.TextMapWriter)
	if !ok {
		return ot.ErrInvalidCarrier
	}

	if c, ok := opaqueCarrier.(ot.HTTPHeadersCarrier); ok {
		// Even though the godoc claims that the key passed to (*http.Header).Set()
		// is case-insensitive, it actually normalizes it using textproto.CanonicalMIMEHeaderKey()
		// before populating the value. As a result headers with non-canonical will not be
		// overwritten with a new value. This is only the case if header names were set while
		// initializing the http.Header instance, i.e.
		//     h := http.Headers{"X-InStAnA-T": {"abc123"}}
		// and does not apply to a common case when requests are being created using http.NewRequest()
		// or http.ReadRequest() that call (*http.Header).Set() to set header values.
		h := http.Header(c)
		delete(h, exstfieldT)
		delete(h, exstfieldS)
		delete(h, exstfieldL)

		for key := range h {
			if strings.HasPrefix(strings.ToLower(key), FieldB) {
				delete(h, key)
			}
		}

		addW3CTraceContext(h, sc)
		addEUMHeaders(h, sc)
	}

	if !sc.Suppressed {
		carrier.Set(exstfieldT, FormatID(sc.TraceID))
		carrier.Set(exstfieldS, FormatID(sc.SpanID))
	} else {
		// remove trace context keys from the carrier
		switch c := opaqueCarrier.(type) {
		case ot.HTTPHeadersCarrier:
			h := http.Header(c)
			h.Del(exstfieldT)
			h.Del(exstfieldS)
		case ot.TextMapCarrier:
			delete(c, exstfieldT)
			delete(c, exstfieldS)
		case interface{ RemoveAll() }:
			// in case carrier has the RemoveAll() method that wipes all trace
			// headers, for example the instasarama.ProducerMessagCarrier, we
			// use it to remove the context of a suppressed trace
			c.RemoveAll()
		}
	}

	carrier.Set(exstfieldL, formatLevel(sc))

	for k, v := range sc.Baggage {
		carrier.Set(exstfieldB+k, v)
	}

	return nil
}

// This method searches for Instana headers (FieldT, FieldS, FieldL and header with name prefixed with FieldB)
// and try to parse their values. It also tries to extract W3C context and assign it inside returned object. W3C context
// will be propagated further and can be used as a fallback.
func extractTraceContext(opaqueCarrier interface{}) (SpanContext, error) {
	spanContext := SpanContext{
		Baggage: make(map[string]string),
	}

	carrier, ok := opaqueCarrier.(ot.TextMapReader)
	if !ok {
		return spanContext, ot.ErrInvalidCarrier
	}

	if c, ok := opaqueCarrier.(ot.HTTPHeadersCarrier); ok {
		pickupW3CTraceContext(http.Header(c), &spanContext)
	}

	// Iterate over the headers, look for Instana headers and try to parse them.
	// In case of error interrupt, iteration and return it.
	err := carrier.ForeachKey(func(k, v string) error {
		var err error

		switch strings.ToLower(k) {
		case FieldT:
			spanContext.TraceIDHi, spanContext.TraceID, err = ParseLongID(v)
			if err != nil {
				sensor.logger.Debug("extract trace context ", FieldT, "=", v, " : ", err)
				return ot.ErrSpanContextCorrupted
			}
		case FieldS:
			spanContext.SpanID, err = ParseID(v)
			if err != nil {
				sensor.logger.Debug("extract trace context ", FieldT, "=", v, " : ", err)
				return ot.ErrSpanContextCorrupted
			}
		case FieldL:
			// When FieldL is present and equals to "0", then spanContext is suppressed.
			// In addition to that non-empty correlation data may be extracted.
			suppressed, corrData, err := parseLevel(v)
			if err != nil {
				sensor.logger.Info("failed to parse ", k, ": ", err, " (", v, ")")
				// use defaults
				suppressed, corrData = false, EUMCorrelationData{}
			}

			spanContext.Suppressed = suppressed
			if !spanContext.Suppressed {
				spanContext.Correlation = corrData
			}
		default:
			if strings.HasPrefix(strings.ToLower(k), FieldB) {
				// preserve original case of the baggage key
				spanContext.Baggage[k[len(FieldB):]] = v
			}
		}

		return nil
	})
	if err != nil {
		return spanContext, err
	}

	// reset the trace IDs if a correlation ID has been provided
	if spanContext.Correlation.ID != "" {
		spanContext.TraceIDHi, spanContext.TraceID, spanContext.SpanID = 0, 0, 0

		return spanContext, nil
	}

	if spanContext.IsZero() {
		return spanContext, ot.ErrSpanContextNotFound
	}

	// When the context is not suppressed and one of Instana ID headers set.
	if !spanContext.Suppressed &&
		(spanContext.SpanID == 0 != (spanContext.TraceIDHi == 0 && spanContext.TraceID == 0)) {
		sensor.logger.Debug("broken Instana trace context:",
			" SpanID=", FormatID(spanContext.SpanID),
			" TraceID=", FormatLongID(spanContext.TraceIDHi, spanContext.TraceID))

		// Check if w3 context was found
		if !spanContext.W3CContext.IsZero() {
			// Return SpanContext with w3 context, ignore other values
			return SpanContext{
				W3CContext: spanContext.W3CContext,
			}, nil
		}

		return spanContext, ot.ErrSpanContextCorrupted
	}

	return spanContext, nil
}

func addW3CTraceContext(h http.Header, sc SpanContext) {
	traceID, spanID := FormatLongID(sc.TraceIDHi, sc.TraceID), FormatID(sc.SpanID)
	trCtx := sc.W3CContext

	// check for an existing w3c trace
	if trCtx.IsZero() {
		// initiate trace if none
		trCtx = w3ctrace.New(w3ctrace.Parent{
			Version:  w3ctrace.Version_Max,
			TraceID:  traceID,
			ParentID: spanID,
			Flags: w3ctrace.Flags{
				Sampled: !sc.Suppressed,
			},
		})
	}

	// update the traceparent parent ID
	p := trCtx.Parent()
	p.ParentID = spanID
	// sync the traceparent `sampled` flags with the X-Instana-L value
	p.Flags.Sampled = !sc.Suppressed

	trCtx.RawParent = p.String()

	// participate in w3c trace context if tracing is enabled
	if !sc.Suppressed {
		// propagate truncated trace ID downstream
		trCtx.RawState = trCtx.State().Add(w3ctrace.VendorInstana, FormatID(sc.TraceID)+";"+spanID).String()
	}

	w3ctrace.Inject(trCtx, h)
}

func pickupW3CTraceContext(h http.Header, sc *SpanContext) {
	trCtx, err := w3ctrace.Extract(h)
	if err != nil {
		return
	}
	sc.W3CContext = trCtx
}

func addEUMHeaders(h http.Header, sc SpanContext) {
	// Preserve original Server-Timing header values by combining them into a comma-separated list
	st := append(h["Server-Timing"], "intid;desc="+FormatID(sc.TraceID))
	h.Set("Server-Timing", strings.Join(st, ", "))
}

var errMalformedHeader = errors.New("malformed header value")

func parseLevel(s string) (bool, EUMCorrelationData, error) {
	const (
		levelState uint8 = iota
		partSeparatorState
		correlationPartState
		correlationTypeState
		correlationIDState
		finalState
	)

	if s == "" {
		return false, EUMCorrelationData{}, nil
	}

	var (
		typeInd                 int
		state                   uint8
		level, corrType, corrID string
	)
PARSE:
	for ptr := 0; state != finalState && ptr < len(s); ptr++ {
		switch state {
		case levelState: // looking for 0 or 1
			level = s[ptr : ptr+1]

			if level != "0" && level != "1" {
				break PARSE
			}

			if ptr == len(s)-1 { // no correlation ID provided
				state = finalState
			} else {
				state = partSeparatorState
			}
		case partSeparatorState: // skip OWS while looking for ','
			switch s[ptr] {
			case ' ', '\t': // advance
			case ',':
				state = correlationPartState
			default:
				break PARSE
			}
		case correlationPartState: // skip OWS while searching for 'correlationType=' prefix
			switch {
			case s[ptr] == ' ' || s[ptr] == '\t': // advance
			case strings.HasPrefix(s[ptr:], "correlationType="):
				ptr += 15 // advance to the end of prefix
				typeInd = ptr + 1
				state = correlationTypeState
			default:
				break PARSE
			}
		case correlationTypeState: // skip OWS while looking for ';'
			switch s[ptr] {
			case ' ', '\t': // possibly trailing OWS, advance
			case ';':
				state = correlationIDState
			default:
				corrType = s[typeInd : ptr+1]
			}
		case correlationIDState: //  skip OWS while searching for 'correlationId=' prefix
			switch {
			case s[ptr] == ' ' || s[ptr] == '\t': // leading OWS, advance
			case strings.HasPrefix(s[ptr:], "correlationId="):
				ptr += 14
				corrID = s[ptr:]
				state = finalState
			default:
				break PARSE
			}
		default:
			break PARSE
		}
	}

	if state != finalState {
		return false, EUMCorrelationData{}, errMalformedHeader
	}

	return level == "0", EUMCorrelationData{Type: corrType, ID: corrID}, nil
}

func formatLevel(sc SpanContext) string {
	if sc.Suppressed {
		return "0"
	}

	return "1"
}
<commit_msg>remove log lines<commit_after>// (c) Copyright IBM Corp. 2021
// (c) Copyright Instana Inc. 2016

package instana

import (
	"errors"
	"net/http"
	"strings"

	"github.com/instana/go-sensor/w3ctrace"
	ot "github.com/opentracing/opentracing-go"
)

// Instana header constants
const (
	// FieldT Trace ID header
	FieldT = "x-instana-t"
	// FieldS Span ID header
	FieldS = "x-instana-s"
	// FieldL Level header
	FieldL = "x-instana-l"
	// FieldB OT Baggage header
	FieldB = "x-instana-b-"
	// FieldSynthetic if set to 1, marks the call as synthetic, e.g.
	// a healthcheck request
	FieldSynthetic = "x-instana-synthetic"
)

func injectTraceContext(sc SpanContext, opaqueCarrier interface{}) error {
	roCarrier, ok := opaqueCarrier.(ot.TextMapReader)
	if !ok {
		return ot.ErrInvalidCarrier
	}

	// Handle pre-existing case-sensitive keys
	exstfieldT := FieldT
	exstfieldS := FieldS
	exstfieldL := FieldL
	exstfieldB := FieldB

	roCarrier.ForeachKey(func(k, v string) error {
		switch strings.ToLower(k) {
		case FieldT:
			exstfieldT = k
		case FieldS:
			exstfieldS = k
		case FieldL:
			exstfieldL = k
		default:
			if strings.HasPrefix(strings.ToLower(k), FieldB) {
				exstfieldB = string([]rune(k)[:len(FieldB)])
			}
		}
		return nil
	})

	carrier, ok := opaqueCarrier.(ot.TextMapWriter)
	if !ok {
		return ot.ErrInvalidCarrier
	}

	if c, ok := opaqueCarrier.(ot.HTTPHeadersCarrier); ok {
		// Even though the godoc claims that the key passed to (*http.Header).Set()
		// is case-insensitive, it actually normalizes it using textproto.CanonicalMIMEHeaderKey()
		// before populating the value. As a result headers with non-canonical will not be
		// overwritten with a new value. This is only the case if header names were set while
		// initializing the http.Header instance, i.e.
		//     h := http.Headers{"X-InStAnA-T": {"abc123"}}
		// and does not apply to a common case when requests are being created using http.NewRequest()
		// or http.ReadRequest() that call (*http.Header).Set() to set header values.
		h := http.Header(c)
		delete(h, exstfieldT)
		delete(h, exstfieldS)
		delete(h, exstfieldL)

		for key := range h {
			if strings.HasPrefix(strings.ToLower(key), FieldB) {
				delete(h, key)
			}
		}

		addW3CTraceContext(h, sc)
		addEUMHeaders(h, sc)
	}

	if !sc.Suppressed {
		carrier.Set(exstfieldT, FormatID(sc.TraceID))
		carrier.Set(exstfieldS, FormatID(sc.SpanID))
	} else {
		// remove trace context keys from the carrier
		switch c := opaqueCarrier.(type) {
		case ot.HTTPHeadersCarrier:
			h := http.Header(c)
			h.Del(exstfieldT)
			h.Del(exstfieldS)
		case ot.TextMapCarrier:
			delete(c, exstfieldT)
			delete(c, exstfieldS)
		case interface{ RemoveAll() }:
			// in case carrier has the RemoveAll() method that wipes all trace
			// headers, for example the instasarama.ProducerMessagCarrier, we
			// use it to remove the context of a suppressed trace
			c.RemoveAll()
		}
	}

	carrier.Set(exstfieldL, formatLevel(sc))

	for k, v := range sc.Baggage {
		carrier.Set(exstfieldB+k, v)
	}

	return nil
}

// This method searches for Instana headers (FieldT, FieldS, FieldL and header with name prefixed with FieldB)
// and try to parse their values. It also tries to extract W3C context and assign it inside returned object. W3C context
// will be propagated further and can be used as a fallback.
func extractTraceContext(opaqueCarrier interface{}) (SpanContext, error) {
	spanContext := SpanContext{
		Baggage: make(map[string]string),
	}

	carrier, ok := opaqueCarrier.(ot.TextMapReader)
	if !ok {
		return spanContext, ot.ErrInvalidCarrier
	}

	if c, ok := opaqueCarrier.(ot.HTTPHeadersCarrier); ok {
		pickupW3CTraceContext(http.Header(c), &spanContext)
	}

	// Iterate over the headers, look for Instana headers and try to parse them.
	// In case of error interrupt, iteration and return it.
	err := carrier.ForeachKey(func(k, v string) error {
		var err error

		switch strings.ToLower(k) {
		case FieldT:
			spanContext.TraceIDHi, spanContext.TraceID, err = ParseLongID(v)
			if err != nil {
				return ot.ErrSpanContextCorrupted
			}
		case FieldS:
			spanContext.SpanID, err = ParseID(v)
			if err != nil {
				return ot.ErrSpanContextCorrupted
			}
		case FieldL:
			// When FieldL is present and equals to "0", then spanContext is suppressed.
			// In addition to that non-empty correlation data may be extracted.
			suppressed, corrData, err := parseLevel(v)
			if err != nil {
				sensor.logger.Info("failed to parse ", k, ": ", err, " (", v, ")")
				// use defaults
				suppressed, corrData = false, EUMCorrelationData{}
			}

			spanContext.Suppressed = suppressed
			if !spanContext.Suppressed {
				spanContext.Correlation = corrData
			}
		default:
			if strings.HasPrefix(strings.ToLower(k), FieldB) {
				// preserve original case of the baggage key
				spanContext.Baggage[k[len(FieldB):]] = v
			}
		}

		return nil
	})
	if err != nil {
		return spanContext, err
	}

	// reset the trace IDs if a correlation ID has been provided
	if spanContext.Correlation.ID != "" {
		spanContext.TraceIDHi, spanContext.TraceID, spanContext.SpanID = 0, 0, 0

		return spanContext, nil
	}

	if spanContext.IsZero() {
		return spanContext, ot.ErrSpanContextNotFound
	}

	// When the context is not suppressed and one of Instana ID headers set.
	if !spanContext.Suppressed &&
		(spanContext.SpanID == 0 != (spanContext.TraceIDHi == 0 && spanContext.TraceID == 0)) {
		sensor.logger.Debug("broken Instana trace context:",
			" SpanID=", FormatID(spanContext.SpanID),
			" TraceID=", FormatLongID(spanContext.TraceIDHi, spanContext.TraceID))

		// Check if w3 context was found
		if !spanContext.W3CContext.IsZero() {
			// Return SpanContext with w3 context, ignore other values
			return SpanContext{
				W3CContext: spanContext.W3CContext,
			}, nil
		}

		return spanContext, ot.ErrSpanContextCorrupted
	}

	return spanContext, nil
}

func addW3CTraceContext(h http.Header, sc SpanContext) {
	traceID, spanID := FormatLongID(sc.TraceIDHi, sc.TraceID), FormatID(sc.SpanID)
	trCtx := sc.W3CContext

	// check for an existing w3c trace
	if trCtx.IsZero() {
		// initiate trace if none
		trCtx = w3ctrace.New(w3ctrace.Parent{
			Version:  w3ctrace.Version_Max,
			TraceID:  traceID,
			ParentID: spanID,
			Flags: w3ctrace.Flags{
				Sampled: !sc.Suppressed,
			},
		})
	}

	// update the traceparent parent ID
	p := trCtx.Parent()
	p.ParentID = spanID
	// sync the traceparent `sampled` flags with the X-Instana-L value
	p.Flags.Sampled = !sc.Suppressed

	trCtx.RawParent = p.String()

	// participate in w3c trace context if tracing is enabled
	if !sc.Suppressed {
		// propagate truncated trace ID downstream
		trCtx.RawState = trCtx.State().Add(w3ctrace.VendorInstana, FormatID(sc.TraceID)+";"+spanID).String()
	}

	w3ctrace.Inject(trCtx, h)
}

func pickupW3CTraceContext(h http.Header, sc *SpanContext) {
	trCtx, err := w3ctrace.Extract(h)
	if err != nil {
		return
	}
	sc.W3CContext = trCtx
}

func addEUMHeaders(h http.Header, sc SpanContext) {
	// Preserve original Server-Timing header values by combining them into a comma-separated list
	st := append(h["Server-Timing"], "intid;desc="+FormatID(sc.TraceID))
	h.Set("Server-Timing", strings.Join(st, ", "))
}

var errMalformedHeader = errors.New("malformed header value")

func parseLevel(s string) (bool, EUMCorrelationData, error) {
	const (
		levelState uint8 = iota
		partSeparatorState
		correlationPartState
		correlationTypeState
		correlationIDState
		finalState
	)

	if s == "" {
		return false, EUMCorrelationData{}, nil
	}

	var (
		typeInd                 int
		state                   uint8
		level, corrType, corrID string
	)
PARSE:
	for ptr := 0; state != finalState && ptr < len(s); ptr++ {
		switch state {
		case levelState: // looking for 0 or 1
			level = s[ptr : ptr+1]

			if level != "0" && level != "1" {
				break PARSE
			}

			if ptr == len(s)-1 { // no correlation ID provided
				state = finalState
			} else {
				state = partSeparatorState
			}
		case partSeparatorState: // skip OWS while looking for ','
			switch s[ptr] {
			case ' ', '\t': // advance
			case ',':
				state = correlationPartState
			default:
				break PARSE
			}
		case correlationPartState: // skip OWS while searching for 'correlationType=' prefix
			switch {
			case s[ptr] == ' ' || s[ptr] == '\t': // advance
			case strings.HasPrefix(s[ptr:], "correlationType="):
				ptr += 15 // advance to the end of prefix
				typeInd = ptr + 1
				state = correlationTypeState
			default:
				break PARSE
			}
		case correlationTypeState: // skip OWS while looking for ';'
			switch s[ptr] {
			case ' ', '\t': // possibly trailing OWS, advance
			case ';':
				state = correlationIDState
			default:
				corrType = s[typeInd : ptr+1]
			}
		case correlationIDState: //  skip OWS while searching for 'correlationId=' prefix
			switch {
			case s[ptr] == ' ' || s[ptr] == '\t': // leading OWS, advance
			case strings.HasPrefix(s[ptr:], "correlationId="):
				ptr += 14
				corrID = s[ptr:]
				state = finalState
			default:
				break PARSE
			}
		default:
			break PARSE
		}
	}

	if state != finalState {
		return false, EUMCorrelationData{}, errMalformedHeader
	}

	return level == "0", EUMCorrelationData{Type: corrType, ID: corrID}, nil
}

func formatLevel(sc SpanContext) string {
	if sc.Suppressed {
		return "0"
	}

	return "1"
}
<|endoftext|>


<commit_before>package proxy

import (
	"../util"
	"log"
	"math/big"
	"strconv"
	"strings"
	"sync"
	"sync/atomic"
	"time"

	"github.com/ethereum/ethash"
	"github.com/ethereum/go-ethereum/common"
)

var hasher = ethash.New()

type Miner struct {
	sync.RWMutex
	Id            string
	IP            string
	startedAt     int64
	lastBeat      int64
	validShares   uint64
	invalidShares uint64
	accepts       uint64
	rejects       uint64
	shares        map[int64]int64
}

func NewMiner(id, ip string) *Miner {
	miner := &Miner{Id: id, IP: ip, shares: make(map[int64]int64), startedAt: util.MakeTimestamp()}
	return miner
}

func (m *Miner) heartbeat() {
	now := util.MakeTimestamp()
	atomic.StoreInt64(&m.lastBeat, now)
}

func (m *Miner) getLastBeat() int64 {
	return atomic.LoadInt64(&m.lastBeat)
}

func (m *Miner) storeShare(diff int64) {
	now := util.MakeTimestamp()
	m.Lock()
	m.shares[now] += diff
	m.Unlock()
}

func (m *Miner) hashrate(hashrateWindow time.Duration) int64 {
	now := util.MakeTimestamp()
	totalShares := int64(0)
	window := int64(hashrateWindow / time.Millisecond)
	boundary := now - m.startedAt

	if boundary > window {
		boundary = window
	}

	m.Lock()
	for k, v := range m.shares {
		if k < now-86400000 {
			delete(m.shares, k)
		} else if k >= now-window {
			totalShares += v
		}
	}
	m.Unlock()
	return totalShares / boundary
}

func (m *Miner) processShare(s *ProxyServer, t *BlockTemplate, diff string, params []string) bool {
	paramsOrig := params[:]

	hashNoNonce := params[1]
	nonce, err := strconv.ParseUint(strings.Replace(params[0], "0x", "", -1), 16, 64)
	if err != nil {
		log.Printf("Malformed nonce: %v", err)
		return false
	}
	mixDigest := params[2]

	rpc := s.rpc()
	var shareDiff *big.Int

	if !rpc.Pool {
		minerDifficulty, err := strconv.ParseFloat(diff, 64)
		if err != nil {
			log.Println("Malformed difficulty: " + diff)
			minerDifficulty = 5
		}
		diff1 := int64(minerDifficulty * 1000000 * 100)
		shareDiff = big.NewInt(diff1)
	} else {
		shareDiff = util.TargetHexToDiff(t.Target)
	}

	share := Block{
		number:      t.Height,
		hashNoNonce: common.HexToHash(hashNoNonce),
		difficulty:  shareDiff,
		nonce:       nonce,
		mixDigest:   common.HexToHash(mixDigest),
	}

	block := Block{
		number:      t.Height,
		hashNoNonce: common.HexToHash(hashNoNonce),
		difficulty:  t.Difficulty,
		nonce:       nonce,
		mixDigest:   common.HexToHash(mixDigest),
	}

	if hasher.Verify(share) {
		m.heartbeat()
		m.storeShare(shareDiff.Int64())
		atomic.AddUint64(&m.validShares, 1)
		log.Printf("Valid share from %s@%s at difficulty %v", m.Id, m.IP, shareDiff)
	} else {
		atomic.AddUint64(&m.invalidShares, 1)
		log.Printf("Invalid share from %s@%s", m.Id, m.IP)
		return false
	}

	if rpc.Pool || hasher.Verify(block) {
		_, err = rpc.SubmitBlock(paramsOrig)
		if err != nil {
			atomic.AddUint64(&m.rejects, 1)
			atomic.AddUint64(&rpc.Rejects, 1)
			log.Printf("Upstream submission failure on height %v: %v", t.Height, err)
		} else {
			s.fetchBlockTemplate()
			atomic.AddUint64(&m.accepts, 1)
			atomic.AddUint64(&rpc.Accepts, 1)
			atomic.StoreInt64(&rpc.LastSubmissionAt, util.MakeTimestamp())
			log.Printf("Upstream share found by miner %v@%v at height %d", m.Id, m.IP, t.Height)
		}
	}
	return true
}
<commit_msg>Force refresh job only if solo block found<commit_after>package proxy

import (
	"../util"
	"log"
	"math/big"
	"strconv"
	"strings"
	"sync"
	"sync/atomic"
	"time"

	"github.com/ethereum/ethash"
	"github.com/ethereum/go-ethereum/common"
)

var hasher = ethash.New()

type Miner struct {
	sync.RWMutex
	Id            string
	IP            string
	startedAt     int64
	lastBeat      int64
	validShares   uint64
	invalidShares uint64
	accepts       uint64
	rejects       uint64
	shares        map[int64]int64
}

func NewMiner(id, ip string) *Miner {
	miner := &Miner{Id: id, IP: ip, shares: make(map[int64]int64), startedAt: util.MakeTimestamp()}
	return miner
}

func (m *Miner) heartbeat() {
	now := util.MakeTimestamp()
	atomic.StoreInt64(&m.lastBeat, now)
}

func (m *Miner) getLastBeat() int64 {
	return atomic.LoadInt64(&m.lastBeat)
}

func (m *Miner) storeShare(diff int64) {
	now := util.MakeTimestamp()
	m.Lock()
	m.shares[now] += diff
	m.Unlock()
}

func (m *Miner) hashrate(hashrateWindow time.Duration) int64 {
	now := util.MakeTimestamp()
	totalShares := int64(0)
	window := int64(hashrateWindow / time.Millisecond)
	boundary := now - m.startedAt

	if boundary > window {
		boundary = window
	}

	m.Lock()
	for k, v := range m.shares {
		if k < now-86400000 {
			delete(m.shares, k)
		} else if k >= now-window {
			totalShares += v
		}
	}
	m.Unlock()
	return totalShares / boundary
}

func (m *Miner) processShare(s *ProxyServer, t *BlockTemplate, diff string, params []string) bool {
	paramsOrig := params[:]

	hashNoNonce := params[1]
	nonce, err := strconv.ParseUint(strings.Replace(params[0], "0x", "", -1), 16, 64)
	if err != nil {
		log.Printf("Malformed nonce: %v", err)
		return false
	}
	mixDigest := params[2]

	rpc := s.rpc()
	var shareDiff *big.Int

	if !rpc.Pool {
		minerDifficulty, err := strconv.ParseFloat(diff, 64)
		if err != nil {
			log.Println("Malformed difficulty: " + diff)
			minerDifficulty = 5
		}
		diff1 := int64(minerDifficulty * 1000000 * 100)
		shareDiff = big.NewInt(diff1)
	} else {
		shareDiff = util.TargetHexToDiff(t.Target)
	}

	share := Block{
		number:      t.Height,
		hashNoNonce: common.HexToHash(hashNoNonce),
		difficulty:  shareDiff,
		nonce:       nonce,
		mixDigest:   common.HexToHash(mixDigest),
	}

	block := Block{
		number:      t.Height,
		hashNoNonce: common.HexToHash(hashNoNonce),
		difficulty:  t.Difficulty,
		nonce:       nonce,
		mixDigest:   common.HexToHash(mixDigest),
	}

	if hasher.Verify(share) {
		m.heartbeat()
		m.storeShare(shareDiff.Int64())
		atomic.AddUint64(&m.validShares, 1)
		log.Printf("Valid share from %s@%s at difficulty %v", m.Id, m.IP, shareDiff)
	} else {
		atomic.AddUint64(&m.invalidShares, 1)
		log.Printf("Invalid share from %s@%s", m.Id, m.IP)
		return false
	}

	if rpc.Pool || hasher.Verify(block) {
		_, err = rpc.SubmitBlock(paramsOrig)
		if err != nil {
			atomic.AddUint64(&m.rejects, 1)
			atomic.AddUint64(&rpc.Rejects, 1)
			log.Printf("Upstream submission failure on height %v: %v", t.Height, err)
		} else {
			// Solo block found, must refresh job
			if !rpc.Pool {
				s.fetchBlockTemplate()
			}
			atomic.AddUint64(&m.accepts, 1)
			atomic.AddUint64(&rpc.Accepts, 1)
			atomic.StoreInt64(&rpc.LastSubmissionAt, util.MakeTimestamp())
			log.Printf("Upstream share found by miner %v@%v at height %d", m.Id, m.IP, t.Height)
		}
	}
	return true
}
<|endoftext|>