<commit_before>package validators

import (
	"strings"
)

// Specs struct
type Specs struct {
	Chars  int
	Weight []int
}

// Rules struct - define rules for validator
type Rules struct {
	Values map[string]Specs
}

// NewRule function
func NewRule() Rules {
	return Rules{}
}

// Build function
func (r *Rules) Build(state string) {
	specs := make(map[string]Specs, 1)
	specs[state] = Specs{Chars: 9, Weight: []int{9, 8, 7, 6, 5, 4}}

	r.Values = specs
}

// Get function return the rules for state
func (r *Rules) Get(state string) Specs {

	return r.Values[state]
}

// IsUndefined function
func (r *Rules) IsUndefined(obj interface{}) bool {

	return obj == nil
}

// IsCorrectSize function
func (r *Rules) IsCorrectSize(value string, size int) bool {

	if r.IsUndefined(size) {
		size = 9
	}
	return len(value) == size
}

// MountSeries function
func (r *Rules) MountSeries(start int, end int) ([]int, error) {

	var slice []int
	if end < start {
		panic("The end parameter is minus that start")
	}

	for start < end {
		start++
		slice = append(slice, start)
	}
	return slice, nil
}

// First function
func (r *Rules) First(value string, quantity int) string {

	if r.IsUndefined(quantity) {
		quantity = 8
	}
	return value[:quantity]
}

// Subtract function
func (r *Rules) Subtract(value int) int {

	if value < 2 {
		return 0
	}
	return 11 - value
}

// Mod function
func (r *Rules) Mod(value string, multipliers []int, divisor int) int {

	if r.IsUndefined(divisor) {
		divisor = 11
	}

	if r.IsUndefined(multipliers) {
		multipliers, _ = r.MountSeries(2, 9)
	}

	i := 0

	slice := strings.Split(value, "")

	return 11 - value
}
<commit_msg>Update the rules<commit_after>package validators

import (
	"strconv"
	"strings"
)

// Specs struct
type Specs struct {
	Chars  int
	Weight []int
}

// Rules struct - define rules for validator
type Rules struct {
	Values map[string]Specs
}

// NewRule function
func NewRule() Rules {
	return Rules{}
}

// Build function
func (r *Rules) Build(state string) {
	specs := make(map[string]Specs, 1)
	specs[state] = Specs{Chars: 9, Weight: []int{9, 8, 7, 6, 5, 4}}

	r.Values = specs
}

// Get function return the rules for state
func (r *Rules) Get(state string) Specs {

	return r.Values[state]
}

// IsUndefined function
func (r *Rules) IsUndefined(obj interface{}) bool {

	return obj == nil
}

// IsCorrectSize function
func (r *Rules) IsCorrectSize(value string, size int) bool {

	if r.IsUndefined(size) {
		size = 9
	}
	return len(value) == size
}

// MountSeries function
func (r *Rules) MountSeries(start int, end int) ([]int, error) {

	var slice []int
	if end < start {
		panic("The end parameter is minus that start")
	}

	for start < end {
		start++
		slice = append(slice, start)
	}
	return slice, nil
}

// First function
func (r *Rules) First(value string, quantity int) string {

	if r.IsUndefined(quantity) {
		quantity = 8
	}
	return value[:quantity]
}

// Subtract function
func (r *Rules) Subtract(value int) int {

	if value < 2 {
		return 0
	}
	return 11 - value
}

// Mod function
func (r *Rules) Mod(param string, multipliers []int, divisor int) int64 {

	if r.IsUndefined(divisor) {
		divisor = 11
	}

	if r.IsUndefined(multipliers) {
		multipliers, _ = r.MountSeries(2, 9)
	}

	var total int64
	values := strings.Split(param, "")
	var a int64 = -1
	for _, value := range values {

		current, _ := strconv.ParseInt(value, 10, 64)

		if a == -1 {
			a = current
			total = current + 0
		} else {
			total = current + a
		}
	}

	return total
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"github.com/codegangsta/cli"
	"github.com/docker/swarmd/backends"
	"github.com/dotcloud/docker/api/server"
	"github.com/dotcloud/docker/engine"
	"github.com/flynn/go-shlex"
	"io"
	"os"
	"strings"
	"time"
)

func main() {
	app := cli.NewApp()
	app.Name = "swarmd"
	app.Usage = "Control a heterogenous distributed system with the Docker API"
	app.Version = "0.0.1"
	app.Flags = []cli.Flag{
		cli.StringFlag{"backend", "debug", "load a backend"},
	}
	app.Action = cmdDaemon
	app.Run(os.Args)
}

func cmdDaemon(c *cli.Context) {
	if len(c.Args()) == 0 {
		Fatalf("Usage: %s <proto>://<address> [<proto>://<address>]...\n", c.App.Name)
	}

	// Load backend
	// FIXME: allow for multiple backends to be loaded.
	// This could be done by instantiating 1 engine per backend,
	// installing each backend in its respective engine,
	// then registering a Catchall on the frontent engine which
	// multiplexes across all backends (with routing / filtering
	// logic along the way).
	back := backends.New()
	bName, bArgs, err := parseCmd(c.String("backend"))
	if err != nil {
		Fatalf("%v", err)
	}
	fmt.Printf("---> Loading backend '%s'\n", strings.Join(append([]string{bName}, bArgs...), " "))
	if err := back.Job(bName, bArgs...).Run(); err != nil {
		Fatalf("%s: %v\n", bName, err)
	}

	// Register the API entrypoint
	// (we register it as `argv[0]` so we can print usage messages straight from the job
	// stderr.
	front := engine.New()
	front.Logging = false
	// FIXME: server should expose an engine.Installer
	front.Register(c.App.Name, server.ServeApi)
	front.RegisterCatchall(func(job *engine.Job) engine.Status {
		fw := back.Job(job.Name, job.Args...)
		fw.Stdout.Add(job.Stdout)
		fw.Stderr.Add(job.Stderr)
		fw.Stdin.Add(job.Stdin)
		fw.Run()
		return engine.Status(fw.StatusCode())
	})

	// Call the API entrypoint
	go func() {
		serve := front.Job(c.App.Name, c.Args()...)
		serve.Stdout.Add(os.Stdout)
		serve.Stderr.Add(os.Stderr)
		if err := serve.Run(); err != nil {
			Fatalf("serveapi: %v", err)
		}
	}()
	// There is a race condition in engine.ServeApi.
	// As a workaround we sleep to give it time to register 'acceptconnections'.
	time.Sleep(1 * time.Second)
	// Notify that we're ready to receive connections
	if err := front.Job("acceptconnections").Run(); err != nil {
		Fatalf("acceptconnections: %v", err)
	}
	// Inifinite loop
	<-make(chan struct{})
}

func parseCmd(txt string) (string, []string, error) {
	l, err := shlex.NewLexer(strings.NewReader(txt))
	if err != nil {
		return "", nil, err
	}
	var cmd []string
	for {
		word, err := l.NextWord()
		if err == io.EOF {
			break
		}
		if err != nil {
			return "", nil, err
		}
		cmd = append(cmd, word)
	}
	if len(cmd) == 0 {
		return "", nil, fmt.Errorf("parse error: empty command")
	}
	return cmd[0], cmd[1:], nil
}

func Fatalf(msg string, args ...interface{}) {
	if !strings.HasSuffix(msg, "\n") {
		msg = msg + "\n"
	}
	fmt.Fprintf(os.Stderr, msg, args...)
	os.Exit(1)
}
<commit_msg>Copy env when creating job in catchall<commit_after>package main

import (
	"fmt"
	"github.com/codegangsta/cli"
	"github.com/docker/swarmd/backends"
	"github.com/dotcloud/docker/api/server"
	"github.com/dotcloud/docker/engine"
	"github.com/flynn/go-shlex"
	"io"
	"os"
	"strings"
	"time"
)

func main() {
	app := cli.NewApp()
	app.Name = "swarmd"
	app.Usage = "Control a heterogenous distributed system with the Docker API"
	app.Version = "0.0.1"
	app.Flags = []cli.Flag{
		cli.StringFlag{"backend", "debug", "load a backend"},
	}
	app.Action = cmdDaemon
	app.Run(os.Args)
}

func cmdDaemon(c *cli.Context) {
	if len(c.Args()) == 0 {
		Fatalf("Usage: %s <proto>://<address> [<proto>://<address>]...\n", c.App.Name)
	}

	// Load backend
	// FIXME: allow for multiple backends to be loaded.
	// This could be done by instantiating 1 engine per backend,
	// installing each backend in its respective engine,
	// then registering a Catchall on the frontent engine which
	// multiplexes across all backends (with routing / filtering
	// logic along the way).
	back := backends.New()
	bName, bArgs, err := parseCmd(c.String("backend"))
	if err != nil {
		Fatalf("%v", err)
	}
	fmt.Printf("---> Loading backend '%s'\n", strings.Join(append([]string{bName}, bArgs...), " "))
	if err := back.Job(bName, bArgs...).Run(); err != nil {
		Fatalf("%s: %v\n", bName, err)
	}

	// Register the API entrypoint
	// (we register it as `argv[0]` so we can print usage messages straight from the job
	// stderr.
	front := engine.New()
	front.Logging = false
	// FIXME: server should expose an engine.Installer
	front.Register(c.App.Name, server.ServeApi)
	front.RegisterCatchall(func(job *engine.Job) engine.Status {
		fw := back.Job(job.Name, job.Args...)
		fw.Stdout.Add(job.Stdout)
		fw.Stderr.Add(job.Stderr)
		fw.Stdin.Add(job.Stdin)
		for key, val := range job.Env().Map() {
			fw.Setenv(key, val)
		}
		fw.Run()
		return engine.Status(fw.StatusCode())
	})

	// Call the API entrypoint
	go func() {
		serve := front.Job(c.App.Name, c.Args()...)
		serve.Stdout.Add(os.Stdout)
		serve.Stderr.Add(os.Stderr)
		if err := serve.Run(); err != nil {
			Fatalf("serveapi: %v", err)
		}
	}()
	// There is a race condition in engine.ServeApi.
	// As a workaround we sleep to give it time to register 'acceptconnections'.
	time.Sleep(1 * time.Second)
	// Notify that we're ready to receive connections
	if err := front.Job("acceptconnections").Run(); err != nil {
		Fatalf("acceptconnections: %v", err)
	}
	// Inifinite loop
	<-make(chan struct{})
}

func parseCmd(txt string) (string, []string, error) {
	l, err := shlex.NewLexer(strings.NewReader(txt))
	if err != nil {
		return "", nil, err
	}
	var cmd []string
	for {
		word, err := l.NextWord()
		if err == io.EOF {
			break
		}
		if err != nil {
			return "", nil, err
		}
		cmd = append(cmd, word)
	}
	if len(cmd) == 0 {
		return "", nil, fmt.Errorf("parse error: empty command")
	}
	return cmd[0], cmd[1:], nil
}

func Fatalf(msg string, args ...interface{}) {
	if !strings.HasSuffix(msg, "\n") {
		msg = msg + "\n"
	}
	fmt.Fprintf(os.Stderr, msg, args...)
	os.Exit(1)
}
<|endoftext|>


<commit_before>// Copyright 2014 Simon Zimmermann. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.

package swift

import (
	"bytes"
	"crypto/md5"
	"fmt"
	"hash"
	"io"
	"io/ioutil"
	"os"
	//"time"

	"github.com/ncw/swift"
	"github.com/simonz05/blobserver/blob"
)

const maxInMemorySlurp = 8 << 20 // 8MB.

// swiftSlurper slurps up a blob to memory (or spilling to disk if
// over maxInMemorySlurp) to verify its digest (and also gets its MD5
// for Amazon's Content-MD5 header, even if the original blobref
// is e.g. sha1-xxxx)
type swiftSlurper struct {
	blob    blob.Ref // only used for tempfile's prefix
	buf     *bytes.Buffer
	r       *bytes.Reader
	md5     hash.Hash
	file    *os.File // nil until allocated
	reading bool     // transitions at most once from false -> true
}

func newSwiftSlurper(blob blob.Ref) *swiftSlurper {
	return &swiftSlurper{
		blob: blob,
		buf:  new(bytes.Buffer),
		md5:  md5.New(),
	}
}

