<commit_before>package main

import (
	"github.com/ugorji/go-msgpack"
	"io/ioutil"
	"log"
	"os"
	"os/exec"
	"strings"
)

type Cache struct {
	Paths   map[string]Path
	History []string
}

type Path struct {
	Dir   string
	Execs []string
	Mtime int64
}

func main() {
	// Where's the cache?
	home := os.Getenv("HOME")
	cacheName := home + "/.cache/gorn.msgpack"
	// Read the cache
	in, _ := os.Open(cacheName)
	dec := msgpack.NewDecoder(in, nil)
	var cache Cache
	dec.Decode(&cache)

	// Check timestamps of everything on $PATH. If the timestamp is newer,
	// regenerate that path
	pathEnv := os.Getenv("PATH")
	paths := strings.Split(pathEnv, ":")
	for _, path := range paths {
		// TODO: compensate for missing paths
		fi, _ := os.Stat(path)
		mtime := fi.ModTime().Unix()
		if cache.Paths[path].Mtime != mtime {
			// Regenerate path
			if len(cache.Paths) == 0 {
				cache.Paths = make(map[string]Path, 64)
			}
			cache.Paths[path] = regenerate(path)
		}
	}

	candidates := make(map[string]string)
	// Populate history map
	historyMap := make(map[string]int)
	for i, exec := range cache.History {
		historyMap[exec] = i
	}
	// For executables in the paths dictionary
	for _, path := range cache.Paths {
		for _, exec := range path.Execs {
			// if it's not in previous input
			if _, ok := historyMap[exec]; !ok {
				// add it to candidates
				candidates[exec] = exec
			}
		}
	}

	var input []string
	// print previous input in order ...
	for _, exec := range cache.History {
		input = append(input, exec)
	}
	// print candidates in any order
	for exec := range candidates {
		input = append(input, exec)
	}
	inputJoined := strings.Join(input, "\n")
	reader := strings.NewReader(inputJoined)

	// get dmenu output
	dmenu := exec.Command("dmenu", os.Args[1:]...)
	dmenu.Stdin = reader
	dmenuBytes, _ := dmenu.Output()
	dmenuOut := strings.TrimSpace(string(dmenuBytes))

	// run it, without a shell
	progParts := strings.Split(dmenuOut, " ")
	path, err := exec.LookPath(progParts[0])
	if err != nil {
		log.Fatal("executable not found in path")
	}
	prog := exec.Command(path, progParts[1:]...)
	prog.Start()

	// add to beginning of list
	newHistory := []string{dmenuOut}
	// if dmenu output in previous input
	if i, ok := historyMap[dmenuOut]; ok {
		// remove it
		before := cache.History[:i]
		after := cache.History[i+1:]
		cache.History = append(before, after...)
	}
	cache.History = append(newHistory, cache.History...)

	// serialize previous input list and write
	// serialize paths and write
	out, _ := os.Create(cacheName)
	enc := msgpack.NewEncoder(out)
	enc.Encode(&cache)
}

func regenerate(pathname string) Path {
	var p Path
	p.Dir = pathname
	fi, _ := os.Stat(pathname)
	p.Mtime = fi.ModTime().Unix()

	fileinfos, _ := ioutil.ReadDir(pathname)
	for _, fi := range fileinfos {
		// Is it an executable?
		if fi.IsDir() == false && fi.Mode()&0111 != 0 {
			p.Execs = append(p.Execs, fi.Name())
		}
	}
	return p
}
<commit_msg>Create the cache directory if it doesn't exist<commit_after>package main

import (
	"github.com/ugorji/go-msgpack"
	"io/ioutil"
	"log"
	"os"
	"os/exec"
	"path/filepath"
	"strings"
)

type Cache struct {
	Paths   map[string]Path
	History []string
}

type Path struct {
	Dir   string
	Execs []string
	Mtime int64
}

func main() {
	// Where's the cache?
	cacheDir := os.Getenv("XDG_CACHE_HOME")
	if cacheDir == "" {
		cacheDir = filepath.Join(os.Getenv("HOME"), ".cache")
	}

	// Per the freedesktop spec, non-existent directories should be created 0700
	os.MkdirAll(cacheDir, 0700)
	cacheName := filepath.Join(cacheDir, "gorn.msgpack")

	// Read the cache
	in, _ := os.Open(cacheName)
	dec := msgpack.NewDecoder(in, nil)
	var cache Cache
	dec.Decode(&cache)

	// Check timestamps of everything on $PATH. If the timestamp is newer,
	// regenerate that path
	pathEnv := os.Getenv("PATH")
	paths := strings.Split(pathEnv, ":")
	for _, path := range paths {
		// TODO: compensate for missing paths
		fi, _ := os.Stat(path)
		mtime := fi.ModTime().Unix()
		if cache.Paths[path].Mtime != mtime {
			// Regenerate path
			if len(cache.Paths) == 0 {
				cache.Paths = make(map[string]Path, 64)
			}
			cache.Paths[path] = regenerate(path)
		}
	}

	candidates := make(map[string]string)
	// Populate history map
	historyMap := make(map[string]int)
	for i, exec := range cache.History {
		historyMap[exec] = i
	}
	// For executables in the paths dictionary
	for _, path := range cache.Paths {
		for _, exec := range path.Execs {
			// if it's not in previous input
			if _, ok := historyMap[exec]; !ok {
				// add it to candidates
				candidates[exec] = exec
			}
		}
	}

	var input []string
	// print previous input in order ...
	for _, exec := range cache.History {
		input = append(input, exec)
	}
	// print candidates in any order
	for exec := range candidates {
		input = append(input, exec)
	}
	inputJoined := strings.Join(input, "\n")
	reader := strings.NewReader(inputJoined)

	// get dmenu output
	dmenu := exec.Command("dmenu", os.Args[1:]...)
	dmenu.Stdin = reader
	dmenuBytes, _ := dmenu.Output()
	dmenuOut := strings.TrimSpace(string(dmenuBytes))

	// run it, without a shell
	progParts := strings.Split(dmenuOut, " ")
	path, err := exec.LookPath(progParts[0])
	if err != nil {
		log.Fatal("executable not found in path")
	}
	prog := exec.Command(path, progParts[1:]...)
	prog.Start()

	// add to beginning of list
	newHistory := []string{dmenuOut}
	// if dmenu output in previous input
	if i, ok := historyMap[dmenuOut]; ok {
		// remove it
		before := cache.History[:i]
		after := cache.History[i+1:]
		cache.History = append(before, after...)
	}
	cache.History = append(newHistory, cache.History...)

	// serialize previous input list and write
	// serialize paths and write
	out, _ := os.Create(cacheName)
	enc := msgpack.NewEncoder(out)
	enc.Encode(&cache)
}

func regenerate(pathname string) Path {
	var p Path
	p.Dir = pathname
	fi, _ := os.Stat(pathname)
	p.Mtime = fi.ModTime().Unix()

	fileinfos, _ := ioutil.ReadDir(pathname)
	for _, fi := range fileinfos {
		// Is it an executable?
		if fi.IsDir() == false && fi.Mode()&0111 != 0 {
			p.Execs = append(p.Execs, fi.Name())
		}
	}
	return p
}
<|endoftext|>


<commit_before>package quic

import (
	"bytes"
	"errors"
	"fmt"

	"github.com/lucas-clemente/quic-go/frames"
	"github.com/lucas-clemente/quic-go/handshake"
	"github.com/lucas-clemente/quic-go/protocol"
)

type packedPacket struct {
	number protocol.PacketNumber
	raw    []byte
	frames []frames.Frame
}

type packetPacker struct {
	connectionID protocol.ConnectionID
	version      protocol.VersionNumber
	cryptoSetup  *handshake.CryptoSetup

	packetNumberGenerator *packetNumberGenerator

	connectionParametersManager *handshake.ConnectionParametersManager

	streamFramer  *streamFramer
	controlFrames []frames.Frame
}

func newPacketPacker(connectionID protocol.ConnectionID, cryptoSetup *handshake.CryptoSetup, connectionParametersHandler *handshake.ConnectionParametersManager, streamFramer *streamFramer, version protocol.VersionNumber) *packetPacker {
	return &packetPacker{
		cryptoSetup:                 cryptoSetup,
		connectionID:                connectionID,
		connectionParametersManager: connectionParametersHandler,
		version:                     version,
		streamFramer:                streamFramer,
		packetNumberGenerator:       newPacketNumberGenerator(protocol.SkipPacketAveragePeriodLength),
	}
}

func (p *packetPacker) PackConnectionClose(frame *frames.ConnectionCloseFrame, leastUnacked protocol.PacketNumber) (*packedPacket, error) {
	return p.packPacket(nil, []frames.Frame{frame}, leastUnacked, true, false)
}

func (p *packetPacker) PackPacket(stopWaitingFrame *frames.StopWaitingFrame, controlFrames []frames.Frame, leastUnacked protocol.PacketNumber, maySendOnlyAck bool) (*packedPacket, error) {
	return p.packPacket(stopWaitingFrame, controlFrames, leastUnacked, false, maySendOnlyAck)
}

func (p *packetPacker) packPacket(stopWaitingFrame *frames.StopWaitingFrame, controlFrames []frames.Frame, leastUnacked protocol.PacketNumber, onlySendOneControlFrame, maySendOnlyAck bool) (*packedPacket, error) {
	if len(controlFrames) > 0 {
		p.controlFrames = append(p.controlFrames, controlFrames...)
	}

	currentPacketNumber := p.packetNumberGenerator.Peek()

	// cryptoSetup needs to be locked here, so that the AEADs are not changed between
	// calling DiversificationNonce() and Seal().
	p.cryptoSetup.LockForSealing()
	defer p.cryptoSetup.UnlockForSealing()

	packetNumberLen := protocol.GetPacketNumberLengthForPublicHeader(currentPacketNumber, leastUnacked)
	responsePublicHeader := &PublicHeader{
		ConnectionID:         p.connectionID,
		PacketNumber:         currentPacketNumber,
		PacketNumberLen:      packetNumberLen,
		TruncateConnectionID: p.connectionParametersManager.TruncateConnectionID(),
		DiversificationNonce: p.cryptoSetup.DiversificationNonce(),
	}

	publicHeaderLength, err := responsePublicHeader.GetLength()
	if err != nil {
		return nil, err
	}

	if stopWaitingFrame != nil {
		stopWaitingFrame.PacketNumber = currentPacketNumber
		stopWaitingFrame.PacketNumberLen = packetNumberLen
	}

	var payloadFrames []frames.Frame
	if onlySendOneControlFrame {
		payloadFrames = []frames.Frame{controlFrames[0]}
	} else {
		payloadFrames, err = p.composeNextPacket(stopWaitingFrame, publicHeaderLength)
		if err != nil {
			return nil, err
		}
	}

	// Check if we have enough frames to send
	if len(payloadFrames) == 0 {
		return nil, nil
	}
	// Don't send out packets that only contain a StopWaitingFrame
	if !onlySendOneControlFrame && len(payloadFrames) == 1 && stopWaitingFrame != nil {
		return nil, nil
	}
	// Don't send out packets that only contain an ACK (plus optional STOP_WAITING), if requested
	if !maySendOnlyAck {
		if len(payloadFrames) == 1 {
			if _, ok := payloadFrames[0].(*frames.AckFrame); ok {
				return nil, nil
			}
		} else if len(payloadFrames) == 2 && stopWaitingFrame != nil {
			if _, ok := payloadFrames[1].(*frames.AckFrame); ok {
				return nil, nil
			}
		}
	}

	raw := getPacketBuffer()
	buffer := bytes.NewBuffer(raw)

	if responsePublicHeader.WritePublicHeader(buffer, p.version) != nil {
		return nil, err
	}

	payloadStartIndex := buffer.Len()

	for _, frame := range payloadFrames {
		err := frame.Write(buffer, p.version)
		if err != nil {
			return nil, err
		}
	}

	if protocol.ByteCount(buffer.Len()+12) > protocol.MaxPacketSize {
		return nil, errors.New("PacketPacker BUG: packet too large")
	}

	raw = raw[0:buffer.Len()]
	p.cryptoSetup.Seal(raw[payloadStartIndex:payloadStartIndex], raw[payloadStartIndex:], currentPacketNumber, raw[:payloadStartIndex])
	raw = raw[0 : buffer.Len()+12]

	num := p.packetNumberGenerator.Pop()
	if num != currentPacketNumber {
		return nil, errors.New("PacketPacker BUG: Peeked and Popped packet numbers do not match.")
	}

	return &packedPacket{
		number: currentPacketNumber,
		raw:    raw,
		frames: payloadFrames,
	}, nil
}

