<commit_before>package main

import (
	"bufio"
	"encoding/csv"
	"flag"
	"fmt"
	"os"
	"path/filepath"
	"strings"
	"time"

	"github.com/AlexanderThaller/logger"
	"github.com/jinzhu/now"
	"github.com/juju/errgo"
)

var (
	flagSource        = flag.String("src", "source.asciidoc", "")
	flagOutFolderPath = flag.String("out", "out", "")
)

func init() {
	flag.Parse()

	now.TimeFormats = append(now.TimeFormats, time.ANSIC)
	now.TimeFormats = append(now.TimeFormats, time.UnixDate)
	now.TimeFormats = append(now.TimeFormats, time.RubyDate)
	now.TimeFormats = append(now.TimeFormats, time.RFC822)
	now.TimeFormats = append(now.TimeFormats, time.RFC822Z)
	now.TimeFormats = append(now.TimeFormats, time.RFC850)
	now.TimeFormats = append(now.TimeFormats, time.RFC1123)
	now.TimeFormats = append(now.TimeFormats, time.RFC1123Z)
	now.TimeFormats = append(now.TimeFormats, time.RFC3339)
	now.TimeFormats = append(now.TimeFormats, time.RFC3339Nano)
	now.TimeFormats = append(now.TimeFormats, "Mon, _2 Jan 2006 15:04:05 MST")
	now.TimeFormats = append(now.TimeFormats, "Mon, _2 Jan 2006 15:04:05 -0700")
	now.TimeFormats = append(now.TimeFormats, "Mon, _2 January 2006 15:04:05 MST")
	now.TimeFormats = append(now.TimeFormats, "Mon, _2 January 2006 15:04:05 -0700")
	now.TimeFormats = append(now.TimeFormats, "Mon, _2 Jan 06 15:04:05 -0700")
	now.TimeFormats = append(now.TimeFormats, "Mon _2. Jan 15:04:05 MST 2006")
	now.TimeFormats = append(now.TimeFormats, "_2 Jan 2006 15:04:05 -0700")
	now.TimeFormats = append(now.TimeFormats, "2006.01.02-15.04.05")
	now.TimeFormats = append(now.TimeFormats, "2006.01.02")
	now.TimeFormats = append(now.TimeFormats, "2006.01.02---- ")
	now.TimeFormats = append(now.TimeFormats, "2006.01.02 - 15:04:05")
}

func main() {
	l := logger.New("main")
	l.SetLevel(logger.Debug)

	file, err := os.OpenFile(*flagSource, os.O_RDONLY, 0640)
	if err != nil {
		l.Alert("Can not open file: ", file)
		return
	}
	defer file.Close()
	scanner := bufio.NewScanner(file)

	var notes []Note
	var project string
	var timestamp time.Time
	var value string
	for scanner.Scan() {
		entry := scanner.Text()

		if strings.HasPrefix(entry, "==== ") ||
			strings.HasPrefix(entry, "===== ") ||
			strings.HasPrefix(entry, "====== ") {

			value += strings.TrimPrefix(entry, "===")
			value += "\n"
			continue
		}

		if strings.HasPrefix(entry, "=== ") {
			oldtimestamp := timestamp
			entrytrim := strings.TrimPrefix(entry, "=== ")
			stamp, err := now.Parse(entrytrim)
			if err != nil {
				l.Alert("Can not parse timestamp: ", err)
				return
			}
			timestamp = stamp

			if oldtimestamp.Equal(time.Time{}) {
				continue
			}

			note := Note{
				Project:   project,
				TimeStamp: timestamp,
				Value:     value,
			}
			fmt.Printf("note: %+v\n", note)
			value = ""

			notes = append(notes, note)
			continue
		}

		if strings.HasPrefix(entry, "== ") {
			oldproject := project
			entrytrim := strings.TrimPrefix(entry, "== ")
			project = entrytrim

			if oldproject == "" {
				continue
			}

			note := Note{
				Project:   project,
				TimeStamp: timestamp,
				Value:     value,
			}
			fmt.Printf("note: %+v\n", note)
			value = ""
			timestamp = time.Time{}

			notes = append(notes, note)
			continue
		}

		value += entry
		value += "\n"
	}

	err = os.MkdirAll(*flagOutFolderPath, 0750)
	if err != nil {
		l.Alert(errgo.New(err.Error()))
		os.Exit(1)
	}

	for _, note := range notes {
		filepath := filepath.Join(*flagOutFolderPath, note.Project+".csv")
		file, err := os.OpenFile(filepath, os.O_RDWR|os.O_APPEND|os.O_CREATE, 0640)
		if err != nil {
			l.Alert(errgo.New(err.Error()))
			os.Exit(1)
		}

		writer := csv.NewWriter(file)

		message := []string{
			note.TimeStamp.Format(time.RFC3339Nano),
			"note",
			strings.TrimSpace(note.Value),
		}

		err = writer.Write(message)
		if err != nil {
			l.Alert(errgo.New(err.Error()))
			os.Exit(1)
		}

		writer.Flush()
		file.Close()
	}
}

type Note struct {
	Project   string
	TimeStamp time.Time
	Value     string
}
<commit_msg>improved importAsciidoc script.<commit_after>package main

import (
	"bufio"
	"encoding/csv"
	"flag"
	"fmt"
	"os"
	"path/filepath"
	"strings"
	"time"

	"github.com/AlexanderThaller/logger"
	"github.com/jinzhu/now"
	"github.com/juju/errgo"
)

var (
	flagSource        = flag.String("src", "source.asciidoc", "")
	flagOutFolderPath = flag.String("out", "out", "")
)

func init() {
	flag.Parse()

	now.TimeFormats = append(now.TimeFormats, time.ANSIC)
	now.TimeFormats = append(now.TimeFormats, time.UnixDate)
	now.TimeFormats = append(now.TimeFormats, time.RubyDate)
	now.TimeFormats = append(now.TimeFormats, time.RFC822)
	now.TimeFormats = append(now.TimeFormats, time.RFC822Z)
	now.TimeFormats = append(now.TimeFormats, time.RFC850)
	now.TimeFormats = append(now.TimeFormats, time.RFC1123)
	now.TimeFormats = append(now.TimeFormats, time.RFC1123Z)
	now.TimeFormats = append(now.TimeFormats, time.RFC3339)
	now.TimeFormats = append(now.TimeFormats, time.RFC3339Nano)
	now.TimeFormats = append(now.TimeFormats, "Mon, _2 Jan 2006 15:04:05 MST")
	now.TimeFormats = append(now.TimeFormats, "Mon, _2 Jan 2006 15:04:05 -0700")
	now.TimeFormats = append(now.TimeFormats, "Mon, _2 January 2006 15:04:05 MST")
	now.TimeFormats = append(now.TimeFormats, "Mon, _2 January 2006 15:04:05 -0700")
	now.TimeFormats = append(now.TimeFormats, "Mon, _2 Jan 06 15:04:05 -0700")
	now.TimeFormats = append(now.TimeFormats, "Mon _2. Jan 15:04:05 MST 2006")
	now.TimeFormats = append(now.TimeFormats, "_2 Jan 2006 15:04:05 -0700")
	now.TimeFormats = append(now.TimeFormats, "2006.01.02-15.04.05")
	now.TimeFormats = append(now.TimeFormats, "2006.01.02")
	now.TimeFormats = append(now.TimeFormats, "2006.01.02---- ")
	now.TimeFormats = append(now.TimeFormats, "2006.01.02 - 15:04:05")
}

func main() {
	l := logger.New("main")
	l.SetLevel(logger.Debug)

	file, err := os.OpenFile(*flagSource, os.O_RDONLY, 0640)
	if err != nil {
		l.Alert("Can not open file: ", file)
		return
	}
	defer file.Close()
	scanner := bufio.NewScanner(file)

	var notes []Note
	var project string
	var timestamp time.Time
	var value string
	var inverbatimenv bool
	for scanner.Scan() {
		entry := scanner.Text()

		if strings.HasPrefix(entry, "----") {
			if inverbatimenv {
				inverbatimenv = false
			} else {
				inverbatimenv = true
			}
		}

		if !inverbatimenv {
			if strings.HasPrefix(entry, "==== ") ||
				strings.HasPrefix(entry, "===== ") ||
				strings.HasPrefix(entry, "====== ") {

				value += strings.TrimPrefix(entry, "===")
				value += "\n"
				continue
			}

			if strings.HasPrefix(entry, "=== ") {
				oldtimestamp := timestamp
				entrytrim := strings.TrimPrefix(entry, "=== ")
				stamp, err := now.Parse(entrytrim)
				if err != nil {
					l.Alert("Can not parse timestamp: ", err)
					return
				}
				timestamp = stamp

				if oldtimestamp.Equal(time.Time{}) {
					continue
				}

				note := Note{
					Project:   project,
					TimeStamp: oldtimestamp,
					Value:     value,
				}
				fmt.Printf("note: %+v\n", note)
				value = ""

				notes = append(notes, note)
				continue
			}

			if strings.HasPrefix(entry, "== ") {
				oldproject := project
				entrytrim := strings.TrimPrefix(entry, "== ")
				project = entrytrim

				if oldproject == "" {
					continue
				}

				note := Note{
					Project:   oldproject,
					TimeStamp: timestamp,
					Value:     value,
				}
				fmt.Printf("note: %+v\n", note)
				value = ""
				timestamp = time.Time{}

				notes = append(notes, note)
				continue
			}
		}

		value += entry
		value += "\n"
	}

	err = os.MkdirAll(*flagOutFolderPath, 0750)
	if err != nil {
		l.Alert(errgo.New(err.Error()))
		os.Exit(1)
	}

	for _, note := range notes {
		filepath := filepath.Join(*flagOutFolderPath, note.Project+".csv")
		file, err := os.OpenFile(filepath, os.O_RDWR|os.O_APPEND|os.O_CREATE, 0640)
		if err != nil {
			l.Alert(errgo.New(err.Error()))
			os.Exit(1)
		}

		writer := csv.NewWriter(file)

		message := []string{
			note.TimeStamp.Format(time.RFC3339Nano),
			"note",
			strings.TrimSpace(note.Value),
		}

		err = writer.Write(message)
		if err != nil {
			l.Alert(errgo.New(err.Error()))
			os.Exit(1)
		}

		writer.Flush()
		file.Close()
	}
}

type Note struct {
	Project   string
	TimeStamp time.Time
	Value     string
}
<|endoftext|>


<commit_before>// Copyright (c) 2017 Cisco and/or its affiliates.
//
// 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 vppcalls

import (
	"fmt"
	"net"
	"time"

	govppapi "git.fd.io/govpp.git/api"
	"github.com/ligato/cn-infra/logging/measure"
	"github.com/ligato/vpp-agent/plugins/defaultplugins/common/bin_api/vxlan"
	intf "github.com/ligato/vpp-agent/plugins/defaultplugins/common/model/interfaces"
)

func addDelVxlanTunnel(iface *intf.Interfaces_Interface_Vxlan, encVrf uint32, isAdd bool, vppChan *govppapi.Channel, stopwatch *measure.Stopwatch) (swIdx uint32, err error) {
	defer func(t time.Time) {
		stopwatch.TimeLog(vxlan.VxlanAddDelTunnel{}).LogTimeEntry(time.Since(t))
	}(time.Now())

	// this is temporary fix to solve creation of VRF table for VXLAN
	if err := CreateVrfIfNeeded(encVrf, vppChan); err != nil {
		return 0, err
	}

	req := &vxlan.VxlanAddDelTunnel{
		IsAdd:          boolToUint(isAdd),
		Vni:            iface.Vni,
		DecapNextIndex: 0xFFFFFFFF,
		EncapVrfID:     encVrf,
	}

	srcAddr := net.ParseIP(iface.SrcAddress).To4()
	if srcAddr == nil {
		srcAddr = net.ParseIP(iface.SrcAddress).To16()
		if srcAddr == nil {
			return 0, fmt.Errorf("invalid VXLAN source address")
		}
		req.IsIpv6 = 1
	} else {
		req.IsIpv6 = 0
	}
	req.SrcAddress = []byte(srcAddr)

	var dstAddr net.IP
	if req.IsIpv6 == 0 {
		dstAddr = net.ParseIP(iface.DstAddress).To4()
	} else {
		dstAddr = net.ParseIP(iface.DstAddress).To16()
	}
	if dstAddr == nil {
		return 0, fmt.Errorf("IP version mismatch for VXLAN destination and source IP addresses")
	}
	req.DstAddress = []byte(dstAddr)

	reply := &vxlan.VxlanAddDelTunnelReply{}
	if err = vppChan.SendRequest(req).ReceiveReply(reply); err != nil {
		return 0, err
	}
	if reply.Retval != 0 {
		return 0, fmt.Errorf("%s returned %d", reply.GetMessageName(), reply.Retval)
	}

	return reply.SwIfIndex, nil
}

// AddVxlanTunnel calls AddDelVxlanTunnelReq with flag add=1.
func AddVxlanTunnel(ifName string, vxlanIntf *intf.Interfaces_Interface_Vxlan, encapVrf uint32, vppChan *govppapi.Channel, stopwatch *measure.Stopwatch) (swIndex uint32, err error) {
	swIfIdx, err := addDelVxlanTunnel(vxlanIntf, encapVrf, true, vppChan, stopwatch)
	if err != nil {
		return 0, err
	}
	return swIfIdx, SetInterfaceTag(ifName, swIfIdx, vppChan, stopwatch)
}

// DeleteVxlanTunnel calls AddDelVxlanTunnelReq with flag add=0.
func DeleteVxlanTunnel(ifName string, idx uint32, vxlanIntf *intf.Interfaces_Interface_Vxlan, vppChan *govppapi.Channel, stopwatch *measure.Stopwatch) error {
	if _, err := addDelVxlanTunnel(vxlanIntf, 0, false, vppChan, stopwatch); err != nil {
		return err
	}
	return RemoveInterfaceTag(ifName, idx, vppChan, stopwatch)
}
<commit_msg>Fix vxlan issue<commit_after>// Copyright (c) 2017 Cisco and/or its affiliates.
//
// 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 vppcalls

