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

package ssa

// deadcode removes dead code from f.
func deadcode(f *Func) {

	// Find all reachable basic blocks.
	reachable := make([]bool, f.NumBlocks())
	reachable[f.Entry.ID] = true
	p := []*Block{f.Entry} // stack-like worklist
	for len(p) > 0 {
		// Pop a reachable block
		b := p[len(p)-1]
		p = p[:len(p)-1]
		// Mark successors as reachable
		for _, c := range b.Succs {
			if !reachable[c.ID] {
				reachable[c.ID] = true
				p = append(p, c) // push
			}
		}
	}

	// Find all live values
	live := make([]bool, f.NumValues()) // flag to set for each live value
	var q []*Value                      // stack-like worklist of unscanned values

	// Starting set: all control values of reachable blocks are live.
	for _, b := range f.Blocks {
		if !reachable[b.ID] {
			continue
		}
		if v := b.Control; v != nil && !live[v.ID] {
			live[v.ID] = true
			q = append(q, v)
		}
	}

	// Compute transitive closure of live values.
	for len(q) > 0 {
		// pop a reachable value
		v := q[len(q)-1]
		q = q[:len(q)-1]
		for _, x := range v.Args {
			if !live[x.ID] {
				live[x.ID] = true
				q = append(q, x) // push
			}
		}
	}

	// Remove dead values from blocks' value list.  Return dead
	// value ids to the allocator.
	for _, b := range f.Blocks {
		i := 0
		for _, v := range b.Values {
			if live[v.ID] {
				b.Values[i] = v
				i++
			} else {
				f.vid.put(v.ID)
			}
		}
		// aid GC
		tail := b.Values[i:]
		for j := range tail {
			tail[j] = nil
		}
		b.Values = b.Values[:i]
	}

	// Remove unreachable blocks.  Return dead block ids to allocator.
	i := 0
	for _, b := range f.Blocks {
		if reachable[b.ID] {
			f.Blocks[i] = b
			i++
		} else {
			if len(b.Values) > 0 {
				b.Fatalf("live values in unreachable block %v: %v", b, b.Values)
			}
			f.bid.put(b.ID)
		}
	}
	// zero remainder to help GC
	tail := f.Blocks[i:]
	for j := range tail {
		tail[j] = nil
	}
	f.Blocks = f.Blocks[:i]

	// TODO: renumber Blocks and Values densely?
	// TODO: save dead Values and Blocks for reuse?  Or should we just let GC handle it?
}

// There was an edge b->c.  c has been removed from b's successors.
// Fix up c to handle that fact.
func (f *Func) removePredecessor(b, c *Block) {
	work := [][2]*Block{{b, c}}

	for len(work) > 0 {
		b, c := work[0][0], work[0][1]
		work = work[1:]

		// find index of b in c's predecessor list
		var i int
		for j, p := range c.Preds {
			if p == b {
				i = j
				break
			}
		}

		n := len(c.Preds) - 1
		c.Preds[i] = c.Preds[n]
		c.Preds[n] = nil // aid GC
		c.Preds = c.Preds[:n]

		// rewrite phi ops to match the new predecessor list
		for _, v := range c.Values {
			if v.Op != OpPhi {
				continue
			}
			v.Args[i] = v.Args[n]
			v.Args[n] = nil // aid GC
			v.Args = v.Args[:n]
			if n == 1 {
				v.Op = OpCopy
			}
		}

		if n == 0 {
			// c is now dead--recycle its values
			for _, v := range c.Values {
				f.vid.put(v.ID)
			}
			c.Values = nil
			// Also kill any successors of c now, to spare later processing.
			for _, succ := range c.Succs {
				work = append(work, [2]*Block{c, succ})
			}
			c.Succs = nil
			c.Kind = BlockDead
			c.Control = nil
		}
	}
}
<commit_msg>[dev.ssa] cmd/compile/internal/ssa: Phi inputs from dead blocks are not live<commit_after>// Copyright 2015 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package ssa

// deadcode removes dead code from f.
func deadcode(f *Func) {

	// Find all reachable basic blocks.
	reachable := make([]bool, f.NumBlocks())
	reachable[f.Entry.ID] = true
	p := []*Block{f.Entry} // stack-like worklist
	for len(p) > 0 {
		// Pop a reachable block
		b := p[len(p)-1]
		p = p[:len(p)-1]
		// Mark successors as reachable
		for _, c := range b.Succs {
			if !reachable[c.ID] {
				reachable[c.ID] = true
				p = append(p, c) // push
			}
		}
	}

	// Find all live values
	live := make([]bool, f.NumValues()) // flag to set for each live value
	var q []*Value                      // stack-like worklist of unscanned values

	// Starting set: all control values of reachable blocks are live.
	for _, b := range f.Blocks {
		if !reachable[b.ID] {
			continue
		}
		if v := b.Control; v != nil && !live[v.ID] {
			live[v.ID] = true
			q = append(q, v)
		}
	}

	// Compute transitive closure of live values.
	for len(q) > 0 {
		// pop a reachable value
		v := q[len(q)-1]
		q = q[:len(q)-1]
		for i, x := range v.Args {
			if v.Op == OpPhi && !reachable[v.Block.Preds[i].ID] {
				continue
			}
			if !live[x.ID] {
				live[x.ID] = true
				q = append(q, x) // push
			}
		}
	}

	// Remove dead values from blocks' value list.  Return dead
	// value ids to the allocator.
	for _, b := range f.Blocks {
		i := 0
		for _, v := range b.Values {
			if live[v.ID] {
				b.Values[i] = v
				i++
			} else {
				f.vid.put(v.ID)
			}
		}
		// aid GC
		tail := b.Values[i:]
		for j := range tail {
			tail[j] = nil
		}
		b.Values = b.Values[:i]
	}

	// Remove unreachable blocks.  Return dead block ids to allocator.
	i := 0
	for _, b := range f.Blocks {
		if reachable[b.ID] {
			f.Blocks[i] = b
			i++
		} else {
			if len(b.Values) > 0 {
				b.Fatalf("live values in unreachable block %v: %v", b, b.Values)
			}
			f.bid.put(b.ID)
		}
	}
	// zero remainder to help GC
	tail := f.Blocks[i:]
	for j := range tail {
		tail[j] = nil
	}
	f.Blocks = f.Blocks[:i]

	// TODO: renumber Blocks and Values densely?
	// TODO: save dead Values and Blocks for reuse?  Or should we just let GC handle it?
}

// There was an edge b->c.  c has been removed from b's successors.
// Fix up c to handle that fact.
func (f *Func) removePredecessor(b, c *Block) {
	work := [][2]*Block{{b, c}}

	for len(work) > 0 {
		b, c := work[0][0], work[0][1]
		work = work[1:]

		// find index of b in c's predecessor list
		var i int
		for j, p := range c.Preds {
			if p == b {
				i = j
				break
			}
		}

		n := len(c.Preds) - 1
		c.Preds[i] = c.Preds[n]
		c.Preds[n] = nil // aid GC
		c.Preds = c.Preds[:n]

		// rewrite phi ops to match the new predecessor list
		for _, v := range c.Values {
			if v.Op != OpPhi {
				continue
			}
			v.Args[i] = v.Args[n]
			v.Args[n] = nil // aid GC
			v.Args = v.Args[:n]
			if n == 1 {
				v.Op = OpCopy
			}
		}

		if n == 0 {
			// c is now dead--recycle its values
			for _, v := range c.Values {
				f.vid.put(v.ID)
			}
			c.Values = nil
			// Also kill any successors of c now, to spare later processing.
			for _, succ := range c.Succs {
				work = append(work, [2]*Block{c, succ})
			}
			c.Succs = nil
			c.Kind = BlockDead
			c.Control = nil
		}
	}
}
<|endoftext|>


<commit_before>package evo

import (
	"log"
)

// This is a population of individuals upon which various operations can be performed
type Population struct {
	individuals []*Individual
}

func NewPopulation(count, genesPerIndividual int, newGene newgene) *Population {
	p := &Population{
		individuals: newIndividuals(count, genesPerIndividual, newGene),
	}

	for _, i := range p.individuals {
		log.Printf("%+v\n", i)
	}
	return p
}

func (p Population) Len() int {
	return len(p.individuals)
}

func (p Population) Swap(i, j int) {
	p.individuals[i], p.individuals[j] = p.individuals[j], p.individuals[i]
}

func (p Population) Less(i, j int) bool {
	return p.individuals[i].fitness < p.individuals[j].fitness
}
<commit_msg>Remove testing<commit_after>package evo

// This is a population of individuals upon which various operations can be performed
type Population struct {
	individuals []*Individual
}

func NewPopulation(count, genesPerIndividual int, newGene newgene) *Population {
	p := &Population{
		individuals: newIndividuals(count, genesPerIndividual, newGene),
	}

	return p
}

func (p Population) Len() int {
	return len(p.individuals)
}

func (p Population) Swap(i, j int) {
	p.individuals[i], p.individuals[j] = p.individuals[j], p.individuals[i]
}

func (p Population) Less(i, j int) bool {
	return p.individuals[i].fitness < p.individuals[j].fitness
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"fmt"
	"net"
	"net/http"
	_ "net/http/pprof"
	"os"
	"os/signal"
	"sync"
	"syscall"
	"time"

	pb "github.com/viru/berrybot/proto"

	log "github.com/Sirupsen/logrus"
	"github.com/kidoman/embd"
	_ "github.com/kidoman/embd/host/rpi" // This loads the RPi driver
	"google.golang.org/grpc"
)

// server is used to implement hellowrld.GreeterServer.
type server struct {
	front, rear *echo
	driver      *driver
}

type echo struct {
	name       string
	echo       embd.DigitalPin
	trig       embd.DigitalPin
	quit, done chan bool
	dist       int64
	last       time.Time
	enabled    bool
}

func newEcho(name string, trigPin, echoPin int) (*echo, error) {
	var e echo
	e.name = name
	e.quit = make(chan bool)
	e.done = make(chan bool)
	var err error
	e.trig, err = embd.NewDigitalPin(trigPin)
	if err != nil {
		return nil, fmt.Errorf("can't init trigger pin: %v", err)
	}
	e.echo, err = embd.NewDigitalPin(echoPin)
	if err != nil {
		return nil, fmt.Errorf("can't init echo pin: %v", err)
	}

	// Set direction.
	if err := e.trig.SetDirection(embd.Out); err != nil {
		return nil, fmt.Errorf("can't set trigger direction: %v", err)
	}
	if err := e.echo.SetDirection(embd.In); err != nil {
		return nil, fmt.Errorf("can't set echo direction: %v", err)
	}
	return &e, nil
}

func (e *echo) runDistancer() {
	if err := e.trig.Write(embd.Low); err != nil {
		log.Warnf("can't set trigger to low: %v", err)
	}
	time.Sleep(time.Second * 1)
	tick := time.NewTicker(time.Millisecond * 500)
	defer tick.Stop()
	for {
		select {
		case <-e.quit:
			e.done <- true
			return
		case <-tick.C:
			if !e.enabled {
				continue
			}
			log.Infof("%s: measuring...", e.name)
			if err := e.trig.Write(embd.High); err != nil {
				log.Warnf("can't set trigger to high: %v", err)
			}
			time.Sleep(time.Microsecond * 10)
			if err := e.trig.Write(embd.Low); err != nil {
				log.Warnf("can't set trigger to low: %v", err)
			}
			dur, err := e.echo.TimePulse(embd.High)
			if err != nil {
				log.Warnf("can't time pulse: %v", err)
			}
			log.Infof("%s: distance: %dcm", e.name, dur.Nanoseconds()/1000*34/1000/2)
			e.dist = dur.Nanoseconds() / 1000 * 34 / 1000 / 2
		}
	}
}

func (e *echo) close() {
	e.quit <- true
	<-e.done
	e.echo.Close()
	e.trig.Close()
}

type driver struct {
	left, right *engine
	mu          sync.Mutex
	moving      bool
	last        time.Time
}

func (d *driver) safetyStop() {
	ticker := time.NewTicker(time.Second)
	for range ticker.C {
		d.mu.Lock()
		if d.moving && d.last.Add(time.Second).Before(time.Now()) {
			d.mu.Unlock()
			d.stop()
			log.Warn("Emergency stop!")
			continue
		}
		d.mu.Unlock()
	}
}

func (d *driver) setMoving(moving bool) {
	d.mu.Lock()
	d.last = time.Now()
	d.moving = moving
	d.mu.Unlock()
}

func (d *driver) stop() {
	d.left.pwr.Write(embd.Low)
	d.right.pwr.Write(embd.Low)
	d.setMoving(false)
}

func (d *driver) forward() {
	d.left.pwr.Write(embd.High)
	d.left.fwd.Write(embd.High)
	d.right.pwr.Write(embd.High)
	d.right.fwd.Write(embd.High)
	d.setMoving(true)
}

func (d *driver) backward() {
	d.left.pwr.Write(embd.High)
	d.left.fwd.Write(embd.Low)
	d.right.pwr.Write(embd.High)
	d.right.fwd.Write(embd.Low)
	d.setMoving(true)
}

func (d *driver) sharpRight() {
	d.left.pwr.Write(embd.High)
	d.left.fwd.Write(embd.High)
	d.right.pwr.Write(embd.High)
	d.right.fwd.Write(embd.Low)
	d.setMoving(true)
}

func (d *driver) sharpLeft() {
	d.left.pwr.Write(embd.High)
	d.left.fwd.Write(embd.Low)
	d.right.pwr.Write(embd.High)
	d.right.fwd.Write(embd.High)
	d.setMoving(true)
}

func (d *driver) fwdRight() {
	d.left.pwr.Write(embd.High)
	d.left.fwd.Write(embd.High)
	d.right.pwr.Write(embd.Low)
	d.right.fwd.Write(embd.High)
	d.setMoving(true)
}

func (d *driver) fwdLeft() {
	d.left.pwr.Write(embd.Low)
	d.left.fwd.Write(embd.High)
	d.right.pwr.Write(embd.High)
	d.right.fwd.Write(embd.High)
	d.setMoving(true)
}