func (as *swiftSlurper) Read(p []byte) (n int, err error) {
	if !as.reading {
		as.reading = true
		if as.file != nil {
			as.file.Seek(0, 0)
		}
	}
	if as.file != nil {
		return as.file.Read(p)
	}
	if as.r == nil {
		as.r = bytes.NewReader(as.buf.Bytes())
	}
	return as.r.Read(p)
}

func (as *swiftSlurper) Seek(offset int64, whence int) (int64, error) {
	if as.file != nil {
		return as.file.Seek(offset, whence)
	}
	if as.r != nil {
		return as.r.Seek(offset, whence)
	}
	return offset, nil
}

func (as *swiftSlurper) Write(p []byte) (n int, err error) {
	if as.reading {
		panic("write after read")
	}
	as.md5.Write(p)
	if as.file != nil {
		n, err = as.file.Write(p)
		return
	}

	if as.buf.Len()+len(p) > maxInMemorySlurp {
		as.file, err = ioutil.TempFile("", as.blob.String())
		if err != nil {
			return
		}
		_, err = io.Copy(as.file, as.buf)
		if err != nil {
			return
		}
		as.buf = nil
		n, err = as.file.Write(p)
		return
	}

	return as.buf.Write(p)
}

func (as *swiftSlurper) Cleanup() {
	if as.file != nil {
		os.Remove(as.file.Name())
	}
}

func (sto *swiftStorage) ReceiveBlob(b blob.Ref, source io.Reader) (sr blob.SizedRef, err error) {
	slurper := newSwiftSlurper(b)
	defer slurper.Cleanup()

	size, err := io.Copy(slurper, source)

	if err != nil {
		return sr, err
	}

	hash := fmt.Sprintf("%x", slurper.md5.Sum(nil))
	retries := 1
Retry:
	_, err = sto.conn.ObjectPut(sto.container(b), b.String(), slurper, false, hash, "", nil)

	if err != nil {
		// assume both of these mean container not found in this context
		if (err == swift.ObjectNotFound || err == swift.ContainerNotFound) && retries > 0 {
			retries--
			h := make(swift.Headers)
			h["X-Container-Read"] = sto.containerReadACL
			err = sto.conn.ContainerCreate(sto.container(b), h)
			slurper.Seek(0, 0)
			goto Retry
		} else {
			return sr, err
		}
	}
	return blob.SizedRef{Ref: b, Size: uint32(size)}, nil
}
<commit_msg>swift: fix discard error<commit_after>// Copyright 2014 Simon Zimmermann. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.

package swift

import (
	"bytes"
	"crypto/md5"
	"fmt"
	"hash"
	"io"
	"io/ioutil"
	"os"
	//"time"

	"github.com/ncw/swift"
	"github.com/simonz05/blobserver/blob"
)

const maxInMemorySlurp = 8 << 20 // 8MB.

// swiftSlurper slurps up a blob to memory (or spilling to disk if
// over maxInMemorySlurp) to verify its digest (and also gets its MD5
// for Amazon's Content-MD5 header, even if the original blobref
// is e.g. sha1-xxxx)
type swiftSlurper struct {
	blob    blob.Ref // only used for tempfile's prefix
	buf     *bytes.Buffer
	r       *bytes.Reader
	md5     hash.Hash
	file    *os.File // nil until allocated
	reading bool     // transitions at most once from false -> true
}

func newSwiftSlurper(blob blob.Ref) *swiftSlurper {
	return &swiftSlurper{
		blob: blob,
		buf:  new(bytes.Buffer),
		md5:  md5.New(),
	}
}

func (as *swiftSlurper) Read(p []byte) (n int, err error) {
	if !as.reading {
		as.reading = true
		if as.file != nil {
			as.file.Seek(0, 0)
		}
	}
	if as.file != nil {
		return as.file.Read(p)
	}
	if as.r == nil {
		as.r = bytes.NewReader(as.buf.Bytes())
	}
	return as.r.Read(p)
}

func (as *swiftSlurper) Seek(offset int64, whence int) (int64, error) {
	if as.file != nil {
		return as.file.Seek(offset, whence)
	}
	if as.r != nil {
		return as.r.Seek(offset, whence)
	}
	return offset, nil
}

func (as *swiftSlurper) Write(p []byte) (n int, err error) {
	if as.reading {
		panic("write after read")
	}
	as.md5.Write(p)
	if as.file != nil {
		n, err = as.file.Write(p)
		return
	}

	if as.buf.Len()+len(p) > maxInMemorySlurp {
		as.file, err = ioutil.TempFile("", as.blob.String())
		if err != nil {
			return
		}
		_, err = io.Copy(as.file, as.buf)
		if err != nil {
			return
		}
		as.buf = nil
		n, err = as.file.Write(p)
		return
	}

	return as.buf.Write(p)
}

func (as *swiftSlurper) Cleanup() {
	if as.file != nil {
		os.Remove(as.file.Name())
	}
}

func (sto *swiftStorage) ReceiveBlob(b blob.Ref, source io.Reader) (sr blob.SizedRef, err error) {
	slurper := newSwiftSlurper(b)
	defer slurper.Cleanup()

	size, err := io.Copy(slurper, source)

	if err != nil {
		return sr, err
	}

	hash := fmt.Sprintf("%x", slurper.md5.Sum(nil))
	retries := 1
retry:
	_, err = sto.conn.ObjectPut(sto.container(b), b.String(), slurper, false, hash, "", nil)

	if err != nil {
		// assume both of these mean container not found in this context
		if (err == swift.ObjectNotFound || err == swift.ContainerNotFound) && retries > 0 {
			retries--
			slurper.Seek(0, 0)
			h := make(swift.Headers)
			h["X-Container-Read"] = sto.containerReadACL
			err = sto.conn.ContainerCreate(sto.container(b), h)
			if err == nil {
				goto retry
			}
		}
		return sr, err
	}
	return blob.SizedRef{Ref: b, Size: uint32(size)}, nil
}
<|endoftext|>


