<commit_before>package main

import (
	"bytes"
	"encoding/xml"
	"errors"
	"flag"
	"fmt"
	"github.com/NotaryChains/NotaryChainCode/notaryapi"
	"github.com/conformal/btcrpcclient"
	"github.com/conformal/btcutil"
	"github.com/conformal/btcwire"
	"github.com/firelizzard18/dynrsrc"
	"github.com/firelizzard18/gobundle"
	"github.com/firelizzard18/gocoding"
	"github.com/firelizzard18/gocoding/json"
	"io/ioutil"
	"net/http"
	"net/url"
	"path/filepath"
	"reflect"
	"strconv"
	"strings"
	"sync"
	"time"
	"log"
)

var client *btcrpcclient.Client
var currentAddr *btcutil.Address
var balance int64

var portNumber = flag.Int("p", 8083, "Set the port to listen on")
var blocks []*notaryapi.Block
var blockMutex = &sync.Mutex{}
var tickers [2]*time.Ticker

func watchError(err error) {
	panic(err)
}

func readError(err error) {
	fmt.Println("error: ", err)
}

func initWithBinary() {
	matches, err := filepath.Glob(gobundle.DataFile("store.*.block"))
	if err != nil {
		panic(err)
	}

	blocks = make([]*notaryapi.Block, len(matches))

	num := 0
	for _, match := range matches {
		data, err := ioutil.ReadFile(match)
		if err != nil {
			panic(err)
		}

		block := new(notaryapi.Block)
		err = block.UnmarshalBinary(data)
		if err != nil {
			panic(err)
		}

		blocks[num] = block
		num++
	}
}

func init() {
	gobundle.Setup.Application.Name = "NotaryChains/restapi"
	gobundle.Init()

	dynrsrc.Start(watchError, readError)
	notaryapi.StartDynamic(gobundle.DataFile("html.gwp"), readError)

	initWithBinary()

	fmt.Println("Loaded", len(blocks), "blocks")

	for i := 0; i < len(blocks); i = i + 1 {
		if uint64(i) != blocks[i].BlockID {
			panic(errors.New("BlockID does not equal index"))
		}
	}
	notaryapi.UpdateNextBlockID(uint64(len(blocks)))

	tickers[0] = time.NewTicker(time.Minute * 5)
	tickers[1] = time.NewTicker(time.Hour)

	go func() {
		for _ = range tickers[1].C {
			save()
		}
	}()
}

func main() {

	cadr, err := btcutil.DecodeAddress("mtmkwxRDToguqs6q9dX526wq8xxh8TCbGB", activeNet.Params)

	currentAddr = &cadr

	// Only override the handlers for notifications you care about.
	// Also note most of the handlers will only be called if you register
	// for notifications.  See the documentation of the btcrpcclient
	// NotificationHandlers type for more details about each handler.
	ntfnHandlers := btcrpcclient.NotificationHandlers{
		OnAccountBalance: func(account string, balance btcutil.Amount, confirmed bool) {
		     go newBalance(account, balance, confirmed)
	    },

		OnBlockConnected: func(hash *btcwire.ShaHash, height int32) {
			go newBlock(hash, height)
		},
	}

	// Connect to local btcwallet RPC server using websockets.
	certHomeDir := btcutil.AppDataDir("btcwallet", false)
	certs, err := ioutil.ReadFile(filepath.Join(certHomeDir, "rpc.cert"))
	if err != nil {
		log.Fatal(err)
	}
	connCfg := &btcrpcclient.ConnConfig{
		Host:         "localhost:18332",
		Endpoint:     "ws",
		User:         "testuser",
		Pass:         "notarychain",
		Certificates: certs,
	}

	client, err = btcrpcclient.New(connCfg, &ntfnHandlers)

	if err != nil {
		log.Fatal(err)
		return;
	}else{
        defer shutdown(client)
    }

	flag.Parse()

	defer func() {
		tickers[0].Stop()
		tickers[1].Stop()
		save()
		dynrsrc.Stop()
	}()

	http.HandleFunc("/", serveRESTfulHTTP)
	err = http.ListenAndServe(":"+strconv.Itoa(*portNumber), nil)
	if err != nil {
		panic(err)
	}
}

func save() {
	bcp := make([]*notaryapi.Block, len(blocks))

	blockMutex.Lock()
	copy(bcp, blocks)
	blockMutex.Unlock()

	for i, block := range bcp {
		data, err := block.MarshalBinary()
		if err != nil {
			panic(err)
		}

		err = ioutil.WriteFile(fmt.Sprintf(`app/rest/store.%d.block`, i), data, 0777)
		if err != nil {
			panic(err)
		}
	}
}

func serveRESTfulHTTP(w http.ResponseWriter, r *http.Request) {
	var resource interface{}
	var err *notaryapi.Error
	var buf bytes.Buffer

	path, method, accept, form, err := parse(r)

	defer func() {
		switch accept {
		case "text":
			w.Header().Set("Content-Type", "text/plain; charset=utf-8")

		case "json":
			w.Header().Set("Content-Type", "application/json; charset=utf-8")

		case "xml":
			w.Header().Set("Content-Type", "application/xml; charset=utf-8")

		case "html":
			w.Header().Set("Content-Type", "text/html; charset=utf-8")
		}

		if err != nil {
			var r *notaryapi.Error

			buf.Reset()
			r = notaryapi.Marshal(err, accept, &buf, false)
			if r != nil {
				err = r
			}
			w.WriteHeader(err.HTTPCode)
		}

		buf.WriteTo(w)
		w.Write([]byte("\n\n"))
	}()

	switch method {
	case "GET":
		resource, err = find(path)

	case "POST":
		if len(path) != 1 {
			err = notaryapi.CreateError(notaryapi.ErrorBadMethod, `POST can only be used in the root context: /v1`)
			return
		}

		resource, err = post("/"+strings.Join(path, "/"), form)

	default:
		err = notaryapi.CreateError(notaryapi.ErrorBadMethod, fmt.Sprintf(`The HTTP %s method is not supported`, method))
		return
	}

	if err != nil {
		resource = err
	}

	alt := false
	for _, s := range form["byref"] {
		b, err := strconv.ParseBool(s)
		if err == nil {
			alt = b
			break
		}
	}

	err = notaryapi.Marshal(resource, accept, &buf, alt)
}

var blockPtrType = reflect.TypeOf((*notaryapi.Block)(nil)).Elem()

func post(context string, form url.Values) (interface{}, *notaryapi.Error) {
	newEntry := notaryapi.NewDataEntry([]byte{})
	format, data := form.Get("format"), form.Get("data")

	switch format {
	case "", "json":
		reader := gocoding.ReadString(data)
		err := json.Unmarshal(reader, newEntry)
		if err != nil {
			return nil, notaryapi.CreateError(notaryapi.ErrorJSONUnmarshal, err.Error())
		}

	case "xml":
		err := xml.Unmarshal([]byte(data), newEntry)
		if err != nil {
			return nil, notaryapi.CreateError(notaryapi.ErrorXMLUnmarshal, err.Error())
		}

	default:
		return nil, notaryapi.CreateError(notaryapi.ErrorUnsupportedUnmarshal, fmt.Sprintf(`The format "%s" is not supported`, format))
	}

	if newEntry == nil {
		return nil, notaryapi.CreateError(notaryapi.ErrorInternal, `Entity to be POSTed is nil`)
	}

	newEntry.StampTime()

	blockMutex.Lock()
	err := blocks[len(blocks)-1].AddEntry(newEntry)
	blockMutex.Unlock()

	if err != nil {
		return nil, notaryapi.CreateError(notaryapi.ErrorInternal, fmt.Sprintf(`Error while adding Entity to Block: %s`, err.Error()))
	}

	return newEntry, nil
}
<commit_msg>Other bug fixes Both bugfixes involved decoding Signatures and actually using the code for that<commit_after>package main

import (
	"bytes"
	"encoding/xml"
	"errors"
	"flag"
	"fmt"
	"github.com/NotaryChains/NotaryChainCode/notaryapi"
	"github.com/conformal/btcrpcclient"
	"github.com/conformal/btcutil"
	"github.com/conformal/btcwire"
	"github.com/firelizzard18/dynrsrc"
	"github.com/firelizzard18/gobundle"
	"github.com/firelizzard18/gocoding"
	"io/ioutil"
	"net/http"
	"net/url"
	"path/filepath"
	"reflect"
	"strconv"
	"strings"
	"sync"
	"time"
	"log"
)

var client *btcrpcclient.Client
var currentAddr *btcutil.Address
var balance int64

var portNumber = flag.Int("p", 8083, "Set the port to listen on")
var blocks []*notaryapi.Block
var blockMutex = &sync.Mutex{}
var tickers [2]*time.Ticker

func watchError(err error) {
	panic(err)
}

func readError(err error) {
	fmt.Println("error: ", err)
}

func initWithBinary() {
	matches, err := filepath.Glob(gobundle.DataFile("store.*.block"))
	if err != nil {
		panic(err)
	}

	blocks = make([]*notaryapi.Block, len(matches))

	num := 0
	for _, match := range matches {
		data, err := ioutil.ReadFile(match)
		if err != nil {
			panic(err)
		}

		block := new(notaryapi.Block)
		err = block.UnmarshalBinary(data)
		if err != nil {
			panic(err)
		}

		blocks[num] = block
		num++
	}
}

func init() {
	gobundle.Setup.Application.Name = "NotaryChains/restapi"
	gobundle.Init()

	dynrsrc.Start(watchError, readError)
	notaryapi.StartDynamic(gobundle.DataFile("html.gwp"), readError)

	initWithBinary()

	fmt.Println("Loaded", len(blocks), "blocks")

	for i := 0; i < len(blocks); i = i + 1 {
		if uint64(i) != blocks[i].BlockID {
			panic(errors.New("BlockID does not equal index"))
		}
	}
	notaryapi.UpdateNextBlockID(uint64(len(blocks)))

	tickers[0] = time.NewTicker(time.Minute * 5)
	tickers[1] = time.NewTicker(time.Hour)

	go func() {
		for _ = range tickers[1].C {
			save()
		}
	}()
}

func main() {

	cadr, err := btcutil.DecodeAddress("mtmkwxRDToguqs6q9dX526wq8xxh8TCbGB", activeNet.Params)

	currentAddr = &cadr

	// Only override the handlers for notifications you care about.
	// Also note most of the handlers will only be called if you register
	// for notifications.  See the documentation of the btcrpcclient
	// NotificationHandlers type for more details about each handler.
	ntfnHandlers := btcrpcclient.NotificationHandlers{
		OnAccountBalance: func(account string, balance btcutil.Amount, confirmed bool) {
		     go newBalance(account, balance, confirmed)
	    },

		OnBlockConnected: func(hash *btcwire.ShaHash, height int32) {
			go newBlock(hash, height)
		},
	}

	// Connect to local btcwallet RPC server using websockets.
	certHomeDir := btcutil.AppDataDir("btcwallet", false)
	certs, err := ioutil.ReadFile(filepath.Join(certHomeDir, "rpc.cert"))
	if err != nil {
		log.Fatal(err)
	}
	connCfg := &btcrpcclient.ConnConfig{
		Host:         "localhost:18332",
		Endpoint:     "ws",
		User:         "testuser",
		Pass:         "notarychain",
		Certificates: certs,
	}

	client, err = btcrpcclient.New(connCfg, &ntfnHandlers)

	if err != nil {
		log.Fatal(err)
		return;
	}else{
        defer shutdown(client)
    }

	flag.Parse()

	defer func() {
		tickers[0].Stop()
		tickers[1].Stop()
		save()
		dynrsrc.Stop()
	}()

	http.HandleFunc("/", serveRESTfulHTTP)
	err = http.ListenAndServe(":"+strconv.Itoa(*portNumber), nil)
	if err != nil {
		panic(err)
	}
}

func save() {
	bcp := make([]*notaryapi.Block, len(blocks))

	blockMutex.Lock()
	copy(bcp, blocks)
	blockMutex.Unlock()

	for i, block := range bcp {
		data, err := block.MarshalBinary()
		if err != nil {
			panic(err)
		}

		err = ioutil.WriteFile(fmt.Sprintf(`app/rest/store.%d.block`, i), data, 0777)
		if err != nil {
			panic(err)
		}
	}
}

func serveRESTfulHTTP(w http.ResponseWriter, r *http.Request) {
	var resource interface{}
	var err *notaryapi.Error
	var buf bytes.Buffer

	path, method, accept, form, err := parse(r)

	defer func() {
		switch accept {
		case "text":
			w.Header().Set("Content-Type", "text/plain; charset=utf-8")

		case "json":
			w.Header().Set("Content-Type", "application/json; charset=utf-8")

		case "xml":
			w.Header().Set("Content-Type", "application/xml; charset=utf-8")

		case "html":
			w.Header().Set("Content-Type", "text/html; charset=utf-8")
		}

		if err != nil {
			var r *notaryapi.Error

			buf.Reset()
			r = notaryapi.Marshal(err, accept, &buf, false)
			if r != nil {
				err = r
			}
			w.WriteHeader(err.HTTPCode)
		}

		buf.WriteTo(w)
		w.Write([]byte("\n\n"))
	}()

	switch method {
	case "GET":
		resource, err = find(path)

	case "POST":
		if len(path) != 1 {
			err = notaryapi.CreateError(notaryapi.ErrorBadMethod, `POST can only be used in the root context: /v1`)
			return
		}

		resource, err = post("/"+strings.Join(path, "/"), form)

	default:
		err = notaryapi.CreateError(notaryapi.ErrorBadMethod, fmt.Sprintf(`The HTTP %s method is not supported`, method))
		return
	}

	if err != nil {
		resource = err
	}

	alt := false
	for _, s := range form["byref"] {
		b, err := strconv.ParseBool(s)
		if err == nil {
			alt = b
			break
		}
	}

	err = notaryapi.Marshal(resource, accept, &buf, alt)
}

