<commit_before>package mesh

import (
	"bytes"
	"encoding/gob"
	"fmt"
	"math"
	"net"
	"sync"
	"time"
)

var (
	// Port is the port used for all mesh communication.
	Port = 6783

	// ChannelSize is the buffer size used by so-called actor goroutines
	// throughout mesh.
	ChannelSize = 16

	defaultGossipInterval = 30 * time.Second
)

const (
	tcpHeartbeat     = 30 * time.Second
	maxDuration      = time.Duration(math.MaxInt64)
	acceptMaxTokens  = 100
	acceptTokenDelay = 100 * time.Millisecond // [2]
)

// Config defines dimensions of configuration for the router.
// TODO(pb): provide usable defaults in NewRouter
type Config struct {
	Host               string
	Port               int
	Password           []byte
	ConnLimit          int
	ProtocolMinVersion byte
	PeerDiscovery      bool
	TrustedSubnets     []*net.IPNet
	GossipInterval     *time.Duration
}

// Router manages communication between this peer and the rest of the mesh.
// Router implements Gossiper.
type Router struct {
	Config
	Overlay         Overlay
	Ourself         *localPeer
	Peers           *Peers
	Routes          *routes
	ConnectionMaker *connectionMaker
	gossipLock      sync.RWMutex
	gossipChannels  gossipChannels
	topologyGossip  Gossip
	acceptLimiter   *tokenBucket
	logger          Logger
}

// NewRouter returns a new router. It must be started.
func NewRouter(config Config, name PeerName, nickName string, overlay Overlay, logger Logger) (*Router, error) {
	router := &Router{Config: config, gossipChannels: make(gossipChannels)}

	if overlay == nil {
		overlay = NullOverlay{}
	}

	router.Overlay = overlay
	router.Ourself = newLocalPeer(name, nickName, router)
	router.Peers = newPeers(router.Ourself)
	router.Peers.OnGC(func(peer *Peer) {
		logger.Printf("Removed unreachable peer %s", peer)
	})
	router.Routes = newRoutes(router.Ourself, router.Peers)
	router.ConnectionMaker = newConnectionMaker(router.Ourself, router.Peers, net.JoinHostPort(router.Host, "0"), router.Port, router.PeerDiscovery, logger)
	router.logger = logger
	gossip, err := router.NewGossip("topology", router)
	if err != nil {
		return nil, err
	}
	router.topologyGossip = gossip
	router.acceptLimiter = newTokenBucket(acceptMaxTokens, acceptTokenDelay)
	return router, nil
}

// Start listening for TCP connections. This is separate from NewRouter so
// that gossipers can register before we start forming connections.
func (router *Router) Start() {
	router.listenTCP()
}

// Stop shuts down the router.
func (router *Router) Stop() error {
	router.Overlay.Stop()
	// TODO: perform more graceful shutdown...
	return nil
}

func (router *Router) usingPassword() bool {
	return router.Password != nil
}

func (router *Router) listenTCP() {
	localAddr, err := net.ResolveTCPAddr("tcp", net.JoinHostPort(router.Host, fmt.Sprint(router.Port)))
	if err != nil {
		panic(err)
	}
	ln, err := net.ListenTCP("tcp", localAddr)
	if err != nil {
		panic(err)
	}
	go func() {
		defer ln.Close()
		for {
			tcpConn, err := ln.AcceptTCP()
			if err != nil {
				router.logger.Printf("%v", err)
				continue
			}
			router.acceptTCP(tcpConn)
			router.acceptLimiter.wait()
		}
	}()
}

func (router *Router) acceptTCP(tcpConn *net.TCPConn) {
	remoteAddrStr := tcpConn.RemoteAddr().String()
	router.logger.Printf("->[%s] connection accepted", remoteAddrStr)
	connRemote := newRemoteConnection(router.Ourself.Peer, nil, remoteAddrStr, false, false)
	startLocalConnection(connRemote, tcpConn, router, true, router.logger)
}

// NewGossip returns a usable GossipChannel from the router.
//
// TODO(pb): rename?
func (router *Router) NewGossip(channelName string, g Gossiper) (Gossip, error) {
	channel := newGossipChannel(channelName, router.Ourself, router.Routes, g, router.logger)
	router.gossipLock.Lock()
	defer router.gossipLock.Unlock()
	if _, found := router.gossipChannels[channelName]; found {
		return nil, fmt.Errorf("[gossip] duplicate channel %s", channelName)
	}
	router.gossipChannels[channelName] = channel
	return channel, nil
}

func (router *Router) gossipChannel(channelName string) *gossipChannel {
	router.gossipLock.RLock()
	channel, found := router.gossipChannels[channelName]
	router.gossipLock.RUnlock()
	if found {
		return channel
	}
	router.gossipLock.Lock()
	defer router.gossipLock.Unlock()
	if channel, found = router.gossipChannels[channelName]; found {
		return channel
	}
	channel = newGossipChannel(channelName, router.Ourself, router.Routes, &surrogateGossiper{router: router}, router.logger)
	channel.logf("created surrogate channel")
	router.gossipChannels[channelName] = channel
	return channel
}

func (router *Router) gossipChannelSet() map[*gossipChannel]struct{} {
	channels := make(map[*gossipChannel]struct{})
	router.gossipLock.RLock()
	defer router.gossipLock.RUnlock()
	for _, channel := range router.gossipChannels {
		channels[channel] = struct{}{}
	}
	return channels
}

func (router *Router) gossipInterval() time.Duration {
	if router.Config.GossipInterval != nil {
		return *router.Config.GossipInterval
	} else {
		return defaultGossipInterval
	}
}

func (router *Router) handleGossip(tag protocolTag, payload []byte) error {
	decoder := gob.NewDecoder(bytes.NewReader(payload))
	var channelName string
	if err := decoder.Decode(&channelName); err != nil {
		return err
	}
	channel := router.gossipChannel(channelName)
	var srcName PeerName
	if err := decoder.Decode(&srcName); err != nil {
		return err
	}
	switch tag {
	case ProtocolGossipUnicast:
		return channel.deliverUnicast(srcName, payload, decoder)
	case ProtocolGossipBroadcast:
		return channel.deliverBroadcast(srcName, payload, decoder)
	case ProtocolGossip:
		return channel.deliver(srcName, payload, decoder)
	}
	return nil
}

// Relay all pending gossip data for each channel via random neighbours.
func (router *Router) sendAllGossip() {
	for channel := range router.gossipChannelSet() {
		if gossip := channel.gossiper.Gossip(); gossip != nil {
			channel.Send(gossip)
		}
	}
}

// Relay all pending gossip data for each channel via conn.
func (router *Router) sendAllGossipDown(conn Connection) {
	for channel := range router.gossipChannelSet() {
		if gossip := channel.gossiper.Gossip(); gossip != nil {
			channel.SendDown(conn, gossip)
		}
	}
}

// for testing
func (router *Router) sendPendingGossip() bool {
	sentSomething := false
	for conn := range router.Ourself.getConnections() {
		sentSomething = conn.(gossipConnection).gossipSenders().Flush() || sentSomething
	}
	return sentSomething
}

// BroadcastTopologyUpdate is invoked whenever there is a change to the mesh
// topology, and broadcasts the new set of peers to the mesh.
func (router *Router) broadcastTopologyUpdate(update peerNameSet) {
	gossipData := &topologyGossipData{peers: router.Peers, update: update}
	router.topologyGossip.GossipNeighbourSubset(gossipData)
}

// OnGossipUnicast implements Gossiper, but always returns an error, as a
// router should only receive gossip broadcasts of TopologyGossipData.
func (router *Router) OnGossipUnicast(sender PeerName, msg []byte) error {
	return fmt.Errorf("unexpected topology gossip unicast: %v", msg)
}

// OnGossipBroadcast receives broadcasts of TopologyGossipData.
// It returns the received update unchanged.
func (router *Router) OnGossipBroadcast(_ PeerName, update []byte) (GossipData, error) {
	origUpdate, _, err := router.applyTopologyUpdate(update)
	if err != nil || len(origUpdate) == 0 {
		return nil, err
	}
	return &topologyGossipData{peers: router.Peers, update: origUpdate}, nil
}

// Gossip yields the current topology as GossipData.
func (router *Router) Gossip() GossipData {
	return &topologyGossipData{peers: router.Peers, update: router.Peers.names()}
}

// OnGossip receives broadcasts of TopologyGossipData.
// It returns an "improved" version of the received update.
// See peers.ApplyUpdate.
func (router *Router) OnGossip(update []byte) (GossipData, error) {
	_, newUpdate, err := router.applyTopologyUpdate(update)
	if err != nil || len(newUpdate) == 0 {
		return nil, err
	}
	return &topologyGossipData{peers: router.Peers, update: newUpdate}, nil
}

func (router *Router) applyTopologyUpdate(update []byte) (peerNameSet, peerNameSet, error) {
	origUpdate, newUpdate, err := router.Peers.applyUpdate(update)
	if err != nil {
		return nil, nil, err
	}
	if len(newUpdate) > 0 {
		router.ConnectionMaker.refresh()
		router.Routes.recalculate()
	}
	return origUpdate, newUpdate, nil
}

func (router *Router) trusts(remote *remoteConnection) bool {
	if tcpAddr, err := net.ResolveTCPAddr("tcp", remote.remoteTCPAddr); err == nil {
		for _, trustedSubnet := range router.TrustedSubnets {
			if trustedSubnet.Contains(tcpAddr.IP) {
				return true
			}
		}
	} else {
		// Should not happen as remoteTCPAddr was obtained from TCPConn
		router.logger.Printf("Unable to parse remote TCP addr: %s", err)
	}
	return false
}

// The set of peers in the mesh network.
// Gossiped just like anything else.
type topologyGossipData struct {
	peers  *Peers
	update peerNameSet
}

// Merge implements GossipData.
func (d *topologyGossipData) Merge(other GossipData) GossipData {
	names := make(peerNameSet)
	for name := range d.update {
		names[name] = struct{}{}
	}
	for name := range other.(*topologyGossipData).update {
		names[name] = struct{}{}
	}
	return &topologyGossipData{peers: d.peers, update: names}
}

// Encode implements GossipData.
func (d *topologyGossipData) Encode() [][]byte {
	return [][]byte{d.peers.encodePeers(d.update)}
}
<commit_msg>Slow down accepting new connections, to reduce peak memory usage<commit_after>package mesh

import (
	"bytes"
	"encoding/gob"
	"fmt"
	"math"
	"net"
	"sync"
	"time"
)

var (
	// Port is the port used for all mesh communication.
	Port = 6783

	// ChannelSize is the buffer size used by so-called actor goroutines
	// throughout mesh.
	ChannelSize = 16

	defaultGossipInterval = 30 * time.Second
)

const (
	tcpHeartbeat     = 30 * time.Second
	maxDuration      = time.Duration(math.MaxInt64)
	acceptMaxTokens  = 20
	acceptTokenDelay = 50 * time.Millisecond
)

// Config defines dimensions of configuration for the router.
// TODO(pb): provide usable defaults in NewRouter
type Config struct {
	Host               string
	Port               int
	Password           []byte
	ConnLimit          int
	ProtocolMinVersion byte
	PeerDiscovery      bool
	TrustedSubnets     []*net.IPNet
	GossipInterval     *time.Duration
}

// Router manages communication between this peer and the rest of the mesh.
// Router implements Gossiper.
type Router struct {
	Config
	Overlay         Overlay
	Ourself         *localPeer
	Peers           *Peers
	Routes          *routes
	ConnectionMaker *connectionMaker
	gossipLock      sync.RWMutex
	gossipChannels  gossipChannels
	topologyGossip  Gossip
	acceptLimiter   *tokenBucket
	logger          Logger
}

// NewRouter returns a new router. It must be started.
func NewRouter(config Config, name PeerName, nickName string, overlay Overlay, logger Logger) (*Router, error) {
	router := &Router{Config: config, gossipChannels: make(gossipChannels)}

	if overlay == nil {
		overlay = NullOverlay{}
	}

	router.Overlay = overlay
	router.Ourself = newLocalPeer(name, nickName, router)
	router.Peers = newPeers(router.Ourself)
	router.Peers.OnGC(func(peer *Peer) {
		logger.Printf("Removed unreachable peer %s", peer)
	})
	router.Routes = newRoutes(router.Ourself, router.Peers)
	router.ConnectionMaker = newConnectionMaker(router.Ourself, router.Peers, net.JoinHostPort(router.Host, "0"), router.Port, router.PeerDiscovery, logger)
	router.logger = logger
	gossip, err := router.NewGossip("topology", router)
	if err != nil {
		return nil, err
	}
	router.topologyGossip = gossip
	router.acceptLimiter = newTokenBucket(acceptMaxTokens, acceptTokenDelay)
	return router, nil
}

// Start listening for TCP connections. This is separate from NewRouter so
// that gossipers can register before we start forming connections.
func (router *Router) Start() {
	router.listenTCP()
}

// Stop shuts down the router.
func (router *Router) Stop() error {
	router.Overlay.Stop()
	// TODO: perform more graceful shutdown...
	return nil
}

func (router *Router) usingPassword() bool {
	return router.Password != nil
}

func (router *Router) listenTCP() {
	localAddr, err := net.ResolveTCPAddr("tcp", net.JoinHostPort(router.Host, fmt.Sprint(router.Port)))
	if err != nil {
		panic(err)
	}
	ln, err := net.ListenTCP("tcp", localAddr)
	if err != nil {
		panic(err)
	}
	go func() {
		defer ln.Close()
		for {
			tcpConn, err := ln.AcceptTCP()
			if err != nil {
				router.logger.Printf("%v", err)
				continue
			}
			router.acceptTCP(tcpConn)
			router.acceptLimiter.wait()
		}
	}()
}