<commit_before>/*
Copyright (c) 2014 VMware, Inc. All Rights Reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package debug

import (
	"io"
	"os"
	"path"
)

// FileProvider implements a debugging provider that creates a real file for
// every call to NewFile. It maintains a list of all files that it creates,
// such that it can close them when its Flush function is called.
type FileProvider struct {
	Path  string
	files []*os.File
}

func (fp *FileProvider) NewFile(p string) io.WriteCloser {
	f, err := os.Create(path.Join(fp.Path, p))
	if err != nil {
		panic(err)
	}

	fp.files = append(fp.files, f)

	return NewFileWriterCloser(f, p)
}

func (fp *FileProvider) Flush() {
	for _, f := range fp.files {
		f.Close()
	}
}

type FileWriterCloser struct {
	f *os.File
	p string
}

func NewFileWriterCloser(f *os.File, p string) *FileWriterCloser {
	return &FileWriterCloser{
		f,
		p,
	}
}

func (fwc *FileWriterCloser) Write(p []byte) (n int, err error) {
	return fwc.f.Write(Scrub(p))
}

func (fwc *FileWriterCloser) Close() error {
	return fwc.f.Close()
}
<commit_msg>Fix: Protect FileProvider.files to avoid concurrent modification<commit_after>/*
Copyright (c) 2014 VMware, Inc. All Rights Reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package debug

import (
	"io"
	"os"
	"path"
	"sync"
)

// FileProvider implements a debugging provider that creates a real file for
// every call to NewFile. It maintains a list of all files that it creates,
// such that it can close them when its Flush function is called.
type FileProvider struct {
	Path string

	mu    sync.Mutex
	files []*os.File
}

func (fp *FileProvider) NewFile(p string) io.WriteCloser {
	f, err := os.Create(path.Join(fp.Path, p))
	if err != nil {
		panic(err)
	}

	fp.mu.Lock()
	defer fp.mu.Unlock()
	fp.files = append(fp.files, f)

	return NewFileWriterCloser(f, p)
}

func (fp *FileProvider) Flush() {
	fp.mu.Lock()
	defer fp.mu.Unlock()
	for _, f := range fp.files {
		f.Close()
	}
}

type FileWriterCloser struct {
	f *os.File
	p string
}

func NewFileWriterCloser(f *os.File, p string) *FileWriterCloser {
	return &FileWriterCloser{
		f,
		p,
	}
}

func (fwc *FileWriterCloser) Write(p []byte) (n int, err error) {
	return fwc.f.Write(Scrub(p))
}

func (fwc *FileWriterCloser) Close() error {
	return fwc.f.Close()
}
<|endoftext|>


<commit_before>/**
 *  Copyright 2014 Paul Querna
 *
 *  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 workers

import (
	"fmt"
	"github.com/dchest/uniuri"
	"github.com/pquerna/hurl/common"
	"sync"
	"time"
)

type ResultSaver interface {
	SaveRecord(string) error
}

type WorkerTask interface {
	Work(rv *common.Result) error
}

type Worker interface {
	Start(wg *sync.WaitGroup, reqChan chan int64) error
	Halt() error
}

type newTask func(common.ConfigGetter) WorkerTask

var g_workers_tasks map[string]newTask

func init() {
	g_workers_tasks = make(map[string]newTask)
}

func Register(wt string, nt newTask) {
	g_workers_tasks[wt] = nt
}

type LocalWorker struct {
	WorkerType string
	wg         *sync.WaitGroup
	reqChan    chan int64
	task       WorkerTask
	rs         ResultSaver
}

func (lw *LocalWorker) runWorker(id string) {
	defer lw.wg.Done()

	for {
		reqNum, ok := <-lw.reqChan
		if !ok {
			return
		}
		rv := common.Result{Id: fmt.Sprintf("%s-%d", id, reqNum)}
		startTime := time.Now()
		err := lw.task.Work(&rv)
		duration := time.Since(startTime)
		if err != nil {
			// TODO: report this back to UI in a better way? Convert to ErrorResult?
			panic(err)
			return
		}
		rv.Duration = duration
		// TODO: results storage
	}
}

func (lw *LocalWorker) Start(wg *sync.WaitGroup, reqChan chan int64) error {
	lw.reqChan = reqChan
	lw.wg = wg
	lw.wg.Add(1)
	go lw.runWorker(uniuri.New())

	return nil
}

func (lw *LocalWorker) Halt() error {
	return nil
}

func Run(ui common.UI, task string, conf common.ConfigGetter) error {
	//	if clusterConf != "" {
	//		// TODO: add ClusterWorker
	//		return nil, fmt.Errorf("TODO: Cluster support")
	//	}
	wt, ok := g_workers_tasks[task]
	if !ok {
		return fmt.Errorf("unknown worker type: %s", task)
	}

	bconf := conf.GetBasicConfig()
	workers := make([]Worker, bconf.Concurrency)
	for index, _ := range workers {
		workers[index] = &LocalWorker{task: wt(conf)}
	}

	ui.WorkStart(bconf.NumRequests)
	defer func() {
		for _, worker := range workers {
			worker.Halt()
		}
	}()

	var wg sync.WaitGroup
	reqchan := make(chan int64, 1024*1024)
	for _, worker := range workers {
		err := worker.Start(&wg, reqchan)
		if err != nil {
			return err
		}
	}

	var i int64

	for i = 0; i < bconf.NumRequests; i++ {
		reqchan <- i
		// TOOD: ui.WorkStatus(numDone int64)
	}
	close(reqchan)
	wg.Wait()
	ui.WorkEnd()

	return nil
}
<commit_msg>basics of getting results<commit_after>/**
 *  Copyright 2014 Paul Querna
 *
 *  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 workers

import (
	"fmt"
	"github.com/dchest/uniuri"
	"github.com/pquerna/hurl/common"
	"sync"
	"time"
)

type WorkerTask interface {
	Work(rv *common.Result) error
}

type Worker interface {
	Start(wg *sync.WaitGroup, reqChan chan int64, resChan chan *common.Result) error
	Halt() error
}

type newTask func(common.ConfigGetter) WorkerTask

var g_workers_tasks map[string]newTask

func init() {
	g_workers_tasks = make(map[string]newTask)
}

func Register(wt string, nt newTask) {
	g_workers_tasks[wt] = nt
}

type LocalWorker struct {
	WorkerType string
	wg         *sync.WaitGroup
	reqChan    chan int64
	resChan    chan *common.Result
	task       WorkerTask
}

func (lw *LocalWorker) runWorker(id string) {
	defer lw.wg.Done()

	for {
		reqNum, ok := <-lw.reqChan
		if !ok {
			return
		}
		rv := common.Result{Id: fmt.Sprintf("%s-%d", id, reqNum)}
		startTime := time.Now()
		err := lw.task.Work(&rv)
		duration := time.Since(startTime)
		if err != nil {
			// TODO: report this back to UI in a better way? Convert to ErrorResult?
			panic(err)
			return
		}
		rv.Duration = duration
		// TODO: results storage
		lw.resChan <- &rv
	}
}

func (lw *LocalWorker) Start(wg *sync.WaitGroup, reqChan chan int64, resChan chan *common.Result) error {
	lw.reqChan = reqChan
	lw.resChan = resChan
	lw.wg = wg
	lw.wg.Add(1)
	go lw.runWorker(uniuri.New())

	return nil
}

func (lw *LocalWorker) Halt() error {
	return nil
}

func Run(ui common.UI, task string, conf common.ConfigGetter) error {
	//	if clusterConf != "" {
	//		// TODO: add ClusterWorker
	//		return nil, fmt.Errorf("TODO: Cluster support")
	//	}
	wt, ok := g_workers_tasks[task]
	if !ok {
		return fmt.Errorf("unknown worker type: %s", task)
	}

	bconf := conf.GetBasicConfig()
	workers := make([]Worker, bconf.Concurrency)
	for index, _ := range workers {
		workers[index] = &LocalWorker{task: wt(conf)}
	}

	ui.WorkStart(bconf.NumRequests)
	defer func() {
		for _, worker := range workers {
			worker.Halt()
		}
	}()

	var wg sync.WaitGroup
	reqchan := make(chan int64, 1024*1024)
	// TODO: how big should this be?
	reschan := make(chan *common.Result)
	for _, worker := range workers {
		err := worker.Start(&wg, reqchan, reschan)
		if err != nil {
			return err
		}
	}

	var i int64

	for i = 0; i < bconf.NumRequests; i++ {
		reqchan <- i
		// TOOD: ui.WorkStatus(numDone int64)
	}
	go func() {
		i = 0
		for {
			_, ok := <-reschan
			if !ok {
				return
			}
			i++
			ui.WorkStatus(i)
		}
	}()

	close(reqchan)
	wg.Wait()
	close(reschan)
	ui.WorkEnd()

	return nil
}
<|endoftext|>


<commit_before>/*
 * Copyright 2017 Dgraph Labs, Inc. and Contributors
 *
 * 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 table

import (
	"bytes"
	"encoding/binary"
	//	"fmt"
	"math"

	"github.com/dgraph-io/badger/y"
	"github.com/willf/bloom"
)

//var tableSize int64 = 50 << 20
var (
	restartInterval int = 100 // Might want to change this to be based on total size instead of numKeys.
	bufPool             = new(bufferPool)
	Mi              int = 1000000
)

func init() {
	bufPool.Ch = make(chan *bytes.Buffer, 10)
}

type bufferPool struct {
	Ch chan *bytes.Buffer
}

func (p *bufferPool) Put(b *bytes.Buffer) {
	b.Reset()

	select {
	case p.Ch <- b:
	default:
		// ignore
	}
}

func (p *bufferPool) Get() *bytes.Buffer {
	select {
	case b := <-p.Ch:
		return b
	default:
		b := new(bytes.Buffer)
		b.Grow(64 << 20)
		return b
	}
}

type header struct {
	plen int // Overlap with base key.
	klen int // Length of the diff.
	vlen int // Length of value.
	prev int // Offset for the previous key-value pair. The offset is relative to block base offset.
}

// Encode encodes the header.
func (h header) Encode(b []byte) {
	binary.BigEndian.PutUint16(b[0:2], uint16(h.plen))
	binary.BigEndian.PutUint16(b[2:4], uint16(h.klen))
	binary.BigEndian.PutUint16(b[4:6], uint16(h.vlen))
	binary.BigEndian.PutUint32(b[6:10], uint32(h.prev))
}

// Decode decodes the header.
func (h *header) Decode(buf []byte) int {
	h.plen = int(binary.BigEndian.Uint16(buf[0:2]))
	h.klen = int(binary.BigEndian.Uint16(buf[2:4]))
	h.vlen = int(binary.BigEndian.Uint16(buf[4:6]))
	h.prev = int(binary.BigEndian.Uint32(buf[6:10]))
	return h.Size()
}

// Size returns size of the header. Currently it's just a constant.
func (h header) Size() int { return 10 }

type TableBuilder struct {
	counter int // Number of keys written for the current block.

	// Typically tens or hundreds of meg. This is for one single file.
	buf *bytes.Buffer

	baseKey    []byte // Base key for the current block.
	baseOffset int    // Offset for the current block.

	restarts []uint32 // Base offsets of every block.

	// Tracks offset for the previous key-value pair. Offset is relative to block base offset.
	prevOffset int

	total int // Total keys written
	bf    *bloom.BloomFilter
}

func NewTableBuilder() *TableBuilder {
	return &TableBuilder{
		buf:        bufPool.Get(),
		prevOffset: math.MaxUint32,                         // Used for the first element!
		bf:         bloom.NewWithEstimates(uint(Mi), 0.01), // Size = 1198160
	}
}

// Close closes the TableBuilder. Do not use buf field anymore.
func (b *TableBuilder) Close() {
	bufPool.Put(b.buf)
}

func (b *TableBuilder) Empty() bool { return b.buf.Len() == 0 }

// keyDiff returns a suffix of newKey that is different from b.baseKey.
func (b TableBuilder) keyDiff(newKey []byte) []byte {
	var i int
	for i = 0; i < len(newKey) && i < len(b.baseKey); i++ {
		if newKey[i] != b.baseKey[i] {
			break
		}
	}
	return newKey[i:]
}

func (b *TableBuilder) addHelper(key []byte, v y.ValueStruct) {
	// Add key to bloom filter.
	b.bf.Add(key)
	b.total++

	// diffKey stores the difference of key with baseKey.
	var diffKey []byte
	if len(b.baseKey) == 0 {
		// Make a copy. Builder should not keep references. Otherwise, caller has to be very careful
		// and will have to make copies of keys every time they add to builder, which is even worse.
		b.baseKey = append(b.baseKey[:0], key...)
		diffKey = key
	} else {
		diffKey = b.keyDiff(key)
	}

	h := header{
		plen: len(key) - len(diffKey),
		klen: len(diffKey),
		vlen: len(v.Value) + 1 + 2, // Include meta byte and casCounter.
		prev: b.prevOffset,         // prevOffset is the location of the last key-value added.
	}
	b.prevOffset = b.buf.Len() - b.baseOffset // Remember current offset for the next Add call.

	// Layout: header, diffKey, value.
	var hbuf [10]byte
	h.Encode(hbuf[:])
	b.buf.Write(hbuf[:])
	b.buf.Write(diffKey)    // We only need to store the key difference.
	b.buf.WriteByte(v.Meta) // Meta byte precedes actual value.
	var casBytes [2]byte
	binary.BigEndian.PutUint16(casBytes[:], v.CASCounter)
	b.buf.Write(casBytes[:])
	b.buf.Write(v.Value)
	b.counter++ // Increment number of keys added for this current block.
}

func (b *TableBuilder) finishBlock() {
	// When we are at the end of the block and Valid=false, and the user wants to do a Prev,
	// we need a dummy header to tell us the offset of the previous key-value pair.
	b.addHelper([]byte{}, y.ValueStruct{})
}

// Add adds a key-value pair to the block.
// If doNotRestart is true, we will not restart even if b.counter >= restartInterval.
func (b *TableBuilder) Add(key []byte, value y.ValueStruct) error {
	if b.counter >= restartInterval {
		b.finishBlock()
		// Start a new block. Initialize the block.
		b.restarts = append(b.restarts, uint32(b.buf.Len()))
		b.counter = 0
		b.baseKey = []byte{}
		b.baseOffset = b.buf.Len()
		b.prevOffset = math.MaxUint32 // First key-value pair of block has header.prev=MaxUint32.
	}
	b.addHelper(key, value)
	return nil // Currently, there is no meaningful error.
}

// FinalSize returns the *rough* final size of the array, counting the header which is not yet written.
// TODO: Look into why there is a discrepancy. I suspect it is because of Write(empty, empty)
// at the end. The diff can vary.
func (b *TableBuilder) ReachedCapacity(cap int64) bool {
	if b.total > Mi {
		return true
	}
	estimateSz := /*1198160 +*/ b.buf.Len() + 8 /* empty header */ + 4*len(b.restarts) + 8 // 8 = end of buf offset + len(restarts).
	return int64(estimateSz) > cap
}

// blockIndex generates the block index for the table.
// It is mainly a list of all the block base offsets.
func (b *TableBuilder) blockIndex() []byte {
	// Store the end offset, so we know the length of the final block.
	b.restarts = append(b.restarts, uint32(b.buf.Len()))

	// Add 4 because we want to write out number of restarts at the end.
	sz := 4*len(b.restarts) + 4
	out := make([]byte, sz)
	buf := out
	for _, r := range b.restarts {
		binary.BigEndian.PutUint32(buf[:4], r)
		buf = buf[4:]
	}
	binary.BigEndian.PutUint32(buf[:4], uint32(len(b.restarts)))
	return out
}

var emptySlice = make([]byte, 100)