func (d *driver) backRight() {
	d.left.pwr.Write(embd.High)
	d.left.fwd.Write(embd.Low)
	d.right.pwr.Write(embd.Low)
	d.right.fwd.Write(embd.Low)
	d.setMoving(true)
}

func (d *driver) backLeft() {
	d.left.pwr.Write(embd.Low)
	d.left.fwd.Write(embd.Low)
	d.right.pwr.Write(embd.High)
	d.right.fwd.Write(embd.Low)
	d.setMoving(true)
}

const (
	safeStraightDist = 20
	safeTurningDist  = 10
)

func (s *server) drive(dir *pb.Direction) {
	switch {
	case dir.Dy > -5 && dir.Dy < 5 && dir.Dx > -5 && dir.Dx < 5:
		s.front.enabled = false
		s.rear.enabled = false
		s.driver.stop()
	case dir.Dy > 5 && dir.Dx > -5 && dir.Dx < 5:
		s.front.enabled = true
		s.driver.forward()
	case dir.Dy < -5 && dir.Dx > -5 && dir.Dx < 5:
		s.rear.enabled = true
		s.driver.backward()
	case dir.Dx > 5 && dir.Dy > -5 && dir.Dy < 5:
		s.driver.sharpRight()
	case dir.Dx < -5 && dir.Dy > -5 && dir.Dy < 5:
		s.driver.sharpLeft()
	case dir.Dx > 5 && dir.Dy > 5:
		s.driver.fwdRight()
	case dir.Dx < -5 && dir.Dy > 5:
		s.driver.fwdLeft()
	case dir.Dx > 5 && dir.Dy < -5:
		s.driver.backRight()
	case dir.Dx < -5 && dir.Dy < -5:
		s.driver.backLeft()
	}
}

type engine struct {
	fwd, pwr embd.DigitalPin
}

func newEngine(pwrPin, fwdPin int) (*engine, error) {
	var e engine
	var err error
	e.pwr, err = embd.NewDigitalPin(pwrPin)
	if err != nil {
		return nil, fmt.Errorf("can't init power pin: %v", err)
	}
	e.fwd, err = embd.NewDigitalPin(fwdPin)
	if err != nil {
		return nil, fmt.Errorf("can't init forward pin: %v", err)
	}

	// Set direction.
	if err := e.pwr.SetDirection(embd.Out); err != nil {
		return nil, fmt.Errorf("can't set power direction: %v", err)
	}
	if err := e.fwd.SetDirection(embd.Out); err != nil {
		return nil, fmt.Errorf("can't set forward direction: %v", err)
	}
	return &e, nil
}

func (e *engine) close() {
	e.pwr.Close()
	e.fwd.Close()
}

const (
	sensorUnknown = iota
	sensorFront
	sensorRear
)

func (s *server) Drive(stream pb.Driver_DriveServer) error {
	waitc := make(chan struct{})
	go func() {
		for {
			d, err := stream.Recv()
			if err != nil {
				log.Warnf("ERR from client: %v", err)
				close(waitc)
				return
			}
			s.drive(d)
		}
	}()

	for {
		select {
		case <-time.After(time.Second):
			if !s.front.enabled && !s.rear.enabled {
				continue
			}
			if err := stream.Send(&pb.Telemetry{Speed: 1, DistFront: int32(s.front.dist), DistRear: int32(s.rear.dist)}); err != nil {
				log.Errorf("can't send telemetry: %v", err)
				return err
			}
			log.Info("Sending telemetry!")
		case <-waitc:
			log.Info("got ERR from client, closing sending loop")
			return nil
		}
	}
}

var grpcPort = flag.String("grpc-port", "31337", "gRPC listen port")

func main() {
	flag.Parse()

	go http.ListenAndServe(":9191", nil)

	// Initialize GPIO.
	var err error
	if err = embd.InitGPIO(); err != nil {
		log.Fatalf("Can't init GPIO: %v", err)
	}
	defer embd.CloseGPIO()
	front, err := newEcho("front", 9, 10)
	if err != nil {
		log.Fatalf("Can't init front echo: %v", err)
	}
	defer front.close()
	rear, err := newEcho("rear", 19, 20)
	if err != nil {
		log.Fatalf("Can't init rear echo: %v", err)
	}
	defer rear.close()
	go front.runDistancer()
	go rear.runDistancer()

	left, err := newEngine(23, 4)
	if err != nil {
		log.Fatalf("Can't init left engine: %v", err)
	}
	defer left.close()
	right, err := newEngine(24, 17)
	if err != nil {
		log.Fatalf("Can't init right engine: %v", err)
	}
	defer right.close()

	// Listen for GRPC connections.
	lis, err := net.Listen("tcp", ":"+*grpcPort)
	if err != nil {
		log.Fatalf("failed to listen: %v", err)
	}
	defer lis.Close()

	drv := driver{left: left, right: right}
	go drv.safetyStop()

	srv := server{front: front, rear: rear, driver: &drv}
	s := grpc.NewServer()
	pb.RegisterDriverServer(s, &srv)

	// Open broadcast connection.
	bcast, err := net.ListenPacket("udp", ":0")
	if err != nil {
		log.Fatal(err)
	}
	defer bcast.Close()

	broadcastAddr := "255.255.255.255:8032"
	dst, err := net.ResolveUDPAddr("udp", broadcastAddr)
	if err != nil {
		log.Fatal(err)
	}

	go func() {
		log.Infof("Starting to broadcast our port %s on %s", *grpcPort, broadcastAddr)
		for {
			if _, err := bcast.WriteTo([]byte(*grpcPort), dst); err != nil {
				log.Warn(err)
			}
			time.Sleep(time.Second)
		}
	}()

	c := make(chan os.Signal, 1)
	signal.Notify(c, syscall.SIGTERM, syscall.SIGINT)
	go func() {
		sig := <-c
		log.Infof("Got %s, trying to shutdown gracefully", sig.String())
		front.close()
		rear.close()
		left.close()
		right.close()
		embd.CloseGPIO()
		lis.Close()
		bcast.Close()
		os.Exit(0)
	}()

	// Start serving GRPC.
	log.Fatal(s.Serve(lis))
}
<commit_msg>Send speed based on movement (binary for now)<commit_after>package main

import (
	"flag"
	"fmt"
	"net"
	"net/http"
	_ "net/http/pprof"
	"os"
	"os/signal"
	"sync"
	"syscall"
	"time"

	pb "github.com/viru/berrybot/proto"

	log "github.com/Sirupsen/logrus"
	"github.com/kidoman/embd"
	_ "github.com/kidoman/embd/host/rpi" // This loads the RPi driver
	"google.golang.org/grpc"
)

// server is used to implement hellowrld.GreeterServer.
type server struct {
	front, rear *echo
	driver      *driver
}

type echo struct {
	name       string
	echo       embd.DigitalPin
	trig       embd.DigitalPin
	quit, done chan bool
	dist       int64
	last       time.Time
	enabled    bool
}

func newEcho(name string, trigPin, echoPin int) (*echo, error) {
	var e echo
	e.name = name
	e.quit = make(chan bool)
	e.done = make(chan bool)
	var err error
	e.trig, err = embd.NewDigitalPin(trigPin)
	if err != nil {
		return nil, fmt.Errorf("can't init trigger pin: %v", err)
	}
	e.echo, err = embd.NewDigitalPin(echoPin)
	if err != nil {
		return nil, fmt.Errorf("can't init echo pin: %v", err)
	}

	// Set direction.
	if err := e.trig.SetDirection(embd.Out); err != nil {
		return nil, fmt.Errorf("can't set trigger direction: %v", err)
	}
	if err := e.echo.SetDirection(embd.In); err != nil {
		return nil, fmt.Errorf("can't set echo direction: %v", err)
	}
	return &e, nil
}

func (e *echo) runDistancer() {
	if err := e.trig.Write(embd.Low); err != nil {
		log.Warnf("can't set trigger to low: %v", err)
	}
	time.Sleep(time.Second * 1)
	tick := time.NewTicker(time.Millisecond * 500)
	defer tick.Stop()
	for {
		select {
		case <-e.quit:
			e.done <- true
			return
		case <-tick.C:
			if !e.enabled {
				continue
			}
			log.Infof("%s: measuring...", e.name)
			if err := e.trig.Write(embd.High); err != nil {
				log.Warnf("can't set trigger to high: %v", err)
			}
			time.Sleep(time.Microsecond * 10)
			if err := e.trig.Write(embd.Low); err != nil {
				log.Warnf("can't set trigger to low: %v", err)
			}
			dur, err := e.echo.TimePulse(embd.High)
			if err != nil {
				log.Warnf("can't time pulse: %v", err)
			}
			log.Infof("%s: distance: %dcm", e.name, dur.Nanoseconds()/1000*34/1000/2)
			e.dist = dur.Nanoseconds() / 1000 * 34 / 1000 / 2
		}
	}
}

func (e *echo) close() {
	e.quit <- true
	<-e.done
	e.echo.Close()
	e.trig.Close()
}

type driver struct {
	left, right *engine
	mu          sync.Mutex
	moving      bool
	last        time.Time
}

func (d *driver) safetyStop() {
	ticker := time.NewTicker(time.Second)
	for range ticker.C {
		d.mu.Lock()
		if d.moving && d.last.Add(time.Second).Before(time.Now()) {
			d.mu.Unlock()
			d.stop()
			log.Warn("Emergency stop!")
			continue
		}
		d.mu.Unlock()
	}
}

func (d *driver) setMoving(moving bool) {
	d.mu.Lock()
	d.last = time.Now()
	d.moving = moving
	d.mu.Unlock()
}

func (d *driver) stop() {
	d.left.pwr.Write(embd.Low)
	d.right.pwr.Write(embd.Low)
	d.setMoving(false)
}

func (d *driver) forward() {
	d.left.pwr.Write(embd.High)
	d.left.fwd.Write(embd.High)
	d.right.pwr.Write(embd.High)
	d.right.fwd.Write(embd.High)
	d.setMoving(true)
}

func (d *driver) backward() {
	d.left.pwr.Write(embd.High)
	d.left.fwd.Write(embd.Low)
	d.right.pwr.Write(embd.High)
	d.right.fwd.Write(embd.Low)
	d.setMoving(true)
}

func (d *driver) sharpRight() {
	d.left.pwr.Write(embd.High)
	d.left.fwd.Write(embd.High)
	d.right.pwr.Write(embd.High)
	d.right.fwd.Write(embd.Low)
	d.setMoving(true)
}

func (d *driver) sharpLeft() {
	d.left.pwr.Write(embd.High)
	d.left.fwd.Write(embd.Low)
	d.right.pwr.Write(embd.High)
	d.right.fwd.Write(embd.High)
	d.setMoving(true)
}

func (d *driver) fwdRight() {
	d.left.pwr.Write(embd.High)
	d.left.fwd.Write(embd.High)
	d.right.pwr.Write(embd.Low)
	d.right.fwd.Write(embd.High)
	d.setMoving(true)
}

func (d *driver) fwdLeft() {
	d.left.pwr.Write(embd.Low)
	d.left.fwd.Write(embd.High)
	d.right.pwr.Write(embd.High)
	d.right.fwd.Write(embd.High)
	d.setMoving(true)
}

func (d *driver) backRight() {
	d.left.pwr.Write(embd.High)
	d.left.fwd.Write(embd.Low)
	d.right.pwr.Write(embd.Low)
	d.right.fwd.Write(embd.Low)
	d.setMoving(true)
}

func (d *driver) backLeft() {
	d.left.pwr.Write(embd.Low)
	d.left.fwd.Write(embd.Low)
	d.right.pwr.Write(embd.High)
	d.right.fwd.Write(embd.Low)
	d.setMoving(true)
}

const (
	safeStraightDist = 20
	safeTurningDist  = 10
)

func (s *server) drive(dir *pb.Direction) {
	switch {
	case dir.Dy > -5 && dir.Dy < 5 && dir.Dx > -5 && dir.Dx < 5:
		s.front.enabled = false
		s.rear.enabled = false
		s.driver.stop()
	case dir.Dy > 5 && dir.Dx > -5 && dir.Dx < 5:
		s.front.enabled = true
		s.driver.forward()
	case dir.Dy < -5 && dir.Dx > -5 && dir.Dx < 5:
		s.rear.enabled = true
		s.driver.backward()
	case dir.Dx > 5 && dir.Dy > -5 && dir.Dy < 5:
		s.driver.sharpRight()
	case dir.Dx < -5 && dir.Dy > -5 && dir.Dy < 5:
		s.driver.sharpLeft()
	case dir.Dx > 5 && dir.Dy > 5:
		s.driver.fwdRight()
	case dir.Dx < -5 && dir.Dy > 5:
		s.driver.fwdLeft()
	case dir.Dx > 5 && dir.Dy < -5:
		s.driver.backRight()
	case dir.Dx < -5 && dir.Dy < -5:
		s.driver.backLeft()
	}
}

type engine struct {
	fwd, pwr embd.DigitalPin
}

func newEngine(pwrPin, fwdPin int) (*engine, error) {
	var e engine
	var err error
	e.pwr, err = embd.NewDigitalPin(pwrPin)
	if err != nil {
		return nil, fmt.Errorf("can't init power pin: %v", err)
	}
	e.fwd, err = embd.NewDigitalPin(fwdPin)
	if err != nil {
		return nil, fmt.Errorf("can't init forward pin: %v", err)
	}

	// Set direction.
	if err := e.pwr.SetDirection(embd.Out); err != nil {
		return nil, fmt.Errorf("can't set power direction: %v", err)
	}
	if err := e.fwd.SetDirection(embd.Out); err != nil {
		return nil, fmt.Errorf("can't set forward direction: %v", err)
	}
	return &e, nil
}

func (e *engine) close() {
	e.pwr.Close()
	e.fwd.Close()
}

const (
	sensorUnknown = iota
	sensorFront
	sensorRear
)

