<commit_before>package udpsender

import (
	"bytes"
	"crypto/aes"
	"crypto/cipher"
	"crypto/rand"
	"crypto/sha1"
	"encoding/binary"
	"encoding/hex"
	"errors"
	"fmt"
	"io"
	"net"
	"os"
	"time"
)

type RecvService struct {
	key          string
	ch           chan *RecvBlock
	transactions map[string]*RecvTransaction
	sock         *net.UDPConn
	fn           RecvHandleFunc
	disk         bool
	dir          string
}

type RecvTransaction struct {
	num         int
	blocks      map[int]*RecvBlock
	lastTime    int64
	blockSize   int64
	Speed       float64
	completed   bool
	Addr        *net.UDPAddr
	Transaction []byte
}

type RecvBlock struct {
	transaction             []byte
	blockHash               []byte
	fileHash                []byte
	fileData                []byte
	num, id                 int32
	start, end, size, size1 int64
	time1                   int64
	addr                    *net.UDPAddr
}

type RecvHandleFunc func(service *RecvService, transaction *RecvTransaction)

func InitRecvService(key string, url string, fn RecvHandleFunc) (service *RecvService, err error) {
	service = new(RecvService)
	service.key = key
	service.fn = fn
	service.ch = make(chan *RecvBlock, 100)
	service.transactions = map[string]*RecvTransaction{}

	addr, err := net.ResolveUDPAddr("udp4", url)
	if err != nil {
		return nil, err
	}
	service.sock, err = net.ListenUDP("udp4", addr)
	if err != nil {
		return nil, err
	}
	go service.loop()

	return service, nil
}

func InitRecvTransaction(block *RecvBlock) *RecvTransaction {
	transaction := new(RecvTransaction)
	transaction.blocks = map[int]*RecvBlock{}
	transaction.lastTime = time.Now().UnixNano()
	transaction.blockSize = block.size1
	transaction.num = int(block.num)
	transaction.Addr = block.addr
	transaction.Transaction = block.transaction
	return transaction
}
func (service *RecvService) EnableFileStorage(dir string) {
	service.disk = true
	service.dir = dir
}
func (service *RecvService) processRecvBlock(block *RecvBlock) {
	stransaction := hex.EncodeToString(block.transaction)
	transaction, ok := service.transactions[stransaction]
	if !ok {
		fmt.Println("Creating transaction:", stransaction)
		transaction = InitRecvTransaction(block)
		service.transactions[stransaction] = transaction
	}
	if transaction.num != int(block.num) {
		// error
	}
	block.time1 = time.Now().UnixNano()
	fdtime := float64(block.time1 - transaction.lastTime)
	transaction.lastTime = block.time1
	speed := float64(len(block.fileData)) / fdtime * float64(time.Second)
	transaction.Speed = movingExpAvg(speed, transaction.Speed, fdtime, float64(time.Second))

	_, ok = transaction.blocks[int(block.id)]
	if ok {
		// dupe
		return
	}
	transaction.blocks[int(block.id)] = block
	// fmt.Printf("got %d %d %d\n%s\n", block.id, len(transaction.blocks), transaction.num, string(block.fileData))
	fmt.Printf("got %d %d %d %f\n", block.id, len(transaction.blocks), transaction.num, transaction.Speed)
	if len(transaction.blocks) == transaction.num {
		transaction.completed = true
		service.fn(service, transaction)

		// if service.disk {

		// 	os.MkdirAll(service.dir+"/"+stransaction, 0700)

		// 	f1, err := os.Create(service.dir + "/" + stransaction + "/file.out")
		// 	if err != nil {
		// 		// panic(err)
		// 		return
		// 	}
		// 	// defer f1.Close()

		// 	for i := 1; i <= transaction.num; i++ {
		// 		block1, ok := transaction.blocks[i]
		// 		if !ok {
		// 			// error
		// 			panic(errors.New(fmt.Sprintf("Not all blocks %d", i)))
		// 		}
		// 		f1.Write(block1.fileData)
		// 	}
		// 	f1.Close()
		// 	block1.fileData = nil
		// }

	}
}
func (service *RecvService) WriteTo(transaction *RecvTransaction, w io.Writer) error {
	if service.disk {
		for i := 1; i <= transaction.num; i++ {
			block1, ok := transaction.blocks[i]
			if !ok {
				// error
				return errors.New(fmt.Sprintf("Not all blocks %d", i))
			}
			// w.Write(block1.fileData)

			f1, err := os.Open(service.dir + "/" + hex.EncodeToString(block1.transaction) + "/" + fmt.Sprintf("%d.data", block1.id))
			if err != nil {
				// panic(err)
				return err
			}
			io.Copy(w, f1)
		}
	} else {
		for i := 1; i <= transaction.num; i++ {
			block1, ok := transaction.blocks[i]
			if !ok {
				// error
				return errors.New(fmt.Sprintf("Not all blocks %d", i))
			}
			w.Write(block1.fileData)
		}
	}

	return nil
}
func (service *RecvService) Stop() {
	service.sock.Close()
}
func (service *RecvService) Loop() error {

	for {
		// len, remote, err := sock.ReadFromUDP(buf[:])
		var buf [1 << 16]byte
		len, remote, err := service.sock.ReadFromUDP(buf[:])
		if err != nil {
			// 	(err)
			return err
		}
		fmt.Print("+")
		service.processPacket(remote, buf[:len])
	}
}
func (service *RecvService) loop() {

	ticker := time.Tick(100 * time.Millisecond)
	var stopTickerTill int64

	for {

		select {
		case blck, ok := <-service.ch:
			if ok {
				service.processRecvBlock(blck)
			}
		case <-ticker:
			time1 := time.Now().UnixNano()
			if stopTickerTill > time1 {
				continue
			}
			for _, transaction := range service.transactions {
				if transaction.completed {
					continue
				}

				fdtime := float64(time1 - transaction.lastTime)
				transaction.lastTime = time1
				transaction.Speed = movingExpAvg(0.0, transaction.Speed, fdtime, float64(time.Second))

				//
				// find last_block
				last_block := -1
				var block *RecvBlock
				for i, _block := range transaction.blocks {
					if last_block < i {
						last_block = i
						block = _block
					}
				}
				if last_block == -1 {
					continue
				}

				rangespeed := transaction.Speed

				if rangespeed < 100000 {
					rangespeed = 100000
				}
				if rangespeed > 10000000 {
					rangespeed = 10000000
				}

				// dtime  = Now - last_block.time
				dtime := time1 - block.time1
				// last_block + (dtime-100ms)*speed/blocksize
				shift := last_block + int((float64(dtime)-100.0*float64(time.Millisecond))*rangespeed/float64(transaction.blockSize)/float64(time.Second))
				// get first 100 un recieved blocks

				req := []int{}

				for i := 1; i <= transaction.num; i++ {
					if i > shift {
						break
					}
					_, ok := transaction.blocks[i]
					if !ok {
						req = append(req, i)
						if len(req) >= 100 {
							break
						}
					}
				}

				// fmt.Printf(":%d %d#", len(req), shift)
				fmt.Println("@", shift, last_block, dtime/int64(time.Millisecond), dtime, rangespeed, float64(transaction.blockSize))

				if len(req) > 0 {
					service.rerequestPackets(transaction, req)
					stopTickerTill = time1 + int64(time.Second)
				}
			}
		}

	}

}
func (service *RecvService) rerequestPackets(transaction *RecvTransaction, req []int) error {
	fmt.Printf("rerequestPackets %#v\n", req)
	r1 := make([]byte, 16)
	_, err := rand.Read(r1)
	if err != nil {
		// panic(err)
		return err
	}

	data := append(transaction.Transaction, r1...)

	buffer := new(bytes.Buffer)
	binary.Write(buffer, binary.LittleEndian, int32(1))
	binary.Write(buffer, binary.LittleEndian, int32(len(req)))
	for _, i := range req {
		binary.Write(buffer, binary.LittleEndian, int32(i))
	}

	block, err := aes.NewCipher([]byte(service.key))
	if err != nil {
		// panic(err)
		return err
	}

	data1 := buffer.Bytes()

	stream := cipher.NewCFBEncrypter(block, r1)
	stream.XORKeyStream(data1, data1)

	data = append(data, data1...)

	service.sock.WriteToUDP(data, transaction.Addr)
	return nil
}
func (service *RecvService) processPacket(addr *net.UDPAddr, buf []byte) error {
	blck := new(RecvBlock)
	blck.transaction = buf[:16]
	blck.addr = addr
	r1 := buf[16:32]
	data2 := buf[32:]

	block, err := aes.NewCipher([]byte(service.key))
	if err != nil {
		// panic(err)
		return err
	}

	stream := cipher.NewCFBDecrypter(block, r1)

	stream.XORKeyStream(data2, data2)

	// fileHash := data2[0:20]

	buffer := bytes.NewBuffer(data2[20:52])
	binary.Read(buffer, binary.LittleEndian, &blck.id)
	binary.Read(buffer, binary.LittleEndian, &blck.num)
	binary.Read(buffer, binary.LittleEndian, &blck.start)
	binary.Read(buffer, binary.LittleEndian, &blck.end)
	binary.Read(buffer, binary.LittleEndian, &blck.size)
	blck.blockHash = data2[52:72]
	blck.size1 = int64(len(data2[72:]))
	bufCopy := make([]byte, blck.size1)
	copy(bufCopy[:], data2[72:])
	blck.fileData = bufCopy
	blockHash := sha1.Sum(blck.fileData)
	verified := bytes.Equal(blck.blockHash, blockHash[:])

	fmt.Println("processPacker:", blck.id, hex.EncodeToString(r1))

	if verified {
		if service.disk {
			os.MkdirAll(service.dir+"/"+hex.EncodeToString(blck.transaction), 0700)
			f1, err := os.Create(service.dir + "/" + hex.EncodeToString(blck.transaction) + "/" + fmt.Sprintf("%d.data", blck.id))
			if err != nil {
				// panic(err)
				return err
			}
			defer f1.Close()
			f1.Write(blck.fileData)
			blck.fileData = nil
		}
		service.ch <- blck
	} else {
		fmt.Println("wrong hash %#v %#v", blck.blockHash, blockHash[:])
	}
	return nil
}
<commit_msg>StartTime in transaction<commit_after>package udpsender

import (
	"bytes"
	"crypto/aes"
	"crypto/cipher"
	"crypto/rand"
	"crypto/sha1"
	"encoding/binary"
	"encoding/hex"
	"errors"
	"fmt"
	"io"
	"net"
	"os"
	"time"
)

type RecvService struct {
	key          string
	ch           chan *RecvBlock
	transactions map[string]*RecvTransaction
	sock         *net.UDPConn
	fn           RecvHandleFunc
	disk         bool
	dir          string
}

type RecvTransaction struct {
	StartTime   int64
	num         int
	blocks      map[int]*RecvBlock
	lastTime    int64
	blockSize   int64
	Speed       float64
	completed   bool
	Addr        *net.UDPAddr
	Transaction []byte
}

type RecvBlock struct {
	transaction             []byte
	blockHash               []byte
	fileHash                []byte
	fileData                []byte
	num, id                 int32
	start, end, size, size1 int64
	time1                   int64
	addr                    *net.UDPAddr
}

type RecvHandleFunc func(service *RecvService, transaction *RecvTransaction)

func InitRecvService(key string, url string, fn RecvHandleFunc) (service *RecvService, err error) {
	service = new(RecvService)
	service.key = key
	service.fn = fn
	service.ch = make(chan *RecvBlock, 100)
	service.transactions = map[string]*RecvTransaction{}

	addr, err := net.ResolveUDPAddr("udp4", url)
	if err != nil {
		return nil, err
	}
	service.sock, err = net.ListenUDP("udp4", addr)
	if err != nil {
		return nil, err
	}
	go service.loop()

	return service, nil
}

