<commit_before>package main

import (
	"fmt"
	"math"
	"os"
	"strings"

	"github.com/cavaliercoder/go-rpm"
)

func main() {
	if len(os.Args) < 2 || strings.HasPrefix(os.Args[1], "-") {
		os.Exit(usage(1))
	}

	fmt.Printf("---\n")
	for i, path := range os.Args[1:] {
		if i > 0 {
			fmt.Printf("\n")
		}

		raw(path)
	}
}

func raw(path string) {
	fmt.Printf("- path: %v\n", path)
	p, err := rpm.OpenPackageFile(path)
	if err != nil {
		fmt.Printf("  error: %v\n", err)
		return
	}

	fmt.Printf("  headers:\n")
	for i, h := range p.Headers {
		if i > 0 {
			fmt.Printf("\n")
		}

		fmt.Printf("  - index: %v\n", i)
		fmt.Printf("    version: %v\n", h.Version)
		fmt.Printf("    start: %v\n", h.Start)
		fmt.Printf("    end: %v\n", h.End)
		fmt.Printf("    length: %v\n", h.Length)
		fmt.Printf("    indexes:\n")
		for j, ix := range h.Indexes {
			if j > 0 {
				fmt.Printf("\n")
			}

			fmt.Printf("    - index: %v\n", j)
			fmt.Printf("      tag: %v\n", ix.Tag)
			fmt.Printf("      type: %v\n", ix.Type)
			fmt.Printf("      offset: %v\n", ix.Offset)

			switch ix.Value.(type) {
			case []string:
				ss := ix.Value.([]string)
				if len(ss) == 1 && strings.Index(ss[0], "\n") == -1 {
					fmt.Printf("      value: [\"%v\"]\n", ss[0])
				} else {
					fmt.Printf("      value:\n")
					for _, s := range ss {
						if strings.Index(s, "\n") == -1 {
							fmt.Printf("      - \"%v\"\n", s)
						} else {
							fmt.Printf("      - |\n")
							lines := strings.Split(s, "\n")
							for _, line := range lines {
								fmt.Printf("        %v\n", line)
							}
						}
					}
				}

			case []byte:
				b := ix.Value.([]byte)
				if len(b) <= 16 {
					fmt.Print("      value: [")
					for i, x := range b {
						if i > 0 {
							fmt.Print(" ")
						}
						fmt.Printf("%02x", x)
					}
					fmt.Println("]")
				} else {
					fmt.Println("      value: |")
					for i := 0; i < len(b); i += 16 {
						fmt.Printf("        %08x  ", i)
						l := int(math.Min(16, float64(len(b)-i)))
						for j := 0; j < l; j++ {
							fmt.Printf("%02x ", b[i+j])
							if j == 7 {
								fmt.Print(" ")
							}
						}

						for j := 0; j < 16-l; j++ {
							fmt.Print("   ")
						}
						if l < 8 {
							fmt.Print(" ")
						}

						s := [16]byte{}
						copy(s[:], b[i:])
						for j := 0; j < 16; j++ {
							// print '.' if char is not printable ascii
							if s[j] < 32 || s[j] > 126 {
								s[j] = 46
							}
						}
						fmt.Printf(" |%s|\n", s)
					}
				}

			default:
				fmt.Printf("      value: %v\n", ix.Value)
			}
		}
	}
}

func usage(exitCode int) int {
	w := os.Stdout
	if exitCode != 0 {
		w = os.Stderr
	}

	fmt.Fprintf(w, "usage: %v [path ...]\n", os.Args[0])
	return exitCode
}

func die(format string, a ...interface{}) {
	fmt.Fprintf(os.Stderr, format, a...)
	os.Exit(1)
}

func dieOn(err error) {
	if err != nil {
		die("%v\n", err)
	}
}
<commit_msg>Fixed broken API in rpmdump<commit_after>package main

import (
	"fmt"
	"math"
	"os"
	"strings"

	"github.com/cavaliercoder/go-rpm"
)

func main() {
	if len(os.Args) < 2 || strings.HasPrefix(os.Args[1], "-") {
		os.Exit(usage(1))
	}

	fmt.Printf("---\n")
	for i, path := range os.Args[1:] {
		if i > 0 {
			fmt.Printf("\n")
		}

		raw(path)
	}
}

func raw(path string) {
	fmt.Printf("- path: %v\n", path)
	p, err := rpm.OpenPackageFile(path)
	if err != nil {
		fmt.Printf("  error: %v\n", err)
		return
	}

	fmt.Printf("  headers:\n")
	for i, h := range p.Headers {
		if i > 0 {
			fmt.Printf("\n")
		}

		fmt.Printf("  - index: %v\n", i)
		fmt.Printf("    version: %v\n", h.Version)
		fmt.Printf("    length: %v\n", h.Length)
		fmt.Printf("    indexes:\n")
		for j, ix := range h.Indexes {
			if j > 0 {
				fmt.Printf("\n")
			}

			fmt.Printf("    - index: %v\n", j)
			fmt.Printf("      tag: %v\n", ix.Tag)
			fmt.Printf("      type: %v\n", ix.Type)
			fmt.Printf("      offset: %v\n", ix.Offset)

			switch ix.Value.(type) {
			case []string:
				ss := ix.Value.([]string)
				if len(ss) == 1 && strings.Index(ss[0], "\n") == -1 {
					fmt.Printf("      value: [\"%v\"]\n", ss[0])
				} else {
					fmt.Printf("      value:\n")
					for _, s := range ss {
						if strings.Index(s, "\n") == -1 {
							fmt.Printf("      - \"%v\"\n", s)
						} else {
							fmt.Printf("      - |\n")
							lines := strings.Split(s, "\n")
							for _, line := range lines {
								fmt.Printf("        %v\n", line)
							}
						}
					}
				}

			case []byte:
				b := ix.Value.([]byte)
				if len(b) <= 16 {
					fmt.Print("      value: [")
					for i, x := range b {
						if i > 0 {
							fmt.Print(" ")
						}
						fmt.Printf("%02x", x)
					}
					fmt.Println("]")
				} else {
					fmt.Println("      value: |")
					for i := 0; i < len(b); i += 16 {
						fmt.Printf("        %08x  ", i)
						l := int(math.Min(16, float64(len(b)-i)))
						for j := 0; j < l; j++ {
							fmt.Printf("%02x ", b[i+j])
							if j == 7 {
								fmt.Print(" ")
							}
						}

						for j := 0; j < 16-l; j++ {
							fmt.Print("   ")
						}
						if l < 8 {
							fmt.Print(" ")
						}

						s := [16]byte{}
						copy(s[:], b[i:])
						for j := 0; j < 16; j++ {
							// print '.' if char is not printable ascii
							if s[j] < 32 || s[j] > 126 {
								s[j] = 46
							}
						}
						fmt.Printf(" |%s|\n", s)
					}
				}

			default:
				fmt.Printf("      value: %v\n", ix.Value)
			}
		}
	}
}

func usage(exitCode int) int {
	w := os.Stdout
	if exitCode != 0 {
		w = os.Stderr
	}

	fmt.Fprintf(w, "usage: %v [path ...]\n", os.Args[0])
	return exitCode
}

func die(format string, a ...interface{}) {
	fmt.Fprintf(os.Stderr, format, a...)
	os.Exit(1)
}

func dieOn(err error) {
	if err != nil {
		die("%v\n", err)
	}
}
<|endoftext|>


<commit_before>package goap

import (
	"bytes"
	"log"
	"net"
	"strconv"
	"time"
	. "github.com/zubairhamed/go-commons/network"
)

func NewServer(localAddr *net.UDPAddr, remoteAddr *net.UDPAddr) *CoapServer {

	return &CoapServer{
		remoteAddr: remoteAddr,
		localAddr:  localAddr,
	}
}

type CoapServer struct {
	localAddr  *net.UDPAddr
	remoteAddr *net.UDPAddr
	conn       *net.UDPConn
	messageIds map[uint16]time.Time
	routes     []*Route

	evtOnStartup  EventHandler
	evtOnClose    EventHandler
	evtOnDiscover EventHandler
	evtOnError    EventHandler
	evtOnMessage  EventHandler
}

func (s *CoapServer) Start() {

	var discoveryRoute RouteHandler = func(req Request) Response {
		msg := req.(*CoapRequest).GetMessage()

		ack := NewMessageOfType(TYPE_ACKNOWLEDGEMENT, msg.MessageId)
		ack.Code = COAPCODE_205_CONTENT
		ack.AddOption(OPTION_CONTENT_FORMAT, MEDIATYPE_APPLICATION_LINK_FORMAT)

		var buf bytes.Buffer
		for _, r := range s.routes {
			if r.Path != ".well-known/core" {
				buf.WriteString("</")
				buf.WriteString(r.Path)
				buf.WriteString(">")

				// Media Types
				lenMt := len(r.MediaTypes)
				if lenMt > 0 {
					buf.WriteString(";ct=")
					for idx, mt := range r.MediaTypes {

						buf.WriteString(strconv.Itoa(int(mt)))
						if idx+1 < lenMt {
							buf.WriteString(" ")
						}
					}
				}

				buf.WriteString(",")
				// buf.WriteString("</" + r.Path + ">;ct=0,")
			}
		}
		ack.Payload = NewPlainTextPayload(buf.String())

		/*
		   if s.fnEventDiscover != nil {
		       e := NewEvent()
		       e.Message = ack

		       ack = s.fnEventDiscover(e)
		   }
		*/

		resp := NewResponseWithMessage(ack)

		return resp
	}

	s.NewRoute(".well-known/core", GET, discoveryRoute)
	s.serveServer()
}

func (s *CoapServer) serveServer() {
		s.messageIds = make(map[uint16]time.Time)

		conn, err := net.ListenUDP("udp", s.localAddr)
		IfErr(err)
		s.conn = conn

		log.Println("Started server ", conn.LocalAddr())

		CallEvent(s.evtOnStartup, EmptyEventPayload())

		s.handleMessageIdPurge()

		readBuf := make([]byte, BUF_SIZE)
		for {
			len, addr, err := conn.ReadFromUDP(readBuf)

			if err == nil {

				msgBuf := make([]byte, len)
				copy(msgBuf, readBuf)

				// Look for route handler matching path and then dispatch
				go s.handleMessage(msgBuf, conn, addr)
			}
		}
}

func (s *CoapServer) handleMessageIdPurge() {
	// Routine for clearing up message IDs which has expired
	ticker := time.NewTicker(MESSAGEID_PURGE_DURATION * time.Second)
	go func() {
		for {
			select {
			case <-ticker.C:
				for k, v := range s.messageIds {
					elapsed := time.Since(v)
					if elapsed > MESSAGEID_PURGE_DURATION {
						delete(s.messageIds, k)
					}
				}
			}
		}
	}()
}

func (s *CoapServer) handleMessage(msgBuf []byte, conn *net.UDPConn, addr *net.UDPAddr) {
	msg, err := BytesToMessage(msgBuf)

	CallEvent(s.evtOnMessage, EmptyEventPayload())

	// Unsupported Method
	if msg.Code != GET && msg.Code != POST && msg.Code != PUT && msg.Code != DELETE {
		ret := NewMessage(TYPE_NONCONFIRMABLE, COAPCODE_501_NOT_IMPLEMENTED, msg.MessageId)
		ret.CloneOptions(msg, OPTION_URI_PATH, OPTION_CONTENT_FORMAT)

		SendMessageTo(ret, conn, addr)
		return
	}

	if err != nil {
		if err == ERR_UNKNOWN_CRITICAL_OPTION {
			if msg.MessageType == TYPE_CONFIRMABLE {
				SendError402BadOption(msg.MessageId, conn, addr)
				return
			} else {
				// Ignore silently
				return
			}
		}
	}

	route, attrs, err := MatchingRoute(msg.GetUriPath(), MethodString(msg.Code), msg.GetOptions(OPTION_CONTENT_FORMAT), s.routes)
	if err != nil {
		if err == ERR_NO_MATCHING_ROUTE {
			ret := NewMessage(TYPE_NONCONFIRMABLE, COAPCODE_404_NOT_FOUND, msg.MessageId)
			ret.CloneOptions(msg, OPTION_URI_PATH, OPTION_CONTENT_FORMAT)
			ret.Token = msg.Token

			SendMessageTo(ret, conn, addr)
			CallEvent(s.evtOnError, EmptyEventPayload())
			return
		}

		if err == ERR_NO_MATCHING_METHOD {
			ret := NewMessage(TYPE_NONCONFIRMABLE, COAPCODE_405_METHOD_NOT_ALLOWED, msg.MessageId)
			ret.CloneOptions(msg, OPTION_URI_PATH, OPTION_CONTENT_FORMAT)

			SendMessageTo(ret, conn, addr)
			CallEvent(s.evtOnError, EmptyEventPayload())
			return
		}

		if err == ERR_UNSUPPORTED_CONTENT_FORMAT {
			ret := NewMessage(TYPE_NONCONFIRMABLE, COAPCODE_415_UNSUPPORTED_CONTENT_FORMAT, msg.MessageId)
			ret.CloneOptions(msg, OPTION_URI_PATH, OPTION_CONTENT_FORMAT)

			SendMessageTo(ret, conn, addr)
			CallEvent(s.evtOnError, EmptyEventPayload())
			return
		}
	}

	// Duplicate Message ID Check
	_, dupe := s.messageIds[msg.MessageId]
	if dupe {
		log.Println("Duplicate Message ID ", msg.MessageId)
		if msg.MessageType == TYPE_CONFIRMABLE {
			ret := NewMessage(TYPE_RESET, COAPCODE_0_EMPTY, msg.MessageId)
			ret.CloneOptions(msg, OPTION_URI_PATH, OPTION_CONTENT_FORMAT)

			SendMessageTo(ret, conn, addr)
		}
		return
	}

	if err == nil {
		s.messageIds[msg.MessageId] = time.Now()

		// TODO: #47 - Forward Proxy

		// Auto acknowledge
		if msg.MessageType == TYPE_CONFIRMABLE && route.AutoAck {
			ack := NewMessageOfType(TYPE_ACKNOWLEDGEMENT, msg.MessageId)

			SendMessageTo(ack, conn, addr)
		}

		req := NewRequestFromMessage(msg, attrs)

		resp := route.Handler(req).(*CoapResponse)

		// TODO: Validate Message before sending (.e.g missing messageId)
		SendMessageTo(resp.GetMessage(), conn, addr)
	}
}