var blockPtrType = reflect.TypeOf((*notaryapi.Block)(nil)).Elem()

func post(context string, form url.Values) (interface{}, *notaryapi.Error) {
	newEntry := notaryapi.NewDataEntry([]byte{})
	format, data := form.Get("format"), form.Get("data")

	switch format {
	case "", "json":
		reader := gocoding.ReadString(data)
		err := notaryapi.UnmarshalJSON(reader, newEntry)
		if err != nil {
			return nil, notaryapi.CreateError(notaryapi.ErrorJSONUnmarshal, err.Error())
		}

	case "xml":
		err := xml.Unmarshal([]byte(data), newEntry)
		if err != nil {
			return nil, notaryapi.CreateError(notaryapi.ErrorXMLUnmarshal, err.Error())
		}

	default:
		return nil, notaryapi.CreateError(notaryapi.ErrorUnsupportedUnmarshal, fmt.Sprintf(`The format "%s" is not supported`, format))
	}

	if newEntry == nil {
		return nil, notaryapi.CreateError(notaryapi.ErrorInternal, `Entity to be POSTed is nil`)
	}

	newEntry.StampTime()

	blockMutex.Lock()
	err := blocks[len(blocks)-1].AddEntry(newEntry)
	blockMutex.Unlock()

	if err != nil {
		return nil, notaryapi.CreateError(notaryapi.ErrorInternal, fmt.Sprintf(`Error while adding Entity to Block: %s`, err.Error()))
	}

	return newEntry, nil
}
<|endoftext|>


<commit_before>package uuid

/****************
 * Date: 16/02/14
 * Time: 11:29 AM
 ***************/

import (
	"fmt"
	"log"
	"net/url"
	"testing"
)

var (
	goLang Name = "https://google.com/golang.org?q=golang"
)

const (
	generate = 10000
)

func TestUUID_NewV1(t *testing.T) {
	u := NewV1()
	if u.Version() != 1 {
		t.Errorf("Expected correct version %d, but got %d", 1, u.Version())
	}
	if u.Variant() != ReservedRFC4122 {
		t.Errorf("Expected RFC4122 variant %x, but got %x", ReservedRFC4122, u.Variant())
	}
	if !parseUUIDRegex.MatchString(u.String()) {
		t.Errorf("Expected string representation to be valid, given: %s", u.String())
	}
}

func TestUUID_NewV1Bulk(t *testing.T) {
	for i := 0; i < generate; i++ {
		o := NewV1()
	}
}

// Tests NewV3
func TestUUID_NewV3(t *testing.T) {
	u := NewV3(NamespaceURL, goLang)
	if u.Version() != 3 {
		t.Errorf("Expected correct version %d, but got %d", 3, u.Version())
	}
	if u.Variant() != ReservedRFC4122 {
		t.Errorf("Expected RFC4122 variant %x, but got %x", ReservedRFC4122, u.Variant())
	}
	if !parseUUIDRegex.MatchString(u.String()) {
		t.Errorf("Expected string representation to be valid, given: %s", u.String())
	}
	ur, _ := url.Parse(string(goLang))

	// Same NS same name MUST be equal
	u2 := NewV3(NamespaceURL, ur)
	if !Equal(u2, u) {
		t.Errorf("Expected UUIDs generated with same namespace and name to equal but got: %s and %s", u2, u)
	}

	// Different NS same name MUST NOT be equal
	u3 := NewV3(NamespaceDNS, ur)
	if Equal(u3, u) {
		t.Errorf("Expected UUIDs generated with different namespace and same name to be different but got: %s and %s", u3, u)
	}

	// Same NS different name MUST NOT be equal
	u4 := NewV3(NamespaceURL, u)
	if Equal(u4, u) {
		t.Errorf("Expected UUIDs generated with the same namespace and different names to be different but got: %s and %s", u4, u)
	}

	ids := []UUID{
		u, u2, u3, u4,
	}
	for j, id := range ids {
		i := NewV3(NamespaceURL, NewName(string(j), id))
		if Equal(id, i) {
			t.Errorf("Expected UUIDs generated with the same namespace and different names to be different but got: %s and %s", id, i)
		}
	}
}

func TestUUID_NewV3Bulk(t *testing.T) {
	for i := 0; i < generate; i++ {
		NewV3(NamespaceDNS, goLang)
	}
}

func TestUUID_NewV4(t *testing.T) {
	u := NewV4()
	if u.Version() != 4 {
		t.Errorf("Expected correct version %d, but got %d", 4, u.Version())
	}
	if u.Variant() != ReservedRFC4122 {
		t.Errorf("Expected RFC4122 variant %x, but got %x", ReservedRFC4122, u.Variant())
	}
	if !parseUUIDRegex.MatchString(u.String()) {
		t.Errorf("Expected string representation to be valid, given: %s", u.String())
	}
}

func TestUUID_NewV4Bulk(t *testing.T) {
	for i := 0; i < generate; i++ {
		NewV4()
	}
}

// Tests NewV5
func TestUUID_NewV5(t *testing.T) {
	u := NewV5(NamespaceURL, goLang)
	if u.Version() != 5 {
		t.Errorf("Expected correct version %d, but got %d", 5, u.Version())
	}
	if u.Variant() != ReservedRFC4122 {
		t.Errorf("Expected RFC4122 variant %x, but got %x", ReservedRFC4122, u.Variant())
	}
	if !parseUUIDRegex.MatchString(u.String()) {
		t.Errorf("Expected string representation to be valid, given: %s", u.String())
	}
	ur, _ := url.Parse(string(goLang))

	// Same NS same name MUST be equal
	u2 := NewV5(NamespaceURL, ur)
	if !Equal(u2, u) {
		t.Errorf("Expected UUIDs generated with same namespace and name to equal but got: %s and %s", u2, u)
	}

	// Different NS same name MUST NOT be equal
	u3 := NewV5(NamespaceDNS, ur)
	if Equal(u3, u) {
		t.Errorf("Expected UUIDs generated with different namespace and same name to be different but got: %s and %s", u3, u)
	}

	// Same NS different name MUST NOT be equal
	u4 := NewV5(NamespaceURL, u)
	if Equal(u4, u) {
		t.Errorf("Expected UUIDs generated with the same namespace and different names to be different but got: %s and %s", u4, u)
	}

	ids := []UUID{
		u, u2, u3, u4,
	}
	for j, id := range ids {
		i := NewV5(NamespaceURL, NewName(string(j), id))
		if Equal(id, i) {
			t.Errorf("Expected UUIDs generated with the same namespace and different names to be different but got: %s and %s", id, i)
		}
	}
}

func TestUUID_NewV5Bulk(t *testing.T) {
	for i := 0; i < generate; i++ {
		NewV5(NamespaceDNS, goLang)
	}
}

// A small test to test uniqueness across all UUIDs created
func TestUUID_EachIsUnique(t *testing.T) {
	s := 1000
	ids := make([]UUID, s)
	for i := 0; i < s; i++ {
		u := NewV1()
		ids[i] = u
		for j := 0; j < i; j++ {
			if Equal(ids[j], u) {
				t.Error("Should not create the same V1 UUID", u, ids[j])
			}
		}
	}
	ids = make([]UUID, s)
	for i := 0; i < s; i++ {
		u := NewV3(NamespaceDNS, NewName(string(i), Name(goLang)))
		ids[i] = u
		for j := 0; j < i; j++ {
			if Equal(ids[j], u) {
				t.Error("Should not create the same V3 UUID", u, ids[j])
			}
		}
	}
	ids = make([]UUID, s)
	for i := 0; i < s; i++ {
		u := NewV4()
		ids[i] = u
		for j := 0; j < i; j++ {
			if Equal(ids[j], u) {
				t.Error("Should not create the same V4 UUID", u, ids[j])
			}
		}
	}
	ids = make([]UUID, s)
	for i := 0; i < s; i++ {
		u := NewV5(NamespaceDNS, NewName(string(i), Name(goLang)))
		ids[i] = u
		for j := 0; j < i; j++ {
			if Equal(ids[j], u) {
				t.Error("Should not create the same V5 UUID", u, ids[j])
			}
		}
	}
}

// Not really a test but used for visual verification of the defaults
func UUID_NamespaceDefaults() {
	fmt.Println(NamespaceDNS)
	fmt.Println(NamespaceURL)
	fmt.Println(NamespaceOID)
	fmt.Println(NamespaceX500)
}
<commit_msg>Fix log verbosity in tests<commit_after>package uuid

/****************
 * Date: 16/02/14
 * Time: 11:29 AM
 ***************/

import (
	"fmt"
	"net/url"
	"testing"
)

var (
	goLang Name = "https://google.com/golang.org?q=golang"
)

const (
	generate = 10000
)

func TestUUID_NewV1(t *testing.T) {
	u := NewV1()
	if u.Version() != 1 {
		t.Errorf("Expected correct version %d, but got %d", 1, u.Version())
	}
	if u.Variant() != ReservedRFC4122 {
		t.Errorf("Expected RFC4122 variant %x, but got %x", ReservedRFC4122, u.Variant())
	}
	if !parseUUIDRegex.MatchString(u.String()) {
		t.Errorf("Expected string representation to be valid, given: %s", u.String())
	}
}

func TestUUID_NewV1Bulk(t *testing.T) {
	for i := 0; i < generate; i++ {
		o := NewV1()
	}
}

// Tests NewV3
func TestUUID_NewV3(t *testing.T) {
	u := NewV3(NamespaceURL, goLang)
	if u.Version() != 3 {
		t.Errorf("Expected correct version %d, but got %d", 3, u.Version())
	}
	if u.Variant() != ReservedRFC4122 {
		t.Errorf("Expected RFC4122 variant %x, but got %x", ReservedRFC4122, u.Variant())
	}
	if !parseUUIDRegex.MatchString(u.String()) {
		t.Errorf("Expected string representation to be valid, given: %s", u.String())
	}
	ur, _ := url.Parse(string(goLang))

	// Same NS same name MUST be equal
	u2 := NewV3(NamespaceURL, ur)
	if !Equal(u2, u) {
		t.Errorf("Expected UUIDs generated with same namespace and name to equal but got: %s and %s", u2, u)
	}

	// Different NS same name MUST NOT be equal
	u3 := NewV3(NamespaceDNS, ur)
	if Equal(u3, u) {
		t.Errorf("Expected UUIDs generated with different namespace and same name to be different but got: %s and %s", u3, u)
	}

	// Same NS different name MUST NOT be equal
	u4 := NewV3(NamespaceURL, u)
	if Equal(u4, u) {
		t.Errorf("Expected UUIDs generated with the same namespace and different names to be different but got: %s and %s", u4, u)
	}

	ids := []UUID{
		u, u2, u3, u4,
	}
	for j, id := range ids {
		i := NewV3(NamespaceURL, NewName(string(j), id))
		if Equal(id, i) {
			t.Errorf("Expected UUIDs generated with the same namespace and different names to be different but got: %s and %s", id, i)
		}
	}
}

func TestUUID_NewV3Bulk(t *testing.T) {
	for i := 0; i < generate; i++ {
		NewV3(NamespaceDNS, goLang)
	}
}

func TestUUID_NewV4(t *testing.T) {
	u := NewV4()
	if u.Version() != 4 {
		t.Errorf("Expected correct version %d, but got %d", 4, u.Version())
	}
	if u.Variant() != ReservedRFC4122 {
		t.Errorf("Expected RFC4122 variant %x, but got %x", ReservedRFC4122, u.Variant())
	}
	if !parseUUIDRegex.MatchString(u.String()) {
		t.Errorf("Expected string representation to be valid, given: %s", u.String())
	}
}

func TestUUID_NewV4Bulk(t *testing.T) {
	for i := 0; i < generate; i++ {
		NewV4()
	}
}

// Tests NewV5
func TestUUID_NewV5(t *testing.T) {
	u := NewV5(NamespaceURL, goLang)
	if u.Version() != 5 {
		t.Errorf("Expected correct version %d, but got %d", 5, u.Version())
	}
	if u.Variant() != ReservedRFC4122 {
		t.Errorf("Expected RFC4122 variant %x, but got %x", ReservedRFC4122, u.Variant())
	}
	if !parseUUIDRegex.MatchString(u.String()) {
		t.Errorf("Expected string representation to be valid, given: %s", u.String())
	}
	ur, _ := url.Parse(string(goLang))

	// Same NS same name MUST be equal
	u2 := NewV5(NamespaceURL, ur)
	if !Equal(u2, u) {
		t.Errorf("Expected UUIDs generated with same namespace and name to equal but got: %s and %s", u2, u)
	}

	// Different NS same name MUST NOT be equal
	u3 := NewV5(NamespaceDNS, ur)
	if Equal(u3, u) {
		t.Errorf("Expected UUIDs generated with different namespace and same name to be different but got: %s and %s", u3, u)
	}

	// Same NS different name MUST NOT be equal
	u4 := NewV5(NamespaceURL, u)
	if Equal(u4, u) {
		t.Errorf("Expected UUIDs generated with the same namespace and different names to be different but got: %s and %s", u4, u)
	}

	ids := []UUID{
		u, u2, u3, u4,
	}
	for j, id := range ids {
		i := NewV5(NamespaceURL, NewName(string(j), id))
		if Equal(id, i) {
			t.Errorf("Expected UUIDs generated with the same namespace and different names to be different but got: %s and %s", id, i)
		}
	}
}