func (router *Router) acceptTCP(tcpConn *net.TCPConn) {
	remoteAddrStr := tcpConn.RemoteAddr().String()
	router.logger.Printf("->[%s] connection accepted", remoteAddrStr)
	connRemote := newRemoteConnection(router.Ourself.Peer, nil, remoteAddrStr, false, false)
	startLocalConnection(connRemote, tcpConn, router, true, router.logger)
}

// NewGossip returns a usable GossipChannel from the router.
//
// TODO(pb): rename?
func (router *Router) NewGossip(channelName string, g Gossiper) (Gossip, error) {
	channel := newGossipChannel(channelName, router.Ourself, router.Routes, g, router.logger)
	router.gossipLock.Lock()
	defer router.gossipLock.Unlock()
	if _, found := router.gossipChannels[channelName]; found {
		return nil, fmt.Errorf("[gossip] duplicate channel %s", channelName)
	}
	router.gossipChannels[channelName] = channel
	return channel, nil
}

func (router *Router) gossipChannel(channelName string) *gossipChannel {
	router.gossipLock.RLock()
	channel, found := router.gossipChannels[channelName]
	router.gossipLock.RUnlock()
	if found {
		return channel
	}
	router.gossipLock.Lock()
	defer router.gossipLock.Unlock()
	if channel, found = router.gossipChannels[channelName]; found {
		return channel
	}
	channel = newGossipChannel(channelName, router.Ourself, router.Routes, &surrogateGossiper{router: router}, router.logger)
	channel.logf("created surrogate channel")
	router.gossipChannels[channelName] = channel
	return channel
}

func (router *Router) gossipChannelSet() map[*gossipChannel]struct{} {
	channels := make(map[*gossipChannel]struct{})
	router.gossipLock.RLock()
	defer router.gossipLock.RUnlock()
	for _, channel := range router.gossipChannels {
		channels[channel] = struct{}{}
	}
	return channels
}

func (router *Router) gossipInterval() time.Duration {
	if router.Config.GossipInterval != nil {
		return *router.Config.GossipInterval
	} else {
		return defaultGossipInterval
	}
}

func (router *Router) handleGossip(tag protocolTag, payload []byte) error {
	decoder := gob.NewDecoder(bytes.NewReader(payload))
	var channelName string
	if err := decoder.Decode(&channelName); err != nil {
		return err
	}
	channel := router.gossipChannel(channelName)
	var srcName PeerName
	if err := decoder.Decode(&srcName); err != nil {
		return err
	}
	switch tag {
	case ProtocolGossipUnicast:
		return channel.deliverUnicast(srcName, payload, decoder)
	case ProtocolGossipBroadcast:
		return channel.deliverBroadcast(srcName, payload, decoder)
	case ProtocolGossip:
		return channel.deliver(srcName, payload, decoder)
	}
	return nil
}

// Relay all pending gossip data for each channel via random neighbours.
func (router *Router) sendAllGossip() {
	for channel := range router.gossipChannelSet() {
		if gossip := channel.gossiper.Gossip(); gossip != nil {
			channel.Send(gossip)
		}
	}
}

// Relay all pending gossip data for each channel via conn.
func (router *Router) sendAllGossipDown(conn Connection) {
	for channel := range router.gossipChannelSet() {
		if gossip := channel.gossiper.Gossip(); gossip != nil {
			channel.SendDown(conn, gossip)
		}
	}
}

// for testing
func (router *Router) sendPendingGossip() bool {
	sentSomething := false
	for conn := range router.Ourself.getConnections() {
		sentSomething = conn.(gossipConnection).gossipSenders().Flush() || sentSomething
	}
	return sentSomething
}

// BroadcastTopologyUpdate is invoked whenever there is a change to the mesh
// topology, and broadcasts the new set of peers to the mesh.
func (router *Router) broadcastTopologyUpdate(update peerNameSet) {
	gossipData := &topologyGossipData{peers: router.Peers, update: update}
	router.topologyGossip.GossipNeighbourSubset(gossipData)
}

// OnGossipUnicast implements Gossiper, but always returns an error, as a
// router should only receive gossip broadcasts of TopologyGossipData.
func (router *Router) OnGossipUnicast(sender PeerName, msg []byte) error {
	return fmt.Errorf("unexpected topology gossip unicast: %v", msg)
}

// OnGossipBroadcast receives broadcasts of TopologyGossipData.
// It returns the received update unchanged.
func (router *Router) OnGossipBroadcast(_ PeerName, update []byte) (GossipData, error) {
	origUpdate, _, err := router.applyTopologyUpdate(update)
	if err != nil || len(origUpdate) == 0 {
		return nil, err
	}
	return &topologyGossipData{peers: router.Peers, update: origUpdate}, nil
}

// Gossip yields the current topology as GossipData.
func (router *Router) Gossip() GossipData {
	return &topologyGossipData{peers: router.Peers, update: router.Peers.names()}
}

// OnGossip receives broadcasts of TopologyGossipData.
// It returns an "improved" version of the received update.
// See peers.ApplyUpdate.
func (router *Router) OnGossip(update []byte) (GossipData, error) {
	_, newUpdate, err := router.applyTopologyUpdate(update)
	if err != nil || len(newUpdate) == 0 {
		return nil, err
	}
	return &topologyGossipData{peers: router.Peers, update: newUpdate}, nil
}

func (router *Router) applyTopologyUpdate(update []byte) (peerNameSet, peerNameSet, error) {
	origUpdate, newUpdate, err := router.Peers.applyUpdate(update)
	if err != nil {
		return nil, nil, err
	}
	if len(newUpdate) > 0 {
		router.ConnectionMaker.refresh()
		router.Routes.recalculate()
	}
	return origUpdate, newUpdate, nil
}

func (router *Router) trusts(remote *remoteConnection) bool {
	if tcpAddr, err := net.ResolveTCPAddr("tcp", remote.remoteTCPAddr); err == nil {
		for _, trustedSubnet := range router.TrustedSubnets {
			if trustedSubnet.Contains(tcpAddr.IP) {
				return true
			}
		}
	} else {
		// Should not happen as remoteTCPAddr was obtained from TCPConn
		router.logger.Printf("Unable to parse remote TCP addr: %s", err)
	}
	return false
}

// The set of peers in the mesh network.
// Gossiped just like anything else.
type topologyGossipData struct {
	peers  *Peers
	update peerNameSet
}

// Merge implements GossipData.
func (d *topologyGossipData) Merge(other GossipData) GossipData {
	names := make(peerNameSet)
	for name := range d.update {
		names[name] = struct{}{}
	}
	for name := range other.(*topologyGossipData).update {
		names[name] = struct{}{}
	}
	return &topologyGossipData{peers: d.peers, update: names}
}

// Encode implements GossipData.
func (d *topologyGossipData) Encode() [][]byte {
	return [][]byte{d.peers.encodePeers(d.update)}
}
<|endoftext|>


<commit_before>package version

import (
	"bytes"
	"fmt"
)

// The git commit that was compiled. This will be filled in by the compiler.
var GitCommit string
var GitDescribe string

// The main version number that is being run at the moment.
const Version = "0.6.0"

// A pre-release marker for the version. If this is "" (empty string)
// then it means that it is a final release. Otherwise, this is a pre-release
// such as "dev" (in development), "beta", "rc1", etc.
const VersionPrerelease = "beta2"

// VersionInfo
type VersionInfo struct {
	Revision          string
	Version           string
	VersionPrerelease string
}

func GetVersion() *VersionInfo {
	ver := Version
	rel := VersionPrerelease
	if GitDescribe != "" {
		ver = GitDescribe
	}
	if GitDescribe == "" && rel == "" && VersionPrerelease != "" {
		rel = "dev"
	}

	return &VersionInfo{
		Revision:          GitCommit,
		Version:           ver,
		VersionPrerelease: rel,
	}
}

func (c *VersionInfo) String() string {
	var versionString bytes.Buffer

	fmt.Fprintf(&versionString, "Vault v%s", c.Version)
	if c.VersionPrerelease != "" {
		fmt.Fprintf(&versionString, "-%s", c.VersionPrerelease)

		if c.Revision != "" {
			fmt.Fprintf(&versionString, " (%s)", c.Revision)
		}
	}

	return versionString.String()
}
<commit_msg>Update version to rc1<commit_after>package version

import (
	"bytes"
	"fmt"
)

// The git commit that was compiled. This will be filled in by the compiler.
var GitCommit string
var GitDescribe string

// The main version number that is being run at the moment.
const Version = "0.6.0"

// A pre-release marker for the version. If this is "" (empty string)
// then it means that it is a final release. Otherwise, this is a pre-release
// such as "dev" (in development), "beta", "rc1", etc.
const VersionPrerelease = "rc1"

// VersionInfo
type VersionInfo struct {
	Revision          string
	Version           string
	VersionPrerelease string
}

func GetVersion() *VersionInfo {
	ver := Version
	rel := VersionPrerelease
	if GitDescribe != "" {
		ver = GitDescribe
	}
	if GitDescribe == "" && rel == "" && VersionPrerelease != "" {
		rel = "dev"
	}

	return &VersionInfo{
		Revision:          GitCommit,
		Version:           ver,
		VersionPrerelease: rel,
	}
}

func (c *VersionInfo) String() string {
	var versionString bytes.Buffer

	fmt.Fprintf(&versionString, "Vault v%s", c.Version)
	if c.VersionPrerelease != "" {
		fmt.Fprintf(&versionString, "-%s", c.VersionPrerelease)

		if c.Revision != "" {
			fmt.Fprintf(&versionString, " (%s)", c.Revision)
		}
	}

	return versionString.String()
}
<|endoftext|>


<commit_before>package bitmapfont

import (
	"errors"
	"image"
	"image/color"
	"image/draw"
	"os"

	log "github.com/Sirupsen/logrus"
	conf "github.com/develed/develed/config"
)

var fontImageTable image.Image
var Config conf.BitmapFont

func Render(text string, text_color color.RGBA, text_bg color.RGBA, char_space int, top_off int) (image.Image, error) {

	fontcolums := fontImageTable.Bounds().Dx() / Config.Width
	frame_width := len(text)*Config.Width + (len(text)-1)*(char_space)
	log.Debug("Frame len in px:", frame_width)

	m := image.NewRGBA(image.Rect(0, 0, frame_width, 9))
	draw.Draw(m, m.Bounds(), &image.Uniform{text_bg}, image.ZP, draw.Src)

	src := &image.Uniform{text_color}

	for n, key := range text {
		col := int(key-' ') % fontcolums
		row := int(key-' ') / fontcolums

		draw.DrawMask(m, image.Rect(n*(Config.Width+char_space), 0,
			Config.Width+n*(Config.Width+char_space), Config.High),
			src, image.ZP, fontImageTable, image.Pt(col*Config.Width, row*Config.High), draw.Over)

		log.Debugf("key: %c off: %v c: %v r: %v", key, int(key-' '), col, row)
	}
	return m, nil
}

func Init(path string, name string, cfg []conf.BitmapFont) error {
	if name == "" {
		name = "font5x7"
	}

	for _, s := range cfg {
		log.Debug("Cerco font ", s.Name, " ", name)
		if name == s.Name {
			Config = s
			log.Debug(path + string(os.PathSeparator) + Config.FileName)
			reader, err := os.Open(path + string(os.PathSeparator) + Config.FileName)
			if err != nil {
				return err
			}
			defer reader.Close()

			// Decode fonts table.
			fontImageTable, _, err = image.Decode(reader)
			if err != nil {
				return err
			}
			return nil
		}
	}

	return errors.New("Wrong BitmatFont name.\n")
}
<commit_msg>bitmapfont: Return font char size for text effects.<commit_after>package bitmapfont

import (
	"errors"
	"image"
	"image/color"
	"image/draw"
	"os"

	log "github.com/Sirupsen/logrus"
	conf "github.com/develed/develed/config"
)

var fontImageTable image.Image
var Config conf.BitmapFont

func Render(text string, text_color color.RGBA, text_bg color.RGBA, char_space int, top_off int) (image.Image, int, error) {

	fontcolums := fontImageTable.Bounds().Dx() / Config.Width
	frame_width := len(text)*Config.Width + (len(text)-1)*(char_space)
	log.Debug("Frame len in px:", frame_width)

	m := image.NewRGBA(image.Rect(0, 0, frame_width, 9))
	draw.Draw(m, m.Bounds(), &image.Uniform{text_bg}, image.ZP, draw.Src)

	src := &image.Uniform{text_color}

	for n, key := range text {
		col := int(key-' ') % fontcolums
		row := int(key-' ') / fontcolums

		draw.DrawMask(m, image.Rect(n*(Config.Width+char_space), 0,
			Config.Width+n*(Config.Width+char_space), Config.High),
			src, image.ZP, fontImageTable, image.Pt(col*Config.Width, row*Config.High), draw.Over)

		//log.Debugf("key: %c off: %v c: %v r: %v", key, int(key-' '), col, row)
	}
	return m, (Config.Width + char_space), nil
}