func (p *packetPacker) composeNextPacket(stopWaitingFrame *frames.StopWaitingFrame, publicHeaderLength protocol.ByteCount) ([]frames.Frame, error) {
	var payloadLength protocol.ByteCount
	var payloadFrames []frames.Frame

	maxFrameSize := protocol.MaxFrameAndPublicHeaderSize - publicHeaderLength

	if stopWaitingFrame != nil {
		payloadFrames = append(payloadFrames, stopWaitingFrame)
		minLength, err := stopWaitingFrame.MinLength(p.version)
		if err != nil {
			return nil, err
		}
		payloadLength += minLength
	}

	for len(p.controlFrames) > 0 {
		frame := p.controlFrames[len(p.controlFrames)-1]
		minLength, _ := frame.MinLength(p.version) // controlFrames does not contain any StopWaitingFrames. So it will *never* return an error
		if payloadLength+minLength > maxFrameSize {
			break
		}
		payloadFrames = append(payloadFrames, frame)
		payloadLength += minLength
		p.controlFrames = p.controlFrames[:len(p.controlFrames)-1]
	}

	if payloadLength > maxFrameSize {
		return nil, fmt.Errorf("Packet Packer BUG: packet payload (%d) too large (%d)", payloadLength, maxFrameSize)
	}

	// temporarily increase the maxFrameSize by 2 bytes
	// this leads to a properly sized packet in all cases, since we do all the packet length calculations with StreamFrames that have the DataLen set
	// however, for the last StreamFrame in the packet, we can omit the DataLen, thus saving 2 bytes and yielding a packet of exactly the correct size
	maxFrameSize += 2

	fs := p.streamFramer.PopStreamFrames(maxFrameSize - payloadLength)
	if len(fs) != 0 {
		fs[len(fs)-1].DataLenPresent = false
	}

	// TODO: Simplify
	for _, f := range fs {
		payloadFrames = append(payloadFrames, f)
	}

	for b := p.streamFramer.PopBlockedFrame(); b != nil; b = p.streamFramer.PopBlockedFrame() {
		p.controlFrames = append(p.controlFrames, b)
	}

	return payloadFrames, nil
}

func (p *packetPacker) QueueControlFrameForNextPacket(f frames.Frame) {
	p.controlFrames = append(p.controlFrames, f)
}
<commit_msg>fix public header write error handling<commit_after>package quic

import (
	"bytes"
	"errors"
	"fmt"

	"github.com/lucas-clemente/quic-go/frames"
	"github.com/lucas-clemente/quic-go/handshake"
	"github.com/lucas-clemente/quic-go/protocol"
)

type packedPacket struct {
	number protocol.PacketNumber
	raw    []byte
	frames []frames.Frame
}

type packetPacker struct {
	connectionID protocol.ConnectionID
	version      protocol.VersionNumber
	cryptoSetup  *handshake.CryptoSetup

	packetNumberGenerator *packetNumberGenerator

	connectionParametersManager *handshake.ConnectionParametersManager

	streamFramer  *streamFramer
	controlFrames []frames.Frame
}

func newPacketPacker(connectionID protocol.ConnectionID, cryptoSetup *handshake.CryptoSetup, connectionParametersHandler *handshake.ConnectionParametersManager, streamFramer *streamFramer, version protocol.VersionNumber) *packetPacker {
	return &packetPacker{
		cryptoSetup:                 cryptoSetup,
		connectionID:                connectionID,
		connectionParametersManager: connectionParametersHandler,
		version:                     version,
		streamFramer:                streamFramer,
		packetNumberGenerator:       newPacketNumberGenerator(protocol.SkipPacketAveragePeriodLength),
	}
}

func (p *packetPacker) PackConnectionClose(frame *frames.ConnectionCloseFrame, leastUnacked protocol.PacketNumber) (*packedPacket, error) {
	return p.packPacket(nil, []frames.Frame{frame}, leastUnacked, true, false)
}

func (p *packetPacker) PackPacket(stopWaitingFrame *frames.StopWaitingFrame, controlFrames []frames.Frame, leastUnacked protocol.PacketNumber, maySendOnlyAck bool) (*packedPacket, error) {
	return p.packPacket(stopWaitingFrame, controlFrames, leastUnacked, false, maySendOnlyAck)
}

func (p *packetPacker) packPacket(stopWaitingFrame *frames.StopWaitingFrame, controlFrames []frames.Frame, leastUnacked protocol.PacketNumber, onlySendOneControlFrame, maySendOnlyAck bool) (*packedPacket, error) {
	if len(controlFrames) > 0 {
		p.controlFrames = append(p.controlFrames, controlFrames...)
	}

	currentPacketNumber := p.packetNumberGenerator.Peek()

	// cryptoSetup needs to be locked here, so that the AEADs are not changed between
	// calling DiversificationNonce() and Seal().
	p.cryptoSetup.LockForSealing()
	defer p.cryptoSetup.UnlockForSealing()

	packetNumberLen := protocol.GetPacketNumberLengthForPublicHeader(currentPacketNumber, leastUnacked)
	responsePublicHeader := &PublicHeader{
		ConnectionID:         p.connectionID,
		PacketNumber:         currentPacketNumber,
		PacketNumberLen:      packetNumberLen,
		TruncateConnectionID: p.connectionParametersManager.TruncateConnectionID(),
		DiversificationNonce: p.cryptoSetup.DiversificationNonce(),
	}

	publicHeaderLength, err := responsePublicHeader.GetLength()
	if err != nil {
		return nil, err
	}

	if stopWaitingFrame != nil {
		stopWaitingFrame.PacketNumber = currentPacketNumber
		stopWaitingFrame.PacketNumberLen = packetNumberLen
	}

	var payloadFrames []frames.Frame
	if onlySendOneControlFrame {
		payloadFrames = []frames.Frame{controlFrames[0]}
	} else {
		payloadFrames, err = p.composeNextPacket(stopWaitingFrame, publicHeaderLength)
		if err != nil {
			return nil, err
		}
	}

	// Check if we have enough frames to send
	if len(payloadFrames) == 0 {
		return nil, nil
	}
	// Don't send out packets that only contain a StopWaitingFrame
	if !onlySendOneControlFrame && len(payloadFrames) == 1 && stopWaitingFrame != nil {
		return nil, nil
	}
	// Don't send out packets that only contain an ACK (plus optional STOP_WAITING), if requested
	if !maySendOnlyAck {
		if len(payloadFrames) == 1 {
			if _, ok := payloadFrames[0].(*frames.AckFrame); ok {
				return nil, nil
			}
		} else if len(payloadFrames) == 2 && stopWaitingFrame != nil {
			if _, ok := payloadFrames[1].(*frames.AckFrame); ok {
				return nil, nil
			}
		}
	}

	raw := getPacketBuffer()
	buffer := bytes.NewBuffer(raw)

	if err = responsePublicHeader.WritePublicHeader(buffer, p.version); err != nil {
		return nil, err
	}

	payloadStartIndex := buffer.Len()

	for _, frame := range payloadFrames {
		err := frame.Write(buffer, p.version)
		if err != nil {
			return nil, err
		}
	}

	if protocol.ByteCount(buffer.Len()+12) > protocol.MaxPacketSize {
		return nil, errors.New("PacketPacker BUG: packet too large")
	}

	raw = raw[0:buffer.Len()]
	p.cryptoSetup.Seal(raw[payloadStartIndex:payloadStartIndex], raw[payloadStartIndex:], currentPacketNumber, raw[:payloadStartIndex])
	raw = raw[0 : buffer.Len()+12]

	num := p.packetNumberGenerator.Pop()
	if num != currentPacketNumber {
		return nil, errors.New("PacketPacker BUG: Peeked and Popped packet numbers do not match.")
	}

	return &packedPacket{
		number: currentPacketNumber,
		raw:    raw,
		frames: payloadFrames,
	}, nil
}

func (p *packetPacker) composeNextPacket(stopWaitingFrame *frames.StopWaitingFrame, publicHeaderLength protocol.ByteCount) ([]frames.Frame, error) {
	var payloadLength protocol.ByteCount
	var payloadFrames []frames.Frame

	maxFrameSize := protocol.MaxFrameAndPublicHeaderSize - publicHeaderLength

	if stopWaitingFrame != nil {
		payloadFrames = append(payloadFrames, stopWaitingFrame)
		minLength, err := stopWaitingFrame.MinLength(p.version)
		if err != nil {
			return nil, err
		}
		payloadLength += minLength
	}

	for len(p.controlFrames) > 0 {
		frame := p.controlFrames[len(p.controlFrames)-1]
		minLength, _ := frame.MinLength(p.version) // controlFrames does not contain any StopWaitingFrames. So it will *never* return an error
		if payloadLength+minLength > maxFrameSize {
			break
		}
		payloadFrames = append(payloadFrames, frame)
		payloadLength += minLength
		p.controlFrames = p.controlFrames[:len(p.controlFrames)-1]
	}

	if payloadLength > maxFrameSize {
		return nil, fmt.Errorf("Packet Packer BUG: packet payload (%d) too large (%d)", payloadLength, maxFrameSize)
	}

	// temporarily increase the maxFrameSize by 2 bytes
	// this leads to a properly sized packet in all cases, since we do all the packet length calculations with StreamFrames that have the DataLen set
	// however, for the last StreamFrame in the packet, we can omit the DataLen, thus saving 2 bytes and yielding a packet of exactly the correct size
	maxFrameSize += 2

	fs := p.streamFramer.PopStreamFrames(maxFrameSize - payloadLength)
	if len(fs) != 0 {
		fs[len(fs)-1].DataLenPresent = false
	}

	// TODO: Simplify
	for _, f := range fs {
		payloadFrames = append(payloadFrames, f)
	}

	for b := p.streamFramer.PopBlockedFrame(); b != nil; b = p.streamFramer.PopBlockedFrame() {
		p.controlFrames = append(p.controlFrames, b)
	}

	return payloadFrames, nil
}

func (p *packetPacker) QueueControlFrameForNextPacket(f frames.Frame) {
	p.controlFrames = append(p.controlFrames, f)
}
<|endoftext|>


<commit_before>package main

import (
	"crypto/x509"
	"encoding/json"
	"hash"
	//	"fmt"
	"crypto/sha512"
	"encoding/hex"
	"io"
	"io/ioutil"
	"log"
	"net/http"
	"os"
	"strconv"
	"strings"
	"time"
)

//Image contains data we got from API that we are using to filter and fetch said image next
type Image struct {
	Imgid          int    `json:"id_number"`
	URL            string `json:"image"`
	Filename       string
	Score          int    `json:"score"`
	OriginalFormat string `json:"original_format"`
	Hashval        string `json:"sha512_hash"`
}

//Search returns to us array of searched images...
type Search struct {
	Images []Image `json:"search"`
}

//ImageCh is a channel of image data. You can put images into channel by parsing
//Derpibooru API by id(s) or  by tags and you can download images that are already
//in channel
type ImageCh chan Image

//Push gets unmarchalled JSON info, massages it and plugs it into channel so it
//would be processed in other places
func (imgchan ImageCh) push(dat Image) {
	dat.Filename = strconv.Itoa(dat.Imgid) + "." + dat.OriginalFormat
	dat.URL = prefix + dat.URL
	if dat.OriginalFormat == "svg" {
		i := strings.LastIndex(dat.URL, ".")
		if i != -1 {
			dat.URL = dat.URL[:i] + ".svg" //Was afraid to extract things I needed from the date field, so extracting them from URL.
		}
	}
	imgchan <- dat
}

//ParseImg gets image IDs, fetches information about those images from Derpibooru and pushes them into the channel.
func (imgchan ImageCh) ParseImg() {

	for _, imgid := range opts.Args.IDs {
		source := prefix + "//derpiboo.ru/images/" + strconv.Itoa(imgid) + ".json"
		if opts.Key != "" {
			source = source + "?key=" + opts.Key
		}

		//log.Println("Getting image info at:", source)

		response, err := http.Get(source) //Getting our nice http response. Needs checking for 404 and other responses that are... less expected
		if err != nil {
			if _, ok := err.(x509.UnknownAuthorityError); ok && opts.Unsafe {
				log.Println("Warning: ", err)
			} else {
				elog.Println(err)
				continue
			}
		}

		defer func() {
			err = response.Body.Close() //and not forgetting to close it when it's done
			if err != nil {
				elog.Fatalln("Could  not close server response")
			}
		}()
		var dat Image

		if !okStatus(response) {
			continue
		}

		body, err := ioutil.ReadAll(response.Body) //stolen from official documentation
		if err != nil {
			elog.Println(err)
			continue
		}

		if err := json.Unmarshal(body, &dat); //transforming json into native map

		err != nil {
			elog.Println(err)
			continue
		}

		imgchan.push(dat)
	}

	close(imgchan) //closing channel, we are done here

	return
}

//DlImg reads image data from channel and downloads specified images to disc
func (imgchan ImageCh) DlImg() {

	log.Println("Worker started; reading channel") //nice notification that we are not forgotten

	hasher := sha512.New() //checksums will be done in this

	for imgdata := range imgchan {

		if imgdata.Filename == "" {
			elog.Println("Empty filename. Oops?") //something somewhere had gone wrong, not a cause to die, going to the next image
			continue
		}

		log.Println("Saving as", imgdata.Filename)

		imgdata.saveImage(hasher)

		//fmt.Println("\n", hex.EncodeToString(hash.Sum(nil)), "\n", imgdata.hash )

	}
	done <- true
}