func TestUUID_NewV5Bulk(t *testing.T) {
	for i := 0; i < generate; i++ {
		NewV5(NamespaceDNS, goLang)
	}
}

// A small test to test uniqueness across all UUIDs created
func TestUUID_EachIsUnique(t *testing.T) {
	s := 1000
	ids := make([]UUID, s)
	for i := 0; i < s; i++ {
		u := NewV1()
		ids[i] = u
		for j := 0; j < i; j++ {
			if Equal(ids[j], u) {
				t.Error("Should not create the same V1 UUID", u, ids[j])
			}
		}
	}
	ids = make([]UUID, s)
	for i := 0; i < s; i++ {
		u := NewV3(NamespaceDNS, NewName(string(i), Name(goLang)))
		ids[i] = u
		for j := 0; j < i; j++ {
			if Equal(ids[j], u) {
				t.Error("Should not create the same V3 UUID", u, ids[j])
			}
		}
	}
	ids = make([]UUID, s)
	for i := 0; i < s; i++ {
		u := NewV4()
		ids[i] = u
		for j := 0; j < i; j++ {
			if Equal(ids[j], u) {
				t.Error("Should not create the same V4 UUID", u, ids[j])
			}
		}
	}
	ids = make([]UUID, s)
	for i := 0; i < s; i++ {
		u := NewV5(NamespaceDNS, NewName(string(i), Name(goLang)))
		ids[i] = u
		for j := 0; j < i; j++ {
			if Equal(ids[j], u) {
				t.Error("Should not create the same V5 UUID", u, ids[j])
			}
		}
	}
}

// Not really a test but used for visual verification of the defaults
func UUID_NamespaceDefaults() {
	fmt.Println(NamespaceDNS)
	fmt.Println(NamespaceURL)
	fmt.Println(NamespaceOID)
	fmt.Println(NamespaceX500)
}
<|endoftext|>


<commit_before>package river

import (
	"io/ioutil"
	"time"

	"github.com/BurntSushi/toml"
	"github.com/juju/errors"
)

type SourceConfig struct {
	Schema string   `toml:"schema"`
	Tables []string `toml:"tables"`
}

type Config struct {
	MyAddr     string `toml:"my_addr"`
	MyUser     string `toml:"my_user"`
	MyPassword string `toml:"my_pass"`
	MyCharset  string `toml:"my_charset"`
	AllDB      string `toml:"my_alldb"`

	MongoAddr     string `toml:"mongo_addr"`
    MongoUser     string `toml:"mongo_user"`
    MongoPassword string `toml:"mongo_pass"`

	StatAddr string `toml:"stat_addr"`

	ServerID uint32 `toml:"server_id"`
	Flavor   string `toml:"flavor"`
	DataDir  string `toml:"data_dir"`

	DumpExec string `toml:"mysqldump"`

	Sources []SourceConfig `toml:"source"`

	Rules []*Rule `toml:"rule"`

	BulkSize int `toml:"bulk_size"`

	FlushBulkTime TomlDuration `toml:"flush_bulk_time"`
}

func NewConfigWithFile(name string) (*Config, error) {
	data, err := ioutil.ReadFile(name)
	if err != nil {
		return nil, errors.Trace(err)
	}

	return NewConfig(string(data))
}

func NewConfig(data string) (*Config, error) {
	var c Config

	_, err := toml.Decode(data, &c)
	if err != nil {
		return nil, errors.Trace(err)
	}

	return &c, nil
}

type TomlDuration struct {
	time.Duration
}

func (d *TomlDuration) UnmarshalText(text []byte) error {
	var err error
	d.Duration, err = time.ParseDuration(string(text))
	return err
}
<commit_msg>Update config.go<commit_after>package river

import (
	"io/ioutil"
	"time"

	"github.com/BurntSushi/toml"
	"github.com/juju/errors"
)

type SourceConfig struct {
	Schema string   `toml:"schema"`
	Tables []string `toml:"tables"`
}

type Config struct {
	MyAddr     string `toml:"my_addr"`
	MyUser     string `toml:"my_user"`
	MyPassword string `toml:"my_pass"`
	MyCharset  string `toml:"my_charset"`
	AllDB      string `toml:"my_alldb"`

	MongoAddr     string `toml:"mongo_addr"`
	MongoUser     string `toml:"mongo_user"`
	MongoPassword string `toml:"mongo_pass"`

	StatAddr string `toml:"stat_addr"`

	ServerID uint32 `toml:"server_id"`
	Flavor   string `toml:"flavor"`
	DataDir  string `toml:"data_dir"`

	DumpExec string `toml:"mysqldump"`

	Sources []SourceConfig `toml:"source"`

	Rules []*Rule `toml:"rule"`

	BulkSize int `toml:"bulk_size"`

	FlushBulkTime TomlDuration `toml:"flush_bulk_time"`
}

func NewConfigWithFile(name string) (*Config, error) {
	data, err := ioutil.ReadFile(name)
	if err != nil {
		return nil, errors.Trace(err)
	}

	return NewConfig(string(data))
}

func NewConfig(data string) (*Config, error) {
	var c Config

	_, err := toml.Decode(data, &c)
	if err != nil {
		return nil, errors.Trace(err)
	}

	return &c, nil
}

type TomlDuration struct {
	time.Duration
}

func (d *TomlDuration) UnmarshalText(text []byte) error {
	var err error
	d.Duration, err = time.ParseDuration(string(text))
	return err
}
<|endoftext|>


<commit_before>package web

import (
	"encoding/base64"
	"encoding/json"
	"fmt"
	"image/color"
	"net/http"
	"strconv"
	"strings"
	"time"

	"github.com/StackExchange/bosun/_third_party/github.com/MiniProfiler/go/miniprofiler"
	"github.com/StackExchange/bosun/_third_party/github.com/StackExchange/scollector/metadata"
	"github.com/StackExchange/bosun/_third_party/github.com/StackExchange/scollector/opentsdb"
	svg "github.com/StackExchange/bosun/_third_party/github.com/ajstarks/svgo"
	"github.com/StackExchange/bosun/_third_party/github.com/bradfitz/slice"
	"github.com/StackExchange/bosun/_third_party/github.com/gorilla/mux"
	"github.com/StackExchange/bosun/_third_party/github.com/vdobler/chart"
	"github.com/StackExchange/bosun/_third_party/github.com/vdobler/chart/svgg"
	"github.com/StackExchange/bosun/expr"
	"github.com/StackExchange/bosun/expr/parse"
	"github.com/StackExchange/bosun/sched"
)

// Graph takes an OpenTSDB request data structure and queries OpenTSDB. Use the
// json parameter to pass JSON. Use the b64 parameter to pass base64-encoded
// JSON.
func Graph(t miniprofiler.Timer, w http.ResponseWriter, r *http.Request) (interface{}, error) {
	j := []byte(r.FormValue("json"))
	if bs := r.FormValue("b64"); bs != "" {
		b, err := base64.StdEncoding.DecodeString(bs)
		if err != nil {
			return nil, err
		}
		j = b
	}
	if len(j) == 0 {
		return nil, fmt.Errorf("either json or b64 required")
	}
	oreq, err := opentsdb.RequestFromJSON(j)
	if err != nil {
		return nil, err
	}
	ads_v := r.FormValue("autods")
	if ads_v != "" {
		ads_i, err := strconv.Atoi(ads_v)
		if err != nil {
			return nil, err
		}
		if err := oreq.AutoDownsample(ads_i); err != nil {
			return nil, err
		}
	}
	ar := make(map[int]bool)
	for _, v := range r.Form["autorate"] {
		if i, err := strconv.Atoi(v); err == nil {
			ar[i] = true
		}
	}
	queries := make([]string, len(oreq.Queries))
	var start, end string
	if s, ok := oreq.Start.(string); ok && strings.Contains(s, "-ago") {
		start = strings.TrimSuffix(s, "-ago")
	}
	if s, ok := oreq.End.(string); ok && strings.Contains(s, "-ago") {
		end = strings.TrimSuffix(s, "-ago")
	}
	m_units := make(map[string]string)
	for i, q := range oreq.Queries {
		if ar[i] {
			ms := schedule.GetMetadata(q.Metric, nil)
			q.Rate = true
			q.RateOptions = opentsdb.RateOptions{
				Counter:    true,
				ResetValue: 1,
			}
			for _, m := range ms {
				if m.Name == "unit" {
					if v, ok := m.Value.(string); ok {
						m_units[q.Metric] = v
					}
				}
				if m.Name == "rate" {
					switch m.Value {
					case metadata.Gauge:
						q.Rate = false
						q.RateOptions.Counter = false
					case metadata.Rate:
						q.RateOptions.Counter = false
					}
					break
				}
			}
		}
		queries[i] = fmt.Sprintf(`q("%v", "%v", "%v")`, q, start, end)
		if err := schedule.Search.Expand(q); err != nil {
			return nil, err
		}
	}
	var tr opentsdb.ResponseSet
	b, _ := json.MarshalIndent(oreq, "", "  ")
	t.StepCustomTiming("tsdb", "query", string(b), func() {
		tr, err = oreq.Query(schedule.Conf.TsdbHost)
	})
	if err != nil {
		return nil, err
	}
	cs, err := makeChart(tr, m_units)
	if err != nil {
		return nil, err
	}
	if _, present := r.Form["png"]; present {
		c := chart.ScatterChart{
			Title: fmt.Sprintf("%v - %v", oreq.Start, oreq.End),
		}
		c.XRange.Time = true
		for ri, r := range cs {
			pts := make([]chart.EPoint, len(r.Data))
			for idx, v := range r.Data {
				pts[idx].X = v[0]
				pts[idx].Y = v[1]
			}
			slice.Sort(pts, func(i, j int) bool {
				return pts[i].X < pts[j].X
			})
			c.AddData(r.Name, pts, chart.PlotStyleLinesPoints, sched.Autostyle(ri))
		}
		w.Header().Set("Content-Type", "image/svg+xml")
		white := color.RGBA{0xff, 0xff, 0xff, 0xff}
		const width = 800
		const height = 600
		s := svg.New(w)
		s.Start(width, height)
		s.Rect(0, 0, width, height, "fill: #ffffff")
		sgr := svgg.AddTo(s, 0, 0, width, height, "", 12, white)
		c.Plot(sgr)
		s.End()
		return nil, nil
	}
	return struct {
		Queries []string
		Series  []*chartSeries
	}{
		queries,
		cs,
	}, nil
}

func ExprGraph(t miniprofiler.Timer, w http.ResponseWriter, r *http.Request) (interface{}, error) {
	vars := mux.Vars(r)
	bs := vars["bs"]
	b, err := base64.StdEncoding.DecodeString(bs)
	if err != nil {
		return nil, err
	}
	q := string(b)
	if len(q) == 0 {
		return nil, fmt.Errorf("missing expression")
	}
	autods := 1000
	if a := r.FormValue("autods"); a != "" {
		i, err := strconv.Atoi(a)
		if err != nil {
			return nil, err
		}
		autods = i
	}
	now := time.Now().UTC()
	if n := r.FormValue("now"); n != "" {
		i, err := strconv.ParseInt(n, 10, 64)
		if err != nil {
			return nil, err
		}
		now = time.Unix(i, 0).UTC()
	}
	e, err := expr.New(q)
	if err != nil {
		return nil, err
	} else if e.Root.Return() != parse.TYPE_SERIES {
		return nil, fmt.Errorf("egraph: requires an expression that returns a series")
	}
	res, _, err := e.Execute(opentsdb.NewCache(schedule.Conf.TsdbHost, schedule.Conf.ResponseLimit), t, now, autods, false, schedule.Search, schedule.Lookups, nil)
	if err != nil {
		return nil, err
	}
	if err := schedule.ExprSVG(t, w, 800, 600, res.Results, q, now); err != nil {
		return nil, err
	}
	return nil, nil
}

func makeChart(r opentsdb.ResponseSet, m_units map[string]string) ([]*chartSeries, error) {
	var series []*chartSeries
	for _, resp := range r {
		dps := make([][2]float64, 0)
		for k, v := range resp.DPS {
			ki, err := strconv.ParseInt(k, 10, 64)
			if err != nil {
				return nil, err
			}
			dps = append(dps, [2]float64{float64(ki), float64(v)})
		}
		if len(dps) > 0 {
			slice.Sort(dps, func(i, j int) bool {
				return dps[i][0] < dps[j][0]
			})
			name := resp.Metric
			if len(resp.Tags) > 0 {
				name += resp.Tags.String()
			}
			series = append(series, &chartSeries{
				Name: name,
				Data: dps,
				Unit: m_units[resp.Metric],
			})
		}
	}
	return series, nil
}

type chartSeries struct {
	Name string
	Data [][2]float64
	Unit string
}
<commit_msg>Don't allow auto rate with no metadata<commit_after>package web

import (
	"encoding/base64"
	"encoding/json"
	"fmt"
	"image/color"
	"net/http"
	"strconv"
	"strings"
	"time"

	"github.com/StackExchange/bosun/_third_party/github.com/MiniProfiler/go/miniprofiler"
	"github.com/StackExchange/bosun/_third_party/github.com/StackExchange/scollector/metadata"
	"github.com/StackExchange/bosun/_third_party/github.com/StackExchange/scollector/opentsdb"
	svg "github.com/StackExchange/bosun/_third_party/github.com/ajstarks/svgo"
	"github.com/StackExchange/bosun/_third_party/github.com/bradfitz/slice"
	"github.com/StackExchange/bosun/_third_party/github.com/gorilla/mux"
	"github.com/StackExchange/bosun/_third_party/github.com/vdobler/chart"
	"github.com/StackExchange/bosun/_third_party/github.com/vdobler/chart/svgg"
	"github.com/StackExchange/bosun/expr"
	"github.com/StackExchange/bosun/expr/parse"
	"github.com/StackExchange/bosun/sched"
)