func (s *server) Drive(stream pb.Driver_DriveServer) error {
	waitc := make(chan struct{})
	go func() {
		for {
			d, err := stream.Recv()
			if err != nil {
				log.Warnf("ERR from client: %v", err)
				close(waitc)
				return
			}
			s.drive(d)
		}
	}()

	for {
		select {
		case <-time.After(time.Second):
			if !s.front.enabled && !s.rear.enabled {
				continue
			}
			var speed int32
			if s.driver.moving {
				speed = 100
			}
			if err := stream.Send(&pb.Telemetry{Speed: speed, DistFront: int32(s.front.dist), DistRear: int32(s.rear.dist)}); err != nil {
				log.Errorf("can't send telemetry: %v", err)
				return err
			}
			log.Info("Sending telemetry!")
		case <-waitc:
			log.Info("got ERR from client, closing sending loop")
			return nil
		}
	}
}

var grpcPort = flag.String("grpc-port", "31337", "gRPC listen port")

func main() {
	flag.Parse()

	go http.ListenAndServe(":9191", nil)

	// Initialize GPIO.
	var err error
	if err = embd.InitGPIO(); err != nil {
		log.Fatalf("Can't init GPIO: %v", err)
	}
	defer embd.CloseGPIO()
	front, err := newEcho("front", 9, 10)
	if err != nil {
		log.Fatalf("Can't init front echo: %v", err)
	}
	defer front.close()
	rear, err := newEcho("rear", 19, 20)
	if err != nil {
		log.Fatalf("Can't init rear echo: %v", err)
	}
	defer rear.close()
	go front.runDistancer()
	go rear.runDistancer()

	left, err := newEngine(23, 4)
	if err != nil {
		log.Fatalf("Can't init left engine: %v", err)
	}
	defer left.close()
	right, err := newEngine(24, 17)
	if err != nil {
		log.Fatalf("Can't init right engine: %v", err)
	}
	defer right.close()

	// Listen for GRPC connections.
	lis, err := net.Listen("tcp", ":"+*grpcPort)
	if err != nil {
		log.Fatalf("failed to listen: %v", err)
	}
	defer lis.Close()

	drv := driver{left: left, right: right}
	go drv.safetyStop()

	srv := server{front: front, rear: rear, driver: &drv}
	s := grpc.NewServer()
	pb.RegisterDriverServer(s, &srv)

	// Open broadcast connection.
	bcast, err := net.ListenPacket("udp", ":0")
	if err != nil {
		log.Fatal(err)
	}
	defer bcast.Close()

	broadcastAddr := "255.255.255.255:8032"
	dst, err := net.ResolveUDPAddr("udp", broadcastAddr)
	if err != nil {
		log.Fatal(err)
	}

	go func() {
		log.Infof("Starting to broadcast our port %s on %s", *grpcPort, broadcastAddr)
		for {
			if _, err := bcast.WriteTo([]byte(*grpcPort), dst); err != nil {
				log.Warn(err)
			}
			time.Sleep(time.Second)
		}
	}()

	c := make(chan os.Signal, 1)
	signal.Notify(c, syscall.SIGTERM, syscall.SIGINT)
	go func() {
		sig := <-c
		log.Infof("Got %s, trying to shutdown gracefully", sig.String())
		front.close()
		rear.close()
		left.close()
		right.close()
		embd.CloseGPIO()
		lis.Close()
		bcast.Close()
		os.Exit(0)
	}()

	// Start serving GRPC.
	log.Fatal(s.Serve(lis))
}
<|endoftext|>


<commit_before>package urlutil

import (
	"fmt"
	"regexp"
	"strings"
)

const uriSchemePattern string = `^(?i)([a-z][0-9a-z\-\+.]+)://`

var rxScheme *regexp.Regexp = regexp.MustCompile(uriSchemePattern)

// https://www.iana.org/assignments/uri-schemes/uri-schemes.xhtml

// UriHasScheme returns a boolean true or false if the string
// has a URI scheme.
func UriHasScheme(uri string) bool {
	scheme := UriScheme(uri)
	if len(scheme) > 0 {
		return true
	}
	return false
}

// UriScheme extracts the URI scheme from a string. It returns
// an empty string if none is encountered.
func UriScheme(uri string) string {
	uri = strings.TrimSpace(uri)
	m := rxScheme.FindAllStringSubmatch(uri, -1)
	if len(m) > 0 && len(m[0]) == 2 {
		fmt.Println(m[0][1])
		return strings.TrimSpace(m[0][1])
	}
	return ""
}
<commit_msg>remove debug code<commit_after>package urlutil

import (
	"regexp"
	"strings"
)

const uriSchemePattern string = `^(?i)([a-z][0-9a-z\-\+.]+)://`

var rxScheme *regexp.Regexp = regexp.MustCompile(uriSchemePattern)

// https://www.iana.org/assignments/uri-schemes/uri-schemes.xhtml

// UriHasScheme returns a boolean true or false if the string
// has a URI scheme.
func UriHasScheme(uri string) bool {
	scheme := UriScheme(uri)
	if len(scheme) > 0 {
		return true
	}
	return false
}

// UriScheme extracts the URI scheme from a string. It returns
// an empty string if none is encountered.
func UriScheme(uri string) string {
	uri = strings.TrimSpace(uri)
	m := rxScheme.FindAllStringSubmatch(uri, -1)
	if len(m) > 0 && len(m[0]) == 2 {
		return strings.TrimSpace(m[0][1])
	}
	return ""
}
<|endoftext|>


<commit_before>package logger

import (
	"net/http"
	"time"

	"github.com/Sirupsen/logrus"
)

// responseWriter implements the http.ResponseWriter interface and
// keeps track of the header status
type responseWriter struct {
	Status int
	Writer http.ResponseWriter
}

func (rw *responseWriter) Header() http.Header {
	return rw.Writer.Header()
}

func (rw *responseWriter) Write(b []byte) (int, error) {
	return rw.Writer.Write(b)
}

func (rw *responseWriter) WriteHeader(s int) {
	rw.Status = s
	rw.Writer.WriteHeader(s)
}

func Request(next http.Handler) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		start := time.Now()
		rw := responseWriter{Status: 200, Writer: w}
		defer func() {
			logrus.WithFields(map[string]interface{}{
				"status":  rw.Status,
				"latency": time.Since(start),
				"ip":      r.RemoteAddr,
				"method":  r.Method,
				"url":     r.URL.String(),
			}).Info()
		}()
		next.ServeHTTP(&rw, r)
	})
}
<commit_msg>Add doc to package logger<commit_after>// Package logger implements middleware loggeing.
package logger

import (
	"net/http"
	"time"

	"github.com/Sirupsen/logrus"
)

// responseWriter implements the http.ResponseWriter interface and
// keeps track of the header status
type responseWriter struct {
	Status int
	Writer http.ResponseWriter
}

func (rw *responseWriter) Header() http.Header {
	return rw.Writer.Header()
}

func (rw *responseWriter) Write(b []byte) (int, error) {
	return rw.Writer.Write(b)
}

func (rw *responseWriter) WriteHeader(s int) {
	rw.Status = s
	rw.Writer.WriteHeader(s)
}

// Request returns an http.Handler that can be used as middleware to log requests.
func Request(next http.Handler) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		start := time.Now()
		rw := responseWriter{Status: 200, Writer: w}
		defer func() {
			logrus.WithFields(map[string]interface{}{
				"status":  rw.Status,
				"latency": time.Since(start),
				"ip":      r.RemoteAddr,
				"method":  r.Method,
				"url":     r.URL.String(),
			}).Info()
		}()
		next.ServeHTTP(&rw, r)
	})
}
<|endoftext|>


<commit_before>package networkdb

import (
	"bytes"
	"crypto/rand"
	"fmt"
	"math/big"
	rnd "math/rand"
	"strings"
	"time"

	"github.com/Sirupsen/logrus"
	"github.com/hashicorp/memberlist"
)

const reapInterval = 2 * time.Second

type logWriter struct{}

func (l *logWriter) Write(p []byte) (int, error) {
	str := string(p)

	switch {
	case strings.Contains(str, "[WARN]"):
		logrus.Warn(str)
	case strings.Contains(str, "[DEBUG]"):
		logrus.Debug(str)
	case strings.Contains(str, "[INFO]"):
		logrus.Info(str)
	case strings.Contains(str, "[ERR]"):
		logrus.Warn(str)
	}

	return len(p), nil
}

// SetKey adds a new key to the key ring
func (nDB *NetworkDB) SetKey(key []byte) {
	for _, dbKey := range nDB.config.Keys {
		if bytes.Equal(key, dbKey) {
			return
		}
	}
	nDB.config.Keys = append(nDB.config.Keys, key)
	if nDB.keyring != nil {
		nDB.keyring.AddKey(key)
	}
}

// SetPrimaryKey sets the given key as the primary key. This should have
// been added apriori through SetKey
func (nDB *NetworkDB) SetPrimaryKey(key []byte) {
	for _, dbKey := range nDB.config.Keys {
		if bytes.Equal(key, dbKey) {
			if nDB.keyring != nil {
				nDB.keyring.UseKey(dbKey)
			}
			break
		}
	}
}

// RemoveKey removes a key from the key ring. The key being removed
// can't be the primary key
func (nDB *NetworkDB) RemoveKey(key []byte) {
	for i, dbKey := range nDB.config.Keys {
		if bytes.Equal(key, dbKey) {
			nDB.config.Keys = append(nDB.config.Keys[:i], nDB.config.Keys[i+1:]...)
			if nDB.keyring != nil {
				nDB.keyring.RemoveKey(dbKey)
			}
			break
		}
	}
}

func (nDB *NetworkDB) clusterInit() error {
	config := memberlist.DefaultLANConfig()
	config.Name = nDB.config.NodeName
	config.BindAddr = nDB.config.BindAddr

	if nDB.config.BindPort != 0 {
		config.BindPort = nDB.config.BindPort
	}

	config.ProtocolVersion = memberlist.ProtocolVersionMax
	config.Delegate = &delegate{nDB: nDB}
	config.Events = &eventDelegate{nDB: nDB}
	config.LogOutput = &logWriter{}

	var err error
	if len(nDB.config.Keys) > 0 {
		nDB.keyring, err = memberlist.NewKeyring(nDB.config.Keys, nDB.config.Keys[0])
		if err != nil {
			return err
		}
		config.Keyring = nDB.keyring
	}

	nDB.networkBroadcasts = &memberlist.TransmitLimitedQueue{
		NumNodes: func() int {
			return len(nDB.nodes)
		},
		RetransmitMult: config.RetransmitMult,
	}

	mlist, err := memberlist.Create(config)
	if err != nil {
		return fmt.Errorf("failed to create memberlist: %v", err)
	}

	nDB.stopCh = make(chan struct{})
	nDB.memberlist = mlist
	nDB.mConfig = config

	for _, trigger := range []struct {
		interval time.Duration
		fn       func()
	}{
		{reapInterval, nDB.reapState},
		{config.GossipInterval, nDB.gossip},
		{config.PushPullInterval, nDB.bulkSyncTables},
	} {
		t := time.NewTicker(trigger.interval)
		go nDB.triggerFunc(trigger.interval, t.C, nDB.stopCh, trigger.fn)
		nDB.tickers = append(nDB.tickers, t)
	}

	return nil
}

func (nDB *NetworkDB) clusterJoin(members []string) error {
	mlist := nDB.memberlist

	if _, err := mlist.Join(members); err != nil {
		return fmt.Errorf("could not join node to memberlist: %v", err)
	}

	return nil
}

func (nDB *NetworkDB) clusterLeave() error {
	mlist := nDB.memberlist

	if err := mlist.Leave(time.Second); err != nil {
		return err
	}

	close(nDB.stopCh)

	for _, t := range nDB.tickers {
		t.Stop()
	}

	return mlist.Shutdown()
}

func (nDB *NetworkDB) triggerFunc(stagger time.Duration, C <-chan time.Time, stop <-chan struct{}, f func()) {
	// Use a random stagger to avoid syncronizing
	randStagger := time.Duration(uint64(rnd.Int63()) % uint64(stagger))
	select {
	case <-time.After(randStagger):
	case <-stop:
		return
	}
	for {
		select {
		case <-C:
			f()
		case <-stop:
			return
		}
	}
}

func (nDB *NetworkDB) reapState() {
	nDB.reapNetworks()
	nDB.reapTableEntries()
}

func (nDB *NetworkDB) reapNetworks() {
	now := time.Now()
	nDB.Lock()
	for name, nn := range nDB.networks {
		for id, n := range nn {
			if n.leaving && now.Sub(n.leaveTime) > reapInterval {
				delete(nn, id)
				nDB.deleteNetworkNode(id, name)
			}
		}
	}
	nDB.Unlock()
}

func (nDB *NetworkDB) reapTableEntries() {
	var paths []string

	now := time.Now()

	nDB.RLock()
	nDB.indexes[byTable].Walk(func(path string, v interface{}) bool {
		entry, ok := v.(*entry)
		if !ok {
			return false
		}

		if !entry.deleting || now.Sub(entry.deleteTime) <= reapInterval {
			return false
		}

		paths = append(paths, path)
		return false
	})
	nDB.RUnlock()

	nDB.Lock()
	for _, path := range paths {
		params := strings.Split(path[1:], "/")
		tname := params[0]
		nid := params[1]
		key := params[2]

		if _, ok := nDB.indexes[byTable].Delete(fmt.Sprintf("/%s/%s/%s", tname, nid, key)); !ok {
			logrus.Errorf("Could not delete entry in table %s with network id %s and key %s as it does not exist", tname, nid, key)
		}

		if _, ok := nDB.indexes[byNetwork].Delete(fmt.Sprintf("/%s/%s/%s", nid, tname, key)); !ok {
			logrus.Errorf("Could not delete entry in network %s with table name %s and key %s as it does not exist", nid, tname, key)
		}
	}
	nDB.Unlock()
}