func Init(path string, name string, cfg []conf.BitmapFont) error {
	if name == "" {
		name = "font5x7"
	}

	for _, s := range cfg {
		log.Debug("Cerco font ", s.Name, " ", name)
		if name == s.Name {
			Config = s
			log.Debug(path + string(os.PathSeparator) + Config.FileName)
			reader, err := os.Open(path + string(os.PathSeparator) + Config.FileName)
			if err != nil {
				return err
			}
			defer reader.Close()

			// Decode fonts table.
			fontImageTable, _, err = image.Decode(reader)
			if err != nil {
				return err
			}
			return nil
		}
	}

	return errors.New("Wrong BitmatFont name.\n")
}
<|endoftext|>


<commit_before>package version

// VERSION ...
const VERSION = "1.1.43"
<commit_msg>v1.1.44<commit_after>package version

// VERSION ...
const VERSION = "1.1.44"
<|endoftext|>


<commit_before>// The version package provides a location to set the release versions for all
// packages to consume, without creating import cycles.
//
// This pckage should not import any other terraform packages.
package version

import (
	"fmt"

	version "github.com/hashicorp/go-version"
)

// The main version number that is being run at the moment.
const Version = "0.11.4"

// A pre-release marker for the version. If this is "" (empty string)
// then it means that it is a final release. Otherwise, this is a pre-release
// such as "dev" (in development), "beta", "rc1", etc.
var Prerelease = "dev"

// SemVer is an instance of version.Version. This has the secondary
// benefit of verifying during tests and init time that our version is a
// proper semantic version, which should always be the case.
var SemVer = version.Must(version.NewVersion(Version))

// Header is the header name used to send the current terraform version
// in http requests.
const Header = "Terraform-Version"

// String returns the complete version string, including prerelease
func String() string {
	if Prerelease != "" {
		return fmt.Sprintf("%s-%s", Version, Prerelease)
	}
	return Version
}
<commit_msg>v0.11.4<commit_after>// The version package provides a location to set the release versions for all
// packages to consume, without creating import cycles.
//
// This pckage should not import any other terraform packages.
package version

import (
	"fmt"

	version "github.com/hashicorp/go-version"
)

// The main version number that is being run at the moment.
const Version = "0.11.4"

// A pre-release marker for the version. If this is "" (empty string)
// then it means that it is a final release. Otherwise, this is a pre-release
// such as "dev" (in development), "beta", "rc1", etc.
var Prerelease = ""

// SemVer is an instance of version.Version. This has the secondary
// benefit of verifying during tests and init time that our version is a
// proper semantic version, which should always be the case.
var SemVer = version.Must(version.NewVersion(Version))

// Header is the header name used to send the current terraform version
// in http requests.
const Header = "Terraform-Version"

// String returns the complete version string, including prerelease
func String() string {
	if Prerelease != "" {
		return fmt.Sprintf("%s-%s", Version, Prerelease)
	}
	return Version
}
<|endoftext|>


<commit_before>// The version package implements version parsing.
// It also acts as guardian of the current client Juju version number.
package version

import (
	"fmt"
	"io/ioutil"
	"labix.org/v2/mgo/bson"
	"os"
	"path/filepath"
	"regexp"
	"runtime"
	"strconv"
	"strings"
)

// The presence and format of this constant is very important.
// The debian/rules build recipe uses this value for the version
// number of the release package.
const version = "1.9.3"

// Current gives the current version of the system.  If the file
// "FORCE-VERSION" is present in the same directory as the running
// binary, it will override this.
var Current = Binary{
	Number: MustParse(version),
	Series: readSeries("/etc/lsb-release"), // current Ubuntu release name.
	Arch:   ubuntuArch(runtime.GOARCH),
}

func init() {
	toolsDir := filepath.Dir(os.Args[0])
	v, err := ioutil.ReadFile(filepath.Join(toolsDir, "FORCE-VERSION"))
	if err != nil {
		if os.IsNotExist(err) {
			return
		}
		panic(fmt.Errorf("version: cannot read forced version: %v", err))
	}
	Current = MustParseBinary(strings.TrimSpace(string(v)))
}

// Number represents a juju version.  When bugs are fixed the patch
// number is incremented; when new features are added the minor number
// is incremented and patch is reset; and when compatibility is broken
// the major version is incremented and minor and patch are reset.  The
// build number is automatically assigned and has no well defined
// sequence.  If the build number is greater than zero or any of the
// other numbers are odd, it indicates that the release is still in
// development.
type Number struct {
	Major int
	Minor int
	Patch int
	Build int
}

// Binary specifies a binary version of juju.
type Binary struct {
	Number
	Series string
	Arch   string
}

func (v Binary) String() string {
	return fmt.Sprintf("%v-%s-%s", v.Number, v.Series, v.Arch)
}

// GetBSON turns v into a bson.Getter so it can be saved directly
// on a MongoDB database with mgo.
func (v Binary) GetBSON() (interface{}, error) {
	return v.String(), nil
}

// SetBSON turns v into a bson.Setter so it can be loaded directly
// from a MongoDB database with mgo.
func (vp *Binary) SetBSON(raw bson.Raw) error {
	var s string
	err := raw.Unmarshal(&s)
	if err != nil {
		return err
	}
	v, err := ParseBinary(s)
	if err != nil {
		return err
	}
	*vp = v
	return nil
}

var (
	binaryPat = regexp.MustCompile(`^(\d{1,9})\.(\d{1,9})\.(\d{1,9})(\.\d{1,9})?-([^-]+)-([^-]+)$`)
	numberPat = regexp.MustCompile(`^(\d{1,9})\.(\d{1,9})\.(\d{1,9})(\.\d{1,9})?$`)
)

// MustParse parses a version and panics if it does
// not parse correctly.
func MustParse(s string) Number {
	v, err := Parse(s)
	if err != nil {
		panic(err)
	}
	return v
}

// MustParseBinary parses a binary version and panics if it does
// not parse correctly.
func MustParseBinary(s string) Binary {
	v, err := ParseBinary(s)
	if err != nil {
		panic(err)
	}
	return v
}

// ParseBinary parses a binary version of the form "1.2.3-series-arch".
func ParseBinary(s string) (Binary, error) {
	m := binaryPat.FindStringSubmatch(s)
	if m == nil {
		return Binary{}, fmt.Errorf("invalid binary version %q", s)
	}
	var v Binary
	v.Major = atoi(m[1])
	v.Minor = atoi(m[2])
	v.Patch = atoi(m[3])
	if m[4] != "" {
		v.Build = atoi(m[4][1:])
	}
	v.Series = m[5]
	v.Arch = m[6]
	return v, nil
}

// Parse parses the version, which is of the form 1.2.3
// giving the major, minor and release versions
// respectively.
func Parse(s string) (Number, error) {
	m := numberPat.FindStringSubmatch(s)
	if m == nil {
		return Number{}, fmt.Errorf("invalid version %q", s)
	}
	var v Number
	v.Major = atoi(m[1])
	v.Minor = atoi(m[2])
	v.Patch = atoi(m[3])
	if m[4] != "" {
		v.Build = atoi(m[4][1:])
	}
	return v, nil
}

// atoi is the same as strconv.Atoi but assumes that
// the string has been verified to be a valid integer.
func atoi(s string) int {
	n, err := strconv.Atoi(s)
	if err != nil {
		panic(err)
	}
	return n
}

func (v Number) String() string {
	s := fmt.Sprintf("%d.%d.%d", v.Major, v.Minor, v.Patch)
	if v.Build > 0 {
		s += fmt.Sprintf(".%d", v.Build)
	}
	return s
}

// Less returns whether v is semantically earlier in the
// version sequence than w.
func (v Number) Less(w Number) bool {
	switch {
	case v.Major != w.Major:
		return v.Major < w.Major
	case v.Minor != w.Minor:
		return v.Minor < w.Minor
	case v.Patch != w.Patch:
		return v.Patch < w.Patch
	case v.Build != w.Build:
		return v.Build < w.Build
	}
	return false
}

// GetBSON turns v into a bson.Getter so it can be saved directly
// on a MongoDB database with mgo.
func (v Number) GetBSON() (interface{}, error) {
	return v.String(), nil
}

// SetBSON turns v into a bson.Setter so it can be loaded directly
// from a MongoDB database with mgo.
func (vp *Number) SetBSON(raw bson.Raw) error {
	var s string
	err := raw.Unmarshal(&s)
	if err != nil {
		return err
	}
	v, err := Parse(s)
	if err != nil {
		return err
	}
	*vp = v
	return nil
}

func isOdd(x int) bool {
	return x%2 != 0
}

// IsDev returns whether the version represents a development
// version. A version with an odd-numbered major, minor
// or patch version is considered to be a development version.
func (v Number) IsDev() bool {
	return isOdd(v.Major) || isOdd(v.Minor) || isOdd(v.Patch) || v.Build > 0
}

func readSeries(releaseFile string) string {
	data, err := ioutil.ReadFile(releaseFile)
	if err != nil {
		return "unknown"
	}
	for _, line := range strings.Split(string(data), "\n") {
		const p = "DISTRIB_CODENAME="
		if strings.HasPrefix(line, p) {
			return strings.Trim(line[len(p):], "\t '\"")
		}
	}
	return "unknown"
}

func ubuntuArch(arch string) string {
	if arch == "386" {
		arch = "i386"
	}
	return arch
}
<commit_msg>version: set development version to 1.9.4<commit_after>// The version package implements version parsing.
// It also acts as guardian of the current client Juju version number.
package version

import (
	"fmt"
	"io/ioutil"
	"labix.org/v2/mgo/bson"
	"os"
	"path/filepath"
	"regexp"
	"runtime"
	"strconv"
	"strings"
)

// The presence and format of this constant is very important.
// The debian/rules build recipe uses this value for the version
// number of the release package.
const version = "1.9.4"

// Current gives the current version of the system.  If the file
// "FORCE-VERSION" is present in the same directory as the running
// binary, it will override this.
var Current = Binary{
	Number: MustParse(version),
	Series: readSeries("/etc/lsb-release"), // current Ubuntu release name.
	Arch:   ubuntuArch(runtime.GOARCH),
}

func init() {
	toolsDir := filepath.Dir(os.Args[0])
	v, err := ioutil.ReadFile(filepath.Join(toolsDir, "FORCE-VERSION"))
	if err != nil {
		if os.IsNotExist(err) {
			return
		}
		panic(fmt.Errorf("version: cannot read forced version: %v", err))
	}
	Current = MustParseBinary(strings.TrimSpace(string(v)))
}

// Number represents a juju version.  When bugs are fixed the patch
// number is incremented; when new features are added the minor number
// is incremented and patch is reset; and when compatibility is broken
// the major version is incremented and minor and patch are reset.  The
// build number is automatically assigned and has no well defined
// sequence.  If the build number is greater than zero or any of the
// other numbers are odd, it indicates that the release is still in
// development.
type Number struct {
	Major int
	Minor int
	Patch int
	Build int
}

// Binary specifies a binary version of juju.
type Binary struct {
	Number
	Series string
	Arch   string
}

func (v Binary) String() string {
	return fmt.Sprintf("%v-%s-%s", v.Number, v.Series, v.Arch)
}

// GetBSON turns v into a bson.Getter so it can be saved directly
// on a MongoDB database with mgo.
func (v Binary) GetBSON() (interface{}, error) {
	return v.String(), nil
}

// SetBSON turns v into a bson.Setter so it can be loaded directly
// from a MongoDB database with mgo.
func (vp *Binary) SetBSON(raw bson.Raw) error {
	var s string
	err := raw.Unmarshal(&s)
	if err != nil {
		return err
	}
	v, err := ParseBinary(s)
	if err != nil {
		return err
	}
	*vp = v
	return nil
}

var (
	binaryPat = regexp.MustCompile(`^(\d{1,9})\.(\d{1,9})\.(\d{1,9})(\.\d{1,9})?-([^-]+)-([^-]+)$`)
	numberPat = regexp.MustCompile(`^(\d{1,9})\.(\d{1,9})\.(\d{1,9})(\.\d{1,9})?$`)
)

// MustParse parses a version and panics if it does
// not parse correctly.
func MustParse(s string) Number {
	v, err := Parse(s)
	if err != nil {
		panic(err)
	}
	return v
}

// MustParseBinary parses a binary version and panics if it does
// not parse correctly.
func MustParseBinary(s string) Binary {
	v, err := ParseBinary(s)
	if err != nil {
		panic(err)
	}
	return v
}

// ParseBinary parses a binary version of the form "1.2.3-series-arch".
func ParseBinary(s string) (Binary, error) {
	m := binaryPat.FindStringSubmatch(s)
	if m == nil {
		return Binary{}, fmt.Errorf("invalid binary version %q", s)
	}
	var v Binary
	v.Major = atoi(m[1])
	v.Minor = atoi(m[2])
	v.Patch = atoi(m[3])
	if m[4] != "" {
		v.Build = atoi(m[4][1:])
	}
	v.Series = m[5]
	v.Arch = m[6]
	return v, nil
}

// Parse parses the version, which is of the form 1.2.3
// giving the major, minor and release versions
// respectively.
func Parse(s string) (Number, error) {
	m := numberPat.FindStringSubmatch(s)
	if m == nil {
		return Number{}, fmt.Errorf("invalid version %q", s)
	}
	var v Number
	v.Major = atoi(m[1])
	v.Minor = atoi(m[2])
	v.Patch = atoi(m[3])
	if m[4] != "" {
		v.Build = atoi(m[4][1:])
	}
	return v, nil
}

// atoi is the same as strconv.Atoi but assumes that
// the string has been verified to be a valid integer.
func atoi(s string) int {
	n, err := strconv.Atoi(s)
	if err != nil {
		panic(err)
	}
	return n
}