func (s *CoapServer) NewRoute(path string, method CoapCode, fn RouteHandler) *Route {
	route := CreateNewRoute(path, MethodString(method), fn)
	s.routes = append(s.routes, route)

	return route
}

func (c *CoapServer) Send(req *CoapRequest) (*CoapResponse, error) {
	return SendMessageTo(req.GetMessage(), c.conn, c.remoteAddr)
}

func (c *CoapServer) SendTo(req *CoapRequest, addr *net.UDPAddr) (*CoapResponse, error) {
	return SendMessageTo(req.GetMessage(), c.conn, addr)
}

func (c *CoapServer) OnStartup(eh EventHandler) {
	c.evtOnStartup = eh
}

func (c *CoapServer) OnClose(eh EventHandler) {
	c.evtOnStartup = eh
}

func (c *CoapServer) OnDiscover(eh EventHandler) {
	c.evtOnStartup = eh
}

func (c *CoapServer) OnError(eh EventHandler) {
	c.evtOnStartup = eh
}

func (c *CoapServer) OnMessage(eh EventHandler) {
	c.evtOnStartup = eh
}
<commit_msg>Minor log updates<commit_after>package goap

import (
	"bytes"
	"log"
	"net"
	"strconv"
	"time"
	. "github.com/zubairhamed/go-commons/network"
)

func NewServer(localAddr *net.UDPAddr, remoteAddr *net.UDPAddr) *CoapServer {

	return &CoapServer{
		remoteAddr: remoteAddr,
		localAddr:  localAddr,
	}
}

type CoapServer struct {
	localAddr  *net.UDPAddr
	remoteAddr *net.UDPAddr
	conn       *net.UDPConn
	messageIds map[uint16]time.Time
	routes     []*Route

	evtOnStartup  EventHandler
	evtOnClose    EventHandler
	evtOnDiscover EventHandler
	evtOnError    EventHandler
	evtOnMessage  EventHandler
}

func (s *CoapServer) Start() {

	var discoveryRoute RouteHandler = func(req Request) Response {
		msg := req.(*CoapRequest).GetMessage()

		ack := NewMessageOfType(TYPE_ACKNOWLEDGEMENT, msg.MessageId)
		ack.Code = COAPCODE_205_CONTENT
		ack.AddOption(OPTION_CONTENT_FORMAT, MEDIATYPE_APPLICATION_LINK_FORMAT)

		var buf bytes.Buffer
		for _, r := range s.routes {
			if r.Path != ".well-known/core" {
				buf.WriteString("</")
				buf.WriteString(r.Path)
				buf.WriteString(">")

				// Media Types
				lenMt := len(r.MediaTypes)
				if lenMt > 0 {
					buf.WriteString(";ct=")
					for idx, mt := range r.MediaTypes {

						buf.WriteString(strconv.Itoa(int(mt)))
						if idx+1 < lenMt {
							buf.WriteString(" ")
						}
					}
				}

				buf.WriteString(",")
				// buf.WriteString("</" + r.Path + ">;ct=0,")
			}
		}
		ack.Payload = NewPlainTextPayload(buf.String())

		/*
		   if s.fnEventDiscover != nil {
		       e := NewEvent()
		       e.Message = ack

		       ack = s.fnEventDiscover(e)
		   }
		*/

		resp := NewResponseWithMessage(ack)

		return resp
	}

	s.NewRoute(".well-known/core", GET, discoveryRoute)
	s.serveServer()
}

func (s *CoapServer) serveServer() {
		s.messageIds = make(map[uint16]time.Time)

		conn, err := net.ListenUDP("udp", s.localAddr)
		IfErr(err)
		s.conn = conn

		log.Println("Started CoAP Server ", conn.LocalAddr())

		CallEvent(s.evtOnStartup, EmptyEventPayload())

		s.handleMessageIdPurge()

		readBuf := make([]byte, BUF_SIZE)
		for {
			len, addr, err := conn.ReadFromUDP(readBuf)

			if err == nil {

				msgBuf := make([]byte, len)
				copy(msgBuf, readBuf)

				// Look for route handler matching path and then dispatch
				go s.handleMessage(msgBuf, conn, addr)
			}
		}
}

func (s *CoapServer) handleMessageIdPurge() {
	// Routine for clearing up message IDs which has expired
	ticker := time.NewTicker(MESSAGEID_PURGE_DURATION * time.Second)
	go func() {
		for {
			select {
			case <-ticker.C:
				for k, v := range s.messageIds {
					elapsed := time.Since(v)
					if elapsed > MESSAGEID_PURGE_DURATION {
						delete(s.messageIds, k)
					}
				}
			}
		}
	}()
}

func (s *CoapServer) handleMessage(msgBuf []byte, conn *net.UDPConn, addr *net.UDPAddr) {
	msg, err := BytesToMessage(msgBuf)

	CallEvent(s.evtOnMessage, EmptyEventPayload())

	// Unsupported Method
	if msg.Code != GET && msg.Code != POST && msg.Code != PUT && msg.Code != DELETE {
		ret := NewMessage(TYPE_NONCONFIRMABLE, COAPCODE_501_NOT_IMPLEMENTED, msg.MessageId)
		ret.CloneOptions(msg, OPTION_URI_PATH, OPTION_CONTENT_FORMAT)

		SendMessageTo(ret, conn, addr)
		return
	}

	if err != nil {
		if err == ERR_UNKNOWN_CRITICAL_OPTION {
			if msg.MessageType == TYPE_CONFIRMABLE {
				SendError402BadOption(msg.MessageId, conn, addr)
				return
			} else {
				// Ignore silently
				return
			}
		}
	}

	route, attrs, err := MatchingRoute(msg.GetUriPath(), MethodString(msg.Code), msg.GetOptions(OPTION_CONTENT_FORMAT), s.routes)
	if err != nil {
		if err == ERR_NO_MATCHING_ROUTE {
			ret := NewMessage(TYPE_NONCONFIRMABLE, COAPCODE_404_NOT_FOUND, msg.MessageId)
			ret.CloneOptions(msg, OPTION_URI_PATH, OPTION_CONTENT_FORMAT)
			ret.Token = msg.Token

			SendMessageTo(ret, conn, addr)
			CallEvent(s.evtOnError, EmptyEventPayload())
			return
		}

		if err == ERR_NO_MATCHING_METHOD {
			ret := NewMessage(TYPE_NONCONFIRMABLE, COAPCODE_405_METHOD_NOT_ALLOWED, msg.MessageId)
			ret.CloneOptions(msg, OPTION_URI_PATH, OPTION_CONTENT_FORMAT)

			SendMessageTo(ret, conn, addr)
			CallEvent(s.evtOnError, EmptyEventPayload())
			return
		}

		if err == ERR_UNSUPPORTED_CONTENT_FORMAT {
			ret := NewMessage(TYPE_NONCONFIRMABLE, COAPCODE_415_UNSUPPORTED_CONTENT_FORMAT, msg.MessageId)
			ret.CloneOptions(msg, OPTION_URI_PATH, OPTION_CONTENT_FORMAT)

			SendMessageTo(ret, conn, addr)
			CallEvent(s.evtOnError, EmptyEventPayload())
			return
		}
	}

	// Duplicate Message ID Check
	_, dupe := s.messageIds[msg.MessageId]
	if dupe {
		log.Println("Duplicate Message ID ", msg.MessageId)
		if msg.MessageType == TYPE_CONFIRMABLE {
			ret := NewMessage(TYPE_RESET, COAPCODE_0_EMPTY, msg.MessageId)
			ret.CloneOptions(msg, OPTION_URI_PATH, OPTION_CONTENT_FORMAT)

			SendMessageTo(ret, conn, addr)
		}
		return
	}

	if err == nil {
		s.messageIds[msg.MessageId] = time.Now()

		// TODO: #47 - Forward Proxy

		// Auto acknowledge
		if msg.MessageType == TYPE_CONFIRMABLE && route.AutoAck {
			ack := NewMessageOfType(TYPE_ACKNOWLEDGEMENT, msg.MessageId)

			SendMessageTo(ack, conn, addr)
		}

		req := NewRequestFromMessage(msg, attrs)

		resp := route.Handler(req).(*CoapResponse)

		// TODO: Validate Message before sending (.e.g missing messageId)
		SendMessageTo(resp.GetMessage(), conn, addr)
	}
}

func (s *CoapServer) NewRoute(path string, method CoapCode, fn RouteHandler) *Route {
	route := CreateNewRoute(path, MethodString(method), fn)
	s.routes = append(s.routes, route)

	return route
}

func (c *CoapServer) Send(req *CoapRequest) (*CoapResponse, error) {
	return SendMessageTo(req.GetMessage(), c.conn, c.remoteAddr)
}

func (c *CoapServer) SendTo(req *CoapRequest, addr *net.UDPAddr) (*CoapResponse, error) {
	return SendMessageTo(req.GetMessage(), c.conn, addr)
}

func (c *CoapServer) OnStartup(eh EventHandler) {
	c.evtOnStartup = eh
}

func (c *CoapServer) OnClose(eh EventHandler) {
	c.evtOnStartup = eh
}

func (c *CoapServer) OnDiscover(eh EventHandler) {
	c.evtOnStartup = eh
}

func (c *CoapServer) OnError(eh EventHandler) {
	c.evtOnStartup = eh
}

func (c *CoapServer) OnMessage(eh EventHandler) {
	c.evtOnStartup = eh
}
<|endoftext|>


<commit_before>package brain

import (
	"encoding/json"
)

//MigrationJobModify represents the modifications possible on a migration job
type MigrationJobModification struct {
	Cancel  MigrationJobLocations `json:"cancel,omitempty"`
	Options MigrationJobOptions   `json:"options,omitempty"`
}

// MigrationJobQueue is a list of disc IDs that are still to be migrated as
// part of a migration job.
type MigrationJobQueue struct {
	Discs []int `json:"discs,omitempty"`
}

// MigrationJobLocations represents source or target locations for a migration
// job. Discs, pools and tails maybe represented by ID number, label or UUID.
type MigrationJobLocations struct {
	Discs []json.Number `json:"discs,omitempty"`
	Pools []json.Number `json:"pools,omitempty"`
	Tails []json.Number `json:"tails,omitempty"`
}

// MigrationJobDestinations represents available desintations for a migration
// job. Unlike MigrationJobLocations, these are represented using ID number
// only.
type MigrationJobDestinations struct {
	Pools []int `json:"pools,omitempty"`
}

// MigrationJobOptions represents options on a migration job.
type MigrationJobOptions struct {
	Priority int `json:"priority,omitempty"`
}

// MigrationJobDiscStatus represents the current status of a migration job.
// Each entry is a list of disc IDs indicating the fate of discs that
// have been removed from the queue.
type MigrationJobDiscStatus struct {
	Done      []int `json:"done,omitempty"`
	Errored   []int `json:"errored,omitempty"`
	Cancelled []int `json:"cancelled,omitempty"`
	Skipped   []int `json:"skipped,omitempty"`
}

// MigrationJobStatus captures the status of a migration job, currently only
// discs.
type MigrationJobStatus struct {
	Discs MigrationJobDiscStatus `json:"discs,omitempty"`
}

// MigrationJobSpec is a specification of a migration job to be created
type MigrationJobSpec struct {
	Options      MigrationJobOptions   `json:"options,imotempty"`
	Sources      MigrationJobLocations `json:"sources,omitempty"`
	Destinations MigrationJobLocations `json:"destinations,omitempty"`
}

// MigrationJob is a representation of a migration job.
type MigrationJob struct {
	ID           int                      `json:"id,omitempty"`
	Args         MigrationJobSpec         `json:"args,omitempty"`
	Queue        MigrationJobQueue        `json:"queue,omitempty"`
	Destinations MigrationJobDestinations `json:"destinations,omitempty"`
	Status       MigrationJobStatus       `json:"status,omitempty"`
	Priority     int                      `json:"priority,omitempty"`
	StartedAt    string                   `json:"started_at,omitempty"`
	FinishedAt   string                   `json:"finished_at,omitempty"`
	CreatedAt    string                   `json:"created_at,omitempty"`
	UpdatedAt    string                   `json:"updated_at,omitempty"`
}
<commit_msg>update comment on MigrationJobModification<commit_after>package brain

import (
	"encoding/json"
)

//MigrationJobModification represents the modifications possible on a migration job
type MigrationJobModification struct {
	Cancel  MigrationJobLocations `json:"cancel,omitempty"`
	Options MigrationJobOptions   `json:"options,omitempty"`
}

// MigrationJobQueue is a list of disc IDs that are still to be migrated as
// part of a migration job.
type MigrationJobQueue struct {
	Discs []int `json:"discs,omitempty"`
}

// MigrationJobLocations represents source or target locations for a migration
// job. Discs, pools and tails maybe represented by ID number, label or UUID.
type MigrationJobLocations struct {
	Discs []json.Number `json:"discs,omitempty"`
	Pools []json.Number `json:"pools,omitempty"`
	Tails []json.Number `json:"tails,omitempty"`
}