func (imgdata Image) saveImage(hasher hash.Hash) { // To not hold all the files open when there is no need. All pointers to files are in the scope of this function.

	output, err := os.Create(opts.ImageDir + string(os.PathSeparator) + imgdata.Filename) //And now, THE FILE!
	if err != err {
		elog.Println("Error when creating file for image" + strconv.Itoa(imgdata.Imgid))
		elog.Println(err) //Either we got no permisson or no space, end of line
		return
	}
	defer func() {
		err = output.Close() //Not forgetting to deal with it after completing download
		if err != nil {
			elog.Fatalln("Could  not close downloaded file")
		}
	}()

	start := time.Now()
	response, err := http.Get(imgdata.URL)
	if err != nil {
		if _, ok := err.(x509.UnknownAuthorityError); ok && opts.Unsafe {
			log.Println("Warning: ", err)
		} else {
			elog.Println("Error when getting image", imgdata.Imgid)
			elog.Println(err)
			return
		}
	}
	defer func() {
		err = response.Body.Close() //Same, we shall not listen to the void when we finished getting image
		if err != nil {
			elog.Fatalln("Could  not close server response")
		}
	}()
	if !okStatus(response) {
		return
	}
	size, err := io.Copy(output, io.TeeReader(response.Body, hasher)) //	Writing things we got from Derpibooru into the file and into hasher
	if err != nil {
		elog.Println("Unable to write image on disk, id ", imgdata.Imgid)
		elog.Println(err)
		return
	}
	timed := time.Since(start).Seconds()

	hash := hex.EncodeToString(hasher.Sum(nil))

	if hash != imgdata.Hashval {
		elog.Println("Hash mismatch, got ", hash, " instead of ", imgdata.Hashval)
	}

	hasher.Reset()

	log.Printf("Downloaded %d bytes in %.2fs, speed %s/s\n", size, timed, fmtbytes(float64(size)/timed))
}

//ParseTag gets image tags, fetches information about all images it could from Derpibooru and pushes them into the channel.
func (imgchan ImageCh) ParseTag() {

	source := prefix + "//derpiboo.ru/search.json?q=" + opts.Tag //yay hardwiring url strings!

	if opts.Key != "" {
		source = source + "&key=" + opts.Key
	}

	log.Println("Searching as", source)

	for i := opts.StartPage; opts.StopPage == 0 || i <= opts.StopPage; i++ {
		//I suspect that all those returns could be dealt with in some way. But lazy.
		log.Println("Searching page", i)

		response, err := http.Get(source + "&page=" + strconv.Itoa(i))
		//Getting our nice http response. Needs checking for 404 and other responses that are... less expected

		if err != nil {
			if _, ok := err.(x509.UnknownAuthorityError); ok && opts.Unsafe {
				log.Println("Warning: ", err)
			} else {
				elog.Println("Error while getting search page", i)
				elog.Println(err)
				continue
			}
		}

		defer func() {
			err = response.Body.Close() //and not forgetting to close it when it's done. And before we panic and die horribly.
			if err != nil {
				elog.Fatalln("Could  not close server response")
			}
		}()

		if !okStatus(response) {
			continue
		}

		var dats Search //Because we got array incoming instead of single object, we using an slive of maps!

		//fmt.Println(resp)

		body, err := ioutil.ReadAll(response.Body) //stolen from official documentation
		if err != nil {
			elog.Println("Error while reading search page", i)
			elog.Println(err)
			continue
		}

		//fmt.Println(body)

		err = json.Unmarshal(body, &dats) //transforming json into native slice of maps

		if err != nil {
			elog.Println("Error while parsing search page", i)
			elog.Println(err)
			if serr, ok := err.(*json.SyntaxError); ok {
				log.Println("Occurred at offset:", serr.Offset)
			}
			continue

		}

		if len(dats.Images) == 0 {
			log.Println("Pages are over") //Does not mean that process is over.
			break
		} //exit due to finishing all pages

		for _, dat := range dats.Images {
			imgchan.push(dat)
		}

	}

	close(imgchan)
}

func okStatus(chk *http.Response) bool {
	switch chk.StatusCode {
	case http.StatusOK, http.StatusNotModified:
		return true
	case http.StatusGatewayTimeout:
		elog.Println("Gateway timeout: ", chk.Status)
		return false
	case http.StatusBadRequest, http.StatusTeapot, http.StatusUnauthorized, http.StatusForbidden, http.StatusNotFound, http.StatusRequestURITooLong, http.StatusExpectationFailed:
		elog.Println("Incorrect request to server, error ", chk.Status)
		elog.Println("Possible API changes")
		return false
	default:
		elog.Println("Got something weird from server: ", chk.Status)
		elog.Println("Continuing anyway")
		return true
	}
}
<commit_msg>More readablilty and cases<commit_after>package main

import (
	"crypto/x509"
	"encoding/json"
	"hash"
	//	"fmt"
	"crypto/sha512"
	"encoding/hex"
	"io"
	"io/ioutil"
	"log"
	"net/http"
	"os"
	"strconv"
	"strings"
	"time"
)

//Image contains data we got from API that we are using to filter and fetch said image next
type Image struct {
	Imgid          int    `json:"id_number"`
	URL            string `json:"image"`
	Filename       string
	Score          int    `json:"score"`
	OriginalFormat string `json:"original_format"`
	Hashval        string `json:"sha512_hash"`
}

//Search returns to us array of searched images...
type Search struct {
	Images []Image `json:"search"`
}

//ImageCh is a channel of image data. You can put images into channel by parsing
//Derpibooru API by id(s) or  by tags and you can download images that are already
//in channel
type ImageCh chan Image

//Push gets unmarchalled JSON info, massages it and plugs it into channel so it
//would be processed in other places
func (imgchan ImageCh) push(dat Image) {
	dat.Filename = strconv.Itoa(dat.Imgid) + "." + dat.OriginalFormat
	dat.URL = prefix + dat.URL
	if dat.OriginalFormat == "svg" {
		i := strings.LastIndex(dat.URL, ".")
		if i != -1 {
			dat.URL = dat.URL[:i] + ".svg" //Was afraid to extract things I needed from the date field, so extracting them from URL.
		}
	}
	imgchan <- dat
}

//ParseImg gets image IDs, fetches information about those images from Derpibooru and pushes them into the channel.
func (imgchan ImageCh) ParseImg() {

	for _, imgid := range opts.Args.IDs {
		source := prefix + "//derpiboo.ru/images/" + strconv.Itoa(imgid) + ".json"
		if opts.Key != "" {
			source = source + "?key=" + opts.Key
		}

		//log.Println("Getting image info at:", source)

		response, err := http.Get(source) //Getting our nice http response. Needs checking for 404 and other responses that are... less expected
		if err != nil {
			if _, ok := err.(x509.UnknownAuthorityError); ok && opts.Unsafe {
				log.Println("Warning: ", err)
			} else {
				elog.Println(err)
				continue
			}
		}

		defer func() {
			err = response.Body.Close() //and not forgetting to close it when it's done
			if err != nil {
				elog.Fatalln("Could  not close server response")
			}
		}()
		var dat Image

		if !okStatus(response) {
			continue
		}

		body, err := ioutil.ReadAll(response.Body) //stolen from official documentation
		if err != nil {
			elog.Println(err)
			continue
		}

		if err := json.Unmarshal(body, &dat); //transforming json into native map

		err != nil {
			elog.Println(err)
			continue
		}

		imgchan.push(dat)
	}

	close(imgchan) //closing channel, we are done here

	return
}

//DlImg reads image data from channel and downloads specified images to disc
func (imgchan ImageCh) DlImg() {

	log.Println("Worker started; reading channel") //nice notification that we are not forgotten

	hasher := sha512.New() //checksums will be done in this

	for imgdata := range imgchan {

		if imgdata.Filename == "" {
			elog.Println("Empty filename. Oops?") //something somewhere had gone wrong, not a cause to die, going to the next image
			continue
		}

		log.Println("Saving as", imgdata.Filename)

		imgdata.saveImage(hasher)

		//fmt.Println("\n", hex.EncodeToString(hash.Sum(nil)), "\n", imgdata.hash )

	}
	done <- true
}

func (imgdata Image) saveImage(hasher hash.Hash) { // To not hold all the files open when there is no need. All pointers to files are in the scope of this function.

	output, err := os.Create(opts.ImageDir + string(os.PathSeparator) + imgdata.Filename) //And now, THE FILE!
	if err != err {
		elog.Println("Error when creating file for image" + strconv.Itoa(imgdata.Imgid))
		elog.Println(err) //Either we got no permisson or no space, end of line
		return
	}
	defer func() {
		err = output.Close() //Not forgetting to deal with it after completing download
		if err != nil {
			elog.Fatalln("Could  not close downloaded file")
		}
	}()

	start := time.Now()
	response, err := http.Get(imgdata.URL)
	if err != nil {
		if _, ok := err.(x509.UnknownAuthorityError); ok && opts.Unsafe {
			log.Println("Warning: ", err)
		} else {
			elog.Println("Error when getting image", imgdata.Imgid)
			elog.Println(err)
			return
		}
	}
	defer func() {
		err = response.Body.Close() //Same, we shall not listen to the void when we finished getting image
		if err != nil {
			elog.Fatalln("Could  not close server response")
		}
	}()
	if !okStatus(response) {
		return
	}
	size, err := io.Copy(output, io.TeeReader(response.Body, hasher)) //	Writing things we got from Derpibooru into the file and into hasher
	if err != nil {
		elog.Println("Unable to write image on disk, id ", imgdata.Imgid)
		elog.Println(err)
		return
	}
	timed := time.Since(start).Seconds()

	hash := hex.EncodeToString(hasher.Sum(nil))

	if hash != imgdata.Hashval {
		elog.Println("Hash mismatch, got ", hash, " instead of ", imgdata.Hashval)
	}

	hasher.Reset()

	log.Printf("Downloaded %d bytes in %.2fs, speed %s/s\n", size, timed, fmtbytes(float64(size)/timed))
}

//ParseTag gets image tags, fetches information about all images it could from Derpibooru and pushes them into the channel.
func (imgchan ImageCh) ParseTag() {

	source := prefix + "//derpiboo.ru/search.json?q=" + opts.Tag //yay hardwiring url strings!

	if opts.Key != "" {
		source = source + "&key=" + opts.Key
	}

	log.Println("Searching as", source)

	for i := opts.StartPage; opts.StopPage == 0 || i <= opts.StopPage; i++ {
		//I suspect that all those returns could be dealt with in some way. But lazy.
		log.Println("Searching page", i)

		response, err := http.Get(source + "&page=" + strconv.Itoa(i))
		//Getting our nice http response. Needs checking for 404 and other responses that are... less expected

		if err != nil {
			if _, ok := err.(x509.UnknownAuthorityError); ok && opts.Unsafe {
				log.Println("Warning: ", err)
			} else {
				elog.Println("Error while getting search page", i)
				elog.Println(err)
				continue
			}
		}

		defer func() {
			err = response.Body.Close() //and not forgetting to close it when it's done. And before we panic and die horribly.
			if err != nil {
				elog.Fatalln("Could  not close server response")
			}
		}()

		if !okStatus(response) {
			continue
		}

		var dats Search //Because we got array incoming instead of single object, we using an slive of maps!

		//fmt.Println(resp)

		body, err := ioutil.ReadAll(response.Body) //stolen from official documentation
		if err != nil {
			elog.Println("Error while reading search page", i)
			elog.Println(err)
			continue
		}

		//fmt.Println(body)

		err = json.Unmarshal(body, &dats) //transforming json into native slice of maps

		if err != nil {
			elog.Println("Error while parsing search page", i)
			elog.Println(err)
			if serr, ok := err.(*json.SyntaxError); ok {
				log.Println("Occurred at offset:", serr.Offset)
			}
			continue

		}

		if len(dats.Images) == 0 {
			log.Println("Pages are over") //Does not mean that process is over.
			break
		} //exit due to finishing all pages

		for _, dat := range dats.Images {
			imgchan.push(dat)
		}

	}

	close(imgchan)
}

func okStatus(chk *http.Response) bool {
	switch chk.StatusCode {
	case http.StatusOK, http.StatusNotModified:
		return true
	case http.StatusGatewayTimeout,
		http.StatusInternalServerError,
		http.StatusNotImplemented,
		http.StatusBadGateway,
		http.StatusServiceUnavailable,
		http.StatusHTTPVersionNotSupported:
		elog.Println("Server error: ", chk.Status)
		return false
	case http.StatusBadRequest,
		http.StatusTeapot,
		http.StatusUnauthorized,
		http.StatusForbidden,
		http.StatusNotFound,
		http.StatusRequestURITooLong,
		http.StatusExpectationFailed:
		elog.Println("Incorrect request to server, error ", chk.Status)
		elog.Println("Possible API changes")
		return false
	default:
		elog.Println("Got something weird from server: ", chk.Status)
		elog.Println("Continuing anyway")
		return true
	}
}
<|endoftext|>