// Finish finishes the table by appending the index.
func (b *TableBuilder) Finish(metadata []byte) []byte {
	b.finishBlock() // This will never start a new block.
	index := b.blockIndex()
	b.buf.Write(index)

	// Write bloom filter.
	n, err := b.bf.WriteTo(b.buf)
	y.Check(err)
	var buf [4]byte
	binary.BigEndian.PutUint32(buf[:], uint32(n))
	b.buf.Write(buf[:])

	b.buf.Write(metadata)
	binary.BigEndian.PutUint32(buf[:], uint32(len(metadata)))
	b.buf.Write(buf[:])

	return b.buf.Bytes()
}
<commit_msg>Generate bloom filter at the end, keep track of all keys added.<commit_after>/*
 * Copyright 2017 Dgraph Labs, Inc. and Contributors
 *
 * 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 table

import (
	"bytes"
	"encoding/binary"
	"fmt"
	"math"

	"github.com/dgraph-io/badger/y"
	"github.com/willf/bloom"
)

//var tableSize int64 = 50 << 20
var (
	restartInterval int = 100 // Might want to change this to be based on total size instead of numKeys.
	bufPool             = new(bufferPool)
)

func init() {
	bufPool.Ch = make(chan *bytes.Buffer, 10)
}

type bufferPool struct {
	Ch chan *bytes.Buffer
}

func (p *bufferPool) Put(b *bytes.Buffer) {
	b.Reset()

	select {
	case p.Ch <- b:
	default:
		// ignore
	}
}

func (p *bufferPool) Get() *bytes.Buffer {
	select {
	case b := <-p.Ch:
		return b
	default:
		b := new(bytes.Buffer)
		b.Grow(64 << 20)
		return b
	}
}

type header struct {
	plen int // Overlap with base key.
	klen int // Length of the diff.
	vlen int // Length of value.
	prev int // Offset for the previous key-value pair. The offset is relative to block base offset.
}

// Encode encodes the header.
func (h header) Encode(b []byte) {
	binary.BigEndian.PutUint16(b[0:2], uint16(h.plen))
	binary.BigEndian.PutUint16(b[2:4], uint16(h.klen))
	binary.BigEndian.PutUint16(b[4:6], uint16(h.vlen))
	binary.BigEndian.PutUint32(b[6:10], uint32(h.prev))
}

// Decode decodes the header.
func (h *header) Decode(buf []byte) int {
	h.plen = int(binary.BigEndian.Uint16(buf[0:2]))
	h.klen = int(binary.BigEndian.Uint16(buf[2:4]))
	h.vlen = int(binary.BigEndian.Uint16(buf[4:6]))
	h.prev = int(binary.BigEndian.Uint32(buf[6:10]))
	return h.Size()
}

// Size returns size of the header. Currently it's just a constant.
func (h header) Size() int { return 10 }

type TableBuilder struct {
	counter int // Number of keys written for the current block.

	// Typically tens or hundreds of meg. This is for one single file.
	buf *bytes.Buffer

	baseKey    []byte // Base key for the current block.
	baseOffset int    // Offset for the current block.

	restarts []uint32 // Base offsets of every block.

	// Tracks offset for the previous key-value pair. Offset is relative to block base offset.
	prevOffset int

	bf      *bloom.BloomFilter
	allKeys [][]byte
}

func NewTableBuilder() *TableBuilder {
	return &TableBuilder{
		buf:        bufPool.Get(),
		prevOffset: math.MaxUint32, // Used for the first element!
	}
}

// Close closes the TableBuilder. Do not use buf field anymore.
func (b *TableBuilder) Close() {
	bufPool.Put(b.buf)
}

func (b *TableBuilder) Empty() bool { return b.buf.Len() == 0 }

// keyDiff returns a suffix of newKey that is different from b.baseKey.
func (b TableBuilder) keyDiff(newKey []byte) []byte {
	var i int
	for i = 0; i < len(newKey) && i < len(b.baseKey); i++ {
		if newKey[i] != b.baseKey[i] {
			break
		}
	}
	return newKey[i:]
}

func (b *TableBuilder) addHelper(key []byte, v y.ValueStruct) {
	// Add key to bloom filter.
	k := make([]byte, len(key))
	copy(k, key)
	b.allKeys = append(b.allKeys, k)

	// diffKey stores the difference of key with baseKey.
	var diffKey []byte
	if len(b.baseKey) == 0 {
		// Make a copy. Builder should not keep references. Otherwise, caller has to be very careful
		// and will have to make copies of keys every time they add to builder, which is even worse.
		b.baseKey = append(b.baseKey[:0], key...)
		diffKey = key
	} else {
		diffKey = b.keyDiff(key)
	}

	h := header{
		plen: len(key) - len(diffKey),
		klen: len(diffKey),
		vlen: len(v.Value) + 1 + 2, // Include meta byte and casCounter.
		prev: b.prevOffset,         // prevOffset is the location of the last key-value added.
	}
	b.prevOffset = b.buf.Len() - b.baseOffset // Remember current offset for the next Add call.

	// Layout: header, diffKey, value.
	var hbuf [10]byte
	h.Encode(hbuf[:])
	b.buf.Write(hbuf[:])
	b.buf.Write(diffKey)    // We only need to store the key difference.
	b.buf.WriteByte(v.Meta) // Meta byte precedes actual value.
	var casBytes [2]byte
	binary.BigEndian.PutUint16(casBytes[:], v.CASCounter)
	b.buf.Write(casBytes[:])
	b.buf.Write(v.Value)
	b.counter++ // Increment number of keys added for this current block.
}

func (b *TableBuilder) finishBlock() {
	// When we are at the end of the block and Valid=false, and the user wants to do a Prev,
	// we need a dummy header to tell us the offset of the previous key-value pair.
	b.addHelper([]byte{}, y.ValueStruct{})
}

// Add adds a key-value pair to the block.
// If doNotRestart is true, we will not restart even if b.counter >= restartInterval.
func (b *TableBuilder) Add(key []byte, value y.ValueStruct) error {
	if b.counter >= restartInterval {
		b.finishBlock()
		// Start a new block. Initialize the block.
		b.restarts = append(b.restarts, uint32(b.buf.Len()))
		b.counter = 0
		b.baseKey = []byte{}
		b.baseOffset = b.buf.Len()
		b.prevOffset = math.MaxUint32 // First key-value pair of block has header.prev=MaxUint32.
	}
	b.addHelper(key, value)
	return nil // Currently, there is no meaningful error.
}

// FinalSize returns the *rough* final size of the array, counting the header which is not yet written.
// TODO: Look into why there is a discrepancy. I suspect it is because of Write(empty, empty)
// at the end. The diff can vary.
func (b *TableBuilder) ReachedCapacity(cap int64) bool {
	estimateSz := b.buf.Len() + 8 /* empty header */ + 4*len(b.restarts) + 8 // 8 = end of buf offset + len(restarts).
	return int64(estimateSz) > cap
}

// blockIndex generates the block index for the table.
// It is mainly a list of all the block base offsets.
func (b *TableBuilder) blockIndex() []byte {
	// Store the end offset, so we know the length of the final block.
	b.restarts = append(b.restarts, uint32(b.buf.Len()))

	// Add 4 because we want to write out number of restarts at the end.
	sz := 4*len(b.restarts) + 4
	out := make([]byte, sz)
	buf := out
	for _, r := range b.restarts {
		binary.BigEndian.PutUint32(buf[:4], r)
		buf = buf[4:]
	}
	binary.BigEndian.PutUint32(buf[:4], uint32(len(b.restarts)))
	return out
}

var emptySlice = make([]byte, 100)

// Finish finishes the table by appending the index.
func (b *TableBuilder) Finish(metadata []byte) []byte {
	b.bf = bloom.NewWithEstimates(uint(len(b.allKeys)), 0.01)
	for _, k := range b.allKeys {
		b.bf.Add(k)
	}

	b.finishBlock() // This will never start a new block.
	index := b.blockIndex()
	b.buf.Write(index)

	// Write bloom filter.
	n, err := b.bf.WriteTo(b.buf)
	y.Check(err)
	fmt.Printf("\n--->> Size of bloom filter: %d\n", n)
	var buf [4]byte
	binary.BigEndian.PutUint32(buf[:], uint32(n))
	b.buf.Write(buf[:])

	b.buf.Write(metadata)
	binary.BigEndian.PutUint32(buf[:], uint32(len(metadata)))
	b.buf.Write(buf[:])

	return b.buf.Bytes()
}
<|endoftext|>


<commit_before>package wuxia

import (
	"testing"

	"github.com/spf13/afero"
)

func TestGenerator_Build(t *testing.T) {
	g := NewGenerator(nil, nil, afero.NewOsFs())
	p := "fixture/site"
	g.workDir = p
	g.Verbose = true
	err := g.Config()
	if err != nil {
		t.Error(err)
	}

	err = g.Init()
	if err != nil {
		t.Error(err)
	}
	err = g.Plan()
	if err != nil {
		t.Error(err)
	}
}
<commit_msg>Add Generator.Exec test<commit_after>package wuxia

import (
	"testing"

	"github.com/spf13/afero"
)

func TestGenerator_Build(t *testing.T) {
	g := NewGenerator(nil, nil, afero.NewOsFs())
	p := "fixture/site"
	g.workDir = p
	g.Verbose = true
	err := g.Config()
	if err != nil {
		t.Error(err)
	}

	err = g.Init()
	if err != nil {
		t.Error(err)
	}
	err = g.Plan()
	if err != nil {
		t.Error(err)
	}

	err = g.Exec()
	if err != nil {
		t.Error(err)
	}
}
<|endoftext|>


<commit_before>package backpressure_tests

import (
	crand "crypto/rand"
	"io"
	"math/rand"
	"testing"
	"time"

	inet "github.com/jbenet/go-ipfs/net"
	peer "github.com/jbenet/go-ipfs/peer"
	eventlog "github.com/jbenet/go-ipfs/util/eventlog"
	testutil "github.com/jbenet/go-ipfs/util/testutil"

	context "github.com/jbenet/go-ipfs/Godeps/_workspace/src/code.google.com/p/go.net/context"
)

var log = eventlog.Logger("backpressure")

func GenNetwork(ctx context.Context) (inet.Network, error) {
	p, err := testutil.PeerWithKeysAndAddress(testutil.RandLocalTCPAddress())
	if err != nil {
		return nil, err
	}

	listen := p.Addresses()
	ps := peer.NewPeerstore()
	return inet.NewNetwork(ctx, listen, p, ps)
}

// TestBackpressureStreamHandler tests whether mux handler
// ratelimiting works. Meaning, since the handler is sequential
// it should block senders.
//
// Important note: spdystream (which peerstream uses) has a set
// of n workers (n=spdsystream.FRAME_WORKERS) which handle new
// frames, including those starting new streams. So all of them
// can be in the handler at one time. Also, the sending side
// does not rate limit unless we call stream.Wait()
//
//
// Note: right now, this happens muxer-wide. the muxer should
// learn to flow control, so handlers cant block each other.
func TestBackpressureStreamHandler(t *testing.T) {
	t.Skip(`Sadly, as cool as this test is, it doesn't work
Because spdystream doesnt handle stream open backpressure
well IMO. I'll see about rewriting that part when it becomes
a problem.
`)

	// a number of concurrent request handlers
	limit := 10

	// our way to signal that we're done with 1 request
	requestHandled := make(chan struct{})

	// handler rate limiting
	receiverRatelimit := make(chan struct{}, limit)
	for i := 0; i < limit; i++ {
		receiverRatelimit <- struct{}{}
	}

	// sender counter of successfully opened streams
	senderOpened := make(chan struct{}, limit*100)

	// sender signals it's done (errored out)
	senderDone := make(chan struct{})

	// the receiver handles requests with some rate limiting
	receiver := func(s inet.Stream) {
		log.Debug("receiver received a stream")

		<-receiverRatelimit // acquire
		go func() {
			// our request handler. can do stuff here. we
			// simulate something taking time by waiting
			// on requestHandled
			log.Error("request worker handling...")
			<-requestHandled
			log.Error("request worker done!")
			receiverRatelimit <- struct{}{} // release
		}()
	}

	// the sender opens streams as fast as possible
	sender := func(net inet.Network, remote peer.Peer) {
		var s inet.Stream
		var err error
		defer func() {
			t.Error(err)
			log.Debug("sender error. exiting.")
			senderDone <- struct{}{}
		}()

		for {
			s, err = net.NewStream(inet.ProtocolTesting, remote)
			if err != nil {
				return
			}

			_ = s
			// if err = s.SwarmStream().Stream().Wait(); err != nil {
			// 	return
			// }

			// "count" another successfully opened stream
			// (large buffer so shouldn't block in normal operation)
			log.Debug("sender opened another stream!")
			senderOpened <- struct{}{}
		}
	}

	// count our senderOpened events
	countStreamsOpenedBySender := func(min int) int {
		opened := 0
		for opened < min {
			log.Debugf("countStreamsOpenedBySender got %d (min %d)", opened, min)
			select {
			case <-senderOpened:
				opened++
			case <-time.After(10 * time.Millisecond):
			}
		}
		return opened
	}

	// count our received events
	// waitForNReceivedStreams := func(n int) {
	// 	for n > 0 {
	// 		log.Debugf("waiting for %d received streams...", n)
	// 		select {
	// 		case <-receiverRatelimit:
	// 			n--
	// 		}
	// 	}
	// }

	testStreamsOpened := func(expected int) {
		log.Debugf("testing rate limited to %d streams", expected)
		if n := countStreamsOpenedBySender(expected); n != expected {
			t.Fatalf("rate limiting did not work :( -- %d != %d", expected, n)
		}
	}

	// ok that's enough setup. let's do it!

	ctx := context.Background()
	n1, err := GenNetwork(ctx)
	if err != nil {
		t.Fatal(err)
	}
	n2, err := GenNetwork(ctx)
	if err != nil {
		t.Fatal(err)
	}

	// setup receiver handler
	n1.SetHandler(inet.ProtocolTesting, receiver)

	log.Debugf("dialing %s", n2.ListenAddresses())
	if err := n1.DialPeer(ctx, n2.LocalPeer()); err != nil {
		t.Fatalf("Failed to dial:", err)
	}

	// launch sender!
	go sender(n2, n1.LocalPeer())

	// ok, what do we expect to happen? the receiver should
	// receive 10 requests and stop receiving, blocking the sender.
	// we can test this by counting 10x senderOpened requests

	<-senderOpened // wait for the sender to successfully open some.
	testStreamsOpened(limit - 1)

	// let's "handle" 3 requests.
	<-requestHandled
	<-requestHandled
	<-requestHandled
	// the sender should've now been able to open exactly 3 more.

	testStreamsOpened(3)

	// shouldn't have opened anything more
	testStreamsOpened(0)

	// let's "handle" 100 requests in batches of 5
	for i := 0; i < 20; i++ {
		<-requestHandled
		<-requestHandled
		<-requestHandled
		<-requestHandled
		<-requestHandled
		testStreamsOpened(5)
	}

	// success!

	// now for the sugar on top: let's tear down the receiver. it should
	// exit the sender.
	n1.Close()

	// shouldn't have opened anything more
	testStreamsOpened(0)

	select {
	case <-time.After(100 * time.Millisecond):
		t.Error("receiver shutdown failed to exit sender")
	case <-senderDone:
		log.Info("handler backpressure works!")
	}
}