// MigrationJobDestinations represents available desintations for a migration
// job. Unlike MigrationJobLocations, these are represented using ID number
// only.
type MigrationJobDestinations struct {
	Pools []int `json:"pools,omitempty"`
}

// MigrationJobOptions represents options on a migration job.
type MigrationJobOptions struct {
	Priority int `json:"priority,omitempty"`
}

// MigrationJobDiscStatus represents the current status of a migration job.
// Each entry is a list of disc IDs indicating the fate of discs that
// have been removed from the queue.
type MigrationJobDiscStatus struct {
	Done      []int `json:"done,omitempty"`
	Errored   []int `json:"errored,omitempty"`
	Cancelled []int `json:"cancelled,omitempty"`
	Skipped   []int `json:"skipped,omitempty"`
}

// MigrationJobStatus captures the status of a migration job, currently only
// discs.
type MigrationJobStatus struct {
	Discs MigrationJobDiscStatus `json:"discs,omitempty"`
}

// MigrationJobSpec is a specification of a migration job to be created
type MigrationJobSpec struct {
	Options      MigrationJobOptions   `json:"options,imotempty"`
	Sources      MigrationJobLocations `json:"sources,omitempty"`
	Destinations MigrationJobLocations `json:"destinations,omitempty"`
}

// MigrationJob is a representation of a migration job.
type MigrationJob struct {
	ID           int                      `json:"id,omitempty"`
	Args         MigrationJobSpec         `json:"args,omitempty"`
	Queue        MigrationJobQueue        `json:"queue,omitempty"`
	Destinations MigrationJobDestinations `json:"destinations,omitempty"`
	Status       MigrationJobStatus       `json:"status,omitempty"`
	Priority     int                      `json:"priority,omitempty"`
	StartedAt    string                   `json:"started_at,omitempty"`
	FinishedAt   string                   `json:"finished_at,omitempty"`
	CreatedAt    string                   `json:"created_at,omitempty"`
	UpdatedAt    string                   `json:"updated_at,omitempty"`
}
<|endoftext|>


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

package main_test

import (
	"os"
	"os/exec"
	"path/filepath"
	"runtime"
	"testing"
)

const (
	dataDir = "testdata"
	binary  = "testvet"
)

// Run this shell script, but do it in Go so it can be run by "go test".
// 	go build -o testvet
// 	$(GOROOT)/test/errchk ./testvet -printfuncs='Warn:1,Warnf:1' testdata/*.go testdata/*.s
// 	rm testvet
//
func TestVet(t *testing.T) {
	// Windows systems can't be guaranteed to have Perl and so can't run errchk.
	if runtime.GOOS == "windows" {
		t.Skip("skipping test; no Perl on Windows")
	}

	// go build
	cmd := exec.Command("go", "build", "-o", binary)
	run(cmd, t)

	// defer removal of vet
	defer os.Remove(binary)

	// errchk ./testvet
	gos, err := filepath.Glob(filepath.Join(dataDir, "*.go"))
	if err != nil {
		t.Fatal(err)
	}
	asms, err := filepath.Glob(filepath.Join(dataDir, "*.s"))
	if err != nil {
		t.Fatal(err)
	}
	files := append(gos, asms...)
	errchk := filepath.Join(runtime.GOROOT(), "test", "errchk")
	flags := []string{
		binary,
		"-printfuncs=Warn:1,Warnf:1",
	}
	cmd = exec.Command(errchk, append(flags, files...)...)
	if !run(cmd, t) {
		t.Fatal("vet command failed")
	}
}

func run(c *exec.Cmd, t *testing.T) bool {
	output, err := c.CombinedOutput()
	os.Stderr.Write(output)
	if err != nil {
		t.Fatal(err)
	}
	// Errchk delights by not returning non-zero status if it finds errors, so we look at the output.
	return c.ProcessState.Success() && len(output) == 0
}
<commit_msg>go.tools/cmd/vet: attempt to fix build Can't reproduce the failure outside the builder, but attempt a fix by changing the criterion for failure: FAIL iff the output contains "BUG".<commit_after>// Copyright 2013 The Go Authors.  All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package main_test

import (
	"bytes"
	"os"
	"os/exec"
	"path/filepath"
	"runtime"
	"testing"
)

const (
	dataDir = "testdata"
	binary  = "testvet"
)

// Run this shell script, but do it in Go so it can be run by "go test".
// 	go build -o testvet
// 	$(GOROOT)/test/errchk ./testvet -printfuncs='Warn:1,Warnf:1' testdata/*.go testdata/*.s
// 	rm testvet
//
func TestVet(t *testing.T) {
	// Windows systems can't be guaranteed to have Perl and so can't run errchk.
	if runtime.GOOS == "windows" {
		t.Skip("skipping test; no Perl on Windows")
	}

	// go build
	cmd := exec.Command("go", "build", "-o", binary)
	run(cmd, t)

	// defer removal of vet
	defer os.Remove(binary)

	// errchk ./testvet
	gos, err := filepath.Glob(filepath.Join(dataDir, "*.go"))
	if err != nil {
		t.Fatal(err)
	}
	asms, err := filepath.Glob(filepath.Join(dataDir, "*.s"))
	if err != nil {
		t.Fatal(err)
	}
	files := append(gos, asms...)
	errchk := filepath.Join(runtime.GOROOT(), "test", "errchk")
	flags := []string{
		binary,
		"-printfuncs=Warn:1,Warnf:1",
	}
	cmd = exec.Command(errchk, append(flags, files...)...)
	if !run(cmd, t) {
		t.Fatal("vet command failed")
	}
}

func run(c *exec.Cmd, t *testing.T) bool {
	output, err := c.CombinedOutput()
	os.Stderr.Write(output)
	if err != nil {
		t.Fatal(err)
	}
	// Errchk delights by not returning non-zero status if it finds errors, so we look at the output.
	// It prints "BUG" if there is a failure.
	if !c.ProcessState.Success() {
		return false
	}
	return !bytes.Contains(output, []byte("BUG"))
}
<|endoftext|>


<commit_before>// API version number check
package main

import (
	"fmt"
	"github.com/bmizerany/assert"
	"github.com/xyproto/permissionHSTORE"
	"github.com/xyproto/permissionbolt"
	"github.com/xyproto/permissions2"
	"github.com/xyproto/permissionsql"
	"github.com/xyproto/pinterface"
	"github.com/xyproto/simplebolt"
	"github.com/xyproto/simplehstore"
	"github.com/xyproto/simplemaria"
	"github.com/xyproto/simpleredis"
	"testing"
)

// VersionInfo helps to keep track of package names and versions
type VersionInfo struct {
	name    string
	current float64
	target  float64
}

// New takes the name of the go package, the current and the desired version
func New(name string, current, target float64) *VersionInfo {
	return &VersionInfo{name, current, target}
}

// Check compares the current and target version
func (v *VersionInfo) Check() error {
	if v.current != v.target {
		return fmt.Errorf("is %.1f, needs version %.1f", v.current, v.target)
	}
	return nil
}

func TestAPI(t *testing.T) {
	assert.Equal(t, New("simplebolt", simplebolt.Version, 3.0).Check(), nil)
	assert.Equal(t, New("permissionbolt", permissionbolt.Version, 2.0).Check(), nil)
	assert.Equal(t, New("simpleredis", simpleredis.Version, 2.0).Check(), nil)
	assert.Equal(t, New("permissions", permissions.Version, 2.2).Check(), nil)
	assert.Equal(t, New("simplemaria", simplemaria.Version, 3.0).Check(), nil)
	assert.Equal(t, New("permissionsql", permissionsql.Version, 2.0).Check(), nil)
	assert.Equal(t, New("simplehstore", simplehstore.Version, 2.3).Check(), nil)
	assert.Equal(t, New("permissionHSTORE", permissionHSTORE.Version, 2.1).Check(), nil)
	assert.Equal(t, New("pinterface", pinterface.Version, 4.0).Check(), nil)
}
<commit_msg>Update API test<commit_after>// API version number check
package main

import (
	"fmt"
	"github.com/bmizerany/assert"
	"github.com/xyproto/permissionHSTORE"
	"github.com/xyproto/permissionbolt"
	"github.com/xyproto/permissions2"
	"github.com/xyproto/permissionsql"
	"github.com/xyproto/pinterface"
	"github.com/xyproto/simplebolt"
	"github.com/xyproto/simplehstore"
	"github.com/xyproto/simplemaria"
	"github.com/xyproto/simpleredis"
	"testing"
)

// VersionInfo helps to keep track of package names and versions
type VersionInfo struct {
	name    string
	current float64
	target  float64
}

// New takes the name of the go package, the current and the desired version
func New(name string, current, target float64) *VersionInfo {
	return &VersionInfo{name, current, target}
}

// Check compares the current and target version
func (v *VersionInfo) Check() error {
	if v.current != v.target {
		return fmt.Errorf("is %.1f, needs version %.1f", v.current, v.target)
	}
	return nil
}

func TestAPI(t *testing.T) {
	assert.Equal(t, New("simplebolt", simplebolt.Version, 3.0).Check(), nil)
	assert.Equal(t, New("permissionbolt", permissionbolt.Version, 2.0).Check(), nil)
	assert.Equal(t, New("simpleredis", simpleredis.Version, 2.1).Check(), nil)
	assert.Equal(t, New("permissions", permissions.Version, 2.2).Check(), nil)
	assert.Equal(t, New("simplemaria", simplemaria.Version, 3.0).Check(), nil)
	assert.Equal(t, New("permissionsql", permissionsql.Version, 2.0).Check(), nil)
	assert.Equal(t, New("simplehstore", simplehstore.Version, 2.3).Check(), nil)
	assert.Equal(t, New("permissionHSTORE", permissionHSTORE.Version, 2.1).Check(), nil)
	assert.Equal(t, New("pinterface", pinterface.Version, 4.0).Check(), nil)
}
<|endoftext|>


<commit_before>package tracing

import (
	"errors"
	"io"
	"sync"

	"contrib.go.opencensus.io/exporter/stackdriver"
	oczipkin "contrib.go.opencensus.io/exporter/zipkin"
	zipkin "github.com/openzipkin/zipkin-go"
	httpreporter "github.com/openzipkin/zipkin-go/reporter/http"
	"go.opencensus.io/trace"
	"go.uber.org/zap"

	"knative.dev/pkg/tracing/config"
)

// ConfigOption is the interface for adding additional exporters and configuring opencensus tracing.
type ConfigOption func(*config.Config)

// OpenCensusTracer is responsible for managing and updating configuration of OpenCensus tracing
type OpenCensusTracer struct {
	curCfg        *config.Config
	configOptions []ConfigOption

	closer   io.Closer
	exporter trace.Exporter
}

// OpenCensus tracing keeps state in globals and therefore we can only run one OpenCensusTracer
var (
	octMutex  sync.Mutex
	globalOct *OpenCensusTracer
)

func NewOpenCensusTracer(configOptions ...ConfigOption) *OpenCensusTracer {
	return &OpenCensusTracer{
		configOptions: configOptions,
	}
}

func (oct *OpenCensusTracer) ApplyConfig(cfg *config.Config) error {
	err := oct.acquireGlobal()
	defer octMutex.Unlock()
	if err != nil {
		return err
	}

	// Short circuit if our config hasnt changed
	if oct.curCfg != nil && oct.curCfg.Equals(cfg) {
		return nil
	}

	// Apply config options
	for _, configOpt := range oct.configOptions {
		configOpt(cfg)
	}

	// Set config
	trace.ApplyConfig(*createOCTConfig(cfg))

	return nil
}

func (oct *OpenCensusTracer) Finish() error {
	err := oct.acquireGlobal()
	defer octMutex.Unlock()
	if err != nil {
		return errors.New("finish called on OpenTracer which is not the global OpenCensusTracer")
	}

	for _, configOpt := range oct.configOptions {
		configOpt(nil)
	}
	globalOct = nil

	return nil
}

func (oct *OpenCensusTracer) acquireGlobal() error {
	octMutex.Lock()

	if globalOct == nil {
		globalOct = oct
	} else if globalOct != oct {
		return errors.New("an OpenCensusTracer already exists and only one can be run at a time")
	}

	return nil
}

func createOCTConfig(cfg *config.Config) *trace.Config {
	octCfg := trace.Config{}

	if cfg.Backend != config.None {
		if cfg.Debug {
			octCfg.DefaultSampler = trace.AlwaysSample()
		} else {
			octCfg.DefaultSampler = trace.ProbabilitySampler(cfg.SampleRate)
		}
	} else {
		octCfg.DefaultSampler = trace.NeverSample()
	}

	return &octCfg
}