<commit_before>package integration_test

import (
	"encoding/json"
	"time"

	. "github.com/cloudfoundry-incubator/route-emitter/routing_table/matchers"
	"github.com/cloudfoundry-incubator/runtime-schema/models"
	"github.com/cloudfoundry/gibson"
	"github.com/cloudfoundry/yagnats"
	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
	"github.com/onsi/gomega/gexec"
)

var _ = Describe("Integration", func() {
	listenForRoutes := func(subject string) <-chan gibson.RegistryMessage {
		routes := make(chan gibson.RegistryMessage)

		natsRunner.MessageBus.Subscribe(subject, func(msg *yagnats.Message) {
			defer GinkgoRecover()

			var message gibson.RegistryMessage
			err := json.Unmarshal(msg.Payload, &message)
			Ω(err).ShouldNot(HaveOccurred())

			routes <- message
		})

		return routes
	}

	var (
		registeredRoutes   <-chan gibson.RegistryMessage
		unregisteredRoutes <-chan gibson.RegistryMessage
	)

	BeforeEach(func() {
		registeredRoutes = listenForRoutes("router.register")
		unregisteredRoutes = listenForRoutes("router.unregister")

		natsRunner.MessageBus.Subscribe("router.greet", func(msg *yagnats.Message) {
			defer GinkgoRecover()

			greeting := gibson.RouterGreetingMessage{
				MinimumRegisterInterval: 2,
			}

			response, err := json.Marshal(greeting)
			Ω(err).ShouldNot(HaveOccurred())

			err = natsRunner.MessageBus.Publish(msg.ReplyTo, response)
			Ω(err).ShouldNot(HaveOccurred())
		})
	})

	AfterEach(func() {
		Ω(runner.Session).ShouldNot(gexec.Exit(), "Runner should not have exploded!")
	})

	Context("when the emitter is running", func() {
		BeforeEach(func() {
			runner.Start()
		})

		Context("and routes are desired", func() {
			BeforeEach(func() {
				err := bbs.DesireLRP(models.DesiredLRP{
					ProcessGuid: "guid1",
					Routes:      []string{"route-1", "route-2"},
					Instances:   5,
					Stack:       "some-stack",
					MemoryMB:    1024,
					DiskMB:      512,
					Source:      "http://example.com/",
				})
				Ω(err).ShouldNot(HaveOccurred())
			})

			Context("and an endpoint comes up", func() {
				BeforeEach(func() {
					err := bbs.ReportActualLRPAsRunning(models.ActualLRP{
						ProcessGuid:  "guid1",
						Index:        0,
						InstanceGuid: "iguid1",

						Host: "1.2.3.4",
						Ports: []models.PortMapping{
							{ContainerPort: 8080, HostPort: 65100},
						},
					}, "executor-id")
					Ω(err).ShouldNot(HaveOccurred())
				})

				It("emits its routes immediately", func() {
					Eventually(registeredRoutes).Should(Receive(MatchRegistryMessage(gibson.RegistryMessage{
						URIs: []string{"route-1", "route-2"},
						Host: "1.2.3.4",
						Port: 65100,
					})))
				})
			})
		})

		Context("and an instance starts running", func() {
			BeforeEach(func() {
				err := bbs.DesireLRP(models.DesiredLRP{
					ProcessGuid: "guid1",
					Routes:      []string{"route-1", "route-2"},
					Instances:   5,
					Stack:       "some-stack",
					MemoryMB:    1024,
					DiskMB:      512,
					Source:      "http://example.com/",
				})
				Ω(err).ShouldNot(HaveOccurred())

				err = bbs.ReportActualLRPAsStarting(models.ActualLRP{
					ProcessGuid:  "guid1",
					Index:        0,
					InstanceGuid: "iguid1",
				}, "executor-id")
				Ω(err).ShouldNot(HaveOccurred())

			})

			It("does not emit routes", func() {
				Consistently(registeredRoutes).ShouldNot(Receive())
			})
		})

		Context("and an endpoint comes up", func() {
			BeforeEach(func() {
				err := bbs.ReportActualLRPAsRunning(models.ActualLRP{
					ProcessGuid:  "guid1",
					Index:        0,
					InstanceGuid: "iguid1",

					Host: "1.2.3.4",
					Ports: []models.PortMapping{
						{ContainerPort: 8080, HostPort: 65100},
					},
				}, "executor-id")
				Ω(err).ShouldNot(HaveOccurred())
			})

			Context("and a route is desired", func() {
				BeforeEach(func() {
					time.Sleep(100 * time.Millisecond)
					err := bbs.DesireLRP(models.DesiredLRP{
						ProcessGuid: "guid1",
						Routes:      []string{"route-1", "route-2"},
						Instances:   5,
						Stack:       "some-stack",
						MemoryMB:    1024,
						DiskMB:      512,
						Source:      "http://example.com/",
					})
					Ω(err).ShouldNot(HaveOccurred())
				})

				It("emits its routes immediately", func() {
					Eventually(registeredRoutes).Should(Receive(MatchRegistryMessage(gibson.RegistryMessage{
						URIs: []string{"route-1", "route-2"},
						Host: "1.2.3.4",
						Port: 65100,
					})))
				})

				It("repeats the route message at the interval given by the router", func() {
					var msg1 gibson.RegistryMessage
					Eventually(registeredRoutes).Should(Receive(&msg1))
					t1 := time.Now()

					var msg2 gibson.RegistryMessage
					Eventually(registeredRoutes, 5).Should(Receive(&msg2))
					t2 := time.Now()

					Ω(msg2).Should(MatchRegistryMessage(msg1))
					Ω(t2.Sub(t1)).Should(BeNumerically("~", 2*time.Second, 500*time.Millisecond))
				})
			})
		})

		Context("and etcd goes away", func() {
			BeforeEach(func() {
				etcdRunner.Stop()
			})

			It("does not explode", func() {
				Consistently(runner.Session, 5).ShouldNot(gexec.Exit())
			})
		})
	})

	Context("when the bbs has routes to emit in /desired and /actual", func() {
		BeforeEach(func() {
			err := bbs.DesireLRP(models.DesiredLRP{
				ProcessGuid: "guid1",
				Routes:      []string{"route-1", "route-2"},
				Instances:   5,
				Stack:       "some-stack",
				MemoryMB:    1024,
				DiskMB:      512,
				Source:      "http://example.com/",
			})
			Ω(err).ShouldNot(HaveOccurred())

			err = bbs.ReportActualLRPAsRunning(models.ActualLRP{
				ProcessGuid:  "guid1",
				Index:        0,
				InstanceGuid: "iguid1",

				Host: "1.2.3.4",
				Ports: []models.PortMapping{
					{ContainerPort: 8080, HostPort: 65100},
				},
			}, "executor-id")
			Ω(err).ShouldNot(HaveOccurred())
		})

		Context("and the emitter is started", func() {
			BeforeEach(func() {
				runner.Start()
			})

			It("immediately emits all routes", func() {
				Eventually(registeredRoutes).Should(Receive(MatchRegistryMessage(gibson.RegistryMessage{
					URIs: []string{"route-1", "route-2"},
					Host: "1.2.3.4",
					Port: 65100,
				})))
			})

			Context("and a route is added", func() {
				BeforeEach(func() {
					err := bbs.DesireLRP(models.DesiredLRP{
						ProcessGuid: "guid1",
						Routes:      []string{"route-1", "route-2", "route-3"},
						Instances:   5,
						Stack:       "some-stack",
						MemoryMB:    1024,
						DiskMB:      512,
						Source:      "http://example.com/",
					})
					Ω(err).ShouldNot(HaveOccurred())
				})

				It("immediately emits router.register", func() {
					Eventually(registeredRoutes).Should(Receive(MatchRegistryMessage(gibson.RegistryMessage{
						URIs: []string{"route-1", "route-2", "route-3"},
						Host: "1.2.3.4",
						Port: 65100,
					})))
				})
			})

			Context("and a route is removed", func() {
				BeforeEach(func() {
					err := bbs.DesireLRP(models.DesiredLRP{
						ProcessGuid: "guid1",
						Routes:      []string{"route-2"},
						Instances:   5,
						Stack:       "some-stack",
						MemoryMB:    1024,
						DiskMB:      512,
						Source:      "http://example.com/",
					})
					Ω(err).ShouldNot(HaveOccurred())
				})

				It("immediately emits router.unregister", func() {
					Eventually(unregisteredRoutes).Should(Receive(MatchRegistryMessage(gibson.RegistryMessage{
						URIs: []string{"route-1"},
						Host: "1.2.3.4",
						Port: 65100,
					})))
				})
			})
		})
	})
})
<commit_msg>update desiredlrp usage<commit_after>package integration_test

import (
	"encoding/json"
	"time"

	. "github.com/cloudfoundry-incubator/route-emitter/routing_table/matchers"
	"github.com/cloudfoundry-incubator/runtime-schema/models"
	"github.com/cloudfoundry/gibson"
	"github.com/cloudfoundry/yagnats"
	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
	"github.com/onsi/gomega/gexec"
)