import (
	"fmt"
	"net"
	"time"

	govppapi "git.fd.io/govpp.git/api"
	"github.com/ligato/cn-infra/logging/measure"
	"github.com/ligato/vpp-agent/plugins/defaultplugins/common/bin_api/vxlan"
	intf "github.com/ligato/vpp-agent/plugins/defaultplugins/common/model/interfaces"
)

const vxlanInstanceUnset = ^uint32(0)

func addDelVxlanTunnel(iface *intf.Interfaces_Interface_Vxlan, encVrf uint32, isAdd bool, vppChan *govppapi.Channel, stopwatch *measure.Stopwatch) (swIdx uint32, err error) {
	defer func(t time.Time) {
		stopwatch.TimeLog(vxlan.VxlanAddDelTunnel{}).LogTimeEntry(time.Since(t))
	}(time.Now())

	// this is temporary fix to solve creation of VRF table for VXLAN
	if err := CreateVrfIfNeeded(encVrf, vppChan); err != nil {
		return 0, err
	}

	req := &vxlan.VxlanAddDelTunnel{
		IsAdd:          boolToUint(isAdd),
		Vni:            iface.Vni,
		DecapNextIndex: 0xFFFFFFFF,
		Instance: vxlanInstanceUnset,
		EncapVrfID:     encVrf,
	}

	srcAddr := net.ParseIP(iface.SrcAddress).To4()
	if srcAddr == nil {
		srcAddr = net.ParseIP(iface.SrcAddress).To16()
		if srcAddr == nil {
			return 0, fmt.Errorf("invalid VXLAN source address")
		}
		req.IsIpv6 = 1
	} else {
		req.IsIpv6 = 0
	}
	req.SrcAddress = []byte(srcAddr)

	var dstAddr net.IP
	if req.IsIpv6 == 0 {
		dstAddr = net.ParseIP(iface.DstAddress).To4()
	} else {
		dstAddr = net.ParseIP(iface.DstAddress).To16()
	}
	if dstAddr == nil {
		return 0, fmt.Errorf("IP version mismatch for VXLAN destination and source IP addresses")
	}
	req.DstAddress = []byte(dstAddr)

	reply := &vxlan.VxlanAddDelTunnelReply{}
	if err = vppChan.SendRequest(req).ReceiveReply(reply); err != nil {
		return 0, err
	}
	if reply.Retval != 0 {
		return 0, fmt.Errorf("%s returned %d", reply.GetMessageName(), reply.Retval)
	}

	return reply.SwIfIndex, nil
}

// AddVxlanTunnel calls AddDelVxlanTunnelReq with flag add=1.
func AddVxlanTunnel(ifName string, vxlanIntf *intf.Interfaces_Interface_Vxlan, encapVrf uint32, vppChan *govppapi.Channel, stopwatch *measure.Stopwatch) (swIndex uint32, err error) {
	swIfIdx, err := addDelVxlanTunnel(vxlanIntf, encapVrf, true, vppChan, stopwatch)
	if err != nil {
		return 0, err
	}
	return swIfIdx, SetInterfaceTag(ifName, swIfIdx, vppChan, stopwatch)
}

// DeleteVxlanTunnel calls AddDelVxlanTunnelReq with flag add=0.
func DeleteVxlanTunnel(ifName string, idx uint32, vxlanIntf *intf.Interfaces_Interface_Vxlan, vppChan *govppapi.Channel, stopwatch *measure.Stopwatch) error {
	if _, err := addDelVxlanTunnel(vxlanIntf, 0, false, vppChan, stopwatch); err != nil {
		return err
	}
	return RemoveInterfaceTag(ifName, idx, vppChan, stopwatch)
}
<|endoftext|>


<commit_before>package dagutils

import (
	"context"
	"fmt"

	mdag "github.com/ipfs/go-ipfs/merkledag"

	cid "gx/ipfs/QmNp85zy9RLrQ5oQD4hPyS39ezrrXpcaa7R4Y9kxdWQLLQ/go-cid"
	node "gx/ipfs/QmPN7cwmpcc4DWXb4KTB9dNAJgjuPY69h3npsMfhRrQL9c/go-ipld-format"
)

// DiffEnumerate fetches every object in the graph pointed to by 'to' that is
// not in 'from'. This can be used to more efficiently fetch a graph if you can
// guarantee you already have the entirety of 'from'
func DiffEnumerate(ctx context.Context, dserv node.NodeGetter, from, to *cid.Cid) error {
	fnd, err := dserv.Get(ctx, from)
	if err != nil {
		return fmt.Errorf("get %s: %s", from, err)
	}

	tnd, err := dserv.Get(ctx, to)
	if err != nil {
		return fmt.Errorf("get %s: %s", to, err)
	}

	diff := getLinkDiff(fnd, tnd)

	sset := cid.NewSet()
	for _, c := range diff {
		// Since we're already assuming we have everything in the 'from' graph,
		// add all those cids to our 'already seen' set to avoid potentially
		// enumerating them later
		if c.bef != nil {
			sset.Add(c.bef)
		}
	}
	for _, c := range diff {
		if c.bef == nil {
			if sset.Has(c.aft) {
				continue
			}
			err := mdag.EnumerateChildrenAsync(ctx, mdag.GetLinksDirect(dserv), c.aft, sset.Visit)
			if err != nil {
				return err
			}
		} else {
			err := DiffEnumerate(ctx, dserv, c.bef, c.aft)
			if err != nil {
				return err
			}
		}
	}

	return nil
}

// if both bef and aft are not nil, then that signifies bef was replaces with aft.
// if bef is nil and aft is not, that means aft was newly added
// if aft is nil and bef is not, that means bef was deleted
type diffpair struct {
	bef, aft *cid.Cid
}

// getLinkDiff returns a changeset between nodes 'a' and 'b'. Currently does
// not log deletions as our usecase doesnt call for this.
func getLinkDiff(a, b node.Node) []diffpair {
	have := make(map[string]*node.Link)
	names := make(map[string]*node.Link)
	for _, l := range a.Links() {
		have[l.Cid.KeyString()] = l
		names[l.Name] = l
	}

	var out []diffpair

	for _, l := range b.Links() {
		if have[l.Cid.KeyString()] != nil {
			continue
		}

		match, ok := names[l.Name]
		if !ok {
			out = append(out, diffpair{aft: l.Cid})
			continue
		}

		out = append(out, diffpair{bef: match.Cid, aft: l.Cid})
	}
	return out
}
<commit_msg>optimise pin update command<commit_after>package dagutils

import (
	"context"
	"fmt"

	mdag "github.com/ipfs/go-ipfs/merkledag"

	cid "gx/ipfs/QmNp85zy9RLrQ5oQD4hPyS39ezrrXpcaa7R4Y9kxdWQLLQ/go-cid"
	node "gx/ipfs/QmPN7cwmpcc4DWXb4KTB9dNAJgjuPY69h3npsMfhRrQL9c/go-ipld-format"
)

// DiffEnumerate fetches every object in the graph pointed to by 'to' that is
// not in 'from'. This can be used to more efficiently fetch a graph if you can
// guarantee you already have the entirety of 'from'
func DiffEnumerate(ctx context.Context, dserv node.NodeGetter, from, to *cid.Cid) error {
	fnd, err := dserv.Get(ctx, from)
	if err != nil {
		return fmt.Errorf("get %s: %s", from, err)
	}

	tnd, err := dserv.Get(ctx, to)
	if err != nil {
		return fmt.Errorf("get %s: %s", to, err)
	}

	diff := getLinkDiff(fnd, tnd)

	sset := cid.NewSet()
	for _, c := range diff {
		// Since we're already assuming we have everything in the 'from' graph,
		// add all those cids to our 'already seen' set to avoid potentially
		// enumerating them later
		if c.bef != nil {
			sset.Add(c.bef)
		}
	}
	for _, c := range diff {
		if c.bef == nil {
			if sset.Has(c.aft) {
				continue
			}
			err := mdag.EnumerateChildrenAsync(ctx, mdag.GetLinksDirect(dserv), c.aft, sset.Visit)
			if err != nil {
				return err
			}
		} else {
			err := DiffEnumerate(ctx, dserv, c.bef, c.aft)
			if err != nil {
				return err
			}
		}
	}

	return nil
}

// if both bef and aft are not nil, then that signifies bef was replaces with aft.
// if bef is nil and aft is not, that means aft was newly added
// if aft is nil and bef is not, that means bef was deleted
type diffpair struct {
	bef, aft *cid.Cid
}

// getLinkDiff returns a changeset between nodes 'a' and 'b'. Currently does
// not log deletions as our usecase doesnt call for this.
func getLinkDiff(a, b node.Node) []diffpair {
	ina := make(map[string]*node.Link)
	inb := make(map[string]*node.Link)
	var aonly []*cid.Cid
	for _, l := range b.Links() {
		inb[l.Cid.KeyString()] = l
	}
	for _, l := range a.Links() {
		ina[l.Cid.KeyString()] = l
		if inb[l.Cid.KeyString()] == nil {
			aonly = append(aonly, l.Cid)
		}
	}

	var out []diffpair
	var aindex = 0

	for _, l := range b.Links() {
		if ina[l.Cid.KeyString()] != nil {
			continue
		}

		if aindex < len(aonly) {
			out = append(out, diffpair{bef: aonly[aindex], aft: l.Cid})
			aindex++
		} else {
			out = append(out, diffpair{aft: l.Cid})
			continue
		}
	}
	return out
}
<|endoftext|>


<commit_before>package flagmqtt

import (
	"crypto/tls"
	"crypto/x509"
	"errors"
	"fmt"
	mq "github.com/eclipse/paho.mqtt.golang"
	"github.com/satori/go.uuid"
	"io/ioutil"
	"os"
	"strings"
	"time"
)

type ClientConfig struct {
	WillTopic   string
	WillPayload string
	WillQoS     int
	WillRetain  bool
	ClientID    string
}

func NewPersistantMqtt(config ClientConfig) (mqttClient mq.Client, err error) {
	useTls := false

	if val, ok := os.LookupEnv("MQTT_TLS"); ok {
		useTls = val != "0" && val != "" && strings.ToLower(val) != "false"
	}
	if *mqttTLSFlag {
		useTls = true
	}

	caPath := envOrFlagStr(*MqttCAFlag, "MQTT_CA_PATH", "")
	certPath := envOrFlagStr(*MqttCertFlag, "MQTT_CERT_PATH", "")
	keyPath := envOrFlagStr(*MqttKeyFlag, "MQTT_KEY_PATH", "")
	address := envOrFlagStr(*MqttAddressFlag, "MQTT_ADDRESS", "localhost:1883")
	username := envOrFlagStr(*MqttUsernameFlag, "MQTT_USERNAME", "")
	password := envOrFlagStr(*MqttPasswordFlag, "MQTT_PASSWORD", "")
	connectionTimeout := envOrFlagInt(*MqttConnectionTimeout, "MQTT_CONNECTION_TIMEOUT", 10)
	keepAlive := envOrFlagInt(*MqttKeepAlive, "MQTT_KEEPALIVE", 5)
	maxReconnectInterval := envOrFlagInt(*MqttMaxReconnectInterval, "MQTT_MAX_RECONNECT_INTERVAL", 2)
	pingTimeout := envOrFlagInt(*MqttPingTimeout, "MQTT_PING_TIMEOUT", 10)
	writeTimeout := envOrFlagInt(*MqttWriteTimeout, "MQTT_WRITE_TIMEOUT", 5)

	var tlsCfg *tls.Config
	if useTls {
		tlsCfg, err = setupTLS(caPath, certPath, keyPath)
		if err != nil {
			return
		}
	}

	clientId := config.ClientID

	if clientId == "" {
		var rndUuid uuid.UUID
		rndUuid = uuid.NewV4()
		clientId = rndUuid.String()
	}

	pts := mq.NewClientOptions().
		AddBroker(fmt.Sprintf("tcp://%s", address)).
		SetClientID(clientId).
		SetConnectTimeout(time.Duration(connectionTimeout) * time.Second).
		SetKeepAlive(time.Duration(keepAlive) * time.Second).
		SetMaxReconnectInterval(time.Duration(maxReconnectInterval) * time.Minute).
		SetMessageChannelDepth(100).
		SetPingTimeout(time.Duration(pingTimeout) * time.Second).
		SetProtocolVersion(4).
		SetWriteTimeout(time.Duration(writeTimeout) * time.Second)

	if config.WillTopic != "" {
		opts.SetWill(
			config.WillTopic,
			config.WillPayload,
			byte(config.WillQoS&0xff),
			config.WillRetain,
		)
	}

	if username != "" {
		opts.SetUsername(username)
	}
	if password != "" {
		opts.SetPassword(password)
	}
	if useTls {
		opts.SetTLSConfig(tlsCfg)
	}

	return mq.NewClient(opts), nil
}

func setupTLS(caPath, certPath, keyPath string) (*tls.Config, error) {
	tlsCfg := &tls.Config{}
	if caPath != "" {
		caPem, err := ioutil.ReadFile(caPath)
		if err != nil {
			return nil, err
		}
		tlsCfg.RootCAs = x509.NewCertPool()
		tlsCfg.RootCAs.AppendCertsFromPEM(caPem)
	}

	if certPath != "" && keyPath != "" {
		if keyPath == "" {
			return nil, errors.New("Certificate path specified, but key path missing")
		}
		cert, err := tls.LoadX509KeyPair(certPath, keyPath)
		if err != nil {
			return nil, err
		}
		tlsCfg.Certificates = []tls.Certificate{cert}
		tlsCfg.BuildNameToCertificate()
	}

	return tlsCfg, nil
}
<commit_msg>:ambulance: Correct variable names<commit_after>package flagmqtt

import (
	"crypto/tls"
	"crypto/x509"
	"errors"
	"fmt"
	mq "github.com/eclipse/paho.mqtt.golang"
	"github.com/satori/go.uuid"
	"io/ioutil"
	"os"
	"strings"
	"time"
)

type ClientConfig struct {
	WillTopic   string
	WillPayload string
	WillQoS     int
	WillRetain  bool
	ClientID    string
}