// Graph takes an OpenTSDB request data structure and queries OpenTSDB. Use the
// json parameter to pass JSON. Use the b64 parameter to pass base64-encoded
// JSON.
func Graph(t miniprofiler.Timer, w http.ResponseWriter, r *http.Request) (interface{}, error) {
	j := []byte(r.FormValue("json"))
	if bs := r.FormValue("b64"); bs != "" {
		b, err := base64.StdEncoding.DecodeString(bs)
		if err != nil {
			return nil, err
		}
		j = b
	}
	if len(j) == 0 {
		return nil, fmt.Errorf("either json or b64 required")
	}
	oreq, err := opentsdb.RequestFromJSON(j)
	if err != nil {
		return nil, err
	}
	ads_v := r.FormValue("autods")
	if ads_v != "" {
		ads_i, err := strconv.Atoi(ads_v)
		if err != nil {
			return nil, err
		}
		if err := oreq.AutoDownsample(ads_i); err != nil {
			return nil, err
		}
	}
	ar := make(map[int]bool)
	for _, v := range r.Form["autorate"] {
		if i, err := strconv.Atoi(v); err == nil {
			ar[i] = true
		}
	}
	queries := make([]string, len(oreq.Queries))
	var start, end string
	if s, ok := oreq.Start.(string); ok && strings.Contains(s, "-ago") {
		start = strings.TrimSuffix(s, "-ago")
	}
	if s, ok := oreq.End.(string); ok && strings.Contains(s, "-ago") {
		end = strings.TrimSuffix(s, "-ago")
	}
	m_units := make(map[string]string)
Loop:
	for i, q := range oreq.Queries {
		if ar[i] {
			ms := schedule.GetMetadata(q.Metric, nil)
			for _, m := range ms {
				if m.Name == "unit" {
					if v, ok := m.Value.(string); ok {
						m_units[q.Metric] = v
					}
				}
				if m.Name == "rate" {
					switch m.Value {
					case metadata.Gauge:
						// ignore
					case metadata.Rate:
						q.Rate = true
					case metadata.Counter:
						q.Rate = true
						q.RateOptions = opentsdb.RateOptions{
							Counter:    true,
							ResetValue: 1,
						}
					default:
						return nil, fmt.Errorf("unknown metadata rate: %s", m.Value)
					}
					continue Loop
				}
			}
			return nil, fmt.Errorf("no metadata for %s: cannot use auto rate", q.Metric)
		}
		queries[i] = fmt.Sprintf(`q("%v", "%v", "%v")`, q, start, end)
		if err := schedule.Search.Expand(q); err != nil {
			return nil, err
		}
	}
	var tr opentsdb.ResponseSet
	b, _ := json.MarshalIndent(oreq, "", "  ")
	t.StepCustomTiming("tsdb", "query", string(b), func() {
		tr, err = oreq.Query(schedule.Conf.TsdbHost)
	})
	if err != nil {
		return nil, err
	}
	cs, err := makeChart(tr, m_units)
	if err != nil {
		return nil, err
	}
	if _, present := r.Form["png"]; present {
		c := chart.ScatterChart{
			Title: fmt.Sprintf("%v - %v", oreq.Start, oreq.End),
		}
		c.XRange.Time = true
		for ri, r := range cs {
			pts := make([]chart.EPoint, len(r.Data))
			for idx, v := range r.Data {
				pts[idx].X = v[0]
				pts[idx].Y = v[1]
			}
			slice.Sort(pts, func(i, j int) bool {
				return pts[i].X < pts[j].X
			})
			c.AddData(r.Name, pts, chart.PlotStyleLinesPoints, sched.Autostyle(ri))
		}
		w.Header().Set("Content-Type", "image/svg+xml")
		white := color.RGBA{0xff, 0xff, 0xff, 0xff}
		const width = 800
		const height = 600
		s := svg.New(w)
		s.Start(width, height)
		s.Rect(0, 0, width, height, "fill: #ffffff")
		sgr := svgg.AddTo(s, 0, 0, width, height, "", 12, white)
		c.Plot(sgr)
		s.End()
		return nil, nil
	}
	return struct {
		Queries []string
		Series  []*chartSeries
	}{
		queries,
		cs,
	}, nil
}

func ExprGraph(t miniprofiler.Timer, w http.ResponseWriter, r *http.Request) (interface{}, error) {
	vars := mux.Vars(r)
	bs := vars["bs"]
	b, err := base64.StdEncoding.DecodeString(bs)
	if err != nil {
		return nil, err
	}
	q := string(b)
	if len(q) == 0 {
		return nil, fmt.Errorf("missing expression")
	}
	autods := 1000
	if a := r.FormValue("autods"); a != "" {
		i, err := strconv.Atoi(a)
		if err != nil {
			return nil, err
		}
		autods = i
	}
	now := time.Now().UTC()
	if n := r.FormValue("now"); n != "" {
		i, err := strconv.ParseInt(n, 10, 64)
		if err != nil {
			return nil, err
		}
		now = time.Unix(i, 0).UTC()
	}
	e, err := expr.New(q)
	if err != nil {
		return nil, err
	} else if e.Root.Return() != parse.TYPE_SERIES {
		return nil, fmt.Errorf("egraph: requires an expression that returns a series")
	}
	res, _, err := e.Execute(opentsdb.NewCache(schedule.Conf.TsdbHost, schedule.Conf.ResponseLimit), t, now, autods, false, schedule.Search, schedule.Lookups, nil)
	if err != nil {
		return nil, err
	}
	if err := schedule.ExprSVG(t, w, 800, 600, res.Results, q, now); err != nil {
		return nil, err
	}
	return nil, nil
}

func makeChart(r opentsdb.ResponseSet, m_units map[string]string) ([]*chartSeries, error) {
	var series []*chartSeries
	for _, resp := range r {
		dps := make([][2]float64, 0)
		for k, v := range resp.DPS {
			ki, err := strconv.ParseInt(k, 10, 64)
			if err != nil {
				return nil, err
			}
			dps = append(dps, [2]float64{float64(ki), float64(v)})
		}
		if len(dps) > 0 {
			slice.Sort(dps, func(i, j int) bool {
				return dps[i][0] < dps[j][0]
			})
			name := resp.Metric
			if len(resp.Tags) > 0 {
				name += resp.Tags.String()
			}
			series = append(series, &chartSeries{
				Name: name,
				Data: dps,
				Unit: m_units[resp.Metric],
			})
		}
	}
	return series, nil
}

type chartSeries struct {
	Name string
	Data [][2]float64
	Unit string
}
<|endoftext|>


<commit_before>// Copyright (c) 2017 DG Lab
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

// fred project main.go
package main

import (
	"fmt"
	"log"
	"os"
	"os/signal"
	"syscall"
	"time"

	"democonf"
	"rpc"
)

// URL for accessing RPC
var rpcurl string = "http://127.0.0.1:10040"

// ID for accessing RPC
var rpcuser string = "user"

// Password for accessing RPC
var rpcpass string = "pass"

var rpcClient *rpc.Rpc

var interval = 3 * time.Second

var logger *log.Logger

var stop bool = false

func checkgenerate() error {
	var txs []string
	res, err := rpcClient.RequestAndUnmarshalResult(&txs, "getrawmempool")
	if err != nil {
		logger.Printf("Rpc#RequestAndUnmarshalResult error:%v res:%+v", err, res)
		return err
	}
	if len(txs) == 0 {
		return nil
	}
	rpcClient.View = true
	var hashs []string
	res, err = rpcClient.RequestAndUnmarshalResult(&hashs, "generate", 1)
	rpcClient.View = false
	if err != nil {
		logger.Printf("Rpc#RequestAndUnmarshalResult error:%v res:%+v", err, res)
		return err
	}
	return nil
}

func loop() {
	fmt.Println("Loop interval:", interval)
	for {
		time.Sleep(interval)
		err := checkgenerate()
		if err != nil {
			logger.Println("checkgenarate error:", err)
		}
		if stop {
			break
		}
	}
}

func loadConf() {
	conf := democonf.NewDemoConf("fred")
	rpcurl = conf.GetString("rpcurl", rpcurl)
	rpcuser = conf.GetString("rpcuser", rpcuser)
	rpcpass = conf.GetString("rpcpass", rpcpass)
}

func main() {
	logger = log.New(os.Stdout, "Fred:", log.LstdFlags+log.Lshortfile)
	fmt.Println("Fred start")

	loadConf()
	rpcClient = rpc.NewRpc(rpcurl, rpcuser, rpcpass)

	// signal handling (ctrl + c)
	sig := make(chan os.Signal)
	signal.Notify(sig, syscall.SIGINT)
	go func() {
		fmt.Println("signal:", <-sig)
		stop = true
	}()

	loop()

	fmt.Println("Fred stop")
}
<commit_msg>fred fix golint<commit_after>// Copyright (c) 2017 DG Lab
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

// fred project main.go
package main

import (
	"fmt"
	"log"
	"os"
	"os/signal"
	"syscall"
	"time"

	"democonf"
	"rpc"
)

// URL for accessing RPC
var rpcurl = "http://127.0.0.1:10040"

// ID for accessing RPC
var rpcuser = "user"

// Password for accessing RPC
var rpcpass = "pass"

var rpcClient *rpc.Rpc

var interval = 3 * time.Second

var logger *log.Logger

var stop = false

func checkgenerate() error {
	var txs []string
	res, err := rpcClient.RequestAndUnmarshalResult(&txs, "getrawmempool")
	if err != nil {
		logger.Printf("Rpc#RequestAndUnmarshalResult error:%v res:%+v", err, res)
		return err
	}
	if len(txs) == 0 {
		return nil
	}
	rpcClient.View = true
	var hashs []string
	res, err = rpcClient.RequestAndUnmarshalResult(&hashs, "generate", 1)
	rpcClient.View = false
	if err != nil {
		logger.Printf("Rpc#RequestAndUnmarshalResult error:%v res:%+v", err, res)
		return err
	}
	return nil
}

func loop() {
	fmt.Println("Loop interval:", interval)
	for {
		time.Sleep(interval)
		err := checkgenerate()
		if err != nil {
			logger.Println("checkgenarate error:", err)
		}
		if stop {
			break
		}
	}
}

func loadConf() {
	conf := democonf.NewDemoConf("fred")
	rpcurl = conf.GetString("rpcurl", rpcurl)
	rpcuser = conf.GetString("rpcuser", rpcuser)
	rpcpass = conf.GetString("rpcpass", rpcpass)
}

func main() {
	logger = log.New(os.Stdout, "Fred:", log.LstdFlags+log.Lshortfile)
	fmt.Println("Fred start")

	loadConf()
	rpcClient = rpc.NewRpc(rpcurl, rpcuser, rpcpass)

	// signal handling (ctrl + c)
	sig := make(chan os.Signal)
	signal.Notify(sig, syscall.SIGINT)
	go func() {
		fmt.Println("signal:", <-sig)
		stop = true
	}()

	loop()

	fmt.Println("Fred stop")
}
<|endoftext|>


<commit_before>package seven5

import (
	"fmt"
	"github.com/coocood/qbs"
	"log"
	"net/http"
	"net/url"
	"os"
	"strings"
)

type QbsStore struct {
	Q      *qbs.Qbs
	Policy *QbsDefaultOrmTransactionPolicy
	Dsn    *qbs.DataSourceName
}

// NewQbsStore creates an instance of the object that is used to represent a
// connection to the database via the Qbs ORM.
// NewQbsStore creates a *QbsStore from a DSN; DSNs can be created
// directly with ParamsToDSN or from the environment EnvironmentUrlToDSN (via
// the DATABASE_URL environment var).
func NewQbsStore(dsn *qbs.DataSourceName) *QbsStore {
	result := &QbsStore{}
	result.Dsn = dsn
	result.Policy = NewQbsDefaultOrmTransactionPolicy()
	qbs.RegisterWithDataSourceName(result.Dsn)
	q, err := qbs.GetQbs()
	if err != nil {
		panic(err)
	}
	result.Q = q
	return result
}

//ParamsToDSN allows you to create a DSN directly from some values. This
//is useful for testing.  If driver or user is "", the default driver and
//user are used.
func ParamsToDSN(dbname string, driver string, user string) *qbs.DataSourceName {
	if driver == "" {
		driver = "postgres"
	}
	if user == "" {
		if u := os.Getenv("PGUSER"); u != "" {
			user = u
		} else {
			user = "postgres"
		}
	}
	dsn := &qbs.DataSourceName{}
	dsn.DbName = dbname
	dsn.Dialect = StringToDialect(driver)
	dsn.Username = user
	log.Printf("DSN for DB: %+v\n", dsn)
	return dsn
}

//This function returns the datasource name for the DATABASE_URL
//in the environment. If the value cannot be found, this panics.
func EnvironmentUrlToDSN() *qbs.DataSourceName {
	db := os.Getenv("DATABASE_URL")
	if db == "" {
		panic("no DATABASE_URL found, cannot connect to a *QbsStore")
	}
	log.Printf("found a database:%s", db)
	u, err := url.Parse(db)
	if err != nil {
		panic(fmt.Sprintf("unable to parse database URL: %s", err))
	}
	log.Printf("got a url %+v\n", u)
	dsn := &qbs.DataSourceName{}
	dsn.DbName = u.Path[1:]
	dsn.Host = u.Host
	if strings.Index(u.Host, ":") != -1 {
		pair := strings.Split(u.Host, ":")
		if len(pair) != 2 {
			panic("badly formed host:port")
		}
		dsn.Host = pair[0]
		dsn.Port = pair[1]
	}
	p, set := u.User.Password()
	if set {
		dsn.Password = p
	}
	dsn.Username = u.User.Username()
	dsn.Dialect = StringToDialect(u.Scheme)
	return dsn
}