var _ = Describe("Integration", func() {
	listenForRoutes := func(subject string) <-chan gibson.RegistryMessage {
		routes := make(chan gibson.RegistryMessage)

		natsRunner.MessageBus.Subscribe(subject, func(msg *yagnats.Message) {
			defer GinkgoRecover()

			var message gibson.RegistryMessage
			err := json.Unmarshal(msg.Payload, &message)
			Ω(err).ShouldNot(HaveOccurred())

			routes <- message
		})

		return routes
	}

	var (
		registeredRoutes   <-chan gibson.RegistryMessage
		unregisteredRoutes <-chan gibson.RegistryMessage
	)

	BeforeEach(func() {
		registeredRoutes = listenForRoutes("router.register")
		unregisteredRoutes = listenForRoutes("router.unregister")

		natsRunner.MessageBus.Subscribe("router.greet", func(msg *yagnats.Message) {
			defer GinkgoRecover()

			greeting := gibson.RouterGreetingMessage{
				MinimumRegisterInterval: 2,
			}

			response, err := json.Marshal(greeting)
			Ω(err).ShouldNot(HaveOccurred())

			err = natsRunner.MessageBus.Publish(msg.ReplyTo, response)
			Ω(err).ShouldNot(HaveOccurred())
		})
	})

	AfterEach(func() {
		Ω(runner.Session).ShouldNot(gexec.Exit(), "Runner should not have exploded!")
	})

	Context("when the emitter is running", func() {
		BeforeEach(func() {
			runner.Start()
		})

		Context("and routes are desired", func() {
			BeforeEach(func() {
				err := bbs.DesireLRP(models.DesiredLRP{
					ProcessGuid: "guid1",
					Routes:      []string{"route-1", "route-2"},
					Instances:   5,
					Stack:       "some-stack",
					MemoryMB:    1024,
					DiskMB:      512,
					Actions: []models.ExecutorAction{
						models.ExecutorAction{
							models.RunAction{
								Path: "ls",
							},
						},
					},
				})
				Ω(err).ShouldNot(HaveOccurred())
			})

			Context("and an endpoint comes up", func() {
				BeforeEach(func() {
					err := bbs.ReportActualLRPAsRunning(models.ActualLRP{
						ProcessGuid:  "guid1",
						Index:        0,
						InstanceGuid: "iguid1",

						Host: "1.2.3.4",
						Ports: []models.PortMapping{
							{ContainerPort: 8080, HostPort: 65100},
						},
					}, "executor-id")
					Ω(err).ShouldNot(HaveOccurred())
				})

				It("emits its routes immediately", func() {
					Eventually(registeredRoutes).Should(Receive(MatchRegistryMessage(gibson.RegistryMessage{
						URIs: []string{"route-1", "route-2"},
						Host: "1.2.3.4",
						Port: 65100,
					})))
				})
			})
		})

		Context("and an instance starts running", func() {
			BeforeEach(func() {
				err := bbs.DesireLRP(models.DesiredLRP{
					ProcessGuid: "guid1",
					Routes:      []string{"route-1", "route-2"},
					Instances:   5,
					Stack:       "some-stack",
					MemoryMB:    1024,
					DiskMB:      512,
					Actions: []models.ExecutorAction{
						models.ExecutorAction{
							models.RunAction{
								Path: "ls",
							},
						},
					},
				})
				Ω(err).ShouldNot(HaveOccurred())

				err = bbs.ReportActualLRPAsStarting(models.ActualLRP{
					ProcessGuid:  "guid1",
					Index:        0,
					InstanceGuid: "iguid1",
				}, "executor-id")
				Ω(err).ShouldNot(HaveOccurred())

			})

			It("does not emit routes", func() {
				Consistently(registeredRoutes).ShouldNot(Receive())
			})
		})

		Context("and an endpoint comes up", func() {
			BeforeEach(func() {
				err := bbs.ReportActualLRPAsRunning(models.ActualLRP{
					ProcessGuid:  "guid1",
					Index:        0,
					InstanceGuid: "iguid1",

					Host: "1.2.3.4",
					Ports: []models.PortMapping{
						{ContainerPort: 8080, HostPort: 65100},
					},
				}, "executor-id")
				Ω(err).ShouldNot(HaveOccurred())
			})

			Context("and a route is desired", func() {
				BeforeEach(func() {
					time.Sleep(100 * time.Millisecond)
					err := bbs.DesireLRP(models.DesiredLRP{
						ProcessGuid: "guid1",
						Routes:      []string{"route-1", "route-2"},
						Instances:   5,
						Stack:       "some-stack",
						MemoryMB:    1024,
						DiskMB:      512,
						Actions: []models.ExecutorAction{
							models.ExecutorAction{
								models.RunAction{
									Path: "ls",
								},
							},
						},
					})
					Ω(err).ShouldNot(HaveOccurred())
				})

				It("emits its routes immediately", func() {
					Eventually(registeredRoutes).Should(Receive(MatchRegistryMessage(gibson.RegistryMessage{
						URIs: []string{"route-1", "route-2"},
						Host: "1.2.3.4",
						Port: 65100,
					})))
				})

				It("repeats the route message at the interval given by the router", func() {
					var msg1 gibson.RegistryMessage
					Eventually(registeredRoutes).Should(Receive(&msg1))
					t1 := time.Now()

					var msg2 gibson.RegistryMessage
					Eventually(registeredRoutes, 5).Should(Receive(&msg2))
					t2 := time.Now()

					Ω(msg2).Should(MatchRegistryMessage(msg1))
					Ω(t2.Sub(t1)).Should(BeNumerically("~", 2*time.Second, 500*time.Millisecond))
				})
			})
		})

		Context("and etcd goes away", func() {
			BeforeEach(func() {
				etcdRunner.Stop()
			})

			It("does not explode", func() {
				Consistently(runner.Session, 5).ShouldNot(gexec.Exit())
			})
		})
	})

	Context("when the bbs has routes to emit in /desired and /actual", func() {
		BeforeEach(func() {
			err := bbs.DesireLRP(models.DesiredLRP{
				ProcessGuid: "guid1",
				Routes:      []string{"route-1", "route-2"},
				Instances:   5,
				Stack:       "some-stack",
				MemoryMB:    1024,
				DiskMB:      512,
				Actions: []models.ExecutorAction{
					models.ExecutorAction{
						models.RunAction{
							Path: "ls",
						},
					},
				},
			})
			Ω(err).ShouldNot(HaveOccurred())

			err = bbs.ReportActualLRPAsRunning(models.ActualLRP{
				ProcessGuid:  "guid1",
				Index:        0,
				InstanceGuid: "iguid1",

				Host: "1.2.3.4",
				Ports: []models.PortMapping{
					{ContainerPort: 8080, HostPort: 65100},
				},
			}, "executor-id")
			Ω(err).ShouldNot(HaveOccurred())
		})

		Context("and the emitter is started", func() {
			BeforeEach(func() {
				runner.Start()
			})

			It("immediately emits all routes", func() {
				Eventually(registeredRoutes).Should(Receive(MatchRegistryMessage(gibson.RegistryMessage{
					URIs: []string{"route-1", "route-2"},
					Host: "1.2.3.4",
					Port: 65100,
				})))
			})

			Context("and a route is added", func() {
				BeforeEach(func() {
					err := bbs.DesireLRP(models.DesiredLRP{
						ProcessGuid: "guid1",
						Routes:      []string{"route-1", "route-2", "route-3"},
						Instances:   5,
						Stack:       "some-stack",
						MemoryMB:    1024,
						DiskMB:      512,
						Actions: []models.ExecutorAction{
							models.ExecutorAction{
								models.RunAction{
									Path: "ls",
								},
							},
						},
					})
					Ω(err).ShouldNot(HaveOccurred())
				})

				It("immediately emits router.register", func() {
					Eventually(registeredRoutes).Should(Receive(MatchRegistryMessage(gibson.RegistryMessage{
						URIs: []string{"route-1", "route-2", "route-3"},
						Host: "1.2.3.4",
						Port: 65100,
					})))
				})
			})

			Context("and a route is removed", func() {
				BeforeEach(func() {
					err := bbs.DesireLRP(models.DesiredLRP{
						ProcessGuid: "guid1",
						Routes:      []string{"route-2"},
						Instances:   5,
						Stack:       "some-stack",
						MemoryMB:    1024,
						DiskMB:      512,
						Actions: []models.ExecutorAction{
							models.ExecutorAction{
								models.RunAction{
									Path: "ls",
								},
							},
						},
					})
					Ω(err).ShouldNot(HaveOccurred())
				})

				It("immediately emits router.unregister", func() {
					Eventually(unregisteredRoutes).Should(Receive(MatchRegistryMessage(gibson.RegistryMessage{
						URIs: []string{"route-1"},
						Host: "1.2.3.4",
						Port: 65100,
					})))
				})
			})
		})
	})
})
<|endoftext|>


<commit_before>/*
 *
 * Copyright 2018 gRPC 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 binarylog implementation binary logging as defined in
// https://github.com/grpc/proposal/blob/master/A16-binary-logging.md.
package binarylog

import (
	"fmt"
	"os"

	"google.golang.org/grpc/grpclog"
)

// Logger is the global binary logger. It can be used to get binary logger for
// each method.
type Logger interface {
	getMethodLogger(methodName string) *MethodLogger
}

// binLogger is the global binary logger for the binary. One of this should be
// built at init time from the configuration (environment variable or flags).
//
// It is used to get a methodLogger for each individual method.
var binLogger Logger

// SetLogger sets the binarg logger.
//
// Only call this at init time.
func SetLogger(l Logger) {
	binLogger = l
}

// GetMethodLogger returns the methodLogger for the given methodName.
//
// methodName should be in the format of "/service/method".
//
// Each methodLogger returned by this method is a new instance. This is to
// generate sequence id within the call.
func GetMethodLogger(methodName string) *MethodLogger {
	if binLogger == nil {
		return nil
	}
	return binLogger.getMethodLogger(methodName)
}

func init() {
	const envStr = "GRPC_BINARY_LOG_FILTER"
	configStr := os.Getenv(envStr)
	binLogger = NewLoggerFromConfigString(configStr)
}

type methodLoggerConfig struct {
	// Max length of header and message.
	hdr, msg uint64
}

type logger struct {
	all      *methodLoggerConfig
	services map[string]*methodLoggerConfig
	methods  map[string]*methodLoggerConfig

	blacklist map[string]struct{}
}

// newEmptyLogger creates an empty logger. The map fields need to be filled in
// using the set* functions.
func newEmptyLogger() *logger {
	return &logger{}
}

// Set method logger for "*".
func (l *logger) setDefaultMethodLogger(ml *methodLoggerConfig) error {
	if l.all != nil {
		return fmt.Errorf("conflicting global rules found")
	}
	l.all = ml
	return nil
}

// Set method logger for "service/*".
//
// New methodLogger with same service overrides the old one.
func (l *logger) setServiceMethodLogger(service string, ml *methodLoggerConfig) error {
	if _, ok := l.services[service]; ok {
		return fmt.Errorf("conflicting rules for service %v found", service)
	}
	if l.services == nil {
		l.services = make(map[string]*methodLoggerConfig)
	}
	l.services[service] = ml
	return nil
}

// Set method logger for "service/method".
//
// New methodLogger with same method overrides the old one.
func (l *logger) setMethodMethodLogger(method string, ml *methodLoggerConfig) error {
	if _, ok := l.blacklist[method]; ok {
		return fmt.Errorf("conflicting rules for method %v found", method)
	}
	if _, ok := l.methods[method]; ok {
		return fmt.Errorf("conflicting rules for method %v found", method)
	}
	if l.methods == nil {
		l.methods = make(map[string]*methodLoggerConfig)
	}
	l.methods[method] = ml
	return nil
}

// Set blacklist method for "-service/method".
func (l *logger) setBlacklist(method string) error {
	if _, ok := l.blacklist[method]; ok {
		return fmt.Errorf("conflicting rules for method %v found", method)
	}
	if _, ok := l.methods[method]; ok {
		return fmt.Errorf("conflicting rules for method %v found", method)
	}
	if l.blacklist == nil {
		l.blacklist = make(map[string]struct{})
	}
	l.blacklist[method] = struct{}{}
	return nil
}

// getMethodLogger returns the methodLogger for the given methodName.
//
// methodName should be in the format of "/service/method".
//
// Each methodLogger returned by this method is a new instance. This is to
// generate sequence id within the call.
func (l *logger) getMethodLogger(methodName string) *MethodLogger {
	s, m, err := parseMethodName(methodName)
	if err != nil {
		grpclog.Infof("binarylogging: failed to parse %q: %v", methodName, err)
		return nil
	}
	if ml, ok := l.methods[s+"/"+m]; ok {
		return newMethodLogger(ml.hdr, ml.msg)
	}
	if _, ok := l.blacklist[s+"/"+m]; ok {
		return nil
	}
	if ml, ok := l.services[s]; ok {
		return newMethodLogger(ml.hdr, ml.msg)
	}
	if l.all == nil {
		return nil
	}
	return newMethodLogger(l.all.hdr, l.all.msg)
}
<commit_msg>more detailed log message (#3117)<commit_after>/*
 *
 * Copyright 2018 gRPC 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 binarylog implementation binary logging as defined in
// https://github.com/grpc/proposal/blob/master/A16-binary-logging.md.
package binarylog

import (
	"fmt"
	"os"

	"google.golang.org/grpc/grpclog"
)

// Logger is the global binary logger. It can be used to get binary logger for
// each method.
type Logger interface {
	getMethodLogger(methodName string) *MethodLogger
}

// binLogger is the global binary logger for the binary. One of this should be
// built at init time from the configuration (environment variable or flags).
//
// It is used to get a methodLogger for each individual method.
var binLogger Logger

// SetLogger sets the binarg logger.
//
// Only call this at init time.
func SetLogger(l Logger) {
	binLogger = l
}

// GetMethodLogger returns the methodLogger for the given methodName.
//
// methodName should be in the format of "/service/method".
//
// Each methodLogger returned by this method is a new instance. This is to
// generate sequence id within the call.
func GetMethodLogger(methodName string) *MethodLogger {
	if binLogger == nil {
		return nil
	}
	return binLogger.getMethodLogger(methodName)
}

func init() {
	const envStr = "GRPC_BINARY_LOG_FILTER"
	configStr := os.Getenv(envStr)
	binLogger = NewLoggerFromConfigString(configStr)
}

type methodLoggerConfig struct {
	// Max length of header and message.
	hdr, msg uint64
}

type logger struct {
	all      *methodLoggerConfig
	services map[string]*methodLoggerConfig
	methods  map[string]*methodLoggerConfig

	blacklist map[string]struct{}
}

// newEmptyLogger creates an empty logger. The map fields need to be filled in
// using the set* functions.
func newEmptyLogger() *logger {
	return &logger{}
}

// Set method logger for "*".
func (l *logger) setDefaultMethodLogger(ml *methodLoggerConfig) error {
	if l.all != nil {
		return fmt.Errorf("conflicting global rules found")
	}
	l.all = ml
	return nil
}

// Set method logger for "service/*".
//
// New methodLogger with same service overrides the old one.
func (l *logger) setServiceMethodLogger(service string, ml *methodLoggerConfig) error {
	if _, ok := l.services[service]; ok {
		return fmt.Errorf("conflicting service rules for service %v found", service)
	}
	if l.services == nil {
		l.services = make(map[string]*methodLoggerConfig)
	}
	l.services[service] = ml
	return nil
}

// Set method logger for "service/method".
//
// New methodLogger with same method overrides the old one.
func (l *logger) setMethodMethodLogger(method string, ml *methodLoggerConfig) error {
	if _, ok := l.blacklist[method]; ok {
		return fmt.Errorf("conflicting blacklist rules for method %v found", method)
	}
	if _, ok := l.methods[method]; ok {
		return fmt.Errorf("conflicting method rules for method %v found", method)
	}
	if l.methods == nil {
		l.methods = make(map[string]*methodLoggerConfig)
	}
	l.methods[method] = ml
	return nil
}

// Set blacklist method for "-service/method".
func (l *logger) setBlacklist(method string) error {
	if _, ok := l.blacklist[method]; ok {
		return fmt.Errorf("conflicting blacklist rules for method %v found", method)
	}
	if _, ok := l.methods[method]; ok {
		return fmt.Errorf("conflicting method rules for method %v found", method)
	}
	if l.blacklist == nil {
		l.blacklist = make(map[string]struct{})
	}
	l.blacklist[method] = struct{}{}
	return nil
}

// getMethodLogger returns the methodLogger for the given methodName.
//
// methodName should be in the format of "/service/method".
//
// Each methodLogger returned by this method is a new instance. This is to
// generate sequence id within the call.
func (l *logger) getMethodLogger(methodName string) *MethodLogger {
	s, m, err := parseMethodName(methodName)
	if err != nil {
		grpclog.Infof("binarylogging: failed to parse %q: %v", methodName, err)
		return nil
	}
	if ml, ok := l.methods[s+"/"+m]; ok {
		return newMethodLogger(ml.hdr, ml.msg)
	}
	if _, ok := l.blacklist[s+"/"+m]; ok {
		return nil
	}
	if ml, ok := l.services[s]; ok {
		return newMethodLogger(ml.hdr, ml.msg)
	}
	if l.all == nil {
		return nil
	}
	return newMethodLogger(l.all.hdr, l.all.msg)
}
<|endoftext|>


<commit_before>// Copyright (C) 2018 Nippon Telegraph and Telephone Corporation.
//
// 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 version

import "fmt"

const MAJOR uint = 2
const MINOR uint = 29
const PATCH uint = 0

var COMMIT string = ""
var IDENTIFIER string = ""
var METADATA string = ""

func Version() string {
	var suffix string = ""
	if len(IDENTIFIER) > 0 {
		suffix = fmt.Sprintf("-%s", IDENTIFIER)
	}

	if len(COMMIT) > 0 || len(METADATA) > 0 {
		suffix = suffix + "+"
	}

	if len(COMMIT) > 0 {
		suffix = fmt.Sprintf("%s"+"commit.%s", suffix, COMMIT)

	}

	if len(METADATA) > 0 {
		if len(COMMIT) > 0 {
			suffix = suffix + "."
		}
		suffix = suffix + METADATA
	}

	return fmt.Sprintf("%d.%d.%d%s", MAJOR, MINOR, PATCH, suffix)
}
<commit_msg>v2.30.0<commit_after>// Copyright (C) 2018 Nippon Telegraph and Telephone Corporation.
//
// 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 version

import "fmt"

const MAJOR uint = 2
const MINOR uint = 30
const PATCH uint = 0

var COMMIT string = ""
var IDENTIFIER string = ""
var METADATA string = ""

func Version() string {
	var suffix string = ""
	if len(IDENTIFIER) > 0 {
		suffix = fmt.Sprintf("-%s", IDENTIFIER)
	}

	if len(COMMIT) > 0 || len(METADATA) > 0 {
		suffix = suffix + "+"
	}

	if len(COMMIT) > 0 {
		suffix = fmt.Sprintf("%s"+"commit.%s", suffix, COMMIT)

	}

	if len(METADATA) > 0 {
		if len(COMMIT) > 0 {
			suffix = suffix + "."
		}
		suffix = suffix + METADATA
	}

	return fmt.Sprintf("%d.%d.%d%s", MAJOR, MINOR, PATCH, suffix)
}
<|endoftext|>


<commit_before>// Copyright 2017 Zack Guo <zack.y.guo@gmail.com>. All rights reserved.
// Use of this source code is governed by a MIT license that can
// be found in the LICENSE file.

package termui

// GridBufferer introduces a Bufferer that can be manipulated by Grid.
type GridBufferer interface {
	Bufferer
	GetHeight() int
	SetWidth(int)
	SetX(int)
	SetY(int)
}

// Row builds a layout tree
type Row struct {
	Cols   []*Row       //children
	Widget GridBufferer // root
	X      int
	Y      int
	Width  int
	Height int
	Span   int
	Offset int
}

// calculate and set the underlying layout tree's x, y, height and width.
func (r *Row) calcLayout() {
	r.assignWidth(r.Width)
	r.Height = r.solveHeight()
	r.assignX(r.X)
	r.assignY(r.Y)
}

// tell if the node is leaf in the tree.
func (r *Row) isLeaf() bool {
	return r.Cols == nil || len(r.Cols) == 0
}

func (r *Row) isRenderableLeaf() bool {
	return r.isLeaf() && r.Widget != nil
}

// assign widgets' (and their parent rows') width recursively.
func (r *Row) assignWidth(w int) {
	r.SetWidth(w)

	accW := 0                            // acc span and offset
	calcW := make([]int, len(r.Cols))    // calculated width
	calcOftX := make([]int, len(r.Cols)) // computed start position of x

	for i, c := range r.Cols {
		accW += c.Span + c.Offset
		cw := int(float64(c.Span*r.Width) / 12.0)

		if i >= 1 {
			calcOftX[i] = calcOftX[i-1] +
				calcW[i-1] +
				int(float64(r.Cols[i-1].Offset*r.Width)/12.0)
		}

		// use up the space if it is the last col
		if i == len(r.Cols)-1 && accW == 12 {
			cw = r.Width - calcOftX[i]
		}
		calcW[i] = cw
		r.Cols[i].assignWidth(cw)
	}
}

// bottom up calc and set rows' (and their widgets') height,
// return r's total height.
func (r *Row) solveHeight() int {
	if r.isRenderableLeaf() {
		r.Height = r.Widget.GetHeight()
		return r.Widget.GetHeight()
	}

	maxh := 0
	if !r.isLeaf() {
		for _, c := range r.Cols {
			nh := c.solveHeight()
			// when embed rows in Cols, row widgets stack up
			if r.Widget != nil {
				nh += r.Widget.GetHeight()
			}
			if nh > maxh {
				maxh = nh
			}
		}
	}

	r.Height = maxh
	return maxh
}

// recursively assign x position for r tree.
func (r *Row) assignX(x int) {
	r.SetX(x)

	if !r.isLeaf() {
		acc := 0
		for i, c := range r.Cols {
			if c.Offset != 0 {
				acc += int(float64(c.Offset*r.Width) / 12.0)
			}
			r.Cols[i].assignX(x + acc)
			acc += c.Width
		}
	}
}

// recursively assign y position to r.
func (r *Row) assignY(y int) {
	r.SetY(y)

	if r.isLeaf() {
		return
	}

	for i := range r.Cols {
		acc := 0
		if r.Widget != nil {
			acc = r.Widget.GetHeight()
		}
		r.Cols[i].assignY(y + acc)
	}

}

// GetHeight implements GridBufferer interface.
func (r Row) GetHeight() int {
	return r.Height
}

// SetX implements GridBufferer interface.
func (r *Row) SetX(x int) {
	r.X = x
	if r.Widget != nil {
		r.Widget.SetX(x)
	}
}

// SetY implements GridBufferer interface.
func (r *Row) SetY(y int) {
	r.Y = y
	if r.Widget != nil {
		r.Widget.SetY(y)
	}
}

// SetWidth implements GridBufferer interface.
func (r *Row) SetWidth(w int) {
	r.Width = w
	if r.Widget != nil {
		r.Widget.SetWidth(w)
	}
}

// Buffer implements Bufferer interface,
// recursively merge all widgets buffer
func (r *Row) Buffer() Buffer {
	merged := NewBuffer()

	if r.isRenderableLeaf() {
		return r.Widget.Buffer()
	}

	// for those are not leaves but have a renderable widget
	if r.Widget != nil {
		merged.Merge(r.Widget.Buffer())
	}

	// collect buffer from children
	if !r.isLeaf() {
		for _, c := range r.Cols {
			merged.Merge(c.Buffer())
		}
	}

	return merged
}

// Grid implements 12 columns system.
// A simple example:
/*
   import ui "github.com/gizak/termui"
   // init and create widgets...

   // build
   ui.Body.AddRows(
       ui.NewRow(
           ui.NewCol(6, 0, widget0),
           ui.NewCol(6, 0, widget1)),
       ui.NewRow(
           ui.NewCol(3, 0, widget2),
           ui.NewCol(3, 0, widget30, widget31, widget32),
           ui.NewCol(6, 0, widget4)))

   // calculate layout
   ui.Body.Align()

   ui.Render(ui.Body)
*/
type Grid struct {
	Rows    []*Row
	Width   int
	X       int
	Y       int
	BgColor Attribute
}