func (nDB *NetworkDB) gossip() {
	networkNodes := make(map[string][]string)
	nDB.RLock()
	thisNodeNetworks := nDB.networks[nDB.config.NodeName]
	for nid := range thisNodeNetworks {
		networkNodes[nid] = nDB.networkNodes[nid]

	}
	nDB.RUnlock()

	for nid, nodes := range networkNodes {
		mNodes := nDB.mRandomNodes(3, nodes)
		bytesAvail := udpSendBuf - compoundHeaderOverhead

		nDB.RLock()
		network, ok := thisNodeNetworks[nid]
		nDB.RUnlock()
		if !ok || network == nil {
			// It is normal for the network to be removed
			// between the time we collect the network
			// attachments of this node and processing
			// them here.
			continue
		}

		broadcastQ := network.tableBroadcasts

		if broadcastQ == nil {
			logrus.Errorf("Invalid broadcastQ encountered while gossiping for network %s", nid)
			continue
		}

		msgs := broadcastQ.GetBroadcasts(compoundOverhead, bytesAvail)
		if len(msgs) == 0 {
			continue
		}

		// Create a compound message
		compound := makeCompoundMessage(msgs)

		for _, node := range mNodes {
			nDB.RLock()
			mnode := nDB.nodes[node]
			nDB.RUnlock()

			if mnode == nil {
				break
			}

			// Send the compound message
			if err := nDB.memberlist.SendToUDP(mnode, compound); err != nil {
				logrus.Errorf("Failed to send gossip to %s: %s", mnode.Addr, err)
			}
		}
	}
}

func (nDB *NetworkDB) bulkSyncTables() {
	var networks []string
	nDB.RLock()
	for nid := range nDB.networks[nDB.config.NodeName] {
		networks = append(networks, nid)
	}
	nDB.RUnlock()

	for {
		if len(networks) == 0 {
			break
		}

		nid := networks[0]
		networks = networks[1:]

		completed, err := nDB.bulkSync(nid, false)
		if err != nil {
			logrus.Errorf("periodic bulk sync failure for network %s: %v", nid, err)
			continue
		}

		// Remove all the networks for which we have
		// successfully completed bulk sync in this iteration.
		updatedNetworks := make([]string, 0, len(networks))
		for _, nid := range networks {
			for _, completedNid := range completed {
				if nid == completedNid {
					continue
				}

				updatedNetworks = append(updatedNetworks, nid)
			}
		}

		networks = updatedNetworks
	}
}

func (nDB *NetworkDB) bulkSync(nid string, all bool) ([]string, error) {
	nDB.RLock()
	nodes := nDB.networkNodes[nid]
	nDB.RUnlock()

	if !all {
		// If not all, then just pick one.
		nodes = nDB.mRandomNodes(1, nodes)
	}

	logrus.Debugf("%s: Initiating bulk sync with nodes %v", nDB.config.NodeName, nodes)
	var err error
	var networks []string
	for _, node := range nodes {
		if node == nDB.config.NodeName {
			continue
		}

		networks = nDB.findCommonNetworks(node)
		err = nDB.bulkSyncNode(networks, node, true)
		if err != nil {
			err = fmt.Errorf("bulk sync failed on node %s: %v", node, err)
		}
	}

	if err != nil {
		return nil, err
	}

	return networks, nil
}

// Bulk sync all the table entries belonging to a set of networks to a
// single peer node. It can be unsolicited or can be in response to an
// unsolicited bulk sync
func (nDB *NetworkDB) bulkSyncNode(networks []string, node string, unsolicited bool) error {
	var msgs [][]byte

	logrus.Debugf("%s: Initiating bulk sync for networks %v with node %s", nDB.config.NodeName, networks, node)

	nDB.RLock()
	mnode := nDB.nodes[node]
	if mnode == nil {
		nDB.RUnlock()
		return nil
	}

	for _, nid := range networks {
		nDB.indexes[byNetwork].WalkPrefix(fmt.Sprintf("/%s", nid), func(path string, v interface{}) bool {
			entry, ok := v.(*entry)
			if !ok {
				return false
			}

			params := strings.Split(path[1:], "/")
			tEvent := TableEvent{
				Type:      TableEventTypeCreate,
				LTime:     entry.ltime,
				NodeName:  entry.node,
				NetworkID: nid,
				TableName: params[1],
				Key:       params[2],
				Value:     entry.value,
			}

			msg, err := encodeMessage(MessageTypeTableEvent, &tEvent)
			if err != nil {
				logrus.Errorf("Encode failure during bulk sync: %#v", tEvent)
				return false
			}

			msgs = append(msgs, msg)
			return false
		})
	}
	nDB.RUnlock()

	// Create a compound message
	compound := makeCompoundMessage(msgs)

	bsm := BulkSyncMessage{
		LTime:       nDB.tableClock.Time(),
		Unsolicited: unsolicited,
		NodeName:    nDB.config.NodeName,
		Networks:    networks,
		Payload:     compound,
	}

	buf, err := encodeMessage(MessageTypeBulkSync, &bsm)
	if err != nil {
		return fmt.Errorf("failed to encode bulk sync message: %v", err)
	}

	nDB.Lock()
	ch := make(chan struct{})
	nDB.bulkSyncAckTbl[node] = ch
	nDB.Unlock()

	err = nDB.memberlist.SendToTCP(mnode, buf)
	if err != nil {
		nDB.Lock()
		delete(nDB.bulkSyncAckTbl, node)
		nDB.Unlock()

		return fmt.Errorf("failed to send a TCP message during bulk sync: %v", err)
	}

	// Wait on a response only if it is unsolicited.
	if unsolicited {
		startTime := time.Now()
		select {
		case <-time.After(30 * time.Second):
			logrus.Errorf("Bulk sync to node %s timed out", node)
		case <-ch:
			nDB.Lock()
			delete(nDB.bulkSyncAckTbl, node)
			nDB.Unlock()

			logrus.Debugf("%s: Bulk sync to node %s took %s", nDB.config.NodeName, node, time.Now().Sub(startTime))
		}
	}

	return nil
}

// Returns a random offset between 0 and n
func randomOffset(n int) int {
	if n == 0 {
		return 0
	}

	val, err := rand.Int(rand.Reader, big.NewInt(int64(n)))
	if err != nil {
		logrus.Errorf("Failed to get a random offset: %v", err)
		return 0
	}

	return int(val.Int64())
}

// mRandomNodes is used to select up to m random nodes. It is possible
// that less than m nodes are returned.
func (nDB *NetworkDB) mRandomNodes(m int, nodes []string) []string {
	n := len(nodes)
	mNodes := make([]string, 0, m)
OUTER:
	// Probe up to 3*n times, with large n this is not necessary
	// since k << n, but with small n we want search to be
	// exhaustive
	for i := 0; i < 3*n && len(mNodes) < m; i++ {
		// Get random node
		idx := randomOffset(n)
		node := nodes[idx]

		if node == nDB.config.NodeName {
			continue
		}

		// Check if we have this node already
		for j := 0; j < len(mNodes); j++ {
			if node == mNodes[j] {
				continue OUTER
			}
		}

		// Append the node
		mNodes = append(mNodes, node)
	}

	return mNodes
}
<commit_msg>Make sure to notify watchers on node going away<commit_after>package networkdb

import (
	"bytes"
	"crypto/rand"
	"fmt"
	"math/big"
	rnd "math/rand"
	"strings"
	"time"

	"github.com/Sirupsen/logrus"
	"github.com/hashicorp/memberlist"
)

const reapInterval = 2 * time.Second

type logWriter struct{}

func (l *logWriter) Write(p []byte) (int, error) {
	str := string(p)

	switch {
	case strings.Contains(str, "[WARN]"):
		logrus.Warn(str)
	case strings.Contains(str, "[DEBUG]"):
		logrus.Debug(str)
	case strings.Contains(str, "[INFO]"):
		logrus.Info(str)
	case strings.Contains(str, "[ERR]"):
		logrus.Warn(str)
	}

	return len(p), nil
}

// SetKey adds a new key to the key ring
func (nDB *NetworkDB) SetKey(key []byte) {
	for _, dbKey := range nDB.config.Keys {
		if bytes.Equal(key, dbKey) {
			return
		}
	}
	nDB.config.Keys = append(nDB.config.Keys, key)
	if nDB.keyring != nil {
		nDB.keyring.AddKey(key)
	}
}

// SetPrimaryKey sets the given key as the primary key. This should have
// been added apriori through SetKey
func (nDB *NetworkDB) SetPrimaryKey(key []byte) {
	for _, dbKey := range nDB.config.Keys {
		if bytes.Equal(key, dbKey) {
			if nDB.keyring != nil {
				nDB.keyring.UseKey(dbKey)
			}
			break
		}
	}
}

// RemoveKey removes a key from the key ring. The key being removed
// can't be the primary key
func (nDB *NetworkDB) RemoveKey(key []byte) {
	for i, dbKey := range nDB.config.Keys {
		if bytes.Equal(key, dbKey) {
			nDB.config.Keys = append(nDB.config.Keys[:i], nDB.config.Keys[i+1:]...)
			if nDB.keyring != nil {
				nDB.keyring.RemoveKey(dbKey)
			}
			break
		}
	}
}

func (nDB *NetworkDB) clusterInit() error {
	config := memberlist.DefaultLANConfig()
	config.Name = nDB.config.NodeName
	config.BindAddr = nDB.config.BindAddr

	if nDB.config.BindPort != 0 {
		config.BindPort = nDB.config.BindPort
	}

	config.ProtocolVersion = memberlist.ProtocolVersionMax
	config.Delegate = &delegate{nDB: nDB}
	config.Events = &eventDelegate{nDB: nDB}
	config.LogOutput = &logWriter{}

	var err error
	if len(nDB.config.Keys) > 0 {
		nDB.keyring, err = memberlist.NewKeyring(nDB.config.Keys, nDB.config.Keys[0])
		if err != nil {
			return err
		}
		config.Keyring = nDB.keyring
	}

	nDB.networkBroadcasts = &memberlist.TransmitLimitedQueue{
		NumNodes: func() int {
			return len(nDB.nodes)
		},
		RetransmitMult: config.RetransmitMult,
	}

	mlist, err := memberlist.Create(config)
	if err != nil {
		return fmt.Errorf("failed to create memberlist: %v", err)
	}

	nDB.stopCh = make(chan struct{})
	nDB.memberlist = mlist
	nDB.mConfig = config

	for _, trigger := range []struct {
		interval time.Duration
		fn       func()
	}{
		{reapInterval, nDB.reapState},
		{config.GossipInterval, nDB.gossip},
		{config.PushPullInterval, nDB.bulkSyncTables},
	} {
		t := time.NewTicker(trigger.interval)
		go nDB.triggerFunc(trigger.interval, t.C, nDB.stopCh, trigger.fn)
		nDB.tickers = append(nDB.tickers, t)
	}

	return nil
}

func (nDB *NetworkDB) clusterJoin(members []string) error {
	mlist := nDB.memberlist

	if _, err := mlist.Join(members); err != nil {
		return fmt.Errorf("could not join node to memberlist: %v", err)
	}

	return nil
}

func (nDB *NetworkDB) clusterLeave() error {
	mlist := nDB.memberlist

	if err := mlist.Leave(time.Second); err != nil {
		return err
	}

	close(nDB.stopCh)

	for _, t := range nDB.tickers {
		t.Stop()
	}

	return mlist.Shutdown()
}

func (nDB *NetworkDB) triggerFunc(stagger time.Duration, C <-chan time.Time, stop <-chan struct{}, f func()) {
	// Use a random stagger to avoid syncronizing
	randStagger := time.Duration(uint64(rnd.Int63()) % uint64(stagger))
	select {
	case <-time.After(randStagger):
	case <-stop:
		return
	}
	for {
		select {
		case <-C:
			f()
		case <-stop:
			return
		}
	}
}

func (nDB *NetworkDB) reapState() {
	nDB.reapNetworks()
	nDB.reapTableEntries()
}

func (nDB *NetworkDB) reapNetworks() {
	now := time.Now()
	nDB.Lock()
	for name, nn := range nDB.networks {
		for id, n := range nn {
			if n.leaving && now.Sub(n.leaveTime) > reapInterval {
				delete(nn, id)
				nDB.deleteNetworkNode(id, name)
			}
		}
	}
	nDB.Unlock()
}

func (nDB *NetworkDB) reapTableEntries() {
	var (
		paths   []string
		entries []*entry
	)

	now := time.Now()

	nDB.RLock()
	nDB.indexes[byTable].Walk(func(path string, v interface{}) bool {
		entry, ok := v.(*entry)
		if !ok {
			return false
		}

		if !entry.deleting || now.Sub(entry.deleteTime) <= reapInterval {
			return false
		}

		paths = append(paths, path)
		entries = append(entries, entry)
		return false
	})
	nDB.RUnlock()

	nDB.Lock()
	for i, path := range paths {
		entry := entries[i]
		params := strings.Split(path[1:], "/")
		tname := params[0]
		nid := params[1]
		key := params[2]

		if _, ok := nDB.indexes[byTable].Delete(fmt.Sprintf("/%s/%s/%s", tname, nid, key)); !ok {
			logrus.Errorf("Could not delete entry in table %s with network id %s and key %s as it does not exist", tname, nid, key)
		}

		if _, ok := nDB.indexes[byNetwork].Delete(fmt.Sprintf("/%s/%s/%s", nid, tname, key)); !ok {
			logrus.Errorf("Could not delete entry in network %s with table name %s and key %s as it does not exist", nid, tname, key)
		}

		nDB.broadcaster.Write(makeEvent(opDelete, tname, nid, key, entry.value))
	}
	nDB.Unlock()
}