func InitRecvTransaction(block *RecvBlock) *RecvTransaction {
	transaction := new(RecvTransaction)
	transaction.blocks = map[int]*RecvBlock{}
	transaction.lastTime = time.Now().UnixNano()
	transaction.StartTime = transaction.lastTime
	transaction.blockSize = block.size1
	transaction.num = int(block.num)
	transaction.Addr = block.addr
	transaction.Transaction = block.transaction
	return transaction
}
func (service *RecvService) EnableFileStorage(dir string) {
	service.disk = true
	service.dir = dir
}
func (service *RecvService) processRecvBlock(block *RecvBlock) {
	stransaction := hex.EncodeToString(block.transaction)
	transaction, ok := service.transactions[stransaction]
	if !ok {
		fmt.Println("Creating transaction:", stransaction)
		transaction = InitRecvTransaction(block)
		service.transactions[stransaction] = transaction
	}
	if transaction.num != int(block.num) {
		// error
	}
	block.time1 = time.Now().UnixNano()
	fdtime := float64(block.time1 - transaction.lastTime)
	transaction.lastTime = block.time1
	speed := float64(len(block.fileData)) / fdtime * float64(time.Second)
	transaction.Speed = movingExpAvg(speed, transaction.Speed, fdtime, float64(time.Second))

	_, ok = transaction.blocks[int(block.id)]
	if ok {
		// dupe
		return
	}
	transaction.blocks[int(block.id)] = block
	// fmt.Printf("got %d %d %d\n%s\n", block.id, len(transaction.blocks), transaction.num, string(block.fileData))
	fmt.Printf("got %d %d %d %f\n", block.id, len(transaction.blocks), transaction.num, transaction.Speed)
	if len(transaction.blocks) == transaction.num {
		transaction.completed = true
		service.fn(service, transaction)

		// if service.disk {

		// 	os.MkdirAll(service.dir+"/"+stransaction, 0700)

		// 	f1, err := os.Create(service.dir + "/" + stransaction + "/file.out")
		// 	if err != nil {
		// 		// panic(err)
		// 		return
		// 	}
		// 	// defer f1.Close()

		// 	for i := 1; i <= transaction.num; i++ {
		// 		block1, ok := transaction.blocks[i]
		// 		if !ok {
		// 			// error
		// 			panic(errors.New(fmt.Sprintf("Not all blocks %d", i)))
		// 		}
		// 		f1.Write(block1.fileData)
		// 	}
		// 	f1.Close()
		// 	block1.fileData = nil
		// }

	}
}
func (service *RecvService) WriteTo(transaction *RecvTransaction, w io.Writer) error {
	if service.disk {
		for i := 1; i <= transaction.num; i++ {
			block1, ok := transaction.blocks[i]
			if !ok {
				// error
				return errors.New(fmt.Sprintf("Not all blocks %d", i))
			}
			// w.Write(block1.fileData)

			f1, err := os.Open(service.dir + "/" + hex.EncodeToString(block1.transaction) + "/" + fmt.Sprintf("%d.data", block1.id))
			if err != nil {
				// panic(err)
				return err
			}
			io.Copy(w, f1)
		}
	} else {
		for i := 1; i <= transaction.num; i++ {
			block1, ok := transaction.blocks[i]
			if !ok {
				// error
				return errors.New(fmt.Sprintf("Not all blocks %d", i))
			}
			w.Write(block1.fileData)
		}
	}

	return nil
}
func (service *RecvService) Stop() {
	service.sock.Close()
}
func (service *RecvService) Loop() error {

	for {
		// len, remote, err := sock.ReadFromUDP(buf[:])
		var buf [1 << 16]byte
		len, remote, err := service.sock.ReadFromUDP(buf[:])
		if err != nil {
			// 	(err)
			return err
		}
		fmt.Print("+")
		service.processPacket(remote, buf[:len])
	}
}
func (service *RecvService) loop() {

	ticker := time.Tick(100 * time.Millisecond)
	var stopTickerTill int64

	for {

		select {
		case blck, ok := <-service.ch:
			if ok {
				service.processRecvBlock(blck)
			}
		case <-ticker:
			time1 := time.Now().UnixNano()
			if stopTickerTill > time1 {
				continue
			}
			for _, transaction := range service.transactions {
				if transaction.completed {
					continue
				}

				fdtime := float64(time1 - transaction.lastTime)
				transaction.lastTime = time1
				transaction.Speed = movingExpAvg(0.0, transaction.Speed, fdtime, float64(time.Second))

				//
				// find last_block
				last_block := -1
				var block *RecvBlock
				for i, _block := range transaction.blocks {
					if last_block < i {
						last_block = i
						block = _block
					}
				}
				if last_block == -1 {
					continue
				}

				rangespeed := transaction.Speed

				if rangespeed < 100000 {
					rangespeed = 100000
				}
				if rangespeed > 10000000 {
					rangespeed = 10000000
				}

				// dtime  = Now - last_block.time
				dtime := time1 - block.time1
				// last_block + (dtime-100ms)*speed/blocksize
				shift := last_block + int((float64(dtime)-100.0*float64(time.Millisecond))*rangespeed/float64(transaction.blockSize)/float64(time.Second))
				// get first 100 un recieved blocks

				req := []int{}

				for i := 1; i <= transaction.num; i++ {
					if i > shift {
						break
					}
					_, ok := transaction.blocks[i]
					if !ok {
						req = append(req, i)
						if len(req) >= 100 {
							break
						}
					}
				}

				// fmt.Printf(":%d %d#", len(req), shift)
				fmt.Println("@", shift, last_block, dtime/int64(time.Millisecond), dtime, rangespeed, float64(transaction.blockSize))

				if len(req) > 0 {
					service.rerequestPackets(transaction, req)
					stopTickerTill = time1 + int64(time.Second)
				}
			}
		}

	}

}
func (service *RecvService) rerequestPackets(transaction *RecvTransaction, req []int) error {
	fmt.Printf("rerequestPackets %#v\n", req)
	r1 := make([]byte, 16)
	_, err := rand.Read(r1)
	if err != nil {
		// panic(err)
		return err
	}

	data := append(transaction.Transaction, r1...)

	buffer := new(bytes.Buffer)
	binary.Write(buffer, binary.LittleEndian, int32(1))
	binary.Write(buffer, binary.LittleEndian, int32(len(req)))
	for _, i := range req {
		binary.Write(buffer, binary.LittleEndian, int32(i))
	}

	block, err := aes.NewCipher([]byte(service.key))
	if err != nil {
		// panic(err)
		return err
	}

	data1 := buffer.Bytes()

	stream := cipher.NewCFBEncrypter(block, r1)
	stream.XORKeyStream(data1, data1)

	data = append(data, data1...)

	service.sock.WriteToUDP(data, transaction.Addr)
	return nil
}
func (service *RecvService) processPacket(addr *net.UDPAddr, buf []byte) error {
	blck := new(RecvBlock)
	blck.transaction = buf[:16]
	blck.addr = addr
	r1 := buf[16:32]
	data2 := buf[32:]

	block, err := aes.NewCipher([]byte(service.key))
	if err != nil {
		// panic(err)
		return err
	}

	stream := cipher.NewCFBDecrypter(block, r1)

	stream.XORKeyStream(data2, data2)

	// fileHash := data2[0:20]

	buffer := bytes.NewBuffer(data2[20:52])
	binary.Read(buffer, binary.LittleEndian, &blck.id)
	binary.Read(buffer, binary.LittleEndian, &blck.num)
	binary.Read(buffer, binary.LittleEndian, &blck.start)
	binary.Read(buffer, binary.LittleEndian, &blck.end)
	binary.Read(buffer, binary.LittleEndian, &blck.size)
	blck.blockHash = data2[52:72]
	blck.size1 = int64(len(data2[72:]))
	bufCopy := make([]byte, blck.size1)
	copy(bufCopy[:], data2[72:])
	blck.fileData = bufCopy
	blockHash := sha1.Sum(blck.fileData)
	verified := bytes.Equal(blck.blockHash, blockHash[:])

	fmt.Println("processPacker:", blck.id, hex.EncodeToString(r1))

	if verified {
		if service.disk {
			os.MkdirAll(service.dir+"/"+hex.EncodeToString(blck.transaction), 0700)
			f1, err := os.Create(service.dir + "/" + hex.EncodeToString(blck.transaction) + "/" + fmt.Sprintf("%d.data", blck.id))
			if err != nil {
				// panic(err)
				return err
			}
			defer f1.Close()
			f1.Write(blck.fileData)
			blck.fileData = nil
		}
		service.ch <- blck
	} else {
		fmt.Println("wrong hash %#v %#v", blck.blockHash, blockHash[:])
	}
	return nil
}
<|endoftext|>


<commit_before>package circuitbreaker

import (
	"context"
	"errors"
	"sync/atomic"
	"time"

	"github.com/morikuni/guard"
)

func New(window Window, threashold float64, backoff guard.Backoff) guard.Guard {
	window.Reset()
	cb := &circuitBreaker{
		window,
		threashold,
		close,
		backoff.Reset(),
	}
	return cb
}

const (
	close int32 = iota
	halfopen
	open
)

var ErrCircuitBreakerOpen = errors.New("circuit breaker open")

type circuitBreaker struct {
	window     Window
	threashold float64
	state      int32
	backoff    guard.Backoff
}

func (cb *circuitBreaker) Call(ctx context.Context, f func(context.Context) error) error {
	state, available := cb.currentState()
	if !available {
		return ErrCircuitBreakerOpen
	}

	err := f(ctx)
	switch err {
	case nil:
		cb.succeed(state)
	case context.Canceled:
		// this is normal, so do nothing.
	default:
		// context.DeadlimeExceeded and other errors are regarded as a failure.
		cb.fail(state)
	}
	return err
}

func (cb *circuitBreaker) succeed(state int32) {
	cb.window.PutSuccess()
	switch state {
	case close:
	case halfopen:
		cb.close(state)
	default:
		panic("never come here")
	}
}

func (cb *circuitBreaker) fail(state int32) {
	cb.window.PutFailure()
	switch state {
	case close:
		if cb.window.FailureRate() >= cb.threashold {
			cb.open(state)
		}
	case halfopen:
		cb.open(state)
	default:
		panic("never come here")
	}
}

func (cb *circuitBreaker) currentState() (state int32, available bool) {
	switch atomic.LoadInt32(&cb.state) {
	case close:
		return close, true
	case halfopen:
		return halfopen, true
	case open:
		return open, false
	}
	panic("never come here")
}

func (cb *circuitBreaker) change(from, to int32) bool {
	return atomic.CompareAndSwapInt32(&cb.state, from, to)
}

func (cb *circuitBreaker) open(state int32) {
	if cb.change(state, open) {
		time.AfterFunc(cb.backoff.NextInterval(), func() {
			cb.change(open, halfopen)
		})
	}
}

func (cb *circuitBreaker) close(state int32) {
	if cb.change(state, close) {
		cb.backoff = cb.backoff.Reset()
		cb.window.Reset()
	}
}
<commit_msg>Add Subscribe to CircuitBreaker<commit_after>package circuitbreaker

import (
	"context"
	"errors"
	"fmt"
	"sync"
	"sync/atomic"
	"time"

	"github.com/morikuni/guard"
)

type CircuitBreaker interface {
	guard.Guard

	Subscribe() <-chan StateChange
}

func New(window Window, threashold float64, backoff guard.Backoff) CircuitBreaker {
	window.Reset()
	cb := &circuitBreaker{
		window,
		threashold,
		close,
		backoff.Reset(),

		[]chan<- StateChange{},
		sync.RWMutex{},
	}
	return cb
}

const (
	close int32 = iota
	halfopen
	open
)

var ErrCircuitBreakerOpen = errors.New("circuit breaker open")

type circuitBreaker struct {
	window     Window
	threashold float64
	state      int32
	backoff    guard.Backoff

	subscribers []chan<- StateChange
	mu          sync.RWMutex
}

func (cb *circuitBreaker) Call(ctx context.Context, f func(context.Context) error) error {
	state, available := cb.currentState()
	if !available {
		return ErrCircuitBreakerOpen
	}

	err := f(ctx)
	switch err {
	case nil:
		cb.succeed(state)
	case context.Canceled:
		// this is normal, so do nothing.
	default:
		// context.DeadlimeExceeded and other errors are regarded as a failure.
		cb.fail(state)
	}
	return err
}

func (cb *circuitBreaker) succeed(state int32) {
	cb.window.PutSuccess()
	switch state {
	case close:
	case halfopen:
		cb.close()
	default:
		panic("never come here")
	}
}

func (cb *circuitBreaker) fail(state int32) {
	cb.window.PutFailure()
	switch state {
	case close:
		if cb.window.FailureRate() >= cb.threashold {
			cb.open(state)
		}
	case halfopen:
		cb.open(state)
	default:
		panic("never come here")
	}
}

func (cb *circuitBreaker) currentState() (state int32, available bool) {
	switch atomic.LoadInt32(&cb.state) {
	case close:
		return close, true
	case halfopen:
		return halfopen, true
	case open:
		return open, false
	}
	panic("never come here")
}

func (cb *circuitBreaker) change(from, to int32, sc StateChange) bool {
	ok := atomic.CompareAndSwapInt32(&cb.state, from, to)
	if ok {
		cb.notify(sc)
	}
	return ok
}