// NewGrid returns *Grid with given rows.
func NewGrid(rows ...*Row) *Grid {
	return &Grid{Rows: rows}
}

// AddRows appends given rows to Grid.
func (g *Grid) AddRows(rs ...*Row) {
	g.Rows = append(g.Rows, rs...)
}

// NewRow creates a new row out of given columns.
func NewRow(cols ...*Row) *Row {
	rs := &Row{Span: 12, Cols: cols}
	return rs
}

// NewCol accepts: widgets are LayoutBufferer or widgets is A NewRow.
// Note that if multiple widgets are provided, they will stack up in the col.
func NewCol(span, offset int, widgets ...GridBufferer) *Row {
	r := &Row{Span: span, Offset: offset}

	if widgets != nil && len(widgets) == 1 {
		wgt := widgets[0]
		nw, isRow := wgt.(*Row)
		if isRow {
			r.Cols = nw.Cols
		} else {
			r.Widget = wgt
		}
		return r
	}

	r.Cols = []*Row{}
	ir := r
	for _, w := range widgets {
		nr := &Row{Span: 12, Widget: w}
		ir.Cols = []*Row{nr}
		ir = nr
	}

	return r
}

// Align calculate each rows' layout.
func (g *Grid) Align() {
	h := 0
	for _, r := range g.Rows {
		r.SetWidth(g.Width)
		r.SetX(g.X)
		r.SetY(g.Y + h)
		r.calcLayout()
		h += r.GetHeight()
	}
}

// Buffer implments Bufferer interface.
func (g Grid) Buffer() Buffer {
	buf := NewBuffer()

	for _, r := range g.Rows {
		buf.Merge(r.Buffer())
	}
	return buf
}

var Body *Grid
<commit_msg>spelling: implements<commit_after>// Copyright 2017 Zack Guo <zack.y.guo@gmail.com>. All rights reserved.
// Use of this source code is governed by a MIT license that can
// be found in the LICENSE file.

package termui

// GridBufferer introduces a Bufferer that can be manipulated by Grid.
type GridBufferer interface {
	Bufferer
	GetHeight() int
	SetWidth(int)
	SetX(int)
	SetY(int)
}

// Row builds a layout tree
type Row struct {
	Cols   []*Row       //children
	Widget GridBufferer // root
	X      int
	Y      int
	Width  int
	Height int
	Span   int
	Offset int
}

// calculate and set the underlying layout tree's x, y, height and width.
func (r *Row) calcLayout() {
	r.assignWidth(r.Width)
	r.Height = r.solveHeight()
	r.assignX(r.X)
	r.assignY(r.Y)
}

// tell if the node is leaf in the tree.
func (r *Row) isLeaf() bool {
	return r.Cols == nil || len(r.Cols) == 0
}

func (r *Row) isRenderableLeaf() bool {
	return r.isLeaf() && r.Widget != nil
}

// assign widgets' (and their parent rows') width recursively.
func (r *Row) assignWidth(w int) {
	r.SetWidth(w)

	accW := 0                            // acc span and offset
	calcW := make([]int, len(r.Cols))    // calculated width
	calcOftX := make([]int, len(r.Cols)) // computed start position of x

	for i, c := range r.Cols {
		accW += c.Span + c.Offset
		cw := int(float64(c.Span*r.Width) / 12.0)

		if i >= 1 {
			calcOftX[i] = calcOftX[i-1] +
				calcW[i-1] +
				int(float64(r.Cols[i-1].Offset*r.Width)/12.0)
		}

		// use up the space if it is the last col
		if i == len(r.Cols)-1 && accW == 12 {
			cw = r.Width - calcOftX[i]
		}
		calcW[i] = cw
		r.Cols[i].assignWidth(cw)
	}
}

// bottom up calc and set rows' (and their widgets') height,
// return r's total height.
func (r *Row) solveHeight() int {
	if r.isRenderableLeaf() {
		r.Height = r.Widget.GetHeight()
		return r.Widget.GetHeight()
	}

	maxh := 0
	if !r.isLeaf() {
		for _, c := range r.Cols {
			nh := c.solveHeight()
			// when embed rows in Cols, row widgets stack up
			if r.Widget != nil {
				nh += r.Widget.GetHeight()
			}
			if nh > maxh {
				maxh = nh
			}
		}
	}

	r.Height = maxh
	return maxh
}

// recursively assign x position for r tree.
func (r *Row) assignX(x int) {
	r.SetX(x)

	if !r.isLeaf() {
		acc := 0
		for i, c := range r.Cols {
			if c.Offset != 0 {
				acc += int(float64(c.Offset*r.Width) / 12.0)
			}
			r.Cols[i].assignX(x + acc)
			acc += c.Width
		}
	}
}

// recursively assign y position to r.
func (r *Row) assignY(y int) {
	r.SetY(y)

	if r.isLeaf() {
		return
	}

	for i := range r.Cols {
		acc := 0
		if r.Widget != nil {
			acc = r.Widget.GetHeight()
		}
		r.Cols[i].assignY(y + acc)
	}

}

// GetHeight implements GridBufferer interface.
func (r Row) GetHeight() int {
	return r.Height
}

// SetX implements GridBufferer interface.
func (r *Row) SetX(x int) {
	r.X = x
	if r.Widget != nil {
		r.Widget.SetX(x)
	}
}