func (nDB *NetworkDB) gossip() {
	networkNodes := make(map[string][]string)
	nDB.RLock()
	thisNodeNetworks := nDB.networks[nDB.config.NodeName]
	for nid := range thisNodeNetworks {
		networkNodes[nid] = nDB.networkNodes[nid]

	}
	nDB.RUnlock()

	for nid, nodes := range networkNodes {
		mNodes := nDB.mRandomNodes(3, nodes)
		bytesAvail := udpSendBuf - compoundHeaderOverhead

		nDB.RLock()
		network, ok := thisNodeNetworks[nid]
		nDB.RUnlock()
		if !ok || network == nil {
			// It is normal for the network to be removed
			// between the time we collect the network
			// attachments of this node and processing
			// them here.
			continue
		}

		broadcastQ := network.tableBroadcasts

		if broadcastQ == nil {
			logrus.Errorf("Invalid broadcastQ encountered while gossiping for network %s", nid)
			continue
		}

		msgs := broadcastQ.GetBroadcasts(compoundOverhead, bytesAvail)
		if len(msgs) == 0 {
			continue
		}

		// Create a compound message
		compound := makeCompoundMessage(msgs)

		for _, node := range mNodes {
			nDB.RLock()
			mnode := nDB.nodes[node]
			nDB.RUnlock()

			if mnode == nil {
				break
			}

			// Send the compound message
			if err := nDB.memberlist.SendToUDP(mnode, compound); err != nil {
				logrus.Errorf("Failed to send gossip to %s: %s", mnode.Addr, err)
			}
		}
	}
}

func (nDB *NetworkDB) bulkSyncTables() {
	var networks []string
	nDB.RLock()
	for nid := range nDB.networks[nDB.config.NodeName] {
		networks = append(networks, nid)
	}
	nDB.RUnlock()

	for {
		if len(networks) == 0 {
			break
		}

		nid := networks[0]
		networks = networks[1:]

		completed, err := nDB.bulkSync(nid, false)
		if err != nil {
			logrus.Errorf("periodic bulk sync failure for network %s: %v", nid, err)
			continue
		}

		// Remove all the networks for which we have
		// successfully completed bulk sync in this iteration.
		updatedNetworks := make([]string, 0, len(networks))
		for _, nid := range networks {
			for _, completedNid := range completed {
				if nid == completedNid {
					continue
				}

				updatedNetworks = append(updatedNetworks, nid)
			}
		}

		networks = updatedNetworks
	}
}

func (nDB *NetworkDB) bulkSync(nid string, all bool) ([]string, error) {
	nDB.RLock()
	nodes := nDB.networkNodes[nid]
	nDB.RUnlock()

	if !all {
		// If not all, then just pick one.
		nodes = nDB.mRandomNodes(1, nodes)
	}

	logrus.Debugf("%s: Initiating bulk sync with nodes %v", nDB.config.NodeName, nodes)
	var err error
	var networks []string
	for _, node := range nodes {
		if node == nDB.config.NodeName {
			continue
		}

		networks = nDB.findCommonNetworks(node)
		err = nDB.bulkSyncNode(networks, node, true)
		if err != nil {
			err = fmt.Errorf("bulk sync failed on node %s: %v", node, err)
		}
	}

	if err != nil {
		return nil, err
	}

	return networks, nil
}

// Bulk sync all the table entries belonging to a set of networks to a
// single peer node. It can be unsolicited or can be in response to an
// unsolicited bulk sync
func (nDB *NetworkDB) bulkSyncNode(networks []string, node string, unsolicited bool) error {
	var msgs [][]byte

	logrus.Debugf("%s: Initiating bulk sync for networks %v with node %s", nDB.config.NodeName, networks, node)

	nDB.RLock()
	mnode := nDB.nodes[node]
	if mnode == nil {
		nDB.RUnlock()
		return nil
	}

	for _, nid := range networks {
		nDB.indexes[byNetwork].WalkPrefix(fmt.Sprintf("/%s", nid), func(path string, v interface{}) bool {
			entry, ok := v.(*entry)
			if !ok {
				return false
			}

			params := strings.Split(path[1:], "/")
			tEvent := TableEvent{
				Type:      TableEventTypeCreate,
				LTime:     entry.ltime,
				NodeName:  entry.node,
				NetworkID: nid,
				TableName: params[1],
				Key:       params[2],
				Value:     entry.value,
			}

			msg, err := encodeMessage(MessageTypeTableEvent, &tEvent)
			if err != nil {
				logrus.Errorf("Encode failure during bulk sync: %#v", tEvent)
				return false
			}

			msgs = append(msgs, msg)
			return false
		})
	}
	nDB.RUnlock()

	// Create a compound message
	compound := makeCompoundMessage(msgs)

	bsm := BulkSyncMessage{
		LTime:       nDB.tableClock.Time(),
		Unsolicited: unsolicited,
		NodeName:    nDB.config.NodeName,
		Networks:    networks,
		Payload:     compound,
	}

	buf, err := encodeMessage(MessageTypeBulkSync, &bsm)
	if err != nil {
		return fmt.Errorf("failed to encode bulk sync message: %v", err)
	}

	nDB.Lock()
	ch := make(chan struct{})
	nDB.bulkSyncAckTbl[node] = ch
	nDB.Unlock()

	err = nDB.memberlist.SendToTCP(mnode, buf)
	if err != nil {
		nDB.Lock()
		delete(nDB.bulkSyncAckTbl, node)
		nDB.Unlock()

		return fmt.Errorf("failed to send a TCP message during bulk sync: %v", err)
	}

	// Wait on a response only if it is unsolicited.
	if unsolicited {
		startTime := time.Now()
		select {
		case <-time.After(30 * time.Second):
			logrus.Errorf("Bulk sync to node %s timed out", node)
		case <-ch:
			nDB.Lock()
			delete(nDB.bulkSyncAckTbl, node)
			nDB.Unlock()

			logrus.Debugf("%s: Bulk sync to node %s took %s", nDB.config.NodeName, node, time.Now().Sub(startTime))
		}
	}

	return nil
}

// Returns a random offset between 0 and n
func randomOffset(n int) int {
	if n == 0 {
		return 0
	}

	val, err := rand.Int(rand.Reader, big.NewInt(int64(n)))
	if err != nil {
		logrus.Errorf("Failed to get a random offset: %v", err)
		return 0
	}

	return int(val.Int64())
}

// mRandomNodes is used to select up to m random nodes. It is possible
// that less than m nodes are returned.
func (nDB *NetworkDB) mRandomNodes(m int, nodes []string) []string {
	n := len(nodes)
	mNodes := make([]string, 0, m)
OUTER:
	// Probe up to 3*n times, with large n this is not necessary
	// since k << n, but with small n we want search to be
	// exhaustive
	for i := 0; i < 3*n && len(mNodes) < m; i++ {
		// Get random node
		idx := randomOffset(n)
		node := nodes[idx]

		if node == nDB.config.NodeName {
			continue
		}

		// Check if we have this node already
		for j := 0; j < len(mNodes); j++ {
			if node == mNodes[j] {
				continue OUTER
			}
		}

		// Append the node
		mNodes = append(mNodes, node)
	}

	return mNodes
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	//        "io"
	"io/ioutil"
	"path"
	//        "strings"
	"encoding/csv"
	"os"
	"strconv"
)

func checkErr(e error) {
	if e != nil {
		fmt.Println("POOP!")
		os.Exit(1)
	}
}

// Removes non-directory elements of any []os.FileInfo (a helper function, for convenience)
// Makes use of idiomatic Golang return: out_ls is declared and returned implicitly
func onlyDirectories(potential_files []os.FileInfo) (out_ls []os.FileInfo) {
	for _, fd := range potential_files {
		if fd.IsDir() {
			out_ls = append(out_ls, fd)
		}
	}
	return
}

// Extend "records" matrix to have rows until time "desired_time"
// Return: Extended version of record
func extendRecordsToTime(records [][]string, desired_time int, recordCols int) [][]string {
	lenr := len(records)
	// records[1] stores cycle [1], as records[0] is column names
	for j := lenr; j < desired_time+1; j++ {
		records = append(records, make([]string, recordCols))
		records[j][0] = strconv.Itoa(j)
		for k := 1; k < recordCols; k++ {
			records[j][k] = ""
		}
	}
	return records
}

// Enters all report subdirectories, from benchmark to fengine to trial;
// composes individual CSVs (only two columns) into larger CSVs
func composeAllNamed(desired_report_fname string) {
	master_path := "./reports"
	bmarks, err := ioutil.ReadDir(master_path)
	checkErr(err)
	for _, bmark := range bmarks {
		// all_fe_file, err := os.Create(path.Join(master_path, bmark.Name(), desired_report_fname))
		// checkErr(err)
		// defer all_fe_file.Close()
		// all_fe_writer := csv.NewWriter(all_fe_file)
		// meta_records := [][]string{{"time"}}
		potential_fengines, err := ioutil.ReadDir(path.Join(master_path, bmark.Name()))
		checkErr(err)
		// narrow potential_fengines to fengines so the indices of `range fengines` are useful
		fengines := onlyDirectories(potential_fengines)

		for _, fengine := range fengines {
			// Create fds
			this_fe_file, err := os.Create(path.Join(master_path, bmark.Name(), fengine.Name(), desired_report_fname))
			checkErr(err)
			defer this_fe_file.Close()
			this_fe_writer := csv.NewWriter(this_fe_file)

			// Create matrix, to eventually become a CSV
			records := [][]string{{"time"}}

			// Enter sub-directories
			potential_trials, err := ioutil.ReadDir(path.Join(master_path, bmark.Name(), fengine.Name()))
			checkErr(err)
			trials := onlyDirectories(potential_trials)

			num_record_columns := len(trials) + 1
			for j, trial := range trials {
				// Create fds
				this_file, err := os.Open(path.Join(master_path, bmark.Name(), fengine.Name(), trial.Name(), desired_report_fname))
				checkErr(err)
				defer this_file.Close()
				this_reader := csv.NewReader(this_file)

				// Read whole CSV to an array
				experiment_records, err := this_reader.ReadAll()
				checkErr(err)
				// Add the name of this new column to records[0]
				records[0] = append(records[0], fengine.Name()+trial.Name())

				for _, row := range experiment_records {
					// row[0] is time, on the x-axis; row[1] is value, on the y-axis
					time_now, err := strconv.Atoi(row[0])
					checkErr(err)
					//If this test went longer than all of the others, so far
					if len(records) < time_now+1 {
						records = extendRecordsToTime(records, time_now, num_record_columns)
					}
					records[time_now][j+1] = row[1]
				}
			}
			this_fe_writer.WriteAll(records)
			// Potentially put this fengine into a broader comparison CSV
		}
		// TODO: create comparison between fengines, having already composed trials
		// Do this by identifying the max (or potentially median) performing trial
		// For each fengine, and putting them all into a CSV which can be graphed
	}
}

func main() {
	composeAllNamed("coverage-graph.csv")
	composeAllNamed("corpus-size-graph.csv")
	composeAllNamed("corpus-elems-graph.csv")
	// createIFramesFor("setOfFrames.html")
	//
}
<commit_msg>Report gen documentation, also loop corrections<commit_after>package main

import (
	"fmt"
	//        "io"
	"io/ioutil"
	"path"
	//        "strings"
	"encoding/csv"
	"os"
	"strconv"
)

func checkErr(e error) {
	if e != nil {
		fmt.Println("Poop! Error encountered:", e)
		os.Exit(1)
	}
}

// Removes non-directory elements of any []os.FileInfo
func onlyDirectories(potential_files []os.FileInfo) (out_ls []os.FileInfo) {
	for _, fd := range potential_files {
		if fd.IsDir() {
			out_ls = append(out_ls, fd)
		}
	}
	return
}

// Extend "records" matrix to have rows until time "desired_time"
// Return: Extended version of record
func extendRecordsToTime(records [][]string, desired_time int, record_cols int) [][]string {
	lenr := len(records)
	// records[1] stores cycle [1], as records[0] is column names
	for j := lenr; j < desired_time+1; j++ {
		records = append(records, make([]string, record_cols))
		records[j][0] = strconv.Itoa(j)
	}
	return records
}

// Enters all report subdirectories, from benchmark to fengine to trial;
// composes individual CSVs (only two columns) into larger CSVs
func composeAllNamed(desired_report_fname string) {
	master_path := "./reports"
	bmarks, err := ioutil.ReadDir(master_path)
	checkErr(err)
	for _, bmark := range bmarks {
		// all_fe_file, err := os.Create(path.Join(master_path, bmark.Name(), desired_report_fname))
		// checkErr(err)
		// defer all_fe_file.Close()
		// all_fe_writer := csv.NewWriter(all_fe_file)
		// meta_records := [][]string{{"time"}}
		potential_fengines, err := ioutil.ReadDir(path.Join(master_path, bmark.Name()))
		checkErr(err)
		// narrow potential_fengines to fengines so the indices of `range fengines` are useful
		fengines := onlyDirectories(potential_fengines)

		for _, fengine := range fengines {
			// Create fds
			this_fe_file, err := os.Create(path.Join(master_path, bmark.Name(), fengine.Name(), desired_report_fname))
			checkErr(err)
			defer this_fe_file.Close()
			this_fe_writer := csv.NewWriter(this_fe_file)

			// Create matrix, to eventually become a CSV
			records := [][]string{{"time"}}

			// Enter sub-directories
			potential_trials, err := ioutil.ReadDir(path.Join(master_path, bmark.Name(), fengine.Name()))
			checkErr(err)
			trials := onlyDirectories(potential_trials)

			num_record_columns := len(trials) + 1
			for j, trial := range trials {
				// Create fds
				this_file, err := os.Open(path.Join(master_path, bmark.Name(), fengine.Name(), trial.Name(), desired_report_fname))
				checkErr(err)
				defer this_file.Close()
				this_reader := csv.NewReader(this_file)

				// Read whole CSV to an array
				experiment_records, err := this_reader.ReadAll()
				checkErr(err)
				// Add the name of this new column to records[0]
				records[0] = append(records[0], fengine.Name()+trial.Name())

				final_time, err := strconv.Atoi(experiment_records[len(experiment_records)-1][0])
				checkErr(err)
				//If this test went longer than all of the others, so far
				if len(records) < final_time+1 {
					records = extendRecordsToTime(records, final_time, num_record_columns)
				}
				for _, row := range experiment_records {
					// row[0] is time, on the x-axis; row[1] is value, on the y-axis
					time_now, err := strconv.Atoi(row[0])
					checkErr(err)
					records[time_now][j+1] = row[1]
				}
			}
			this_fe_writer.WriteAll(records)
			// Potentially put this fengine into a broader comparison CSV
		}
		// TODO: create comparison between fengines, having already composed trials
		// Do this by identifying the max (or potentially median) performing trial
		// For each fengine, and putting them all into a CSV which can be graphed
	}
}