func (cb *circuitBreaker) open(state int32) {
	sc := CloseToOpen
	if state == halfopen {
		sc = HalfOpenToOpen
	}
	if cb.change(state, open, sc) {
		time.AfterFunc(cb.backoff.NextInterval(), func() {
			cb.change(open, halfopen, OpenToHalfOpen)
		})
	}
}

func (cb *circuitBreaker) close() {
	if cb.change(halfopen, close, HalfOpenToClose) {
		cb.backoff = cb.backoff.Reset()
		cb.window.Reset()
	}
}

func (cb *circuitBreaker) Subscribe() <-chan StateChange {
	c := make(chan StateChange, 100)

	cb.mu.Lock()
	defer cb.mu.Unlock()
	cb.subscribers = append(cb.subscribers, c)
	return c
}

func (cb *circuitBreaker) notify(sc StateChange) {
	cb.mu.RLock()
	defer cb.mu.RUnlock()
	for _, subscriber := range cb.subscribers {
		subscriber <- sc
	}
}

type StateChange int

const (
	CloseToOpen StateChange = iota
	HalfOpenToOpen
	HalfOpenToClose
	OpenToHalfOpen
)

func (sc StateChange) String() string {
	switch sc {
	case CloseToOpen:
		return "close to open"
	case HalfOpenToOpen:
		return "half-open to open"
	case HalfOpenToClose:
		return "half-open to close"
	case OpenToHalfOpen:
		return "open to half-open"
	default:
		panic(fmt.Sprint("unknown state change", sc))
	}
}
<|endoftext|>


<commit_before>// Common contains structs, data, and interfaces that
// needs to be referenced by many packages but doesn't
// necessarily have an obvious place it belongs
package common

import (
	"time"
)

const (
	// How many bytes of entropy must be produced each entropy cycle
	EntropyVolume int = 32

	// How big a single slice of data is for a host, in bytes
	MinSliceSize int = 512
	MaxSliceSize int = 1048576 // 1 MB

	// How many hosts participate in each quorum
	// This number is chosen to minimize the probability of a single quorum
	// 	becoming more than 80% compromised by an attacker controlling 1/2 of
	// 	the network.
	QuorumSize int = 128

	// How long a single step in the consensus algorithm takes
	StepDuration time.Duration = 15 * time.Second
)

type Entropy [EntropyVolume]byte

// Messages are for sending things over the network.
// Each message has a single destination, and it is
// the job of the network package to interpret the
// destinations.
type Message struct {
	Destination []string // may not remain a string
	Payload     string
}

type MessageHandler interface {
	HandleMessage(m Message)
}
<commit_msg>add Address struct and MessageSender interface<commit_after>// Common contains structs, data, and interfaces that
// need to be referenced by other packages
package common

import (
	"time"
)

const (
	// How many bytes of entropy must be produced each entropy cycle
	EntropyVolume int = 32

	// How big a single slice of data is for a host, in bytes
	MinSliceSize int = 512
	MaxSliceSize int = 1048576 // 1 MB

	// How many hosts participate in each quorum
	// This number is chosen to minimize the probability of a single quorum
	// 	becoming more than 80% compromised by an attacker controlling 1/2 of
	// 	the network.
	QuorumSize int = 128

	// How long a single step in the consensus algorithm takes
	StepDuration time.Duration = 15 * time.Second
)

type Entropy [EntropyVolume]byte

// An Address is used to uniquely identify a message recipient.
type Address struct {
	Identifier int
	Host       string
	Port       int
}

// Messages are for sending things over the network.
// Each message has a single destination, and it is
// the job of the network package to interpret the
// destinations.
type Message struct {
	Destination Address
	Payload     []byte
}

type MessageHandler interface {
	HandleMessage(payload []byte)
}

type MessageSender interface {
	Address() Address
	SendMessage(m *Message) error
}
<|endoftext|>


<commit_before>package riak

type NodeManager interface {
	ExecuteOnNode(nodes []*Node, command Command, previous *Node) (executed bool, err error)
}

type defaultNodeManager struct {
	nodeIndex uint16
}

func (nm *defaultNodeManager) ExecuteOnNode(nodes []*Node, command Command, previous *Node) (executed bool, err error) {
	executed = false
	startingIndex := nm.nodeIndex

	for {
		node := nodes[nm.nodeIndex]

		nm.nodeIndex++

		if int(nm.nodeIndex) == len(nodes) {
			nm.nodeIndex = 0
		}

		// don't try the same node twice in a row if we have multiple nodes
		if len(nodes) > 1 && previous != nil && previous == node {
			continue
		}

		if executed, err = node.Execute(command); err != nil {
			executed = false
			logErr(err)
		} else {
			executed = true
			break
		}

		if nm.nodeIndex == startingIndex {
			break
		}
	}

	return
}
<commit_msg>Add docblocks.<commit_after>package riak

// NodeManager enforces the structure needed to if going to implement your own NodeManager
type NodeManager interface {
	ExecuteOnNode(nodes []*Node, command Command, previous *Node) (executed bool, err error)
}

type defaultNodeManager struct {
	nodeIndex uint16
}

// ExecuteOnNode selects a Node from the pool and executes the provided Command on that Node. The
// defaultNodeManager uses a simple round robin approach to distributing load
func (nm *defaultNodeManager) ExecuteOnNode(nodes []*Node, command Command, previous *Node) (executed bool, err error) {
	executed = false
	startingIndex := nm.nodeIndex

	for {
		node := nodes[nm.nodeIndex]

		nm.nodeIndex++

		if int(nm.nodeIndex) == len(nodes) {
			nm.nodeIndex = 0
		}

		// don't try the same node twice in a row if we have multiple nodes
		if len(nodes) > 1 && previous != nil && previous == node {
			continue
		}

		if executed, err = node.Execute(command); err != nil {
			executed = false
			logErr(err)
		} else {
			executed = true
			break
		}

		if nm.nodeIndex == startingIndex {
			break
		}
	}

	return
}
<|endoftext|>