func NewPersistantMqtt(config ClientConfig) (mqttClient mq.Client, err error) {
	useTls := false

	if val, ok := os.LookupEnv("MQTT_TLS"); ok {
		useTls = val != "0" && val != "" && strings.ToLower(val) != "false"
	}
	if *MqttTLSFlag {
		useTls = true
	}

	caPath := envOrFlagStr(*MqttCAFlag, "MQTT_CA_PATH", "")
	certPath := envOrFlagStr(*MqttCertFlag, "MQTT_CERT_PATH", "")
	keyPath := envOrFlagStr(*MqttKeyFlag, "MQTT_KEY_PATH", "")
	address := envOrFlagStr(*MqttAddressFlag, "MQTT_ADDRESS", "localhost:1883")
	username := envOrFlagStr(*MqttUsernameFlag, "MQTT_USERNAME", "")
	password := envOrFlagStr(*MqttPasswordFlag, "MQTT_PASSWORD", "")
	connectionTimeout := envOrFlagInt(*MqttConnectionTimeout, "MQTT_CONNECTION_TIMEOUT", 10)
	keepAlive := envOrFlagInt(*MqttKeepAlive, "MQTT_KEEPALIVE", 5)
	maxReconnectInterval := envOrFlagInt(*MqttMaxReconnectInterval, "MQTT_MAX_RECONNECT_INTERVAL", 2)
	pingTimeout := envOrFlagInt(*MqttPingTimeout, "MQTT_PING_TIMEOUT", 10)
	writeTimeout := envOrFlagInt(*MqttWriteTimeout, "MQTT_WRITE_TIMEOUT", 5)

	var tlsCfg *tls.Config
	if useTls {
		tlsCfg, err = setupTLS(caPath, certPath, keyPath)
		if err != nil {
			return
		}
	}

	clientId := config.ClientID

	if clientId == "" {
		var rndUuid uuid.UUID
		rndUuid = uuid.NewV4()
		clientId = rndUuid.String()
	}

	opts := mq.NewClientOptions().
		AddBroker(fmt.Sprintf("tcp://%s", address)).
		SetClientID(clientId).
		SetConnectTimeout(time.Duration(connectionTimeout) * time.Second).
		SetKeepAlive(time.Duration(keepAlive) * time.Second).
		SetMaxReconnectInterval(time.Duration(maxReconnectInterval) * time.Minute).
		SetMessageChannelDepth(100).
		SetPingTimeout(time.Duration(pingTimeout) * time.Second).
		SetProtocolVersion(4).
		SetWriteTimeout(time.Duration(writeTimeout) * time.Second)

	if config.WillTopic != "" {
		opts.SetWill(
			config.WillTopic,
			config.WillPayload,
			byte(config.WillQoS&0xff),
			config.WillRetain,
		)
	}

	if username != "" {
		opts.SetUsername(username)
	}
	if password != "" {
		opts.SetPassword(password)
	}
	if useTls {
		opts.SetTLSConfig(tlsCfg)
	}

	return mq.NewClient(opts), nil
}

func setupTLS(caPath, certPath, keyPath string) (*tls.Config, error) {
	tlsCfg := &tls.Config{}
	if caPath != "" {
		caPem, err := ioutil.ReadFile(caPath)
		if err != nil {
			return nil, err
		}
		tlsCfg.RootCAs = x509.NewCertPool()
		tlsCfg.RootCAs.AppendCertsFromPEM(caPem)
	}

	if certPath != "" && keyPath != "" {
		if keyPath == "" {
			return nil, errors.New("Certificate path specified, but key path missing")
		}
		cert, err := tls.LoadX509KeyPair(certPath, keyPath)
		if err != nil {
			return nil, err
		}
		tlsCfg.Certificates = []tls.Certificate{cert}
		tlsCfg.BuildNameToCertificate()
	}

	return tlsCfg, nil
}
<|endoftext|>


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

package graphite

import (
	"encoding/json"
	"errors"
	"fmt"
	"net/http"
	"strings"

	"github.com/tsuru/config"
	"github.com/tsuru/tsuru/metrics"
)

type graphiteData struct {
	DataPoints [][]float64
}

// graphite represents the Graphite time series database.
type graphite struct{}

func getHost() string {
	host, err := config.GetString("graphite:host")
	if err != nil {
		return ""
	}
	if !strings.Contains(host, "http") {
		host = fmt.Sprintf("http://%s", host)
	}
	return host
}

// Summarize summarizes the data into interval buckets of a certain size.
func (g *graphite) Summarize(key, interval, function string) (metrics.Series, error) {
	url := fmt.Sprintf("%s/render/?target=keepLastValue(maxSeries(%s))&from=%s&format=json", getHost(), key, interval)
	resp, err := http.Get(url)
	if err != nil {
		return nil, err
	}
	var series metrics.Series
	var data []graphiteData
	err = json.NewDecoder(resp.Body).Decode(&data)
	if err != nil {
		fmt.Println(err)
		return nil, errors.New("metrics disabled")
	}
	defer resp.Body.Close()
	for _, dataPoint := range data[0].DataPoints {
		series = append(series, metrics.Data{
			Value:     dataPoint[0],
			Timestamp: dataPoint[1],
		})
	}
	return series, nil
}
<commit_msg>metrics: register graphite.<commit_after>// Copyright 2015 tsuru authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package graphite

import (
	"encoding/json"
	"errors"
	"fmt"
	"net/http"
	"strings"

	"github.com/tsuru/config"
	"github.com/tsuru/tsuru/metrics"
)

func init() {
	metrics.Register("graphite", graphite{})
}

type graphiteData struct {
	DataPoints [][]float64
}

// graphite represents the Graphite time series database.
type graphite struct{}

func getHost() string {
	host, err := config.GetString("graphite:host")
	if err != nil {
		return ""
	}
	if !strings.Contains(host, "http") {
		host = fmt.Sprintf("http://%s", host)
	}
	return host
}

// Summarize summarizes the data into interval buckets of a certain size.
func (g graphite) Summarize(key, interval, function string) (metrics.Series, error) {
	url := fmt.Sprintf("%s/render/?target=keepLastValue(maxSeries(%s))&from=%s&format=json", getHost(), key, interval)
	resp, err := http.Get(url)
	if err != nil {
		return nil, err
	}
	var series metrics.Series
	var data []graphiteData
	err = json.NewDecoder(resp.Body).Decode(&data)
	if err != nil {
		fmt.Println(err)
		return nil, errors.New("metrics disabled")
	}
	defer resp.Body.Close()
	for _, dataPoint := range data[0].DataPoints {
		series = append(series, metrics.Data{
			Value:     dataPoint[0],
			Timestamp: dataPoint[1],
		})
	}
	return series, nil
}
<|endoftext|>


<commit_before>package adapters

import (
	"bytes"
	"context"
	"encoding/json"
	"errors"
	"fmt"
	"github.com/prebid/openrtb"
	"github.com/prebid/prebid-server/pbs"
	"golang.org/x/net/context/ctxhttp"
	"io/ioutil"
	"net/http"
)

type PubmaticAdapter struct {
	http         *HTTPAdapter
	URI          string
	usersyncInfo *pbs.UsersyncInfo
}

/* Name - export adapter name */
func (a *PubmaticAdapter) Name() string {
	return "Pubmatic"
}

// used for cookies and such
func (a *PubmaticAdapter) FamilyName() string {
	return "pubmatic"
}

func (a *PubmaticAdapter) GetUsersyncInfo() *pbs.UsersyncInfo {
	return a.usersyncInfo
}

type pubmaticParams struct {
	PublisherId string `json:"publisherId"`
	AdSlot      string `json:"adSlot"`
}

func (a *PubmaticAdapter) Call(ctx context.Context, req *pbs.PBSRequest, bidder *pbs.PBSBidder) (pbs.PBSBidSlice, error) {
	pbReq := makeOpenRTBGeneric(req, bidder, a.FamilyName())
	pbReq.AT = 0 // this seems to break their bidder otherwise
	for i, unit := range bidder.AdUnits {
		var params pubmaticParams
		err := json.Unmarshal(unit.Params, &params)
		if err != nil {
			return nil, err
		}
		if params.PublisherId == "" {
			return nil, errors.New("Missing publisherId param")
		}
		if params.AdSlot == "" {
			return nil, errors.New("Missing adSlot param")
		}
		pbReq.Imp[i].Banner.Format = nil // pubmatic doesn't support
		pbReq.Imp[i].TagID = params.AdSlot
		pbReq.Site.Publisher = &openrtb.Publisher{ID: params.PublisherId}
	}

	reqJSON, err := json.Marshal(pbReq)

	if req.IsDebug {
		bidder.Debug.RequestBody = string(reqJSON)
		bidder.Debug.RequestURI = a.URI
	}

	httpReq, err := http.NewRequest("POST", a.URI, bytes.NewBuffer(reqJSON))
	httpReq.Header.Add("Content-Type", "application/json;charset=utf-8")
	httpReq.Header.Add("Accept", "application/json")
	httpReq.AddCookie(&http.Cookie{
		Name:  "KADUSERCOOKIE",
		Value: req.GetUserID(a.FamilyName()),
	})

	pbResp, err := ctxhttp.Do(ctx, a.http.Client, httpReq)
	if err != nil {
		return nil, err
	}

	if req.IsDebug {
		bidder.Debug.StatusCode = pbResp.StatusCode
	}

	if pbResp.StatusCode == 204 {
		return nil, nil
	}

	if pbResp.StatusCode != 200 {
		return nil, errors.New(fmt.Sprintf("HTTP status: %d", pbResp.StatusCode))
	}

	defer pbResp.Body.Close()
	body, err := ioutil.ReadAll(pbResp.Body)
	if err != nil {
		return nil, err
	}

	if req.IsDebug {
		bidder.Debug.ResponseBody = string(body)
	}

	var bidResp openrtb.BidResponse
	err = json.Unmarshal(body, &bidResp)
	if err != nil {
		return nil, err
	}

	bids := make(pbs.PBSBidSlice, 0)

	numBids := 0
	for _, sb := range bidResp.SeatBid {
		for _, bid := range sb.Bid {
			numBids++

			bidID := bidder.LookupBidID(bid.ImpID)
			if bidID == "" {
				return nil, errors.New(fmt.Sprintf("Unknown ad unit code '%s'", bid.ImpID))
			}

			pbid := pbs.PBSBid{
				BidID:       bidID,
				AdUnitCode:  bid.ImpID,
				BidderCode:  bidder.BidderCode,
				Price:       bid.Price,
				Adm:         bid.AdM,
				Creative_id: bid.CrID,
				Width:       bid.W,
				Height:      bid.H,
				DealId:      bid.DealID,
			}
			bids = append(bids, &pbid)
		}
	}

	return bids, nil
}