// TestStBackpressureStreamWrite tests whether streams see proper
// backpressure when writing data over the network streams.
func TestStBackpressureStreamWrite(t *testing.T) {

	// senderWrote signals that the sender wrote bytes to remote.
	// the value is the count of bytes written.
	senderWrote := make(chan int, 10000)

	// sender signals it's done (errored out)
	senderDone := make(chan struct{})

	// writeStats lets us listen to all the writes and return
	// how many happened and how much was written
	writeStats := func() (int, int) {
		writes := 0
		bytes := 0
		for {
			select {
			case n := <-senderWrote:
				writes++
				bytes = bytes + n
			default:
				log.Debugf("stats: sender wrote %d bytes, %d writes", bytes, writes)
				return bytes, writes
			}
		}
	}

	// sender attempts to write as fast as possible, signaling on the
	// completion of every write. This makes it possible to see how
	// fast it's actually writing. We pair this with a receiver
	// that waits for a signal to read.
	sender := func(s inet.Stream) {
		defer func() {
			s.Close()
			senderDone <- struct{}{}
		}()

		// ready a buffer of random data
		buf := make([]byte, 65536)
		crand.Read(buf)

		for {
			// send a randomly sized subchunk
			from := rand.Intn(len(buf) / 2)
			to := rand.Intn(len(buf) / 2)
			sendbuf := buf[from : from+to]

			n, err := s.Write(sendbuf)
			if err != nil {
				log.Debug("sender error. exiting:", err)
				return
			}

			log.Debugf("sender wrote %d bytes", n)
			senderWrote <- n
		}
	}

	// receive a number of bytes from a stream.
	// returns the number of bytes written.
	receive := func(s inet.Stream, expect int) {
		log.Debugf("receiver to read %d bytes", expect)
		rbuf := make([]byte, expect)
		n, err := io.ReadFull(s, rbuf)
		if err != nil {
			t.Error("read failed:", err)
		}
		if expect != n {
			t.Error("read len differs: %d != %d", expect, n)
		}
	}

	// ok let's do it!

	// setup the networks
	ctx := context.Background()
	n1, err := GenNetwork(ctx)
	if err != nil {
		t.Fatal(err)
	}
	n2, err := GenNetwork(ctx)
	if err != nil {
		t.Fatal(err)
	}

	// setup sender handler on 1
	n1.SetHandler(inet.ProtocolTesting, sender)

	log.Debugf("dialing %s", n2.ListenAddresses())
	if err := n1.DialPeer(ctx, n2.LocalPeer()); err != nil {
		t.Fatalf("Failed to dial:", err)
	}

	// open a stream, from 2->1, this is our reader
	s, err := n2.NewStream(inet.ProtocolTesting, n1.LocalPeer())

	// let's make sure r/w works.
	testSenderWrote := func(bytesE int) {
		bytesA, writesA := writeStats()
		if bytesA != bytesE {
			t.Errorf("numbers failed: %d =?= %d bytes, via %d writes", bytesA, bytesE, writesA)
		}
	}

	// 500ms rounds of lockstep write + drain
	roundsStart := time.Now()
	roundsTotal := 0
	for roundsTotal < (2 << 20) {
		// let the sender fill its buffers, it will stop sending.
		<-time.After(300 * time.Millisecond)
		b, _ := writeStats()
		testSenderWrote(0)
		testSenderWrote(0)

		// drain it all, wait again
		receive(s, b)
		roundsTotal = roundsTotal + b
	}
	roundsTime := time.Now().Sub(roundsStart)

	// now read continously, while we measure stats.
	stop := make(chan struct{})
	contStart := time.Now()

	go func() {
		for {
			select {
			case <-stop:
				return
			default:
				receive(s, 2<<15)
			}
		}
	}()

	contTotal := 0
	for contTotal < (2 << 20) {
		n := <-senderWrote
		contTotal += n
	}
	stop <- struct{}{}
	contTime := time.Now().Sub(contStart)

	if roundsTime < contTime {
		t.Error("continuous should have been faster")
	}

	if roundsTotal < contTotal {
		t.Error("continuous should have been larger, too!")
	}

	<-time.After(300 * time.Millisecond)
	writeStats()
	testSenderWrote(0)
	testSenderWrote(0)

	// this doesn't work :(:
	// // now for the sugar on top: let's tear down the receiver. it should
	// // exit the sender.
	// n1.Close()
	// testSenderWrote(0)
	// testSenderWrote(0)
	// select {
	// case <-time.After(2 * time.Second):
	// 	t.Error("receiver shutdown failed to exit sender")
	// case <-senderDone:
	// 	log.Info("handler backpressure works!")
	// }
}
<commit_msg>backpressure: explanation + more rounds<commit_after>package backpressure_tests

import (
	crand "crypto/rand"
	"io"
	"math/rand"
	"testing"
	"time"

	inet "github.com/jbenet/go-ipfs/net"
	peer "github.com/jbenet/go-ipfs/peer"
	eventlog "github.com/jbenet/go-ipfs/util/eventlog"
	testutil "github.com/jbenet/go-ipfs/util/testutil"

	context "github.com/jbenet/go-ipfs/Godeps/_workspace/src/code.google.com/p/go.net/context"
)

var log = eventlog.Logger("backpressure")

func GenNetwork(ctx context.Context) (inet.Network, error) {
	p, err := testutil.PeerWithKeysAndAddress(testutil.RandLocalTCPAddress())
	if err != nil {
		return nil, err
	}

	listen := p.Addresses()
	ps := peer.NewPeerstore()
	return inet.NewNetwork(ctx, listen, p, ps)
}

// TestBackpressureStreamHandler tests whether mux handler
// ratelimiting works. Meaning, since the handler is sequential
// it should block senders.
//
// Important note: spdystream (which peerstream uses) has a set
// of n workers (n=spdsystream.FRAME_WORKERS) which handle new
// frames, including those starting new streams. So all of them
// can be in the handler at one time. Also, the sending side
// does not rate limit unless we call stream.Wait()
//
//
// Note: right now, this happens muxer-wide. the muxer should
// learn to flow control, so handlers cant block each other.
func TestBackpressureStreamHandler(t *testing.T) {
	t.Skip(`Sadly, as cool as this test is, it doesn't work
Because spdystream doesnt handle stream open backpressure
well IMO. I'll see about rewriting that part when it becomes
a problem.
`)

	// a number of concurrent request handlers
	limit := 10

	// our way to signal that we're done with 1 request
	requestHandled := make(chan struct{})

	// handler rate limiting
	receiverRatelimit := make(chan struct{}, limit)
	for i := 0; i < limit; i++ {
		receiverRatelimit <- struct{}{}
	}

	// sender counter of successfully opened streams
	senderOpened := make(chan struct{}, limit*100)

	// sender signals it's done (errored out)
	senderDone := make(chan struct{})

	// the receiver handles requests with some rate limiting
	receiver := func(s inet.Stream) {
		log.Debug("receiver received a stream")

		<-receiverRatelimit // acquire
		go func() {
			// our request handler. can do stuff here. we
			// simulate something taking time by waiting
			// on requestHandled
			log.Error("request worker handling...")
			<-requestHandled
			log.Error("request worker done!")
			receiverRatelimit <- struct{}{} // release
		}()
	}

	// the sender opens streams as fast as possible
	sender := func(net inet.Network, remote peer.Peer) {
		var s inet.Stream
		var err error
		defer func() {
			t.Error(err)
			log.Debug("sender error. exiting.")
			senderDone <- struct{}{}
		}()

		for {
			s, err = net.NewStream(inet.ProtocolTesting, remote)
			if err != nil {
				return
			}

			_ = s
			// if err = s.SwarmStream().Stream().Wait(); err != nil {
			// 	return
			// }

			// "count" another successfully opened stream
			// (large buffer so shouldn't block in normal operation)
			log.Debug("sender opened another stream!")
			senderOpened <- struct{}{}
		}
	}

	// count our senderOpened events
	countStreamsOpenedBySender := func(min int) int {
		opened := 0
		for opened < min {
			log.Debugf("countStreamsOpenedBySender got %d (min %d)", opened, min)
			select {
			case <-senderOpened:
				opened++
			case <-time.After(10 * time.Millisecond):
			}
		}
		return opened
	}

	// count our received events
	// waitForNReceivedStreams := func(n int) {
	// 	for n > 0 {
	// 		log.Debugf("waiting for %d received streams...", n)
	// 		select {
	// 		case <-receiverRatelimit:
	// 			n--
	// 		}
	// 	}
	// }

	testStreamsOpened := func(expected int) {
		log.Debugf("testing rate limited to %d streams", expected)
		if n := countStreamsOpenedBySender(expected); n != expected {
			t.Fatalf("rate limiting did not work :( -- %d != %d", expected, n)
		}
	}

	// ok that's enough setup. let's do it!

	ctx := context.Background()
	n1, err := GenNetwork(ctx)
	if err != nil {
		t.Fatal(err)
	}
	n2, err := GenNetwork(ctx)
	if err != nil {
		t.Fatal(err)
	}

	// setup receiver handler
	n1.SetHandler(inet.ProtocolTesting, receiver)

	log.Debugf("dialing %s", n2.ListenAddresses())
	if err := n1.DialPeer(ctx, n2.LocalPeer()); err != nil {
		t.Fatalf("Failed to dial:", err)
	}

	// launch sender!
	go sender(n2, n1.LocalPeer())

	// ok, what do we expect to happen? the receiver should
	// receive 10 requests and stop receiving, blocking the sender.
	// we can test this by counting 10x senderOpened requests

	<-senderOpened // wait for the sender to successfully open some.
	testStreamsOpened(limit - 1)

	// let's "handle" 3 requests.
	<-requestHandled
	<-requestHandled
	<-requestHandled
	// the sender should've now been able to open exactly 3 more.

	testStreamsOpened(3)

	// shouldn't have opened anything more
	testStreamsOpened(0)

	// let's "handle" 100 requests in batches of 5
	for i := 0; i < 20; i++ {
		<-requestHandled
		<-requestHandled
		<-requestHandled
		<-requestHandled
		<-requestHandled
		testStreamsOpened(5)
	}

	// success!

	// now for the sugar on top: let's tear down the receiver. it should
	// exit the sender.
	n1.Close()

	// shouldn't have opened anything more
	testStreamsOpened(0)

	select {
	case <-time.After(100 * time.Millisecond):
		t.Error("receiver shutdown failed to exit sender")
	case <-senderDone:
		log.Info("handler backpressure works!")
	}
}