<commit_before>/*
Copyright 2015 Nodetemple <hostmaster@nodetemple.com>

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

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

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

package main

import (
	"os"
	"fmt"
	"strings"
	"text/tabwriter"

	"github.com/nodetemple/nodetemple/common"
	flag "github.com/ogier/pflag"
)

const (
	OK = iota
	ERROR_API
	ERROR_USAGE
	ERROR_NO_COMMAND

	cliName        = "nodectl"
	cliDescription = "CLI for an orchestration of CoreOS and Kubernetes cluster"
	cliVersion     = common.Version
)

type StringFlag struct {
	value    *string
	required bool
}

type Command struct {
	Name        string
	Usage       string
	Summary     string
	Description string
	Flags       flag.FlagSet
	Run         handlerFunc
	Subcommands []*Command
}

type handlerFunc func([]string) int

var (
	out           *tabwriter.Writer
	globalFlagSet *flag.FlagSet
	commands      []*Command

	globalFlags struct {
		Providers     string
		Debug         bool
		Version       bool
		Help          bool
	}
)

func init() {
	out = new(tabwriter.Writer)
	out.Init(os.Stdout, 0, 8, 1, '\t', 0)

	globalFlagSet = flag.NewFlagSet(cliName, flag.ContinueOnError)
	globalFlagSet.SetOutput(os.DevNull)
	globalFlagSet.Usage = func() {}

	globalFlagSet.StringVarP(&globalFlags.Providers, "providers", "p", "", "A comma-separated list of IaaS providers ("+strings.Join(common.AvailableProviders, ",")+") and API keys, format: 'provider:api-key,...'")

	globalFlagSet.BoolVar(&globalFlags.Debug, "debug", false, "Output debugging info to stderr")
	globalFlagSet.BoolVarP(&globalFlags.Version, "version", "v", false, "Print version information and exit")
	globalFlagSet.BoolVarP(&globalFlags.Help, "help", "h", false, "Print usage information and exit")

	commands = []*Command{
		cmdDemo,
		cmdHelp,
	}
}

func main() {
	if err := globalFlagSet.Parse(os.Args[1:]); err != nil {
		stderr("Error: %s", err)
		stderr("Run '%s help' for usage information", cliName)
		os.Exit(ERROR_USAGE)
    }
	var args = globalFlagSet.Args()
	getFlagsFromEnv(cliName, globalFlagSet)

	if globalFlags.Version {
		stdout("%s version %s", cliName, cliVersion)
		os.Exit(OK)
	}

	if globalFlags.Help {
		printGlobalUsage()
		os.Exit(OK)
	}

	if len(args) < 1 {
		args = append(args, "help")
	}

	cmd, name := findCommand("", args, commands)

	if cmd == nil {
		stderr("Error: unknown command '%s'", name)
		stderr("Run '%s help' for usage information", cliName)
		os.Exit(ERROR_NO_COMMAND)
	}

	if cmd.Run == nil {
		printCommandUsage(cmd)
		os.Exit(ERROR_USAGE)
	} else {
		exit := handle(cmd.Run)(&cmd.Flags)
		if exit == ERROR_USAGE {
			printCommandUsage(cmd)
		}
		os.Exit(exit)
	}
}

func handle(fn handlerFunc) func(f *flag.FlagSet) int {
	return func(f *flag.FlagSet) (exit int) {
		exit = fn(f.Args())
		return
	}
}

func findCommand(search string, args []string, commands []*Command) (cmd *Command, name string) {
	if len(args) < 1 {
		return
	}
	if search == "" {
		search = args[0]
	} else {
		search = fmt.Sprintf("%s %s", search, args[0])
	}
	name = search
	for _, c := range commands {
		if c.Name == search {
			cmd = c
			if errHelp := c.Flags.Parse(args[1:]); errHelp != nil {
				printCommandUsage(cmd)
				os.Exit(ERROR_USAGE)
			}
			if len(cmd.Subcommands) != 0 {
				subArgs := cmd.Flags.Args()
				var subCmd *Command
				subCmd, name = findCommand(search, subArgs, cmd.Subcommands)
				if subCmd != nil {
					cmd = subCmd
				}
			}
			break
		}
	}
	return
}
<commit_msg>ioutil.Discard<commit_after>/*
Copyright 2015 Nodetemple <hostmaster@nodetemple.com>

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

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

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

package main

import (
	"os"
	"io/ioutil"
	"fmt"
	"strings"
	"text/tabwriter"

	"github.com/nodetemple/nodetemple/common"
	flag "github.com/ogier/pflag"
)

const (
	OK = iota
	ERROR_API
	ERROR_USAGE
	ERROR_NO_COMMAND

	cliName        = "nodectl"
	cliDescription = "CLI for an orchestration of CoreOS and Kubernetes cluster"
	cliVersion     = common.Version
)

type StringFlag struct {
	value    *string
	required bool
}

type Command struct {
	Name        string
	Usage       string
	Summary     string
	Description string
	Flags       flag.FlagSet
	Run         handlerFunc
	Subcommands []*Command
}

type handlerFunc func([]string) int

var (
	out           *tabwriter.Writer
	globalFlagSet *flag.FlagSet
	commands      []*Command

	globalFlags struct {
		Providers     string
		Debug         bool
		Version       bool
		Help          bool
	}
)

func init() {
	out = new(tabwriter.Writer)
	out.Init(os.Stdout, 0, 8, 1, '\t', 0)

	globalFlagSet = flag.NewFlagSet(cliName, flag.ContinueOnError)
	globalFlagSet.SetOutput(ioutil.Discard)
	globalFlagSet.Usage = func() {}

	globalFlagSet.StringVarP(&globalFlags.Providers, "providers", "p", "", "A comma-separated list of IaaS providers ("+strings.Join(common.AvailableProviders, ",")+") and API keys, format: 'provider:api-key,...'")

	globalFlagSet.BoolVar(&globalFlags.Debug, "debug", false, "Output debugging info to stderr")
	globalFlagSet.BoolVarP(&globalFlags.Version, "version", "v", false, "Print version information and exit")
	globalFlagSet.BoolVarP(&globalFlags.Help, "help", "h", false, "Print usage information and exit")

	commands = []*Command{
		cmdDemo,
		cmdHelp,
	}
}

func main() {
	if err := globalFlagSet.Parse(os.Args[1:]); err != nil {
		stderr("Error: %s", err)
		stderr("Run '%s help' for usage information", cliName)
		os.Exit(ERROR_USAGE)
    }
	var args = globalFlagSet.Args()
	getFlagsFromEnv(cliName, globalFlagSet)

	if globalFlags.Version {
		stdout("%s version %s", cliName, cliVersion)
		os.Exit(OK)
	}

	if globalFlags.Help {
		printGlobalUsage()
		os.Exit(OK)
	}

	if len(args) < 1 {
		args = append(args, "help")
	}

	cmd, name := findCommand("", args, commands)

	if cmd == nil {
		stderr("Error: unknown command '%s'", name)
		stderr("Run '%s help' for usage information", cliName)
		os.Exit(ERROR_NO_COMMAND)
	}

	if cmd.Run == nil {
		printCommandUsage(cmd)
		os.Exit(ERROR_USAGE)
	} else {
		exit := handle(cmd.Run)(&cmd.Flags)
		if exit == ERROR_USAGE {
			printCommandUsage(cmd)
		}
		os.Exit(exit)
	}
}

func handle(fn handlerFunc) func(f *flag.FlagSet) int {
	return func(f *flag.FlagSet) (exit int) {
		exit = fn(f.Args())
		return
	}
}

func findCommand(search string, args []string, commands []*Command) (cmd *Command, name string) {
	if len(args) < 1 {
		return
	}
	if search == "" {
		search = args[0]
	} else {
		search = fmt.Sprintf("%s %s", search, args[0])
	}
	name = search
	for _, c := range commands {
		if c.Name == search {
			cmd = c
			if errHelp := c.Flags.Parse(args[1:]); errHelp != nil {
				printCommandUsage(cmd)
				os.Exit(ERROR_USAGE)
			}
			if len(cmd.Subcommands) != 0 {
				subArgs := cmd.Flags.Args()
				var subCmd *Command
				subCmd, name = findCommand(search, subArgs, cmd.Subcommands)
				if subCmd != nil {
					cmd = subCmd
				}
			}
			break
		}
	}
	return
}
<|endoftext|>


<commit_before>package notify

import (
	"github.com/godbus/dbus"
	"log"
	"errors"
)

// This package is a wrapper around godbus for notification handling
// See: https://developer.gnome.org/notification-spec/
//
// Each notification displayed is allocated a unique ID by the server. (see Notify)
// This is unique within the dbus session. While the notification server is running,
// the ID will not be recycled unless the capacity of a uint32 is exceeded.
// This can be used to hide the notification before the expiration timeout is reached. (see CloseNotification)
// It can also be used to atomically replace the notification with another (Notification.ReplaceID).
// This allows you to (for instance) modify the contents of a notification while it's on-screen.
const (
	objectPath                 = "/org/freedesktop/Notifications" // the DBUS object path
	dbusNotificationsInterface = "org.freedesktop.Notifications"  // DBUS Interface
	getCapabilities            = "org.freedesktop.Notifications.GetCapabilities"
	closeNotification          = "org.freedesktop.Notifications.CloseNotification"
	notify                     = "org.freedesktop.Notifications.Notify"
	getServerInformation       = "org.freedesktop.Notifications.GetServerInformation"
)

func NewNotifier(conn *dbus.Conn) Notificator {
	return &Notifier{
		conn: conn,
	}
}

type Notifier struct {
	conn *dbus.Conn
}

// GetCapabilities gets the capabilities of the notification server.
// This call takes no parameters.
// It returns an array of strings. Each string describes an optional capability implemented by the server.
//
// Implements dbus call:
//
// STRING_ARRAY org.freedesktop.Notifications.GetCapabilities ()
//
// See also: https://developer.gnome.org/notification-spec/
func (self *Notifier) GetCapabilities() ([]string, error) {
	obj := self.conn.Object(dbusNotificationsInterface, objectPath)
	call := obj.Call(getCapabilities, 0)
	if call.Err != nil {
		log.Printf("error calling GetCapabilities: %v", call.Err)
		return []string{}, call.Err
	}
	var ret []string
	err := call.Store(&ret)
	if err != nil {
		log.Printf("error getting capabilities ret value: %v", err)
		return ret, err
	}
	return ret, nil
}

type AskCapabilities interface {
	GetCapabilities() ([]string, error)
}

// org.freedesktop.Notifications.CloseNotification
// void org.freedesktop.Notifications.CloseNotification ( id )
//														 UINT32 id;
//
// Causes a notification to be forcefully closed and removed from the user's view. It can be used, for example, in the event that what the notification pertains to is no longer relevant, or to cancel a notification with no expiration time.
// The NotificationClosed signal is emitted by this method.
// If the notification no longer exists, an empty D-BUS Error message is sent back.
func (self *Notifier) CloseNotification(id int) (bool, error) {
	obj := self.conn.Object(dbusNotificationsInterface, objectPath)
	call := obj.Call(closeNotification, 0, uint32(id))
	if call.Err != nil {
		return false, call.Err
	}
	return true, nil
}

// Closer is an interface for implementing CloseNotification call
type Closer interface {
	CloseNotification(id int) (bool, error)
}

// ServerInformation is a holder for information returned by
// GetServerInformation call
type ServerInformation struct {
	Name        string
	Vendor      string
	Version     string
	SpecVersion string
}

// GetServerInformation
// This message returns the information on the server. Specifically, the server name, vendor, and version number.
//
// org.freedesktop.Notifications.GetServerInformation
//
//  GetServerInformation Return Values
//
//		Name		 Type	  Description
//		name		 STRING	  The product name of the server.
//		vendor		 STRING	  The vendor name. For example, "KDE," "GNOME," "freedesktop.org," or "Microsoft."
//		version		 STRING	  The server's version number.
//		spec_version STRING	  The specification version the server is compliant with.
func (self *Notifier) GetServerInformation() (ServerInformation, error) {
	obj := self.conn.Object(dbusNotificationsInterface, objectPath)
	if obj == nil {
		return ServerInformation{}, errors.New("error creating dbus call object")
	}
	call := obj.Call(getServerInformation, 0)
	if call.Err != nil {
		log.Printf("Error calling %v: %v", getServerInformation, call.Err)
		return ServerInformation{}, call.Err
	}

	ret := ServerInformation{}
	err := call.Store(&ret.Name, &ret.Vendor, &ret.Version, &ret.SpecVersion)
	if err != nil {
		log.Printf("error reading %v return values: %v", getServerInformation, err)
		return ret, err
	}
	return ret, nil
}

// ServerInformator is an interface for implementing GetServerInformation
type ServerInformator interface {
	GetServerInformation() (ServerInformation, error)
}

// Sends a notification to the notification server.
// Implements dbus call:
//
// UINT32 org.freedesktop.Notifications.Notify ( STRING app_name,
//												 UINT32 replaces_id,
//												 STRING app_icon,
//												 STRING summary,
//												 STRING body,
//												 ARRAY  actions,
//												 DICT   hints,
//												 INT32  expire_timeout);
//
//		Table 6. Notify Parameters
//
//		 Name	    	Type	Description
//		 app_name		STRING	The optional name of the application sending the notification. Can be blank.
//		 replaces_id	UINT32	The optional notification ID that this notification replaces. The server must atomically (ie with no flicker or other visual cues) replace the given notification with this one. This allows clients to effectively modify the notification while it's active. A value of value of 0 means that this notification won't replace any existing notifications.
//		 app_icon		STRING	The optional program icon of the calling application. See Icons and Images. Can be an empty string, indicating no icon.
//		 summary		STRING	The summary text briefly describing the notification.
//		 body			STRING	The optional detailed body text. Can be empty.
//		 actions		ARRAY	Actions are sent over as a list of pairs. Each even element in the list (starting at index 0) represents the identifier for the action. Each odd element in the list is the localized string that will be displayed to the user.
//		 hints	        DICT	Optional hints that can be passed to the server from the client program. Although clients and servers should never assume each other supports any specific hints, they can be used to pass along information, such as the process PID or window ID, that the server may be able to make use of. See Hints. Can be empty.
//       expire_timeout INT32   The timeout time in milliseconds since the display of the notification at which the notification should automatically close.
//								If -1, the notification's expiration time is dependent on the notification server's settings, and may vary for the type of notification. If 0, never expire.
//
//If replaces_id is 0, the return value is a UINT32 that represent the notification. It is unique, and will not be reused unless a MAXINT number of notifications have been generated. An acceptable implementation may just use an incrementing counter for the ID. The returned ID is always greater than zero. Servers must make sure not to return zero as an ID.
//If replaces_id is not 0, the returned value is the same value as replaces_id.
func (self *Notifier) SendNotification(n Notification) (int, error) {
	return SendNotification(self.conn, n)
}

func SendNotification(conn *dbus.Conn, n Notification) (int, error) {
	obj := conn.Object(dbusNotificationsInterface, objectPath)
	call := obj.Call(notify, 0,
		n.AppName,
		n.ReplacesID,
		n.AppIcon,
		n.Summary,
		n.Body,
		n.Actions,
		n.Hints,
		n.ExpireTimeout)
	if call.Err != nil {
		return 0, call.Err
	}
	var ret uint32
	err := call.Store(&ret)
	if err != nil {
		log.Printf("error getting uint32 ret value: %v", err)
		return int(ret), err
	}
	return int(ret), nil
}
// Notifyer is an interface for implementing SendNotification
type Notifyer interface {
	SendNotification(n Notification) (int, error)
}

// Notification holds all information needed for creating a notification
type Notification struct {
	AppName       string
	ReplacesID    uint32
	AppIcon       string // see icons here: http://standards.freedesktop.org/icon-naming-spec/icon-naming-spec-latest.html
	Summary       string
	Body          string
	Actions       []string
	Hints         map[string]dbus.Variant
	ExpireTimeout int32 // millisecond to show notification
}

// Notificator is just a holder for all the small interfaces here.
type Notificator interface {
	Notifyer
	AskCapabilities
	ServerInformator
	Closer
}
<commit_msg>int --> uint32 to keep it consistent with notification.ReplaceID<commit_after>package notify

import (
	"github.com/godbus/dbus"
	"log"
	"errors"
)

// This package is a wrapper around godbus for notification handling
// See: https://developer.gnome.org/notification-spec/
//
// Each notification displayed is allocated a unique ID by the server. (see Notify)
// This is unique within the dbus session. While the notification server is running,
// the ID will not be recycled unless the capacity of a uint32 is exceeded.
// This can be used to hide the notification before the expiration timeout is reached. (see CloseNotification)
// It can also be used to atomically replace the notification with another (Notification.ReplaceID).
// This allows you to (for instance) modify the contents of a notification while it's on-screen.
const (
	objectPath                 = "/org/freedesktop/Notifications" // the DBUS object path
	dbusNotificationsInterface = "org.freedesktop.Notifications"  // DBUS Interface
	getCapabilities            = "org.freedesktop.Notifications.GetCapabilities"
	closeNotification          = "org.freedesktop.Notifications.CloseNotification"
	notify                     = "org.freedesktop.Notifications.Notify"
	getServerInformation       = "org.freedesktop.Notifications.GetServerInformation"
)

func NewNotifier(conn *dbus.Conn) Notificator {
	return &Notifier{
		conn: conn,
	}
}

type Notifier struct {
	conn *dbus.Conn
}

// GetCapabilities gets the capabilities of the notification server.
// This call takes no parameters.
// It returns an array of strings. Each string describes an optional capability implemented by the server.
//
// Implements dbus call:
//
// STRING_ARRAY org.freedesktop.Notifications.GetCapabilities ()
//
// See also: https://developer.gnome.org/notification-spec/
func (self *Notifier) GetCapabilities() ([]string, error) {
	obj := self.conn.Object(dbusNotificationsInterface, objectPath)
	call := obj.Call(getCapabilities, 0)
	if call.Err != nil {
		log.Printf("error calling GetCapabilities: %v", call.Err)
		return []string{}, call.Err
	}
	var ret []string
	err := call.Store(&ret)
	if err != nil {
		log.Printf("error getting capabilities ret value: %v", err)
		return ret, err
	}
	return ret, nil
}

type AskCapabilities interface {
	GetCapabilities() ([]string, error)
}

// org.freedesktop.Notifications.CloseNotification
// void org.freedesktop.Notifications.CloseNotification ( id )
//														 UINT32 id;
//
// Causes a notification to be forcefully closed and removed from the user's view. It can be used, for example, in the event that what the notification pertains to is no longer relevant, or to cancel a notification with no expiration time.
// The NotificationClosed signal is emitted by this method.
// If the notification no longer exists, an empty D-BUS Error message is sent back.
func (self *Notifier) CloseNotification(id int) (bool, error) {
	obj := self.conn.Object(dbusNotificationsInterface, objectPath)
	call := obj.Call(closeNotification, 0, uint32(id))
	if call.Err != nil {
		return false, call.Err
	}
	return true, nil
}

// Closer is an interface for implementing CloseNotification call
type Closer interface {
	CloseNotification(id int) (bool, error)
}

// ServerInformation is a holder for information returned by
// GetServerInformation call
type ServerInformation struct {
	Name        string
	Vendor      string
	Version     string
	SpecVersion string
}

// GetServerInformation
// This message returns the information on the server. Specifically, the server name, vendor, and version number.
//
// org.freedesktop.Notifications.GetServerInformation
//
//  GetServerInformation Return Values
//
//		Name		 Type	  Description
//		name		 STRING	  The product name of the server.
//		vendor		 STRING	  The vendor name. For example, "KDE," "GNOME," "freedesktop.org," or "Microsoft."
//		version		 STRING	  The server's version number.
//		spec_version STRING	  The specification version the server is compliant with.
func (self *Notifier) GetServerInformation() (ServerInformation, error) {
	obj := self.conn.Object(dbusNotificationsInterface, objectPath)
	if obj == nil {
		return ServerInformation{}, errors.New("error creating dbus call object")
	}
	call := obj.Call(getServerInformation, 0)
	if call.Err != nil {
		log.Printf("Error calling %v: %v", getServerInformation, call.Err)
		return ServerInformation{}, call.Err
	}

	ret := ServerInformation{}
	err := call.Store(&ret.Name, &ret.Vendor, &ret.Version, &ret.SpecVersion)
	if err != nil {
		log.Printf("error reading %v return values: %v", getServerInformation, err)
		return ret, err
	}
	return ret, nil
}

// ServerInformator is an interface for implementing GetServerInformation
type ServerInformator interface {
	GetServerInformation() (ServerInformation, error)
}

// Sends a notification to the notification server.
// Implements dbus call:
//
// UINT32 org.freedesktop.Notifications.Notify ( STRING app_name,
//												 UINT32 replaces_id,
//												 STRING app_icon,
//												 STRING summary,
//												 STRING body,
//												 ARRAY  actions,
//												 DICT   hints,
//												 INT32  expire_timeout);
//
//		Table 6. Notify Parameters
//
//		 Name	    	Type	Description
//		 app_name		STRING	The optional name of the application sending the notification. Can be blank.
//		 replaces_id	UINT32	The optional notification ID that this notification replaces. The server must atomically (ie with no flicker or other visual cues) replace the given notification with this one. This allows clients to effectively modify the notification while it's active. A value of value of 0 means that this notification won't replace any existing notifications.
//		 app_icon		STRING	The optional program icon of the calling application. See Icons and Images. Can be an empty string, indicating no icon.
//		 summary		STRING	The summary text briefly describing the notification.
//		 body			STRING	The optional detailed body text. Can be empty.
//		 actions		ARRAY	Actions are sent over as a list of pairs. Each even element in the list (starting at index 0) represents the identifier for the action. Each odd element in the list is the localized string that will be displayed to the user.
//		 hints	        DICT	Optional hints that can be passed to the server from the client program. Although clients and servers should never assume each other supports any specific hints, they can be used to pass along information, such as the process PID or window ID, that the server may be able to make use of. See Hints. Can be empty.
//       expire_timeout INT32   The timeout time in milliseconds since the display of the notification at which the notification should automatically close.
//								If -1, the notification's expiration time is dependent on the notification server's settings, and may vary for the type of notification. If 0, never expire.
//
//If replaces_id is 0, the return value is a UINT32 that represent the notification. It is unique, and will not be reused unless a MAXINT number of notifications have been generated. An acceptable implementation may just use an incrementing counter for the ID. The returned ID is always greater than zero. Servers must make sure not to return zero as an ID.
//If replaces_id is not 0, the returned value is the same value as replaces_id.
func (self *Notifier) SendNotification(n Notification) (uint32, error) {
	return SendNotification(self.conn, n)
}

func SendNotification(conn *dbus.Conn, n Notification) (uint32, error) {
	obj := conn.Object(dbusNotificationsInterface, objectPath)
	call := obj.Call(notify, 0,
		n.AppName,
		n.ReplacesID,
		n.AppIcon,
		n.Summary,
		n.Body,
		n.Actions,
		n.Hints,
		n.ExpireTimeout)
	if call.Err != nil {
		return 0, call.Err
	}
	var ret uint32
	err := call.Store(&ret)
	if err != nil {
		log.Printf("error getting uint32 ret value: %v", err)
		return ret, err
	}
	return ret, nil
}
// Notifyer is an interface for implementing SendNotification
type Notifyer interface {
	SendNotification(n Notification) (uint32, error)
}

// Notification holds all information needed for creating a notification
type Notification struct {
	AppName       string
	ReplacesID    uint32
	AppIcon       string // see icons here: http://standards.freedesktop.org/icon-naming-spec/icon-naming-spec-latest.html
	Summary       string
	Body          string
	Actions       []string
	Hints         map[string]dbus.Variant
	ExpireTimeout int32 // millisecond to show notification
}

// Notificator is just a holder for all the small interfaces here.
type Notificator interface {
	Notifyer
	AskCapabilities
	ServerInformator
	Closer
}
<|endoftext|>


<commit_before>package main

import (
    "database/sql"
    "os"
    "log"

    _ "github.com/lib/pq"
)

var currentDB *sql.DB

func init() {
    currentDB = connect()
}

func connect() *sql.DB {
    dbUrl := os.Getenv("DATABASE_URL")
    database, err := sql.Open("postgres", dbUrl)
    if err != nil {
        log.Fatalf("[x] Could not open the connection to the database. Reason: %s", err.Error())
    }
    return database
}

func Name() string {
    tx, _ := currentDB.Begin()

    stmt, _ := tx.Prepare("SELECT name FROM bots WHERE id = '$1'")
    var name string
    stmt.QueryRow(1).Scan(&name)
    stmt.Close()

    tx.Commit()

    return name
}<commit_msg>Adjust statement<commit_after>package main

import (
    "database/sql"
    "os"
    "log"

    _ "github.com/lib/pq"
)

var currentDB *sql.DB

func init() {
    currentDB = connect()
}

func connect() *sql.DB {
    dbUrl := os.Getenv("DATABASE_URL")
    database, err := sql.Open("postgres", dbUrl)
    if err != nil {
        log.Fatalf("[x] Could not open the connection to the database. Reason: %s", err.Error())
    }
    return database
}

func Name() string {
    tx, _ := currentDB.Begin()

    stmt, _ := tx.Prepare("SELECT name FROM bots WHERE id = '$1'")
    var name string
    stmt.QueryRow("1").Scan(&name)
    stmt.Close()

    tx.Commit()

    return name
}<|endoftext|>


<commit_before>/*
Copyright 2012 Rackspace

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

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

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

package rackspace

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io"
	"io/ioutil"
	"mime"
	"net/http"
	"net/http/httputil"
)

type RestError struct {
	ErrorString string
}

func (e *RestError) Error() string {
	return e.ErrorString
}

type RestRequest struct {
	Method              string
	Path                string
	Header              http.Header
	Body                RequestBody
	ExpectedStatusCodes []int
}

type RequestBody interface {
	ContentType() (string, error)
	ContentLength() (int64, error)
	Body() (io.Reader, error)
}

type JSONRequestBody struct {
	Object interface{}
	data   []byte
}

func (b *JSONRequestBody) marshal() error {
	if b.data != nil {
		return nil
	}

	data, err := json.Marshal(b.Object)
	if err == nil {
		b.data = data
	}

	return err
}

func (b *JSONRequestBody) ContentType() (string, error) {
	return "application/json", nil
}

func (b *JSONRequestBody) ContentLength() (int64, error) {
	err := b.marshal()
	if err != nil {
		return 0, err
	}

	return int64(len(b.data)), nil
}

func (b *JSONRequestBody) Body() (io.Reader, error) {
	err := b.marshal()
	if err != nil {
		return nil, err
	}

	return bytes.NewReader(b.data), nil
}

type RestResponse struct {
	*http.Response
}

func (r *RestResponse) DeserializeBody(target interface{}) error {
	defer r.Body.Close()
	data, err := ioutil.ReadAll(r.Body)

	if err != nil {
		return err
	}

	contentType, _, err := mime.ParseMediaType(r.Header.Get("Content-Type"))

	if err != nil {
		return err
	}

	switch contentType {
	case "application/json":
		return json.Unmarshal(data, target)
	}

	return fmt.Errorf("unsupported Content-Type: %s", r.Header.Get("Content-Type"))
}

type RequestMiddleware interface {
	HandleRequest(*RestRequest) (*RestRequest, error)
}

type RestClient struct {
	BaseUrl            string
	RequestMiddlewares []RequestMiddleware
	Debug              bool
	client             *http.Client
}

func MakeRestClient(url string) *RestClient {
	return &RestClient{
		BaseUrl:            url,
		RequestMiddlewares: []RequestMiddleware{},
		Debug:              false,
		client:             &http.Client{},
	}
}

func (c *RestClient) PerformRequest(restReq *RestRequest) (*RestResponse, error) {
	var err error
	var body io.Reader

	// Request Middlewares shouldn't have to worry about a nil Header
	if restReq.Header == nil {
		restReq.Header = http.Header{}
	}

	for _, middleware := range c.RequestMiddlewares {
		restReq, err = middleware.HandleRequest(restReq)

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

	if restReq.Body != nil {
		body, err = restReq.Body.Body()
		if err != nil {
			return nil, err
		}
	}

	req, err := http.NewRequest(restReq.Method, c.BaseUrl+restReq.Path, body)
	req.Header = restReq.Header

	if len(req.Header.Get("Accept")) == 0 {
		req.Header.Set("Accept", "application/json")
	}

	if restReq.Body != nil {
		if err != nil {
			return nil, err
		}

		contentLength, err := restReq.Body.ContentLength()
		if err != nil {
			return nil, err
		}

		req.ContentLength = contentLength

		contentType, err := restReq.Body.ContentType()
		if err != nil {
			return nil, err
		}

		req.Header.Set("Content-Type", contentType)
	}

	if c.Debug {
		dump, err := httputil.DumpRequestOut(req, true)
		if err != nil {
			fmt.Println(err.Error())
		}
		fmt.Println("")
		fmt.Println(string(dump))
	}

	resp, err := c.client.Do(req)
	if err != nil {
		return nil, err
	}

	if c.Debug {
		dump, err := httputil.DumpResponse(resp, true)
		if err != nil {
			fmt.Println(err.Error())
		}
		fmt.Println("")
		fmt.Println(string(dump))
	}

	if restReq.ExpectedStatusCodes != nil {
		for _, value := range restReq.ExpectedStatusCodes {
			if value == resp.StatusCode {
				return &RestResponse{resp}, nil
			}
		}

		return nil, fmt.Errorf("unexpected HTTP status code: %d", resp.StatusCode)
	}

	return &RestResponse{resp}, nil
}

func (c *RestClient) SetDebug(debug bool) {
	c.Debug = debug
}
<commit_msg>Missed a package name<commit_after>/*
Copyright 2012 Rackspace

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

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

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

package gorax

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io"
	"io/ioutil"
	"mime"
	"net/http"
	"net/http/httputil"
)

type RestError struct {
	ErrorString string
}

func (e *RestError) Error() string {
	return e.ErrorString
}

type RestRequest struct {
	Method              string
	Path                string
	Header              http.Header
	Body                RequestBody
	ExpectedStatusCodes []int
}

type RequestBody interface {
	ContentType() (string, error)
	ContentLength() (int64, error)
	Body() (io.Reader, error)
}

type JSONRequestBody struct {
	Object interface{}
	data   []byte
}

func (b *JSONRequestBody) marshal() error {
	if b.data != nil {
		return nil
	}

	data, err := json.Marshal(b.Object)
	if err == nil {
		b.data = data
	}

	return err
}

func (b *JSONRequestBody) ContentType() (string, error) {
	return "application/json", nil
}

func (b *JSONRequestBody) ContentLength() (int64, error) {
	err := b.marshal()
	if err != nil {
		return 0, err
	}

	return int64(len(b.data)), nil
}

func (b *JSONRequestBody) Body() (io.Reader, error) {
	err := b.marshal()
	if err != nil {
		return nil, err
	}

	return bytes.NewReader(b.data), nil
}

type RestResponse struct {
	*http.Response
}

func (r *RestResponse) DeserializeBody(target interface{}) error {
	defer r.Body.Close()
	data, err := ioutil.ReadAll(r.Body)

	if err != nil {
		return err
	}

	contentType, _, err := mime.ParseMediaType(r.Header.Get("Content-Type"))

	if err != nil {
		return err
	}

	switch contentType {
	case "application/json":
		return json.Unmarshal(data, target)
	}

	return fmt.Errorf("unsupported Content-Type: %s", r.Header.Get("Content-Type"))
}

type RequestMiddleware interface {
	HandleRequest(*RestRequest) (*RestRequest, error)
}

type RestClient struct {
	BaseUrl            string
	RequestMiddlewares []RequestMiddleware
	Debug              bool
	client             *http.Client
}

func MakeRestClient(url string) *RestClient {
	return &RestClient{
		BaseUrl:            url,
		RequestMiddlewares: []RequestMiddleware{},
		Debug:              false,
		client:             &http.Client{},
	}
}

func (c *RestClient) PerformRequest(restReq *RestRequest) (*RestResponse, error) {
	var err error
	var body io.Reader

	// Request Middlewares shouldn't have to worry about a nil Header
	if restReq.Header == nil {
		restReq.Header = http.Header{}
	}

	for _, middleware := range c.RequestMiddlewares {
		restReq, err = middleware.HandleRequest(restReq)

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

	if restReq.Body != nil {
		body, err = restReq.Body.Body()
		if err != nil {
			return nil, err
		}
	}

	req, err := http.NewRequest(restReq.Method, c.BaseUrl+restReq.Path, body)
	req.Header = restReq.Header

	if len(req.Header.Get("Accept")) == 0 {
		req.Header.Set("Accept", "application/json")
	}

	if restReq.Body != nil {
		if err != nil {
			return nil, err
		}

		contentLength, err := restReq.Body.ContentLength()
		if err != nil {
			return nil, err
		}

		req.ContentLength = contentLength

		contentType, err := restReq.Body.ContentType()
		if err != nil {
			return nil, err
		}

		req.Header.Set("Content-Type", contentType)
	}

	if c.Debug {
		dump, err := httputil.DumpRequestOut(req, true)
		if err != nil {
			fmt.Println(err.Error())
		}
		fmt.Println("")
		fmt.Println(string(dump))
	}

	resp, err := c.client.Do(req)
	if err != nil {
		return nil, err
	}

	if c.Debug {
		dump, err := httputil.DumpResponse(resp, true)
		if err != nil {
			fmt.Println(err.Error())
		}
		fmt.Println("")
		fmt.Println(string(dump))
	}

	if restReq.ExpectedStatusCodes != nil {
		for _, value := range restReq.ExpectedStatusCodes {
			if value == resp.StatusCode {
				return &RestResponse{resp}, nil
			}
		}

		return nil, fmt.Errorf("unexpected HTTP status code: %d", resp.StatusCode)
	}

	return &RestResponse{resp}, nil
}

func (c *RestClient) SetDebug(debug bool) {
	c.Debug = debug
}
<|endoftext|>


<commit_before>package main

import "fmt"

func main() {
	fmt.Println("Hello gorest!")
}<commit_msg>Test httprouter.<commit_after>package main

import (
	"fmt"
	"log"
	"net/http"

	"github.com/julienschmidt/httprouter"
)

// Index controller
func Index(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
	fmt.Fprint(w, "Welcome!\n")
}

// Hello controller
func Hello(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
	fmt.Fprintf(w, "hello, %s!\n", ps.ByName("name"))
}

func main() {
	router := httprouter.New()
	router.GET("/", Index)
	router.GET("/hello/:name", Hello)
	log.Fatal(http.ListenAndServe(":8080", router))
}
<|endoftext|>


<commit_before>package networking_test

import (
	"fmt"
	"net"
	"net/http"
	"os/exec"
	"strconv"
	"strings"

	"github.com/cloudfoundry-incubator/garden"
	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
	"github.com/onsi/gomega/gbytes"
	"github.com/pivotal-golang/localip"
)

var _ = Describe("IP settings", func() {
	var (
		container1 garden.Container
		container2 garden.Container

		containerNetwork1 string
		containerNetwork2 string

		containerInterface string

		gardenParms []string
	)

	BeforeEach(func() {
		container1 = nil
		container2 = nil
		containerNetwork1 = ""
		containerNetwork2 = ""

		gardenParms = []string{}
	})

	JustBeforeEach(func() {
		client = startGarden(gardenParms...)

		var err error
		container1, err = client.Create(garden.ContainerSpec{Network: containerNetwork1})
		Expect(err).ToNot(HaveOccurred())

		if len(containerNetwork2) > 0 {
			container2, err = client.Create(garden.ContainerSpec{Network: containerNetwork2})
			Expect(err).ToNot(HaveOccurred())
		}

		containerInterface = "w" + strconv.Itoa(GinkgoParallelNode()) + container1.Handle() + "-1"
	})

	AfterEach(func() {
		if container1 != nil {
			err := client.Destroy(container1.Handle())
			Expect(err).ToNot(HaveOccurred())
		}

		if container2 != nil {
			err := client.Destroy(container2.Handle())
			Expect(err).ToNot(HaveOccurred())
		}
	})

	Context("when the Network parameter is a subnet address", func() {
		BeforeEach(func() {
			containerNetwork1 = fmt.Sprintf("10.%d.0.0/24", GinkgoParallelNode())
		})

		Describe("container's network interface", func() {
			It("has the correct IP address", func() {
				stdout := gbytes.NewBuffer()
				stderr := gbytes.NewBuffer()

				process, err := container1.Run(garden.ProcessSpec{
					User: "vcap",
					Path: "/sbin/ifconfig",
					Args: []string{containerInterface},
				}, garden.ProcessIO{
					Stdout: stdout,
					Stderr: stderr,
				})
				Expect(err).ToNot(HaveOccurred())
				rc, err := process.Wait()
				Expect(err).ToNot(HaveOccurred())
				Expect(rc).To(Equal(0))

				Expect(stdout.Contents()).To(ContainSubstring(fmt.Sprintf(" inet addr:10.%d.0.1 ", GinkgoParallelNode())))
			})
		})
	})

	Context("when the Network parameter is not a subnet address", func() {
		BeforeEach(func() {
			containerNetwork1 = fmt.Sprintf("10.%d.0.2/24", GinkgoParallelNode())
		})

		Describe("container's network interface", func() {
			It("has the specified IP address", func() {
				stdout := gbytes.NewBuffer()
				stderr := gbytes.NewBuffer()

				process, err := container1.Run(garden.ProcessSpec{
					User: "vcap",
					Path: "/sbin/ifconfig",
					Args: []string{containerIfName(container1)},
				}, garden.ProcessIO{
					Stdout: stdout,
					Stderr: stderr,
				})
				Expect(err).ToNot(HaveOccurred())
				rc, err := process.Wait()
				Expect(err).ToNot(HaveOccurred())
				Expect(rc).To(Equal(0))

				Expect(stdout.Contents()).To(ContainSubstring(fmt.Sprintf(" inet addr:10.%d.0.2 ", GinkgoParallelNode())))
			})
		})
	})

	Describe("the container's network", func() {
		BeforeEach(func() {
			containerNetwork1 = fmt.Sprintf("10.%d.0.0/24", GinkgoParallelNode())
		})

		It("is reachable from the host", func() {
			info1, ierr := container1.Info()
			Expect(ierr).ToNot(HaveOccurred())

			out, err := exec.Command("/bin/ping", "-c 2", info1.ContainerIP).Output()
			Expect(out).To(ContainSubstring(" 0% packet loss"))
			Expect(err).ToNot(HaveOccurred())
		})
	})

	Describe("another container on the same subnet", func() {
		BeforeEach(func() {
			containerNetwork1 = fmt.Sprintf("10.%d.0.0/24", GinkgoParallelNode())
			containerNetwork2 = containerNetwork1
		})

		Context("when the first container is deleted", func() {
			JustBeforeEach(func() {
				Expect(client.Destroy(container1.Handle())).To(Succeed())
				container1 = nil
			})

			Context("the second container", func() {
				It("can still reach external networks", func() {
					Expect(checkInternet(container2)).To(Succeed())
				})

				It("can still be reached from the host", func() {
					info2, ierr := container2.Info()
					Expect(ierr).ToNot(HaveOccurred())

					out, err := exec.Command("/bin/ping", "-c 2", info2.ContainerIP).Output()
					Expect(out).To(ContainSubstring(" 0% packet loss"))
					Expect(err).ToNot(HaveOccurred())
				})
			})

			Context("a newly created container in the same subnet", func() {
				var (
					container3 garden.Container
				)

				JustBeforeEach(func() {
					var err error
					container3, err = client.Create(garden.ContainerSpec{Network: containerNetwork1})
					Expect(err).ToNot(HaveOccurred())
				})

				AfterEach(func() {
					err := client.Destroy(container3.Handle())
					Expect(err).ToNot(HaveOccurred())
				})

				It("can reach the second container", func() {
					info2, err := container2.Info()
					Expect(err).ToNot(HaveOccurred())

					listener, err := container2.Run(garden.ProcessSpec{
						User: "vcap",
						Path: "sh",
						Args: []string{"-c", "echo hi | nc -l -p 8080"},
					}, garden.ProcessIO{})
					Expect(err).ToNot(HaveOccurred())

					Expect(checkConnection(container3, info2.ContainerIP, 8080)).To(Succeed())

					Expect(listener.Wait()).To(Equal(0))
				})

				It("can be reached from the host", func() {
					info3, ierr := container3.Info()
					Expect(ierr).ToNot(HaveOccurred())

					out, err := exec.Command("/bin/ping", "-c 2", info3.ContainerIP).Output()
					Expect(out).To(ContainSubstring(" 0% packet loss"))
					Expect(err).ToNot(HaveOccurred())
				})
			})
		})
	})

	Describe("host's network", func() {
		Context("when host access is explicitly allowed", func() {
			BeforeEach(func() {
				containerNetwork1 = fmt.Sprintf("10.%d.0.8/30", GinkgoParallelNode())
				gardenParms = []string{"-allowHostAccess=true"}
			})

			It("is reachable from inside the container", func() {
				checkHostAccess(container1, true)
			})
		})

		Context("when host access is explicitly disallowed", func() {
			BeforeEach(func() {
				containerNetwork1 = fmt.Sprintf("10.%d.0.8/30", GinkgoParallelNode())
				gardenParms = []string{"-allowHostAccess=false"}
			})

			It("is not reachable from inside the container", func() {
				checkHostAccess(container1, false)
			})
		})

		Context("when host access is implicitly disallowed", func() {
			BeforeEach(func() {
				containerNetwork1 = fmt.Sprintf("10.%d.0.8/30", GinkgoParallelNode())
			})

			It("is not reachable from inside the container", func() {
				checkHostAccess(container1, false)
			})
		})
	})

	Describe("the container's external ip", func() {
		It("is the external IP of its host", func() {
			info1, err := container1.Info()
			Expect(err).ToNot(HaveOccurred())

			localIP, err := localip.LocalIP()
			Expect(err).ToNot(HaveOccurred())

			Expect(localIP).To(Equal(info1.ExternalIP))
		})
	})
})

func checkHostAccess(container garden.Container, permitted bool) {
	info1, ierr := container.Info()
	Expect(ierr).ToNot(HaveOccurred())

	listener, err := net.Listen("tcp", fmt.Sprintf("%s:0", info1.HostIP))
	Expect(err).ToNot(HaveOccurred())
	defer listener.Close()

	mux := http.NewServeMux()
	mux.HandleFunc("/test", func(w http.ResponseWriter, r *http.Request) {
		fmt.Fprintf(w, "Hello")
	})

	go (&http.Server{Handler: mux}).Serve(listener)

	port, err := strconv.Atoi(strings.Split(listener.Addr().String(), ":")[1])
	Expect(err).ToNot(HaveOccurred())
	err = checkConnection(container, info1.HostIP, port)

	if permitted {
		Expect(err).ToNot(HaveOccurred())
	} else {
		Expect(err).To(HaveOccurred())
	}
}
<commit_msg>Fix test flake<commit_after>package networking_test

import (
	"fmt"
	"net"
	"net/http"
	"os/exec"
	"strconv"
	"strings"

	"github.com/cloudfoundry-incubator/garden"
	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
	"github.com/onsi/gomega/gbytes"
	"github.com/pivotal-golang/localip"
)

var _ = Describe("IP settings", func() {
	var (
		container1 garden.Container
		container2 garden.Container

		containerNetwork1 string
		containerNetwork2 string

		containerInterface string

		gardenParms []string
	)

	BeforeEach(func() {
		container1 = nil
		container2 = nil
		containerNetwork1 = ""
		containerNetwork2 = ""

		gardenParms = []string{}
	})

	JustBeforeEach(func() {
		client = startGarden(gardenParms...)

		var err error
		container1, err = client.Create(garden.ContainerSpec{Network: containerNetwork1})
		Expect(err).ToNot(HaveOccurred())

		if len(containerNetwork2) > 0 {
			container2, err = client.Create(garden.ContainerSpec{Network: containerNetwork2})
			Expect(err).ToNot(HaveOccurred())
		}

		containerInterface = "w" + strconv.Itoa(GinkgoParallelNode()) + container1.Handle() + "-1"
	})

	AfterEach(func() {
		if container1 != nil {
			err := client.Destroy(container1.Handle())
			Expect(err).ToNot(HaveOccurred())
		}

		if container2 != nil {
			err := client.Destroy(container2.Handle())
			Expect(err).ToNot(HaveOccurred())
		}
	})

	Context("when the Network parameter is a subnet address", func() {
		BeforeEach(func() {
			containerNetwork1 = fmt.Sprintf("10.%d.0.0/24", GinkgoParallelNode())
		})

		Describe("container's network interface", func() {
			It("has the correct IP address", func() {
				stdout := gbytes.NewBuffer()
				stderr := gbytes.NewBuffer()

				process, err := container1.Run(garden.ProcessSpec{
					User: "vcap",
					Path: "/sbin/ifconfig",
					Args: []string{containerInterface},
				}, garden.ProcessIO{
					Stdout: stdout,
					Stderr: stderr,
				})
				Expect(err).ToNot(HaveOccurred())
				rc, err := process.Wait()
				Expect(err).ToNot(HaveOccurred())
				Expect(rc).To(Equal(0))

				Expect(stdout.Contents()).To(ContainSubstring(fmt.Sprintf(" inet addr:10.%d.0.1 ", GinkgoParallelNode())))
			})
		})
	})

	Context("when the Network parameter is not a subnet address", func() {
		BeforeEach(func() {
			containerNetwork1 = fmt.Sprintf("10.%d.0.2/24", GinkgoParallelNode())
		})

		Describe("container's network interface", func() {
			It("has the specified IP address", func() {
				stdout := gbytes.NewBuffer()
				stderr := gbytes.NewBuffer()

				process, err := container1.Run(garden.ProcessSpec{
					User: "vcap",
					Path: "/sbin/ifconfig",
					Args: []string{containerIfName(container1)},
				}, garden.ProcessIO{
					Stdout: stdout,
					Stderr: stderr,
				})
				Expect(err).ToNot(HaveOccurred())
				rc, err := process.Wait()
				Expect(err).ToNot(HaveOccurred())
				Expect(rc).To(Equal(0))

				Expect(stdout.Contents()).To(ContainSubstring(fmt.Sprintf(" inet addr:10.%d.0.2 ", GinkgoParallelNode())))
			})
		})
	})

	Describe("the container's network", func() {
		BeforeEach(func() {
			containerNetwork1 = fmt.Sprintf("10.%d.0.0/24", GinkgoParallelNode())
		})

		It("is reachable from the host", func() {
			info1, ierr := container1.Info()
			Expect(ierr).ToNot(HaveOccurred())

			out, err := exec.Command("/bin/ping", "-c 2", info1.ContainerIP).Output()
			Expect(out).To(ContainSubstring(" 0% packet loss"))
			Expect(err).ToNot(HaveOccurred())
		})
	})

	Describe("another container on the same subnet", func() {
		BeforeEach(func() {
			containerNetwork1 = fmt.Sprintf("10.%d.0.0/24", GinkgoParallelNode())
			containerNetwork2 = containerNetwork1
		})

		Context("when the first container is deleted", func() {
			JustBeforeEach(func() {
				Expect(client.Destroy(container1.Handle())).To(Succeed())
				container1 = nil
			})

			Context("the second container", func() {
				It("can still reach external networks", func() {
					Expect(checkInternet(container2)).To(Succeed())
				})

				It("can still be reached from the host", func() {
					info2, ierr := container2.Info()
					Expect(ierr).ToNot(HaveOccurred())

					out, err := exec.Command("/bin/ping", "-c 2", info2.ContainerIP).Output()
					Expect(out).To(ContainSubstring(" 0% packet loss"))
					Expect(err).ToNot(HaveOccurred())
				})
			})

			Context("a newly created container in the same subnet", func() {
				var (
					container3 garden.Container
				)

				JustBeforeEach(func() {
					var err error
					container3, err = client.Create(garden.ContainerSpec{Network: containerNetwork1})
					Expect(err).ToNot(HaveOccurred())
				})

				AfterEach(func() {
					err := client.Destroy(container3.Handle())
					Expect(err).ToNot(HaveOccurred())
				})

				It("can reach the second container", func() {
					info2, err := container2.Info()
					Expect(err).ToNot(HaveOccurred())

					listener, err := container2.Run(garden.ProcessSpec{
						User: "vcap",
						Path: "sh",
						Args: []string{"-c", "echo hi | nc -l -p 8080"},
					}, garden.ProcessIO{})
					Expect(err).ToNot(HaveOccurred())

					Eventually(func() error { return checkConnection(container3, info2.ContainerIP, 8080) }).Should(Succeed())

					Expect(listener.Wait()).To(Equal(0))
				})

				It("can be reached from the host", func() {
					info3, ierr := container3.Info()
					Expect(ierr).ToNot(HaveOccurred())

					out, err := exec.Command("/bin/ping", "-c 2", info3.ContainerIP).Output()
					Expect(out).To(ContainSubstring(" 0% packet loss"))
					Expect(err).ToNot(HaveOccurred())
				})
			})
		})
	})

	Describe("host's network", func() {
		Context("when host access is explicitly allowed", func() {
			BeforeEach(func() {
				containerNetwork1 = fmt.Sprintf("10.%d.0.8/30", GinkgoParallelNode())
				gardenParms = []string{"-allowHostAccess=true"}
			})

			It("is reachable from inside the container", func() {
				checkHostAccess(container1, true)
			})
		})

		Context("when host access is explicitly disallowed", func() {
			BeforeEach(func() {
				containerNetwork1 = fmt.Sprintf("10.%d.0.8/30", GinkgoParallelNode())
				gardenParms = []string{"-allowHostAccess=false"}
			})

			It("is not reachable from inside the container", func() {
				checkHostAccess(container1, false)
			})
		})

		Context("when host access is implicitly disallowed", func() {
			BeforeEach(func() {
				containerNetwork1 = fmt.Sprintf("10.%d.0.8/30", GinkgoParallelNode())
			})

			It("is not reachable from inside the container", func() {
				checkHostAccess(container1, false)
			})
		})
	})

	Describe("the container's external ip", func() {
		It("is the external IP of its host", func() {
			info1, err := container1.Info()
			Expect(err).ToNot(HaveOccurred())

			localIP, err := localip.LocalIP()
			Expect(err).ToNot(HaveOccurred())

			Expect(localIP).To(Equal(info1.ExternalIP))
		})
	})
})

func checkHostAccess(container garden.Container, permitted bool) {
	info1, ierr := container.Info()
	Expect(ierr).ToNot(HaveOccurred())

	listener, err := net.Listen("tcp", fmt.Sprintf("%s:0", info1.HostIP))
	Expect(err).ToNot(HaveOccurred())
	defer listener.Close()

	mux := http.NewServeMux()
	mux.HandleFunc("/test", func(w http.ResponseWriter, r *http.Request) {
		fmt.Fprintf(w, "Hello")
	})

	go (&http.Server{Handler: mux}).Serve(listener)

	port, err := strconv.Atoi(strings.Split(listener.Addr().String(), ":")[1])
	Expect(err).ToNot(HaveOccurred())
	err = checkConnection(container, info1.HostIP, port)

	if permitted {
		Expect(err).ToNot(HaveOccurred())
	} else {
		Expect(err).To(HaveOccurred())
	}
}
<|endoftext|>


<commit_before>// Copyright 2017 The Ebiten Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package audio

import (
	"fmt"
	"io"
)

// InfiniteLoop represents a loop which never ends.
type InfiniteLoop struct {
	stream ReadSeekCloser
	size   int64
}

// NewInfiniteLoop creates a new infinite loop stream with a stream and size in bytes.
func NewInfiniteLoop(stream ReadSeekCloser, size int64) *InfiniteLoop {
	return &InfiniteLoop{
		stream: stream,
		size:   size,
	}
}

// Read is implementation of ReadSeekCloser's Read.
func (i *InfiniteLoop) Read(b []byte) (int, error) {
	n, err := i.stream.Read(b)
	if err == io.EOF {
		if _, err := i.Seek(0, io.SeekStart); err != nil {
			return 0, err
		}
		err = nil
	}
	return n, err
}

// Seek is implementation of ReadSeekCloser's Seek.
func (i *InfiniteLoop) Seek(offset int64, whence int) (int64, error) {
	next := int64(0)
	switch whence {
	case io.SeekStart:
		next = offset
	case io.SeekCurrent:
		current, err := i.stream.Seek(0, io.SeekCurrent)
		if err != nil {
			return 0, err
		}
		next = current + offset
	case io.SeekEnd:
		return 0, fmt.Errorf("audio: whence must be 0 or 1 for InfiniteLoop")
	}
	next %= i.size
	pos, err := i.stream.Seek(next, io.SeekStart)
	if err != nil {
		return 0, err
	}
	return pos, nil
}

// Close is implementation of ReadSeekCloser's Close.
func (l *InfiniteLoop) Close() error {
	return l.stream.Close()
}
<commit_msg>audio: Better error message<commit_after>// Copyright 2017 The Ebiten Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package audio

import (
	"fmt"
	"io"
)

// InfiniteLoop represents a loop which never ends.
type InfiniteLoop struct {
	stream ReadSeekCloser
	size   int64
}

// NewInfiniteLoop creates a new infinite loop stream with a stream and size in bytes.
func NewInfiniteLoop(stream ReadSeekCloser, size int64) *InfiniteLoop {
	return &InfiniteLoop{
		stream: stream,
		size:   size,
	}
}

// Read is implementation of ReadSeekCloser's Read.
func (i *InfiniteLoop) Read(b []byte) (int, error) {
	n, err := i.stream.Read(b)
	if err == io.EOF {
		if _, err := i.Seek(0, io.SeekStart); err != nil {
			return 0, err
		}
		err = nil
	}
	return n, err
}

// Seek is implementation of ReadSeekCloser's Seek.
func (i *InfiniteLoop) Seek(offset int64, whence int) (int64, error) {
	next := int64(0)
	switch whence {
	case io.SeekStart:
		next = offset
	case io.SeekCurrent:
		current, err := i.stream.Seek(0, io.SeekCurrent)
		if err != nil {
			return 0, err
		}
		next = current + offset
	case io.SeekEnd:
		return 0, fmt.Errorf("audio: whence must be io.SeekStart or io.SeekCurrent for InfiniteLoop")
	}
	next %= i.size
	pos, err := i.stream.Seek(next, io.SeekStart)
	if err != nil {
		return 0, err
	}
	return pos, nil
}

// Close is implementation of ReadSeekCloser's Close.
func (l *InfiniteLoop) Close() error {
	return l.stream.Close()
}
<|endoftext|>


<commit_before>// Copyright 2016 The fleet Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package rpc

import (
	"io/ioutil"
	"os"
	"testing"

	etcd "github.com/coreos/etcd/client"
	"golang.org/x/net/context"

	"github.com/coreos/fleet/job"
	"github.com/coreos/fleet/machine"
	"github.com/coreos/fleet/pkg/lease"
	"github.com/coreos/fleet/registry"
	"github.com/coreos/fleet/systemd"
	"github.com/coreos/fleet/unit"
)

type action struct {
	key string
	val string
	rec bool
}

type testEtcdKeysAPI struct {
	etcd.KeysAPI
	gets    []action
	sets    []action
	deletes []action
	res     []*etcd.Response // errors returned from subsequent calls to etcd
	ri      int
	err     []error // results returned from subsequent calls to etcd
	ei      int
}

func (t *testEtcdKeysAPI) Set(_ context.Context, key string, value string, _ *etcd.SetOptions) (*etcd.Response, error) {
	t.sets = append(t.sets, action{key: key, val: value})
	return t.next()
}

func (t *testEtcdKeysAPI) Get(_ context.Context, key string, opts *etcd.GetOptions) (*etcd.Response, error) {
	act := action{key: key}
	if opts != nil {
		act.rec = opts.Recursive
	}
	t.gets = append(t.gets, act)
	return t.next()
}

func (t *testEtcdKeysAPI) Delete(_ context.Context, key string, opts *etcd.DeleteOptions) (*etcd.Response, error) {
	act := action{key: key}
	if opts != nil {
		act.rec = opts.Recursive
	}
	t.deletes = append(t.deletes, act)
	return t.next()
}

func (t *testEtcdKeysAPI) next() (r *etcd.Response, e error) {
	if t.ri < len(t.res) {
		r = t.res[t.ri]
		t.ri++
	}
	if t.ei < len(t.err) {
		e = t.err[t.ei]
		t.ei++
	}
	return r, e
}

func TestRegistryMuxUnitManagement(t *testing.T) {
	uDir, err := ioutil.TempDir("", "fleet-")
	if err != nil {
		t.Fatalf("failed creating tempdir: %v", err)
	}
	defer os.RemoveAll(uDir)

	state := &machine.MachineState{
		ID:       "id",
		PublicIP: "127.0.0.1",
		Metadata: make(map[string]string, 0),
	}
	mgr, err := systemd.NewSystemdUnitManager(uDir, false)
	if err != nil {
		// NOTE: ideally we should fail with t.Fatalf(), but then it would always
		// fail on travis CI, because apparently systemd dbus socket is not
		// available there. So let's just skip the test for now.
		// In the long run, we should find a way to test it correctly on travis.
		// - dpark 20160812
		t.Skipf("unexpected error creating systemd unit manager: %v", err)
	}

	mach := machine.NewCoreOSMachine(*state, mgr)
	e := &testEtcdKeysAPI{}
	etcdReg := registry.NewEtcdRegistry(e, "/fleet/")

	lManager := lease.NewEtcdLeaseManager(e, "/fleet/")
	reg := NewRegistryMux(etcdReg, mach, lManager)

	contents := `
[Unit]
Description = Foo
`
	unitFile, err := unit.NewUnitFile(contents)
	if err != nil {
		t.Fatalf("unexpected error parsing unit %q: %v", contents, err)
	}
	unit := &job.Unit{
		Name:        "foo",
		Unit:        *unitFile,
		TargetState: job.JobStateLoaded,
	}
	if err := reg.CreateUnit(unit); err != nil {
		t.Fatalf("unexpected error creating an unit: %v", err)
	}

	machineID := "testMachine"
	if err := reg.ScheduleUnit(unit.Name, machineID); err != nil {
		t.Fatalf("unexpected error scheduling an unit: %v", err)
	}

	if err := reg.UnscheduleUnit(unit.Name, machineID); err != nil {
		t.Fatalf("unexpected error unscheduling an unit: %v", err)
	}

	if err := reg.DestroyUnit(unit.Name); err != nil {
		t.Fatalf("unexpected error destroying an unit: %v", err)
	}

	if err := reg.RemoveMachineState(machineID); err != nil {
		t.Fatalf("unexpected error removing machine state: %v", err)
	}
}
<commit_msg>registry/rpc: reenable error handling after NewSystemdUnitManager<commit_after>// Copyright 2016 The fleet Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package rpc

import (
	"io/ioutil"
	"os"
	"syscall"
	"testing"

	etcd "github.com/coreos/etcd/client"
	"golang.org/x/net/context"

	"github.com/coreos/fleet/job"
	"github.com/coreos/fleet/machine"
	"github.com/coreos/fleet/pkg/lease"
	"github.com/coreos/fleet/registry"
	"github.com/coreos/fleet/systemd"
	"github.com/coreos/fleet/unit"
)

type action struct {
	key string
	val string
	rec bool
}

type testEtcdKeysAPI struct {
	etcd.KeysAPI
	gets    []action
	sets    []action
	deletes []action
	res     []*etcd.Response // errors returned from subsequent calls to etcd
	ri      int
	err     []error // results returned from subsequent calls to etcd
	ei      int
}

func (t *testEtcdKeysAPI) Set(_ context.Context, key string, value string, _ *etcd.SetOptions) (*etcd.Response, error) {
	t.sets = append(t.sets, action{key: key, val: value})
	return t.next()
}

func (t *testEtcdKeysAPI) Get(_ context.Context, key string, opts *etcd.GetOptions) (*etcd.Response, error) {
	act := action{key: key}
	if opts != nil {
		act.rec = opts.Recursive
	}
	t.gets = append(t.gets, act)
	return t.next()
}

func (t *testEtcdKeysAPI) Delete(_ context.Context, key string, opts *etcd.DeleteOptions) (*etcd.Response, error) {
	act := action{key: key}
	if opts != nil {
		act.rec = opts.Recursive
	}
	t.deletes = append(t.deletes, act)
	return t.next()
}

func (t *testEtcdKeysAPI) next() (r *etcd.Response, e error) {
	if t.ri < len(t.res) {
		r = t.res[t.ri]
		t.ri++
	}
	if t.ei < len(t.err) {
		e = t.err[t.ei]
		t.ei++
	}
	return r, e
}

func TestRegistryMuxUnitManagement(t *testing.T) {
	uDir, err := ioutil.TempDir("", "fleet-")
	if err != nil {
		t.Fatalf("failed creating tempdir: %v", err)
	}
	defer os.RemoveAll(uDir)

	if syscall.Geteuid() != 0 {
		t.Skipf("non-root user cannot call systemd unit manager. skip.")
	}
	if info, err := os.Stat("/run/systemd/system"); err != nil || !info.IsDir() {
		t.Skipf("systemd is not available. skip.")
	}

	state := &machine.MachineState{
		ID:       "id",
		PublicIP: "127.0.0.1",
		Metadata: make(map[string]string, 0),
	}
	mgr, err := systemd.NewSystemdUnitManager(uDir, false)
	if err != nil {
		t.Fatalf("unexpected error creating systemd unit manager: %v", err)
	}

	mach := machine.NewCoreOSMachine(*state, mgr)
	e := &testEtcdKeysAPI{}
	etcdReg := registry.NewEtcdRegistry(e, "/fleet/")

	lManager := lease.NewEtcdLeaseManager(e, "/fleet/")
	reg := NewRegistryMux(etcdReg, mach, lManager)

	contents := `
[Unit]
Description = Foo
`
	unitFile, err := unit.NewUnitFile(contents)
	if err != nil {
		t.Fatalf("unexpected error parsing unit %q: %v", contents, err)
	}
	unit := &job.Unit{
		Name:        "foo",
		Unit:        *unitFile,
		TargetState: job.JobStateLoaded,
	}
	if err := reg.CreateUnit(unit); err != nil {
		t.Fatalf("unexpected error creating an unit: %v", err)
	}

	machineID := "testMachine"
	if err := reg.ScheduleUnit(unit.Name, machineID); err != nil {
		t.Fatalf("unexpected error scheduling an unit: %v", err)
	}

	if err := reg.UnscheduleUnit(unit.Name, machineID); err != nil {
		t.Fatalf("unexpected error unscheduling an unit: %v", err)
	}

	if err := reg.DestroyUnit(unit.Name); err != nil {
		t.Fatalf("unexpected error destroying an unit: %v", err)
	}

	if err := reg.RemoveMachineState(machineID); err != nil {
		t.Fatalf("unexpected error removing machine state: %v", err)
	}
}
<|endoftext|>


<commit_before>/*
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements.  See the NOTICE file
distributed with this work for additional information
regarding copyright ownership.  The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License.  You may obtain a copy of the License at

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

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

package main

import (
	"io/ioutil"
	"os"
	"sync"

	"obc-peer/obcca/obcca"
	"github.com/spf13/viper"
)

func main() {
	viper.AutomaticEnv()
	viper.SetConfigName("obcca")
	viper.SetConfigType("yaml")
	viper.AddConfigPath("./")
	err := viper.ReadInConfig()
	if err != nil {
		panic(err)
	}

	obcca.LogInit(ioutil.Discard, os.Stdout, os.Stdout, os.Stderr, os.Stdout)

	eca := obcca.NewECA()
	defer eca.Close()

	tca := obcca.NewTCA(eca)
	defer tca.Close()

	var wg sync.WaitGroup
	eca.Start(&wg)
	tca.Start(&wg)

	wg.Wait()
}
<commit_msg>fix build error on import statement<commit_after>/*
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements.  See the NOTICE file
distributed with this work for additional information
regarding copyright ownership.  The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License.  You may obtain a copy of the License at

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

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

package main

import (
	"io/ioutil"
	"os"
	"sync"

	"github.com/openblockchain/obc-peer/obcca/obcca"
	//"obc-peer/obcca/obcca"
	"github.com/spf13/viper"
)

func main() {
	viper.AutomaticEnv()
	viper.SetConfigName("obcca")
	viper.SetConfigType("yaml")
	viper.AddConfigPath("./")
	err := viper.ReadInConfig()
	if err != nil {
		panic(err)
	}

	obcca.LogInit(ioutil.Discard, os.Stdout, os.Stdout, os.Stderr, os.Stdout)

	eca := obcca.NewECA()
	defer eca.Close()

	tca := obcca.NewTCA(eca)
	defer tca.Close()

	var wg sync.WaitGroup
	eca.Start(&wg)
	tca.Start(&wg)

	wg.Wait()
}
<|endoftext|>


<commit_before>package backend

import (
	"context"
	"fmt"
	"io/ioutil"
	"net/http"
	"net/url"
	"strings"
	"time"

	"github.com/uber-go/zap"
)

func formatSQL(q string) string {
	s := strings.Split(q, "\n")
	for i := 0; i < len(s); i++ {
		s[i] = strings.TrimSpace(s[i])
	}

	return strings.Join(s, " ")
}

func Query(ctx context.Context, dsn string, query string, timeout time.Duration) (body []byte, err error) {
	start := time.Now()

	logger := Logger(ctx)
	logger = logger.With(zap.String("query", formatSQL(query)))

	defer func() {
		log := logger.With(zap.Duration("time_ns", time.Since(start)))

		if err != nil {
			log.Error("query", zap.Error(err))
		} else {
			log.Debug("query")
		}
	}()

	p, err := url.Parse(dsn)
	if err != nil {
		return
	}

	url := p.String()

	req, err := http.NewRequest("POST", url, strings.NewReader(query))
	if err != nil {
		return
	}

	client := &http.Client{Timeout: timeout}
	resp, err := client.Do(req)
	if err != nil {
		return
	}
	defer resp.Body.Close()

	body, _ = ioutil.ReadAll(resp.Body)

	if resp.StatusCode != 200 {
		// logrus.Errorf("[clickhouse] (time: %s, error: %s) %s", time.Now().Sub(start).String(), string(body), formatSQL(query))
		err = fmt.Errorf("clickhouse response status %d: %s", resp.StatusCode, string(body))
		return
	}

	// logrus.Debugf("[clickhouse] (time: %s) %s", time.Now().Sub(start).String(), formatSQL(query))
	return
}
<commit_msg>Don't log full queries >500 chars even in Debug<commit_after>package backend

import (
	"context"
	"fmt"
	"io/ioutil"
	"net/http"
	"net/url"
	"strings"
	"time"

	"github.com/uber-go/zap"
)

func formatSQL(q string) string {
	s := strings.Split(q, "\n")
	for i := 0; i < len(s); i++ {
		s[i] = strings.TrimSpace(s[i])
	}

	return strings.Join(s, " ")
}

func Query(ctx context.Context, dsn string, query string, timeout time.Duration) (body []byte, err error) {
	start := time.Now()

	logger := Logger(ctx)
	queryForLogger := query
	if len(queryForLogger) > 500 {
		queryForLogger = queryForLogger[:495] + "<...>"
	}
	logger = logger.With(zap.String("query", formatSQL(queryForLogger)))

	defer func() {
		log := logger.With(zap.Duration("time_ns", time.Since(start)))

		if err != nil {
			log.Error("query", zap.Error(err))
		} else {
			log.Debug("query")
		}
	}()

	p, err := url.Parse(dsn)
	if err != nil {
		return
	}

	url := p.String()

	req, err := http.NewRequest("POST", url, strings.NewReader(query))
	if err != nil {
		return
	}

	client := &http.Client{Timeout: timeout}
	resp, err := client.Do(req)
	if err != nil {
		return
	}
	defer resp.Body.Close()

	body, _ = ioutil.ReadAll(resp.Body)

	if resp.StatusCode != 200 {
		// logrus.Errorf("[clickhouse] (time: %s, error: %s) %s", time.Now().Sub(start).String(), string(body), formatSQL(query))
		err = fmt.Errorf("clickhouse response status %d: %s", resp.StatusCode, string(body))
		return
	}

	// logrus.Debugf("[clickhouse] (time: %s) %s", time.Now().Sub(start).String(), formatSQL(query))
	return
}
<|endoftext|>