func NewPubmaticAdapter(config *HTTPAdapterConfig, uri string, externalURL string) *PubmaticAdapter {
	a := NewHTTPAdapter(config)

	redirect_uri := fmt.Sprintf("%s/setuid?bidder=pubmatic&uid=$UID", externalURL)
	usersyncURL := "http://ads.pubmatic.com/AdServer/js/user_sync.html?predirect="

	info := &pbs.UsersyncInfo{
		URL:         fmt.Sprintf("%s%s", usersyncURL, redirect_uri),
		Type:        "iframe",
		SupportCORS: false,
	}

	return &PubmaticAdapter{
		http:         a,
		URI:          uri,
		usersyncInfo: info,
	}
}
<commit_msg>move pubmatic to HTTPS, remove macro, add back encoding (#8)<commit_after>package adapters

import (
	"bytes"
	"context"
	"encoding/json"
	"errors"
	"fmt"
	"io/ioutil"
	"net/http"
	"net/url"

	"github.com/prebid/openrtb"
	"github.com/prebid/prebid-server/pbs"
	"golang.org/x/net/context/ctxhttp"
)

type PubmaticAdapter struct {
	http         *HTTPAdapter
	URI          string
	usersyncInfo *pbs.UsersyncInfo
}

/* Name - export adapter name */
func (a *PubmaticAdapter) Name() string {
	return "Pubmatic"
}

// used for cookies and such
func (a *PubmaticAdapter) FamilyName() string {
	return "pubmatic"
}

func (a *PubmaticAdapter) GetUsersyncInfo() *pbs.UsersyncInfo {
	return a.usersyncInfo
}

type pubmaticParams struct {
	PublisherId string `json:"publisherId"`
	AdSlot      string `json:"adSlot"`
}

func (a *PubmaticAdapter) Call(ctx context.Context, req *pbs.PBSRequest, bidder *pbs.PBSBidder) (pbs.PBSBidSlice, error) {
	pbReq := makeOpenRTBGeneric(req, bidder, a.FamilyName())
	pbReq.AT = 0 // this seems to break their bidder otherwise
	for i, unit := range bidder.AdUnits {
		var params pubmaticParams
		err := json.Unmarshal(unit.Params, &params)
		if err != nil {
			return nil, err
		}
		if params.PublisherId == "" {
			return nil, errors.New("Missing publisherId param")
		}
		if params.AdSlot == "" {
			return nil, errors.New("Missing adSlot param")
		}
		pbReq.Imp[i].Banner.Format = nil // pubmatic doesn't support
		pbReq.Imp[i].TagID = params.AdSlot
		pbReq.Site.Publisher = &openrtb.Publisher{ID: params.PublisherId}
	}

	reqJSON, err := json.Marshal(pbReq)

	if req.IsDebug {
		bidder.Debug.RequestBody = string(reqJSON)
		bidder.Debug.RequestURI = a.URI
	}

	httpReq, err := http.NewRequest("POST", a.URI, bytes.NewBuffer(reqJSON))
	httpReq.Header.Add("Content-Type", "application/json;charset=utf-8")
	httpReq.Header.Add("Accept", "application/json")
	httpReq.AddCookie(&http.Cookie{
		Name:  "KADUSERCOOKIE",
		Value: req.GetUserID(a.FamilyName()),
	})

	pbResp, err := ctxhttp.Do(ctx, a.http.Client, httpReq)
	if err != nil {
		return nil, err
	}

	if req.IsDebug {
		bidder.Debug.StatusCode = pbResp.StatusCode
	}

	if pbResp.StatusCode == 204 {
		return nil, nil
	}

	if pbResp.StatusCode != 200 {
		return nil, errors.New(fmt.Sprintf("HTTP status: %d", pbResp.StatusCode))
	}

	defer pbResp.Body.Close()
	body, err := ioutil.ReadAll(pbResp.Body)
	if err != nil {
		return nil, err
	}

	if req.IsDebug {
		bidder.Debug.ResponseBody = string(body)
	}

	var bidResp openrtb.BidResponse
	err = json.Unmarshal(body, &bidResp)
	if err != nil {
		return nil, err
	}

	bids := make(pbs.PBSBidSlice, 0)

	numBids := 0
	for _, sb := range bidResp.SeatBid {
		for _, bid := range sb.Bid {
			numBids++

			bidID := bidder.LookupBidID(bid.ImpID)
			if bidID == "" {
				return nil, errors.New(fmt.Sprintf("Unknown ad unit code '%s'", bid.ImpID))
			}

			pbid := pbs.PBSBid{
				BidID:       bidID,
				AdUnitCode:  bid.ImpID,
				BidderCode:  bidder.BidderCode,
				Price:       bid.Price,
				Adm:         bid.AdM,
				Creative_id: bid.CrID,
				Width:       bid.W,
				Height:      bid.H,
				DealId:      bid.DealID,
			}
			bids = append(bids, &pbid)
		}
	}

	return bids, nil
}

func NewPubmaticAdapter(config *HTTPAdapterConfig, uri string, externalURL string) *PubmaticAdapter {
	a := NewHTTPAdapter(config)
	redirect_uri := fmt.Sprintf("%s/setuid?bidder=pubmatic&uid=", externalURL)
	usersyncURL := "https://ads.pubmatic.com/AdServer/js/user_sync.html?predirect="

	info := &pbs.UsersyncInfo{
		URL:         fmt.Sprintf("%s%s", usersyncURL, url.QueryEscape(redirect_uri)),
		Type:        "iframe",
		SupportCORS: false,
	}

	return &PubmaticAdapter{
		http:         a,
		URI:          uri,
		usersyncInfo: info,
	}
}
<|endoftext|>


<commit_before>// Copyright 2014-2015 Amazon.com, Inc. or its affiliates. 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. A copy of the
// License is located at
//
//	http://aws.amazon.com/apache2.0/
//
// or in the "license" file accompanying this file. This file 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 stats

import (
	"fmt"
	"math"
	"sync"

	"github.com/aws/amazon-ecs-agent/agent/tcs/model/ecstcs"
)

const (
	// BytesInMiB is the number of bytes in a MebiByte.
	BytesInMiB = 1024 * 1024
)

// Queue abstracts a queue using UsageStats slice.
type Queue struct {
	buffer     []UsageStats
	maxSize    int
	bufferLock sync.RWMutex
}

// NewQueue creates a queue.
func NewQueue(maxSize int) *Queue {
	return &Queue{
		buffer:  make([]UsageStats, 0, maxSize),
		maxSize: maxSize,
	}
}

// Reset resets the stats queue.
func (queue *Queue) Reset() {
	queue.buffer = queue.buffer[:0]
}

// Add adds a new set of container stats to the queue.
func (queue *Queue) Add(rawStat *ContainerStats) {
	queue.bufferLock.Lock()
	defer queue.bufferLock.Unlock()

	queueLength := len(queue.buffer)
	stat := UsageStats{
		CPUUsagePerc:      float32(nan32()),
		MemoryUsageInMegs: uint32(rawStat.memoryUsage / BytesInMiB),
		Timestamp:         rawStat.timestamp,
		cpuUsage:          rawStat.cpuUsage,
	}
	if queueLength != 0 {
		// % utilization can be calculated only when queue is non-empty.
		lastStat := queue.buffer[queueLength-1]
		stat.CPUUsagePerc = 100 * float32(rawStat.cpuUsage-lastStat.cpuUsage) / float32(rawStat.timestamp.Sub(lastStat.Timestamp).Nanoseconds())
		if queue.maxSize == queueLength {
			// Remove first element if queue is full.
			queue.buffer = queue.buffer[1:queueLength]
		}
	}

	queue.buffer = append(queue.buffer, stat)
}

// GetCPUStatsSet gets the stats set for CPU utilization.
func (queue *Queue) GetCPUStatsSet() (*ecstcs.CWStatsSet, error) {
	return queue.getCWStatsSet(getCPUUsagePerc)
}

// GetMemoryStatsSet gets the stats set for memory utilization.
func (queue *Queue) GetMemoryStatsSet() (*ecstcs.CWStatsSet, error) {
	return queue.getCWStatsSet(getMemoryUsagePerc)
}

// GetRawUsageStats gets the array of most recent raw UsageStats, in descending
// order of timestamps.
func (queue *Queue) GetRawUsageStats(numStats int) ([]UsageStats, error) {
	queue.bufferLock.Lock()
	defer queue.bufferLock.Unlock()

	queueLength := len(queue.buffer)
	if queueLength == 0 {
		return nil, fmt.Errorf("No data in the queue")
	}

	if numStats > queueLength {
		numStats = queueLength
	}

	usageStats := make([]UsageStats, numStats)
	for i := 0; i < numStats; i++ {
		// Order such that usageStats[i].timestamp > usageStats[i+1].timestamp
		rawUsageStat := queue.buffer[queueLength-i-1]
		usageStats[i] = UsageStats{
			CPUUsagePerc:      rawUsageStat.CPUUsagePerc,
			MemoryUsageInMegs: rawUsageStat.MemoryUsageInMegs,
			Timestamp:         rawUsageStat.Timestamp,
		}
	}

	return usageStats, nil
}

func getCPUUsagePerc(s *UsageStats) float64 {
	return float64(s.CPUUsagePerc)
}

func getMemoryUsagePerc(s *UsageStats) float64 {
	return float64(s.MemoryUsageInMegs)
}

type getUsageFunc func(*UsageStats) float64

// getCWStatsSet gets the stats set for either CPU or Memory based on the
// function pointer.
func (queue *Queue) getCWStatsSet(f getUsageFunc) (*ecstcs.CWStatsSet, error) {
	queue.bufferLock.Lock()
	defer queue.bufferLock.Unlock()

	queueLength := len(queue.buffer)
	if queueLength < 2 {
		// Need at least 2 data points to calculate this.
		return nil, fmt.Errorf("No data in the queue")
	}

	var min, max, sum float64
	var sampleCount int64
	min = math.MaxFloat64
	max = -math.MaxFloat64
	sum = 0
	sampleCount = 0

	for _, stat := range queue.buffer {
		perc := f(&stat)
		if math.IsNaN(perc) {
			continue
		}

		min = math.Min(min, perc)
		max = math.Max(max, perc)
		sampleCount++
		sum += perc
	}

	return &ecstcs.CWStatsSet{
		Max:         &max,
		Min:         &min,
		SampleCount: &sampleCount,
		Sum:         &sum,
	}, nil
}
<commit_msg>Fixed potential race condition when resetting metrics buffer<commit_after>// Copyright 2014-2015 Amazon.com, Inc. or its affiliates. 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. A copy of the
// License is located at
//
//	http://aws.amazon.com/apache2.0/
//
// or in the "license" file accompanying this file. This file 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 stats

import (
	"fmt"
	"math"
	"sync"

	"github.com/aws/amazon-ecs-agent/agent/tcs/model/ecstcs"
)

const (
	// BytesInMiB is the number of bytes in a MebiByte.
	BytesInMiB = 1024 * 1024
)

// Queue abstracts a queue using UsageStats slice.
type Queue struct {
	buffer     []UsageStats
	maxSize    int
	bufferLock sync.RWMutex
}

// NewQueue creates a queue.
func NewQueue(maxSize int) *Queue {
	return &Queue{
		buffer:  make([]UsageStats, 0, maxSize),
		maxSize: maxSize,
	}
}

// Reset resets the stats queue.
func (queue *Queue) Reset() {
	queue.bufferLock.Lock()
	defer queue.bufferLock.Unlock()

	queue.buffer = queue.buffer[:0]
}

// Add adds a new set of container stats to the queue.
func (queue *Queue) Add(rawStat *ContainerStats) {
	queue.bufferLock.Lock()
	defer queue.bufferLock.Unlock()

	queueLength := len(queue.buffer)
	stat := UsageStats{
		CPUUsagePerc:      float32(nan32()),
		MemoryUsageInMegs: uint32(rawStat.memoryUsage / BytesInMiB),
		Timestamp:         rawStat.timestamp,
		cpuUsage:          rawStat.cpuUsage,
	}
	if queueLength != 0 {
		// % utilization can be calculated only when queue is non-empty.
		lastStat := queue.buffer[queueLength-1]
		stat.CPUUsagePerc = 100 * float32(rawStat.cpuUsage-lastStat.cpuUsage) / float32(rawStat.timestamp.Sub(lastStat.Timestamp).Nanoseconds())
		if queue.maxSize == queueLength {
			// Remove first element if queue is full.
			queue.buffer = queue.buffer[1:queueLength]
		}
	}

	queue.buffer = append(queue.buffer, stat)
}

// GetCPUStatsSet gets the stats set for CPU utilization.
func (queue *Queue) GetCPUStatsSet() (*ecstcs.CWStatsSet, error) {
	return queue.getCWStatsSet(getCPUUsagePerc)
}

// GetMemoryStatsSet gets the stats set for memory utilization.
func (queue *Queue) GetMemoryStatsSet() (*ecstcs.CWStatsSet, error) {
	return queue.getCWStatsSet(getMemoryUsagePerc)
}

// GetRawUsageStats gets the array of most recent raw UsageStats, in descending
// order of timestamps.
func (queue *Queue) GetRawUsageStats(numStats int) ([]UsageStats, error) {
	queue.bufferLock.Lock()
	defer queue.bufferLock.Unlock()

	queueLength := len(queue.buffer)
	if queueLength == 0 {
		return nil, fmt.Errorf("No data in the queue")
	}

	if numStats > queueLength {
		numStats = queueLength
	}

	usageStats := make([]UsageStats, numStats)
	for i := 0; i < numStats; i++ {
		// Order such that usageStats[i].timestamp > usageStats[i+1].timestamp
		rawUsageStat := queue.buffer[queueLength-i-1]
		usageStats[i] = UsageStats{
			CPUUsagePerc:      rawUsageStat.CPUUsagePerc,
			MemoryUsageInMegs: rawUsageStat.MemoryUsageInMegs,
			Timestamp:         rawUsageStat.Timestamp,
		}
	}

	return usageStats, nil
}

func getCPUUsagePerc(s *UsageStats) float64 {
	return float64(s.CPUUsagePerc)
}

func getMemoryUsagePerc(s *UsageStats) float64 {
	return float64(s.MemoryUsageInMegs)
}

type getUsageFunc func(*UsageStats) float64

// getCWStatsSet gets the stats set for either CPU or Memory based on the
// function pointer.
func (queue *Queue) getCWStatsSet(f getUsageFunc) (*ecstcs.CWStatsSet, error) {
	queue.bufferLock.Lock()
	defer queue.bufferLock.Unlock()

	queueLength := len(queue.buffer)
	if queueLength < 2 {
		// Need at least 2 data points to calculate this.
		return nil, fmt.Errorf("No data in the queue")
	}

	var min, max, sum float64
	var sampleCount int64
	min = math.MaxFloat64
	max = -math.MaxFloat64
	sum = 0
	sampleCount = 0

	for _, stat := range queue.buffer {
		perc := f(&stat)
		if math.IsNaN(perc) {
			continue
		}

		min = math.Min(min, perc)
		max = math.Max(max, perc)
		sampleCount++
		sum += perc
	}

	return &ecstcs.CWStatsSet{
		Max:         &max,
		Min:         &min,
		SampleCount: &sampleCount,
		Sum:         &sum,
	}, nil
}
<|endoftext|>


<commit_before>/*
 Copyright 2016 Padduck, LLC

 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 install

import (
	"io/ioutil"
	"os/exec"
	"github.com/pufferpanel/pufferd/logging"
	"syscall"
)

const SYSTEMD = `
[Unit]
Description=pufferd daemon service

[Service]
Type=simple
WorkingDirectory=/srv/pufferd
ExecStart=/srv/pufferd/pufferd
User=pufferd
Group=pufferd

[Install]
WantedBy=multi-user.target
`

func InstallService() {
	cmd := exec.Command("useradd", "--system", "--no-create-home", "--user-group", "pufferd")

	err := cmd.Run()
	if err != nil {
		if exitErr, ok := err.(*exec.ExitError); ok {
			if status, ok := exitErr.Sys().(syscall.WaitStatus); ok {
				if status.ExitStatus() != 9 {
					logging.Error("Error creating pufferd user", err)
					return
				}
			} else {
				logging.Error("Error creating pufferd user", err)
				return
			}
		} else {
			logging.Error("Error creating pufferd user", err)
			return
		}
	}

	err = ioutil.WriteFile("/etc/systemd/system/pufferd.service", []byte(SYSTEMD), 0664)
	if err != nil {
		logging.Error("Cannot write systemd file, will not install service", err)
		return
	}
	cmd = exec.Command("systemctl", "enable", "pufferd")
	output, err := cmd.CombinedOutput()
	if err != nil {
		logging.Error("Error enabling pufferd service", err)
		logging.Error(string(output))
		return
	}
	logging.Info(string(output))

	logging.Info("Service may be started with: systemctl start pufferd")
}
<commit_msg>Fix user creation for $HOME<commit_after>/*
 Copyright 2016 Padduck, LLC

 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 install

import (
	"io/ioutil"
	"os/exec"
	"github.com/pufferpanel/pufferd/logging"
	"syscall"
)

const SYSTEMD = `
[Unit]
Description=pufferd daemon service

[Service]
Type=simple
WorkingDirectory=/srv/pufferd
ExecStart=/srv/pufferd/pufferd
User=pufferd
Group=pufferd

[Install]
WantedBy=multi-user.target
`

func InstallService() {
	cmd := exec.Command("useradd", "--system", "--no-create-home", "--user-group", "--home", "/srv/pufferd/data", "pufferd")

	err := cmd.Run()
	if err != nil {
		if exitErr, ok := err.(*exec.ExitError); ok {
			if status, ok := exitErr.Sys().(syscall.WaitStatus); ok {
				if status.ExitStatus() != 9 {
					logging.Error("Error creating pufferd user", err)
					return
				}
			} else {
				logging.Error("Error creating pufferd user", err)
				return
			}
		} else {
			logging.Error("Error creating pufferd user", err)
			return
		}
	}

	err = ioutil.WriteFile("/etc/systemd/system/pufferd.service", []byte(SYSTEMD), 0664)
	if err != nil {
		logging.Error("Cannot write systemd file, will not install service", err)
		return
	}
	cmd = exec.Command("systemctl", "enable", "pufferd")
	output, err := cmd.CombinedOutput()
	if err != nil {
		logging.Error("Error enabling pufferd service", err)
		logging.Error(string(output))
		return
	}
	logging.Info(string(output))

	logging.Info("Service may be started with: systemctl start pufferd")
}
<|endoftext|>


<commit_before>// pss RPC routed over swarm
package main

import (
	"context"
	"fmt"
	"os"
	"time"

	"github.com/ethereum/go-ethereum/common"
	"github.com/ethereum/go-ethereum/contracts/chequebook"
	"github.com/ethereum/go-ethereum/crypto"
	"github.com/ethereum/go-ethereum/node"
	"github.com/ethereum/go-ethereum/p2p"
	"github.com/ethereum/go-ethereum/p2p/protocols"
	"github.com/ethereum/go-ethereum/swarm"
	bzzapi "github.com/ethereum/go-ethereum/swarm/api"
	"github.com/ethereum/go-ethereum/swarm/pss"
	pssclient "github.com/ethereum/go-ethereum/swarm/pss/client"

	demo "github.com/nolash/go-ethereum-p2p-demo/common"
)

// simple ping and receive protocol
var (
	proto = p2p.Protocol{
		Name:    demo.FooProtocolName,
		Version: demo.FooProtocolVersion,
		Length:  uint64(len(demo.FooMessages)),
		Run: func(p *p2p.Peer, rw p2p.MsgReadWriter) error {
			pp := protocols.NewPeer(p, rw, &demo.FooProtocol)
			go func() {
				err := pp.Send(&demo.FooPingMsg{
					Created: time.Now(),
				})
				if err != nil {
					demo.Log.Error("protocol send fail", "err", err)
				}
			}()
			return pp.Run(run)
		},
	}
	topic = pss.PingTopic
	quitC = make(chan struct{})
)

// receive message and quit
func run(msg interface{}) error {
	foomsg, ok := msg.(*demo.FooPingMsg)
	if !ok {
		return fmt.Errorf("invalid msg: %v", msg)
	}
	demo.Log.Info("received message", "time", foomsg.Created)
	quitC <- struct{}{}
	return nil
}

func newService(bzzdir string, bzzport int, bzznetworkid uint64) func(ctx *node.ServiceContext) (node.Service, error) {
	return func(ctx *node.ServiceContext) (node.Service, error) {

		// generate a new private key
		privkey, err := crypto.GenerateKey()
		if err != nil {
			demo.Log.Crit("private key generate servicenode 'left' fail: %v")
		}

		// create necessary swarm params
		var ensApi chequebook.Backend = nil
		bzzconfig := bzzapi.NewConfig()
		bzzconfig.Path = bzzdir
		bzzconfig.Init(privkey)
		if err != nil {
			demo.Log.Crit("unable to configure swarm", "err", err)
		}
		bzzconfig.Port = fmt.Sprintf("%d", bzzport)

		// shortcut to setting up a swarm node
		return swarm.NewSwarm(ctx, ensApi, bzzconfig, nil)

	}
}

func main() {

	// create two nodes
	l_stack, err := demo.NewServiceNode(demo.P2pPort, 0, demo.WSDefaultPort, "pss")
	if err != nil {
		demo.Log.Crit(err.Error())
	}
	r_stack, err := demo.NewServiceNode(demo.P2pPort+1, 0, demo.WSDefaultPort+1, "pss")
	if err != nil {
		demo.Log.Crit(err.Error())
	}

	// register the pss activated bzz services
	l_svc := newService(l_stack.InstanceDir(), demo.BzzDefaultPort, demo.BzzDefaultNetworkId)
	err = l_stack.Register(l_svc)
	if err != nil {
		demo.Log.Crit("servicenode 'left' pss register fail", "err", err)
	}

	r_svc := newService(r_stack.InstanceDir(), demo.BzzDefaultPort+1, demo.BzzDefaultNetworkId)
	err = r_stack.Register(r_svc)
	if err != nil {
		demo.Log.Crit("servicenode 'right' pss register fail", "err", err)
	}

	// start the nodes
	err = l_stack.Start()
	if err != nil {
		demo.Log.Crit("servicenode start failed", "err", err)
	}
	defer os.RemoveAll(l_stack.DataDir())
	err = r_stack.Start()
	if err != nil {
		demo.Log.Crit("servicenode start failed", "err", err)
	}
	defer os.RemoveAll(r_stack.DataDir())

	// connect the nodes to the middle
	l_stack.Server().AddPeer(r_stack.Server().Self())

	// get the rpc clients
	l_rpcclient, err := l_stack.Attach()
	r_rpcclient, err := r_stack.Attach()

	// get the public keys
	var l_pubkey string
	err = l_rpcclient.Call(&l_pubkey, "pss_getPublicKey")
	if err != nil {
		demo.Log.Crit("pss get pubkey fail", "err", err)
	}
	var r_pubkey string
	err = r_rpcclient.Call(&r_pubkey, "pss_getPublicKey")
	if err != nil {
		demo.Log.Crit("pss get pubkey fail", "err", err)
	}

	// get the overlay addresses
	var l_bzzaddr string
	err = l_rpcclient.Call(&l_bzzaddr, "pss_baseAddr")
	if err != nil {
		demo.Log.Crit("pss get baseaddr fail", "err", err)
	}
	var r_bzzaddr string
	err = r_rpcclient.Call(&r_bzzaddr, "pss_baseAddr")
	if err != nil {
		demo.Log.Crit("pss get baseaddr fail", "err", err)
	}

	// make the nodes aware of each others' public keys
	err = l_rpcclient.Call(nil, "pss_setPeerPublicKey", r_pubkey, topic, r_bzzaddr)
	if err != nil {
		demo.Log.Crit("pss set pubkey fail", "err", err)
	}
	err = r_rpcclient.Call(nil, "pss_setPeerPublicKey", l_pubkey, topic, l_bzzaddr)
	if err != nil {
		demo.Log.Crit("pss set pubkey fail", "err", err)
	}

	// wait until the state of the swarm overlay network is ready
	ctx, cancel := context.WithTimeout(context.Background(), time.Second)
	defer cancel()
	err = demo.WaitHealthy(ctx, 2, l_rpcclient, r_rpcclient)
	if err != nil {
		demo.Log.Crit("health check fail", "err", err)
	}
	time.Sleep(time.Second) // because the healthy does not work

	// configure and start up pss client RPCs
	c_left, err := pssclient.NewClient(fmt.Sprintf("ws://localhost:%d", demo.WSDefaultPort))
	if err != nil {
		demo.Log.Crit("pssclient 'left' create fail", "err", err)
	}
	c_right, err := pssclient.NewClient(fmt.Sprintf("ws://localhost:%d", demo.WSDefaultPort+1))
	if err != nil {
		demo.Log.Crit("pssclient 'right' create fail", "err", err)
	}

	// set up generic ping protocol
	l_ping := pss.Ping{
		Pong: false,
		OutC: make(chan bool),
		InC:  make(chan bool),
	}
	l_proto := pss.NewPingProtocol(&l_ping)
	r_ping := pss.Ping{
		Pong: true,
		OutC: make(chan bool),
		InC:  make(chan bool),
	}
	r_proto := pss.NewPingProtocol(&r_ping)

	// run the pssclient protocols
	// this registers the protocol handler in pss with topic generated from the protocol name and version
	ctx, cancel = context.WithTimeout(context.Background(), time.Second)
	defer cancel()
	c_left.RunProtocol(ctx, l_proto)

	ctx, cancel = context.WithTimeout(context.Background(), time.Second)
	defer cancel()
	c_right.RunProtocol(ctx, r_proto)

	// add the 'right' peer
	c_left.AddPssPeer(r_pubkey, common.FromHex(r_bzzaddr), pss.PingProtocol)

	time.Sleep(time.Second)

	// send ping
	l_ping.OutC <- false

	// get ping
	<-r_ping.InC
	demo.Log.Info("got ping")

	// get pong
	<-l_ping.InC
	demo.Log.Info("got pong")

	// the 'right' will receive the ping and send on the quit channel
	c_left.Close()
	c_right.Close()
}
<commit_msg>Replace one websocket with unix socket in pssclient example<commit_after>// pss RPC routed over swarm
package main

import (
	"context"
	"fmt"
	"os"
	"time"

	"github.com/ethereum/go-ethereum/common"
	"github.com/ethereum/go-ethereum/contracts/chequebook"
	"github.com/ethereum/go-ethereum/crypto"
	"github.com/ethereum/go-ethereum/node"
	"github.com/ethereum/go-ethereum/p2p"
	"github.com/ethereum/go-ethereum/p2p/protocols"
	"github.com/ethereum/go-ethereum/swarm"
	bzzapi "github.com/ethereum/go-ethereum/swarm/api"
	"github.com/ethereum/go-ethereum/swarm/pss"
	pssclient "github.com/ethereum/go-ethereum/swarm/pss/client"

	demo "github.com/nolash/go-ethereum-p2p-demo/common"
)

// simple ping and receive protocol
var (
	proto = p2p.Protocol{
		Name:    demo.FooProtocolName,
		Version: demo.FooProtocolVersion,
		Length:  uint64(len(demo.FooMessages)),
		Run: func(p *p2p.Peer, rw p2p.MsgReadWriter) error {
			pp := protocols.NewPeer(p, rw, &demo.FooProtocol)
			go func() {
				err := pp.Send(&demo.FooPingMsg{
					Created: time.Now(),
				})
				if err != nil {
					demo.Log.Error("protocol send fail", "err", err)
				}
			}()
			return pp.Run(run)
		},
	}
	topic = pss.PingTopic
	quitC = make(chan struct{})
)

// receive message and quit
func run(msg interface{}) error {
	foomsg, ok := msg.(*demo.FooPingMsg)
	if !ok {
		return fmt.Errorf("invalid msg: %v", msg)
	}
	demo.Log.Info("received message", "time", foomsg.Created)
	quitC <- struct{}{}
	return nil
}

func newService(bzzdir string, bzzport int, bzznetworkid uint64) func(ctx *node.ServiceContext) (node.Service, error) {
	return func(ctx *node.ServiceContext) (node.Service, error) {

		// generate a new private key
		privkey, err := crypto.GenerateKey()
		if err != nil {
			demo.Log.Crit("private key generate servicenode 'left' fail: %v")
		}

		// create necessary swarm params
		var ensApi chequebook.Backend = nil
		bzzconfig := bzzapi.NewConfig()
		bzzconfig.Path = bzzdir
		bzzconfig.Init(privkey)
		if err != nil {
			demo.Log.Crit("unable to configure swarm", "err", err)
		}
		bzzconfig.Port = fmt.Sprintf("%d", bzzport)

		// shortcut to setting up a swarm node
		return swarm.NewSwarm(ctx, ensApi, bzzconfig, nil)

	}
}

func main() {

	// create two nodes
	l_stack, err := demo.NewServiceNode(demo.P2pPort, 0, demo.WSDefaultPort, "pss")
	if err != nil {
		demo.Log.Crit(err.Error())
	}
	r_stack, err := demo.NewServiceNode(demo.P2pPort+1, 0, demo.WSDefaultPort+1, "pss")
	if err != nil {
		demo.Log.Crit(err.Error())
	}

	// register the pss activated bzz services
	l_svc := newService(l_stack.InstanceDir(), demo.BzzDefaultPort, demo.BzzDefaultNetworkId)
	err = l_stack.Register(l_svc)
	if err != nil {
		demo.Log.Crit("servicenode 'left' pss register fail", "err", err)
	}

	r_svc := newService(r_stack.InstanceDir(), demo.BzzDefaultPort+1, demo.BzzDefaultNetworkId)
	err = r_stack.Register(r_svc)
	if err != nil {
		demo.Log.Crit("servicenode 'right' pss register fail", "err", err)
	}

	// start the nodes
	err = l_stack.Start()
	if err != nil {
		demo.Log.Crit("servicenode start failed", "err", err)
	}
	defer os.RemoveAll(l_stack.DataDir())
	err = r_stack.Start()
	if err != nil {
		demo.Log.Crit("servicenode start failed", "err", err)
	}
	defer os.RemoveAll(r_stack.DataDir())

	// connect the nodes to the middle
	l_stack.Server().AddPeer(r_stack.Server().Self())

	// get the rpc clients
	l_rpcclient, err := l_stack.Attach()
	r_rpcclient, err := r_stack.Attach()

	// get the public keys
	var l_pubkey string
	err = l_rpcclient.Call(&l_pubkey, "pss_getPublicKey")
	if err != nil {
		demo.Log.Crit("pss get pubkey fail", "err", err)
	}
	var r_pubkey string
	err = r_rpcclient.Call(&r_pubkey, "pss_getPublicKey")
	if err != nil {
		demo.Log.Crit("pss get pubkey fail", "err", err)
	}

	// get the overlay addresses
	var l_bzzaddr string
	err = l_rpcclient.Call(&l_bzzaddr, "pss_baseAddr")
	if err != nil {
		demo.Log.Crit("pss get baseaddr fail", "err", err)
	}
	var r_bzzaddr string
	err = r_rpcclient.Call(&r_bzzaddr, "pss_baseAddr")
	if err != nil {
		demo.Log.Crit("pss get baseaddr fail", "err", err)
	}

	// make the nodes aware of each others' public keys
	err = l_rpcclient.Call(nil, "pss_setPeerPublicKey", r_pubkey, topic, r_bzzaddr)
	if err != nil {
		demo.Log.Crit("pss set pubkey fail", "err", err)
	}
	err = r_rpcclient.Call(nil, "pss_setPeerPublicKey", l_pubkey, topic, l_bzzaddr)
	if err != nil {
		demo.Log.Crit("pss set pubkey fail", "err", err)
	}

	// wait until the state of the swarm overlay network is ready
	ctx, cancel := context.WithTimeout(context.Background(), time.Second)
	defer cancel()
	err = demo.WaitHealthy(ctx, 2, l_rpcclient, r_rpcclient)
	if err != nil {
		demo.Log.Crit("health check fail", "err", err)
	}
	time.Sleep(time.Second) // because the healthy does not work

	// configure and start up pss client RPCs
	// we can use websockets ...
	c_left, err := pssclient.NewClient(fmt.Sprintf("ws://localhost:%d", demo.WSDefaultPort))
	if err != nil {
		demo.Log.Crit("pssclient 'left' create fail", "err", err)
	}
	// ... or unix sockets, the client handles both :)
	c_right, err := pssclient.NewClient(r_stack.IPCEndpoint())
	if err != nil {
		demo.Log.Crit("pssclient 'right' create fail", "err", err)
	}

	// set up generic ping protocol
	l_ping := pss.Ping{
		Pong: false,
		OutC: make(chan bool),
		InC:  make(chan bool),
	}
	l_proto := pss.NewPingProtocol(&l_ping)
	r_ping := pss.Ping{
		Pong: true,
		OutC: make(chan bool),
		InC:  make(chan bool),
	}
	r_proto := pss.NewPingProtocol(&r_ping)

	// run the pssclient protocols
	// this registers the protocol handler in pss with topic generated from the protocol name and version
	ctx, cancel = context.WithTimeout(context.Background(), time.Second)
	defer cancel()
	c_left.RunProtocol(ctx, l_proto)

	ctx, cancel = context.WithTimeout(context.Background(), time.Second)
	defer cancel()
	c_right.RunProtocol(ctx, r_proto)

	// add the 'right' peer
	c_left.AddPssPeer(r_pubkey, common.FromHex(r_bzzaddr), pss.PingProtocol)

	time.Sleep(time.Second)

	// send ping
	l_ping.OutC <- false

	// get ping
	<-r_ping.InC
	demo.Log.Info("got ping")

	// get pong
	<-l_ping.InC
	demo.Log.Info("got pong")

	// the 'right' will receive the ping and send on the quit channel
	c_left.Close()
	c_right.Close()
}
<|endoftext|>


<commit_before>package integration

import (
	"fmt"
	"io/ioutil"
	"os"
	"path/filepath"
	"runtime"

	"code.cloudfoundry.org/cli/integration/helpers"

	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
	. "github.com/onsi/gomega/gbytes"
	. "github.com/onsi/gomega/gexec"
)

var _ = Describe("Push", func() {
	Context("when the environment is set up correctly", func() {
		var (
			orgName   string
			spaceName string
		)

		BeforeEach(func() {
			orgName = helpers.NewOrgName()
			spaceName = helpers.PrefixedRandomName("SPACE")

			setupCF(orgName, spaceName)
		})

		Context("when the app has over 260 character paths", func() {
			var (
				tmpDir string
				cwd    string
			)

			BeforeEach(func() {
				var err error
				tmpDir, err = ioutil.TempDir("", "")
				Expect(err).ToNot(HaveOccurred())

				dirName := "dir_name"
				dirNames := []string{}
				for i := 0; i < 32; i++ { // minimum 300 chars, including separators
					dirNames = append(dirNames, dirName)
				}

				err = ioutil.WriteFile(filepath.Join(tmpDir, "index.html"), []byte("hello world"), 0666)
				Expect(err).ToNot(HaveOccurred())
				fullPath := filepath.Join(tmpDir, filepath.Join(dirNames...))

				if runtime.GOOS == "windows" {
					var err error
					cwd, err = os.Getwd()
					Expect(err).NotTo(HaveOccurred())

					// `\\?\` is used to skip Windows' file name processor, which imposes
					// length limits. Search MSDN for 'Maximum Path Length Limitation' for
					// more.
					err = os.MkdirAll(`\\?\`+filepath.Join(cwd, fullPath), os.ModeDir|os.ModePerm)
					Expect(err).NotTo(HaveOccurred())
				} else {
					err := os.MkdirAll(fullPath, os.ModeDir|os.ModePerm)
					Expect(err).NotTo(HaveOccurred())
				}
			})

			It("successfully pushes the app", func() {
				defer os.RemoveAll(tmpDir)
				appName := helpers.PrefixedRandomName("APP")
				session := helpers.CF("push", appName, "-p", tmpDir, "-b", "staticfile_buildpack")
				Eventually(session).Should(Exit(0))
				Expect(session).To(Say("1 of 1 instances running"))
				Expect(session).To(Say("App %s was started using this command", appName))
			})
		})

		Context("when pushing with manifest routes and specifying the -n flag", func() {
			var (
				quotaName     string
				appDir        string
				manifestPath  string
				privateDomain helpers.Domain
				sharedDomain  helpers.Domain
				tcpDomain     helpers.Domain
			)

			BeforeEach(func() {
				quotaName = helpers.PrefixedRandomName("INTEGRATION-QUOTA")

				session := helpers.CF("create-quota", quotaName, "-m", "10G", "-r", "10", "--reserved-route-ports", "4")
				Eventually(session).Should(Exit(0))
				session = helpers.CF("set-quota", orgName, quotaName)
				Eventually(session).Should(Exit(0))

				privateDomain = helpers.NewDomain(orgName, helpers.DomainName("private"))
				privateDomain.Create()
				sharedDomain = helpers.NewDomain(orgName, helpers.DomainName("shared"))
				sharedDomain.CreateShared()
				tcpDomain = helpers.NewDomain(orgName, helpers.DomainName("tcp"))
				tcpDomain.CreateWithRouterGroup("default-tcp")

				var err error
				appDir, err = ioutil.TempDir("", "simple-app")
				Expect(err).ToNot(HaveOccurred())
				manifestContents := []byte(fmt.Sprintf(`
---
applications:
- name: app-with-routes
  memory: 100M
  instances: 1
  path: .
  routes:
  - route: %s
  - route: %s
  - route: manifest-host.%s/path
  - route: %s:1100
`, privateDomain.Name, sharedDomain.Name, sharedDomain.Name, tcpDomain.Name))
				manifestPath = filepath.Join(appDir, "manifest.yml")
				err = ioutil.WriteFile(manifestPath, manifestContents, 0666)
				Expect(err).ToNot(HaveOccurred())

				err = ioutil.WriteFile(filepath.Join(appDir, "index.html"), []byte("hello world"), 0666)
				Expect(err).ToNot(HaveOccurred())
			})

			It("should set or replace the route's hostname with the flag value", func() {
				defer os.RemoveAll(appDir)
				var session *Session
				session = helpers.CF("push", helpers.PrefixedRandomName("APP"), "-p", appDir, "-n", "flag-hostname", "-b", "staticfile_buildpack", "-f", manifestPath)

				Eventually(session).Should(Say("Creating route flag-hostname.%s...\nOK", privateDomain.Name))
				Eventually(session).Should(Say("Creating route flag-hostname.%s...\nOK", sharedDomain.Name))
				Eventually(session).Should(Say("Creating route flag-hostname.%s/path...\nOK", sharedDomain.Name))
				Eventually(session).Should(Say("Creating route %s:1100...\nOK", tcpDomain.Name))
				Eventually(session).Should(Exit(0))
			})
		})
	})
})
<commit_msg>use the full path we create in the push test<commit_after>package integration

import (
	"fmt"
	"io/ioutil"
	"os"
	"path/filepath"
	"runtime"

	"code.cloudfoundry.org/cli/integration/helpers"

	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
	. "github.com/onsi/gomega/gbytes"
	. "github.com/onsi/gomega/gexec"
)

var _ = Describe("Push", func() {
	Context("when the environment is set up correctly", func() {
		var (
			orgName   string
			spaceName string
		)

		BeforeEach(func() {
			orgName = helpers.NewOrgName()
			spaceName = helpers.PrefixedRandomName("SPACE")

			setupCF(orgName, spaceName)
		})

		Context("when the app has over 260 character paths", func() {
			var tmpDir string

			BeforeEach(func() {
				var err error
				tmpDir, err = ioutil.TempDir("", "")
				Expect(err).ToNot(HaveOccurred())

				dirName := "dir_name"
				dirNames := []string{}
				for i := 0; i < 32; i++ { // minimum 300 chars, including separators
					dirNames = append(dirNames, dirName)
				}

				fullPath := filepath.Join(tmpDir, filepath.Join(dirNames...))
				if runtime.GOOS == "windows" {
					// `\\?\` is used to skip Windows' file name processor, which imposes
					// length limits. Search MSDN for 'Maximum Path Length Limitation' for
					// more.
					fullPath = `\\?\` + fullPath
				}
				err = os.MkdirAll(fullPath, os.ModeDir|os.ModePerm)
				Expect(err).NotTo(HaveOccurred())

				err = ioutil.WriteFile(filepath.Join(fullPath, "index.html"), []byte("hello world"), 0666)
				Expect(err).ToNot(HaveOccurred())
			})

			It("successfully pushes the app", func() {
				defer os.RemoveAll(tmpDir)
				appName := helpers.PrefixedRandomName("APP")
				session := helpers.CF("push", appName, "-p", tmpDir, "-b", "staticfile_buildpack")
				Eventually(session).Should(Say("1 of 1 instances running"))
				Eventually(session).Should(Say("App %s was started using this command", appName))
				Eventually(session).Should(Exit(0))
			})
		})

		Context("when pushing with manifest routes and specifying the -n flag", func() {
			var (
				quotaName     string
				appDir        string
				manifestPath  string
				privateDomain helpers.Domain
				sharedDomain  helpers.Domain
				tcpDomain     helpers.Domain
			)

			BeforeEach(func() {
				quotaName = helpers.PrefixedRandomName("INTEGRATION-QUOTA")

				session := helpers.CF("create-quota", quotaName, "-m", "10G", "-r", "10", "--reserved-route-ports", "4")
				Eventually(session).Should(Exit(0))
				session = helpers.CF("set-quota", orgName, quotaName)
				Eventually(session).Should(Exit(0))

				privateDomain = helpers.NewDomain(orgName, helpers.DomainName("private"))
				privateDomain.Create()
				sharedDomain = helpers.NewDomain(orgName, helpers.DomainName("shared"))
				sharedDomain.CreateShared()
				tcpDomain = helpers.NewDomain(orgName, helpers.DomainName("tcp"))
				tcpDomain.CreateWithRouterGroup("default-tcp")

				var err error
				appDir, err = ioutil.TempDir("", "simple-app")
				Expect(err).ToNot(HaveOccurred())
				manifestContents := []byte(fmt.Sprintf(`
---
applications:
- name: app-with-routes
  memory: 100M
  instances: 1
  path: .
  routes:
  - route: %s
  - route: %s
  - route: manifest-host.%s/path
  - route: %s:1100
`, privateDomain.Name, sharedDomain.Name, sharedDomain.Name, tcpDomain.Name))
				manifestPath = filepath.Join(appDir, "manifest.yml")
				err = ioutil.WriteFile(manifestPath, manifestContents, 0666)
				Expect(err).ToNot(HaveOccurred())

				err = ioutil.WriteFile(filepath.Join(appDir, "index.html"), []byte("hello world"), 0666)
				Expect(err).ToNot(HaveOccurred())
			})

			It("should set or replace the route's hostname with the flag value", func() {
				defer os.RemoveAll(appDir)
				var session *Session
				session = helpers.CF("push", helpers.PrefixedRandomName("APP"), "-p", appDir, "-n", "flag-hostname", "-b", "staticfile_buildpack", "-f", manifestPath)

				Eventually(session).Should(Say("Creating route flag-hostname.%s...\nOK", privateDomain.Name))
				Eventually(session).Should(Say("Creating route flag-hostname.%s...\nOK", sharedDomain.Name))
				Eventually(session).Should(Say("Creating route flag-hostname.%s/path...\nOK", sharedDomain.Name))
				Eventually(session).Should(Say("Creating route %s:1100...\nOK", tcpDomain.Name))
				Eventually(session).Should(Exit(0))
			})
		})
	})
})
<|endoftext|>


<commit_before>package command

import (
	"fmt"
	"os"
	"strings"

	"github.com/hashicorp/terraform/internal/backend"
	"github.com/hashicorp/terraform/internal/command/arguments"
	"github.com/hashicorp/terraform/internal/command/format"
	"github.com/hashicorp/terraform/internal/command/jsonplan"
	"github.com/hashicorp/terraform/internal/command/jsonstate"
	"github.com/hashicorp/terraform/internal/command/views"
	"github.com/hashicorp/terraform/internal/plans"
	"github.com/hashicorp/terraform/internal/plans/planfile"
	"github.com/hashicorp/terraform/internal/states/statefile"
	"github.com/hashicorp/terraform/internal/states/statemgr"
	"github.com/hashicorp/terraform/internal/tfdiags"
)

// ShowCommand is a Command implementation that reads and outputs the
// contents of a Terraform plan or state file.
type ShowCommand struct {
	Meta
}

func (c *ShowCommand) Run(args []string) int {
	args = c.Meta.process(args)
	cmdFlags := c.Meta.defaultFlagSet("show")
	var jsonOutput bool
	cmdFlags.BoolVar(&jsonOutput, "json", false, "produce JSON output")
	cmdFlags.Usage = func() { c.Ui.Error(c.Help()) }
	if err := cmdFlags.Parse(args); err != nil {
		c.Ui.Error(fmt.Sprintf("Error parsing command-line flags: %s\n", err.Error()))
		return 1
	}

	args = cmdFlags.Args()
	if len(args) > 2 {
		c.Ui.Error(
			"The show command expects at most two arguments.\n The path to a " +
				"Terraform state or plan file, and optionally -json for json output.\n")
		cmdFlags.Usage()
		return 1
	}

	// Check for user-supplied plugin path
	var err error
	if c.pluginPath, err = c.loadPluginPath(); err != nil {
		c.Ui.Error(fmt.Sprintf("Error loading plugin path: %s", err))
		return 1
	}

	var diags tfdiags.Diagnostics

	// Load the backend
	b, backendDiags := c.Backend(nil)
	diags = diags.Append(backendDiags)
	if backendDiags.HasErrors() {
		c.showDiagnostics(diags)
		return 1
	}

	// We require a local backend
	local, ok := b.(backend.Local)
	if !ok {
		c.showDiagnostics(diags) // in case of any warnings in here
		c.Ui.Error(ErrUnsupportedLocalOp)
		return 1
	}

	// This is a read-only command
	c.ignoreRemoteVersionConflict(b)

	// the show command expects the config dir to always be the cwd
	cwd, err := os.Getwd()
	if err != nil {
		c.Ui.Error(fmt.Sprintf("Error getting cwd: %s", err))
		return 1
	}

	// Determine if a planfile was passed to the command
	var planFile *planfile.Reader
	if len(args) > 0 {
		// We will handle error checking later on - this is just required to
		// load the local context if the given path is successfully read as
		// a planfile.
		planFile, _ = c.PlanFile(args[0])
	}

	// Build the operation
	opReq := c.Operation(b)
	opReq.ConfigDir = cwd
	opReq.PlanFile = planFile
	opReq.ConfigLoader, err = c.initConfigLoader()
	opReq.AllowUnsetVariables = true
	opReq.DisablePlanFileStateLineageChecks = true
	if err != nil {
		diags = diags.Append(err)
		c.showDiagnostics(diags)
		return 1
	}

	// Get the context
	lr, _, ctxDiags := local.LocalRun(opReq)
	diags = diags.Append(ctxDiags)
	if ctxDiags.HasErrors() {
		c.showDiagnostics(diags)
		return 1
	}

	// Get the schemas from the context
	schemas, moreDiags := lr.Core.Schemas(lr.Config, lr.InputState)
	diags = diags.Append(moreDiags)
	if moreDiags.HasErrors() {
		c.showDiagnostics(diags)
		return 1
	}

	var planErr, stateErr error
	var plan *plans.Plan
	var stateFile *statefile.File

	// if a path was provided, try to read it as a path to a planfile
	// if that fails, try to read the cli argument as a path to a statefile
	if len(args) > 0 {
		path := args[0]
		plan, stateFile, planErr = getPlanFromPath(path)
		if planErr != nil {
			stateFile, stateErr = getStateFromPath(path)
			if stateErr != nil {
				c.Ui.Error(fmt.Sprintf(
					"Terraform couldn't read the given file as a state or plan file.\n"+
						"The errors while attempting to read the file as each format are\n"+
						"shown below.\n\n"+
						"State read error: %s\n\nPlan read error: %s",
					stateErr,
					planErr))
				return 1
			}
		}
	} else {
		env, err := c.Workspace()
		if err != nil {
			c.Ui.Error(fmt.Sprintf("Error selecting workspace: %s", err))
			return 1
		}
		stateFile, stateErr = getStateFromEnv(b, env)
		if stateErr != nil {
			c.Ui.Error(stateErr.Error())
			return 1
		}
	}

	if plan != nil {
		if jsonOutput {
			config := lr.Config
			jsonPlan, err := jsonplan.Marshal(config, plan, stateFile, schemas)

			if err != nil {
				c.Ui.Error(fmt.Sprintf("Failed to marshal plan to json: %s", err))
				return 1
			}
			c.Ui.Output(string(jsonPlan))
			return 0
		}

		view := views.NewShow(arguments.ViewHuman, c.View)
		view.Plan(plan, schemas)
		return 0
	}

	if jsonOutput {
		// At this point, it is possible that there is neither state nor a plan.
		// That's ok, we'll just return an empty object.
		jsonState, err := jsonstate.Marshal(stateFile, schemas)
		if err != nil {
			c.Ui.Error(fmt.Sprintf("Failed to marshal state to json: %s", err))
			return 1
		}
		c.Ui.Output(string(jsonState))
	} else {
		if stateFile == nil {
			c.Ui.Output("No state.")
			return 0
		}
		c.Ui.Output(format.State(&format.StateOpts{
			State:   stateFile.State,
			Color:   c.Colorize(),
			Schemas: schemas,
		}))
	}

	return 0
}

func (c *ShowCommand) Help() string {
	helpText := `
Usage: terraform [global options] show [options] [path]

  Reads and outputs a Terraform state or plan file in a human-readable
  form. If no path is specified, the current state will be shown.

Options:

  -no-color           If specified, output won't contain any color.
  -json               If specified, output the Terraform plan or state in
                      a machine-readable form.

`
	return strings.TrimSpace(helpText)
}

func (c *ShowCommand) Synopsis() string {
	return "Show the current state or a saved plan"
}

// getPlanFromPath returns a plan and statefile if the user-supplied path points
// to a planfile. If both plan and error are nil, the path is likely a
// directory. An error could suggest that the given path points to a statefile.
func getPlanFromPath(path string) (*plans.Plan, *statefile.File, error) {
	pr, err := planfile.Open(path)
	if err != nil {
		return nil, nil, err
	}
	plan, err := pr.ReadPlan()
	if err != nil {
		return nil, nil, err
	}

	stateFile, err := pr.ReadStateFile()
	return plan, stateFile, err
}

// getStateFromPath returns a statefile if the user-supplied path points to a statefile.
func getStateFromPath(path string) (*statefile.File, error) {
	f, err := os.Open(path)
	if err != nil {
		return nil, fmt.Errorf("Error loading statefile: %s", err)
	}
	defer f.Close()

	var stateFile *statefile.File
	stateFile, err = statefile.Read(f)
	if err != nil {
		return nil, fmt.Errorf("Error reading %s as a statefile: %s", path, err)
	}
	return stateFile, nil
}

// getStateFromEnv returns the State for the current workspace, if available.
func getStateFromEnv(b backend.Backend, env string) (*statefile.File, error) {
	// Get the state
	stateStore, err := b.StateMgr(env)
	if err != nil {
		return nil, fmt.Errorf("Failed to load state manager: %s", err)
	}

	if err := stateStore.RefreshState(); err != nil {
		return nil, fmt.Errorf("Failed to load state: %s", err)
	}

	sf := statemgr.Export(stateStore)

	return sf, nil
}
<commit_msg>cli: Refactor show command to remove dependence on local run and only load the backend when we need it<commit_after>package command

import (
	"fmt"
	"os"
	"strings"

	"github.com/hashicorp/terraform/internal/backend"
	"github.com/hashicorp/terraform/internal/command/arguments"
	"github.com/hashicorp/terraform/internal/command/format"
	"github.com/hashicorp/terraform/internal/command/jsonplan"
	"github.com/hashicorp/terraform/internal/command/jsonstate"
	"github.com/hashicorp/terraform/internal/command/views"
	"github.com/hashicorp/terraform/internal/configs"
	"github.com/hashicorp/terraform/internal/plans"
	"github.com/hashicorp/terraform/internal/plans/planfile"
	"github.com/hashicorp/terraform/internal/states/statefile"
	"github.com/hashicorp/terraform/internal/states/statemgr"
	"github.com/hashicorp/terraform/internal/terraform"
	"github.com/hashicorp/terraform/internal/tfdiags"
)

// ShowCommand is a Command implementation that reads and outputs the
// contents of a Terraform plan or state file.
type ShowCommand struct {
	Meta
}

func (c *ShowCommand) Run(args []string) int {
	args = c.Meta.process(args)
	cmdFlags := c.Meta.defaultFlagSet("show")
	var jsonOutput bool
	cmdFlags.BoolVar(&jsonOutput, "json", false, "produce JSON output")
	cmdFlags.Usage = func() { c.Ui.Error(c.Help()) }
	if err := cmdFlags.Parse(args); err != nil {
		c.Ui.Error(fmt.Sprintf("Error parsing command-line flags: %s\n", err.Error()))
		return 1
	}

	args = cmdFlags.Args()
	if len(args) > 2 {
		c.Ui.Error(
			"The show command expects at most two arguments.\n The path to a " +
				"Terraform state or plan file, and optionally -json for json output.\n")
		cmdFlags.Usage()
		return 1
	}

	// Check for user-supplied plugin path
	var err error
	if c.pluginPath, err = c.loadPluginPath(); err != nil {
		c.Ui.Error(fmt.Sprintf("Error loading plugin path: %s", err))
		return 1
	}

	var diags tfdiags.Diagnostics

	var planErr, stateErr error
	var plan *plans.Plan
	var stateFile *statefile.File
	var config *configs.Config
	var schemas *terraform.Schemas

	// if a path was provided, try to read it as a path to a planfile
	// if that fails, try to read the cli argument as a path to a statefile
	if len(args) > 0 {
		path := args[0]
		plan, stateFile, config, planErr = getPlanFromPath(path)
		if planErr != nil {
			stateFile, stateErr = getStateFromPath(path)
			if stateErr != nil {
				c.Ui.Error(fmt.Sprintf(
					"Terraform couldn't read the given file as a state or plan file.\n"+
						"The errors while attempting to read the file as each format are\n"+
						"shown below.\n\n"+
						"State read error: %s\n\nPlan read error: %s",
					stateErr,
					planErr))
				return 1
			}
		}
	} else {
		// Load the backend
		b, backendDiags := c.Backend(nil)
		diags = diags.Append(backendDiags)
		if backendDiags.HasErrors() {
			c.showDiagnostics(diags)
			return 1
		}
		c.ignoreRemoteVersionConflict(b)

		workspace, err := c.Workspace()
		if err != nil {
			c.Ui.Error(fmt.Sprintf("Error selecting workspace: %s", err))
			return 1
		}
		stateFile, stateErr = getStateFromBackend(b, workspace)
		if stateErr != nil {
			c.Ui.Error(stateErr.Error())
			return 1
		}
	}

	if config != nil || stateFile != nil {
		opts, err := c.contextOpts()
		if err != nil {
			diags = diags.Append(err)
			c.showDiagnostics(diags)
			return 1
		}
		tfCtx, ctxDiags := terraform.NewContext(opts)
		diags = diags.Append(ctxDiags)
		if ctxDiags.HasErrors() {
			c.showDiagnostics(diags)
			return 1
		}
		var schemaDiags tfdiags.Diagnostics
		schemas, schemaDiags = tfCtx.Schemas(config, stateFile.State)
		diags = diags.Append(schemaDiags)
		if schemaDiags.HasErrors() {
			c.showDiagnostics(diags)
			return 1
		}
	}

	if plan != nil {
		if jsonOutput {
			jsonPlan, err := jsonplan.Marshal(config, plan, stateFile, schemas)

			if err != nil {
				c.Ui.Error(fmt.Sprintf("Failed to marshal plan to json: %s", err))
				return 1
			}
			c.Ui.Output(string(jsonPlan))
			return 0
		}

		view := views.NewShow(arguments.ViewHuman, c.View)
		view.Plan(plan, schemas)
		return 0
	}

	if jsonOutput {
		// At this point, it is possible that there is neither state nor a plan.
		// That's ok, we'll just return an empty object.
		jsonState, err := jsonstate.Marshal(stateFile, schemas)
		if err != nil {
			c.Ui.Error(fmt.Sprintf("Failed to marshal state to json: %s", err))
			return 1
		}
		c.Ui.Output(string(jsonState))
	} else {
		if stateFile == nil {
			c.Ui.Output("No state.")
			return 0
		}
		c.Ui.Output(format.State(&format.StateOpts{
			State:   stateFile.State,
			Color:   c.Colorize(),
			Schemas: schemas,
		}))
	}

	return 0
}

func (c *ShowCommand) Help() string {
	helpText := `
Usage: terraform [global options] show [options] [path]

  Reads and outputs a Terraform state or plan file in a human-readable
  form. If no path is specified, the current state will be shown.

Options:

  -no-color           If specified, output won't contain any color.
  -json               If specified, output the Terraform plan or state in
                      a machine-readable form.

`
	return strings.TrimSpace(helpText)
}

func (c *ShowCommand) Synopsis() string {
	return "Show the current state or a saved plan"
}

// getPlanFromPath returns a plan, statefile, and config if the user-supplied
// path points to a planfile. If both plan and error are nil, the path is likely
// a directory. An error could suggest that the given path points to a statefile.
func getPlanFromPath(path string) (*plans.Plan, *statefile.File, *configs.Config, error) {
	planReader, err := planfile.Open(path)
	if err != nil {
		return nil, nil, nil, err
	}

	// Get plan
	plan, err := planReader.ReadPlan()
	if err != nil {
		return nil, nil, nil, err
	}

	// Get statefile
	stateFile, err := planReader.ReadStateFile()
	if err != nil {
		return nil, nil, nil, err
	}

	// Get config
	config, diags := planReader.ReadConfig()
	if diags.HasErrors() {
		return nil, nil, nil, diags.Err()
	}

	return plan, stateFile, config, err
}

// getStateFromPath returns a statefile if the user-supplied path points to a statefile.
func getStateFromPath(path string) (*statefile.File, error) {
	file, err := os.Open(path)
	if err != nil {
		return nil, fmt.Errorf("Error loading statefile: %s", err)
	}
	defer file.Close()

	var stateFile *statefile.File
	stateFile, err = statefile.Read(file)
	if err != nil {
		return nil, fmt.Errorf("Error reading %s as a statefile: %s", path, err)
	}
	return stateFile, nil
}

// getStateFromBackend returns the State for the current workspace, if available.
func getStateFromBackend(b backend.Backend, workspace string) (*statefile.File, error) {
	// Get the state store for the given workspace
	stateStore, err := b.StateMgr(workspace)
	if err != nil {
		return nil, fmt.Errorf("Failed to load state manager: %s", err)
	}

	// Refresh the state store with the latest state snapshot from persistent storage
	if err := stateStore.RefreshState(); err != nil {
		return nil, fmt.Errorf("Failed to load state: %s", err)
	}

	// Get the latest state snapshot and return it
	stateFile := statemgr.Export(stateStore)
	return stateFile, nil
}
<|endoftext|>


<commit_before>package main

import (
	"crypto/rand"
	"crypto/sha1"
	"encoding/hex"
	"errors"
	"fmt"
	"log"
	"net"
	"runtime"
	"strings"
	"sync"
	"time"

	"github.com/nictuku/dht"
	zmq "github.com/pebbe/zmq4"
)

type PeerManager struct {
	d        *dht.DHT
	sub      *zmq.Socket
	pub      *zmq.Socket
	pubchan  chan interface{}
	addrchan chan interface{}
	nick     string
	friends  map[string][]string
	venue    string
	mtx      *sync.RWMutex

	pubkey  string
	privkey string
}

func init() {
	zmq.AuthSetVerbose(true)
	zmq.AuthStart()
}

func NewPeerManager() *PeerManager {
	conf := dht.NewConfig()
	conf.Port = 55000

	pm := PeerManager{}

	var err error
	if pm.pub, err = zmq.NewSocket(zmq.PUB); err != nil {
		log.Fatalf(`can't create PUB socket: %s`, err)
	}
	if pm.sub, err = zmq.NewSocket(zmq.SUB); err != nil {
		log.Fatalf(`can't create SUB socket: %s`, err)
	}

	pm.pubchan = make(chan interface{})
	pm.addrchan = make(chan interface{}, 20)

	if pm.d, err = dht.New(conf); err != nil {
		log.Fatalf(`can't create DHT: %s`, err)
	}

	sum := sha1.Sum([]byte("LetsMeetHere"))
	pm.venue = hex.EncodeToString(sum[:])

	buf := make([]byte, 4)
	rand.Read(buf)
	pm.nick = hex.EncodeToString(buf)

	log.Printf(`My nickname is %s`, pm.nick)
	log.Printf(`I will meet my friends at %s`, pm.venue)

	pm.friends = make(map[string][]string)

	pm.sub.SetSubscribe("*")
	pm.sub.SetSubscribe(pm.nick)

	pm.pubkey = "O36ghIt]]XlwH!C?/$XWd2U/S2nXaM/.zaf6<EL+"
	pm.privkey = "-N%06D]D^+uw0v}EJjOeS-=>9f$N#E]u}}@?GBv["

	zmq.AuthCurveAdd("*", pm.pubkey)
	if err := pm.pub.ServerAuthCurve("*", pm.privkey); err != nil {
		log.Fatalf(`can't configure server auth: %s`, err)
	}
	if err := pm.sub.ClientAuthCurve(pm.pubkey, pm.pubkey, pm.privkey); err != nil {
		log.Fatalf(`can't configure client auth: %s`, err)
	}

	pm.mtx = &sync.RWMutex{}

	return &pm
}

func (pm *PeerManager) String() string {
	pm.mtx.RLock()
	defer pm.mtx.RUnlock()

	s := []string{
		fmt.Sprintf("DHT: Port: %d", pm.d.Port()),
		fmt.Sprintf("\r\nI am %s", pm.nick),
		fmt.Sprintf("I have %d friend(s)", len(pm.friends)),
		fmt.Sprintf("We're meeting at '%s'", pm.venue),
		"\r\nLast messages from my friends:\r\n",
	}

	for p, msg := range pm.friends {
		s = append(s, fmt.Sprintf("%s: %v", p, msg))
	}

	return strings.Join(s, "\r\n")
}

func (pm *PeerManager) Publish(dst string, payload []string) {
	msg := []string{ dst, pm.nick }
	pm.pubchan <- append(msg, payload...)
}

func (pm *PeerManager) Loop() {
	ih, err := dht.DecodeInfoHash(pm.venue)
	if err != nil {
		log.Printf(`can't decode infohash: %s`, err)
		return
	}

	if err := pm.d.Start(); err != nil {
		log.Printf(`can't start DHT: %s`, err)
		return
	}

	log.Printf(`DHT bound to port %d`, pm.d.Port())

	if err := pm.pub.Bind(fmt.Sprintf("tcp://*:%d", pm.d.Port())); err != nil {
		log.Fatalf(`can't bind PUB socket: %s`, err)
	}
	if err := pm.sub.Bind(fmt.Sprintf("tcp://*:%d", pm.d.Port()+1)); err != nil {
		log.Fatalf(`can't bind PUB socket: %s`, err)
	}

	go pm.drainPeers()
	/* These needs to be synchroneous because 0MQ sockets are not threadsafe */
	go func() {
		runtime.LockOSThread()

		r := zmq.NewReactor()
		r.AddSocket(pm.sub, zmq.POLLIN, func(s zmq.State) error {
			/* Handle socket input here */
			msg, err := pm.sub.RecvMessage(0)
			if err != nil {
				return err
			}

			if len(msg) < 2 {
				return errors.New(`short message received`)
			}

			tgt := msg[0]
			src := msg[1]

			if src == pm.nick {
				return nil
			}

			if tgt != pm.nick && tgt != "*" {
				log.Printf(`the following message is not for me. weird`)
			}

			log.Printf(`tgt: %s, src: %s, msg: %v`, tgt, src, msg[2:])

			pm.mtx.Lock()
			if _, ok := pm.friends[src]; !ok {
				log.Printf(`%s is a new friend!`, src)
				pm.Publish(src, []string{"hello friend :)"})
			}

			pm.friends[src] = msg[2:]
			pm.mtx.Unlock()

			return nil
		})
		r.AddChannel(pm.addrchan, 1, func(a interface{}) error {
			addr := a.(string)
			pm.connectToPeer(addr)
			return nil
		})
		r.AddChannel(pm.pubchan, 1, func(m interface{}) error {
			msg := m.([]string)
			pm.pub.SendMessageDontwait(msg)
			return nil
		})

		for {
			if err := r.Run(1 * time.Second); err != nil {
				log.Fatalf(`can't run reactor: %s`, err)
			}
			log.Printf(`polling for messages`)
		}
	}()

	go func() {
		/* This is just for testing */
		i := 0
		for {
			pm.Publish("*", []string{"test", fmt.Sprintf("%d", i)})
			i++
			time.Sleep(1 * time.Second)
		}
	}()

	for {
		pm.d.PeersRequest(string(ih), true)
		time.Sleep(5 * time.Second)
	}
}