func (v Number) String() string {
	s := fmt.Sprintf("%d.%d.%d", v.Major, v.Minor, v.Patch)
	if v.Build > 0 {
		s += fmt.Sprintf(".%d", v.Build)
	}
	return s
}

// Less returns whether v is semantically earlier in the
// version sequence than w.
func (v Number) Less(w Number) bool {
	switch {
	case v.Major != w.Major:
		return v.Major < w.Major
	case v.Minor != w.Minor:
		return v.Minor < w.Minor
	case v.Patch != w.Patch:
		return v.Patch < w.Patch
	case v.Build != w.Build:
		return v.Build < w.Build
	}
	return false
}

// GetBSON turns v into a bson.Getter so it can be saved directly
// on a MongoDB database with mgo.
func (v Number) GetBSON() (interface{}, error) {
	return v.String(), nil
}

// SetBSON turns v into a bson.Setter so it can be loaded directly
// from a MongoDB database with mgo.
func (vp *Number) SetBSON(raw bson.Raw) error {
	var s string
	err := raw.Unmarshal(&s)
	if err != nil {
		return err
	}
	v, err := Parse(s)
	if err != nil {
		return err
	}
	*vp = v
	return nil
}

func isOdd(x int) bool {
	return x%2 != 0
}

// IsDev returns whether the version represents a development
// version. A version with an odd-numbered major, minor
// or patch version is considered to be a development version.
func (v Number) IsDev() bool {
	return isOdd(v.Major) || isOdd(v.Minor) || isOdd(v.Patch) || v.Build > 0
}

func readSeries(releaseFile string) string {
	data, err := ioutil.ReadFile(releaseFile)
	if err != nil {
		return "unknown"
	}
	for _, line := range strings.Split(string(data), "\n") {
		const p = "DISTRIB_CODENAME="
		if strings.HasPrefix(line, p) {
			return strings.Trim(line[len(p):], "\t '\"")
		}
	}
	return "unknown"
}

func ubuntuArch(arch string) string {
	if arch == "386" {
		arch = "i386"
	}
	return arch
}
<|endoftext|>


<commit_before>package version

const Version = "0.1.1+git"
<commit_msg>chore(release): bump version to 0.1.2<commit_after>package version

const Version = "0.1.2"
<|endoftext|>


<commit_before>package version

// Version is the version of the build.
const Version = "1.9.0"
<commit_msg>Bump to v1.9.1-dev<commit_after>package version

// Version is the version of the build.
const Version = "1.9.1-dev"
<|endoftext|>


<commit_before>package kick

import (
	"github.com/spf13/cobra"
	"fmt"
	"github.com/BluePecker/JwtAuth/engine/client"
	"github.com/BluePecker/JwtAuth/engine/server/parameter/jwt/request"
	"github.com/BluePecker/JwtAuth/engine/server/parameter"
	"encoding/json"
	"errors"
)

func NewCommand() *cobra.Command {
	cmd := &cobra.Command{
		Use:   "kick",
		Short: "force users to go offline",
		RunE: func(cmd *cobra.Command, args []string) error {
			unixSock, err := cmd.Parent().Flags().GetString("unix-sock")
			if err != nil {
				return err
			}
			cli := client.NewClient(unixSock)
			if body, err := cli.Post("/v1.0/token/kick", request.Kick{Unique: args[0]}); err != nil {
				return err
			} else {
				defer body.Close()
				var res parameter.Response
				if err := json.NewDecoder(body).Decode(&res); err != nil {
					return err
				} else {
					if res.Code != 200 {
						return errors.New(res.Message)
					}
					fmt.Printf("successfully kicked out the user.\n")
					return nil
				}
			}
		},
	}
	return cmd
}
<commit_msg>fix bug<commit_after>package kick

import (
	"github.com/spf13/cobra"
	"fmt"
	"github.com/BluePecker/JwtAuth/engine/client"
	"github.com/BluePecker/JwtAuth/engine/server/parameter/jwt/request"
	"github.com/BluePecker/JwtAuth/engine/server/parameter"
	"encoding/json"
	"errors"
)

func NewCommand() *cobra.Command {
	cmd := &cobra.Command{
		Use:   "kick",
		Short: "force users to go offline",
		RunE: func(cmd *cobra.Command, args []string) error {
			unixSock, err := cmd.Parent().Flags().GetString("unix-sock")
			if err != nil {
				return err
			}
			cli := client.NewClient(unixSock)
			if body, err := cli.Post("/v1.0/token/kick", request.Kick{Unique: args[0]}); err != nil {
				return err
			} else {
				defer body.Close()
				var res parameter.Response
				if err := json.NewDecoder(body).Decode(&res); err != nil {
					return err
				} else {
					if res.Code != 200 {
						return errors.New(res.Message)
					}
					fmt.Printf(res.Message, "successfully kicked out the user.\n")
					return nil
				}
			}
		},
	}
	return cmd
}
<|endoftext|>


<commit_before>package whisper

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

var ainfo = NewArchiveInfo

func tempFileName() string {
	f, err := ioutil.TempFile("", "whisper")
	if err != nil {
		panic(err)
	}
	f.Close()
	os.Remove(f.Name())
	return f.Name()
}

func TestQuantizeArchive(t *testing.T) {
	points := archive{Point{0, 0}, Point{3, 0}, Point{10, 0}}
	pointsOut := archive{Point{0, 0}, Point{2, 0}, Point{10, 0}}
	quantizedPoints := quantizeArchive(points, 2)
	for i := range quantizedPoints {
		if quantizedPoints[i] != pointsOut[i] {
			t.Errorf("%v != %v", quantizedPoints[i], pointsOut[i])
		}
	}
}

func TestQuantizePoint(t *testing.T) {
	var pointTests = []struct {
		in         uint32
		resolution uint32
		out        uint32
	}{
		{0, 2, 0},
		{3, 2, 2},
	}

	for i, tt := range pointTests {
		q := quantize(tt.in, tt.resolution)
		if q != tt.out {
			t.Errorf("%d. quantizePoint(%q, %q) => %q, want %q", i, tt.in, tt.resolution, q, tt.out)
		}
	}
}

func TestAggregate(t *testing.T) {
	points := archive{Point{0, 0}, Point{0, 1}, Point{0, 2}, Point{0, 1}}
	expected := Point{0, 1}
	if p, err := aggregate(AggregationAverage, points); (p != expected) || (err != nil) {
		t.Errorf("Average failed to average to %v, got %v: %v", expected, p, err)
	}

	expected = Point{0, 4}
	if p, err := aggregate(AggregationSum, points); (p != expected) || (err != nil) {
		t.Errorf("Sum failed to aggregate to %v, got %v: %v", expected, p, err)
	}

	expected = Point{0, 1}
	if p, err := aggregate(AggregationLast, points); (p != expected) || (err != nil) {
		t.Errorf("Last failed to aggregate to %v, got %v: %v", expected, p, err)
	}

	expected = Point{0, 2}
	if p, err := aggregate(AggregationMax, points); (p != expected) || (err != nil) {
		t.Errorf("Max failed to aggregate to %v, got %v: %v", expected, p, err)
	}

	expected = Point{0, 0}
	if p, err := aggregate(AggregationMin, points); (p != expected) || (err != nil) {
		t.Errorf("Min failed to aggregate to %v, got %v: %v", expected, p, err)
	}

	if _, err := aggregate(1000, points); err == nil {
		t.Errorf("No error for invalid aggregation")
	}
}

func TestParseArchiveInfo(t *testing.T) {
	tests := map[string]ArchiveInfo{
		"60:1440": ArchiveInfo{0, 60, 1440},    // 60 seconds per datapoint, 1440 datapoints = 1 day of retention
		"15m:8":   ArchiveInfo{0, 15 * 60, 8},  // 15 minutes per datapoint, 8 datapoints = 2 hours of retention
		"1h:7d":   ArchiveInfo{0, 3600, 168},   // 1 hour per datapoint, 7 days of retention
		"12h:2y":  ArchiveInfo{0, 43200, 1456}, // 12 hours per datapoint, 2 years of retention
	}

	for info, expected := range tests {
		if a, err := ParseArchiveInfo(info); (a != expected) || (err != nil) {
			t.Errorf("%s: %v != %v, %v", info, a, expected, err)
		}
	}

}

func TestWhisperAggregation(t *testing.T) {
	filename := tempFileName()
	defer os.Remove(filename)
	options := DefaultCreateOptions()
	options.AggregationMethod = AggregationMin
	w, err := Create(filename, []ArchiveInfo{NewArchiveInfo(60, 60)}, options)
	if err != nil {
		t.Fatal("failed to create database:", err)
	}
	defer func() {
		if err := w.Close(); err != nil {
			t.Fatal("failed to close database:", err)
		}
	}()

	w.SetAggregationMethod(AggregationMax)
	if method := w.Header.Metadata.AggregationMethod; method != AggregationMax {
		t.Fatalf("AggregationMethod: %d, want %d", method, AggregationMax)
	}
}

func TestArchiveHeader(t *testing.T) {
	filename := tempFileName()
	defer os.Remove(filename)

	w, err := Create(filename, []ArchiveInfo{ainfo(1, 60), ainfo(60, 60)}, DefaultCreateOptions())
	if err != nil {
		t.Fatal("failed to create database:", err)
	}

	hSize := headerSize(2)
	verifyHeader := func(w *Whisper) {
		meta := w.Header.Metadata
		expectedMeta := Metadata{AggregationAverage, 60 * 60, 0.5, 2}
		if meta != expectedMeta {
			t.Errorf("bad metadata, got %v want %v", meta, expectedMeta)
		}

		archive0 := ArchiveInfo{hSize, 1, 60}
		if w.Header.Archives[0] != archive0 {
			t.Errorf("bad archive 0, got %v want %v", w.Header.Archives[0], archive0)
		}

		archive1 := ArchiveInfo{hSize + pointSize*60, 60, 60}
		if w.Header.Archives[1] != archive1 {
			t.Errorf("bad archive 1, got %v want %v", w.Header.Archives[1], archive1)
		}
	}

	verifyHeader(w)
	if err := w.Close(); err != nil {
		t.Fatal("failed to close database:", err)
	}

	w, err = Open(filename)
	if err != nil {
		t.Fatal("failed to open database:", err)
	}
	verifyHeader(w)
	if err := w.Close(); err != nil {
		t.Fatal("failed to close database:", err)
	}
}

func TestFetch(t *testing.T) {
	filename := tempFileName()
	defer os.Remove(filename)

	const (
		step    = 60
		nPoints = 100
	)

	w, err := Create(filename, []ArchiveInfo{NewArchiveInfo(step, nPoints)}, DefaultCreateOptions())
	if err != nil {
		t.Fatal("failed to create database:", err)
	}
	defer func() {
		if err := w.Close(); err != nil {
			t.Fatal("failed to close database:", err)
		}
	}()

	points := make([]Point, nPoints)
	now := time.Now()
	for i := 0; i < nPoints; i++ {
		points[i] = NewPoint(now.Add(-time.Duration(nPoints-1-i)*time.Minute), float64(i))
	}
	err = w.UpdateMany(points)
	if err != nil {
		t.Fatal("failed to update points:", err)
	}

	_, fetchedPoints, err := w.FetchUntil(1, 0)
	if err == nil {
		t.Fatal("no error from nonsensical fetch, fetched", fetchedPoints)
	}

	_, fetchedPoints, err = w.Fetch(0)
	if err != nil {
		t.Fatal("error fetching points:", err)
	}
	if len(fetchedPoints) != nPoints {
		t.Fatalf("got %d points, want %d", len(fetchedPoints), nPoints)
	}
	for i := range fetchedPoints {
		point := points[i]
		point.Timestamp = quantize(point.Timestamp, step)
		if fetchedPoints[i] != point {
			t.Errorf("point %d: got %v, want %v", i, fetchedPoints[i], point)
		}
	}
}

// TestMaxRetention tests the behaviour of an archive's maximum retenetion.
func TestMaxRetention(t *testing.T) {
	filename := tempFileName()
	defer os.Remove(filename)

	w, err := Create(filename, []ArchiveInfo{NewArchiveInfo(60, 10)}, DefaultCreateOptions())
	if err != nil {
		t.Fatal("failed to create database:", err)
	}
	defer func() {
		if err := w.Close(); err != nil {
			t.Fatal("failed to close database:", err)
		}
	}()

	invalid := NewPoint(time.Now().Add(-11*time.Minute), 0)
	if err = w.Update(invalid); err == nil {
		t.Fatal("invalid point did not return an error")
	}
	valid := NewPoint(time.Now().Add(-9*time.Minute), 0)
	if err = w.Update(valid); err != nil {
		t.Fatalf("valid point returned an error: %s", err)
	}
}

func TestCreateTwice(t *testing.T) {
	filename := tempFileName()
	archiveInfos := []ArchiveInfo{NewArchiveInfo(60, 10)}
	defer os.Remove(filename)

	w, err := Create(filename, archiveInfos, DefaultCreateOptions())
	if err != nil {
		t.Fatal("failed to create database:", err)
	}
	if err := w.Close(); err != nil {
		t.Fatal("failed to close database:", err)
	}

	_, err = Create(filename, archiveInfos, DefaultCreateOptions())
	if err == nil {
		t.Fatal("no error when attempting to overwrite database")
	}
}