//StringToDialect returns an sql dialect for use with QBS given a string
//name.  IF the name is not known, this code panics.
func StringToDialect(n string) qbs.Dialect {
	switch n {
	case "postgres":
		return qbs.NewPostgres()
	case "sqlite3":
		return qbs.NewSqlite3()
	}
	panic(fmt.Sprintf("unable to deal with db dialact provided %s", n))
}

//NewQbsDefaultOrmTransactionPolicy returns a new default implementation of policy
//that will Rollback transactions if there is a 400 or 500 returned by the client. It will also
//rollback if a non-http error is returned, or if the called code panics.  After rolling
//back the transaction, it allows the panic to continue.
func NewQbsDefaultOrmTransactionPolicy() *QbsDefaultOrmTransactionPolicy {
	return &QbsDefaultOrmTransactionPolicy{}
}

//StartTransaction returns a new qbs object after creating the transaction.
func (self *QbsDefaultOrmTransactionPolicy) StartTransaction(q *qbs.Qbs) *qbs.Qbs {
	if err := q.Begin(); err != nil {
		panic(err)
	}
	return q
}

//HandleResult determines whether or not the transaction provided should be rolled
//back or if it should be committed.  It rolls back when the result value is
//a non-http error, if it is an Error and the status code is >= 400.
func (self *QbsDefaultOrmTransactionPolicy) HandleResult(tx *qbs.Qbs, value interface{}, err error) (interface{}, error) {
	if err != nil {
		switch e := err.(type) {
		case *Error:
			if e.StatusCode >= 400 {
				rerr := tx.Rollback()
				if rerr != nil {
					return nil, rerr
				}
			}
		default:
			rerr := tx.Rollback()
			if rerr != nil {
				return nil, rerr
			}
			return nil, HTTPError(http.StatusInternalServerError, fmt.Sprintf("%v", err))
		}
	} else {
		if cerr := tx.Commit(); cerr != nil {
			return nil, cerr
		}
	}
	return value, err
}

//HandlePanic rolls back the transiction provided and then panics again.
func (self *QbsDefaultOrmTransactionPolicy) HandlePanic(tx *qbs.Qbs, err interface{}) (interface{}, error) {
	log.Printf("got panic, rolling back and returning 500 to client (%v)\n", err)
	if rerr := tx.Rollback(); rerr != nil {
		panic(rerr)
	}
	return nil, HTTPError(http.StatusInternalServerError, fmt.Sprintf("panic: %v", err))
}

//QbsDefaultOrmTransactionPolicy is a simple implementation of transaction
//policy that is sufficient for most applications.
type QbsDefaultOrmTransactionPolicy struct {
}
<commit_msg>removed stray log message<commit_after>package seven5

import (
	"fmt"
	"github.com/coocood/qbs"
	"log"
	"net/http"
	"net/url"
	"os"
	"strings"
)

type QbsStore struct {
	Q      *qbs.Qbs
	Policy *QbsDefaultOrmTransactionPolicy
	Dsn    *qbs.DataSourceName
}

// NewQbsStore creates an instance of the object that is used to represent a
// connection to the database via the Qbs ORM.
// NewQbsStore creates a *QbsStore from a DSN; DSNs can be created
// directly with ParamsToDSN or from the environment EnvironmentUrlToDSN (via
// the DATABASE_URL environment var).
func NewQbsStore(dsn *qbs.DataSourceName) *QbsStore {
	result := &QbsStore{}
	result.Dsn = dsn
	result.Policy = NewQbsDefaultOrmTransactionPolicy()
	qbs.RegisterWithDataSourceName(result.Dsn)
	q, err := qbs.GetQbs()
	if err != nil {
		panic(err)
	}
	result.Q = q
	return result
}

//ParamsToDSN allows you to create a DSN directly from some values. This
//is useful for testing.  If driver or user is "", the default driver and
//user are used.
func ParamsToDSN(dbname string, driver string, user string) *qbs.DataSourceName {
	if driver == "" {
		driver = "postgres"
	}
	if user == "" {
		if u := os.Getenv("PGUSER"); u != "" {
			user = u
		} else {
			user = "postgres"
		}
	}
	dsn := &qbs.DataSourceName{}
	dsn.DbName = dbname
	dsn.Dialect = StringToDialect(driver)
	dsn.Username = user
	log.Printf("DSN for DB: %+v\n", dsn)
	return dsn
}

//This function returns the datasource name for the DATABASE_URL
//in the environment. If the value cannot be found, this panics.
func EnvironmentUrlToDSN() *qbs.DataSourceName {
	db := os.Getenv("DATABASE_URL")
	if db == "" {
		panic("no DATABASE_URL found, cannot connect to a *QbsStore")
	}
	u, err := url.Parse(db)
	if err != nil {
		panic(fmt.Sprintf("unable to parse database URL: %s", err))
	}
	log.Printf("DATABASE_URL found, connecting to %+v\n", u)
	dsn := &qbs.DataSourceName{}
	dsn.DbName = u.Path[1:]
	dsn.Host = u.Host
	if strings.Index(u.Host, ":") != -1 {
		pair := strings.Split(u.Host, ":")
		if len(pair) != 2 {
			panic("badly formed host:port")
		}
		dsn.Host = pair[0]
		dsn.Port = pair[1]
	}
	p, set := u.User.Password()
	if set {
		dsn.Password = p
	}
	dsn.Username = u.User.Username()
	dsn.Dialect = StringToDialect(u.Scheme)
	return dsn
}

//StringToDialect returns an sql dialect for use with QBS given a string
//name.  IF the name is not known, this code panics.
func StringToDialect(n string) qbs.Dialect {
	switch n {
	case "postgres":
		return qbs.NewPostgres()
	case "sqlite3":
		return qbs.NewSqlite3()
	}
	panic(fmt.Sprintf("unable to deal with db dialact provided %s", n))
}

//NewQbsDefaultOrmTransactionPolicy returns a new default implementation of policy
//that will Rollback transactions if there is a 400 or 500 returned by the client. It will also
//rollback if a non-http error is returned, or if the called code panics.  After rolling
//back the transaction, it allows the panic to continue.
func NewQbsDefaultOrmTransactionPolicy() *QbsDefaultOrmTransactionPolicy {
	return &QbsDefaultOrmTransactionPolicy{}
}

//StartTransaction returns a new qbs object after creating the transaction.
func (self *QbsDefaultOrmTransactionPolicy) StartTransaction(q *qbs.Qbs) *qbs.Qbs {
	if err := q.Begin(); err != nil {
		panic(err)
	}
	return q
}

//HandleResult determines whether or not the transaction provided should be rolled
//back or if it should be committed.  It rolls back when the result value is
//a non-http error, if it is an Error and the status code is >= 400.
func (self *QbsDefaultOrmTransactionPolicy) HandleResult(tx *qbs.Qbs, value interface{}, err error) (interface{}, error) {
	if err != nil {
		switch e := err.(type) {
		case *Error:
			if e.StatusCode >= 400 {
				rerr := tx.Rollback()
				if rerr != nil {
					return nil, rerr
				}
			}
		default:
			rerr := tx.Rollback()
			if rerr != nil {
				return nil, rerr
			}
			return nil, HTTPError(http.StatusInternalServerError, fmt.Sprintf("%v", err))
		}
	} else {
		if cerr := tx.Commit(); cerr != nil {
			return nil, cerr
		}
	}
	return value, err
}

//HandlePanic rolls back the transiction provided and then panics again.
func (self *QbsDefaultOrmTransactionPolicy) HandlePanic(tx *qbs.Qbs, err interface{}) (interface{}, error) {
	log.Printf("got panic, rolling back and returning 500 to client (%v)\n", err)
	if rerr := tx.Rollback(); rerr != nil {
		panic(rerr)
	}
	return nil, HTTPError(http.StatusInternalServerError, fmt.Sprintf("panic: %v", err))
}

//QbsDefaultOrmTransactionPolicy is a simple implementation of transaction
//policy that is sufficient for most applications.
type QbsDefaultOrmTransactionPolicy struct {
}
<|endoftext|>


<commit_before>package dclupgrade

import (
	"context"
	"fmt"

	sdk "github.com/cosmos/cosmos-sdk/types"
	sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
	upgradetypes "github.com/cosmos/cosmos-sdk/x/upgrade/types"
	"github.com/stretchr/testify/require"
	testconstants "github.com/zigbee-alliance/distributed-compliance-ledger/integration_tests/constants"
	test_dclauth "github.com/zigbee-alliance/distributed-compliance-ledger/integration_tests/grpc_rest/dclauth"
	"github.com/zigbee-alliance/distributed-compliance-ledger/integration_tests/utils"
	dclauthtypes "github.com/zigbee-alliance/distributed-compliance-ledger/x/dclauth/types"
	dclupgradetypes "github.com/zigbee-alliance/distributed-compliance-ledger/x/dclupgrade/types"
)

func NewMsgProposeUpgrade(signer string, name string, height int64, info string) *dclupgradetypes.MsgProposeUpgrade {
	return &dclupgradetypes.MsgProposeUpgrade{
		Creator: signer,
		Plan: upgradetypes.Plan{
			Name:   name,
			Height: height,
			Info:   info,
		},
	}
}

func NewMsgApproveUpgrade(signer string, name string) *dclupgradetypes.MsgApproveUpgrade {
	return &dclupgradetypes.MsgApproveUpgrade{
		Creator: signer,
		Name:    name,
	}
}

func ProposeUpgrade(
	suite *utils.TestSuite,
	msg *dclupgradetypes.MsgProposeUpgrade,
	signerName string,
	signerAccount *dclauthtypes.Account,
) (*sdk.TxResponse, error) {
	msg.Creator = suite.GetAddress(signerName).String()
	return suite.BuildAndBroadcastTx([]sdk.Msg{msg}, signerName, signerAccount)
}

func ApproveUpgrade(
	suite *utils.TestSuite,
	msg *dclupgradetypes.MsgApproveUpgrade,
	signerName string,
	signerAccount *dclauthtypes.Account,
) (*sdk.TxResponse, error) {
	msg.Creator = suite.GetAddress(signerName).String()
	return suite.BuildAndBroadcastTx([]sdk.Msg{msg}, signerName, signerAccount)
}

func GetProposedUpgrade(
	suite *utils.TestSuite,
	name string,
) (*dclupgradetypes.ProposedUpgrade, error) {
	var res dclupgradetypes.ProposedUpgrade

	if suite.Rest {
		var resp dclupgradetypes.QueryGetProposedUpgradeResponse
		err := suite.QueryREST(fmt.Sprintf("/dcl/dclupgrade/proposed-upgrades/%s", name), &resp)
		if err != nil {
			return nil, err
		}
		res = resp.GetProposedUpgrade()
	} else {
		grpcConn := suite.GetGRPCConn()
		defer grpcConn.Close()

		// This creates a gRPC client to query the x/dclauth service.
		dclupgradeClient := dclupgradetypes.NewQueryClient(grpcConn)
		resp, err := dclupgradeClient.ProposedUpgrade(
			context.Background(),
			&dclupgradetypes.QueryGetProposedUpgradeRequest{Name: name},
		)
		if err != nil {
			return nil, err
		}
		res = resp.GetProposedUpgrade()
	}

	return &res, nil
}

func GetApprovedUpgrade(
	suite *utils.TestSuite,
	name string,
) (*dclupgradetypes.ApprovedUpgrade, error) {
	var res dclupgradetypes.ApprovedUpgrade

	if suite.Rest {
		var resp dclupgradetypes.QueryGetApprovedUpgradeResponse
		err := suite.QueryREST(fmt.Sprintf("/dcl/dclupgrade/approved-upgrades/%s", name), &resp)
		if err != nil {
			return nil, err
		}
		res = resp.GetApprovedUpgrade()
	} else {
		grpcConn := suite.GetGRPCConn()
		defer grpcConn.Close()

		// This creates a gRPC client to query the x/dclauth service.
		dclupgradeClient := dclupgradetypes.NewQueryClient(grpcConn)
		resp, err := dclupgradeClient.ApprovedUpgrade(
			context.Background(),
			&dclupgradetypes.QueryGetApprovedUpgradeRequest{Name: name},
		)
		if err != nil {
			return nil, err
		}
		res = resp.GetApprovedUpgrade()
	}

	return &res, nil
}

func GetProposedUpgrades(suite *utils.TestSuite) (res []dclupgradetypes.ProposedUpgrade, err error) {
	if suite.Rest {
		var resp dclupgradetypes.QueryAllProposedUpgradeResponse
		err := suite.QueryREST("/dcl/dclupgrade/proposed-upgrades", &resp)
		if err != nil {
			return nil, err
		}
		res = resp.GetProposedUpgrade()
	} else {
		grpcConn := suite.GetGRPCConn()
		defer grpcConn.Close()

		// This creates a gRPC client to query the x/dclauth service.
		dclupgradeClient := dclupgradetypes.NewQueryClient(grpcConn)
		resp, err := dclupgradeClient.ProposedUpgradeAll(
			context.Background(),
			&dclupgradetypes.QueryAllProposedUpgradeRequest{},
		)
		if err != nil {
			return nil, err
		}
		res = resp.GetProposedUpgrade()
	}

	return res, nil
}