// TestStBackpressureStreamWrite tests whether streams see proper
// backpressure when writing data over the network streams.
func TestStBackpressureStreamWrite(t *testing.T) {

	// senderWrote signals that the sender wrote bytes to remote.
	// the value is the count of bytes written.
	senderWrote := make(chan int, 10000)

	// sender signals it's done (errored out)
	senderDone := make(chan struct{})

	// writeStats lets us listen to all the writes and return
	// how many happened and how much was written
	writeStats := func() (int, int) {
		writes := 0
		bytes := 0
		for {
			select {
			case n := <-senderWrote:
				writes++
				bytes = bytes + n
			default:
				log.Debugf("stats: sender wrote %d bytes, %d writes", bytes, writes)
				return bytes, writes
			}
		}
	}

	// sender attempts to write as fast as possible, signaling on the
	// completion of every write. This makes it possible to see how
	// fast it's actually writing. We pair this with a receiver
	// that waits for a signal to read.
	sender := func(s inet.Stream) {
		defer func() {
			s.Close()
			senderDone <- struct{}{}
		}()

		// ready a buffer of random data
		buf := make([]byte, 65536)
		crand.Read(buf)

		for {
			// send a randomly sized subchunk
			from := rand.Intn(len(buf) / 2)
			to := rand.Intn(len(buf) / 2)
			sendbuf := buf[from : from+to]

			n, err := s.Write(sendbuf)
			if err != nil {
				log.Debug("sender error. exiting:", err)
				return
			}

			log.Debugf("sender wrote %d bytes", n)
			senderWrote <- n
		}
	}

	// receive a number of bytes from a stream.
	// returns the number of bytes written.
	receive := func(s inet.Stream, expect int) {
		log.Debugf("receiver to read %d bytes", expect)
		rbuf := make([]byte, expect)
		n, err := io.ReadFull(s, rbuf)
		if err != nil {
			t.Error("read failed:", err)
		}
		if expect != n {
			t.Error("read len differs: %d != %d", expect, n)
		}
	}

	// ok let's do it!

	// setup the networks
	ctx := context.Background()
	n1, err := GenNetwork(ctx)
	if err != nil {
		t.Fatal(err)
	}
	n2, err := GenNetwork(ctx)
	if err != nil {
		t.Fatal(err)
	}

	// setup sender handler on 1
	n1.SetHandler(inet.ProtocolTesting, sender)

	log.Debugf("dialing %s", n2.ListenAddresses())
	if err := n1.DialPeer(ctx, n2.LocalPeer()); err != nil {
		t.Fatalf("Failed to dial:", err)
	}

	// open a stream, from 2->1, this is our reader
	s, err := n2.NewStream(inet.ProtocolTesting, n1.LocalPeer())

	// let's make sure r/w works.
	testSenderWrote := func(bytesE int) {
		bytesA, writesA := writeStats()
		if bytesA != bytesE {
			t.Errorf("numbers failed: %d =?= %d bytes, via %d writes", bytesA, bytesE, writesA)
		}
	}

	// 500ms rounds of lockstep write + drain
	roundsStart := time.Now()
	roundsTotal := 0
	for roundsTotal < (2 << 20) {
		// let the sender fill its buffers, it will stop sending.
		<-time.After(300 * time.Millisecond)
		b, _ := writeStats()
		testSenderWrote(0)
		testSenderWrote(0)

		// drain it all, wait again
		receive(s, b)
		roundsTotal = roundsTotal + b
	}
	roundsTime := time.Now().Sub(roundsStart)

	// now read continously, while we measure stats.
	stop := make(chan struct{})
	contStart := time.Now()

	go func() {
		for {
			select {
			case <-stop:
				return
			default:
				receive(s, 2<<15)
			}
		}
	}()

	contTotal := 0
	for contTotal < (2 << 20) {
		n := <-senderWrote
		contTotal += n
	}
	stop <- struct{}{}
	contTime := time.Now().Sub(contStart)

	// now compare! continuous should've been faster AND larger
	if roundsTime < contTime {
		t.Error("continuous should have been faster")
	}

	if roundsTotal < contTotal {
		t.Error("continuous should have been larger, too!")
	}

	// and a couple rounds more for good measure ;)
	for i := 0; i < 3; i++ {
		// let the sender fill its buffers, it will stop sending.
		<-time.After(300 * time.Millisecond)
		b, _ := writeStats()
		testSenderWrote(0)
		testSenderWrote(0)

		// drain it all, wait again
		receive(s, b)
	}

	// this doesn't work :(:
	// // now for the sugar on top: let's tear down the receiver. it should
	// // exit the sender.
	// n1.Close()
	// testSenderWrote(0)
	// testSenderWrote(0)
	// select {
	// case <-time.After(2 * time.Second):
	// 	t.Error("receiver shutdown failed to exit sender")
	// case <-senderDone:
	// 	log.Info("handler backpressure works!")
	// }
}
<|endoftext|>


<commit_before>package qemu

import (
	"bufio"
	"bytes"
	"fmt"
	"github.com/mitchellh/multistep"
	"io"
	"log"
	"os/exec"
	"regexp"
	"strings"
	"sync"
	"syscall"
	"unicode"
)

type DriverCancelCallback func(state multistep.StateBag) bool

// A driver is able to talk to qemu-system-x86_64 and perform certain
// operations with it.
type Driver interface {
	// Stop stops a running machine, forcefully.
	Stop() error

	// Qemu executes the given command via qemu-system-x86_64
	Qemu(qemuArgs ...string) error

	// wait on shutdown of the VM with option to cancel
	WaitForShutdown(<-chan struct{}) bool

	// Qemu executes the given command via qemu-img
	QemuImg(...string) error

	// Verify checks to make sure that this driver should function
	// properly. If there is any indication the driver can't function,
	// this will return an error.
	Verify() error

	// Version reads the version of Qemu that is installed.
	Version() (string, error)
}

type QemuDriver struct {
	QemuPath    string
	QemuImgPath string

	vmCmd   *exec.Cmd
	vmEndCh <-chan int
	lock    sync.Mutex
}

func (d *QemuDriver) Stop() error {
	d.lock.Lock()
	defer d.lock.Unlock()

	if d.vmCmd != nil {
		if err := d.vmCmd.Process.Kill(); err != nil {
			return err
		}
	}

	return nil
}

func (d *QemuDriver) Qemu(qemuArgs ...string) error {
	d.lock.Lock()
	defer d.lock.Unlock()

	if d.vmCmd != nil {
		panic("Existing VM state found")
	}

	stdout_r, stdout_w := io.Pipe()
	stderr_r, stderr_w := io.Pipe()

	log.Printf("Executing %s: %#v", d.QemuPath, qemuArgs)
	cmd := exec.Command(d.QemuPath, qemuArgs...)
	cmd.Stdout = stdout_w
	cmd.Stderr = stderr_w

	err := cmd.Start()
	if err != nil {
		err = fmt.Errorf("Error starting VM: %s", err)
		return err
	}

	go logReader("Qemu stdout", stdout_r)
	go logReader("Qemu stderr", stderr_r)

	log.Printf("Started Qemu. Pid: %d", cmd.Process.Pid)

	// Wait for Qemu to complete in the background, and mark when its done
	endCh := make(chan int, 1)
	go func() {
		defer stderr_w.Close()
		defer stdout_w.Close()

		var exitCode int = 0
		if err := cmd.Wait(); err != nil {
			if exiterr, ok := err.(*exec.ExitError); ok {
				// The program has exited with an exit code != 0
				if status, ok := exiterr.Sys().(syscall.WaitStatus); ok {
					exitCode = status.ExitStatus()
				} else {
					exitCode = 254
				}
			}
		}

		endCh <- exitCode

		d.lock.Lock()
		defer d.lock.Unlock()
		d.vmCmd = nil
		d.vmEndCh = nil
	}()

	// Setup our state so we know we are running
	d.vmCmd = cmd
	d.vmEndCh = endCh

	return nil
}

func (d *QemuDriver) WaitForShutdown(cancelCh <-chan struct{}) bool {
	d.lock.Lock()
	endCh := d.vmEndCh
	d.lock.Unlock()

	if endCh == nil {
		return true
	}

	select {
	case <-endCh:
		return true
	case <-cancelCh:
		return false
	}
}

func (d *QemuDriver) QemuImg(args ...string) error {
	var stdout, stderr bytes.Buffer

	log.Printf("Executing qemu-img: %#v", args)
	cmd := exec.Command(d.QemuImgPath, args...)
	cmd.Stdout = &stdout
	cmd.Stderr = &stderr
	err := cmd.Run()

	stdoutString := strings.TrimSpace(stdout.String())
	stderrString := strings.TrimSpace(stderr.String())

	if _, ok := err.(*exec.ExitError); ok {
		err = fmt.Errorf("QemuImg error: %s", stderrString)
	}

	log.Printf("stdout: %s", stdoutString)
	log.Printf("stderr: %s", stderrString)

	return err
}

func (d *QemuDriver) Verify() error {
	return nil
}

func (d *QemuDriver) Version() (string, error) {
	var stdout bytes.Buffer

	cmd := exec.Command(d.QemuPath, "-version")
	cmd.Stdout = &stdout
	if err := cmd.Run(); err != nil {
		return "", err
	}

	versionOutput := strings.TrimSpace(stdout.String())
	log.Printf("Qemu --version output: %s", versionOutput)
	versionRe := regexp.MustCompile("qemu-kvm-[0-9]\\.[0-9]")
	matches := versionRe.Split(versionOutput, 2)
	if len(matches) == 0 {
		return "", fmt.Errorf("No version found: %s", versionOutput)
	}

	log.Printf("Qemu version: %s", matches[0])
	return matches[0], nil
}

func logReader(name string, r io.Reader) {
	bufR := bufio.NewReader(r)
	for {
		line, err := bufR.ReadString('\n')
		if line != "" {
			line = strings.TrimRightFunc(line, unicode.IsSpace)
			log.Printf("%s: %s", name, line)
		}

		if err == io.EOF {
			break
		}
	}
}
<commit_msg>builder/qemu: catch early exits of qemu<commit_after>package qemu

import (
	"bufio"
	"bytes"
	"fmt"
	"github.com/mitchellh/multistep"
	"io"
	"log"
	"os/exec"
	"regexp"
	"strings"
	"sync"
	"syscall"
	"time"
	"unicode"
)

type DriverCancelCallback func(state multistep.StateBag) bool

// A driver is able to talk to qemu-system-x86_64 and perform certain
// operations with it.
type Driver interface {
	// Stop stops a running machine, forcefully.
	Stop() error

	// Qemu executes the given command via qemu-system-x86_64
	Qemu(qemuArgs ...string) error

	// wait on shutdown of the VM with option to cancel
	WaitForShutdown(<-chan struct{}) bool

	// Qemu executes the given command via qemu-img
	QemuImg(...string) error

	// Verify checks to make sure that this driver should function
	// properly. If there is any indication the driver can't function,
	// this will return an error.
	Verify() error

	// Version reads the version of Qemu that is installed.
	Version() (string, error)
}

type QemuDriver struct {
	QemuPath    string
	QemuImgPath string

	vmCmd   *exec.Cmd
	vmEndCh <-chan int
	lock    sync.Mutex
}

func (d *QemuDriver) Stop() error {
	d.lock.Lock()
	defer d.lock.Unlock()

	if d.vmCmd != nil {
		if err := d.vmCmd.Process.Kill(); err != nil {
			return err
		}
	}

	return nil
}

func (d *QemuDriver) Qemu(qemuArgs ...string) error {
	d.lock.Lock()
	defer d.lock.Unlock()

	if d.vmCmd != nil {
		panic("Existing VM state found")
	}

	stdout_r, stdout_w := io.Pipe()
	stderr_r, stderr_w := io.Pipe()

	log.Printf("Executing %s: %#v", d.QemuPath, qemuArgs)
	cmd := exec.Command(d.QemuPath, qemuArgs...)
	cmd.Stdout = stdout_w
	cmd.Stderr = stderr_w

	err := cmd.Start()
	if err != nil {
		err = fmt.Errorf("Error starting VM: %s", err)
		return err
	}

	go logReader("Qemu stdout", stdout_r)
	go logReader("Qemu stderr", stderr_r)

	log.Printf("Started Qemu. Pid: %d", cmd.Process.Pid)

	// Wait for Qemu to complete in the background, and mark when its done
	endCh := make(chan int, 1)
	go func() {
		defer stderr_w.Close()
		defer stdout_w.Close()

		var exitCode int = 0
		if err := cmd.Wait(); err != nil {
			if exiterr, ok := err.(*exec.ExitError); ok {
				// The program has exited with an exit code != 0
				if status, ok := exiterr.Sys().(syscall.WaitStatus); ok {
					exitCode = status.ExitStatus()
				} else {
					exitCode = 254
				}
			}
		}

		endCh <- exitCode

		d.lock.Lock()
		defer d.lock.Unlock()
		d.vmCmd = nil
		d.vmEndCh = nil
	}()

	// Wait at least a couple seconds for an early fail from Qemu so
	// we can report that.
	select {
	case exit := <-endCh:
		if exit != 0 {
			return fmt.Errorf("Qemu failed to start. Please run with logs to get more info.")
		}
	case <-time.After(2 * time.Second):
	}

	// Setup our state so we know we are running
	d.vmCmd = cmd
	d.vmEndCh = endCh

	return nil
}