// SetY implements GridBufferer interface.
func (r *Row) SetY(y int) {
	r.Y = y
	if r.Widget != nil {
		r.Widget.SetY(y)
	}
}

// SetWidth implements GridBufferer interface.
func (r *Row) SetWidth(w int) {
	r.Width = w
	if r.Widget != nil {
		r.Widget.SetWidth(w)
	}
}

// Buffer implements Bufferer interface,
// recursively merge all widgets buffer
func (r *Row) Buffer() Buffer {
	merged := NewBuffer()

	if r.isRenderableLeaf() {
		return r.Widget.Buffer()
	}

	// for those are not leaves but have a renderable widget
	if r.Widget != nil {
		merged.Merge(r.Widget.Buffer())
	}

	// collect buffer from children
	if !r.isLeaf() {
		for _, c := range r.Cols {
			merged.Merge(c.Buffer())
		}
	}

	return merged
}

// Grid implements 12 columns system.
// A simple example:
/*
   import ui "github.com/gizak/termui"
   // init and create widgets...

   // build
   ui.Body.AddRows(
       ui.NewRow(
           ui.NewCol(6, 0, widget0),
           ui.NewCol(6, 0, widget1)),
       ui.NewRow(
           ui.NewCol(3, 0, widget2),
           ui.NewCol(3, 0, widget30, widget31, widget32),
           ui.NewCol(6, 0, widget4)))

   // calculate layout
   ui.Body.Align()

   ui.Render(ui.Body)
*/
type Grid struct {
	Rows    []*Row
	Width   int
	X       int
	Y       int
	BgColor Attribute
}

// NewGrid returns *Grid with given rows.
func NewGrid(rows ...*Row) *Grid {
	return &Grid{Rows: rows}
}

// AddRows appends given rows to Grid.
func (g *Grid) AddRows(rs ...*Row) {
	g.Rows = append(g.Rows, rs...)
}

// NewRow creates a new row out of given columns.
func NewRow(cols ...*Row) *Row {
	rs := &Row{Span: 12, Cols: cols}
	return rs
}

// NewCol accepts: widgets are LayoutBufferer or widgets is A NewRow.
// Note that if multiple widgets are provided, they will stack up in the col.
func NewCol(span, offset int, widgets ...GridBufferer) *Row {
	r := &Row{Span: span, Offset: offset}

	if widgets != nil && len(widgets) == 1 {
		wgt := widgets[0]
		nw, isRow := wgt.(*Row)
		if isRow {
			r.Cols = nw.Cols
		} else {
			r.Widget = wgt
		}
		return r
	}

	r.Cols = []*Row{}
	ir := r
	for _, w := range widgets {
		nr := &Row{Span: 12, Widget: w}
		ir.Cols = []*Row{nr}
		ir = nr
	}

	return r
}

// Align calculate each rows' layout.
func (g *Grid) Align() {
	h := 0
	for _, r := range g.Rows {
		r.SetWidth(g.Width)
		r.SetX(g.X)
		r.SetY(g.Y + h)
		r.calcLayout()
		h += r.GetHeight()
	}
}

// Buffer implements Bufferer interface.
func (g Grid) Buffer() Buffer {
	buf := NewBuffer()

	for _, r := range g.Rows {
		buf.Merge(r.Buffer())
	}
	return buf
}

var Body *Grid
<|endoftext|>


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

// Package htmlmin minifies HTML.
package htmlmin

import (
	"bytes"
	"io"

	"code.google.com/p/go.net/html"
	"github.com/dchest/cssmin"
	"github.com/dchest/jsmin"
)

type Options struct {
	MinifyScripts bool // if true, use jsmin to minify contents of script tags.
	MinifyStyles  bool // if true, use cssmin to minify contents of style tags and inline styles.
}

var DefaultOptions = &Options{
	MinifyScripts: false,
	MinifyStyles:  false,
}

var FullOptions = &Options{
	MinifyScripts: true,
	MinifyStyles:  true,
}

// Minify returns minified version of the given HTML data.
// If passed options is nil, uses default options.
func Minify(data []byte, options *Options) (out []byte, err error) {
	if options == nil {
		options = DefaultOptions
	}
	var b bytes.Buffer
	z := html.NewTokenizer(bytes.NewReader(data))
	raw := false
	javascript := false
	style := false
	for {
		tt := z.Next()
		switch tt {
		case html.ErrorToken:
			err := z.Err()
			if err == io.EOF {
				return b.Bytes(), nil
			}
			return nil, err
		case html.StartTagToken, html.SelfClosingTagToken:
			tagName, hasAttr := z.TagName()
			switch string(tagName) {
			case "script":
				javascript = true
				raw = true
			case "style":
				style = true
				raw = true
			case "pre", "code", "textarea":
				raw = true
			default:
				raw = false
			}
			b.WriteByte('<')
			b.Write(tagName)
			var k, v []byte
			isFirst := true
			for hasAttr {
				k, v, hasAttr = z.TagAttr()
				if javascript && string(k) == "type" && string(v) != "text/javascript" {
					javascript = false
				}
				if string(k) == "style" && options.MinifyStyles {
					v = []byte("a{" + string(v) + "}") // simulate "full" CSS
					v = cssmin.Minify(v)
					v = v[2 : len(v)-1] // strip simulation
				}
				if isFirst {
					b.WriteByte(' ')
					isFirst = false
				}
				b.Write(k)
				b.WriteByte('=')
				if quoteChar := valueQuoteChar(v); quoteChar != 0 {
					// Quoted value.
					b.WriteByte(quoteChar)
					b.WriteString(html.EscapeString(string(v)))
					b.WriteByte(quoteChar)
				} else {
					// Unquoted value.
					b.Write(v)
				}
				if hasAttr {
					b.WriteByte(' ')
				}
			}
			b.WriteByte('>')
		case html.EndTagToken:
			tagName, _ := z.TagName()
			raw = false
			if javascript && string(tagName) == "script" {
				javascript = false
			}
			if style && string(tagName) == "style" {
				style = false
			}
			b.Write([]byte("</"))
			b.Write(tagName)
			b.WriteByte('>')
		case html.CommentToken:
			if bytes.Contains(z.Raw(), []byte("<!--[if")) {
				// IE conditional comment, preserve.
				b.Write(z.Raw())
			}
			// ... otherwise, skip.
		case html.TextToken:
			if javascript && options.MinifyScripts {
				min, err := jsmin.Minify(z.Raw())
				if err != nil {
					// Just write it as is.
					b.Write(z.Raw())
				} else {
					b.Write(min)
				}
			} else if style && options.MinifyStyles {
				b.Write(cssmin.Minify(z.Raw()))
			} else if raw {
				b.Write(z.Raw())
			} else {
				b.Write(trimTextToken(z.Raw()))
			}
		default:
			b.Write(z.Raw())
		}

	}
}

func trimTextToken(b []byte) (out []byte) {
	out = make([]byte, 0)
	seenSpace := false
	for _, c := range b {
		switch c {
		case ' ', '\n', '\r', '\t':
			if !seenSpace {
				out = append(out, c)
				seenSpace = true
			}
		default:
			out = append(out, c)
			seenSpace = false
		}
	}
	return out
}

func valueQuoteChar(b []byte) byte {
	if len(b) == 0 || bytes.IndexAny(b, "'`=<> \n\r\t\b") != -1 {
		return '"' // quote with quote mark
	}
	if bytes.IndexByte(b, '"') != -1 {
		return '\'' // quote with apostrophe
	}
	return 0 // do not quote
}
<commit_msg>Preserve comments that start with <!--//<commit_after>// Copyright 2013 Dmitry Chestnykh. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// Package htmlmin minifies HTML.
package htmlmin

import (
	"bytes"
	"io"

	"code.google.com/p/go.net/html"
	"github.com/dchest/cssmin"
	"github.com/dchest/jsmin"
)

type Options struct {
	MinifyScripts bool // if true, use jsmin to minify contents of script tags.
	MinifyStyles  bool // if true, use cssmin to minify contents of style tags and inline styles.
}

var DefaultOptions = &Options{
	MinifyScripts: false,
	MinifyStyles:  false,
}

var FullOptions = &Options{
	MinifyScripts: true,
	MinifyStyles:  true,
}

// Minify returns minified version of the given HTML data.
// If passed options is nil, uses default options.
func Minify(data []byte, options *Options) (out []byte, err error) {
	if options == nil {
		options = DefaultOptions
	}
	var b bytes.Buffer
	z := html.NewTokenizer(bytes.NewReader(data))
	raw := false
	javascript := false
	style := false
	for {
		tt := z.Next()
		switch tt {
		case html.ErrorToken:
			err := z.Err()
			if err == io.EOF {
				return b.Bytes(), nil
			}
			return nil, err
		case html.StartTagToken, html.SelfClosingTagToken:
			tagName, hasAttr := z.TagName()
			switch string(tagName) {
			case "script":
				javascript = true
				raw = true
			case "style":
				style = true
				raw = true
			case "pre", "code", "textarea":
				raw = true
			default:
				raw = false
			}
			b.WriteByte('<')
			b.Write(tagName)
			var k, v []byte
			isFirst := true
			for hasAttr {
				k, v, hasAttr = z.TagAttr()
				if javascript && string(k) == "type" && string(v) != "text/javascript" {
					javascript = false
				}
				if string(k) == "style" && options.MinifyStyles {
					v = []byte("a{" + string(v) + "}") // simulate "full" CSS
					v = cssmin.Minify(v)
					v = v[2 : len(v)-1] // strip simulation
				}
				if isFirst {
					b.WriteByte(' ')
					isFirst = false
				}
				b.Write(k)
				b.WriteByte('=')
				if quoteChar := valueQuoteChar(v); quoteChar != 0 {
					// Quoted value.
					b.WriteByte(quoteChar)
					b.WriteString(html.EscapeString(string(v)))
					b.WriteByte(quoteChar)
				} else {
					// Unquoted value.
					b.Write(v)
				}
				if hasAttr {
					b.WriteByte(' ')
				}
			}
			b.WriteByte('>')
		case html.EndTagToken:
			tagName, _ := z.TagName()
			raw = false
			if javascript && string(tagName) == "script" {
				javascript = false
			}
			if style && string(tagName) == "style" {
				style = false
			}
			b.Write([]byte("</"))
			b.Write(tagName)
			b.WriteByte('>')
		case html.CommentToken:
			if bytes.HasPrefix(z.Raw(), []byte("<!--[if")) ||
			   bytes.HasPrefix(z.Raw(), []byte("<!--//")) {
				// Preserve IE conditional and special style comments.
				b.Write(z.Raw())
			}
			// ... otherwise, skip.
		case html.TextToken:
			if javascript && options.MinifyScripts {
				min, err := jsmin.Minify(z.Raw())
				if err != nil {
					// Just write it as is.
					b.Write(z.Raw())
				} else {
					b.Write(min)
				}
			} else if style && options.MinifyStyles {
				b.Write(cssmin.Minify(z.Raw()))
			} else if raw {
				b.Write(z.Raw())
			} else {
				b.Write(trimTextToken(z.Raw()))
			}
		default:
			b.Write(z.Raw())
		}

	}
}

func trimTextToken(b []byte) (out []byte) {
	out = make([]byte, 0)
	seenSpace := false
	for _, c := range b {
		switch c {
		case ' ', '\n', '\r', '\t':
			if !seenSpace {
				out = append(out, c)
				seenSpace = true
			}
		default:
			out = append(out, c)
			seenSpace = false
		}
	}
	return out
}

func valueQuoteChar(b []byte) byte {
	if len(b) == 0 || bytes.IndexAny(b, "'`=<> \n\r\t\b") != -1 {
		return '"' // quote with quote mark
	}
	if bytes.IndexByte(b, '"') != -1 {
		return '\'' // quote with apostrophe
	}
	return 0 // do not quote
}
<|endoftext|>


<commit_before>// +build !without_qemu

/*
 * This file is part of the libvirt-go project
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 *
 * Copyright (c) 2013 Alex Zorin
 * Copyright (C) 2016 Red Hat, Inc.
 *
 */

package libvirt

/*
#cgo pkg-config: libvirt
// Can't rely on pkg-config for libvirt-qemu since it was not
// installed until 2.6.0 onwards
#cgo LDFLAGS: -lvirt-qemu
#include <libvirt/libvirt.h>
#include <libvirt/libvirt-qemu.h>
#include <libvirt/virterror.h>
#include <stdlib.h>
#include "qemu_compat.h"
*/
import "C"

import (
	"unsafe"
)

/*
 * QMP has two different kinds of ways to talk to QEMU. One is legacy (HMP,
 * or 'human' monitor protocol. The default is QMP, which is all-JSON.
 *
 * QMP json commands are of the format:
 * 	{"execute" : "query-cpus"}
 *
 * whereas the same command in 'HMP' would be:
 *	'info cpus'
 */

type DomainQemuMonitorCommandFlags int