// WithExporter returns a ConfigOption for use with NewOpenCensusTracer that configures
// it to export traces based on the configuration read from config-tracing.
func WithExporter(name string, logger *zap.SugaredLogger) ConfigOption {
	return func(cfg *config.Config) {
		var (
			exporter trace.Exporter
			closer   io.Closer
		)
		switch cfg.Backend {
		case config.Stackdriver:
			exp, err := stackdriver.NewExporter(stackdriver.Options{
				ProjectID: cfg.StackdriverProjectID,
			})
			if err != nil {
				logger.Errorw("error reading project-id from metadata", zap.Error(err))
				return
			}
			exporter = exp
		case config.Zipkin:
			zipEP, err := zipkin.NewEndpoint(name, ":80")
			if err != nil {
				logger.Errorw("error building zipkin endpoint", zap.Error(err))
				return
			}
			reporter := httpreporter.NewReporter(cfg.ZipkinEndpoint)
			exporter = oczipkin.NewExporter(reporter, zipEP)
			closer = reporter
		default:
			// Disables tracing.
		}
		if exporter != nil {
			trace.RegisterExporter(exporter)
		}
		// We know this is set because we are called with acquireGlobal lock held
		if globalOct.exporter != nil {
			trace.UnregisterExporter(globalOct.exporter)
		}
		if globalOct.closer != nil {
			globalOct.closer.Close()
		}

		globalOct.exporter = exporter
		globalOct.closer = closer
	}
}
<commit_msg>update with hostport (#614)<commit_after>package tracing

import (
	"errors"
	"io"
	"sync"

	"contrib.go.opencensus.io/exporter/stackdriver"
	oczipkin "contrib.go.opencensus.io/exporter/zipkin"
	zipkin "github.com/openzipkin/zipkin-go"
	httpreporter "github.com/openzipkin/zipkin-go/reporter/http"
	"go.opencensus.io/trace"
	"go.uber.org/zap"

	"knative.dev/pkg/tracing/config"
)

// ConfigOption is the interface for adding additional exporters and configuring opencensus tracing.
type ConfigOption func(*config.Config)

// OpenCensusTracer is responsible for managing and updating configuration of OpenCensus tracing
type OpenCensusTracer struct {
	curCfg        *config.Config
	configOptions []ConfigOption

	closer   io.Closer
	exporter trace.Exporter
}

// OpenCensus tracing keeps state in globals and therefore we can only run one OpenCensusTracer
var (
	octMutex  sync.Mutex
	globalOct *OpenCensusTracer
)

func NewOpenCensusTracer(configOptions ...ConfigOption) *OpenCensusTracer {
	return &OpenCensusTracer{
		configOptions: configOptions,
	}
}

func (oct *OpenCensusTracer) ApplyConfig(cfg *config.Config) error {
	err := oct.acquireGlobal()
	defer octMutex.Unlock()
	if err != nil {
		return err
	}

	// Short circuit if our config hasnt changed
	if oct.curCfg != nil && oct.curCfg.Equals(cfg) {
		return nil
	}

	// Apply config options
	for _, configOpt := range oct.configOptions {
		configOpt(cfg)
	}

	// Set config
	trace.ApplyConfig(*createOCTConfig(cfg))

	return nil
}

func (oct *OpenCensusTracer) Finish() error {
	err := oct.acquireGlobal()
	defer octMutex.Unlock()
	if err != nil {
		return errors.New("finish called on OpenTracer which is not the global OpenCensusTracer")
	}

	for _, configOpt := range oct.configOptions {
		configOpt(nil)
	}
	globalOct = nil

	return nil
}

func (oct *OpenCensusTracer) acquireGlobal() error {
	octMutex.Lock()

	if globalOct == nil {
		globalOct = oct
	} else if globalOct != oct {
		return errors.New("an OpenCensusTracer already exists and only one can be run at a time")
	}

	return nil
}

func createOCTConfig(cfg *config.Config) *trace.Config {
	octCfg := trace.Config{}

	if cfg.Backend != config.None {
		if cfg.Debug {
			octCfg.DefaultSampler = trace.AlwaysSample()
		} else {
			octCfg.DefaultSampler = trace.ProbabilitySampler(cfg.SampleRate)
		}
	} else {
		octCfg.DefaultSampler = trace.NeverSample()
	}

	return &octCfg
}

// WithExporter returns a ConfigOption for use with NewOpenCensusTracer that configures
// it to export traces based on the configuration read from config-tracing.
func WithExporter(name string, logger *zap.SugaredLogger) ConfigOption {
	return func(cfg *config.Config) {
		var (
			exporter trace.Exporter
			closer   io.Closer
		)
		switch cfg.Backend {
		case config.Stackdriver:
			exp, err := stackdriver.NewExporter(stackdriver.Options{
				ProjectID: cfg.StackdriverProjectID,
			})
			if err != nil {
				logger.Errorw("error reading project-id from metadata", zap.Error(err))
				return
			}
			exporter = exp
		case config.Zipkin:
			hostPort := name + ":80"
			zipEP, err := zipkin.NewEndpoint(name, hostPort)
			if err != nil {
				logger.Errorw("error building zipkin endpoint", zap.Error(err))
				return
			}
			reporter := httpreporter.NewReporter(cfg.ZipkinEndpoint)
			exporter = oczipkin.NewExporter(reporter, zipEP)
			closer = reporter
		default:
			// Disables tracing.
		}
		if exporter != nil {
			trace.RegisterExporter(exporter)
		}
		// We know this is set because we are called with acquireGlobal lock held
		if globalOct.exporter != nil {
			trace.UnregisterExporter(globalOct.exporter)
		}
		if globalOct.closer != nil {
			globalOct.closer.Close()
		}

		globalOct.exporter = exporter
		globalOct.closer = closer
	}
}
<|endoftext|>


<commit_before>package integration_test

import (
	"path/filepath"

	"github.com/cloudfoundry/libbuildpack/cutlass"

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

var _ = Describe("override yml", func() {
	var app *cutlass.App
	var buildpackName string
	AfterEach(func() {
		if buildpackName != "" {
			cutlass.DeleteBuildpack(buildpackName)
		}

		if app != nil {
			app.Destroy()
		}
		app = nil
	})

	BeforeEach(func() {
		if !ApiHasMultiBuildpack() {
			Skip("Multi buildpack support is required")
		}

		buildpackName = "override_yml_" + cutlass.RandStringRunes(5)
		Expect(cutlass.CreateOrUpdateBuildpack(buildpackName, filepath.Join(bpDir, "fixtures", "overrideyml_bp"))).To(Succeed())

		app = cutlass.New(filepath.Join(bpDir, "fixtures", "simple_app"))
		app.Buildpacks = []string{buildpackName + "_buildpack", "nodejs_buildpack"}
	})

	It("Forces node from override buildpack", func() {
		Expect(app.Push()).ToNot(Succeed())
		Eventually(func() error { return app.ConfirmBuildpack(buildpackVersion) }).Should(Succeed())
		Eventually(app.Stdout.String).Should(ContainSubstring("-----> OverrideYML Buildpack"))

		Eventually(app.Stdout.String).Should(ContainSubstring("-----> Installing node"))
		Eventually(app.Stdout.String).Should(MatchRegexp("Copy .*/node.tgz"))
		Eventually(app.Stdout.String).Should(ContainSubstring("Unable to install node: dependency sha256 mismatch: expected sha256 062d906c87839d03b243e2821e10653c89b4c92878bfe2bf995dec231e117bfc, actual sha256 b56b58ac21f9f42d032e1e4b8bf8b8823e69af5411caa15aee2b140bc756962f"))
	})
})
<commit_msg>Increase timeout in order to actually get the output.<commit_after>package integration_test

import (
	"path/filepath"

	"github.com/cloudfoundry/libbuildpack/cutlass"

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

var _ = Describe("override yml", func() {
	var app *cutlass.App
	var buildpackName string
	AfterEach(func() {
		if buildpackName != "" {
			cutlass.DeleteBuildpack(buildpackName)
		}

		if app != nil {
			app.Destroy()
		}
		app = nil
	})

	BeforeEach(func() {
		if !ApiHasMultiBuildpack() {
			Skip("Multi buildpack support is required")
		}

		buildpackName = "override_yml_" + cutlass.RandStringRunes(5)
		Expect(cutlass.CreateOrUpdateBuildpack(buildpackName, filepath.Join(bpDir, "fixtures", "overrideyml_bp"))).To(Succeed())

		app = cutlass.New(filepath.Join(bpDir, "fixtures", "simple_app"))
		app.Buildpacks = []string{buildpackName + "_buildpack", "nodejs_buildpack"}
	})

	It("Forces node from override buildpack", func() {
		Expect(app.Push()).ToNot(Succeed())
		Eventually(func() error { return app.ConfirmBuildpack(buildpackVersion) }, "30s").Should(Succeed())
		Eventually(app.Stdout.String).Should(ContainSubstring("-----> OverrideYML Buildpack"))

		Eventually(app.Stdout.String).Should(ContainSubstring("-----> Installing node"))
		Eventually(app.Stdout.String).Should(MatchRegexp("Copy .*/node.tgz"))
		Eventually(app.Stdout.String).Should(ContainSubstring("Unable to install node: dependency sha256 mismatch: expected sha256 062d906c87839d03b243e2821e10653c89b4c92878bfe2bf995dec231e117bfc, actual sha256 b56b58ac21f9f42d032e1e4b8bf8b8823e69af5411caa15aee2b140bc756962f"))
	})
})
<|endoftext|>


<commit_before>package transfer

import (
	"errors"
	"fmt"
	"net"
	"sync"
	"time"

	log "github.com/Sirupsen/logrus"
	"github.com/disorganizer/brig/id"
	"github.com/disorganizer/brig/repo"
	"github.com/disorganizer/brig/transfer/wire"
	"github.com/disorganizer/brig/util"
	"github.com/disorganizer/brig/util/ipfsutil"
)

var (
	ErrListenerWasClosed = errors.New("Listener was closed")
)

type Connector struct {
	layer Layer

	// Open repo. required for answering requests.
	// (might be nil for tests if no handlers are tested)
	rp *repo.Repository

	// Conversation pool handling.
	cp *ConversationPool
}

type ConversationPool struct {
	// Map of open conversations
	open map[id.ID]Conversation

	// Map from hash id to last seen timestamp
	heartbeat map[id.ID]*ipfsutil.Pinger

	// lock for `open`
	mu sync.Mutex

	rp *repo.Repository
}

func newConversationPool(rp *repo.Repository) *ConversationPool {
	return &ConversationPool{
		open:      make(map[id.ID]Conversation),
		heartbeat: make(map[id.ID]*ipfsutil.Pinger),
		rp:        rp,
	}
}

// Set add a conversation for a specific to the pool.
func (cp *ConversationPool) Set(peer id.Peer, cnv Conversation) error {
	cp.mu.Lock()
	defer cp.mu.Unlock()

	cp.open[peer.ID()] = cnv

	if _, ok := cp.heartbeat[peer.ID()]; !ok {
		pinger, err := cp.rp.IPFS.Ping(peer.Hash())
		if err != nil {
			return err
		}
		cp.heartbeat[peer.ID()] = pinger
	}

	return nil
}

// Iter iterates over the conversation pool.
func (cp *ConversationPool) Iter() chan Conversation {
	cnvs := make(chan Conversation)
	go func() {
		cp.mu.Lock()
		defer cp.mu.Unlock()

		for _, cnv := range cp.open {
			cnvs <- cnv
		}
		close(cnvs)
	}()
	return cnvs
}

// LastSeen timestamp of a specific peer.
func (cp *ConversationPool) LastSeen(peer id.Peer) time.Time {
	cp.mu.Lock()
	defer cp.mu.Unlock()

	if pinger := cp.heartbeat[peer.ID()]; pinger != nil {
		return pinger.LastSeen()
	}

	return time.Unix(0, 0)
}

// Close the complete conversation pool and free ressources.
func (cp *ConversationPool) Close() error {
	var errs util.Errors

	cp.mu.Lock()
	defer cp.mu.Unlock()

	for _, cnv := range cp.open {
		if err := cnv.Close(); err != nil {
			errs = append(errs, err)
		}
	}

	cp.open = make(map[id.ID]Conversation)
	cp.heartbeat = make(map[id.ID]*ipfsutil.Pinger)
	return errs.ToErr()
}

// dialer uses ipfs to create a net.Conn to another node.
type dialer struct {
	layer Layer
	node  *ipfsutil.Node
}

func (d *dialer) Dial(peer id.Peer) (net.Conn, error) {
	log.Debugf("IPFS dialing to %v", peer.Hash())
	return d.node.Dial(peer.Hash(), d.layer.ProtocolID())
}

type listenerFilter struct {
	ls   net.Listener
	rms  repo.RemoteStore
	quit chan bool
}

func newListenerFilter(ls net.Listener, rms repo.RemoteStore) *listenerFilter {
	return &listenerFilter{
		ls:   ls,
		rms:  rms,
		quit: make(chan bool, 1),
	}
}

func (lf *listenerFilter) Accept() (net.Conn, error) {
	for {
		conn, err := lf.ls.Accept()
		if err != nil {
			return nil, err
		}

		select {
		case <-lf.quit:
			return nil, ErrListenerWasClosed
		default:
			break
		}

		streamConn, ok := conn.(*ipfsutil.StreamConn)
		if !ok {
			return nil, fmt.Errorf("Not used with ipfs listener?")
		}

		hash := streamConn.PeerHash()

		// Check if we know of this hash:
		for remote := range lf.rms.Iter() {
			if remote.Hash() == hash {
				return streamConn, nil
			}
		}

		log.Warningf("Denying incoming connection from `%s`", hash)
	}

	return nil, ErrListenerWasClosed
}

func (lf *listenerFilter) Close() error {
	// quit is buffered, this will return immediately.
	// The Accept() loop might have errored out before,
	// so we don't want this to block if it won't be read.
	lf.quit <- true
	return lf.ls.Close()
}

func (lf *listenerFilter) Addr() net.Addr {
	return lf.Addr()
}

// NewConnector returns an unconnected Connector.
func NewConnector(layer Layer, rp *repo.Repository) *Connector {
	// TODO: pass authMgr.
	// authMgr := MockAuthSuccess
	cnc := &Connector{
		rp:    rp,
		layer: layer,
		cp:    newConversationPool(rp),
	}

	handlerMap := map[wire.RequestType]HandlerFunc{
		wire.RequestType_FETCH:         cnc.handleFetch,
		wire.RequestType_UPDATE_FILE:   cnc.handleUpdateFile,
		wire.RequestType_STORE_VERSION: cnc.handleStoreVersion,
	}

	for typ, handler := range handlerMap {
		layer.RegisterHandler(typ, handler)
	}

	return cnc
}

func (cn *Connector) Dial(peer id.Peer) (*APIClient, error) {
	if !cn.IsInOnlineMode() {
		return nil, ErrOffline
	}

	// TODO: use the remote here somehow :)
	_, err := cn.rp.Remotes.Get(peer.ID())
	if err != nil {
		return nil, err
	}

	cnv, err := cn.layer.Dial(peer)
	if err != nil {
		return nil, err
	}

	if err := cn.cp.Set(peer, cnv); err != nil {
		return nil, err
	}

	return newAPIClient(cnv, cn.rp.IPFS)
}

func (c *Connector) Repo() *repo.Repository {
	return c.rp
}

func (cn *Connector) IsOnline(peer id.Peer) bool {
	if !cn.IsInOnlineMode() {
		return false
	}

	if time.Since(cn.cp.LastSeen(peer)) < 15*time.Second {
		return true
	}

	return false
}

func (cn *Connector) Broadcast(req *wire.Request) error {
	var errs util.Errors

	for cnv := range cn.cp.Iter() {
		if err := cnv.SendAsync(req, nil); err != nil {
			errs = append(errs, err)
		}
	}

	return errs
}

func (cn *Connector) Layer() Layer {
	return cn.layer
}

func (cn *Connector) Connect() error {
	ls, err := cn.rp.IPFS.Listen(cn.layer.ProtocolID())
	if err != nil {
		return err
	}

	// Make sure we filter unauthorized incoming connections:
	filter := newListenerFilter(ls, cn.rp.Remotes)

	if err := cn.layer.Connect(filter, &dialer{cn.layer, cn.rp.IPFS}); err != nil {
		return err
	}

	go func() {
		for remote := range cn.rp.Remotes.Iter() {
			cnv, err := cn.layer.Dial(remote)
			if err != nil {
				log.Warningf("Could not connect to `%s`: %v", remote.ID(), err)
				continue
			}

			if err := cn.cp.Set(remote, cnv); err != nil {
				log.Warningf("Cannot create pinger: %v", err)
			}
		}
	}()

	return nil
}

func (cn *Connector) Disconnect() error {
	errs := util.Errors{}
	if err := cn.cp.Close(); err != nil {
		errs = append(errs, err)
	}

	if err := cn.layer.Disconnect(); err != nil {
		errs = append(errs, err)
	}

	return errs.ToErr()
}

func (cn *Connector) Close() error {
	return cn.Disconnect()
}

func (cn *Connector) IsInOnlineMode() bool {
	return cn.layer.IsInOnlineMode()
}
<commit_msg>transfer/connector.go: Bugfix cumulative error return in broadcast<commit_after>package transfer

import (
	"errors"
	"fmt"
	"net"
	"sync"
	"time"

	log "github.com/Sirupsen/logrus"
	"github.com/disorganizer/brig/id"
	"github.com/disorganizer/brig/repo"
	"github.com/disorganizer/brig/transfer/wire"
	"github.com/disorganizer/brig/util"
	"github.com/disorganizer/brig/util/ipfsutil"
)

var (
	ErrListenerWasClosed = errors.New("Listener was closed")
)

type Connector struct {
	layer Layer

	// Open repo. required for answering requests.
	// (might be nil for tests if no handlers are tested)
	rp *repo.Repository

	// Conversation pool handling.
	cp *ConversationPool
}

type ConversationPool struct {
	// Map of open conversations
	open map[id.ID]Conversation

	// Map from hash id to last seen timestamp
	heartbeat map[id.ID]*ipfsutil.Pinger

	// lock for `open`
	mu sync.Mutex

	rp *repo.Repository
}

func newConversationPool(rp *repo.Repository) *ConversationPool {
	return &ConversationPool{
		open:      make(map[id.ID]Conversation),
		heartbeat: make(map[id.ID]*ipfsutil.Pinger),
		rp:        rp,
	}
}

// Set add a conversation for a specific to the pool.
func (cp *ConversationPool) Set(peer id.Peer, cnv Conversation) error {
	cp.mu.Lock()
	defer cp.mu.Unlock()

	cp.open[peer.ID()] = cnv

	if _, ok := cp.heartbeat[peer.ID()]; !ok {
		pinger, err := cp.rp.IPFS.Ping(peer.Hash())
		if err != nil {
			return err
		}
		cp.heartbeat[peer.ID()] = pinger
	}

	return nil
}

// Iter iterates over the conversation pool.
func (cp *ConversationPool) Iter() chan Conversation {
	cnvs := make(chan Conversation)
	go func() {
		cp.mu.Lock()
		defer cp.mu.Unlock()

		for _, cnv := range cp.open {
			cnvs <- cnv
		}
		close(cnvs)
	}()
	return cnvs
}

// LastSeen timestamp of a specific peer.
func (cp *ConversationPool) LastSeen(peer id.Peer) time.Time {
	cp.mu.Lock()
	defer cp.mu.Unlock()

	if pinger := cp.heartbeat[peer.ID()]; pinger != nil {
		return pinger.LastSeen()
	}

	return time.Unix(0, 0)
}

// Close the complete conversation pool and free ressources.
func (cp *ConversationPool) Close() error {
	var errs util.Errors

	cp.mu.Lock()
	defer cp.mu.Unlock()

	for _, cnv := range cp.open {
		if err := cnv.Close(); err != nil {
			errs = append(errs, err)
		}
	}

	cp.open = make(map[id.ID]Conversation)
	cp.heartbeat = make(map[id.ID]*ipfsutil.Pinger)
	return errs.ToErr()
}

// dialer uses ipfs to create a net.Conn to another node.
type dialer struct {
	layer Layer
	node  *ipfsutil.Node
}

func (d *dialer) Dial(peer id.Peer) (net.Conn, error) {
	log.Debugf("IPFS dialing to %v", peer.Hash())
	return d.node.Dial(peer.Hash(), d.layer.ProtocolID())
}

type listenerFilter struct {
	ls   net.Listener
	rms  repo.RemoteStore
	quit chan bool
}

func newListenerFilter(ls net.Listener, rms repo.RemoteStore) *listenerFilter {
	return &listenerFilter{
		ls:   ls,
		rms:  rms,
		quit: make(chan bool, 1),
	}
}

func (lf *listenerFilter) Accept() (net.Conn, error) {
	for {
		conn, err := lf.ls.Accept()
		if err != nil {
			return nil, err
		}

		select {
		case <-lf.quit:
			return nil, ErrListenerWasClosed
		default:
			break
		}

		streamConn, ok := conn.(*ipfsutil.StreamConn)
		if !ok {
			return nil, fmt.Errorf("Not used with ipfs listener?")
		}

		hash := streamConn.PeerHash()

		// Check if we know of this hash:
		for remote := range lf.rms.Iter() {
			if remote.Hash() == hash {
				return streamConn, nil
			}
		}

		log.Warningf("Denying incoming connection from `%s`", hash)
	}

	return nil, ErrListenerWasClosed
}

func (lf *listenerFilter) Close() error {
	// quit is buffered, this will return immediately.
	// The Accept() loop might have errored out before,
	// so we don't want this to block if it won't be read.
	lf.quit <- true
	return lf.ls.Close()
}

func (lf *listenerFilter) Addr() net.Addr {
	return lf.Addr()
}

// NewConnector returns an unconnected Connector.
func NewConnector(layer Layer, rp *repo.Repository) *Connector {
	// TODO: pass authMgr.
	// authMgr := MockAuthSuccess
	cnc := &Connector{
		rp:    rp,
		layer: layer,
		cp:    newConversationPool(rp),
	}

	handlerMap := map[wire.RequestType]HandlerFunc{
		wire.RequestType_FETCH:         cnc.handleFetch,
		wire.RequestType_UPDATE_FILE:   cnc.handleUpdateFile,
		wire.RequestType_STORE_VERSION: cnc.handleStoreVersion,
	}

	for typ, handler := range handlerMap {
		layer.RegisterHandler(typ, handler)
	}

	return cnc
}

func (cn *Connector) Dial(peer id.Peer) (*APIClient, error) {
	if !cn.IsInOnlineMode() {
		return nil, ErrOffline
	}

	// TODO: use the remote here somehow :)
	_, err := cn.rp.Remotes.Get(peer.ID())
	if err != nil {
		return nil, err
	}

	cnv, err := cn.layer.Dial(peer)
	if err != nil {
		return nil, err
	}

	if err := cn.cp.Set(peer, cnv); err != nil {
		return nil, err
	}

	return newAPIClient(cnv, cn.rp.IPFS)
}

func (c *Connector) Repo() *repo.Repository {
	return c.rp
}

func (cn *Connector) IsOnline(peer id.Peer) bool {
	if !cn.IsInOnlineMode() {
		return false
	}

	if time.Since(cn.cp.LastSeen(peer)) < 15*time.Second {
		return true
	}

	return false
}

func (cn *Connector) Broadcast(req *wire.Request) error {
	var errs util.Errors

	for cnv := range cn.cp.Iter() {
		if err := cnv.SendAsync(req, nil); err != nil {
			errs = append(errs, err)
		}
	}

	return errs.ToErr()
}

func (cn *Connector) Layer() Layer {
	return cn.layer
}

func (cn *Connector) Connect() error {
	ls, err := cn.rp.IPFS.Listen(cn.layer.ProtocolID())
	if err != nil {
		return err
	}

	// Make sure we filter unauthorized incoming connections:
	filter := newListenerFilter(ls, cn.rp.Remotes)

	if err := cn.layer.Connect(filter, &dialer{cn.layer, cn.rp.IPFS}); err != nil {
		return err
	}

	go func() {
		for remote := range cn.rp.Remotes.Iter() {
			cnv, err := cn.layer.Dial(remote)
			if err != nil {
				log.Warningf("Could not connect to `%s`: %v", remote.ID(), err)
				continue
			}

			if err := cn.cp.Set(remote, cnv); err != nil {
				log.Warningf("Cannot create pinger: %v", err)
			}
		}
	}()

	return nil
}

func (cn *Connector) Disconnect() error {
	errs := util.Errors{}
	if err := cn.cp.Close(); err != nil {
		errs = append(errs, err)
	}

	if err := cn.layer.Disconnect(); err != nil {
		errs = append(errs, err)
	}

	return errs.ToErr()
}

func (cn *Connector) Close() error {
	return cn.Disconnect()
}

func (cn *Connector) IsInOnlineMode() bool {
	return cn.layer.IsInOnlineMode()
}
<|endoftext|>


<commit_before>package yang

type stringSet map[string]struct{}

func newStringSet() stringSet {
	return map[string]struct{}{}
}

func newStringSetWith(ss []string) stringSet {
	set := newStringSet()
	for _, s := range ss {
		set[s] = struct{}{}
	}
	return set
}

func (s stringSet) contains(element string) bool {
	_, ok := s[element]
	return ok
}

func (s stringSet) add(element string) {
	s[element] = struct{}{}
}

func (s stringSet) remove(element string) {
	delete(s, element)
}
<commit_msg>Add comment<commit_after>package yang

// Set for strings
type stringSet map[string]struct{}

func newStringSet() stringSet {
	return map[string]struct{}{}
}

func newStringSetWith(ss []string) stringSet {
	set := newStringSet()
	for _, s := range ss {
		set[s] = struct{}{}
	}
	return set
}

func (s stringSet) contains(element string) bool {
	_, ok := s[element]
	return ok
}

func (s stringSet) add(element string) {
	s[element] = struct{}{}
}

func (s stringSet) remove(element string) {
	delete(s, element)
}
<|endoftext|>


<commit_before>package transports

import (
	"fmt"
	"encoding/json"
	"net/http"
	"io/ioutil"
	"os/exec"
	"time"
	"strings"
	"bytes"
	// "errors"
)

const YowsupHttpWrapperPath = "../yowsup-http-wrapper/run.py"
const YowsupHttpWrapperUrl = "http://127.0.0.1:8888/"

type WhatsappTransport struct {
	*Transport
	Login         string
	Password      string
	Contact				string
	Serializer		DefaultSerializer
	Messages			[]WhatsappMessage
}

type WhatsappMessage struct {
	Id string	`json:"id,omitempty"`
	Body string `json:"msg,omitempty"`
	Origin string	`json:"origin,omitempty"`
	Dest string `json:"dest,omitempty"`
}

type WhatsappMessageCallback func(*WhatsappTransport)

func (t *WhatsappTransport) DaemonizeWrapper() {
	fmt.Println( "WhatsappTransport, daemonizing YowsupWrapper...")
	cmd := exec.Command( "python3", YowsupHttpWrapperPath, t.Login, t.Password )
	err := cmd.Run()

	if err != nil {
		panic(err)
	}
}

func( t *WhatsappTransport) GetMessageIds() []string {
	MessageIds := make( []string, 0 )
	for _, Message := range t.Messages {
		MessageIds = append( MessageIds, Message.Id )
	}
	return MessageIds
}

func( t *WhatsappTransport) PurgeMessage( Id string ) {
	messagesUrl := fmt.Sprintf("%s%s?id=%s", YowsupHttpWrapperUrl, "messages", Id)
	deleteRequest, _ := http.NewRequest( "DELETE", messagesUrl, nil)
	http.DefaultClient.Do(deleteRequest)
}

func( t *WhatsappTransport) FetchMessages() {
	messagesUrl := strings.Join([]string{YowsupHttpWrapperUrl, "messages"}, "")
	resp, err := http.Get(messagesUrl)

	// fmt.Println( "Request:",resp, "Error:",err)

	if err != nil {
		// fmt.Println( "Wrapper error:", err)
		return
	}

	defer resp.Body.Close()

	rawBody, _ := ioutil.ReadAll( resp.Body )

	var messageList map[string]interface{}

	jsonErr := json.Unmarshal( rawBody, &messageList)

	if jsonErr != nil {
		return
	}

	MessageIds := t.GetMessageIds()

	for Id, Values := range messageList {
		ValuesMap := Values.(map[string]interface{})
		Message := WhatsappMessage{ Id: Id, Body: ValuesMap["body"].(string), Origin: ValuesMap["origin"].(string) }
		Exists := false

		for _, ExistingId := range MessageIds {
			if ExistingId == Id {
				Exists = true
				return
			}
		}

		if !Exists {
			t.Messages = append( t.Messages, Message )
		}
	}

	return
}

func (t *WhatsappTransport) SendMessage(body string) {
	messagesUrl := strings.Join([]string{YowsupHttpWrapperUrl, "messages"}, "")
	message := WhatsappMessage{Body: body, Dest: t.Contact}
	jsonBuffer, _ := json.Marshal(&message)
	resp, err := http.Post(messagesUrl, "application/json", bytes.NewReader(jsonBuffer) )
	return
}

func (t *WhatsappTransport) DoLogin() bool {
	fmt.Println("FacebookTransport, Login()")
	return true
}

func (t *WhatsappTransport) Prepare() {
	fmt.Println("WhatsappTransport, Prepare()")

	t.Serializer = DefaultSerializer{}

	t.Messages = make([]WhatsappMessage, 0)

	go t.DaemonizeWrapper()

	go t.Listen(nil)

	/*
	if !t.DoLogin() {
		err := errors.New( "Authentication error!")
		panic(err)
	}
	*/

	return
}

func (t *WhatsappTransport) Handler(w http.ResponseWriter, originalRequest *http.Request) {

	client := &http.Client{}

	request, _ := http.NewRequest(originalRequest.Method, originalRequest.URL.String(), nil)

	serializedRequest := t.Serializer.Serialize(originalRequest)

	t.SendMessage(string(serializedRequest))

	resp, _ := client.Do(request)
	b, _ := ioutil.ReadAll(resp.Body)
	resp.Body.Close()

	w.Write(b)

	return
}

func (t *WhatsappTransport) Listen( Callback WhatsappMessageCallback ) {
	fmt.Println( "FacebookTransport, Listen()")
	fmt.Println("Polling...")
	for {
		fmt.Println( "Poll, messages:", t.Messages )
		t.FetchMessages()
		if Callback == nil {
		} else {
			Callback( t )
		}
		t.FetchMessages()
		time.Sleep(1 * time.Second)
	}
	return
}
<commit_msg>WrapperUrl update<commit_after>package transports

import (
	"fmt"
	"encoding/json"
	"net/http"
	"io/ioutil"
	"os/exec"
	"time"
	"strings"
	"bytes"
	// "errors"
)

const YowsupHttpWrapperPath = "../yowsup-http-wrapper/run.py"

type WhatsappTransport struct {
	*Transport
	Login         string
	Password      string
	Contact				string
	YowsupWrapperPort	string
	YowsupWrapperUrl string
	Serializer		DefaultSerializer
	Messages			[]WhatsappMessage
}

type WhatsappMessage struct {
	Id string	`json:"id,omitempty"`
	Body string `json:"msg,omitempty"`
	Origin string	`json:"origin,omitempty"`
	Dest string `json:"dest,omitempty"`
}

type WhatsappMessageCallback func(*WhatsappTransport)

func (t *WhatsappTransport) DaemonizeWrapper() {
	fmt.Println( "WhatsappTransport, daemonizing YowsupWrapper...")

	t.YowsupWrapperUrl = fmt.Sprintf("http://127.0.0.1:%s/", t.YowsupWrapperPort)

	cmd := exec.Command( "python3", YowsupHttpWrapperPath, t.Login, t.Password, t.YowsupWrapperPort )
	err := cmd.Run()

	fmt.Println(cmd,err)

	if err != nil {
		panic(err)
	}
}

func( t *WhatsappTransport) GetMessageIds() []string {
	MessageIds := make( []string, 0 )
	for _, Message := range t.Messages {
		MessageIds = append( MessageIds, Message.Id )
	}
	return MessageIds
}

func( t *WhatsappTransport) PurgeMessage( Id string ) {
	messagesUrl := fmt.Sprintf("%s%s?id=%s", t.YowsupWrapperUrl, "messages", Id)
	deleteRequest, _ := http.NewRequest( "DELETE", messagesUrl, nil)
	http.DefaultClient.Do(deleteRequest)
}

func( t *WhatsappTransport) FetchMessages() {
	messagesUrl := strings.Join([]string{t.YowsupWrapperUrl, "messages"}, "")
	resp, err := http.Get(messagesUrl)

	// fmt.Println( "Request:",resp, "Error:",err)

	if err != nil {
		fmt.Println( "Wrapper error:", err)
		return
	}

	defer resp.Body.Close()

	rawBody, _ := ioutil.ReadAll( resp.Body )

	var messageList map[string]interface{}

	jsonErr := json.Unmarshal( rawBody, &messageList)

	if jsonErr != nil {
		return
	}

	MessageIds := t.GetMessageIds()

	for Id, Values := range messageList {
		ValuesMap := Values.(map[string]interface{})
		Message := WhatsappMessage{ Id: Id, Body: ValuesMap["body"].(string), Origin: ValuesMap["origin"].(string) }
		Exists := false

		for _, ExistingId := range MessageIds {
			if ExistingId == Id {
				Exists = true
				return
			}
		}

		if !Exists {
			t.Messages = append( t.Messages, Message )
		}
	}

	return
}

func (t *WhatsappTransport) SendMessage(body string) {
	messagesUrl := strings.Join([]string{t.YowsupWrapperUrl, "messages"}, "")
	message := WhatsappMessage{Body: body, Dest: t.Contact}
	fmt.Println("Sending message", message)
	jsonBuffer, _ := json.Marshal(&message)
	http.Post(messagesUrl, "application/json", bytes.NewReader(jsonBuffer) )
	return
}

func (t *WhatsappTransport) DoLogin() bool {
	fmt.Println("FacebookTransport, Login()")
	return true
}

func (t *WhatsappTransport) Prepare() {
	fmt.Println("WhatsappTransport, Prepare()")

	t.Serializer = DefaultSerializer{}

	t.Messages = make([]WhatsappMessage, 0)

	// go t.DaemonizeWrapper()

	// go t.Listen(nil)

	/*
	if !t.DoLogin() {
		err := errors.New( "Authentication error!")
		panic(err)
	}
	*/

	return
}

func (t *WhatsappTransport) Handler(w http.ResponseWriter, originalRequest *http.Request) {

	client := &http.Client{}

	request, _ := http.NewRequest(originalRequest.Method, originalRequest.URL.String(), nil)

	serializedRequest := t.Serializer.Serialize(originalRequest)

	t.SendMessage(string(serializedRequest))

	resp, _ := client.Do(request)
	b, _ := ioutil.ReadAll(resp.Body)
	resp.Body.Close()

	w.Write(b)

	return
}

func (t *WhatsappTransport) Listen( Callback WhatsappMessageCallback ) {

	fmt.Println( "FacebookTransport, Listen()")
	fmt.Println("Polling...")

	t.Prepare()

	go t.DaemonizeWrapper()

	for {
		fmt.Println( "Poll, messages:", t.Messages )
		t.FetchMessages()
		if Callback == nil {
		} else {
			Callback( t )
		}
		t.FetchMessages()
		time.Sleep(1 * time.Second)
	}
	return
}
<|endoftext|>


<commit_before>/*
Copyright 2015 The Kubernetes Authors All rights reserved.

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

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

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

package e2e

import (
	"time"

	client "k8s.io/kubernetes/pkg/client/unversioned"
	"k8s.io/kubernetes/pkg/fields"
	"k8s.io/kubernetes/pkg/labels"

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

const datapointAmount = 5

var systemContainers = []string{"/docker-daemon", "/kubelet", "/kube-proxy", "/system"}

//TODO tweak those values.
var allowedUsage = resourceUsagePerContainer{
	"/docker-daemon": &containerResourceUsage{
		CPUUsageInCores:         0.08,
		MemoryUsageInBytes:      4500000000,
		MemoryWorkingSetInBytes: 1500000000,
	},
	"/kubelet": &containerResourceUsage{
		CPUUsageInCores:         0.1,
		MemoryUsageInBytes:      150000000,
		MemoryWorkingSetInBytes: 150000000,
	},
	"/kube-proxy": &containerResourceUsage{
		CPUUsageInCores:         0.025,
		MemoryUsageInBytes:      100000000,
		MemoryWorkingSetInBytes: 100000000,
	},
	"/system": &containerResourceUsage{
		CPUUsageInCores:         0.03,
		MemoryUsageInBytes:      100000000,
		MemoryWorkingSetInBytes: 100000000,
	},
}

func computeAverage(sliceOfUsages []resourceUsagePerContainer) (result resourceUsagePerContainer) {
	result = make(resourceUsagePerContainer)
	for _, container := range systemContainers {
		result[container] = &containerResourceUsage{}
	}
	for _, usage := range sliceOfUsages {
		for _, container := range systemContainers {
			singleResult := &containerResourceUsage{
				CPUUsageInCores:         result[container].CPUUsageInCores + usage[container].CPUUsageInCores,
				MemoryUsageInBytes:      result[container].MemoryUsageInBytes + usage[container].MemoryUsageInBytes,
				MemoryWorkingSetInBytes: result[container].MemoryWorkingSetInBytes + usage[container].MemoryWorkingSetInBytes,
			}
			result[container] = singleResult
		}
	}
	for _, container := range systemContainers {
		singleResult := &containerResourceUsage{
			CPUUsageInCores:         result[container].CPUUsageInCores / float64(len(sliceOfUsages)),
			MemoryUsageInBytes:      result[container].MemoryUsageInBytes / int64(len(sliceOfUsages)),
			MemoryWorkingSetInBytes: result[container].MemoryWorkingSetInBytes / int64(len(sliceOfUsages)),
		}
		result[container] = singleResult
	}
	return
}

// This tests does nothing except checking current resource usage of containers defined in kubelet_stats systemContainers variable.
// Test fails if an average container resource consumption over datapointAmount tries exceeds amount defined in allowedUsage.
var _ = Describe("Resource usage of system containers", func() {
	var c *client.Client
	BeforeEach(func() {
		var err error
		c, err = loadClient()
		expectNoError(err)
	})

	It("should not exceed expected amount.", func() {
		By("Getting ResourceConsumption on all nodes")
		nodeList, err := c.Nodes().List(labels.Everything(), fields.Everything())
		expectNoError(err)

		resourceUsagePerNode := make(map[string][]resourceUsagePerContainer)

		for i := 0; i < datapointAmount; i++ {
			for _, node := range nodeList.Items {
				resourceUsage, err := getOneTimeResourceUsageOnNode(c, node.Name, 5*time.Second, func() []string {
					if providerIs("gce", "gke") {
						return systemContainers
					} else {
						return []string{}
					}
				}, false)
				expectNoError(err)
				resourceUsagePerNode[node.Name] = append(resourceUsagePerNode[node.Name], resourceUsage)
			}
			time.Sleep(3 * time.Second)
		}

		averageResourceUsagePerNode := make(map[string]resourceUsagePerContainer)
		for _, node := range nodeList.Items {
			averageResourceUsagePerNode[node.Name] = computeAverage(resourceUsagePerNode[node.Name])
		}

		violating := make(map[string]resourceUsagePerContainer)
		for node, usage := range averageResourceUsagePerNode {
			for container, cUsage := range usage {
				Logf("%v on %v usage: %#v", container, node, cUsage)
				if !allowedUsage[container].isStrictlyGreaterThan(cUsage) {
					if _, ok := violating[node]; !ok {
						violating[node] = make(resourceUsagePerContainer)
					}
					if allowedUsage[container].CPUUsageInCores < cUsage.CPUUsageInCores {
						Logf("CPU is too high for %s (%v)", container, cUsage.CPUUsageInCores)
					}
					if allowedUsage[container].MemoryUsageInBytes < cUsage.MemoryUsageInBytes {
						Logf("Memory use is too high for %s (%v)", container, cUsage.MemoryUsageInBytes)
					}
					if allowedUsage[container].MemoryWorkingSetInBytes < cUsage.MemoryWorkingSetInBytes {
						Logf("Working set is too high for %s (%v)", container, cUsage.MemoryWorkingSetInBytes)
					}
					violating[node][container] = usage[container]
				}
			}
		}

		Expect(violating).To(BeEmpty())
	})
})
<commit_msg>don't test kube-proxy in system resource container monitoring since it is running in a docker container now<commit_after>/*
Copyright 2015 The Kubernetes Authors All rights reserved.

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

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

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

package e2e

import (
	"time"

	client "k8s.io/kubernetes/pkg/client/unversioned"
	"k8s.io/kubernetes/pkg/fields"
	"k8s.io/kubernetes/pkg/labels"

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

const datapointAmount = 5

var systemContainers = []string{"/docker-daemon", "/kubelet", "/system"}

//TODO tweak those values.
var allowedUsage = resourceUsagePerContainer{
	"/docker-daemon": &containerResourceUsage{
		CPUUsageInCores:         0.08,
		MemoryUsageInBytes:      4500000000,
		MemoryWorkingSetInBytes: 1500000000,
	},
	"/kubelet": &containerResourceUsage{
		CPUUsageInCores:         0.1,
		MemoryUsageInBytes:      150000000,
		MemoryWorkingSetInBytes: 150000000,
	},
	"/system": &containerResourceUsage{
		CPUUsageInCores:         0.03,
		MemoryUsageInBytes:      100000000,
		MemoryWorkingSetInBytes: 100000000,
	},
}

func computeAverage(sliceOfUsages []resourceUsagePerContainer) (result resourceUsagePerContainer) {
	result = make(resourceUsagePerContainer)
	for _, container := range systemContainers {
		result[container] = &containerResourceUsage{}
	}
	for _, usage := range sliceOfUsages {
		for _, container := range systemContainers {
			singleResult := &containerResourceUsage{
				CPUUsageInCores:         result[container].CPUUsageInCores + usage[container].CPUUsageInCores,
				MemoryUsageInBytes:      result[container].MemoryUsageInBytes + usage[container].MemoryUsageInBytes,
				MemoryWorkingSetInBytes: result[container].MemoryWorkingSetInBytes + usage[container].MemoryWorkingSetInBytes,
			}
			result[container] = singleResult
		}
	}
	for _, container := range systemContainers {
		singleResult := &containerResourceUsage{
			CPUUsageInCores:         result[container].CPUUsageInCores / float64(len(sliceOfUsages)),
			MemoryUsageInBytes:      result[container].MemoryUsageInBytes / int64(len(sliceOfUsages)),
			MemoryWorkingSetInBytes: result[container].MemoryWorkingSetInBytes / int64(len(sliceOfUsages)),
		}
		result[container] = singleResult
	}
	return
}

// This tests does nothing except checking current resource usage of containers defined in kubelet_stats systemContainers variable.
// Test fails if an average container resource consumption over datapointAmount tries exceeds amount defined in allowedUsage.
var _ = Describe("Resource usage of system containers", func() {
	var c *client.Client
	BeforeEach(func() {
		var err error
		c, err = loadClient()
		expectNoError(err)
	})

	It("should not exceed expected amount.", func() {
		By("Getting ResourceConsumption on all nodes")
		nodeList, err := c.Nodes().List(labels.Everything(), fields.Everything())
		expectNoError(err)

		resourceUsagePerNode := make(map[string][]resourceUsagePerContainer)

		for i := 0; i < datapointAmount; i++ {
			for _, node := range nodeList.Items {
				resourceUsage, err := getOneTimeResourceUsageOnNode(c, node.Name, 5*time.Second, func() []string {
					if providerIs("gce", "gke") {
						return systemContainers
					} else {
						return []string{}
					}
				}, false)
				expectNoError(err)
				resourceUsagePerNode[node.Name] = append(resourceUsagePerNode[node.Name], resourceUsage)
			}
			time.Sleep(3 * time.Second)
		}

		averageResourceUsagePerNode := make(map[string]resourceUsagePerContainer)
		for _, node := range nodeList.Items {
			averageResourceUsagePerNode[node.Name] = computeAverage(resourceUsagePerNode[node.Name])
		}

		violating := make(map[string]resourceUsagePerContainer)
		for node, usage := range averageResourceUsagePerNode {
			for container, cUsage := range usage {
				Logf("%v on %v usage: %#v", container, node, cUsage)
				if !allowedUsage[container].isStrictlyGreaterThan(cUsage) {
					if _, ok := violating[node]; !ok {
						violating[node] = make(resourceUsagePerContainer)
					}
					if allowedUsage[container].CPUUsageInCores < cUsage.CPUUsageInCores {
						Logf("CPU is too high for %s (%v)", container, cUsage.CPUUsageInCores)
					}
					if allowedUsage[container].MemoryUsageInBytes < cUsage.MemoryUsageInBytes {
						Logf("Memory use is too high for %s (%v)", container, cUsage.MemoryUsageInBytes)
					}
					if allowedUsage[container].MemoryWorkingSetInBytes < cUsage.MemoryWorkingSetInBytes {
						Logf("Working set is too high for %s (%v)", container, cUsage.MemoryWorkingSetInBytes)
					}
					violating[node][container] = usage[container]
				}
			}
		}

		Expect(violating).To(BeEmpty())
	})
})
<|endoftext|>


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

package zanzibar

import (
	"bytes"
	"context"
	"fmt"
	"strings"
	"sync"

	tchannel "github.com/uber/tchannel-go"
	netContext "golang.org/x/net/context"

	"github.com/pkg/errors"
	"go.uber.org/thriftrw/protocol"
	"go.uber.org/thriftrw/wire"
	"go.uber.org/zap"
)

// PostResponseCB registers a callback that is run after a response has been
// completely processed (e.g. written to the channel).
// This gives the server a chance to clean up resources from the response object
type PostResponseCB func(ctx context.Context, method string, response RWTStruct)

type handler struct {
	tchannelHandler TChannelHandler
	postResponseCB  PostResponseCB
}

// TChannelRouter handles incoming TChannel calls and routes them to the matching TChannelHandler.
type TChannelRouter struct {
	sync.RWMutex
	registrar tchannel.Registrar
	logger    *zap.Logger
	handlers  map[string]handler
}

// netContextRouter implements the Handler interface that consumes netContext instead of stdlib context
type netContextRouter struct {
	router *TChannelRouter
}

func (ncr netContextRouter) Handle(ctx netContext.Context, call *tchannel.InboundCall) {
	ncr.router.Handle(ctx, call)
}

// NewTChannelRouter returns a TChannel router that can serve thrift services over TChannel.
func NewTChannelRouter(registrar tchannel.Registrar, logger *zap.Logger) *TChannelRouter {
	return &TChannelRouter{
		registrar: registrar,
		logger:    logger,
		handlers:  map[string]handler{},
	}
}

// Register registers the given TChannelHandler to be called on an incoming call for its method.
// "service" is the thrift service name as in the thrift definition.
func (s *TChannelRouter) Register(service string, method string, h TChannelHandler) {
	handler := &handler{tchannelHandler: h}
	s.register(service, method, handler)
}

// RegisterWithPostResponseCB registers the given TChannelHandler with a PostResponseCB function
func (s *TChannelRouter) RegisterWithPostResponseCB(service string, method string, h TChannelHandler, cb PostResponseCB) {
	handler := &handler{
		tchannelHandler: h,
		postResponseCB:  cb,
	}
	s.register(service, method, handler)
}

func (s *TChannelRouter) register(service string, method string, h *handler) {
	key := service + "::" + method

	s.Lock()
	s.handlers[key] = *h
	s.Unlock()

	ncr := netContextRouter{router: s}
	s.registrar.Register(ncr, key)
}

// Handle handles an incoming TChannel call and forwards it to the correct handler.
func (s *TChannelRouter) Handle(ctx context.Context, call *tchannel.InboundCall) {
	op := call.MethodString()
	service, method, ok := getServiceMethod(op)
	if !ok {
		s.logger.Error(fmt.Sprintf("Handle got call for %s which does not match the expected call format", op))
	}

	s.RLock()
	handler, ok := s.handlers[op]
	s.RUnlock()
	if !ok {
		s.logger.Error(fmt.Sprintf("Handle got call for %s which is not registered", op))
	}

	if err := s.handle(ctx, handler, service, method, call); err != nil {
		s.onError(err)
	}
}

func (s *TChannelRouter) onError(err error) {
	if tchannel.GetSystemErrorCode(err) == tchannel.ErrCodeTimeout {
		s.logger.Warn("Thrift server timeout",
			zap.String("error", err.Error()),
		)
	} else {
		s.logger.Error("Thrift server error.",
			zap.String("error", err.Error()),
		)
	}
}

func (s *TChannelRouter) handle(ctx context.Context, handler handler, service string, method string, call *tchannel.InboundCall) error {
	reader, err := call.Arg2Reader()
	if err != nil {
		return errors.Wrapf(err, "could not create arg2reader for inbound call: %s::%s", service, method)
	}
	headers, err := ReadHeaders(reader)
	if err != nil {
		return errors.Wrapf(err, "could not reade headers for inbound call: %s::%s", service, method)
	}
	if err := EnsureEmpty(reader, "reading request headers"); err != nil {
		return errors.Wrapf(err, "could not ensure arg2reader is empty for inbound call: %s::%s", service, method)
	}

	if err := reader.Close(); err != nil {
		return errors.Wrapf(err, "could not close arg2reader for inbound call: %s::%s", service, method)
	}

	reader, err = call.Arg3Reader()
	if err != nil {
		return errors.Wrapf(err, "could not create arg3reader for inbound call: %s::%s", service, method)
	}

	buf := GetBuffer()
	defer PutBuffer(buf)
	if _, err := buf.ReadFrom(reader); err != nil {
		return errors.Wrapf(err, "could not read from arg3reader for inbound call: %s::%s", service, method)
	}

	tracer := tchannel.TracerFromRegistrar(s.registrar)
	ctx = tchannel.ExtractInboundSpan(ctx, call, headers, tracer)

	wireValue, err := protocol.Binary.Decode(bytes.NewReader(buf.Bytes()), wire.TStruct)
	if err != nil {
		return errors.Wrapf(err, "could not decode arg3 for inbound call: %s::%s", service, method)
	}

	success, resp, respHeaders, err := handler.tchannelHandler.Handle(ctx, headers, &wireValue)

	if handler.postResponseCB != nil {
		defer handler.postResponseCB(ctx, method, resp)
	}

	if err != nil {
		if er := reader.Close(); er != nil {
			return errors.Wrapf(er, "could not close arg3reader for inbound call: %s::%s", service, method)
		}
		return call.Response().SendSystemError(err)
	}

	if err := EnsureEmpty(reader, "reading request body"); err != nil {
		return errors.Wrapf(err, "could not ensure arg3reader is empty for inbound call: %s::%s", service, method)
	}
	if err := reader.Close(); err != nil {
		return errors.Wrapf(err, "could not close arg3reader is empty for inbound call: %s::%s", service, method)
	}

	if !success {
		if err := call.Response().SetApplicationError(); err != nil {
			return err
		}
	}

	writer, err := call.Response().Arg2Writer()
	if err != nil {
		return errors.Wrapf(err, "could not create arg2writer for inbound call response: %s::%s", service, method)
	}

	if err := WriteHeaders(writer, respHeaders); err != nil {
		return errors.Wrapf(err, "could not write headers for inbound call response: %s::%s", service, method)
	}
	if err := writer.Close(); err != nil {
		return errors.Wrapf(err, "could not close arg2writer for inbound call response: %s::%s", service, method)
	}

	writer, err = call.Response().Arg3Writer()
	if err != nil {
		return errors.Wrapf(err, "could not create arg3writer for inbound call response: %s::%s", service, method)
	}

	err = WriteStruct(writer, resp)
	if err != nil {
		return errors.Wrapf(err, "could not write arg3 for inbound call response: %s::%s", service, method)
	}

	if err := writer.Close(); err != nil {
		return errors.Wrapf(err, "could not close arg3writer for inbound call response: %s::%s", service, method)
	}

	return nil
}

func getServiceMethod(method string) (string, string, bool) {
	s := string(method)
	sep := strings.Index(s, "::")
	if sep == -1 {
		return "", "", false
	}
	return s[:sep], s[sep+2:], true
}
<commit_msg>Log unexpected tchannel system error<commit_after>// Copyright (c) 2017 Uber Technologies, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

package zanzibar

import (
	"bytes"
	"context"
	"fmt"
	"strings"
	"sync"

	tchannel "github.com/uber/tchannel-go"
	netContext "golang.org/x/net/context"

	"github.com/pkg/errors"
	"go.uber.org/thriftrw/protocol"
	"go.uber.org/thriftrw/wire"
	"go.uber.org/zap"
)

// PostResponseCB registers a callback that is run after a response has been
// completely processed (e.g. written to the channel).
// This gives the server a chance to clean up resources from the response object
type PostResponseCB func(ctx context.Context, method string, response RWTStruct)

type handler struct {
	tchannelHandler TChannelHandler
	postResponseCB  PostResponseCB
}

// TChannelRouter handles incoming TChannel calls and routes them to the matching TChannelHandler.
type TChannelRouter struct {
	sync.RWMutex
	registrar tchannel.Registrar
	logger    *zap.Logger
	handlers  map[string]handler
}

// netContextRouter implements the Handler interface that consumes netContext instead of stdlib context
type netContextRouter struct {
	router *TChannelRouter
}

func (ncr netContextRouter) Handle(ctx netContext.Context, call *tchannel.InboundCall) {
	ncr.router.Handle(ctx, call)
}

// NewTChannelRouter returns a TChannel router that can serve thrift services over TChannel.
func NewTChannelRouter(registrar tchannel.Registrar, logger *zap.Logger) *TChannelRouter {
	return &TChannelRouter{
		registrar: registrar,
		logger:    logger,
		handlers:  map[string]handler{},
	}
}

// Register registers the given TChannelHandler to be called on an incoming call for its method.
// "service" is the thrift service name as in the thrift definition.
func (s *TChannelRouter) Register(service string, method string, h TChannelHandler) {
	handler := &handler{tchannelHandler: h}
	s.register(service, method, handler)
}

// RegisterWithPostResponseCB registers the given TChannelHandler with a PostResponseCB function
func (s *TChannelRouter) RegisterWithPostResponseCB(service string, method string, h TChannelHandler, cb PostResponseCB) {
	handler := &handler{
		tchannelHandler: h,
		postResponseCB:  cb,
	}
	s.register(service, method, handler)
}

func (s *TChannelRouter) register(service string, method string, h *handler) {
	key := service + "::" + method

	s.Lock()
	s.handlers[key] = *h
	s.Unlock()

	ncr := netContextRouter{router: s}
	s.registrar.Register(ncr, key)
}

// Handle handles an incoming TChannel call and forwards it to the correct handler.
func (s *TChannelRouter) Handle(ctx context.Context, call *tchannel.InboundCall) {
	op := call.MethodString()
	service, method, ok := getServiceMethod(op)
	if !ok {
		s.logger.Error(fmt.Sprintf("Handle got call for %s which does not match the expected call format", op))
	}

	s.RLock()
	handler, ok := s.handlers[op]
	s.RUnlock()
	if !ok {
		s.logger.Error(fmt.Sprintf("Handle got call for %s which is not registered", op))
	}

	if err := s.handle(ctx, handler, service, method, call); err != nil {
		s.onError(err)
	}
}

func (s *TChannelRouter) onError(err error) {
	if tchannel.GetSystemErrorCode(err) == tchannel.ErrCodeTimeout {
		s.logger.Warn("Thrift server timeout",
			zap.String("error", err.Error()),
		)
	} else {
		s.logger.Error("Thrift server error.",
			zap.String("error", err.Error()),
		)
	}
}

func (s *TChannelRouter) handle(ctx context.Context, handler handler, service string, method string, call *tchannel.InboundCall) error {
	reader, err := call.Arg2Reader()
	if err != nil {
		return errors.Wrapf(err, "could not create arg2reader for inbound call: %s::%s", service, method)
	}
	headers, err := ReadHeaders(reader)
	if err != nil {
		return errors.Wrapf(err, "could not reade headers for inbound call: %s::%s", service, method)
	}
	if err := EnsureEmpty(reader, "reading request headers"); err != nil {
		return errors.Wrapf(err, "could not ensure arg2reader is empty for inbound call: %s::%s", service, method)
	}

	if err := reader.Close(); err != nil {
		return errors.Wrapf(err, "could not close arg2reader for inbound call: %s::%s", service, method)
	}

	reader, err = call.Arg3Reader()
	if err != nil {
		return errors.Wrapf(err, "could not create arg3reader for inbound call: %s::%s", service, method)
	}

	buf := GetBuffer()
	defer PutBuffer(buf)
	if _, err := buf.ReadFrom(reader); err != nil {
		return errors.Wrapf(err, "could not read from arg3reader for inbound call: %s::%s", service, method)
	}

	tracer := tchannel.TracerFromRegistrar(s.registrar)
	ctx = tchannel.ExtractInboundSpan(ctx, call, headers, tracer)

	wireValue, err := protocol.Binary.Decode(bytes.NewReader(buf.Bytes()), wire.TStruct)
	if err != nil {
		return errors.Wrapf(err, "could not decode arg3 for inbound call: %s::%s", service, method)
	}

	success, resp, respHeaders, err := handler.tchannelHandler.Handle(ctx, headers, &wireValue)

	if handler.postResponseCB != nil {
		defer handler.postResponseCB(ctx, method, resp)
	}

	if err != nil {
		if er := reader.Close(); er != nil {
			return errors.Wrapf(er, "could not close arg3reader for inbound call: %s::%s", service, method)
		}
		s.logger.Warn("Unexpected tchannel system error",
			zap.String("error", err.Error()),
		)
		return call.Response().SendSystemError(err)
	}

	if err := EnsureEmpty(reader, "reading request body"); err != nil {
		return errors.Wrapf(err, "could not ensure arg3reader is empty for inbound call: %s::%s", service, method)
	}
	if err := reader.Close(); err != nil {
		return errors.Wrapf(err, "could not close arg3reader is empty for inbound call: %s::%s", service, method)
	}

	if !success {
		if err := call.Response().SetApplicationError(); err != nil {
			return err
		}
	}

	writer, err := call.Response().Arg2Writer()
	if err != nil {
		return errors.Wrapf(err, "could not create arg2writer for inbound call response: %s::%s", service, method)
	}

	if err := WriteHeaders(writer, respHeaders); err != nil {
		return errors.Wrapf(err, "could not write headers for inbound call response: %s::%s", service, method)
	}
	if err := writer.Close(); err != nil {
		return errors.Wrapf(err, "could not close arg2writer for inbound call response: %s::%s", service, method)
	}

	writer, err = call.Response().Arg3Writer()
	if err != nil {
		return errors.Wrapf(err, "could not create arg3writer for inbound call response: %s::%s", service, method)
	}

	err = WriteStruct(writer, resp)
	if err != nil {
		return errors.Wrapf(err, "could not write arg3 for inbound call response: %s::%s", service, method)
	}

	if err := writer.Close(); err != nil {
		return errors.Wrapf(err, "could not close arg3writer for inbound call response: %s::%s", service, method)
	}

	return nil
}

func getServiceMethod(method string) (string, string, bool) {
	s := string(method)
	sep := strings.Index(s, "::")
	if sep == -1 {
		return "", "", false
	}
	return s[:sep], s[sep+2:], true
}
<|endoftext|>


<commit_before>// snippet-comment:[These are tags for the AWS doc team's sample catalog. Do not remove.]
// snippet-sourceauthor:[AWS]
// snippet-sourcedescription:[rds_list_cluster_snapshots lists your RDS cluster snapshots.]
// snippet-keyword:[Amazon Relational Database Service]
// snippet-keyword:[Amazon RDS]
// snippet-keyword:[DescribeDBClusterSnapshots function]
// snippet-keyword:[Go]
// snippet-service:[s3]
// snippet-keyword:[Code Sample]
// snippet-sourcetype:[full-example]
// snippet-sourcedate:[2019-01-30]
/*
   Copyright 2010-2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.

   This file is 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/

   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.
*/
// snippet-start:[rds.go.describe_db_cluster_snapshots
package main

import (
	"fmt"
	"os"

	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/aws/session"
	"github.com/aws/aws-sdk-go/service/rds"
)

func main() {
	// Initialize a session in us-west-2 that the SDK will use to load
	// credentials from the shared credentials file ~/.aws/credentials.
	sess, err := session.NewSession(&aws.Config{
		Region: aws.String("us-west-2")},
	)

	// Create RDS service client
	svc := rds.New(sess)

	result, err := svc.DescribeDBClusterSnapshots(nil)
	if err != nil {
		exitErrorf("Unable to list snapshots, %v", err)
	}

	for _, s := range result.DBClusterSnapshots {
		fmt.Printf("* %s with status %s\n",
			aws.StringValue(s.DBClusterSnapshotIdentifier), aws.StringValue(s.Status))
	}
}

func exitErrorf(msg string, args ...interface{}) {
	fmt.Fprintf(os.Stderr, msg+"\n", args...)
	os.Exit(1)
}
// snippet-end:[rds.go.describe_db_cluster_snapshots
<commit_msg>Update rds_list_cluster_snapshots.go<commit_after>// snippet-comment:[These are tags for the AWS doc team's sample catalog. Do not remove.]
// snippet-sourceauthor:[AWS]
// snippet-sourcedescription:[rds_list_cluster_snapshots lists your RDS cluster snapshots.]
// snippet-keyword:[Amazon Relational Database Service]
// snippet-keyword:[Amazon RDS]
// snippet-keyword:[DescribeDBClusterSnapshots function]
// snippet-keyword:[Go]
// snippet-service:[s3]
// snippet-keyword:[Code Sample]
// snippet-sourcetype:[full-example]
// snippet-sourcedate:[2019-01-30]
/*
   Copyright 2010-2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.

   This file is 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/

   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.
*/
// snippet-start:[rds.go.describe_db_cluster_snapshots]
package main

import (
	"fmt"
	"os"

	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/aws/session"
	"github.com/aws/aws-sdk-go/service/rds"
)

func main() {
	// Initialize a session in us-west-2 that the SDK will use to load
	// credentials from the shared credentials file ~/.aws/credentials.
	sess, err := session.NewSession(&aws.Config{
		Region: aws.String("us-west-2")},
	)

	// Create RDS service client
	svc := rds.New(sess)

	result, err := svc.DescribeDBClusterSnapshots(nil)
	if err != nil {
		exitErrorf("Unable to list snapshots, %v", err)
	}

	for _, s := range result.DBClusterSnapshots {
		fmt.Printf("* %s with status %s\n",
			aws.StringValue(s.DBClusterSnapshotIdentifier), aws.StringValue(s.Status))
	}
}

func exitErrorf(msg string, args ...interface{}) {
	fmt.Fprintf(os.Stderr, msg+"\n", args...)
	os.Exit(1)
}
// snippet-end:[rds.go.describe_db_cluster_snapshots]
<|endoftext|>


<commit_before>/*
Copyright 2021 The Vitess Authors.

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

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

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

package planbuilder

import (
	"testing"

	"github.com/stretchr/testify/assert"

	"vitess.io/vitess/go/vt/sqlparser"
)

func TestCheckIfAlreadyExists(t *testing.T) {
	tests := []struct {
		name string
		expr *sqlparser.AliasedExpr
		sel  *sqlparser.Select
		want int
	}{
		{name: "No alias, both ColName", want: 0, expr: &sqlparser.AliasedExpr{Expr: sqlparser.NewColName("id")}, sel: &sqlparser.Select{SelectExprs: []sqlparser.SelectExpr{&sqlparser.AliasedExpr{Expr: sqlparser.NewColName("id")}}}},
		{name: "Aliased expression and ColName", want: 0, expr: &sqlparser.AliasedExpr{Expr: sqlparser.NewColName("user_id")}, sel: &sqlparser.Select{SelectExprs: []sqlparser.SelectExpr{&sqlparser.AliasedExpr{As: sqlparser.NewColIdent("user_id"), Expr: sqlparser.NewColName("id")}}}},
		{name: "Non-ColName expressions", want: 0, expr: &sqlparser.AliasedExpr{Expr: sqlparser.NewStrLiteral("test")}, sel: &sqlparser.Select{SelectExprs: []sqlparser.SelectExpr{&sqlparser.AliasedExpr{Expr: sqlparser.NewStrLiteral("test")}}}},
		{name: "No alias, multiple ColName in projection", want: 1, expr: &sqlparser.AliasedExpr{Expr: sqlparser.NewColName("id")}, sel: &sqlparser.Select{SelectExprs: []sqlparser.SelectExpr{&sqlparser.AliasedExpr{Expr: sqlparser.NewColName("foo")}, &sqlparser.AliasedExpr{Expr: sqlparser.NewColName("id")}}}},
		{name: "No matching entry", want: -1, expr: &sqlparser.AliasedExpr{Expr: sqlparser.NewColName("id")}, sel: &sqlparser.Select{SelectExprs: []sqlparser.SelectExpr{&sqlparser.AliasedExpr{Expr: sqlparser.NewColName("foo")}, &sqlparser.AliasedExpr{Expr: sqlparser.NewColName("name")}}}},
		{name: "No AliasedExpr in projection", want: -1, expr: &sqlparser.AliasedExpr{Expr: sqlparser.NewColName("id")}, sel: &sqlparser.Select{SelectExprs: []sqlparser.SelectExpr{&sqlparser.StarExpr{TableName: sqlparser.TableName{Name: sqlparser.NewTableIdent("user")}}, &sqlparser.StarExpr{TableName: sqlparser.TableName{Name: sqlparser.NewTableIdent("people")}}}}},
	}
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			got := checkIfAlreadyExists(tt.expr, tt.sel)
			assert.Equal(t, tt.want, got)
		})
	}
}
<commit_msg>More readable horizon planning unit test<commit_after>/*
Copyright 2021 The Vitess Authors.

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

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

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

package planbuilder

import (
	"testing"

	"github.com/stretchr/testify/assert"

	"vitess.io/vitess/go/vt/sqlparser"
)

func TestCheckIfAlreadyExists(t *testing.T) {
	tests := []struct {
		name string
		expr *sqlparser.AliasedExpr
		sel  *sqlparser.Select
		want int
	}{
		{
			name: "No alias, both ColName",
			want: 0,
			expr: &sqlparser.AliasedExpr{Expr: sqlparser.NewColName("id")},
			sel:  &sqlparser.Select{SelectExprs: []sqlparser.SelectExpr{&sqlparser.AliasedExpr{Expr: sqlparser.NewColName("id")}}},
		},
		{
			name: "Aliased expression and ColName",
			want: 0,
			expr: &sqlparser.AliasedExpr{Expr: sqlparser.NewColName("user_id")},
			sel:  &sqlparser.Select{SelectExprs: []sqlparser.SelectExpr{&sqlparser.AliasedExpr{As: sqlparser.NewColIdent("user_id"), Expr: sqlparser.NewColName("id")}}},
		},
		{
			name: "Non-ColName expressions",
			want: 0,
			expr: &sqlparser.AliasedExpr{Expr: sqlparser.NewStrLiteral("test")},
			sel:  &sqlparser.Select{SelectExprs: []sqlparser.SelectExpr{&sqlparser.AliasedExpr{Expr: sqlparser.NewStrLiteral("test")}}},
		},
		{
			name: "No alias, multiple ColName in projection",
			want: 1,
			expr: &sqlparser.AliasedExpr{Expr: sqlparser.NewColName("id")},
			sel:  &sqlparser.Select{SelectExprs: []sqlparser.SelectExpr{&sqlparser.AliasedExpr{Expr: sqlparser.NewColName("foo")}, &sqlparser.AliasedExpr{Expr: sqlparser.NewColName("id")}}},
		},
		{
			name: "No matching entry",
			want: -1,
			expr: &sqlparser.AliasedExpr{Expr: sqlparser.NewColName("id")},
			sel:  &sqlparser.Select{SelectExprs: []sqlparser.SelectExpr{&sqlparser.AliasedExpr{Expr: sqlparser.NewColName("foo")}, &sqlparser.AliasedExpr{Expr: sqlparser.NewColName("name")}}},
		},
		{
			name: "No AliasedExpr in projection",
			want: -1,
			expr: &sqlparser.AliasedExpr{Expr: sqlparser.NewColName("id")},
			sel:  &sqlparser.Select{SelectExprs: []sqlparser.SelectExpr{&sqlparser.StarExpr{TableName: sqlparser.TableName{Name: sqlparser.NewTableIdent("user")}}, &sqlparser.StarExpr{TableName: sqlparser.TableName{Name: sqlparser.NewTableIdent("people")}}}},
		},
	}
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			got := checkIfAlreadyExists(tt.expr, tt.sel)
			assert.Equal(t, tt.want, got)
		})
	}
}
<|endoftext|>