func main() {
	composeAllNamed("coverage-graph.csv")
	composeAllNamed("corpus-size-graph.csv")
	composeAllNamed("corpus-elems-graph.csv")
	// createIFramesFor("setOfFrames.html")
	//
}
<|endoftext|>


<commit_before>package archive

import (
	"archive/tar"
	"context"
	"fmt"
	"io"
	"io/ioutil"
	"os"
	"os/exec"
	"strings"

	"golang.org/x/sys/unix"

	"github.com/lxc/lxd/lxd/apparmor"
	"github.com/lxc/lxd/lxd/sys"
	"github.com/lxc/lxd/shared"
	"github.com/lxc/lxd/shared/ioprogress"
	"github.com/lxc/lxd/shared/logger"
	"github.com/lxc/lxd/shared/subprocess"
)

// ExtractWithFds runs extractor process under specifc AppArmor profile.
// The allowedCmds argument specify commands which are allowed to run by apparmor.
// The cmd argument is automatically added to allowedCmds slice.
func ExtractWithFds(cmd string, args []string, allowedCmds []string, stdin io.ReadCloser, sysOS *sys.OS, output *os.File) error {
	outputPath := output.Name()

	allowedCmds = append(allowedCmds, cmd)
	allowedCmdPaths := []string{}
	for _, c := range allowedCmds {
		cmdPath, err := exec.LookPath(c)
		if err != nil {
			return fmt.Errorf("Failed to start extract: Failed to find executable: %w", err)
		}
		allowedCmdPaths = append(allowedCmdPaths, cmdPath)
	}

	err := apparmor.ArchiveLoad(sysOS, outputPath, allowedCmdPaths)
	if err != nil {
		return fmt.Errorf("Failed to start extract: Failed to load profile: %w", err)
	}
	defer apparmor.ArchiveDelete(sysOS, outputPath)
	defer apparmor.ArchiveUnload(sysOS, outputPath)

	p, err := subprocess.NewProcessWithFds(cmd, args, stdin, output, nil)
	if err != nil {
		return fmt.Errorf("Failed to start extract: Failed to creating subprocess: %w", err)
	}

	p.SetApparmor(apparmor.ArchiveProfileName(outputPath))

	err = p.Start()
	if err != nil {
		return fmt.Errorf("Failed to start extract: Failed running: tar: %w", err)
	}

	p.Wait(context.Background())
	return nil
}

// CompressedTarReader returns a tar reader from the supplied (optionally compressed) tarball stream.
// The unpacker arguments are those returned by DetectCompressionFile().
// The returned cancelFunc should be called when finished with reader to clean up any resources used.
// This can be done before reading to the end of the tarball if desired.
func CompressedTarReader(ctx context.Context, r io.ReadSeeker, unpacker []string, sysOS *sys.OS, outputPath string) (*tar.Reader, context.CancelFunc, error) {
	ctx, cancelFunc := context.WithCancel(ctx)

	r.Seek(0, 0)
	var tr *tar.Reader

	if len(unpacker) > 0 {
		cmdPath, err := exec.LookPath(unpacker[0])
		if err != nil {
			return nil, cancelFunc, fmt.Errorf("Failed to start unpack: Failed to find executable: %w", err)
		}

		err = apparmor.ArchiveLoad(sysOS, outputPath, []string{cmdPath})
		if err != nil {
			return nil, cancelFunc, fmt.Errorf("Failed to start unpack: Failed to load profile: %w", err)
		}

		pipeReader, pipeWriter := io.Pipe()
		p, err := subprocess.NewProcessWithFds(unpacker[0], unpacker[1:], ioutil.NopCloser(r), pipeWriter, nil)
		if err != nil {
			return nil, cancelFunc, fmt.Errorf("Failed to start unpack: Failed to creating subprocess: %w", err)
		}

		p.SetApparmor(apparmor.ArchiveProfileName(outputPath))
		err = p.Start()
		if err != nil {
			return nil, cancelFunc, fmt.Errorf("Failed to start unpack: Failed running: %s: %w", unpacker[0], err)
		}

		ctxCancelFunc := cancelFunc

		// Now that unpacker process has started, wrap context cancel function with one that waits for
		// the unpacker process to complete.
		cancelFunc = func() {
			ctxCancelFunc()
			pipeWriter.Close()
			p.Wait(ctx)
			apparmor.ArchiveUnload(sysOS, outputPath)
			apparmor.ArchiveDelete(sysOS, outputPath)
		}

		tr = tar.NewReader(pipeReader)
	} else {
		tr = tar.NewReader(r)
	}

	return tr, cancelFunc, nil
}

// Unpack extracts image from archive.
func Unpack(file string, path string, blockBackend bool, sysOS *sys.OS, tracker *ioprogress.ProgressTracker) error {
	extractArgs, extension, unpacker, err := shared.DetectCompression(file)
	if err != nil {
		return err
	}

	command := ""
	args := []string{}
	var reader io.Reader
	if strings.HasPrefix(extension, ".tar") {
		command = "tar"
		if sysOS.RunningInUserNS {
			// We can't create char/block devices so avoid extracting them.
			args = append(args, "--wildcards")
			args = append(args, "--exclude=dev/*")
			args = append(args, "--exclude=./dev/*")
			args = append(args, "--exclude=rootfs/dev/*")
			args = append(args, "--exclude=rootfs/./dev/*")
		}
		args = append(args, "--restrict", "--force-local")
		args = append(args, "-C", path, "--numeric-owner", "--xattrs-include=*")
		args = append(args, extractArgs...)
		args = append(args, "-")

		f, err := os.Open(file)
		if err != nil {
			return err
		}
		defer f.Close()

		reader = f

		// Attach the ProgressTracker if supplied.
		if tracker != nil {
			fsinfo, err := f.Stat()
			if err != nil {
				return err
			}

			tracker.Length = fsinfo.Size()
			reader = &ioprogress.ProgressReader{
				ReadCloser: f,
				Tracker:    tracker,
			}
		}
	} else if strings.HasPrefix(extension, ".squashfs") {
		// unsquashfs does not support reading from stdin,
		// so ProgressTracker is not possible.
		command = "unsquashfs"
		args = append(args, "-f", "-d", path, "-n")

		// Limit unsquashfs chunk size to 10% of memory and up to 256MB (default)
		// When running on a low memory system, also disable multi-processing
		mem, err := shared.DeviceTotalMemory()
		mem = mem / 1024 / 1024 / 10
		if err == nil && mem < 256 {
			args = append(args, "-da", fmt.Sprintf("%d", mem), "-fr", fmt.Sprintf("%d", mem), "-p", "1")
		}

		args = append(args, file)
	} else {
		return fmt.Errorf("Unsupported image format: %s", extension)
	}

	allowedCmds := []string{}
	if len(unpacker) > 0 {
		allowedCmds = append(allowedCmds, unpacker[0])
	}

	outputDir, err := os.OpenFile(path, os.O_RDONLY, 0)
	if err != nil {
		return fmt.Errorf("Error opening directory: %w", err)
	}
	defer outputDir.Close()

	var readCloser io.ReadCloser
	if reader != nil {
		readCloser = ioutil.NopCloser(reader)
	}

	err = ExtractWithFds(command, args, allowedCmds, readCloser, sysOS, outputDir)
	if err != nil {
		// We can't create char/block devices in unpriv containers so ignore related errors.
		if sysOS.RunningInUserNS && command == "unsquashfs" {
			runError, ok := err.(shared.RunError)
			if !ok || runError.Stderr == "" {
				return err
			}

			// Confirm that all errors are related to character or block devices.
			found := false
			for _, line := range strings.Split(runError.Stderr, "\n") {
				line = strings.TrimSpace(line)
				if line == "" {
					continue
				}

				if !strings.Contains(line, "failed to create block device") {
					continue
				}

				if !strings.Contains(line, "failed to create character device") {
					continue
				}

				// We found an actual error.
				found = true
			}

			if !found {
				// All good, assume everything unpacked.
				return nil
			}
		}

		// Check if we ran out of space
		fs := unix.Statfs_t{}

		err1 := unix.Statfs(path, &fs)
		if err1 != nil {
			return err1
		}

		// Check if we're running out of space
		if int64(fs.Bfree) < 10 {
			if blockBackend {
				return fmt.Errorf("Unable to unpack image, run out of disk space (consider increasing your pool's volume.size)")
			} else {
				return fmt.Errorf("Unable to unpack image, run out of disk space")
			}
		}

		logger.Debugf("Unpacking failed")
		logger.Debugf(err.Error())
		return fmt.Errorf("Unpack failed, %s.", err)
	}

	return nil
}
<commit_msg>lxd/archive/archive: Don't use supplementary unpacker command<commit_after>package archive

import (
	"archive/tar"
	"context"
	"fmt"
	"io"
	"io/ioutil"
	"os"
	"os/exec"
	"strings"

	"golang.org/x/sys/unix"

	"github.com/lxc/lxd/lxd/apparmor"
	"github.com/lxc/lxd/lxd/sys"
	"github.com/lxc/lxd/shared"
	"github.com/lxc/lxd/shared/ioprogress"
	"github.com/lxc/lxd/shared/logger"
	"github.com/lxc/lxd/shared/subprocess"
)

// ExtractWithFds runs extractor process under specifc AppArmor profile.
// The allowedCmds argument specify commands which are allowed to run by apparmor.
// The cmd argument is automatically added to allowedCmds slice.
func ExtractWithFds(cmd string, args []string, allowedCmds []string, stdin io.ReadCloser, sysOS *sys.OS, output *os.File) error {
	outputPath := output.Name()

	allowedCmds = append(allowedCmds, cmd)
	allowedCmdPaths := []string{}
	for _, c := range allowedCmds {
		cmdPath, err := exec.LookPath(c)
		if err != nil {
			return fmt.Errorf("Failed to start extract: Failed to find executable: %w", err)
		}
		allowedCmdPaths = append(allowedCmdPaths, cmdPath)
	}

	err := apparmor.ArchiveLoad(sysOS, outputPath, allowedCmdPaths)
	if err != nil {
		return fmt.Errorf("Failed to start extract: Failed to load profile: %w", err)
	}
	defer apparmor.ArchiveDelete(sysOS, outputPath)
	defer apparmor.ArchiveUnload(sysOS, outputPath)

	p, err := subprocess.NewProcessWithFds(cmd, args, stdin, output, nil)
	if err != nil {
		return fmt.Errorf("Failed to start extract: Failed to creating subprocess: %w", err)
	}

	p.SetApparmor(apparmor.ArchiveProfileName(outputPath))

	err = p.Start()
	if err != nil {
		return fmt.Errorf("Failed to start extract: Failed running: tar: %w", err)
	}

	p.Wait(context.Background())
	return nil
}

// CompressedTarReader returns a tar reader from the supplied (optionally compressed) tarball stream.
// The unpacker arguments are those returned by DetectCompressionFile().
// The returned cancelFunc should be called when finished with reader to clean up any resources used.
// This can be done before reading to the end of the tarball if desired.
func CompressedTarReader(ctx context.Context, r io.ReadSeeker, unpacker []string, sysOS *sys.OS, outputPath string) (*tar.Reader, context.CancelFunc, error) {
	ctx, cancelFunc := context.WithCancel(ctx)

	r.Seek(0, 0)
	var tr *tar.Reader

	if len(unpacker) > 0 {
		cmdPath, err := exec.LookPath(unpacker[0])
		if err != nil {
			return nil, cancelFunc, fmt.Errorf("Failed to start unpack: Failed to find executable: %w", err)
		}

		err = apparmor.ArchiveLoad(sysOS, outputPath, []string{cmdPath})
		if err != nil {
			return nil, cancelFunc, fmt.Errorf("Failed to start unpack: Failed to load profile: %w", err)
		}

		pipeReader, pipeWriter := io.Pipe()
		p, err := subprocess.NewProcessWithFds(unpacker[0], unpacker[1:], ioutil.NopCloser(r), pipeWriter, nil)
		if err != nil {
			return nil, cancelFunc, fmt.Errorf("Failed to start unpack: Failed to creating subprocess: %w", err)
		}

		p.SetApparmor(apparmor.ArchiveProfileName(outputPath))
		err = p.Start()
		if err != nil {
			return nil, cancelFunc, fmt.Errorf("Failed to start unpack: Failed running: %s: %w", unpacker[0], err)
		}

		ctxCancelFunc := cancelFunc

		// Now that unpacker process has started, wrap context cancel function with one that waits for
		// the unpacker process to complete.
		cancelFunc = func() {
			ctxCancelFunc()
			pipeWriter.Close()
			p.Wait(ctx)
			apparmor.ArchiveUnload(sysOS, outputPath)
			apparmor.ArchiveDelete(sysOS, outputPath)
		}

		tr = tar.NewReader(pipeReader)
	} else {
		tr = tar.NewReader(r)
	}

	return tr, cancelFunc, nil
}