const (
	DOMAIN_QEMU_MONITOR_COMMAND_DEFAULT = DomainQemuMonitorCommandFlags(C.VIR_DOMAIN_QEMU_MONITOR_COMMAND_DEFAULT)
	DOMAIN_QEMU_MONITOR_COMMAND_HMP     = DomainQemuMonitorCommandFlags(C.VIR_DOMAIN_QEMU_MONITOR_COMMAND_HMP)
)

type DomainQemuAgentCommandTimeout int

const (
	DOMAIN_QEMU_AGENT_COMMAND_MIN      = DomainQemuAgentCommandTimeout(C.VIR_DOMAIN_QEMU_AGENT_COMMAND_MIN)
	DOMAIN_QEMU_AGENT_COMMAND_BLOCK    = DomainQemuAgentCommandTimeout(C.VIR_DOMAIN_QEMU_AGENT_COMMAND_BLOCK)
	DOMAIN_QEMU_AGENT_COMMAND_DEFAULT  = DomainQemuAgentCommandTimeout(C.VIR_DOMAIN_QEMU_AGENT_COMMAND_DEFAULT)
	DOMAIN_QEMU_AGENT_COMMAND_NOWAIT   = DomainQemuAgentCommandTimeout(C.VIR_DOMAIN_QEMU_AGENT_COMMAND_NOWAIT)
	DOMAIN_QEMU_AGENT_COMMAND_SHUTDOWN = DomainQemuAgentCommandTimeout(C.VIR_DOMAIN_QEMU_AGENT_COMMAND_SHUTDOWN)
)

func (d *Domain) QemuMonitorCommand(command string, flags DomainQemuMonitorCommandFlags) (string, error) {
	var cResult *C.char
	cCommand := C.CString(command)
	defer C.free(unsafe.Pointer(cCommand))
	result := C.virDomainQemuMonitorCommand(d.ptr, cCommand, &cResult, C.uint(flags))

	if result != 0 {
		return "", GetLastError()
	}

	rstring := C.GoString(cResult)
	C.free(unsafe.Pointer(cResult))
	return rstring, nil
}

func (d *Domain) QemuAgentCommand(command string, timeout DomainQemuAgentCommandTimeout, flags uint32) (string, error) {
	cCommand := C.CString(command)
	defer C.free(unsafe.Pointer(cCommand))
	result := C.virDomainQemuAgentCommand(d.ptr, cCommand, C.int(timeout), C.uint(flags))

	if result == nil {
		return "", GetLastError()
	}

	rstring := C.GoString(result)
	C.free(unsafe.Pointer(result))
	return rstring, nil
}
<commit_msg>Add binding for virDomainQemuAttach<commit_after>// +build !without_qemu

/*
 * This file is part of the libvirt-go project
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 *
 * Copyright (c) 2013 Alex Zorin
 * Copyright (C) 2016 Red Hat, Inc.
 *
 */

package libvirt

/*
#cgo pkg-config: libvirt
// Can't rely on pkg-config for libvirt-qemu since it was not
// installed until 2.6.0 onwards
#cgo LDFLAGS: -lvirt-qemu
#include <libvirt/libvirt.h>
#include <libvirt/libvirt-qemu.h>
#include <libvirt/virterror.h>
#include <stdlib.h>
#include "qemu_compat.h"
*/
import "C"

import (
	"unsafe"
)

/*
 * QMP has two different kinds of ways to talk to QEMU. One is legacy (HMP,
 * or 'human' monitor protocol. The default is QMP, which is all-JSON.
 *
 * QMP json commands are of the format:
 * 	{"execute" : "query-cpus"}
 *
 * whereas the same command in 'HMP' would be:
 *	'info cpus'
 */

type DomainQemuMonitorCommandFlags int

const (
	DOMAIN_QEMU_MONITOR_COMMAND_DEFAULT = DomainQemuMonitorCommandFlags(C.VIR_DOMAIN_QEMU_MONITOR_COMMAND_DEFAULT)
	DOMAIN_QEMU_MONITOR_COMMAND_HMP     = DomainQemuMonitorCommandFlags(C.VIR_DOMAIN_QEMU_MONITOR_COMMAND_HMP)
)

type DomainQemuAgentCommandTimeout int

const (
	DOMAIN_QEMU_AGENT_COMMAND_MIN      = DomainQemuAgentCommandTimeout(C.VIR_DOMAIN_QEMU_AGENT_COMMAND_MIN)
	DOMAIN_QEMU_AGENT_COMMAND_BLOCK    = DomainQemuAgentCommandTimeout(C.VIR_DOMAIN_QEMU_AGENT_COMMAND_BLOCK)
	DOMAIN_QEMU_AGENT_COMMAND_DEFAULT  = DomainQemuAgentCommandTimeout(C.VIR_DOMAIN_QEMU_AGENT_COMMAND_DEFAULT)
	DOMAIN_QEMU_AGENT_COMMAND_NOWAIT   = DomainQemuAgentCommandTimeout(C.VIR_DOMAIN_QEMU_AGENT_COMMAND_NOWAIT)
	DOMAIN_QEMU_AGENT_COMMAND_SHUTDOWN = DomainQemuAgentCommandTimeout(C.VIR_DOMAIN_QEMU_AGENT_COMMAND_SHUTDOWN)
)

func (d *Domain) QemuMonitorCommand(command string, flags DomainQemuMonitorCommandFlags) (string, error) {
	var cResult *C.char
	cCommand := C.CString(command)
	defer C.free(unsafe.Pointer(cCommand))
	result := C.virDomainQemuMonitorCommand(d.ptr, cCommand, &cResult, C.uint(flags))

	if result != 0 {
		return "", GetLastError()
	}

	rstring := C.GoString(cResult)
	C.free(unsafe.Pointer(cResult))
	return rstring, nil
}

func (d *Domain) QemuAgentCommand(command string, timeout DomainQemuAgentCommandTimeout, flags uint32) (string, error) {
	cCommand := C.CString(command)
	defer C.free(unsafe.Pointer(cCommand))
	result := C.virDomainQemuAgentCommand(d.ptr, cCommand, C.int(timeout), C.uint(flags))

	if result == nil {
		return "", GetLastError()
	}

	rstring := C.GoString(result)
	C.free(unsafe.Pointer(result))
	return rstring, nil
}

func (c *Connect) DomainQemuAttach(pid uint32, flags uint32) (*Domain, error) {

	ptr := C.virDomainQemuAttach(c.ptr, C.uint(pid), C.uint(flags))
	if ptr == nil {
		return nil, GetLastError()
	}
	return &Domain{ptr: ptr}, nil
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"github.com/microcosm-cc/bluemonday"
	"math/rand"
	"net/http"
	"strconv"
	"time"
)

func user_name(post_time time.Time, user_id uint64, post_id uint64) string {
	return "test_name"
	/*rand.Seed(post_time.UnixNano() ^ int64(names_seed) ^ int64(user_id) ^ int64(post_id))
	return adjectives[rand.Intn(len(adjectives))] +
		colours[rand.Intn(len(colours))] +
		animals[rand.Intn(len(animals))]*/
}

func preview(w http.ResponseWriter, r *http.Request, user_id uint64) {
	html_san, _ := render_text(r.FormValue("text"), false)
	var input struct {
		Parent    Post
		Child     Comment
		Markdown  string
		Parent_id uint64
		Post_id   uint64
	}
	post_id, post_err := strconv.ParseUint(r.FormValue("post_id"), 10, 64)
	parent_id, parent_err := strconv.ParseUint(r.FormValue("parent_id"), 10, 64)
	if post_err == nil && parent_err == nil {
		parent_comment, _ := view_comment(post_id, parent_id)
		input.Parent = Post{
			ID:       parent_comment.ID,
			Time:     parent_comment.Time,
			Value:    parent_comment.Value,
			Username: parent_comment.Username,
			Html:     parent_comment.Html,
		}
	} else if post_err == nil {
		input.Parent, _ = view_post(post_id)
	} else {
		input.Parent = Post{}
	}
	input.Child = Comment{
		Html:     html_san,
		Username: user_name(input.Parent.Time, user_id, input.Parent.Rand),
		Time:     time.Now(),
	}
	input.Markdown = r.FormValue("text")
	input.Parent_id = parent_id
	input.Post_id = post_id
	err = templates["preview"].Execute(w, Page{
		Content: input,
	})
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
}

func submit_post(w http.ResponseWriter, r *http.Request, user_id uint64) {
	html_san, title := render_text(r.FormValue("text"), true)
	snippet := bluemonday.StrictPolicy().Sanitize(string(html_san))
	snip_length := 200
	if len(snippet) > snip_length {
		snippet = snippet[:snip_length]
	}
	post := Post{
		Title:   title,
		Snippet: snippet,
		Time:    time.Now(),
		Value:   0,
		Html:    html_san,
		Rand:    rand.Uint64(),
	}
	post.Username = user_name(post.Time, user_id, post.Rand)
	post_id := insert_post(post)
	http.Redirect(w, r, fmt.Sprintf("/post/%d", post_id), http.StatusSeeOther)
}

func submit_comment(w http.ResponseWriter, r *http.Request, user_id uint64) {
	html_san, _ := render_text(r.FormValue("text"), false)
	post_id, err := strconv.ParseUint(r.FormValue("post_id"), 10, 64)
	if err != nil {
		http.NotFound(w, r)
		return
	}
	comment := Comment{
		Time:  time.Now(),
		Value: 0,
		Html:  html_san,
	}
	post, _ := view_post(post_id)
	comment.Username = user_name(post.Time, user_id, post.Rand)
	parent_id, err := strconv.ParseUint(r.FormValue("parent_id"), 10, 64)
	insert_comment(post_id, parent_id, comment)
	http.Redirect(w, r, fmt.Sprintf("/post/%d#%d", post_id, comment.ID), http.StatusSeeOther)
}
<commit_msg>re-add names<commit_after>package main

import (
	"fmt"
	"github.com/microcosm-cc/bluemonday"
	"math/rand"
	"net/http"
	"strconv"
	"time"
)

func user_name(post_time time.Time, user_id uint64, post_id uint64) string {
	rand.Seed(post_time.UnixNano() ^ int64(names_salt) ^ int64(user_id) ^ int64(post_id))
	return adjectives[rand.Intn(len(adjectives))] +
		colours[rand.Intn(len(colours))] +
		plants[rand.Intn(len(plants))]
}

func preview(w http.ResponseWriter, r *http.Request, user_id uint64) {
	html_san, _ := render_text(r.FormValue("text"), false)
	var input struct {
		Parent    Post
		Child     Comment
		Markdown  string
		Parent_id uint64
		Post_id   uint64
	}
	post_id, post_err := strconv.ParseUint(r.FormValue("post_id"), 10, 64)
	parent_id, parent_err := strconv.ParseUint(r.FormValue("parent_id"), 10, 64)
	if post_err == nil && parent_err == nil {
		parent_comment, _ := view_comment(post_id, parent_id)
		input.Parent = Post{
			ID:       parent_comment.ID,
			Time:     parent_comment.Time,
			Value:    parent_comment.Value,
			Username: parent_comment.Username,
			Html:     parent_comment.Html,
		}
	} else if post_err == nil {
		input.Parent, _ = view_post(post_id)
	} else {
		input.Parent = Post{}
	}
	input.Child = Comment{
		Html:     html_san,
		Username: user_name(input.Parent.Time, user_id, input.Parent.Rand),
		Time:     time.Now(),
	}
	input.Markdown = r.FormValue("text")
	input.Parent_id = parent_id
	input.Post_id = post_id
	err = templates["preview"].Execute(w, Page{
		Content: input,
	})
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
}

func submit_post(w http.ResponseWriter, r *http.Request, user_id uint64) {
	html_san, title := render_text(r.FormValue("text"), true)
	snippet := bluemonday.StrictPolicy().Sanitize(string(html_san))
	snip_length := 200
	if len(snippet) > snip_length {
		snippet = snippet[:snip_length]
	}
	post := Post{
		Title:   title,
		Snippet: snippet,
		Time:    time.Now(),
		Value:   0,
		Html:    html_san,
		Rand:    rand.Uint64(),
	}
	post.Username = user_name(post.Time, user_id, post.Rand)
	post_id := insert_post(post)
	http.Redirect(w, r, fmt.Sprintf("/post/%d", post_id), http.StatusSeeOther)
}

func submit_comment(w http.ResponseWriter, r *http.Request, user_id uint64) {
	html_san, _ := render_text(r.FormValue("text"), false)
	post_id, err := strconv.ParseUint(r.FormValue("post_id"), 10, 64)
	if err != nil {
		http.NotFound(w, r)
		return
	}
	comment := Comment{
		Time:  time.Now(),
		Value: 0,
		Html:  html_san,
	}
	post, _ := view_post(post_id)
	comment.Username = user_name(post.Time, user_id, post.Rand)
	parent_id, err := strconv.ParseUint(r.FormValue("parent_id"), 10, 64)
	insert_comment(post_id, parent_id, comment)
	http.Redirect(w, r, fmt.Sprintf("/post/%d#%d", post_id, comment.ID), http.StatusSeeOther)
}
<|endoftext|>