func (d *QemuDriver) WaitForShutdown(cancelCh <-chan struct{}) bool {
	d.lock.Lock()
	endCh := d.vmEndCh
	d.lock.Unlock()

	if endCh == nil {
		return true
	}

	select {
	case <-endCh:
		return true
	case <-cancelCh:
		return false
	}
}

func (d *QemuDriver) QemuImg(args ...string) error {
	var stdout, stderr bytes.Buffer

	log.Printf("Executing qemu-img: %#v", args)
	cmd := exec.Command(d.QemuImgPath, args...)
	cmd.Stdout = &stdout
	cmd.Stderr = &stderr
	err := cmd.Run()

	stdoutString := strings.TrimSpace(stdout.String())
	stderrString := strings.TrimSpace(stderr.String())

	if _, ok := err.(*exec.ExitError); ok {
		err = fmt.Errorf("QemuImg error: %s", stderrString)
	}

	log.Printf("stdout: %s", stdoutString)
	log.Printf("stderr: %s", stderrString)

	return err
}

func (d *QemuDriver) Verify() error {
	return nil
}

func (d *QemuDriver) Version() (string, error) {
	var stdout bytes.Buffer

	cmd := exec.Command(d.QemuPath, "-version")
	cmd.Stdout = &stdout
	if err := cmd.Run(); err != nil {
		return "", err
	}

	versionOutput := strings.TrimSpace(stdout.String())
	log.Printf("Qemu --version output: %s", versionOutput)
	versionRe := regexp.MustCompile("qemu-kvm-[0-9]\\.[0-9]")
	matches := versionRe.Split(versionOutput, 2)
	if len(matches) == 0 {
		return "", fmt.Errorf("No version found: %s", versionOutput)
	}

	log.Printf("Qemu version: %s", matches[0])
	return matches[0], nil
}

func logReader(name string, r io.Reader) {
	bufR := bufio.NewReader(r)
	for {
		line, err := bufR.ReadString('\n')
		if line != "" {
			line = strings.TrimRightFunc(line, unicode.IsSpace)
			log.Printf("%s: %s", name, line)
		}

		if err == io.EOF {
			break
		}
	}
}
<|endoftext|>