// Unpack extracts image from archive.
func Unpack(file string, path string, blockBackend bool, sysOS *sys.OS, tracker *ioprogress.ProgressTracker) error {
	extractArgs, extension, unpacker, err := shared.DetectCompression(file)
	if err != nil {
		return err
	}

	command := ""
	args := []string{}
	var allowedCmds []string
	var reader io.Reader
	if strings.HasPrefix(extension, ".tar") {
		command = "tar"
		if sysOS.RunningInUserNS {
			// We can't create char/block devices so avoid extracting them.
			args = append(args, "--wildcards")
			args = append(args, "--exclude=dev/*")
			args = append(args, "--exclude=./dev/*")
			args = append(args, "--exclude=rootfs/dev/*")
			args = append(args, "--exclude=rootfs/./dev/*")
		}
		args = append(args, "--restrict", "--force-local")
		args = append(args, "-C", path, "--numeric-owner", "--xattrs-include=*")
		args = append(args, extractArgs...)
		args = append(args, "-")

		f, err := os.Open(file)
		if err != nil {
			return err
		}
		defer f.Close()

		reader = f

		// Attach the ProgressTracker if supplied.
		if tracker != nil {
			fsinfo, err := f.Stat()
			if err != nil {
				return err
			}

			tracker.Length = fsinfo.Size()
			reader = &ioprogress.ProgressReader{
				ReadCloser: f,
				Tracker:    tracker,
			}
		}

		// Allow supplementary commands for the unpacker to use.
		if len(unpacker) > 0 {
			allowedCmds = append(allowedCmds, unpacker[0])
		}
	} else if strings.HasPrefix(extension, ".squashfs") {
		// unsquashfs does not support reading from stdin,
		// so ProgressTracker is not possible.
		command = "unsquashfs"
		args = append(args, "-f", "-d", path, "-n")

		// Limit unsquashfs chunk size to 10% of memory and up to 256MB (default)
		// When running on a low memory system, also disable multi-processing
		mem, err := shared.DeviceTotalMemory()
		mem = mem / 1024 / 1024 / 10
		if err == nil && mem < 256 {
			args = append(args, "-da", fmt.Sprintf("%d", mem), "-fr", fmt.Sprintf("%d", mem), "-p", "1")
		}

		args = append(args, file)
	} else {
		return fmt.Errorf("Unsupported image format: %s", extension)
	}

	outputDir, err := os.OpenFile(path, os.O_RDONLY, 0)
	if err != nil {
		return fmt.Errorf("Error opening directory: %w", err)
	}
	defer outputDir.Close()

	var readCloser io.ReadCloser
	if reader != nil {
		readCloser = ioutil.NopCloser(reader)
	}

	err = ExtractWithFds(command, args, allowedCmds, readCloser, sysOS, outputDir)
	if err != nil {
		// We can't create char/block devices in unpriv containers so ignore related errors.
		if sysOS.RunningInUserNS && command == "unsquashfs" {
			runError, ok := err.(shared.RunError)
			if !ok || runError.Stderr == "" {
				return err
			}

			// Confirm that all errors are related to character or block devices.
			found := false
			for _, line := range strings.Split(runError.Stderr, "\n") {
				line = strings.TrimSpace(line)
				if line == "" {
					continue
				}

				if !strings.Contains(line, "failed to create block device") {
					continue
				}

				if !strings.Contains(line, "failed to create character device") {
					continue
				}

				// We found an actual error.
				found = true
			}

			if !found {
				// All good, assume everything unpacked.
				return nil
			}
		}

		// Check if we ran out of space
		fs := unix.Statfs_t{}

		err1 := unix.Statfs(path, &fs)
		if err1 != nil {
			return err1
		}

		// Check if we're running out of space
		if int64(fs.Bfree) < 10 {
			if blockBackend {
				return fmt.Errorf("Unable to unpack image, run out of disk space (consider increasing your pool's volume.size)")
			} else {
				return fmt.Errorf("Unable to unpack image, run out of disk space")
			}
		}

		logger.Debugf("Unpacking failed")
		logger.Debugf(err.Error())
		return fmt.Errorf("Unpack failed, %s.", err)
	}

	return nil
}
<|endoftext|>


<commit_before>package main

import (
	"encoding/json"
	"fmt"
	"net/http"
	"time"

	"github.com/gorilla/mux"
	"github.com/lxc/lxd/shared"
)

func containerStateGet(d *Daemon, r *http.Request) Response {
	name := mux.Vars(r)["name"]
	c, err := containerLXDLoad(d, name)
	if err != nil {
		return SmartError(err)
	}

	state, err := c.RenderState()
	if err != nil {
		return InternalError(err)
	}

	return SyncResponse(true, state.Status)
}

func containerStatePut(d *Daemon, r *http.Request) Response {
	name := mux.Vars(r)["name"]

	raw := containerStatePutReq{}

	// We default to -1 (i.e. no timeout) here instead of 0 (instant
	// timeout).
	raw.Timeout = -1

	if err := json.NewDecoder(r.Body).Decode(&raw); err != nil {
		return BadRequest(err)
	}

	c, err := containerLXDLoad(d, name)
	if err != nil {
		return SmartError(err)
	}

	var do func() error
	switch shared.ContainerAction(raw.Action) {
	case shared.Start:
		do = func() error {
			if err = c.Start(); err != nil {
				return err
			}
			return nil
		}
	case shared.Stop:
		if raw.Timeout == 0 || raw.Force {
			do = func() error {
				if err = c.Stop(); err != nil {
					return err
				}
				return nil
			}
		} else {
			do = func() error {
				if err = c.Shutdown(time.Duration(raw.Timeout) * time.Second); err != nil {
					return err
				}
				return nil
			}
		}
	case shared.Restart:
		do = c.Reboot
	case shared.Freeze:
		do = c.Freeze
	case shared.Unfreeze:
		do = c.Unfreeze
	default:
		return BadRequest(fmt.Errorf("unknown action %s", raw.Action))
	}

	return AsyncResponse(shared.OperationWrap(do), nil)
}
<commit_msg>Implement restart as stop+start<commit_after>package main

import (
	"encoding/json"
	"fmt"
	"net/http"
	"time"

	"github.com/gorilla/mux"
	"github.com/lxc/lxd/shared"
)

func containerStateGet(d *Daemon, r *http.Request) Response {
	name := mux.Vars(r)["name"]
	c, err := containerLXDLoad(d, name)
	if err != nil {
		return SmartError(err)
	}

	state, err := c.RenderState()
	if err != nil {
		return InternalError(err)
	}

	return SyncResponse(true, state.Status)
}

func containerStatePut(d *Daemon, r *http.Request) Response {
	name := mux.Vars(r)["name"]

	raw := containerStatePutReq{}

	// We default to -1 (i.e. no timeout) here instead of 0 (instant
	// timeout).
	raw.Timeout = -1

	if err := json.NewDecoder(r.Body).Decode(&raw); err != nil {
		return BadRequest(err)
	}

	c, err := containerLXDLoad(d, name)
	if err != nil {
		return SmartError(err)
	}

	var do func() error
	switch shared.ContainerAction(raw.Action) {
	case shared.Start:
		do = func() error {
			if err = c.Start(); err != nil {
				return err
			}
			return nil
		}
	case shared.Stop:
		if raw.Timeout == 0 || raw.Force {
			do = func() error {
				if err = c.Stop(); err != nil {
					return err
				}
				return nil
			}
		} else {
			do = func() error {
				if err = c.Shutdown(time.Duration(raw.Timeout) * time.Second); err != nil {
					return err
				}
				return nil
			}
		}
	case shared.Restart:
		do = func() error {
			if raw.Timeout == 0 || raw.Force {
				if err = c.Stop(); err != nil {
					return err
				}
			} else {
				if err = c.Shutdown(time.Duration(raw.Timeout) * time.Second); err != nil {
					return err
				}
			}
			if err = c.Start(); err != nil {
				return err
			}
			return nil
		}
	case shared.Freeze:
		do = c.Freeze
	case shared.Unfreeze:
		do = c.Unfreeze
	default:
		return BadRequest(fmt.Errorf("unknown action %s", raw.Action))
	}

	return AsyncResponse(shared.OperationWrap(do), nil)
}
<|endoftext|>


<commit_before>//go:build linux && cgo && !agent

package cluster

import (
	"database/sql"
	"fmt"
)

// RegisterStmt register a SQL statement.
//
// Registered statements will be prepared upfront and re-used, to speed up
// execution.
//
// Return a unique registration code.
func RegisterStmt(sql string) int {
	code := len(stmts)
	stmts[code] = sql
	return code
}

// PrepareStmts prepares all registered statements and returns an index from
// statement code to prepared statement object.
func PrepareStmts(db *sql.DB, skipErrors bool) (map[int]*sql.Stmt, error) {
	index := map[int]*sql.Stmt{}

	for code, sql := range stmts {
		stmt, err := db.Prepare(sql)
		if err != nil && !skipErrors {
			return nil, fmt.Errorf("%q: %w", sql, err)
		}

		index[code] = stmt
	}

	return index, nil
}

var stmts = map[int]string{} // Statement code to statement SQL text.

// PreparedStmts is a placeholder for transitioning to package-scoped transaction functions.
var PreparedStmts = map[int]*sql.Stmt{}

// stmt prepares the in-memory prepared statement for the transaction.
func stmt(tx *sql.Tx, code int) *sql.Stmt {
	stmt, ok := PreparedStmts[code]
	if !ok {
		panic(fmt.Sprintf("No prepared statement registered with code %d", code))
	}

	return tx.Stmt(stmt)
}

// prepare prepares a new statement from a SQL string.
func prepare(tx *sql.Tx, sql string) (*sql.Stmt, error) {
	stmt, err := tx.Prepare(sql)
	if err != nil {
		return nil, fmt.Errorf("Unable to prepare statement with error: %w", err)
	}

	return stmt, nil
}
<commit_msg>lxd/db/cluster/stmt: Export Stmt helper<commit_after>//go:build linux && cgo && !agent

package cluster

import (
	"database/sql"
	"fmt"
)

// RegisterStmt register a SQL statement.
//
// Registered statements will be prepared upfront and re-used, to speed up
// execution.
//
// Return a unique registration code.
func RegisterStmt(sql string) int {
	code := len(stmts)
	stmts[code] = sql
	return code
}

// PrepareStmts prepares all registered statements and returns an index from
// statement code to prepared statement object.
func PrepareStmts(db *sql.DB, skipErrors bool) (map[int]*sql.Stmt, error) {
	index := map[int]*sql.Stmt{}

	for code, sql := range stmts {
		stmt, err := db.Prepare(sql)
		if err != nil && !skipErrors {
			return nil, fmt.Errorf("%q: %w", sql, err)
		}

		index[code] = stmt
	}

	return index, nil
}

var stmts = map[int]string{} // Statement code to statement SQL text.

// PreparedStmts is a placeholder for transitioning to package-scoped transaction functions.
var PreparedStmts = map[int]*sql.Stmt{}

// Stmt prepares the in-memory prepared statement for the transaction.
func Stmt(tx *sql.Tx, code int) *sql.Stmt {
	stmt, ok := PreparedStmts[code]
	if !ok {
		panic(fmt.Sprintf("No prepared statement registered with code %d", code))
	}

	return tx.Stmt(stmt)
}

// prepare prepares a new statement from a SQL string.
func prepare(tx *sql.Tx, sql string) (*sql.Stmt, error) {
	stmt, err := tx.Prepare(sql)
	if err != nil {
		return nil, fmt.Errorf("Unable to prepare statement with error: %w", err)
	}

	return stmt, nil
}
<|endoftext|>


<commit_before>package ripo

import "testing"
import "github.com/stretchr/testify/assert"
import "reflect"

func TestFromEmpty(t *testing.T) {
	{
		value, err := FromEmpty.GetString(nil, "foo")
		assert.NoError(t, err)
		assert.Equal(t, "", *value)
	}
	{
		value, err := FromEmpty.GetStringList(nil, "foo")
		assert.NoError(t, err)
		assert.Equal(t, []string{}, value)
	}
	{
		value, err := FromEmpty.GetInt(nil, "foo")
		assert.NoError(t, err)
		assert.Equal(t, 0, *value)
	}
	{
		value, err := FromEmpty.GetFloat(nil, "foo")
		assert.NoError(t, err)
		assert.Equal(t, 0.0, *value)
	}
	{
		value, err := FromEmpty.GetBool(nil, "foo")
		assert.NoError(t, err)
		assert.Equal(t, false, *value)
	}
	{
		value, err := FromEmpty.GetTime(nil, "foo")
		assert.NoError(t, err)
		assert.Equal(t, int64(-62135596800), value.Unix())
	}
	{
		type Person struct {
			Name      string  `json:"name"`
			BirthDate []int   `json:"birthDate"` // mapstructure does not support [3]int
			Age       float64 `json:"age"`
		}
		value, err := FromEmpty.GetObject(nil, "person", reflect.TypeOf(&Person{}))
		assert.NoError(t, err)
		assert.Equal(t, &Person{}, value)
	}
	{
		type Person struct {
			Name      string  `json:"name"`
			BirthDate []int   `json:"birthDate"` // mapstructure does not support [3]int
			Age       float64 `json:"age"`
		}
		value, err := FromEmpty.GetObject(nil, "person", reflect.TypeOf(Person{}))
		assert.NoError(t, err)
		assert.Equal(t, Person{}, value)
	}
}
<commit_msg>add test for FromEmpty.GetObject with slice<commit_after>package ripo

import "testing"
import "github.com/stretchr/testify/assert"
import "reflect"

func TestFromEmpty(t *testing.T) {
	{
		value, err := FromEmpty.GetString(nil, "foo")
		assert.NoError(t, err)
		assert.Equal(t, "", *value)
	}
	{
		value, err := FromEmpty.GetStringList(nil, "foo")
		assert.NoError(t, err)
		assert.Equal(t, []string{}, value)
	}
	{
		value, err := FromEmpty.GetInt(nil, "foo")
		assert.NoError(t, err)
		assert.Equal(t, 0, *value)
	}
	{
		value, err := FromEmpty.GetFloat(nil, "foo")
		assert.NoError(t, err)
		assert.Equal(t, 0.0, *value)
	}
	{
		value, err := FromEmpty.GetBool(nil, "foo")
		assert.NoError(t, err)
		assert.Equal(t, false, *value)
	}
	{
		value, err := FromEmpty.GetTime(nil, "foo")
		assert.NoError(t, err)
		assert.Equal(t, int64(-62135596800), value.Unix())
	}
	{
		type Person struct {
			Name      string  `json:"name"`
			BirthDate []int   `json:"birthDate"` // mapstructure does not support [3]int
			Age       float64 `json:"age"`
		}
		value, err := FromEmpty.GetObject(nil, "person", reflect.TypeOf(&Person{}))
		assert.NoError(t, err)
		assert.Equal(t, &Person{}, value)
	}
	type Person struct {
		Name      string  `json:"name"`
		BirthDate []int   `json:"birthDate"` // mapstructure does not support [3]int
		Age       float64 `json:"age"`
	}
	{
		value, err := FromEmpty.GetObject(nil, "person", reflect.TypeOf(Person{}))
		assert.NoError(t, err)
		assert.Equal(t, Person{}, value)
	}
	{
		value, err := FromEmpty.GetObject(nil, "list", reflect.SliceOf(reflect.TypeOf(Person{})))
		assert.NoError(t, err)
		assert.Equal(t, []Person(nil), value)
	}
}
<|endoftext|>