func (pm *PeerManager) drainPeers() {
	log.Printf(`draining DHT`)
	seen := make(map[string]struct{})

	for r := range pm.d.PeersRequestResults {
		for _, peers := range r {
			for _, x := range peers {
				addr := dht.DecodePeerAddress(x)
				if _, ok := seen[addr]; !ok {
					pm.addrchan <- addr
				}
				seen[addr] = struct{}{}
			}
		}
	}
}

func (pm *PeerManager) connectToPeer(ip string) {
	addr, err := net.ResolveTCPAddr("tcp", ip)
	if err != nil {
		log.Fatalf(`can't parse tcp address %s: %s`, addr, err)
	}

	if err := pm.sub.Connect(fmt.Sprintf("tcp://%s:%d", addr.IP, addr.Port)); err != nil {
		log.Fatalf(`can't connect SUB to %s: %s`, addr, err)
	}
	if err := pm.pub.Connect(fmt.Sprintf("tcp://%s:%d", addr.IP, addr.Port+1)); err != nil {
		log.Fatalf(`can't connect SUB to %s:%d: %s`, addr.IP, addr.Port, err)
	}
}
<commit_msg>Buffer pubchannel, fix locking<commit_after>package main

import (
	"crypto/rand"
	"crypto/sha1"
	"encoding/hex"
	"errors"
	"fmt"
	"log"
	"net"
	"runtime"
	"strings"
	"sync"
	"time"

	"github.com/nictuku/dht"
	zmq "github.com/pebbe/zmq4"
)