<commit_before>/*
 * Elliptic curve 'Secp256k1' methods.
 *
 * (c) 2011-2013 Bernd Fix   >Y<
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or (at
 * your option) any later version.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

package ecc

///////////////////////////////////////////////////////////////////////
// Import external declarations

import (
	"errors"
	"github.com/bfix/gospel/crypto"
	"github.com/bfix/gospel/math"
	"math/big"
)

///////////////////////////////////////////////////////////////////////
// Point (x,y) on the curve

type point struct { // exported point type
	x, y *big.Int // coordinate values
}

// instaniate a new point
func NewPoint(a, b *big.Int) *point {
	p := &point{}
	p.x = new(big.Int).Set(a)
	p.y = new(big.Int).Set(b)
	return p
}

// point at infinity
var inf = NewPoint(math.ZERO, math.ZERO)

// get base point
func GetBasePoint() *point {
	return NewPoint(curve_gx, curve_gy)
}

/////////////////////////////////////////////////////////////////////
// get byte representation of point (compressed or uncompressed).

func pointAsBytes(p *point, compressed bool) []byte {
	if IsEqual(p, inf) {
		return []byte{0}
	}
	res := make([]byte, 0)
	if compressed {
		rc := byte(2)
		if p.y.Bit(0) == 1 {
			rc = 3
		}
		res = append(res, rc)
		res = append(res, coordAsBytes(p.x)...)
	} else {
		res = append(res, 4)
		res = append(res, coordAsBytes(p.x)...)
		res = append(res, coordAsBytes(p.y)...)
	}
	return res
}

// helper: convert coordinate to byte array of correct length
func coordAsBytes(v *big.Int) []byte {
	bv := v.Bytes()
	plen := 32 - len(bv)
	if plen == 0 {
		return bv
	}
	b := make([]byte, plen)
	return append(b, bv...)
}

/////////////////////////////////////////////////////////////////////
// reconstruct point from binary representation

func pointFromBytes(b []byte) (p *point, err error) {
	p = NewPoint(math.ZERO, math.ZERO)
	err = nil
	switch b[0] {
	case 0:
	case 4:
		p.x.SetBytes(b[1:33])
		p.y.SetBytes(b[33:])
	case 3:
		p.x.SetBytes(b[1:])
		p.y, err = computeY(p.x, 1)
		if err != nil {
			return
		}
	case 2:
		p.x.SetBytes(b[1:])
		p.y, err = computeY(p.x, 0)
		if err != nil {
			return
		}
	default:
		err = errors.New("Invalid binary point representation")
	}
	return
}

// helper: reconstruct y-coordinate of point
func computeY(x *big.Int, m uint) (y *big.Int, err error) {
	y = big.NewInt(0)
	err = nil
	y2 := p_add(p_cub(x), curve_b)
	y, err = math.Sqrt_modP(y2, curve_p)
	if err == nil {
		if y.Bit(0) != m {
			y = new(big.Int).Sub(curve_p, y)
		}
	}
	return
}

/////////////////////////////////////////////////////////////////////
// check if two points are equal

func IsEqual(p1, p2 *point) bool {
	return p1.x.Cmp(p2.x) == 0 && p1.y.Cmp(p2.y) == 0
}

///////////////////////////////////////////////////////////////////////
// check if a point is at infinity

func isInf(p *point) bool {
	return p.x.Cmp(math.ZERO) == 0 && p.y.Cmp(math.ZERO) == 0
}

///////////////////////////////////////////////////////////////////////
// check if a point (x,y) is on the curve

func IsOnCurve(p *point) bool {
	// y² = x³ + 7
	y2 := p_sqr(p.y)
	x3 := p_cub(p.x)
	return y2.Cmp(p_add(x3, curve_b)) == 0
}

///////////////////////////////////////////////////////////////////////
// Add two points on the curve

func add(p1, p2 *point) *point {
	if IsEqual(p1, p2) {
		return double(p1)
	}
	if IsEqual(p1, inf) {
		return p2
	}
	if IsEqual(p2, inf) {
		return p1
	}
	_p1 := NewPoint_(p1.x, p1.y, math.ONE)
	_p2 := NewPoint_(p2.x, p2.y, math.ONE)
	return conv(add_(_p1, _p2))
}

///////////////////////////////////////////////////////////////////////
// Double a point on the curve

func double(p *point) *point {
	if IsEqual(p, inf) {
		return inf
	}
	return conv(double_(NewPoint_(p.x, p.y, math.ONE)))
}

///////////////////////////////////////////////////////////////////////
// Multiply a point on the curve with a scalar value k using
// a Montgomery multiplication approach

func scalarMult(p *point, k *big.Int) *point {
	return conv(scalarMult_(NewPoint_(p.x, p.y, math.ONE), k))
}

///////////////////////////////////////////////////////////////////////
// Multiply the base point of the curve with a scalar value k

func ScalarMultBase(k *big.Int) *point {
	return scalarMult(GetBasePoint(), k)
}

///////////////////////////////////////////////////////////////////////
// points (x,y) on the curve are represented internally in Jacobian
// coordinates (X,Y,Z) with "x = X/Z^2" and "y = Y/Z^3". See:
// [http://www.hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html]

type point_ struct { // internal point type
	x, y, z *big.Int // using Jacobian coordinates
}

// instaniate a new point
func NewPoint_(a, b, c *big.Int) *point_ {
	p := &point_{}
	p.x = new(big.Int).Set(a)
	p.y = new(big.Int).Set(b)
	p.z = new(big.Int).Set(c)
	return p
}

// point at infinity
var inf_ = NewPoint_(inf.x, inf.y, math.ONE)

///////////////////////////////////////////////////////////////////////
// check if a point is at infinity

func isInf_(p *point_) bool {
	return p.x.Cmp(math.ZERO) == 0 && p.y.Cmp(math.ZERO) == 0
}

///////////////////////////////////////////////////////////////////////
// convert internal point to external representation

func conv(p *point_) *point {
	zi := p_inv(p.z)
	x := p_mul(p.x, p_sqr(zi))
	y := p_mul(p.y, p_cub(zi))
	return NewPoint(x, y)
}

///////////////////////////////////////////////////////////////////////
// add two points on the curve
// [http://www.hyperelliptic.org/EFD/g1p/data/shortw/jacobian-0/addition/add-2007-bl]

func add_(p1, p2 *point_) *point_ {
	if isInf_(p1) {
		return p2
	}
	if isInf_(p2) {
		return p1
	}
	z1z1 := p_sqr(p1.z)
	z2z2 := p_sqr(p2.z)
	u1 := p_mul(p1.x, z2z2)
	u2 := p_mul(p2.x, z1z1)
	s1 := p_mul(p_mul(p1.y, p2.z), z2z2)
	s2 := p_mul(p_mul(p2.y, p1.z), z1z1)
	h := p_sub(u2, u1)
	i := p_sqr(p_mul(math.TWO, h))
	j := p_mul(h, i)
	r := p_mul(math.TWO, p_sub(s2, s1))
	v := p_mul(u1, i)
	w := p_add(p1.z, p2.z)
	x := p_sub(p_sub(p_sqr(r), j), p_mul(math.TWO, v))
	y := p_sub(p_mul(r, p_sub(v, x)), p_mul(math.TWO, p_mul(s1, j)))
	z := p_mul(p_sub(p_sub(p_sqr(w), z1z1), z2z2), h)
	return NewPoint_(x, y, z)
}

///////////////////////////////////////////////////////////////////////
// double a point on the curve
// [http://www.hyperelliptic.org/EFD/g1p/data/shortw/jacobian-0/doubling/dbl-2009-alnr]

func double_(p *point_) *point_ {
	if isInf_(p) {
		return p
	}
	a := p_sqr(p.x)
	b := p_sqr(p.y)
	zz := p_sqr(p.z)
	c := p_sqr(b)
	d := p_mul(math.TWO, p_sub(p_sub(p_sqr(_add(p.x, b)), a), c))
	e := p_mul(math.THREE, a)
	f := p_sqr(e)
	x := p_sub(f, p_mul(math.TWO, d))
	y := p_sub(p_mul(e, p_sub(d, x)), p_mul(math.EIGHT, c))
	z := p_sub(p_sub(p_sqr(p_add(p.y, p.z)), b), zz)
	return NewPoint_(x, y, z)
}

///////////////////////////////////////////////////////////////////////
// Multiply a point on the curve with a scalar value k using
// a Montgomery multiplication algorithm

func scalarMult_(p *point_, k *big.Int) *point_ {

	if isInf_(p) {
		return p
	}
	if k.Cmp(math.ZERO) == 0 {
		return inf_
	}

	r := inf_
	for _, val := range k.Bytes() {
		for pos := 0; pos < 8; pos++ {
			r = double_(r)
			if val&0x80 == 0x80 {
				r = add_(p, r)
			}
			val <<= 1
		}
	}
	return r
}

///////////////////////////////////////////////////////////////////////
// helper methods for arithmetic operations on curve points

//---------------------------------------------------------------------
//	modulus
//---------------------------------------------------------------------

func _mod(a, n *big.Int) *big.Int {
	return new(big.Int).Mod(a, n)
}

func n_mod(a *big.Int) *big.Int {
	return _mod(a, curve_n)
}

//---------------------------------------------------------------------
//	modular inverse
//---------------------------------------------------------------------

func _inv(a, n *big.Int) *big.Int {
	return new(big.Int).ModInverse(a, n)
}

func p_inv(a *big.Int) *big.Int {
	return _inv(a, curve_p)
}

func n_inv(a *big.Int) *big.Int {
	return _inv(a, curve_n)
}

//---------------------------------------------------------------------
//	multiplication
//---------------------------------------------------------------------

func _mul(a, b, n *big.Int) *big.Int {
	return _mod(new(big.Int).Mul(a, b), n)
}

func p_mul(a, b *big.Int) *big.Int {
	return _mul(a, b, curve_p)
}

func n_mul(a, b *big.Int) *big.Int {
	return _mul(a, b, curve_n)
}

//---------------------------------------------------------------------
//	squares and cubes
//---------------------------------------------------------------------

func p_sqr(a *big.Int) *big.Int {
	return p_mul(a, a)
}

func p_cub(a *big.Int) *big.Int {
	return p_mul(p_sqr(a), a)
}

//---------------------------------------------------------------------
//	addition and subtraction
//---------------------------------------------------------------------

func p_sub(a, b *big.Int) *big.Int {
	x := new(big.Int).Sub(a, b)
	if x.Sign() == -1 {
		x.Add(x, curve_p)
	}
	return x
}

func _add(a, b *big.Int) *big.Int {
	return new(big.Int).Add(a, b)
}

func p_add(a, b *big.Int) *big.Int {
	return _mod(_add(a, b), curve_p)
}

//---------------------------------------------------------------------
//	generate random integer value in given range
//---------------------------------------------------------------------

func n_rnd(a *big.Int) *big.Int {
	return crypto.RandBigInt(a, curve_n)
}
<commit_msg>Return flag for compression on import of binary point data.<commit_after>/*
 * Elliptic curve 'Secp256k1' methods.
 *
 * (c) 2011-2013 Bernd Fix   >Y<
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or (at
 * your option) any later version.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

package ecc

///////////////////////////////////////////////////////////////////////
// Import external declarations

import (
	"errors"
	"github.com/bfix/gospel/crypto"
	"github.com/bfix/gospel/math"
	"math/big"
)

///////////////////////////////////////////////////////////////////////
// Point (x,y) on the curve

type point struct { // exported point type
	x, y *big.Int // coordinate values
}

// instaniate a new point
func NewPoint(a, b *big.Int) *point {
	p := &point{}
	p.x = new(big.Int).Set(a)
	p.y = new(big.Int).Set(b)
	return p
}

// point at infinity
var inf = NewPoint(math.ZERO, math.ZERO)

// get base point
func GetBasePoint() *point {
	return NewPoint(curve_gx, curve_gy)
}

/////////////////////////////////////////////////////////////////////
// get byte representation of point (compressed or uncompressed).

func pointAsBytes(p *point, compressed bool) []byte {
	if IsEqual(p, inf) {
		return []byte{0}
	}
	res := make([]byte, 0)
	if compressed {
		rc := byte(2)
		if p.y.Bit(0) == 1 {
			rc = 3
		}
		res = append(res, rc)
		res = append(res, coordAsBytes(p.x)...)
	} else {
		res = append(res, 4)
		res = append(res, coordAsBytes(p.x)...)
		res = append(res, coordAsBytes(p.y)...)
	}
	return res
}

// helper: convert coordinate to byte array of correct length
func coordAsBytes(v *big.Int) []byte {
	bv := v.Bytes()
	plen := 32 - len(bv)
	if plen == 0 {
		return bv
	}
	b := make([]byte, plen)
	return append(b, bv...)
}

/////////////////////////////////////////////////////////////////////
// reconstruct point from binary representation

func pointFromBytes(b []byte) (p *point, compr bool, err error) {
	p = NewPoint(math.ZERO, math.ZERO)
	err = nil
	compr = true
	switch b[0] {
	case 0:
	case 4:
		p.x.SetBytes(b[1:33])
		p.y.SetBytes(b[33:])
		compr = false
	case 3:
		p.x.SetBytes(b[1:])
		p.y, err = computeY(p.x, 1)
		if err != nil {
			return
		}
	case 2:
		p.x.SetBytes(b[1:])
		p.y, err = computeY(p.x, 0)
		if err != nil {
			return
		}
	default:
		err = errors.New("Invalid binary point representation")
	}
	return
}

// helper: reconstruct y-coordinate of point
func computeY(x *big.Int, m uint) (y *big.Int, err error) {
	y = big.NewInt(0)
	err = nil
	y2 := p_add(p_cub(x), curve_b)
	y, err = math.Sqrt_modP(y2, curve_p)
	if err == nil {
		if y.Bit(0) != m {
			y = new(big.Int).Sub(curve_p, y)
		}
	}
	return
}

/////////////////////////////////////////////////////////////////////
// check if two points are equal

func IsEqual(p1, p2 *point) bool {
	return p1.x.Cmp(p2.x) == 0 && p1.y.Cmp(p2.y) == 0
}

///////////////////////////////////////////////////////////////////////
// check if a point is at infinity

func isInf(p *point) bool {
	return p.x.Cmp(math.ZERO) == 0 && p.y.Cmp(math.ZERO) == 0
}

///////////////////////////////////////////////////////////////////////
// check if a point (x,y) is on the curve

func IsOnCurve(p *point) bool {
	// y² = x³ + 7
	y2 := p_sqr(p.y)
	x3 := p_cub(p.x)
	return y2.Cmp(p_add(x3, curve_b)) == 0
}

///////////////////////////////////////////////////////////////////////
// Add two points on the curve

func add(p1, p2 *point) *point {
	if IsEqual(p1, p2) {
		return double(p1)
	}
	if IsEqual(p1, inf) {
		return p2
	}
	if IsEqual(p2, inf) {
		return p1
	}
	_p1 := NewPoint_(p1.x, p1.y, math.ONE)
	_p2 := NewPoint_(p2.x, p2.y, math.ONE)
	return conv(add_(_p1, _p2))
}

///////////////////////////////////////////////////////////////////////
// Double a point on the curve

func double(p *point) *point {
	if IsEqual(p, inf) {
		return inf
	}
	return conv(double_(NewPoint_(p.x, p.y, math.ONE)))
}

///////////////////////////////////////////////////////////////////////
// Multiply a point on the curve with a scalar value k using
// a Montgomery multiplication approach

func scalarMult(p *point, k *big.Int) *point {
	return conv(scalarMult_(NewPoint_(p.x, p.y, math.ONE), k))
}

///////////////////////////////////////////////////////////////////////
// Multiply the base point of the curve with a scalar value k

func ScalarMultBase(k *big.Int) *point {
	return scalarMult(GetBasePoint(), k)
}

///////////////////////////////////////////////////////////////////////
// points (x,y) on the curve are represented internally in Jacobian
// coordinates (X,Y,Z) with "x = X/Z^2" and "y = Y/Z^3". See:
// [http://www.hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html]

type point_ struct { // internal point type
	x, y, z *big.Int // using Jacobian coordinates
}

// instaniate a new point
func NewPoint_(a, b, c *big.Int) *point_ {
	p := &point_{}
	p.x = new(big.Int).Set(a)
	p.y = new(big.Int).Set(b)
	p.z = new(big.Int).Set(c)
	return p
}

// point at infinity
var inf_ = NewPoint_(inf.x, inf.y, math.ONE)

///////////////////////////////////////////////////////////////////////
// check if a point is at infinity

func isInf_(p *point_) bool {
	return p.x.Cmp(math.ZERO) == 0 && p.y.Cmp(math.ZERO) == 0
}

///////////////////////////////////////////////////////////////////////
// convert internal point to external representation

func conv(p *point_) *point {
	zi := p_inv(p.z)
	x := p_mul(p.x, p_sqr(zi))
	y := p_mul(p.y, p_cub(zi))
	return NewPoint(x, y)
}

///////////////////////////////////////////////////////////////////////
// add two points on the curve
// [http://www.hyperelliptic.org/EFD/g1p/data/shortw/jacobian-0/addition/add-2007-bl]

func add_(p1, p2 *point_) *point_ {
	if isInf_(p1) {
		return p2
	}
	if isInf_(p2) {
		return p1
	}
	z1z1 := p_sqr(p1.z)
	z2z2 := p_sqr(p2.z)
	u1 := p_mul(p1.x, z2z2)
	u2 := p_mul(p2.x, z1z1)
	s1 := p_mul(p_mul(p1.y, p2.z), z2z2)
	s2 := p_mul(p_mul(p2.y, p1.z), z1z1)
	h := p_sub(u2, u1)
	i := p_sqr(p_mul(math.TWO, h))
	j := p_mul(h, i)
	r := p_mul(math.TWO, p_sub(s2, s1))
	v := p_mul(u1, i)
	w := p_add(p1.z, p2.z)
	x := p_sub(p_sub(p_sqr(r), j), p_mul(math.TWO, v))
	y := p_sub(p_mul(r, p_sub(v, x)), p_mul(math.TWO, p_mul(s1, j)))
	z := p_mul(p_sub(p_sub(p_sqr(w), z1z1), z2z2), h)
	return NewPoint_(x, y, z)
}

///////////////////////////////////////////////////////////////////////
// double a point on the curve
// [http://www.hyperelliptic.org/EFD/g1p/data/shortw/jacobian-0/doubling/dbl-2009-alnr]

func double_(p *point_) *point_ {
	if isInf_(p) {
		return p
	}
	a := p_sqr(p.x)
	b := p_sqr(p.y)
	zz := p_sqr(p.z)
	c := p_sqr(b)
	d := p_mul(math.TWO, p_sub(p_sub(p_sqr(_add(p.x, b)), a), c))
	e := p_mul(math.THREE, a)
	f := p_sqr(e)
	x := p_sub(f, p_mul(math.TWO, d))
	y := p_sub(p_mul(e, p_sub(d, x)), p_mul(math.EIGHT, c))
	z := p_sub(p_sub(p_sqr(p_add(p.y, p.z)), b), zz)
	return NewPoint_(x, y, z)
}

///////////////////////////////////////////////////////////////////////
// Multiply a point on the curve with a scalar value k using
// a Montgomery multiplication algorithm

func scalarMult_(p *point_, k *big.Int) *point_ {

	if isInf_(p) {
		return p
	}
	if k.Cmp(math.ZERO) == 0 {
		return inf_
	}

	r := inf_
	for _, val := range k.Bytes() {
		for pos := 0; pos < 8; pos++ {
			r = double_(r)
			if val&0x80 == 0x80 {
				r = add_(p, r)
			}
			val <<= 1
		}
	}
	return r
}

///////////////////////////////////////////////////////////////////////
// helper methods for arithmetic operations on curve points

//---------------------------------------------------------------------
//	modulus
//---------------------------------------------------------------------

func _mod(a, n *big.Int) *big.Int {
	return new(big.Int).Mod(a, n)
}

func n_mod(a *big.Int) *big.Int {
	return _mod(a, curve_n)
}

//---------------------------------------------------------------------
//	modular inverse
//---------------------------------------------------------------------

func _inv(a, n *big.Int) *big.Int {
	return new(big.Int).ModInverse(a, n)
}

func p_inv(a *big.Int) *big.Int {
	return _inv(a, curve_p)
}

func n_inv(a *big.Int) *big.Int {
	return _inv(a, curve_n)
}

//---------------------------------------------------------------------
//	multiplication
//---------------------------------------------------------------------

func _mul(a, b, n *big.Int) *big.Int {
	return _mod(new(big.Int).Mul(a, b), n)
}

func p_mul(a, b *big.Int) *big.Int {
	return _mul(a, b, curve_p)
}

func n_mul(a, b *big.Int) *big.Int {
	return _mul(a, b, curve_n)
}

//---------------------------------------------------------------------
//	squares and cubes
//---------------------------------------------------------------------

func p_sqr(a *big.Int) *big.Int {
	return p_mul(a, a)
}

func p_cub(a *big.Int) *big.Int {
	return p_mul(p_sqr(a), a)
}

//---------------------------------------------------------------------
//	addition and subtraction
//---------------------------------------------------------------------

func p_sub(a, b *big.Int) *big.Int {
	x := new(big.Int).Sub(a, b)
	if x.Sign() == -1 {
		x.Add(x, curve_p)
	}
	return x
}

func _add(a, b *big.Int) *big.Int {
	return new(big.Int).Add(a, b)
}

func p_add(a, b *big.Int) *big.Int {
	return _mod(_add(a, b), curve_p)
}

//---------------------------------------------------------------------
//	generate random integer value in given range
//---------------------------------------------------------------------

func n_rnd(a *big.Int) *big.Int {
	return crypto.RandBigInt(a, curve_n)
}
<|endoftext|>