func TestValidateArchiveList(t *testing.T) {
	tests := []struct {
		Archives []ArchiveInfo
		Error    error
	}{
		{[]ArchiveInfo{}, ErrNoArchives},
		{[]ArchiveInfo{ainfo(10, 10), ainfo(10, 5)}, ErrDuplicateArchive},
		{[]ArchiveInfo{ainfo(2, 5), ainfo(3, 5)}, ErrUnevenPrecision},
		{[]ArchiveInfo{ainfo(10, 6), ainfo(5, 13)}, ErrLowRetention},
		{[]ArchiveInfo{ainfo(10, 6), ainfo(70, 10)}, ErrInsufficientPoints},
		{[]ArchiveInfo{ainfo(2, 5), ainfo(4, 10), ainfo(8, 20)}, nil},

		// The following tests adapted from test_whisper.py
		{[]ArchiveInfo{ainfo(1, 60), ainfo(60, 60)}, nil},
		{[]ArchiveInfo{ainfo(1, 60), ainfo(60, 60), ainfo(1, 60)}, ErrDuplicateArchive},
		{[]ArchiveInfo{ainfo(60, 60), ainfo(6, 60)}, nil},
		{[]ArchiveInfo{ainfo(60, 60), ainfo(7, 60)}, ErrUnevenPrecision},
		{[]ArchiveInfo{ainfo(1, 60), ainfo(10, 1)}, ErrLowRetention},
		{[]ArchiveInfo{ainfo(1, 30), ainfo(60, 60)}, ErrInsufficientPoints},
	}

	for i, test := range tests {
		if err := validateArchiveList(test.Archives); err != test.Error {
			t.Errorf("%d: got: %v, want: %v", i, err, test.Error)
		}
	}
}
<commit_msg>Add test for archive rollup<commit_after>package whisper

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

var ainfo = NewArchiveInfo

func tempFileName() string {
	f, err := ioutil.TempFile("", "whisper")
	if err != nil {
		panic(err)
	}
	f.Close()
	os.Remove(f.Name())
	return f.Name()
}

func TestQuantizeArchive(t *testing.T) {
	points := archive{Point{0, 0}, Point{3, 0}, Point{10, 0}}
	pointsOut := archive{Point{0, 0}, Point{2, 0}, Point{10, 0}}
	quantizedPoints := quantizeArchive(points, 2)
	for i := range quantizedPoints {
		if quantizedPoints[i] != pointsOut[i] {
			t.Errorf("%v != %v", quantizedPoints[i], pointsOut[i])
		}
	}
}

func TestQuantizePoint(t *testing.T) {
	var pointTests = []struct {
		in         uint32
		resolution uint32
		out        uint32
	}{
		{0, 2, 0},
		{3, 2, 2},
	}

	for i, tt := range pointTests {
		q := quantize(tt.in, tt.resolution)
		if q != tt.out {
			t.Errorf("%d. quantizePoint(%q, %q) => %q, want %q", i, tt.in, tt.resolution, q, tt.out)
		}
	}
}

func TestAggregate(t *testing.T) {
	points := archive{Point{0, 0}, Point{0, 1}, Point{0, 2}, Point{0, 1}}
	expected := Point{0, 1}
	if p, err := aggregate(AggregationAverage, points); (p != expected) || (err != nil) {
		t.Errorf("Average failed to average to %v, got %v: %v", expected, p, err)
	}

	expected = Point{0, 4}
	if p, err := aggregate(AggregationSum, points); (p != expected) || (err != nil) {
		t.Errorf("Sum failed to aggregate to %v, got %v: %v", expected, p, err)
	}

	expected = Point{0, 1}
	if p, err := aggregate(AggregationLast, points); (p != expected) || (err != nil) {
		t.Errorf("Last failed to aggregate to %v, got %v: %v", expected, p, err)
	}

	expected = Point{0, 2}
	if p, err := aggregate(AggregationMax, points); (p != expected) || (err != nil) {
		t.Errorf("Max failed to aggregate to %v, got %v: %v", expected, p, err)
	}

	expected = Point{0, 0}
	if p, err := aggregate(AggregationMin, points); (p != expected) || (err != nil) {
		t.Errorf("Min failed to aggregate to %v, got %v: %v", expected, p, err)
	}

	if _, err := aggregate(1000, points); err == nil {
		t.Errorf("No error for invalid aggregation")
	}
}

func TestParseArchiveInfo(t *testing.T) {
	tests := map[string]ArchiveInfo{
		"60:1440": ArchiveInfo{0, 60, 1440},    // 60 seconds per datapoint, 1440 datapoints = 1 day of retention
		"15m:8":   ArchiveInfo{0, 15 * 60, 8},  // 15 minutes per datapoint, 8 datapoints = 2 hours of retention
		"1h:7d":   ArchiveInfo{0, 3600, 168},   // 1 hour per datapoint, 7 days of retention
		"12h:2y":  ArchiveInfo{0, 43200, 1456}, // 12 hours per datapoint, 2 years of retention
	}

	for info, expected := range tests {
		if a, err := ParseArchiveInfo(info); (a != expected) || (err != nil) {
			t.Errorf("%s: %v != %v, %v", info, a, expected, err)
		}
	}

}

func TestWhisperAggregation(t *testing.T) {
	filename := tempFileName()
	defer os.Remove(filename)
	options := DefaultCreateOptions()
	options.AggregationMethod = AggregationMin
	w, err := Create(filename, []ArchiveInfo{NewArchiveInfo(60, 60)}, options)
	if err != nil {
		t.Fatal("failed to create database:", err)
	}
	defer func() {
		if err := w.Close(); err != nil {
			t.Fatal("failed to close database:", err)
		}
	}()

	w.SetAggregationMethod(AggregationMax)
	if method := w.Header.Metadata.AggregationMethod; method != AggregationMax {
		t.Fatalf("AggregationMethod: %d, want %d", method, AggregationMax)
	}
}

func TestArchiveHeader(t *testing.T) {
	filename := tempFileName()
	defer os.Remove(filename)

	w, err := Create(filename, []ArchiveInfo{ainfo(1, 60), ainfo(60, 60)}, DefaultCreateOptions())
	if err != nil {
		t.Fatal("failed to create database:", err)
	}

	hSize := headerSize(2)
	verifyHeader := func(w *Whisper) {
		meta := w.Header.Metadata
		expectedMeta := Metadata{AggregationAverage, 60 * 60, 0.5, 2}
		if meta != expectedMeta {
			t.Errorf("bad metadata, got %v want %v", meta, expectedMeta)
		}

		archive0 := ArchiveInfo{hSize, 1, 60}
		if w.Header.Archives[0] != archive0 {
			t.Errorf("bad archive 0, got %v want %v", w.Header.Archives[0], archive0)
		}

		archive1 := ArchiveInfo{hSize + pointSize*60, 60, 60}
		if w.Header.Archives[1] != archive1 {
			t.Errorf("bad archive 1, got %v want %v", w.Header.Archives[1], archive1)
		}
	}

	verifyHeader(w)
	if err := w.Close(); err != nil {
		t.Fatal("failed to close database:", err)
	}

	w, err = Open(filename)
	if err != nil {
		t.Fatal("failed to open database:", err)
	}
	verifyHeader(w)
	if err := w.Close(); err != nil {
		t.Fatal("failed to close database:", err)
	}
}

func TestFetch(t *testing.T) {
	filename := tempFileName()
	defer os.Remove(filename)

	const (
		step    = 60
		nPoints = 100
	)

	w, err := Create(filename, []ArchiveInfo{NewArchiveInfo(step, nPoints)}, DefaultCreateOptions())
	if err != nil {
		t.Fatal("failed to create database:", err)
	}
	defer func() {
		if err := w.Close(); err != nil {
			t.Fatal("failed to close database:", err)
		}
	}()

	points := make([]Point, nPoints)
	now := time.Now()
	for i := 0; i < nPoints; i++ {
		points[i] = NewPoint(now.Add(-time.Duration(nPoints-1-i)*time.Minute), float64(i))
	}
	err = w.UpdateMany(points)
	if err != nil {
		t.Fatal("failed to update points:", err)
	}

	_, fetchedPoints, err := w.FetchUntil(1, 0)
	if err == nil {
		t.Fatal("no error from nonsensical fetch, fetched", fetchedPoints)
	}

	_, fetchedPoints, err = w.Fetch(0)
	if err != nil {
		t.Fatal("error fetching points:", err)
	}
	if len(fetchedPoints) != nPoints {
		t.Fatalf("got %d points, want %d", len(fetchedPoints), nPoints)
	}
	for i := range fetchedPoints {
		point := points[i]
		point.Timestamp = quantize(point.Timestamp, step)
		if fetchedPoints[i] != point {
			t.Errorf("point %d: got %v, want %v", i, fetchedPoints[i], point)
		}
	}
}

// TestMaxRetention tests the behaviour of an archive's maximum retenetion.
func TestMaxRetention(t *testing.T) {
	filename := tempFileName()
	defer os.Remove(filename)

	w, err := Create(filename, []ArchiveInfo{NewArchiveInfo(60, 10)}, DefaultCreateOptions())
	if err != nil {
		t.Fatal("failed to create database:", err)
	}
	defer func() {
		if err := w.Close(); err != nil {
			t.Fatal("failed to close database:", err)
		}
	}()

	invalid := NewPoint(time.Now().Add(-11*time.Minute), 0)
	if err = w.Update(invalid); err == nil {
		t.Fatal("invalid point did not return an error")
	}
	valid := NewPoint(time.Now().Add(-9*time.Minute), 0)
	if err = w.Update(valid); err != nil {
		t.Fatalf("valid point returned an error: %s", err)
	}
}

func TestCreateTwice(t *testing.T) {
	filename := tempFileName()
	archiveInfos := []ArchiveInfo{NewArchiveInfo(60, 10)}
	defer os.Remove(filename)

	w, err := Create(filename, archiveInfos, DefaultCreateOptions())
	if err != nil {
		t.Fatal("failed to create database:", err)
	}
	if err := w.Close(); err != nil {
		t.Fatal("failed to close database:", err)
	}

	_, err = Create(filename, archiveInfos, DefaultCreateOptions())
	if err == nil {
		t.Fatal("no error when attempting to overwrite database")
	}
}

func TestValidateArchiveList(t *testing.T) {
	tests := []struct {
		Archives []ArchiveInfo
		Error    error
	}{
		{[]ArchiveInfo{}, ErrNoArchives},
		{[]ArchiveInfo{ainfo(10, 10), ainfo(10, 5)}, ErrDuplicateArchive},
		{[]ArchiveInfo{ainfo(2, 5), ainfo(3, 5)}, ErrUnevenPrecision},
		{[]ArchiveInfo{ainfo(10, 6), ainfo(5, 13)}, ErrLowRetention},
		{[]ArchiveInfo{ainfo(10, 6), ainfo(70, 10)}, ErrInsufficientPoints},
		{[]ArchiveInfo{ainfo(2, 5), ainfo(4, 10), ainfo(8, 20)}, nil},

		// The following tests adapted from test_whisper.py
		{[]ArchiveInfo{ainfo(1, 60), ainfo(60, 60)}, nil},
		{[]ArchiveInfo{ainfo(1, 60), ainfo(60, 60), ainfo(1, 60)}, ErrDuplicateArchive},
		{[]ArchiveInfo{ainfo(60, 60), ainfo(6, 60)}, nil},
		{[]ArchiveInfo{ainfo(60, 60), ainfo(7, 60)}, ErrUnevenPrecision},
		{[]ArchiveInfo{ainfo(1, 60), ainfo(10, 1)}, ErrLowRetention},
		{[]ArchiveInfo{ainfo(1, 30), ainfo(60, 60)}, ErrInsufficientPoints},
	}

	for i, test := range tests {
		if err := validateArchiveList(test.Archives); err != test.Error {
			t.Errorf("%d: got: %v, want: %v", i, err, test.Error)
		}
	}
}

// Test that values are aggregated correctly when rolling up into lower archive
func TestArchiveRollup(t *testing.T) {
	filename := tempFileName()
	defer os.Remove(filename)

	options := DefaultCreateOptions()
	options.AggregationMethod = AggregationSum
	ai1, err := ParseArchiveInfo("5s:1m")
	ai2, err := ParseArchiveInfo("10s:2m")
	if err != nil {
		t.Fatal(err)
	}
	w, err := Create(filename, []ArchiveInfo{ai1, ai2}, options)
	if err != nil {
		t.Fatal("failed to create database:", err)
	}
	defer func() {
		if err := w.Close(); err != nil {
			t.Fatal("failed to close database:", err)
		}
	}()

	nPoints := 5
	points := make([]Point, nPoints)
	now := time.Now()
	for i := 0; i < nPoints; i++ {
		points[i] = NewPoint(now.Add(-time.Duration((nPoints-i)*5)*time.Second), float64(1))
	}
	err = w.UpdateMany(points)
	if err != nil {
		t.Fatal("failed to update points:", err)
	}

	oneCount := 0
	twoCount := 0

	dump, err := w.DumpArchive(1)
	if err != nil {
		t.Fatal("failed to read archive:", err)
	}

	for _, point := range dump {
		switch point.Value {
		case 1: oneCount++
		case 2: twoCount++
		}
	}
	if oneCount != 1 || twoCount != 2 {
		t.Fatal("Archive rollup unexpected values")
	}
}
<|endoftext|>


<commit_before>package sequtil

func FindFlankingSeqs(seq string, flankers [][]string) []string {
	return flankers[0]
}
<commit_msg>passed that test<commit_after>package sequtil

import "strings"

func FindFlankingSeqs(seq string, flankers [][]string) []string {
	for _, pair := range flankers {
		if (strings.HasPrefix(seq, pair[0]) && strings.HasSuffix(seq, pair[1])) {
			return pair
		}
	}
	return nil
}
<|endoftext|>