type PeerManager struct {
	d        *dht.DHT
	sub      *zmq.Socket
	pub      *zmq.Socket
	pubchan  chan interface{}
	addrchan chan interface{}
	nick     string
	friends  map[string][]string
	venue    string
	mtx      *sync.RWMutex

	pubkey  string
	privkey string
}

func init() {
	zmq.AuthSetVerbose(true)
	zmq.AuthStart()
}

func NewPeerManager() *PeerManager {
	conf := dht.NewConfig()
	conf.Port = 55000

	pm := PeerManager{}

	var err error
	if pm.pub, err = zmq.NewSocket(zmq.PUB); err != nil {
		log.Fatalf(`can't create PUB socket: %s`, err)
	}
	if pm.sub, err = zmq.NewSocket(zmq.SUB); err != nil {
		log.Fatalf(`can't create SUB socket: %s`, err)
	}

	pm.pubchan = make(chan interface{}, 20)
	pm.addrchan = make(chan interface{}, 20)

	if pm.d, err = dht.New(conf); err != nil {
		log.Fatalf(`can't create DHT: %s`, err)
	}

	sum := sha1.Sum([]byte("LetsMeetHere"))
	pm.venue = hex.EncodeToString(sum[:])

	buf := make([]byte, 4)
	rand.Read(buf)
	pm.nick = hex.EncodeToString(buf)

	log.Printf(`My nickname is %s`, pm.nick)
	log.Printf(`I will meet my friends at %s`, pm.venue)

	pm.friends = make(map[string][]string)

	pm.sub.SetSubscribe("*")
	pm.sub.SetSubscribe(pm.nick)

	pm.pubkey = "O36ghIt]]XlwH!C?/$XWd2U/S2nXaM/.zaf6<EL+"
	pm.privkey = "-N%06D]D^+uw0v}EJjOeS-=>9f$N#E]u}}@?GBv["

	zmq.AuthCurveAdd("*", pm.pubkey)
	if err := pm.pub.ServerAuthCurve("*", pm.privkey); err != nil {
		log.Fatalf(`can't configure server auth: %s`, err)
	}
	if err := pm.sub.ClientAuthCurve(pm.pubkey, pm.pubkey, pm.privkey); err != nil {
		log.Fatalf(`can't configure client auth: %s`, err)
	}

	pm.mtx = &sync.RWMutex{}

	return &pm
}