func GetApprovedUpgrades(suite *utils.TestSuite) (res []dclupgradetypes.ApprovedUpgrade, err error) {
	if suite.Rest {
		var resp dclupgradetypes.QueryAllApprovedUpgradeResponse
		err := suite.QueryREST("/dcl/dclupgrade/approved-upgrades", &resp)
		if err != nil {
			return nil, err
		}
		res = resp.GetApprovedUpgrade()
	} else {
		grpcConn := suite.GetGRPCConn()
		defer grpcConn.Close()

		// This creates a gRPC client to query the x/dclauth service.
		dclupgradeClient := dclupgradetypes.NewQueryClient(grpcConn)
		resp, err := dclupgradeClient.ApprovedUpgradeAll(
			context.Background(),
			&dclupgradetypes.QueryAllApprovedUpgradeRequest{},
		)
		if err != nil {
			return nil, err
		}
		res = resp.GetApprovedUpgrade()
	}

	return res, nil
}

func DCLUpgradeDemo(suite *utils.TestSuite) {
	// Alice and Bob are predefined Trustees
	aliceName := testconstants.AliceAccount
	aliceKeyInfo, err := suite.Kr.Key(aliceName)
	require.NoError(suite.T, err)
	aliceAccount, err := test_dclauth.GetAccount(suite, aliceKeyInfo.GetAddress())
	require.NoError(suite.T, err)

	bobName := testconstants.BobAccount
	bobKeyInfo, err := suite.Kr.Key(bobName)
	require.NoError(suite.T, err)
	bobAccount, err := test_dclauth.GetAccount(suite, bobKeyInfo.GetAddress())
	require.NoError(suite.T, err)

	// trustee proposes upgrade
	proposeUpgradeMsg := NewMsgProposeUpgrade(aliceAccount.Address, utils.RandString(), 100000, utils.RandString())
	_, err = suite.BuildAndBroadcastTx([]sdk.Msg{proposeUpgradeMsg}, aliceName, aliceAccount)
	require.NoError(suite.T, err)

	// Check upgrade is proposed
	proposedUpgrade, err := GetProposedUpgrade(suite, proposeUpgradeMsg.Plan.Name)
	require.NoError(suite.T, err)
	require.Equal(suite.T, proposeUpgradeMsg.Creator, proposedUpgrade.Creator)
	require.Equal(suite.T, proposeUpgradeMsg.Plan, proposedUpgrade.Plan)

	// Get all proposed upgrades
	_, err = GetProposedUpgrades(suite)
	require.NoError(suite.T, err)

	// Get all approved upgrades
	approvedUpgrades, err := GetApprovedUpgrades(suite)
	require.NoError(suite.T, err)
	require.NotContains(suite.T, approvedUpgrades, proposedUpgrade)

	// another trustee approves upgrade
	approveUpgradeMsg := NewMsgApproveUpgrade(bobAccount.Address, proposeUpgradeMsg.Plan.Name)
	_, err = suite.BuildAndBroadcastTx([]sdk.Msg{approveUpgradeMsg}, bobName, bobAccount)
	require.NoError(suite.T, err)

	// Check upgrade is approved
	approvedUpgrade, err := GetApprovedUpgrade(suite, proposeUpgradeMsg.Plan.Name)
	require.NoError(suite.T, err)
	require.Equal(suite.T, proposeUpgradeMsg.Creator, approvedUpgrade.Creator)
	require.Equal(suite.T, proposeUpgradeMsg.Plan, approvedUpgrade.Plan)

	// Get all proposed upgrades
	proposedUpgrades, err := GetProposedUpgrades(suite)
	require.NoError(suite.T, err)
	require.NotContains(suite.T, proposedUpgrades, proposedUpgrade)

	// Get all approved upgrades
	approvedUpgrades, err = GetApprovedUpgrades(suite)
	require.NoError(suite.T, err)
	require.Contains(suite.T, approvedUpgrades, *approvedUpgrade)
}

/* Error cases */

func ProposeUpgradeByNonTrustee(suite *utils.TestSuite) {
	// Alice and Bob are predefined Trustees
	aliceName := testconstants.AliceAccount
	aliceKeyInfo, err := suite.Kr.Key(aliceName)
	require.NoError(suite.T, err)
	aliceAccount, err := test_dclauth.GetAccount(suite, aliceKeyInfo.GetAddress())
	require.NoError(suite.T, err)

	bobName := testconstants.BobAccount
	bobKeyInfo, err := suite.Kr.Key(bobName)
	require.NoError(suite.T, err)
	bobAccount, err := test_dclauth.GetAccount(suite, bobKeyInfo.GetAddress())
	require.NoError(suite.T, err)

	// register new account without Trustee role
	nonTrusteeAccountName := utils.RandString()
	nonTrusteeAccount := test_dclauth.CreateAccount(
		suite,
		nonTrusteeAccountName,
		dclauthtypes.AccountRoles{dclauthtypes.CertificationCenter},
		1,
		aliceName,
		aliceAccount,
		bobName,
		bobAccount,
		testconstants.Info,
	)
	require.NotContains(suite.T, nonTrusteeAccount.Roles, dclupgradetypes.UpgradeApprovalRole)

	// try to add proposeUpgradeMsg
	proposeUpgradeMsg := NewMsgProposeUpgrade(nonTrusteeAccount.Address, utils.RandString(), 100000, utils.RandString())
	_, err = suite.BuildAndBroadcastTx([]sdk.Msg{proposeUpgradeMsg}, nonTrusteeAccountName, nonTrusteeAccount)
	require.Error(suite.T, err)
	require.ErrorIs(suite.T, sdkerrors.ErrUnauthorized, err)
}

func ApproveUpgradeByNonTrustee(suite *utils.TestSuite) {
	// Alice and Bob are predefined Trustees
	aliceName := testconstants.AliceAccount
	aliceKeyInfo, err := suite.Kr.Key(aliceName)
	require.NoError(suite.T, err)
	aliceAccount, err := test_dclauth.GetAccount(suite, aliceKeyInfo.GetAddress())
	require.NoError(suite.T, err)

	bobName := testconstants.BobAccount
	bobKeyInfo, err := suite.Kr.Key(bobName)
	require.NoError(suite.T, err)
	bobAccount, err := test_dclauth.GetAccount(suite, bobKeyInfo.GetAddress())
	require.NoError(suite.T, err)

	// register new account without Trustee role
	nonTrusteeAccountName := utils.RandString()
	nonTrusteeAccount := test_dclauth.CreateAccount(
		suite,
		nonTrusteeAccountName,
		dclauthtypes.AccountRoles{dclauthtypes.CertificationCenter},
		1,
		aliceName,
		aliceAccount,
		bobName,
		bobAccount,
		testconstants.Info,
	)
	require.NotContains(suite.T, nonTrusteeAccount.Roles, dclupgradetypes.UpgradeApprovalRole)

	// propose upgrade
	proposeUpgradeMsg := NewMsgProposeUpgrade(aliceAccount.Address, utils.RandString(), 100000, utils.RandString())
	_, err = suite.BuildAndBroadcastTx([]sdk.Msg{proposeUpgradeMsg}, aliceName, aliceAccount)
	require.NoError(suite.T, err)

	// try to approve upgrade
	approveUpgradeMsg := NewMsgApproveUpgrade(nonTrusteeAccount.Address, proposeUpgradeMsg.Plan.Name)
	_, err = suite.BuildAndBroadcastTx([]sdk.Msg{approveUpgradeMsg}, nonTrusteeAccountName, nonTrusteeAccount)
	require.Error(suite.T, err)
	require.ErrorIs(suite.T, sdkerrors.ErrUnauthorized, err)
}

func ProposeUpgradeTwice(suite *utils.TestSuite) {
	// Alice and Bob are predefined Trustees
	aliceName := testconstants.AliceAccount
	aliceKeyInfo, err := suite.Kr.Key(aliceName)
	require.NoError(suite.T, err)
	aliceAccount, err := test_dclauth.GetAccount(suite, aliceKeyInfo.GetAddress())
	require.NoError(suite.T, err)

	bobName := testconstants.BobAccount
	bobKeyInfo, err := suite.Kr.Key(bobName)
	require.NoError(suite.T, err)
	_, err = test_dclauth.GetAccount(suite, bobKeyInfo.GetAddress())
	require.NoError(suite.T, err)

	// trustee proposes upgrade
	proposeUpgradeMsg := NewMsgProposeUpgrade(aliceAccount.Address, utils.RandString(), 100000, utils.RandString())
	_, err = suite.BuildAndBroadcastTx([]sdk.Msg{proposeUpgradeMsg}, aliceName, aliceAccount)
	require.NoError(suite.T, err)

	// trustee proposes the same upgrade
	_, err = suite.BuildAndBroadcastTx([]sdk.Msg{proposeUpgradeMsg}, aliceName, aliceAccount)
	require.Error(suite.T, err)
	require.ErrorIs(suite.T, dclupgradetypes.ErrProposedUpgradeAlreadyExists, err)
}
<commit_msg>tests updated<commit_after>package dclupgrade

import (
	"context"
	"fmt"

	sdk "github.com/cosmos/cosmos-sdk/types"
	sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
	upgradetypes "github.com/cosmos/cosmos-sdk/x/upgrade/types"
	"github.com/stretchr/testify/require"
	tmrand "github.com/tendermint/tendermint/libs/rand"
	testconstants "github.com/zigbee-alliance/distributed-compliance-ledger/integration_tests/constants"
	test_dclauth "github.com/zigbee-alliance/distributed-compliance-ledger/integration_tests/grpc_rest/dclauth"
	"github.com/zigbee-alliance/distributed-compliance-ledger/integration_tests/utils"
	dclauthtypes "github.com/zigbee-alliance/distributed-compliance-ledger/x/dclauth/types"
	dclupgradetypes "github.com/zigbee-alliance/distributed-compliance-ledger/x/dclupgrade/types"
)

func NewMsgProposeUpgrade(signer string, name string, height int64, info string) *dclupgradetypes.MsgProposeUpgrade {
	return &dclupgradetypes.MsgProposeUpgrade{
		Creator: signer,
		Plan: upgradetypes.Plan{
			Name:   name,
			Height: height,
			Info:   info,
		},
	}
}

func NewMsgApproveUpgrade(signer string, name string) *dclupgradetypes.MsgApproveUpgrade {
	return &dclupgradetypes.MsgApproveUpgrade{
		Creator: signer,
		Name:    name,
	}
}

func ProposeUpgrade(
	suite *utils.TestSuite,
	msg *dclupgradetypes.MsgProposeUpgrade,
	signerName string,
	signerAccount *dclauthtypes.Account,
) (*sdk.TxResponse, error) {
	msg.Creator = suite.GetAddress(signerName).String()
	return suite.BuildAndBroadcastTx([]sdk.Msg{msg}, signerName, signerAccount)
}

func ApproveUpgrade(
	suite *utils.TestSuite,
	msg *dclupgradetypes.MsgApproveUpgrade,
	signerName string,
	signerAccount *dclauthtypes.Account,
) (*sdk.TxResponse, error) {
	msg.Creator = suite.GetAddress(signerName).String()
	return suite.BuildAndBroadcastTx([]sdk.Msg{msg}, signerName, signerAccount)
}

func GetProposedUpgrade(
	suite *utils.TestSuite,
	name string,
) (*dclupgradetypes.ProposedUpgrade, error) {
	var res dclupgradetypes.ProposedUpgrade

	if suite.Rest {
		var resp dclupgradetypes.QueryGetProposedUpgradeResponse
		err := suite.QueryREST(fmt.Sprintf("/dcl/dclupgrade/proposed-upgrades/%s", name), &resp)
		if err != nil {
			return nil, err
		}
		res = resp.GetProposedUpgrade()
	} else {
		grpcConn := suite.GetGRPCConn()
		defer grpcConn.Close()

		// This creates a gRPC client to query the x/dclauth service.
		dclupgradeClient := dclupgradetypes.NewQueryClient(grpcConn)
		resp, err := dclupgradeClient.ProposedUpgrade(
			context.Background(),
			&dclupgradetypes.QueryGetProposedUpgradeRequest{Name: name},
		)
		if err != nil {
			return nil, err
		}
		res = resp.GetProposedUpgrade()
	}

	return &res, nil
}

func GetApprovedUpgrade(
	suite *utils.TestSuite,
	name string,
) (*dclupgradetypes.ApprovedUpgrade, error) {
	var res dclupgradetypes.ApprovedUpgrade

	if suite.Rest {
		var resp dclupgradetypes.QueryGetApprovedUpgradeResponse
		err := suite.QueryREST(fmt.Sprintf("/dcl/dclupgrade/approved-upgrades/%s", name), &resp)
		if err != nil {
			return nil, err
		}
		res = resp.GetApprovedUpgrade()
	} else {
		grpcConn := suite.GetGRPCConn()
		defer grpcConn.Close()

		// This creates a gRPC client to query the x/dclauth service.
		dclupgradeClient := dclupgradetypes.NewQueryClient(grpcConn)
		resp, err := dclupgradeClient.ApprovedUpgrade(
			context.Background(),
			&dclupgradetypes.QueryGetApprovedUpgradeRequest{Name: name},
		)
		if err != nil {
			return nil, err
		}
		res = resp.GetApprovedUpgrade()
	}

	return &res, nil
}

func GetProposedUpgrades(suite *utils.TestSuite) (res []dclupgradetypes.ProposedUpgrade, err error) {
	if suite.Rest {
		var resp dclupgradetypes.QueryAllProposedUpgradeResponse
		err := suite.QueryREST("/dcl/dclupgrade/proposed-upgrades", &resp)
		if err != nil {
			return nil, err
		}
		res = resp.GetProposedUpgrade()
	} else {
		grpcConn := suite.GetGRPCConn()
		defer grpcConn.Close()

		// This creates a gRPC client to query the x/dclauth service.
		dclupgradeClient := dclupgradetypes.NewQueryClient(grpcConn)
		resp, err := dclupgradeClient.ProposedUpgradeAll(
			context.Background(),
			&dclupgradetypes.QueryAllProposedUpgradeRequest{},
		)
		if err != nil {
			return nil, err
		}
		res = resp.GetProposedUpgrade()
	}

	return res, nil
}