<commit_before>package serf

import (
	"encoding/base64"
	"fmt"
	"sync"
)

// keyManager encapsulates all functionality within Serf for handling
// encryption keyring changes across a cluster.
type keyManager struct {
	serf *Serf

	// Embedded mutex to protect read and write operations
	sync.RWMutex
}

// keyRequest is used to contain input parameters which get broadcasted to all
// nodes as part of a key query operation.
type keyRequest struct {
	Key []byte
}

// KeyResponse is used to relay a query for a list of all keys in use.
type KeyResponse struct {
	Messages map[string]string // Map of node name to response message
	NumNodes int               // Total nodes memberlist knows of
	NumResp  int               // Total responses received
	NumErr   int               // Total errors from request

	// Keys is a mapping of the base64-encoded value of the key bytes to the
	// number of nodes that have the key installed.
	Keys map[string]int
}

// streamKeyResp takes care of reading responses from a channel and composing
// them into a KeyResponse. It will update a KeyResponse *in place* and
// therefore has nothing to return.
func (k *keyManager) streamKeyResp(resp *KeyResponse, ch <-chan NodeResponse) {
	for r := range ch {
		var nodeResponse nodeKeyResponse

		resp.NumResp++

		// Decode the response
		if len(r.Payload) < 1 || messageType(r.Payload[0]) != messageKeyResponseType {
			resp.Messages[r.From] = fmt.Sprintf(
				"Invalid key query response type: %v", r.Payload)
			resp.NumErr++
			goto NEXT
		}
		if err := decodeMessage(r.Payload[1:], &nodeResponse); err != nil {
			resp.Messages[r.From] = fmt.Sprintf(
				"Failed to decode key query response: %v", r.Payload)
			resp.NumErr++
			goto NEXT
		}

		if !nodeResponse.Result {
			resp.Messages[r.From] = nodeResponse.Message
			resp.NumErr++
		}

		// Currently only used for key list queries, this adds keys to a counter
		// and increments them for each node response which contains them.
		for _, key := range nodeResponse.Keys {
			if _, ok := resp.Keys[key]; !ok {
				resp.Keys[key] = 1
			} else {
				resp.Keys[key]++
			}
		}

	NEXT:
		// Return early if all nodes have responded. This allows us to avoid
		// waiting for the full timeout when there is nothing left to do.
		if resp.NumResp == resp.NumNodes {
			return
		}
	}
}

// handleKeyRequest performs query broadcasting to all members for any type of
// key operation and manages gathering responses and packing them up into a
// KeyResponse for uniform response handling.
func (k *keyManager) handleKeyRequest(key, query string) (*KeyResponse, error) {
	resp := &KeyResponse{
		Messages: make(map[string]string),
		Keys:     make(map[string]int),
	}
	qName := internalQueryName(query)

	// Decode the new key into raw bytes
	rawKey, err := base64.StdEncoding.DecodeString(key)
	if err != nil {
		return nil, err
	}

	// Encode the query request
	req, err := encodeMessage(messageKeyRequestType, keyRequest{Key: rawKey})
	if err != nil {
		return nil, err
	}

	qParam := k.serf.DefaultQueryParams()
	queryResp, err := k.serf.Query(qName, req, qParam)
	if err != nil {
		return nil, err
	}

	// Handle the response stream and populate the KeyResponse
	resp.NumNodes = k.serf.memberlist.NumMembers()
	k.streamKeyResp(resp, queryResp.respCh)

	// Check the response for any reported failure conditions
	if resp.NumErr != 0 {
		return resp, fmt.Errorf("%d/%d nodes reported failure", resp.NumErr, resp.NumNodes)
	}
	if resp.NumResp != resp.NumNodes {
		return resp, fmt.Errorf("%d/%d nodes reported success", resp.NumResp, resp.NumNodes)
	}

	return resp, nil
}

// InstallKey handles broadcasting a query to all members and gathering
// responses from each of them, returning a list of messages from each node
// and any applicable error conditions.
func (k *keyManager) InstallKey(key string) (*KeyResponse, error) {
	k.Lock()
	defer k.Unlock()

	return k.handleKeyRequest(key, installKeyQuery)
}

// UseKey handles broadcasting a primary key change to all members in the
// cluster, and gathering any response messages. If successful, there should
// be an empty KeyResponse returned.
func (k *keyManager) UseKey(key string) (*KeyResponse, error) {
	k.Lock()
	defer k.Unlock()

	return k.handleKeyRequest(key, useKeyQuery)
}

// RemoveKey handles broadcasting a key to the cluster for removal. Each member
// will receive this event, and if they have the key in their keyring, remove
// it. If any errors are encountered, RemoveKey will collect and relay them.
func (k *keyManager) RemoveKey(key string) (*KeyResponse, error) {
	k.Lock()
	defer k.Unlock()

	return k.handleKeyRequest(key, removeKeyQuery)
}

// ListKeys is used to collect installed keys from members in a Serf cluster
// and return an aggregated list of all installed keys. This is useful to
// operators to ensure that there are no lingering keys installed on any agents.
// Since having multiple keys installed can cause performance penalties in some
// cases, it's important to verify this information and remove unneeded keys.
func (k *keyManager) ListKeys() (*KeyResponse, error) {
	k.RLock()
	defer k.RUnlock()

	return k.handleKeyRequest("", listKeysQuery)
}
<commit_msg>serf: make RWMutex private in keymanager<commit_after>package serf

import (
	"encoding/base64"
	"fmt"
	"sync"
)

// keyManager encapsulates all functionality within Serf for handling
// encryption keyring changes across a cluster.
type keyManager struct {
	serf *Serf

	// Lock to protect read and write operations
	l sync.RWMutex
}

// keyRequest is used to contain input parameters which get broadcasted to all
// nodes as part of a key query operation.
type keyRequest struct {
	Key []byte
}

// KeyResponse is used to relay a query for a list of all keys in use.
type KeyResponse struct {
	Messages map[string]string // Map of node name to response message
	NumNodes int               // Total nodes memberlist knows of
	NumResp  int               // Total responses received
	NumErr   int               // Total errors from request

	// Keys is a mapping of the base64-encoded value of the key bytes to the
	// number of nodes that have the key installed.
	Keys map[string]int
}

// streamKeyResp takes care of reading responses from a channel and composing
// them into a KeyResponse. It will update a KeyResponse *in place* and
// therefore has nothing to return.
func (k *keyManager) streamKeyResp(resp *KeyResponse, ch <-chan NodeResponse) {
	for r := range ch {
		var nodeResponse nodeKeyResponse

		resp.NumResp++

		// Decode the response
		if len(r.Payload) < 1 || messageType(r.Payload[0]) != messageKeyResponseType {
			resp.Messages[r.From] = fmt.Sprintf(
				"Invalid key query response type: %v", r.Payload)
			resp.NumErr++
			goto NEXT
		}
		if err := decodeMessage(r.Payload[1:], &nodeResponse); err != nil {
			resp.Messages[r.From] = fmt.Sprintf(
				"Failed to decode key query response: %v", r.Payload)
			resp.NumErr++
			goto NEXT
		}

		if !nodeResponse.Result {
			resp.Messages[r.From] = nodeResponse.Message
			resp.NumErr++
		}

		// Currently only used for key list queries, this adds keys to a counter
		// and increments them for each node response which contains them.
		for _, key := range nodeResponse.Keys {
			if _, ok := resp.Keys[key]; !ok {
				resp.Keys[key] = 1
			} else {
				resp.Keys[key]++
			}
		}

	NEXT:
		// Return early if all nodes have responded. This allows us to avoid
		// waiting for the full timeout when there is nothing left to do.
		if resp.NumResp == resp.NumNodes {
			return
		}
	}
}

// handleKeyRequest performs query broadcasting to all members for any type of
// key operation and manages gathering responses and packing them up into a
// KeyResponse for uniform response handling.
func (k *keyManager) handleKeyRequest(key, query string) (*KeyResponse, error) {
	resp := &KeyResponse{
		Messages: make(map[string]string),
		Keys:     make(map[string]int),
	}
	qName := internalQueryName(query)

	// Decode the new key into raw bytes
	rawKey, err := base64.StdEncoding.DecodeString(key)
	if err != nil {
		return nil, err
	}

	// Encode the query request
	req, err := encodeMessage(messageKeyRequestType, keyRequest{Key: rawKey})
	if err != nil {
		return nil, err
	}

	qParam := k.serf.DefaultQueryParams()
	queryResp, err := k.serf.Query(qName, req, qParam)
	if err != nil {
		return nil, err
	}

	// Handle the response stream and populate the KeyResponse
	resp.NumNodes = k.serf.memberlist.NumMembers()
	k.streamKeyResp(resp, queryResp.respCh)

	// Check the response for any reported failure conditions
	if resp.NumErr != 0 {
		return resp, fmt.Errorf("%d/%d nodes reported failure", resp.NumErr, resp.NumNodes)
	}
	if resp.NumResp != resp.NumNodes {
		return resp, fmt.Errorf("%d/%d nodes reported success", resp.NumResp, resp.NumNodes)
	}

	return resp, nil
}

// InstallKey handles broadcasting a query to all members and gathering
// responses from each of them, returning a list of messages from each node
// and any applicable error conditions.
func (k *keyManager) InstallKey(key string) (*KeyResponse, error) {
	k.l.Lock()
	defer k.l.Unlock()

	return k.handleKeyRequest(key, installKeyQuery)
}

// UseKey handles broadcasting a primary key change to all members in the
// cluster, and gathering any response messages. If successful, there should
// be an empty KeyResponse returned.
func (k *keyManager) UseKey(key string) (*KeyResponse, error) {
	k.l.Lock()
	defer k.l.Unlock()

	return k.handleKeyRequest(key, useKeyQuery)
}

// RemoveKey handles broadcasting a key to the cluster for removal. Each member
// will receive this event, and if they have the key in their keyring, remove
// it. If any errors are encountered, RemoveKey will collect and relay them.
func (k *keyManager) RemoveKey(key string) (*KeyResponse, error) {
	k.l.Lock()
	defer k.l.Unlock()

	return k.handleKeyRequest(key, removeKeyQuery)
}

// ListKeys is used to collect installed keys from members in a Serf cluster
// and return an aggregated list of all installed keys. This is useful to
// operators to ensure that there are no lingering keys installed on any agents.
// Since having multiple keys installed can cause performance penalties in some
// cases, it's important to verify this information and remove unneeded keys.
func (k *keyManager) ListKeys() (*KeyResponse, error) {
	k.l.RLock()
	defer k.l.RUnlock()

	return k.handleKeyRequest("", listKeysQuery)
}
<|endoftext|>


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

package main

import (
	"github.com/ghodss/yaml"

	"github.com/kubernetes/deployment-manager/expandybird/expander"
	"github.com/kubernetes/deployment-manager/manager/manager"
	"github.com/kubernetes/deployment-manager/registry"

	"bytes"
	"encoding/json"
	"flag"
	"fmt"
	"io"
	"io/ioutil"
	"log"
	"net/http"
	"net/url"
	"os"
	"strconv"
	"strings"
	"time"
)

var (
	// TODO(jackgr): Implement reading a template from stdin
	//stdin       = flag.Bool("stdin", false, "Reads a template from the standard input")
	properties    = flag.String("properties", "", "Properties to use when deploying a type (e.g., --properties k1=v1,k2=v2)")
	type_registry = flag.String("registry", "kubernetes/deployment-manager", "Github based type registry [owner/repo]")
	service       = flag.String("service", "http://localhost:8001/api/v1/proxy/namespaces/default/services/manager-service:manager", "URL for deployment manager")
	binary        = flag.String("binary", "../expandybird/expansion/expansion.py", "Path to template expansion binary")
)

var commands = []string{
	"expand \t\t\t Expands the supplied template(s)",
	"deploy \t\t\t Deploys the supplied type or template(s)",
	"list \t\t\t Lists the deployments in the cluster",
	"get \t\t\t Retrieves the supplied deployment",
	"delete \t\t\t Deletes the supplied deployment",
	"update \t\t\t Updates a deployment using the supplied template(s)",
	"deployed-types \t\t Lists the types deployed in the cluster",
	"deployed-instances \t Lists the instances of the supplied type deployed in the cluster",
	"types \t\t\t Lists the types in the current registry",
	"describe \t\t Describes the supplied type in the current registry",
}

var usage = func() {
	message := "Usage: %s [<flags>] <command> (<type-name> | <deployment-name> | (<template> [<import1>...<importN>]))\n"
	fmt.Fprintf(os.Stderr, message, os.Args[0])
	fmt.Fprintln(os.Stderr, "Commands:")
	for _, command := range commands {
		fmt.Fprintln(os.Stderr, command)
	}

	fmt.Fprintln(os.Stderr)
	fmt.Fprintln(os.Stderr, "Flags:")
	flag.PrintDefaults()
	fmt.Fprintln(os.Stderr)
	os.Exit(1)
}

func getGitRegistry() *registry.GithubRegistry {
	s := strings.Split(*type_registry, "/")
	if len(s) != 2 {
		log.Fatalf("invalid type registry: %s", type_registry)
	}

	return registry.NewGithubRegistry(s[0], s[1])
}