func (pm *PeerManager) String() string {
	pm.mtx.RLock()
	defer pm.mtx.RUnlock()

	s := []string{
		fmt.Sprintf("DHT: Port: %d", pm.d.Port()),
		fmt.Sprintf("\r\nI am %s", pm.nick),
		fmt.Sprintf("I have %d friend(s)", len(pm.friends)),
		fmt.Sprintf("We're meeting at '%s'", pm.venue),
		"\r\nLast messages from my friends:\r\n",
	}

	for p, msg := range pm.friends {
		s = append(s, fmt.Sprintf("%s: %v", p, msg))
	}

	return strings.Join(s, "\r\n")
}

func (pm *PeerManager) Publish(dst string, payload []string) {
	msg := []string{ dst, pm.nick }
	pm.pubchan <- append(msg, payload...)
}

func (pm *PeerManager) Loop() {
	ih, err := dht.DecodeInfoHash(pm.venue)
	if err != nil {
		log.Printf(`can't decode infohash: %s`, err)
		return
	}

	if err := pm.d.Start(); err != nil {
		log.Printf(`can't start DHT: %s`, err)
		return
	}

	log.Printf(`DHT bound to port %d`, pm.d.Port())

	if err := pm.pub.Bind(fmt.Sprintf("tcp://*:%d", pm.d.Port())); err != nil {
		log.Fatalf(`can't bind PUB socket: %s`, err)
	}
	if err := pm.sub.Bind(fmt.Sprintf("tcp://*:%d", pm.d.Port()+1)); err != nil {
		log.Fatalf(`can't bind PUB socket: %s`, err)
	}

	go pm.drainPeers()
	/* These needs to be synchroneous because 0MQ sockets are not threadsafe */
	go func() {
		runtime.LockOSThread()

		r := zmq.NewReactor()
		r.AddSocket(pm.sub, zmq.POLLIN, func(s zmq.State) error {
			/* Handle socket input here */
			msg, err := pm.sub.RecvMessage(0)
			if err != nil {
				return err
			}

			if len(msg) < 2 {
				return errors.New(`short message received`)
			}

			tgt := msg[0]
			src := msg[1]

			if src == pm.nick {
				return nil
			}

			if tgt != pm.nick && tgt != "*" {
				log.Printf(`the following message is not for me. weird`)
			}

			log.Printf(`tgt: %s, src: %s, msg: %v`, tgt, src, msg[2:])

			pm.mtx.Lock()
			_, ok := pm.friends[src]
			pm.friends[src] = msg[2:]
			pm.mtx.Unlock()

			if !ok {
				log.Printf(`%s is a new friend!`, src)
				pm.Publish(src, []string{"hello friend :)"})
			}

			return nil
		})
		r.AddChannel(pm.addrchan, 1, func(a interface{}) error {
			addr := a.(string)
			pm.connectToPeer(addr)
			return nil
		})
		r.AddChannel(pm.pubchan, 1, func(m interface{}) error {
			msg := m.([]string)
			pm.pub.SendMessageDontwait(msg)
			return nil
		})

		for {
			if err := r.Run(1 * time.Second); err != nil {
				log.Fatalf(`can't run reactor: %s`, err)
			}
			log.Printf(`polling for messages`)
		}
	}()

	go func() {
		/* This is just for testing */
		i := 0
		for {
			pm.Publish("*", []string{"test", fmt.Sprintf("%d", i)})
			i++
			time.Sleep(1 * time.Second)
		}
	}()

	for {
		pm.d.PeersRequest(string(ih), true)
		time.Sleep(5 * time.Second)
	}
}

func (pm *PeerManager) drainPeers() {
	log.Printf(`draining DHT`)
	seen := make(map[string]struct{})

	for r := range pm.d.PeersRequestResults {
		for _, peers := range r {
			for _, x := range peers {
				addr := dht.DecodePeerAddress(x)
				if _, ok := seen[addr]; !ok {
					pm.addrchan <- addr
				}
				seen[addr] = struct{}{}
			}
		}
	}
}

func (pm *PeerManager) connectToPeer(ip string) {
	addr, err := net.ResolveTCPAddr("tcp", ip)
	if err != nil {
		log.Fatalf(`can't parse tcp address %s: %s`, addr, err)
	}

	if err := pm.sub.Connect(fmt.Sprintf("tcp://%s:%d", addr.IP, addr.Port)); err != nil {
		log.Fatalf(`can't connect SUB to %s: %s`, addr, err)
	}
	if err := pm.pub.Connect(fmt.Sprintf("tcp://%s:%d", addr.IP, addr.Port+1)); err != nil {
		log.Fatalf(`can't connect SUB to %s:%d: %s`, addr.IP, addr.Port, err)
	}
}
<|endoftext|>