func GetApprovedUpgrades(suite *utils.TestSuite) (res []dclupgradetypes.ApprovedUpgrade, err error) {
	if suite.Rest {
		var resp dclupgradetypes.QueryAllApprovedUpgradeResponse
		err := suite.QueryREST("/dcl/dclupgrade/approved-upgrades", &resp)
		if err != nil {
			return nil, err
		}
		res = resp.GetApprovedUpgrade()
	} else {
		grpcConn := suite.GetGRPCConn()
		defer grpcConn.Close()

		// This creates a gRPC client to query the x/dclauth service.
		dclupgradeClient := dclupgradetypes.NewQueryClient(grpcConn)
		resp, err := dclupgradeClient.ApprovedUpgradeAll(
			context.Background(),
			&dclupgradetypes.QueryAllApprovedUpgradeRequest{},
		)
		if err != nil {
			return nil, err
		}
		res = resp.GetApprovedUpgrade()
	}

	return res, nil
}

func DCLUpgradeDemo(suite *utils.TestSuite) {
	// Alice and Bob are predefined Trustees
	aliceName := testconstants.AliceAccount
	aliceKeyInfo, err := suite.Kr.Key(aliceName)
	require.NoError(suite.T, err)
	aliceAccount, err := test_dclauth.GetAccount(suite, aliceKeyInfo.GetAddress())
	require.NoError(suite.T, err)

	bobName := testconstants.BobAccount
	bobKeyInfo, err := suite.Kr.Key(bobName)
	require.NoError(suite.T, err)
	bobAccount, err := test_dclauth.GetAccount(suite, bobKeyInfo.GetAddress())
	require.NoError(suite.T, err)

	// trustee proposes upgrade
	proposeUpgradeMsg := NewMsgProposeUpgrade(aliceAccount.Address, utils.RandString(), 100000, utils.RandString())
	_, err = suite.BuildAndBroadcastTx([]sdk.Msg{proposeUpgradeMsg}, aliceName, aliceAccount)
	require.NoError(suite.T, err)

	// Check upgrade is proposed
	proposedUpgrade, err := GetProposedUpgrade(suite, proposeUpgradeMsg.Plan.Name)
	require.NoError(suite.T, err)
	require.Equal(suite.T, proposeUpgradeMsg.Creator, proposedUpgrade.Creator)
	require.Equal(suite.T, proposeUpgradeMsg.Plan, proposedUpgrade.Plan)

	// Get all proposed upgrades
	proposedUpgrades, err := GetProposedUpgrades(suite)
	require.NoError(suite.T, err)
	require.Contains(suite.T, proposedUpgrades, *proposedUpgrade)

	// Get approved upgrade
	_, err = GetApprovedUpgrade(suite, proposeUpgradeMsg.Plan.Name)
	suite.AssertNotFound(err)

	// another trustee approves upgrade
	approveUpgradeMsg := NewMsgApproveUpgrade(bobAccount.Address, proposeUpgradeMsg.Plan.Name)
	_, err = suite.BuildAndBroadcastTx([]sdk.Msg{approveUpgradeMsg}, bobName, bobAccount)
	require.NoError(suite.T, err)

	// Check upgrade is approved
	approvedUpgrade, err := GetApprovedUpgrade(suite, proposeUpgradeMsg.Plan.Name)
	require.NoError(suite.T, err)
	require.Equal(suite.T, proposeUpgradeMsg.Creator, approvedUpgrade.Creator)
	require.Equal(suite.T, proposeUpgradeMsg.Plan, approvedUpgrade.Plan)

	// Get all proposed upgrades
	proposedUpgrades, err = GetProposedUpgrades(suite)
	require.NoError(suite.T, err)
	require.NotContains(suite.T, proposedUpgrades, *proposedUpgrade)

	// Get all approved upgrades
	approvedUpgrades, err := GetApprovedUpgrades(suite)
	require.NoError(suite.T, err)
	require.Contains(suite.T, approvedUpgrades, *approvedUpgrade)
}

/* Error cases */

func ProposeUpgradeByNonTrustee(suite *utils.TestSuite) {
	// Alice and Bob are predefined Trustees
	aliceName := testconstants.AliceAccount
	aliceKeyInfo, err := suite.Kr.Key(aliceName)
	require.NoError(suite.T, err)
	aliceAccount, err := test_dclauth.GetAccount(suite, aliceKeyInfo.GetAddress())
	require.NoError(suite.T, err)

	bobName := testconstants.BobAccount
	bobKeyInfo, err := suite.Kr.Key(bobName)
	require.NoError(suite.T, err)
	bobAccount, err := test_dclauth.GetAccount(suite, bobKeyInfo.GetAddress())
	require.NoError(suite.T, err)

	for _, role := range []dclauthtypes.AccountRole{
		dclauthtypes.CertificationCenter,
		dclauthtypes.Vendor,
		dclauthtypes.NodeAdmin,
	} {
		// register new account without Trustee role
		nonTrusteeAccountName := utils.RandString()
		nonTrusteeAccount := test_dclauth.CreateAccount(
			suite,
			nonTrusteeAccountName,
			dclauthtypes.AccountRoles{role},
			int32(tmrand.Uint16()+1),
			aliceName,
			aliceAccount,
			bobName,
			bobAccount,
			testconstants.Info,
		)

		// try to add proposeUpgradeMsg
		proposeUpgradeMsg := NewMsgProposeUpgrade(nonTrusteeAccount.Address, utils.RandString(), 100000, utils.RandString())
		_, err = suite.BuildAndBroadcastTx([]sdk.Msg{proposeUpgradeMsg}, nonTrusteeAccountName, nonTrusteeAccount)
		require.Error(suite.T, err)
		require.ErrorIs(suite.T, err, sdkerrors.ErrUnauthorized)
	}
}

func ApproveUpgradeByNonTrustee(suite *utils.TestSuite) {
	// Alice and Bob are predefined Trustees
	aliceName := testconstants.AliceAccount
	aliceKeyInfo, err := suite.Kr.Key(aliceName)
	require.NoError(suite.T, err)
	aliceAccount, err := test_dclauth.GetAccount(suite, aliceKeyInfo.GetAddress())
	require.NoError(suite.T, err)

	bobName := testconstants.BobAccount
	bobKeyInfo, err := suite.Kr.Key(bobName)
	require.NoError(suite.T, err)
	bobAccount, err := test_dclauth.GetAccount(suite, bobKeyInfo.GetAddress())
	require.NoError(suite.T, err)

	// propose upgrade
	proposeUpgradeMsg := NewMsgProposeUpgrade(aliceAccount.Address, utils.RandString(), 100000, utils.RandString())
	_, err = suite.BuildAndBroadcastTx([]sdk.Msg{proposeUpgradeMsg}, aliceName, aliceAccount)
	require.NoError(suite.T, err)

	for _, role := range []dclauthtypes.AccountRole{
		dclauthtypes.CertificationCenter,
		dclauthtypes.Vendor,
		dclauthtypes.NodeAdmin,
	} {
		// register new account without Trustee role
		nonTrusteeAccountName := utils.RandString()
		nonTrusteeAccount := test_dclauth.CreateAccount(
			suite,
			nonTrusteeAccountName,
			dclauthtypes.AccountRoles{role},
			int32(tmrand.Uint16()+1),
			aliceName,
			aliceAccount,
			bobName,
			bobAccount,
			testconstants.Info,
		)

		// try to approve upgrade
		approveUpgradeMsg := NewMsgApproveUpgrade(nonTrusteeAccount.Address, proposeUpgradeMsg.Plan.Name)
		_, err = suite.BuildAndBroadcastTx([]sdk.Msg{approveUpgradeMsg}, nonTrusteeAccountName, nonTrusteeAccount)
		require.Error(suite.T, err)
		require.ErrorIs(suite.T, err, sdkerrors.ErrUnauthorized)
	}
}

func ProposeUpgradeTwice(suite *utils.TestSuite) {
	// Alice is a predefined Trustee
	aliceName := testconstants.AliceAccount
	aliceKeyInfo, err := suite.Kr.Key(aliceName)
	require.NoError(suite.T, err)
	aliceAccount, err := test_dclauth.GetAccount(suite, aliceKeyInfo.GetAddress())
	require.NoError(suite.T, err)

	// trustee proposes upgrade
	proposeUpgradeMsg := NewMsgProposeUpgrade(aliceAccount.Address, utils.RandString(), 100000, utils.RandString())
	_, err = suite.BuildAndBroadcastTx([]sdk.Msg{proposeUpgradeMsg}, aliceName, aliceAccount)
	require.NoError(suite.T, err)

	// trustee proposes the same upgrade
	_, err = suite.BuildAndBroadcastTx([]sdk.Msg{proposeUpgradeMsg}, aliceName, aliceAccount)
	require.Error(suite.T, err)
	require.ErrorIs(suite.T, err, dclupgradetypes.ErrProposedUpgradeAlreadyExists)
}
<|endoftext|>


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

// The query packages implement Vanadium's query capabilities.
//
// syncql:     This package is used by client's of a Vanadium
//             component that supports queries.
//             It includes:
//                 - ResultStream (which is the product of
//                   executing a query).
//                 - The error messages that could be returned
//                   from performing a query.
//                 - A function to parse an error to get the
//                   offset into a query that caused the error.
//             syncql does does not include the Exec function
//             as that must be provided by the component that
//             supports queries.
//
// engine:     This is the query engine.  A component that
//             supports queries calls the Exec function in this
//             package.
//
// datasource: This package contains the interfaces that a
//             Vanadium component must implement in order to
//             use the query engine.
//
// internal:   This is internal code which implements queries.
//             Its sole client is the engine package.
package query
<commit_msg>v.io/v23: Fixing the doc formatting and small wording changes.<commit_after>// Copyright 2015 The Vanadium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// The query packages implement Vanadium's query capabilities.
//
// The syncql package is used by clients of a Vanadium
// component that supports queries.  It includes: ResultStream
// (which is the product of executing a query), the error messages
// that could be returned from performing a query, and a function
// to parse an error to get the offset into a query that
// caused the error.  syncql does not include the Exec function
// as that must be provided by the component that
// supports queries.
//
// The engine package implements the query engine. A component
// that supports queries calls the Exec function in this package.
//
// The datasource package contains the interfaces that a
// Vanadium component must implement in order to
// use the query engine.
//
// The internal package provides a reference implementation of the
// queries package.
// Its sole client is the engine package.
package query
<|endoftext|>


<commit_before>package main

import (
	"os"

	"github.com/urfave/cli"

	"github.com/dirk/quickhook/context"
	"github.com/dirk/quickhook/hooks"
)

func main() {
	context, err := setupContextInWd()
	if err != nil {
		panic(err)
	}

	app := cli.NewApp()

	app.Commands = []cli.Command{
		{
			Name:  "hook",
			Usage: "run a hook",
			Action: func(c *cli.Context) error {
				return cli.ShowSubcommandHelp(c)
			},
			Subcommands: []cli.Command{
				cli.Command{
					Name: "pre-commit",
					Action: func(c *cli.Context) error {
						err := hooks.PreCommit(context)
						if err != nil { panic(err) }
						return nil
					},
				},
			},
		},
	}

	app.Run(os.Args)
}

// Set up `Context` in current working directory
func setupContextInWd() (*context.Context, error) {
	wd, err := os.Getwd()
	if err != nil {
		return nil, err
	}

	return context.NewContext(wd)
}
<commit_msg>Improve usage in CLI<commit_after>package main

import (
	"os"

	"github.com/urfave/cli"

	"github.com/dirk/quickhook/context"
	"github.com/dirk/quickhook/hooks"
)

const version = "0.1.1"

func main() {
	context, err := setupContextInWd()
	if err != nil {
		panic(err)
	}

	app := cli.NewApp()
	app.Name = "quickhook"
	app.Version = version
	app.Usage = "Git hook runner"

	app.Commands = []cli.Command{
		{
			Name:  "hook",
			Usage: "Run a hook",
			Action: func(c *cli.Context) error {
				return cli.ShowSubcommandHelp(c)
			},
			Subcommands: []cli.Command{
				cli.Command{
					Name: "pre-commit",
					Action: func(c *cli.Context) error {
						err := hooks.PreCommit(context)
						if err != nil { panic(err) }
						return nil
					},
				},
			},
		},
	}

	app.Run(os.Args)
}

// Set up `Context` in current working directory
func setupContextInWd() (*context.Context, error) {
	wd, err := os.Getwd()
	if err != nil {
		return nil, err
	}

	return context.NewContext(wd)
}
<|endoftext|>


<commit_before>package concurrentsort

import (
	"runtime"
	"sync"
)

/*
	Interface and common types
*/

// QuickSortable is an interface which must be satisfied in order to call QuickSort()
type QuickSortable interface {
	Len() int
	LessOrEqual(i, j int) bool
	Swap(i, j int)
	GetSubSliceTo(i int) QuickSortable
	GetSubSliceFrom(j int) QuickSortable
}

// IntSlice attaches the methods of Interface to []int, sorting in increasing order.
type IntSlice []int