<commit_before>package main

/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements. See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership. The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License. You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied. See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

import (
	"fmt"
	"time"

	"git.apache.org/thrift.git/lib/go/thrift"
	"github.com/nats-io/nats"
	"github.com/tylertreat/thrift-nats/example/gen-go/tutorial"
	"github.com/tylertreat/thrift-nats/thrift_nats"
)

func handleClient(client *tutorial.CalculatorClient) (err error) {
	client.Ping()
	fmt.Println("ping()")

	sum, err := client.Add(1, 1)
	if err != nil {
		switch v := err.(type) {
		case *tutorial.InvalidOperation:
			fmt.Println("Invalid operation:", v)
		default:
			fmt.Println("Error during operation:", err)
		}
		return err
	}

	fmt.Print("1+1=", sum, "\n")

	work := tutorial.NewWork()
	work.Op = tutorial.Operation_DIVIDE
	work.Num1 = 1
	work.Num2 = 0
	quotient, err := client.Calculate(1, work)
	if err != nil {
		switch v := err.(type) {
		case *tutorial.InvalidOperation:
			fmt.Println("Invalid operation:", v)
		default:
			fmt.Println("Error during operation:", err)
		}
		return err
	} else {
		fmt.Println("Whoa we can divide by 0 with new value:", quotient)
	}

	work.Op = tutorial.Operation_SUBTRACT
	work.Num1 = 15
	work.Num2 = 10
	diff, err := client.Calculate(1, work)
	if err != nil {
		switch v := err.(type) {
		case *tutorial.InvalidOperation:
			fmt.Println("Invalid operation:", v)
		default:
			fmt.Println("Error during operation:", err)
		}
		return err
	} else {
		fmt.Print("15-10=", diff, "\n")
	}

	log, err := client.GetStruct(1)
	if err != nil {
		fmt.Println("Unable to get struct:", err)
		return err
	} else {
		fmt.Println("Check log:", log.Value)
	}
	return err
}

func runClient(transportFactory thrift.TTransportFactory,
	protocolFactory thrift.TProtocolFactory, addr string, secure bool) error {

	opts := nats.DefaultOptions
	opts.Servers = []string{addr}
	opts.Secure = secure
	conn, err := opts.Connect()
	if err != nil {
		return err
	}

	transport, err := thrift_nats.NATSTransportFactory(conn, "foo", time.Second, time.Second)
	if err != nil {
		return err
	}
	transport = transportFactory.GetTransport(transport)

	defer transport.Close()
	if err := transport.Open(); err != nil {
		return err
	}

	return handleClient(tutorial.NewCalculatorClientFactory(transport, protocolFactory))
}
<commit_msg>Close NATS conn<commit_after>package main

/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements. See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership. The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License. You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied. See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

import (
	"fmt"
	"time"

	"git.apache.org/thrift.git/lib/go/thrift"
	"github.com/nats-io/nats"
	"github.com/tylertreat/thrift-nats/example/gen-go/tutorial"
	"github.com/tylertreat/thrift-nats/thrift_nats"
)

func handleClient(client *tutorial.CalculatorClient) (err error) {
	client.Ping()
	fmt.Println("ping()")

	sum, err := client.Add(1, 1)
	if err != nil {
		switch v := err.(type) {
		case *tutorial.InvalidOperation:
			fmt.Println("Invalid operation:", v)
		default:
			fmt.Println("Error during operation:", err)
		}
		return err
	}

	fmt.Print("1+1=", sum, "\n")

	work := tutorial.NewWork()
	work.Op = tutorial.Operation_DIVIDE
	work.Num1 = 1
	work.Num2 = 0
	quotient, err := client.Calculate(1, work)
	if err != nil {
		switch v := err.(type) {
		case *tutorial.InvalidOperation:
			fmt.Println("Invalid operation:", v)
		default:
			fmt.Println("Error during operation:", err)
		}
		return err
	} else {
		fmt.Println("Whoa we can divide by 0 with new value:", quotient)
	}

	work.Op = tutorial.Operation_SUBTRACT
	work.Num1 = 15
	work.Num2 = 10
	diff, err := client.Calculate(1, work)
	if err != nil {
		switch v := err.(type) {
		case *tutorial.InvalidOperation:
			fmt.Println("Invalid operation:", v)
		default:
			fmt.Println("Error during operation:", err)
		}
		return err
	} else {
		fmt.Print("15-10=", diff, "\n")
	}

	log, err := client.GetStruct(1)
	if err != nil {
		fmt.Println("Unable to get struct:", err)
		return err
	} else {
		fmt.Println("Check log:", log.Value)
	}
	return err
}

func runClient(transportFactory thrift.TTransportFactory,
	protocolFactory thrift.TProtocolFactory, addr string, secure bool) error {

	opts := nats.DefaultOptions
	opts.Servers = []string{addr}
	opts.Secure = secure
	conn, err := opts.Connect()
	if err != nil {
		return err
	}
	defer conn.Close()

	transport, err := thrift_nats.NATSTransportFactory(conn, "foo", time.Second, time.Second)
	if err != nil {
		return err
	}
	transport = transportFactory.GetTransport(transport)

	defer transport.Close()
	if err := transport.Open(); err != nil {
		return err
	}

	return handleClient(tutorial.NewCalculatorClientFactory(transport, protocolFactory))
}
<|endoftext|>


<commit_before>package make

import (
	"fmt"
	"os"
	"strings"

	log "github.com/Sirupsen/logrus"

	"github.com/fubarhouse/golang-drush/vhost"
)

// VhostPathSet sets a virtual host path
func (Site *Site) VhostPathSet(value string) {
	Site.Vhostpath = value
}

// VhostInstall install a virtual host
func (Site *Site) VhostInstall() {
	var vhostPath string
	vhostPath = strings.Replace(Site.Path+Site.TimeStampGet(), Site.TimeStampGet(), Site.Domain+".latest/"+Site.Docroot, -1)
	fmt.Println("Path", Site.Path)
	fmt.Println("Timestamp", Site.TimeStampGet())
	fmt.Println("S", Site.Domain)
	fmt.Println("D", Site.Docroot)
	fmt.Println("X", Site.Domain+".latest/"+Site.Docroot)
	vhostFile := vhost.NewVirtualHost(Site.Name, vhostPath, Site.Webserver, Site.Domain, Site.Vhostpath)

	if Site.Template == "" {
		Site.Template = fmt.Sprintf("%v/src/github.com/fubarhouse/golang-drush/cmd/yoink/templates/vhost-%v.gotpl", os.Getenv("GOPATH"), Site.Webserver)
		log.Printf("No input vhost file, using %v", Site.Template)
	}

	vhostFile.Install(Site.Template)
}

// VhostUninstall un-installs a virtual host
func (Site *Site) VhostUninstall() {
	var vhostPath string
	vhostPath = strings.Replace(Site.Path+Site.TimeStampGet(), Site.TimeStampGet(), Site.Domain+".latest/"+Site.Docroot, -1)
	vhostFile := vhost.NewVirtualHost(Site.Name, vhostPath, Site.Webserver, Site.Domain, Site.Vhostpath)
	vhostFile.Uninstall()
}

// WebserverSet sets the webserver field for a site struct
func (Site *Site) WebserverSet(value string) {
	Site.Webserver = value
}
<commit_msg>Adjust vhost root<commit_after>package make

import (
	"fmt"
	"os"
	"strings"

	log "github.com/Sirupsen/logrus"

	"github.com/fubarhouse/golang-drush/vhost"
)

// VhostPathSet sets a virtual host path
func (Site *Site) VhostPathSet(value string) {
	Site.Vhostpath = value
}

// VhostInstall install a virtual host
func (Site *Site) VhostInstall() {
	var vhostPath string
	vhostPath = strings.Replace(Site.Path+Site.TimeStampGet(), Site.TimeStampGet(), ".latest/"+Site.Docroot, -1)
	fmt.Println("Path", Site.Path)
	fmt.Println("Timestamp", Site.TimeStampGet())
	fmt.Println("S", Site.Domain)
	fmt.Println("D", Site.Docroot)
	fmt.Println("X", Site.Domain+".latest/"+Site.Docroot)
	vhostFile := vhost.NewVirtualHost(Site.Name, vhostPath, Site.Webserver, Site.Domain, Site.Vhostpath)

	if Site.Template == "" {
		Site.Template = fmt.Sprintf("%v/src/github.com/fubarhouse/golang-drush/cmd/yoink/templates/vhost-%v.gotpl", os.Getenv("GOPATH"), Site.Webserver)
		log.Printf("No input vhost file, using %v", Site.Template)
	}

	vhostFile.Install(Site.Template)
}

// VhostUninstall un-installs a virtual host
func (Site *Site) VhostUninstall() {
	var vhostPath string
	vhostPath = strings.Replace(Site.Path+Site.TimeStampGet(), Site.TimeStampGet(), Site.Domain+".latest/"+Site.Docroot, -1)
	vhostFile := vhost.NewVirtualHost(Site.Name, vhostPath, Site.Webserver, Site.Domain, Site.Vhostpath)
	vhostFile.Uninstall()
}

// WebserverSet sets the webserver field for a site struct
func (Site *Site) WebserverSet(value string) {
	Site.Webserver = value
}
<|endoftext|>


<commit_before><commit_msg>remove hack now that vector of int works.<commit_after><|endoftext|>


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

package net

import (
	"regexp";
	"testing";
)

type DialErrorTest struct {
	Net string;
	Laddr string;
	Raddr string;
	Pattern string;
}

var dialErrorTests = []DialErrorTest {
	DialErrorTest{
		"datakit", "", "mh/astro/r70",
		"dial datakit mh/astro/r70: unknown network datakit",
	},
	DialErrorTest{
		"tcp", "", "127.0.0.1:☺",
		"dial tcp 127.0.0.1:☺: unknown port tcp/☺",
	},
	DialErrorTest{
		"tcp", "", "no-such-name.google.com.:80",
		"dial tcp no-such-name.google.com.:80: lookup no-such-name.google.com.( on .*)?: no such host",
	},
	DialErrorTest{
		"tcp", "", "no-such-name.no-such-top-level-domain.:80",
		"dial tcp no-such-name.no-such-top-level-domain.:80: lookup no-such-name.no-such-top-level-domain.( on .*)?: no (.*)",
	},
	DialErrorTest{
		"tcp", "", "no-such-name:80",
		`dial tcp no-such-name:80: lookup no-such-name\..*\.( on .*)?: no such host`,
	},
	DialErrorTest{
		"tcp", "", "mh/astro/r70:http",
		"dial tcp mh/astro/r70:http: lookup mh/astro/r70: invalid domain name",
	},
	DialErrorTest{
		"unix", "", "/etc/file-not-found",
		"dial unix /etc/file-not-found: no such file or directory",
	},
	DialErrorTest{
		"unix", "", "/etc/",
		"dial unix /etc/: (permission denied|socket operation on non-socket)",
	},
}

func TestDialError(t *testing.T) {
	for i, tt := range dialErrorTests {
		c, e := Dial(tt.Net, tt.Laddr, tt.Raddr);
		if c != nil {
			c.Close();
		}
		if e == nil {
			t.Errorf("#%d: nil error, want match for %#q", i, tt.Pattern);
			continue;
		}
		s := e.String();
		match, _ := regexp.MatchString(tt.Pattern, s);
		if !match {
			t.Errorf("#%d: %q, want match for %#q", i, s, tt.Pattern);
		}
	}
}
<commit_msg>two more regexp tweaks<commit_after>// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package net

import (
	"regexp";
	"testing";
)

type DialErrorTest struct {
	Net string;
	Laddr string;
	Raddr string;
	Pattern string;
}

var dialErrorTests = []DialErrorTest {
	DialErrorTest{
		"datakit", "", "mh/astro/r70",
		"dial datakit mh/astro/r70: unknown network datakit",
	},
	DialErrorTest{
		"tcp", "", "127.0.0.1:☺",
		"dial tcp 127.0.0.1:☺: unknown port tcp/☺",
	},
	DialErrorTest{
		"tcp", "", "no-such-name.google.com.:80",
		"dial tcp no-such-name.google.com.:80: lookup no-such-name.google.com.( on .*)?: no (.*)",
	},
	DialErrorTest{
		"tcp", "", "no-such-name.no-such-top-level-domain.:80",
		"dial tcp no-such-name.no-such-top-level-domain.:80: lookup no-such-name.no-such-top-level-domain.( on .*)?: no (.*)",
	},
	DialErrorTest{
		"tcp", "", "no-such-name:80",
		`dial tcp no-such-name:80: lookup no-such-name\..*\.( on .*)?: no (.*)`,
	},
	DialErrorTest{
		"tcp", "", "mh/astro/r70:http",
		"dial tcp mh/astro/r70:http: lookup mh/astro/r70: invalid domain name",
	},
	DialErrorTest{
		"unix", "", "/etc/file-not-found",
		"dial unix /etc/file-not-found: no such file or directory",
	},
	DialErrorTest{
		"unix", "", "/etc/",
		"dial unix /etc/: (permission denied|socket operation on non-socket)",
	},
}

func TestDialError(t *testing.T) {
	for i, tt := range dialErrorTests {
		c, e := Dial(tt.Net, tt.Laddr, tt.Raddr);
		if c != nil {
			c.Close();
		}
		if e == nil {
			t.Errorf("#%d: nil error, want match for %#q", i, tt.Pattern);
			continue;
		}
		s := e.String();
		match, _ := regexp.MatchString(tt.Pattern, s);
		if !match {
			t.Errorf("#%d: %q, want match for %#q", i, s, tt.Pattern);
		}
	}
}
<|endoftext|>