func main() {
	flag.Parse()
	args := flag.Args()
	if len(args) < 1 {
		fmt.Fprintln(os.Stderr, "No command supplied")
		usage()
	}

	command := args[0]
	switch command {
	case "types":
		git := getGitRegistry()
		types, err := git.List()
		if err != nil {
			log.Fatalf("Cannot list %v err")
		}

		fmt.Printf("Types:")
		for _, t := range types {
			fmt.Printf("%s:%s", t.Name, t.Version)
			downloadURL, err := git.GetURL(t)
			if err != nil {
				log.Printf("Failed to get download URL for type %s:%s", t.Name, t.Version)
			}

			fmt.Printf("\tdownload URL: %s", downloadURL)
		}
	case "describe":
		fmt.Printf("this feature is not yet implemented")
	case "expand":
		backend := expander.NewExpander(*binary)
		template := loadTemplate(args)
		output, err := backend.ExpandTemplate(template)
		if err != nil {
			log.Fatalf("cannot expand %s: %s\n", template.Name, err)
		}

		fmt.Println(output)
	case "deploy":
		template := loadTemplate(args)
		action := fmt.Sprintf("deploy template named %s", template.Name)
		callService("deployments", "POST", action, marshalTemplate(template))
	case "list":
		callService("deployments", "GET", "list deployments", nil)
	case "get":
		if len(args) < 2 {
			fmt.Fprintln(os.Stderr, "No deployment name supplied")
			usage()
		}

		path := fmt.Sprintf("deployments/%s", args[1])
		action := fmt.Sprintf("get deployment named %s", args[1])
		callService(path, "GET", action, nil)
	case "delete":
		if len(args) < 2 {
			fmt.Fprintln(os.Stderr, "No deployment name supplied")
			usage()
		}

		path := fmt.Sprintf("deployments/%s", args[1])
		action := fmt.Sprintf("delete deployment named %s", args[1])
		callService(path, "DELETE", action, nil)
	case "update":
		template := loadTemplate(args)
		path := fmt.Sprintf("deployments/%s", template.Name)
		action := fmt.Sprintf("delete deployment named %s", template.Name)
		callService(path, "PUT", action, marshalTemplate(template))
	case "deployed-types":
		action := fmt.Sprintf("list types in registry %s", *type_registry)
		callService("types", "GET", action, nil)
	case "deployed-instances":
		if len(args) < 2 {
			fmt.Fprintln(os.Stderr, "No type name supplied")
			usage()
		}

		path := fmt.Sprintf("types/%s/instances", url.QueryEscape(args[1]))
		action := fmt.Sprintf("list instances of type %s in registry %s", args[1], *type_registry)
		callService(path, "GET", action, nil)
	default:
		usage()
	}
}

func callService(path, method, action string, reader io.ReadCloser) {
	u := fmt.Sprintf("%s/%s", *service, path)
	request, err := http.NewRequest(method, u, reader)
	request.Header.Add("Content-Type", "application/json")
	response, err := http.DefaultClient.Do(request)
	if err != nil {
		log.Fatalf("cannot %s: %s\n", action, err)
	}

	defer response.Body.Close()
	body, err := ioutil.ReadAll(response.Body)
	if err != nil {
		log.Fatalf("cannot %s: %s\n", action, err)
	}

	if response.StatusCode < http.StatusOK ||
		response.StatusCode >= http.StatusMultipleChoices {
		message := fmt.Sprintf("status code: %d status: %s : %s", response.StatusCode, response.Status, body)
		log.Fatalf("cannot %s: %s\n", action, message)
	}

	fmt.Println(string(body))
}

func loadTemplate(args []string) *expander.Template {
	var template *expander.Template
	var err error
	if len(args) < 2 {
		fmt.Fprintln(os.Stderr, "No type name or template file(s) supplied")
		usage()
	}

	if len(args) < 3 {
		if t := getRegistryType(args[1]); t != nil {
			template = buildTemplateFromType(args[1], *t)
		} else {
			template, err = expander.NewTemplateFromRootTemplate(args[1])
		}
	} else {
		template, err = expander.NewTemplateFromFileNames(args[1], args[2:])
	}

	if err != nil {
		log.Fatalf("cannot create template from supplied arguments: %s\n", err)
	}

	return template
}

// TODO: needs better validation that this is actually a registry type.
func getRegistryType(fullType string) *registry.Type {
	tList := strings.Split(fullType, ":")
	if len(tList) != 2 {
		return nil
	}

	return &registry.Type{
		Name:    tList[0],
		Version: tList[1],
	}
}

func buildTemplateFromType(name string, t registry.Type) *expander.Template {
	git := getGitRegistry()
	downloadURL, err := git.GetURL(t)
	if err != nil {
		log.Fatalf("Failed to get download URL for type %s:%s\n%s\n", t.Name, t.Version, err)
	}

	props := make(map[string]interface{})
	if *properties != "" {
		plist := strings.Split(*properties, ",")
		for _, p := range plist {
			ppair := strings.Split(p, "=")
			if len(ppair) != 2 {
				log.Fatalf("--properties must be in the form \"p1=v1,p2=v2,...\": %s\n", p)
			}

			// support ints
			// TODO: needs to support other types.
			i, err := strconv.Atoi(ppair[1])
			if err != nil {
				props[ppair[0]] = ppair[1]
			} else {
				props[ppair[0]] = i
			}
		}
	}

	config := manager.Configuration{Resources: []*manager.Resource{&manager.Resource{
		Name:       name,
		Type:       downloadURL,
		Properties: props,
	}}}

	y, err := yaml.Marshal(config)
	if err != nil {
		log.Fatalf("error: %s\ncannot create configuration for deployment: %v\n", err, config)
	}

	return &expander.Template{
		// Name will be set later.
		Content: string(y),
		// No imports, as this is a single type from repository.
	}
}

func marshalTemplate(template *expander.Template) io.ReadCloser {
	j, err := json.Marshal(template)
	if err != nil {
		log.Fatalf("cannot deploy template %s: %s\n", template.Name, err)
	}

	return ioutil.NopCloser(bytes.NewReader(j))
}