func (p IntSlice) Len() int {
	return len(p)
}
func (p IntSlice) LessOrEqual(i, j int) bool {
	return p[i] <= p[j]
}
func (p IntSlice) Swap(i, j int) {
	p[i], p[j] = p[j], p[i]
}
func (p IntSlice) GetSubSliceTo(i int) QuickSortable {
	return p[:i]
}
func (p IntSlice) GetSubSliceFrom(i int) QuickSortable {
	return p[i:]
}

/*
	Quick Sorting
*/

type quickSortConcurrentManager struct {
	availableWorkers int
	access           sync.Mutex
	rdvpoint         sync.WaitGroup
}

func (qscm *quickSortConcurrentManager) isAWorkerAvailable() bool {
	defer qscm.access.Unlock()
	qscm.access.Lock()
	if qscm.availableWorkers > 0 {
		qscm.availableWorkers--
		qscm.rdvpoint.Add(1)
		return true
	}
	return false
}

func (qscm *quickSortConcurrentManager) workerDone() {
	defer qscm.access.Unlock()
	qscm.access.Lock()
	qscm.availableWorkers++
	qscm.rdvpoint.Done()
}

// QuickSort sorts data using the quicksort algo distributed on nbWorkers goroutines
// forceConcurrentLimit allows to override the value computed to set the minimum slice size for concurrency.
// Set to nil to allow auto computation. Check quicksort.bench package for more informations.
func QuickSort(data QuickSortable, nbWorkers int, forceConcurrentLimit *int) {
	// Init the concurrent manager
	manager := quickSortConcurrentManager{availableWorkers: nbWorkers - 1} // the current goroutine is the first worker
	// And the concurrent "forking" limit
	var concurrentLimit int
	if forceConcurrentLimit != nil {
		concurrentLimit = *forceConcurrentLimit
	} else {
		// How many real cores will be involved in the process ? (at max, if 1 goroutine == 1 thread, which is not always the case)
		cpuCoresInvolved := nbWorkers
		if nbWorkers > runtime.NumCPU() {
			cpuCoresInvolved = runtime.NumCPU()
		}
		// Use this value to compute ideal slice limit for concurrency
		concurrentLimit = int(float64(cpuCoresInvolved) * 1.5) // 1.5 magik number: check quicksort.bench package
		if concurrentLimit < 2 {
			concurrentLimit = 2 // quickSort() will only run if len > 1, so no need to start a goroutine for function doing nothing
		}
	}
	// Start worker 1
	quickSort(data, concurrentLimit, &manager)
	manager.rdvpoint.Wait()
}

func quickSort(data QuickSortable, sliceMinSize int, manager *quickSortConcurrentManager) {
	// Start sorting
	if data.Len() > 1 {
		// Select a pivot on the current slice
		pivotIndex := quickSortSelectPivot(data)
		// Partition it and recover new pivot index
		pivotIndex = quickSortPartition(data, pivotIndex)
		// Prepare the subslices
		firstSlice := data.GetSubSliceTo(pivotIndex)
		secondSlice := data.GetSubSliceFrom(pivotIndex + 1)
		// Are some of them eligible to concurrency ?
		firstSideLaunched := false
		secondSideLaunched := false
		if firstSlice.Len() >= sliceMinSize && manager.isAWorkerAvailable() {
			go func() {
				defer manager.workerDone()
				quickSort(firstSlice, sliceMinSize, manager)
			}()
			firstSideLaunched = true
		} else if secondSlice.Len() >= sliceMinSize && manager.isAWorkerAvailable() {
			go func() {
				defer manager.workerDone()
				quickSort(secondSlice, sliceMinSize, manager)
			}()
			secondSideLaunched = true
		}
		// Sort within the same goroutine
		if !firstSideLaunched {
			quickSort(firstSlice, sliceMinSize, manager)
		}
		if !secondSideLaunched {
			quickSort(secondSlice, sliceMinSize, manager)
		}
	}
}

func quickSortPartition(data QuickSortable, pivotIndex int) (newPivotIndex int) {
	// Swap the pivot to the end
	lastIndex := data.Len() - 1
	data.Swap(pivotIndex, lastIndex)
	pivotIndex = lastIndex
	// Launch the quicksort on this part of the slice
	var j int
	for i := 0; i < pivotIndex; i++ {
		if data.LessOrEqual(i, pivotIndex) {
			data.Swap(i, j)
			j++
		}
	}
	// Swap the pivot to the index where all data on the left are less of equals to him
	data.Swap(j, pivotIndex)
	// Return the new pivot index (now at index j)
	return j
}

func quickSortSelectPivot(data QuickSortable) (pivot int) {
	// Classical variant: take last index
	return data.Len() - 1
	// Check with median of medians ?
}
<commit_msg>quicksort - allow nbWorkers autoset<commit_after>package concurrentsort

import (
	"runtime"
	"sync"
)

/*
	Interface and common types
*/

// QuickSortable is an interface which must be satisfied in order to call QuickSort()
type QuickSortable interface {
	Len() int
	LessOrEqual(i, j int) bool
	Swap(i, j int)
	GetSubSliceTo(i int) QuickSortable
	GetSubSliceFrom(j int) QuickSortable
}

// IntSlice attaches the methods of Interface to []int, sorting in increasing order.
type IntSlice []int

func (p IntSlice) Len() int {
	return len(p)
}
func (p IntSlice) LessOrEqual(i, j int) bool {
	return p[i] <= p[j]
}
func (p IntSlice) Swap(i, j int) {
	p[i], p[j] = p[j], p[i]
}
func (p IntSlice) GetSubSliceTo(i int) QuickSortable {
	return p[:i]
}
func (p IntSlice) GetSubSliceFrom(i int) QuickSortable {
	return p[i:]
}

/*
	Quick Sorting
*/

type quickSortConcurrentManager struct {
	availableWorkers int
	access           sync.Mutex
	rdvpoint         sync.WaitGroup
}

func (qscm *quickSortConcurrentManager) isAWorkerAvailable() bool {
	defer qscm.access.Unlock()
	qscm.access.Lock()
	if qscm.availableWorkers > 0 {
		qscm.availableWorkers--
		qscm.rdvpoint.Add(1)
		return true
	}
	return false
}

func (qscm *quickSortConcurrentManager) workerDone() {
	defer qscm.access.Unlock()
	qscm.access.Lock()
	qscm.availableWorkers++
	qscm.rdvpoint.Done()
}

// QuickSort sorts data using the quicksort algo distributed on nbWorkers goroutines
// nbWorkers will be used to spawn goroutines when needed. If nbworkers < 1, runtime.NumCPU() will be used instead.
// forceConcurrentLimit allows to override the value computed to set the minimum slice size for concurrency.
// Set to nil to allow auto computation. Check quicksort.bench package for more informations.
func QuickSort(data QuickSortable, nbWorkers int, forceConcurrentLimit *int) {
	// Init the concurrent manager
	if nbWorkers < 1 {
		nbWorkers = runtime.NumCPU()
	}
	manager := quickSortConcurrentManager{availableWorkers: nbWorkers - 1} // the current goroutine is the first worker
	// And the concurrent "forking" limit
	var concurrentLimit int
	if forceConcurrentLimit != nil {
		concurrentLimit = *forceConcurrentLimit
	} else {
		// How many real cores will be involved in the process ? (at max, if 1 goroutine == 1 thread, which is not always the case)
		cpuCoresInvolved := nbWorkers
		if nbWorkers > runtime.NumCPU() {
			cpuCoresInvolved = runtime.NumCPU()
		}
		// Use this value to compute ideal slice limit for concurrency
		concurrentLimit = int(float64(cpuCoresInvolved) * 1.5) // 1.5 magik number: check quicksort.bench package
		if concurrentLimit < 2 {
			concurrentLimit = 2 // quickSort() will only run if len > 1, so no need to start a goroutine for function doing nothing
		}
	}
	// Start worker 1
	quickSort(data, concurrentLimit, &manager)
	manager.rdvpoint.Wait()
}

func quickSort(data QuickSortable, sliceMinSize int, manager *quickSortConcurrentManager) {
	// Start sorting
	if data.Len() > 1 {
		// Select a pivot on the current slice
		pivotIndex := quickSortSelectPivot(data)
		// Partition it and recover new pivot index
		pivotIndex = quickSortPartition(data, pivotIndex)
		// Prepare the subslices
		firstSlice := data.GetSubSliceTo(pivotIndex)
		secondSlice := data.GetSubSliceFrom(pivotIndex + 1)
		// Are some of them eligible to concurrency ?
		firstSideLaunched := false
		secondSideLaunched := false
		if firstSlice.Len() >= sliceMinSize && manager.isAWorkerAvailable() {
			go func() {
				defer manager.workerDone()
				quickSort(firstSlice, sliceMinSize, manager)
			}()
			firstSideLaunched = true
		} else if secondSlice.Len() >= sliceMinSize && manager.isAWorkerAvailable() {
			go func() {
				defer manager.workerDone()
				quickSort(secondSlice, sliceMinSize, manager)
			}()
			secondSideLaunched = true
		}
		// Sort within the same goroutine
		if !firstSideLaunched {
			quickSort(firstSlice, sliceMinSize, manager)
		}
		if !secondSideLaunched {
			quickSort(secondSlice, sliceMinSize, manager)
		}
	}
}

func quickSortPartition(data QuickSortable, pivotIndex int) (newPivotIndex int) {
	// Swap the pivot to the end
	lastIndex := data.Len() - 1
	data.Swap(pivotIndex, lastIndex)
	pivotIndex = lastIndex
	// Launch the quicksort on this part of the slice
	var j int
	for i := 0; i < pivotIndex; i++ {
		if data.LessOrEqual(i, pivotIndex) {
			data.Swap(i, j)
			j++
		}
	}
	// Swap the pivot to the index where all data on the left are less of equals to him
	data.Swap(j, pivotIndex)
	// Return the new pivot index (now at index j)
	return j
}

func quickSortSelectPivot(data QuickSortable) (pivot int) {
	// Classical variant: take last index
	return data.Len() - 1
	// Check with median of medians ?
}
<|endoftext|>


<commit_before>// Copyright (C) 2017 Damon Revoe. All rights reserved.
// Use of this source code is governed by the MIT
// license, which can be found in the LICENSE file.

package main

import (
	"errors"
	"io/ioutil"
	"os"
	"path/filepath"

	"gopkg.in/yaml.v2"
)

type workspaceParams struct {
	PkgPath    string `yaml:"pkgpath"`
	InstallDir string `yaml:"installdir,omitempty"`
}

func getWorkspaceDir() string {
	workspaceDir := "." + appName

	if flags.workspaceDir != "" {
		workspaceDir = filepath.Join(flags.workspaceDir, workspaceDir)
	}

	return workspaceDir
}

func getInitPathname(workspaceDir string) string {
	return filepath.Join(workspaceDir, "init.yaml")
}

func createWorkspace() (*workspaceParams, error) {
	workspaceDir := getWorkspaceDir()

	if _, err := os.Stat(workspaceDir); err == nil {
		return nil, errors.New("Workspace already initialized")
	}

	pkgpath, err := getPackagePathFromEnvironment()

	if err != nil {
		return nil, err
	}

	wp := workspaceParams{pkgpath, flags.installDir}

	out, err := yaml.Marshal(&wp)
	if err != nil {
		return nil, err
	}

	err = os.Mkdir(workspaceDir, os.FileMode(0775))
	if err != nil {
		return nil, err
	}

	err = ioutil.WriteFile(getInitPathname(workspaceDir),
		out, os.FileMode(0664))
	if err != nil {
		return nil, err
	}

	return &workspaceParams{}, nil
}

func readWorkspaceParams() (*workspaceParams, error) {
	in, err := ioutil.ReadFile(getInitPathname(getWorkspaceDir()))
	if err != nil {
		return nil, err
	}

	var wp workspaceParams
	err = yaml.Unmarshal(in, &wp)

	return &wp, err
}
<commit_msg>Start error message with a lower case letter<commit_after>// Copyright (C) 2017 Damon Revoe. All rights reserved.
// Use of this source code is governed by the MIT
// license, which can be found in the LICENSE file.

package main

import (
	"errors"
	"io/ioutil"
	"os"
	"path/filepath"

	"gopkg.in/yaml.v2"
)

type workspaceParams struct {
	PkgPath    string `yaml:"pkgpath"`
	InstallDir string `yaml:"installdir,omitempty"`
}

func getWorkspaceDir() string {
	workspaceDir := "." + appName

	if flags.workspaceDir != "" {
		workspaceDir = filepath.Join(flags.workspaceDir, workspaceDir)
	}

	return workspaceDir
}

func getInitPathname(workspaceDir string) string {
	return filepath.Join(workspaceDir, "init.yaml")
}

func createWorkspace() (*workspaceParams, error) {
	workspaceDir := getWorkspaceDir()

	if _, err := os.Stat(workspaceDir); err == nil {
		return nil, errors.New("workspace already initialized")
	}

	pkgpath, err := getPackagePathFromEnvironment()

	if err != nil {
		return nil, err
	}

	wp := workspaceParams{pkgpath, flags.installDir}

	out, err := yaml.Marshal(&wp)
	if err != nil {
		return nil, err
	}

	err = os.Mkdir(workspaceDir, os.FileMode(0775))
	if err != nil {
		return nil, err
	}

	err = ioutil.WriteFile(getInitPathname(workspaceDir),
		out, os.FileMode(0664))
	if err != nil {
		return nil, err
	}

	return &workspaceParams{}, nil
}

func readWorkspaceParams() (*workspaceParams, error) {
	in, err := ioutil.ReadFile(getInitPathname(getWorkspaceDir()))
	if err != nil {
		return nil, err
	}

	var wp workspaceParams
	err = yaml.Unmarshal(in, &wp)

	return &wp, err
}
<|endoftext|>