func getRandomName() string {
	return fmt.Sprintf("manifest-%d", time.Now().UTC().UnixNano())
}
<commit_msg>add newlines to listing types<commit_after>/*
Copyright 2015 The Kubernetes Authors All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
    http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package main

import (
	"github.com/ghodss/yaml"

	"github.com/kubernetes/deployment-manager/expandybird/expander"
	"github.com/kubernetes/deployment-manager/manager/manager"
	"github.com/kubernetes/deployment-manager/registry"

	"bytes"
	"encoding/json"
	"flag"
	"fmt"
	"io"
	"io/ioutil"
	"log"
	"net/http"
	"net/url"
	"os"
	"strconv"
	"strings"
	"time"
)

var (
	// TODO(jackgr): Implement reading a template from stdin
	//stdin       = flag.Bool("stdin", false, "Reads a template from the standard input")
	properties    = flag.String("properties", "", "Properties to use when deploying a type (e.g., --properties k1=v1,k2=v2)")
	type_registry = flag.String("registry", "kubernetes/deployment-manager", "Github based type registry [owner/repo]")
	service       = flag.String("service", "http://localhost:8001/api/v1/proxy/namespaces/default/services/manager-service:manager", "URL for deployment manager")
	binary        = flag.String("binary", "../expandybird/expansion/expansion.py", "Path to template expansion binary")
)

var commands = []string{
	"expand \t\t\t Expands the supplied template(s)",
	"deploy \t\t\t Deploys the supplied type or template(s)",
	"list \t\t\t Lists the deployments in the cluster",
	"get \t\t\t Retrieves the supplied deployment",
	"delete \t\t\t Deletes the supplied deployment",
	"update \t\t\t Updates a deployment using the supplied template(s)",
	"deployed-types \t\t Lists the types deployed in the cluster",
	"deployed-instances \t Lists the instances of the supplied type deployed in the cluster",
	"types \t\t\t Lists the types in the current registry",
	"describe \t\t Describes the supplied type in the current registry",
}

var usage = func() {
	message := "Usage: %s [<flags>] <command> (<type-name> | <deployment-name> | (<template> [<import1>...<importN>]))\n"
	fmt.Fprintf(os.Stderr, message, os.Args[0])
	fmt.Fprintln(os.Stderr, "Commands:")
	for _, command := range commands {
		fmt.Fprintln(os.Stderr, command)
	}

	fmt.Fprintln(os.Stderr)
	fmt.Fprintln(os.Stderr, "Flags:")
	flag.PrintDefaults()
	fmt.Fprintln(os.Stderr)
	os.Exit(1)
}

func getGitRegistry() *registry.GithubRegistry {
	s := strings.Split(*type_registry, "/")
	if len(s) != 2 {
		log.Fatalf("invalid type registry: %s", type_registry)
	}

	return registry.NewGithubRegistry(s[0], s[1])
}

func main() {
	flag.Parse()
	args := flag.Args()
	if len(args) < 1 {
		fmt.Fprintln(os.Stderr, "No command supplied")
		usage()
	}

	command := args[0]
	switch command {
	case "types":
		git := getGitRegistry()
		types, err := git.List()
		if err != nil {
			log.Fatalf("Cannot list %v err")
		}

		fmt.Printf("Types:\n")
		for _, t := range types {
			fmt.Printf("%s:%s\n", t.Name, t.Version)
			downloadURL, err := git.GetURL(t)
			if err != nil {
				log.Printf("Failed to get download URL for type %s:%s", t.Name, t.Version)
			}

			fmt.Printf("\tdownload URL: %s\n", downloadURL)
		}
	case "describe":
		fmt.Printf("this feature is not yet implemented")
	case "expand":
		backend := expander.NewExpander(*binary)
		template := loadTemplate(args)
		output, err := backend.ExpandTemplate(template)
		if err != nil {
			log.Fatalf("cannot expand %s: %s\n", template.Name, err)
		}

		fmt.Println(output)
	case "deploy":
		template := loadTemplate(args)
		action := fmt.Sprintf("deploy template named %s", template.Name)
		callService("deployments", "POST", action, marshalTemplate(template))
	case "list":
		callService("deployments", "GET", "list deployments", nil)
	case "get":
		if len(args) < 2 {
			fmt.Fprintln(os.Stderr, "No deployment name supplied")
			usage()
		}

		path := fmt.Sprintf("deployments/%s", args[1])
		action := fmt.Sprintf("get deployment named %s", args[1])
		callService(path, "GET", action, nil)
	case "delete":
		if len(args) < 2 {
			fmt.Fprintln(os.Stderr, "No deployment name supplied")
			usage()
		}

		path := fmt.Sprintf("deployments/%s", args[1])
		action := fmt.Sprintf("delete deployment named %s", args[1])
		callService(path, "DELETE", action, nil)
	case "update":
		template := loadTemplate(args)
		path := fmt.Sprintf("deployments/%s", template.Name)
		action := fmt.Sprintf("delete deployment named %s", template.Name)
		callService(path, "PUT", action, marshalTemplate(template))
	case "deployed-types":
		action := fmt.Sprintf("list types in registry %s", *type_registry)
		callService("types", "GET", action, nil)
	case "deployed-instances":
		if len(args) < 2 {
			fmt.Fprintln(os.Stderr, "No type name supplied")
			usage()
		}

		path := fmt.Sprintf("types/%s/instances", url.QueryEscape(args[1]))
		action := fmt.Sprintf("list instances of type %s in registry %s", args[1], *type_registry)
		callService(path, "GET", action, nil)
	default:
		usage()
	}
}

func callService(path, method, action string, reader io.ReadCloser) {
	u := fmt.Sprintf("%s/%s", *service, path)
	request, err := http.NewRequest(method, u, reader)
	request.Header.Add("Content-Type", "application/json")
	response, err := http.DefaultClient.Do(request)
	if err != nil {
		log.Fatalf("cannot %s: %s\n", action, err)
	}

	defer response.Body.Close()
	body, err := ioutil.ReadAll(response.Body)
	if err != nil {
		log.Fatalf("cannot %s: %s\n", action, err)
	}

	if response.StatusCode < http.StatusOK ||
		response.StatusCode >= http.StatusMultipleChoices {
		message := fmt.Sprintf("status code: %d status: %s : %s", response.StatusCode, response.Status, body)
		log.Fatalf("cannot %s: %s\n", action, message)
	}

	fmt.Println(string(body))
}

func loadTemplate(args []string) *expander.Template {
	var template *expander.Template
	var err error
	if len(args) < 2 {
		fmt.Fprintln(os.Stderr, "No type name or template file(s) supplied")
		usage()
	}

	if len(args) < 3 {
		if t := getRegistryType(args[1]); t != nil {
			template = buildTemplateFromType(args[1], *t)
		} else {
			template, err = expander.NewTemplateFromRootTemplate(args[1])
		}
	} else {
		template, err = expander.NewTemplateFromFileNames(args[1], args[2:])
	}

	if err != nil {
		log.Fatalf("cannot create template from supplied arguments: %s\n", err)
	}

	return template
}

// TODO: needs better validation that this is actually a registry type.
func getRegistryType(fullType string) *registry.Type {
	tList := strings.Split(fullType, ":")
	if len(tList) != 2 {
		return nil
	}

	return &registry.Type{
		Name:    tList[0],
		Version: tList[1],
	}
}

func buildTemplateFromType(name string, t registry.Type) *expander.Template {
	git := getGitRegistry()
	downloadURL, err := git.GetURL(t)
	if err != nil {
		log.Fatalf("Failed to get download URL for type %s:%s\n%s\n", t.Name, t.Version, err)
	}

	props := make(map[string]interface{})
	if *properties != "" {
		plist := strings.Split(*properties, ",")
		for _, p := range plist {
			ppair := strings.Split(p, "=")
			if len(ppair) != 2 {
				log.Fatalf("--properties must be in the form \"p1=v1,p2=v2,...\": %s\n", p)
			}

			// support ints
			// TODO: needs to support other types.
			i, err := strconv.Atoi(ppair[1])
			if err != nil {
				props[ppair[0]] = ppair[1]
			} else {
				props[ppair[0]] = i
			}
		}
	}

	config := manager.Configuration{Resources: []*manager.Resource{&manager.Resource{
		Name:       name,
		Type:       downloadURL,
		Properties: props,
	}}}

	y, err := yaml.Marshal(config)
	if err != nil {
		log.Fatalf("error: %s\ncannot create configuration for deployment: %v\n", err, config)
	}

	return &expander.Template{
		// Name will be set later.
		Content: string(y),
		// No imports, as this is a single type from repository.
	}
}

func marshalTemplate(template *expander.Template) io.ReadCloser {
	j, err := json.Marshal(template)
	if err != nil {
		log.Fatalf("cannot deploy template %s: %s\n", template.Name, err)
	}

	return ioutil.NopCloser(bytes.NewReader(j))
}

func getRandomName() string {
	return fmt.Sprintf("manifest-%d", time.Now().UTC().UnixNano())
}
<|endoftext|>


<commit_before>package smd

import (
	"testing"
	"time"

	"github.com/gonum/floats"
)

func TestPertArbitrary(t *testing.T) {
	R := []float64{6524.834, 6862.875, 6448.296}
	V := []float64{4.901327, 5.533756, -1.976341}
	o := *NewOrbitFromRV(R, V, Earth)

	pertForce := []float64{1, 2, 3, 4, 5, 6, 0}

	arb := func(o Orbit) []float64 {
		return pertForce
	}

	perts := Perturbations{}
	perts.Arbitrary = arb

	if !floats.Equal(pertForce, perts.Perturb(o, time.Now(), Spacecraft{})) {
		t.Fatal("arbitrary pertubations fail")
	}

}

func TestPert3rdBody(t *testing.T) {
	R := []float64{6524.834, 6862.875, 6448.296}
	V := []float64{4.901327, 5.533756, -1.976341}
	o := *NewOrbitFromRV(R, V, Earth)

	testValues := []struct {
		body CelestialObject
		pert []float64
	}{
		{Sun, []float64{-3.983399598736383e-10, 3.984223156196983e-10, -2.689062600261555e-10, 0, 0, 0, 0}},
		{Mars, []float64{-8.34637777124967e-18, -1.3508542238725528e-17, -1.0830758197973537e-17, 0, 0, 0, 0}},
		{Earth, []float64{0, 0, 0, 0, 0, 0, 0}},
	}

	perts := Perturbations{}
	dt, _ := time.Parse(time.RFC822, "01 Jan 15 10:00 UTC")
	for _, test := range testValues {
		perts.PerturbingBody = &test.body
		pert := perts.Perturb(o, dt, Spacecraft{})
		if !floats.Equal(pert, test.pert) {
			t.Fatalf("invalid pertubations for %s\n%+v\n%v", test.body, pert, test.pert)
		}
	}

}
<commit_msg>Fix perturbation test and remove any perturbation but that of the Sun (since only that one is supported until I'm 100% sure of the implementation)<commit_after>package smd

import (
	"testing"
	"time"

	"github.com/gonum/floats"
)

func TestPertArbitrary(t *testing.T) {
	R := []float64{6524.834, 6862.875, 6448.296}
	V := []float64{4.901327, 5.533756, -1.976341}
	o := *NewOrbitFromRV(R, V, Earth)

	pertForce := []float64{1, 2, 3, 4, 5, 6, 0}

	arb := func(o Orbit) []float64 {
		return pertForce
	}

	perts := Perturbations{}
	perts.Arbitrary = arb

	if !floats.Equal(pertForce, perts.Perturb(o, time.Now(), Spacecraft{})) {
		t.Fatal("arbitrary pertubations fail")
	}

}

func TestPert3rdBody(t *testing.T) {
	R := []float64{6524.834, 6862.875, 6448.296}
	V := []float64{4.901327, 5.533756, -1.976341}
	o := *NewOrbitFromRV(R, V, Earth)

	testValues := []struct {
		body CelestialObject
		pert []float64
	}{
		{Sun, []float64{0, 0, 0, -4.4284739788758433e-10, 5.637851322253714e-10, 9.962451049697812e-11, 0}},
	}

	perts := Perturbations{}
	dt, _ := time.Parse(time.RFC822, "01 Jan 15 10:00 UTC")
	for _, test := range testValues {
		perts.PerturbingBody = &test.body
		pert := perts.Perturb(o, dt, Spacecraft{})
		if !floats.Equal(pert, test.pert) {
			t.Fatalf("invalid pertubations for %s\n%+v\n%v", test.body, pert, test.pert)
		}
	}

}
<|endoftext|>


<commit_before>// Copyright 2015 CoreOS, Inc.
//
// 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 types

import (
	"encoding/json"
	"errors"

	"github.com/coreos/ignition/third_party/github.com/coreos/go-semver/semver"
)

var (
	ErrOldVersion = errors.New("incorrect config version (too old)")
	ErrNewVersion = errors.New("incorrect config version (too new)")
)

type Ignition struct {
	Version IgnitionVersion `json:"version,omitempty" yaml:"version" merge:"old"`
	Config  IgnitionConfig  `json:"config,omitempty"  yaml:"config"  merge:"new"`
}

type IgnitionConfig struct {
	Append  []ConfigReference `json:"append,omitempty"  yaml:"append"`
	Replace *ConfigReference  `json:"replace,omitempty" yaml:"replace"`
}

type ConfigReference struct {
	Source       Url          `json:"source,omitempty"       yaml:"source"`
	Verification Verification `json:"verification,omitempty" yaml:"verification"`
}

type IgnitionVersion semver.Version

func (v *IgnitionVersion) UnmarshalYAML(unmarshal func(interface{}) error) error {
	return v.unmarshal(unmarshal)
}

func (v *IgnitionVersion) UnmarshalJSON(data []byte) error {
	return v.unmarshal(func(tv interface{}) error {
		return json.Unmarshal(data, tv)
	})
}

func (v *IgnitionVersion) unmarshal(unmarshal func(interface{}) error) error {
	tv := semver.Version(*v)
	if err := unmarshal(&tv); err != nil {
		return err
	}
	*v = IgnitionVersion(tv)
	return nil
}

func (v IgnitionVersion) AssertValid() error {
	if MaxVersion.Major > v.Major {
		return ErrOldVersion
	}
	if MaxVersion.LessThan(semver.Version(v)) {
		return ErrNewVersion
	}
	return nil
}
<commit_msg>config/types: marshal ignition version correctly<commit_after>// Copyright 2015 CoreOS, Inc.
//
// 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 types

import (
	"encoding/json"
	"errors"

	"github.com/coreos/ignition/third_party/github.com/coreos/go-semver/semver"
)

var (
	ErrOldVersion = errors.New("incorrect config version (too old)")
	ErrNewVersion = errors.New("incorrect config version (too new)")
)

type Ignition struct {
	Version IgnitionVersion `json:"version,omitempty" yaml:"version" merge:"old"`
	Config  IgnitionConfig  `json:"config,omitempty"  yaml:"config"  merge:"new"`
}

type IgnitionConfig struct {
	Append  []ConfigReference `json:"append,omitempty"  yaml:"append"`
	Replace *ConfigReference  `json:"replace,omitempty" yaml:"replace"`
}

type ConfigReference struct {
	Source       Url          `json:"source,omitempty"       yaml:"source"`
	Verification Verification `json:"verification,omitempty" yaml:"verification"`
}

type IgnitionVersion semver.Version

func (v *IgnitionVersion) UnmarshalYAML(unmarshal func(interface{}) error) error {
	return v.unmarshal(unmarshal)
}

func (v *IgnitionVersion) UnmarshalJSON(data []byte) error {
	return v.unmarshal(func(tv interface{}) error {
		return json.Unmarshal(data, tv)
	})
}

func (v IgnitionVersion) MarshalJSON() ([]byte, error) {
	return semver.Version(v).MarshalJSON()
}

func (v *IgnitionVersion) unmarshal(unmarshal func(interface{}) error) error {
	tv := semver.Version(*v)
	if err := unmarshal(&tv); err != nil {
		return err
	}
	*v = IgnitionVersion(tv)
	return nil
}

func (v IgnitionVersion) AssertValid() error {
	if MaxVersion.Major > v.Major {
		return ErrOldVersion
	}
	if MaxVersion.LessThan(semver.Version(v)) {
		return ErrNewVersion
	}
	return nil
}
<|endoftext|>


<commit_before>package main

import (
	"os/exec"
	"github.com/wsxiaoys/terminal"
	"time"
	"fmt"
	"strings"
	"sync"
)

type Runner struct{
	project *Project
}

func (r *Runner) Start() {
	var wg sync.WaitGroup
	total := len(r.project.global) + len(r.project.local)
	pending, complete := make(chan Process), make(chan string)
	for i:=0;i<total;i++{
		wg.Add(1)
		go r.Run(pending, complete, &wg)
	}
	for _, process := range r.project.global {
		pending <- process
	}
	for _, process := range r.project.local {
		pending <- process
	}

	for message := range complete {
		fmt.Println( message)
	}
	wg.Wait()
}

func (r *Runner) Run(in <-chan Process, out chan<- string, wg *sync.WaitGroup) {
	for process := range in{
		var commands []string
		commands = strings.Split(process.command, " ")

		var args []string

		program := commands[0]
		if(len(commands) > 1){
			args = append(commands[:0], commands[1:]...)
		}else{
			args = []string{}
		}

		cmd := exec.Command(program, args...)

		stdout, err := cmd.StdoutPipe()
		if err != nil {
			fmt.Println(err)
		}

		err = cmd.Start()
		if err != nil {
			fmt.Println(err)
		}
		ch := make(chan string)
		quit := make(chan bool)
		go func() {
			buf := make([]byte, 1024)
			for {
				n, err := stdout.Read(buf)
				if n != 0 {
					ch <- string(buf[:n])
				}
				if err != nil {
					break
				}
			}
			fmt.Println("Goroutine finished")
			close(ch)
		}()

		time.AfterFunc(time.Second, func() { quit <- true })

		loop:
		for {
			select {
				case lines, ok := <-ch:
					if !ok {
						break loop
					}
					for _, line := range strings.Split(lines, "\n") {
						if(line == ""){
							continue
						}
						terminal.Stderr.
						Color(process.color).Print(fmt.Sprintf("[%s] ", process.name)).
						Reset().Print(line).Nl()
					}
			}
		}

		if err != nil{
			out <- fmt.Sprintf("%s failed to start (%s)", process.name, err)
			wg.Done()
			return
		}
		out <- fmt.Sprintf("%s started. Command: %s. Args: %s", process.name, program, args)
		err = cmd.Wait()
		if err != nil{
			out <- fmt.Sprintf("%s failed to wait (%s)", process.name, err)
			wg.Done()
			return
		}
		out <- fmt.Sprintf("%s finished", process.name)
		wg.Done()
	}
}

<commit_msg>Unneccessary output<commit_after>package main

import (
	"os/exec"
	"github.com/wsxiaoys/terminal"
	"time"
	"fmt"
	"strings"
	"sync"
)

type Runner struct{
	project *Project
}

func (r *Runner) Start() {
	var wg sync.WaitGroup
	total := len(r.project.global) + len(r.project.local)
	pending, complete := make(chan Process), make(chan string)
	for i:=0;i<total;i++{
		wg.Add(1)
		go r.Run(pending, complete, &wg)
	}
	for _, process := range r.project.global {
		pending <- process
	}
	for _, process := range r.project.local {
		pending <- process
	}

	for message := range complete {
		fmt.Println( message)
	}
	wg.Wait()
}

func (r *Runner) Run(in <-chan Process, out chan<- string, wg *sync.WaitGroup) {
	for process := range in{
		var commands []string
		commands = strings.Split(process.command, " ")

		var args []string

		program := commands[0]
		if(len(commands) > 1){
			args = append(commands[:0], commands[1:]...)
		}else{
			args = []string{}
		}

		cmd := exec.Command(program, args...)

		stdout, err := cmd.StdoutPipe()
		if err != nil {
			fmt.Println(err)
		}

		err = cmd.Start()
		if err != nil {
			fmt.Println(err)
		}
		ch := make(chan string)
		quit := make(chan bool)
		go func() {
			buf := make([]byte, 1024)
			for {
				n, err := stdout.Read(buf)
				if n != 0 {
					ch <- string(buf[:n])
				}
				if err != nil {
					break
				}
			}
			close(ch)
		}()

		time.AfterFunc(time.Second, func() { quit <- true })

		loop:
		for {
			select {
				case lines, ok := <-ch:
					if !ok {
						break loop
					}
					for _, line := range strings.Split(lines, "\n") {
						if(line == ""){
							continue
						}
						terminal.Stderr.
						Color(process.color).Print(fmt.Sprintf("[%s] ", process.name)).
						Reset().Print(line).Nl()
					}
			}
		}

		if err != nil{
			out <- fmt.Sprintf("%s failed to start (%s)", process.name, err)
			wg.Done()
			return
		}
		out <- fmt.Sprintf("%s started. Command: %s. Args: %s", process.name, program, args)
		err = cmd.Wait()
		if err != nil{
			out <- fmt.Sprintf("%s failed to wait (%s)", process.name, err)
			wg.Done()
			return
		}
		out <- fmt.Sprintf("%s finished", process.name)
		wg.Done()
	}
}

<|endoftext|>