<commit_before>package main

import (
	"github.com/GeertJohan/go.rice"
	"github.com/gorilla/mux"
	"github.com/gorilla/websocket"
	"log"
	"net/http"
	"strconv"
	"text/template"
)

var templatesBox = rice.MustFindBox("resources/templates")

type ProgramStatus struct {
	Program           *Program
	LastExecution     *Execution
	LastExecutionTime string
	Running           bool
	Succeeded         bool
	Failed            bool
	Retryable         bool
}

type IndexPageState struct {
	Succeeded       int
	Retryable       int
	Failed          int
	ProgramStatuses []*ProgramStatus
}

type ProgramPageState struct {
	Program *Program
}

type ExecutionPageState struct {
	Execution *Execution
}

func handleIndex(dagr Dagr) http.HandlerFunc {
	indexTemplate := template.Must(loadTemplate("index.html.tmpl"))

	return func(w http.ResponseWriter, req *http.Request) {
		programs := dagr.AllPrograms()
		programStatuses := []*ProgramStatus{}

		var totalSucceeded, totalFailed, totalRetryable int

		for _, program := range programs {
			executions := program.Executions()
			var lastExecution *Execution
			var lastExecutionTime string
			if len(executions) == 0 {
				lastExecution = nil
				lastExecutionTime = ""
			} else {
				lastExecution = executions[len(executions)-1]
				lastExecutionTime = lastExecution.StartTime.Format("2 Jan 2006 15:04")
			}

			var running, succeeded, retryable, failed bool

			if lastExecution != nil {
				running = !lastExecution.Finished()

				if !running {
					succeeded = lastExecution.ExitStatus() == Success
					retryable = lastExecution.ExitStatus() == Retryable
					failed = lastExecution.ExitStatus() == Failed
				}
			}

			programStatuses = append(programStatuses,
				&ProgramStatus{
					Program:           program,
					LastExecution:     lastExecution,
					LastExecutionTime: lastExecutionTime,
					Running:           running,
					Succeeded:         succeeded,
					Retryable:         retryable,
					Failed:            failed,
				})

			if succeeded {
				totalSucceeded++
			}

			if retryable {
				totalRetryable++
			}

			if failed {
				totalFailed++
			}
		}

		err := indexTemplate.Execute(w, IndexPageState{totalSucceeded, totalRetryable, totalFailed, programStatuses})

		if err != nil {
			log.Println("error when executing index template:", err)
			http.Error(w, err.Error(), 500)
		}
	}
}

func handleProgramInfo(dagr Dagr) http.HandlerFunc {
	infoTemplate := template.Must(loadTemplate("program.html.tmpl"))

	return func(w http.ResponseWriter, req *http.Request) {
		vars := mux.Vars(req)
		programName := vars["program"]
		program := dagr.FindProgram(programName)
		if program == nil {
			log.Println("no such program:", programName)
			http.NotFound(w, req)
		} else if err := infoTemplate.Execute(w, ProgramPageState{program}); err != nil {
			log.Println("error when executing program info template:", err)
			http.Error(w, err.Error(), 500)
		}
	}
}

func handleProgramExecute(dagr Dagr) http.HandlerFunc {
	return func(w http.ResponseWriter, req *http.Request) {
		vars := mux.Vars(req)
		programName := vars["program"]
		program := dagr.FindProgram(programName)
		if program == nil {
			log.Println("no such program:", programName)
			http.NotFound(w, req)
		} else {
			execution, err := dagr.Execute(program)

			if err != nil {
				log.Println("error on execution:", err)
				http.Error(w, err.Error(), 500)
				return
			}

			http.Redirect(w, req, "/executions/"+execution.Id, 302)
		}
	}
}

func handleExecutionInfo(dagr Dagr) http.HandlerFunc {
	showTemplate := template.Must(loadTemplate("execution.html.tmpl"))

	return func(w http.ResponseWriter, req *http.Request) {
		vars := mux.Vars(req)
		executionId := vars["executionId"]
		execution := dagr.FindExecution(executionId)
		if execution == nil {
			log.Println("no such execution:", executionId)
			http.NotFound(w, req)
		} else if err := showTemplate.Execute(w, ExecutionPageState{execution}); err != nil {
			log.Println("error when executing execution info template:", err)
			http.Error(w, err.Error(), 500)
		}
	}
}

func loadTemplate(path string) (*template.Template, error) {
	templateString, err := templatesBox.String(path)
	if err != nil {
		return nil, err
	}
	return template.New(path).Parse(templateString)
}

// read is required (http://www.gorillatoolkit.org/pkg/websocket)
func readLoop(execution *Execution, c *websocket.Conn) {
	for {
		_, _, err := c.NextReader()
		if err != nil {
			c.Close()
			execution.Unsubscribe(c)
			return
		}
	}
}

func handleExecutionMessages(dagr Dagr) http.HandlerFunc {
	upgrader := websocket.Upgrader{
		ReadBufferSize:  1024,
		WriteBufferSize: 1024,
	}

	return func(w http.ResponseWriter, req *http.Request) {
		conn, err := upgrader.Upgrade(w, req, nil)
		if err != nil {
			log.Println("cannot upgrade to websocket")
			return
		}
		vars := mux.Vars(req)
		executionId := vars["executionId"]
		log.Println("subscribing to messages for execution id:", executionId)
		execution := dagr.FindExecution(executionId)
		if execution == nil {
			log.Println("no such execution:", executionId)
			http.NotFound(w, req)
		} else {
			execution.Subscribe(conn)
			countSoFarStr := vars["countSoFar"]
			countSoFar, err := strconv.Atoi(countSoFarStr)
			if err != nil {
				log.Println("countSoFar not an integer?", countSoFarStr, err)
			} else {
				messagesCaughtUp := execution.CatchUp(conn, countSoFar)
				if messagesCaughtUp > 0 {
					log.Println("caught up", messagesCaughtUp, "message(s)")
				}
			}

			go readLoop(execution, conn)
		}
	}
}

func DagrHandler(dagr Dagr) http.Handler {
	r := mux.NewRouter()
	r.HandleFunc("/", handleIndex(dagr)).Methods("GET")
	r.HandleFunc("/program/{program}", handleProgramInfo(dagr)).Methods("GET")
	r.HandleFunc("/program/{program}/execute", handleProgramExecute(dagr)).Methods("POST")
	r.HandleFunc("/executions/{executionId}", handleExecutionInfo(dagr)).Methods("GET")
	r.HandleFunc("/executions/{executionId}/messages/{countSoFar:[0-9]+}", handleExecutionMessages(dagr))
	return r
}
<commit_msg>rely on zero values<commit_after>package main

import (
	"github.com/GeertJohan/go.rice"
	"github.com/gorilla/mux"
	"github.com/gorilla/websocket"
	"log"
	"net/http"
	"strconv"
	"text/template"
)

var templatesBox = rice.MustFindBox("resources/templates")

type ProgramStatus struct {
	Program           *Program
	LastExecution     *Execution
	LastExecutionTime string
	Running           bool
	Succeeded         bool
	Failed            bool
	Retryable         bool
}

type IndexPageState struct {
	Succeeded       int
	Retryable       int
	Failed          int
	ProgramStatuses []*ProgramStatus
}

type ProgramPageState struct {
	Program *Program
}

type ExecutionPageState struct {
	Execution *Execution
}

func handleIndex(dagr Dagr) http.HandlerFunc {
	indexTemplate := template.Must(loadTemplate("index.html.tmpl"))

	return func(w http.ResponseWriter, req *http.Request) {
		programs := dagr.AllPrograms()
		programStatuses := []*ProgramStatus{}

		var totalSucceeded, totalFailed, totalRetryable int

		for _, program := range programs {
			executions := program.Executions()
			var lastExecution *Execution
			var lastExecutionTime string
			if len(executions) > 0 {
				lastExecution = executions[len(executions)-1]
				lastExecutionTime = lastExecution.StartTime.Format("2 Jan 2006 15:04")
			}

			var running, succeeded, retryable, failed bool

			if lastExecution != nil {
				running = !lastExecution.Finished()

				if !running {
					succeeded = lastExecution.ExitStatus() == Success
					retryable = lastExecution.ExitStatus() == Retryable
					failed = lastExecution.ExitStatus() == Failed
				}
			}

			programStatuses = append(programStatuses,
				&ProgramStatus{
					Program:           program,
					LastExecution:     lastExecution,
					LastExecutionTime: lastExecutionTime,
					Running:           running,
					Succeeded:         succeeded,
					Retryable:         retryable,
					Failed:            failed,
				})

			if succeeded {
				totalSucceeded++
			}

			if retryable {
				totalRetryable++
			}

			if failed {
				totalFailed++
			}
		}

		err := indexTemplate.Execute(w, IndexPageState{totalSucceeded, totalRetryable, totalFailed, programStatuses})

		if err != nil {
			log.Println("error when executing index template:", err)
			http.Error(w, err.Error(), 500)
		}
	}
}

func handleProgramInfo(dagr Dagr) http.HandlerFunc {
	infoTemplate := template.Must(loadTemplate("program.html.tmpl"))

	return func(w http.ResponseWriter, req *http.Request) {
		vars := mux.Vars(req)
		programName := vars["program"]
		program := dagr.FindProgram(programName)
		if program == nil {
			log.Println("no such program:", programName)
			http.NotFound(w, req)
		} else if err := infoTemplate.Execute(w, ProgramPageState{program}); err != nil {
			log.Println("error when executing program info template:", err)
			http.Error(w, err.Error(), 500)
		}
	}
}

func handleProgramExecute(dagr Dagr) http.HandlerFunc {
	return func(w http.ResponseWriter, req *http.Request) {
		vars := mux.Vars(req)
		programName := vars["program"]
		program := dagr.FindProgram(programName)
		if program == nil {
			log.Println("no such program:", programName)
			http.NotFound(w, req)
		} else {
			execution, err := dagr.Execute(program)

			if err != nil {
				log.Println("error on execution:", err)
				http.Error(w, err.Error(), 500)
				return
			}

			http.Redirect(w, req, "/executions/"+execution.Id, 302)
		}
	}
}

func handleExecutionInfo(dagr Dagr) http.HandlerFunc {
	showTemplate := template.Must(loadTemplate("execution.html.tmpl"))

	return func(w http.ResponseWriter, req *http.Request) {
		vars := mux.Vars(req)
		executionId := vars["executionId"]
		execution := dagr.FindExecution(executionId)
		if execution == nil {
			log.Println("no such execution:", executionId)
			http.NotFound(w, req)
		} else if err := showTemplate.Execute(w, ExecutionPageState{execution}); err != nil {
			log.Println("error when executing execution info template:", err)
			http.Error(w, err.Error(), 500)
		}
	}
}

func loadTemplate(path string) (*template.Template, error) {
	templateString, err := templatesBox.String(path)
	if err != nil {
		return nil, err
	}
	return template.New(path).Parse(templateString)
}

// read is required (http://www.gorillatoolkit.org/pkg/websocket)
func readLoop(execution *Execution, c *websocket.Conn) {
	for {
		_, _, err := c.NextReader()
		if err != nil {
			c.Close()
			execution.Unsubscribe(c)
			return
		}
	}
}

func handleExecutionMessages(dagr Dagr) http.HandlerFunc {
	upgrader := websocket.Upgrader{
		ReadBufferSize:  1024,
		WriteBufferSize: 1024,
	}

	return func(w http.ResponseWriter, req *http.Request) {
		conn, err := upgrader.Upgrade(w, req, nil)
		if err != nil {
			log.Println("cannot upgrade to websocket")
			return
		}
		vars := mux.Vars(req)
		executionId := vars["executionId"]
		log.Println("subscribing to messages for execution id:", executionId)
		execution := dagr.FindExecution(executionId)
		if execution == nil {
			log.Println("no such execution:", executionId)
			http.NotFound(w, req)
		} else {
			execution.Subscribe(conn)
			countSoFarStr := vars["countSoFar"]
			countSoFar, err := strconv.Atoi(countSoFarStr)
			if err != nil {
				log.Println("countSoFar not an integer?", countSoFarStr, err)
			} else {
				messagesCaughtUp := execution.CatchUp(conn, countSoFar)
				if messagesCaughtUp > 0 {
					log.Println("caught up", messagesCaughtUp, "message(s)")
				}
			}

			go readLoop(execution, conn)
		}
	}
}

func DagrHandler(dagr Dagr) http.Handler {
	r := mux.NewRouter()
	r.HandleFunc("/", handleIndex(dagr)).Methods("GET")
	r.HandleFunc("/program/{program}", handleProgramInfo(dagr)).Methods("GET")
	r.HandleFunc("/program/{program}/execute", handleProgramExecute(dagr)).Methods("POST")
	r.HandleFunc("/executions/{executionId}", handleExecutionInfo(dagr)).Methods("GET")
	r.HandleFunc("/executions/{executionId}/messages/{countSoFar:[0-9]+}", handleExecutionMessages(dagr))
	return r
}
<|endoftext|>


<commit_before>package capacitor

import (
	"fmt"
	"github.com/mathcunha/CloudCapacitor/sync2"
	"log"
)

type ExecInfo struct {
	Execs int
	Path  string
}

type currentExec struct {
	nodes NodesInfo
	key   string
	execs int
	path  string
	it    int
}

type nextExec struct {
	nodes NodesInfo
	execs int
	path  string
	it    int
}

type Heuristic interface {
	Exec(mode string, slo float32, wkls []string)
}

//Execute all configurations and workloads without infer
type BrutalForce struct {
	c *Capacitor
}

//Find the shortest path to Mark all configurations and workloads
type ShortestPath struct {
	c     *Capacitor
	slo   float32
	it    int
	maxIt int
	wg    *sync2.BlockWaitGroup
}

func NewShortestPath(c *Capacitor) (h *ShortestPath) {
	h = new(ShortestPath)
	h.c = c
	return
}

func (bf *BrutalForce) Exec(mode string, slo float32, wkls []string) {
	mapa := bf.c.Dspace.CapacityBy(mode)
	for _, nodes := range *mapa {
		for _, node := range nodes {
			for _, conf := range node.Configs {
				for _, wkl := range wkls {
					result := bf.c.Executor.Execute(*conf, wkl)
					log.Printf("%v x %v ? %v \n", *conf, wkl, result.SLO <= slo)
				}
			}
		}
	}
}

func (h *ShortestPath) Exec(mode string, slo float32, wkls []string) {
	mapa := h.c.Dspace.CapacityBy(mode)
	h.slo = slo
	for key, nodes := range *mapa {
		h.ExecCategory(wkls, nodes)
		log.Println("Category[", key, "] - ", nodes)
	}
}

func (h *ShortestPath) InitControlers() {
	h.wg = sync2.NewBlockWaitGroup(100000)
}

func (h *ShortestPath) PostExecs(nexts []nextExec) (current []currentExec) {
	for _, next := range nexts {
		for key, _ := range next.nodes.matrix {
			current = append(current, currentExec{next.nodes, key, next.execs, next.path, next.it})
		}
	}
	return
}

func (h *ShortestPath) ExecCategory(wkls []string, nodes Nodes) {
	numConfigs := 0
	for _, node := range nodes {
		numConfigs = numConfigs + len(node.Configs)
	}
	h.maxIt = len(wkls) * numConfigs
	log.Printf("Max iterations :%v \n", h.maxIt)

	h.InitControlers()

	nexts := []nextExec{nextExec{buildMatrix(wkls, nodes), 0, "", 1}}
	var best ExecInfo

	for i := 1; i <= h.maxIt; i++ {
		log.Printf("Now trying %v Iteration(s) \n", i)

		h.wg.Add(1)
		go func() {
			defer h.wg.Done()
			nexts, best = h.findShortestPath(h.PostExecs(nexts))
		}()

		h.wg.Wait()

		if nexts == nil {
			log.Printf("the winner is %v", best)
			return
		}

	}

}

func (h *ShortestPath) findShortestPath(current []currentExec) (nexts []nextExec, shortest ExecInfo) {
	for _, ex := range current {
		node := ex.nodes.matrix[ex.key]
		if !(node.When != -1) {
			cNodes := ex.nodes.Clone()
			nExecs := ex.execs
			result := Result{}
			for _, conf := range node.Configs {
				nExecs = nExecs + 1

				result = h.c.Executor.Execute(*conf, node.WKL)

				cNodes.Mark(ex.key, result.SLO <= h.slo, nExecs)

			}
			nPath := fmt.Sprintf("%v%v->", ex.path, ex.key)
			//c.Exec(*cNodes, slo, nExecs, nPath, wg, ch, it+1, maxIts)

			if h.c.HasMore(cNodes) {
				nEx := new(nextExec)
				nEx.nodes = *cNodes
				nEx.execs = nExecs
				nEx.path = nPath
				nEx.it = ex.it + 1
				nexts = append(nexts, *nEx)
			} else {
				//All executions!
				return nil, ExecInfo{nExecs, nPath}
			}
		}
	}

	return nexts, ExecInfo{-1, ""}
}

func (h *ShortestPath) GetBest() (best ExecInfo) {
	best = ExecInfo{-1, ""}

	/*	for len(h.chEndExec) > 0 {
		execInfo := <-h.chEndExec
		best = execInfo
		log.Printf("%v, %v \n", execInfo.Execs, execInfo.Path)
	}*/

	return best
}
<commit_msg>channel to the winner<commit_after>package capacitor

import (
	"fmt"
	"github.com/mathcunha/CloudCapacitor/sync2"
	"log"
)

type ExecInfo struct {
	Execs int
	Path  string
}

type currentExec struct {
	nodes NodesInfo
	key   string
	execs int
	path  string
	it    int
}

type nextExec struct {
	nodes NodesInfo
	execs int
	path  string
	it    int
}

type Heuristic interface {
	Exec(mode string, slo float32, wkls []string)
}

//Execute all configurations and workloads without infer
type BrutalForce struct {
	c *Capacitor
}

//Find the shortest path to Mark all configurations and workloads
type ShortestPath struct {
	c     *Capacitor
	slo   float32
	it    int
	maxIt int
}

func NewShortestPath(c *Capacitor) (h *ShortestPath) {
	h = new(ShortestPath)
	h.c = c
	return
}

func (bf *BrutalForce) Exec(mode string, slo float32, wkls []string) {
	mapa := bf.c.Dspace.CapacityBy(mode)
	for _, nodes := range *mapa {
		for _, node := range nodes {
			for _, conf := range node.Configs {
				for _, wkl := range wkls {
					result := bf.c.Executor.Execute(*conf, wkl)
					log.Printf("%v x %v ? %v \n", *conf, wkl, result.SLO <= slo)
				}
			}
		}
	}
}

func (h *ShortestPath) Exec(mode string, slo float32, wkls []string) {
	mapa := h.c.Dspace.CapacityBy(mode)
	h.slo = slo
	for key, nodes := range *mapa {
		h.ExecCategory(wkls, nodes)
		log.Println("Category[", key, "] - ", nodes)
	}
}

func (h *ShortestPath) PostExecs(nexts []nextExec) (current []currentExec) {
	for _, next := range nexts {
		for key, _ := range next.nodes.matrix {
			current = append(current, currentExec{next.nodes, key, next.execs, next.path, next.it})
		}
	}
	return
}

func (h *ShortestPath) ExecCategory(wkls []string, nodes Nodes) {
	numConfigs := 0
	for _, node := range nodes {
		numConfigs = numConfigs + len(node.Configs)
	}
	h.maxIt = len(wkls) * numConfigs
	log.Printf("Max iterations :%v \n", h.maxIt)

	nexts := []nextExec{nextExec{buildMatrix(wkls, nodes), 0, "", 1}}

	for i := 1; i <= h.maxIt; i++ {
		wg := sync2.NewBlockWaitGroup(100000)
		chBest := make(chan ExecInfo)

		log.Printf("Now trying %v Iteration(s) \n", i)

		wg.Add(1)
		go func() {
			defer wg.Done()
			nexts = h.findShortestPath(h.PostExecs(nexts), wg, chBest)
		}()

		go func() {
			wg.Wait()
			close(chBest)
		}()

		best := h.GetBest(chBest)

		if best.Execs != -1 {
			log.Printf("the winner is %v", best)
			return
		}

	}

}

func (h *ShortestPath) findShortestPath(current []currentExec, wg *sync2.BlockWaitGroup, chBest chan ExecInfo) (nexts []nextExec) {
	for _, ex := range current {
		node := ex.nodes.matrix[ex.key]
		if !(node.When != -1) {
			cNodes := ex.nodes.Clone()
			nExecs := ex.execs
			result := Result{}
			for _, conf := range node.Configs {
				nExecs = nExecs + 1

				result = h.c.Executor.Execute(*conf, node.WKL)

				cNodes.Mark(ex.key, result.SLO <= h.slo, nExecs)

			}
			nPath := fmt.Sprintf("%v%v->", ex.path, ex.key)
			//c.Exec(*cNodes, slo, nExecs, nPath, wg, ch, it+1, maxIts)

			if h.c.HasMore(cNodes) {
				nEx := new(nextExec)
				nEx.nodes = *cNodes
				nEx.execs = nExecs
				nEx.path = nPath
				nEx.it = ex.it + 1
				nexts = append(nexts, *nEx)
			} else {
				//All executions!
				wg.Add(1)
				go func() {
					defer wg.Done()
					log.Printf("winner!! %v,%v", nExecs, nPath)
					chBest <- ExecInfo{nExecs, nPath}
				}()
				//return nil
			}
		}
	}

	return nexts
}

func (h *ShortestPath) GetBest(chBest chan ExecInfo) (best ExecInfo) {
	best = ExecInfo{-1, ""}
	for {
		execInfo, more := <-chBest
		if more {
			best = execInfo
			log.Printf("%v, %v \n", execInfo.Execs, execInfo.Path)
		} else {
			break
		}
	}

	return best
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"github.com/nsf/termbox-go"
	"github.com/xuzhenglun/2048-Go/martix"
	"strconv"
	"time"
)

const MAX_LEN int = 4
const Add_NUM int = 1

var step int

type Go2048 struct {
	martix.Martix
}

func (this Go2048) GoUp() bool {
	this.Left90()
	change := this.Combin()
	this.Left90()
	return change
}

func (this Go2048) GoDown() bool {
	this.Right90()
	change := this.Combin()
	this.Right90()
	return change
}

func (this Go2048) GoLeft() bool {
	change := this.Combin()
	return change
}

func (this Go2048) GoRight() bool {
	this.Mirror()
	change := this.Combin()
	this.Mirror()
	return change
}

func (this Go2048) CheckWinOrLose() bool {
	for x, row := range this.Martix {
		for y, _ := range row {
			if this.Martix[x][y] == 0 {
				return true
				//true = Have not been dead yet
			}
		}
	}
	return false
	//false = Lose
}

func (this Go2048) Init_termbox(x, y int) error {
	fg := termbox.ColorYellow
	bg := termbox.ColorBlack
	err := termbox.Clear(fg, bg)
	if err != nil {
		return err
	}
	str := "Enter: restart game"
	for n, c := range str {
		termbox.SetCell(x+n, y-1, c, fg, bg)
	}

	str = "ESC: quit game" + "  Step: " + strconv.Itoa(step)
	for n, c := range str {
		termbox.SetCell(x+n, y-2, c, fg, bg)
	}

	str = "Play with Arrow Key"
	for n, c := range str {
		termbox.SetCell(x+n, y-3, c, fg, bg)
	}

	fg = termbox.ColorBlack
	bg = termbox.ColorGreen
	for i := 0; i <= len(this.Martix); i++ {
		for t := 0; t < 6*len(this.Martix); t++ {
			if t%6 != 0 {
				termbox.SetCell(x+t, y+i*2, '-', fg, bg)
			}
		}
		for t := 0; t <= 2*len(this.Martix); t++ {
			if t%2 == 0 {
				termbox.SetCell(x+i*6, y+t, '+', fg, bg)
			} else {
				termbox.SetCell(x+i*6, y+t, '|', fg, bg)
			}
		}
	}

	for i, row := range this.Martix {
		for j, _ := range row {
			if this.Martix[i][j] > 0 {
				str := fmt.Sprintf("%-5d", this.Martix[i][j])
				for n, char := range str {
					termbox.SetCell(x+j*6+1+n, y+i*2+1, char, 0x10+termbox.Attribute(this.Martix[i][j]%256), 0xe0-termbox.Attribute(this.Martix[i][j]*2%256))
				}
			}
		}
	}
	return termbox.Flush()
}

func converPrintStr(x, y int, str string, fg, bg termbox.Attribute) error {
	xx := x
	for n, c := range str {
		if c == '\n' {
			y++
			xx = x - n - 1
		}
		termbox.SetCell(xx+n, y, c, fg, bg)
	}
	return termbox.Flush()
}

func (t *Go2048) ListernKey() chan termbox.Event {
	//ev := termbox.PollEvent()
	event_queue := make(chan termbox.Event)
	go func() {
		for {
			event_queue <- termbox.PollEvent() // 开始监听键盘事件
		}
	}()
	return event_queue
}

func (t *Go2048) ActionAndReturnKey(event_queue chan termbox.Event) termbox.Key {
	for {
		ev := <-event_queue
		changed := false

		switch ev.Type {
		case termbox.EventKey:
			switch ev.Key {
			case termbox.KeyArrowUp:
				changed = t.GoUp()
			case termbox.KeyArrowDown:
				changed = t.GoDown()
			case termbox.KeyArrowLeft:
				changed = t.GoLeft()
			case termbox.KeyArrowRight:
				changed = t.GoRight()
			case termbox.KeyEsc, termbox.KeyEnter:
				changed = true
			default:
				changed = false
			}

			// 如果元素的值没有任何更改，则从新开始循环
			if !changed && t.CheckWinOrLose() {
				continue
			}

		case termbox.EventResize:
			x, y := termbox.Size()
			t.Init_termbox(x/2-10, y/2-4)
			continue
		case termbox.EventError:
			panic(ev.Err)
		}
		return ev.Key
	}
}

func main() {
	err := termbox.Init()
	if err != nil {
		panic(err)
	}
	defer termbox.Close()
	x, y := termbox.Size()

	termbox.SetOutputMode(termbox.Output256)

	martix.Init()
	var t Go2048
	t.Martix, _ = martix.Init_martix(MAX_LEN)
	t.AddNum(Add_NUM)
	step = 0
	ch := t.ListernKey()
	defer close(ch)

	for {
		t.Init_termbox(x/2-10, y/2-4)

		key := t.ActionAndReturnKey(ch)

		if t.CheckWinOrLose() == false {
			str := "Lose!"
			strlen := len(str)
			converPrintStr(x/2-strlen/2, y/2, str, termbox.ColorBlack, termbox.ColorRed)
			for {
				key = t.ActionAndReturnKey(ch)
				if key == termbox.KeyEnter || key == termbox.KeyEsc {
					break
				}
			}
		}

		if key == termbox.KeyEnter {
			t.Martix, _ = martix.Init_martix(MAX_LEN)
			step = -1
		}
		if key == termbox.KeyEsc {
			return
		}

		step++

		t.Init_termbox(x/2-10, y/2-4)
		time.Sleep(500 * time.Millisecond)
		t.AddNum(Add_NUM)
	}
}
<commit_msg>support windows cmd<commit_after>package main

import (
	"fmt"
	"github.com/nsf/termbox-go"
	"github.com/xuzhenglun/2048-Go/martix"
	"strconv"
	"time"
)

const MAX_LEN int = 4
const Add_NUM int = 1

var step int
var output_mode = termbox.OutputNormal

type Go2048 struct {
	martix.Martix
}

func (this Go2048) GoUp() bool {
	this.Left90()
	change := this.Combin()
	this.Left90()
	return change
}

func (this Go2048) GoDown() bool {
	this.Right90()
	change := this.Combin()
	this.Right90()
	return change
}

func (this Go2048) GoLeft() bool {
	change := this.Combin()
	return change
}

func (this Go2048) GoRight() bool {
	this.Mirror()
	change := this.Combin()
	this.Mirror()
	return change
}

func (this Go2048) CheckWinOrLose() bool {
	for x, row := range this.Martix {
		for y, _ := range row {
			if this.Martix[x][y] == 0 {
				return true
				//true = Have not been dead yet
			}
		}
	}
	return false
	//false = Lose
}

func (this Go2048) Init_termbox(x, y int) error {
	fg := termbox.ColorYellow
	bg := termbox.ColorBlack
	err := termbox.Clear(fg, bg)
	if err != nil {
		return err
	}
	str := "Enter: restart game"
	for n, c := range str {
		termbox.SetCell(x+n, y-1, c, fg, bg)
	}

	str = "ESC: quit game" + "  Step: " + strconv.Itoa(step)
	for n, c := range str {
		termbox.SetCell(x+n, y-2, c, fg, bg)
	}

	str = "Play with Arrow Key"
	for n, c := range str {
		termbox.SetCell(x+n, y-3, c, fg, bg)
	}

	fg = termbox.ColorBlack
	bg = termbox.ColorGreen
	for i := 0; i <= len(this.Martix); i++ {
		for t := 0; t < 6*len(this.Martix); t++ {
			if t%6 != 0 {
				termbox.SetCell(x+t, y+i*2, '-', fg, bg)
			}
		}
		for t := 0; t <= 2*len(this.Martix); t++ {
			if t%2 == 0 {
				termbox.SetCell(x+i*6, y+t, '+', fg, bg)
			} else {
				termbox.SetCell(x+i*6, y+t, '|', fg, bg)
			}
		}
	}

	for i, row := range this.Martix {
		for j, _ := range row {
			if this.Martix[i][j] > 0 {
				str := fmt.Sprintf("%-5d", this.Martix[i][j])
				for n, char := range str {
					if output_mode == termbox.Output256 {
						termbox.SetCell(x+j*6+1+n, y+i*2+1, char, 0x10+termbox.Attribute(this.Martix[i][j]%256), 0xe0-termbox.Attribute(this.Martix[i][j]*2%256))
					} else {
						termbox.SetCell(x+j*6+1+n, y+i*2+1, char, termbox.ColorWhite, termbox.ColorMagenta)
					}
				}
			}
		}
	}
	return termbox.Flush()
}

func converPrintStr(x, y int, str string, fg, bg termbox.Attribute) error {
	xx := x
	for n, c := range str {
		if c == '\n' {
			y++
			xx = x - n - 1
		}
		termbox.SetCell(xx+n, y, c, fg, bg)
	}
	return termbox.Flush()
}

func (t *Go2048) ListernKey() chan termbox.Event {
	//ev := termbox.PollEvent()
	event_queue := make(chan termbox.Event)
	go func() {
		for {
			event_queue <- termbox.PollEvent() // 开始监听键盘事件
		}
	}()
	return event_queue
}

func (t *Go2048) ActionAndReturnKey(event_queue chan termbox.Event) termbox.Key {
	for {
		ev := <-event_queue
		changed := false

		switch ev.Type {
		case termbox.EventKey:
			switch ev.Key {
			case termbox.KeyArrowUp:
				changed = t.GoUp()
			case termbox.KeyArrowDown:
				changed = t.GoDown()
			case termbox.KeyArrowLeft:
				changed = t.GoLeft()
			case termbox.KeyArrowRight:
				changed = t.GoRight()
			case termbox.KeyEsc, termbox.KeyEnter:
				changed = true
			default:
				changed = false
			}

			// 如果元素的值没有任何更改，则从新开始循环
			if !changed && t.CheckWinOrLose() {
				continue
			}

		case termbox.EventResize:
			x, y := termbox.Size()
			t.Init_termbox(x/2-10, y/2-4)
			continue
		case termbox.EventError:
			panic(ev.Err)
		}
		return ev.Key
	}
}

func main() {
	err := termbox.Init()
	if err != nil {
		panic(err)
	}
	defer termbox.Close()
	x, y := termbox.Size()

	output_mode = termbox.SetOutputMode(termbox.Output256)
	if output_mode != termbox.Output256 {
		termbox.SetOutputMode(termbox.OutputNormal)
	}

	martix.Init()
	var t Go2048
	t.Martix, _ = martix.Init_martix(MAX_LEN)
	t.AddNum(Add_NUM)
	step = 0
	ch := t.ListernKey()
	defer close(ch)

	for {
		t.Init_termbox(x/2-10, y/2-4)

		key := t.ActionAndReturnKey(ch)

		if t.CheckWinOrLose() == false {
			str := "Lose!"
			strlen := len(str)
			converPrintStr(x/2-strlen/2, y/2, str, termbox.ColorBlack, termbox.ColorRed)
			for {
				key = t.ActionAndReturnKey(ch)
				if key == termbox.KeyEnter || key == termbox.KeyEsc {
					break
				}
			}
		}

		if key == termbox.KeyEnter {
			t.Martix, _ = martix.Init_martix(MAX_LEN)
			step = -1
		}
		if key == termbox.KeyEsc {
			return
		}

		step++

		t.Init_termbox(x/2-10, y/2-4)
		time.Sleep(500 * time.Millisecond)
		t.AddNum(Add_NUM)
	}
}
<|endoftext|>


<commit_before>package kafka

import (
	"errors"
	"sync"
	"time"
)

// backend stores information about a given backend. All access to this data should be done
// through methods to ensure accurate counting and limiting.
type backend struct {
	conf    BrokerConf
	addr    string
	channel chan *connection

	// Used for storing links to all connections we ever make, this is a debugging
	// tool to try to help find leaks of connections. All access is protected by mu.
	mu        *sync.Mutex
	conns     []*connection
	counter   int
	debugTime time.Time
}

// getIdleConnection returns a connection if and only if there is an active, idle connection
// that already exists.
func (b *backend) GetIdleConnection() *connection {
	for {
		select {
		case conn := <-b.channel:
			if !conn.IsClosed() {
				return conn
			}
			b.removeConnection(conn)

		default:
			return nil
		}
	}
}

// GetConnection does a full connection logic: attempt to return an idle connection, if
// none are available then wait for up to the IdleConnectionWait time for one, else finally
// establish a new connection if we aren't at the limit. If we are, then continue waiting
// in increments of the idle time for a connection or the limit to come down before making
// a new connection. This could potentially block up to the DialTimeout.
func (b *backend) GetConnection() *connection {
	dialTimeout := time.After(b.conf.DialTimeout)
	for {
		select {
		case <-dialTimeout:
			return nil

		case conn := <-b.channel:
			if !conn.IsClosed() {
				return conn
			}
			b.removeConnection(conn)

		case <-time.After(time.Duration(rndIntn(int(b.conf.IdleConnectionWait)))):
			conn, err := b.getNewConnection()
			if err != nil {
				return nil
			} else if conn != nil {
				return conn
			}
		}
	}
}

// debugHitMaxConnections will potentially do some debugging output to help diagnose situations
// where we're hitting connection limits.
func (b *backend) debugHitMaxConnections() {
	b.mu.Lock()
	defer b.mu.Unlock()

	if time.Now().Before(b.debugTime) {
		return
	}
	b.debugTime = time.Now().Add(10 * time.Second)

	log.Warn("DEBUG: hit max connections",
		"counter", b.counter,
		"len(conns)", len(b.conns))
	for idx, conn := range b.conns {
		log.Warn("DEBUG", "connection",
			"idx", idx,
			"conn", conn,
			"closed", conn.IsClosed(),
			"age", time.Now().Sub(conn.StartTime()))
	}
}

// getNewConnection establishes a new connection if and only if we haven't hit the limit, else
// it will return nil. If an error is returned, we failed to connect to the server and should
// abort the flow. This takes a lock on the mutex which means we can only have a single new
// connection request in-flight at one time. Takes the mutex.
func (b *backend) getNewConnection() (*connection, error) {
	b.mu.Lock()
	defer b.mu.Unlock()

	if b.counter >= b.conf.ConnectionLimit {
		go b.debugHitMaxConnections()
		return nil, nil
	}

	log.Debug("making new connection", "addr", b.addr)
	conn, err := newTCPConnection(b.addr, b.conf.DialTimeout)
	if err != nil {
		log.Error("cannot connect", "addr", b.addr, "error", err)
		return nil, err
	}

	b.counter++
	b.conns = append(b.conns, conn)
	return conn, nil
}

// removeConnection removes the given connection from our tracking. It also decrements the
// open connection count. This takes the mutex.
func (b *backend) removeConnection(conn *connection) {
	b.mu.Lock()
	defer b.mu.Unlock()

	for idx, c := range b.conns {
		if c == conn {
			b.counter--
			b.conns = append(b.conns[0:idx], b.conns[idx+1:]...)
			return
		}
	}
	log.Error("unknown connection in removeConnection", "conn", conn)
}

// Idle is called when a connection should be returned to the store.
func (b *backend) Idle(conn *connection) {
	// If the connection is closed, throw it away. But if the connection pool is closed, then
	// close the connection.
	if conn.IsClosed() {
		b.removeConnection(conn)
		return
	}

	// If we're above the idle connection limit, discard the connection.
	if len(b.channel) >= b.conf.IdleConnectionLimit {
		conn.Close()
		b.removeConnection(conn)
		return
	}

	select {
	case b.channel <- conn:
		// Do nothing, connection was requeued.
	case <-time.After(b.conf.IdleConnectionWait):
		// The queue is full for a while, discard this connection.
		b.removeConnection(conn)
		conn.Close()
	}
}

// NumOpenConnections returns a counter of how may connections are open.
func (b *backend) NumOpenConnections() int {
	b.mu.Lock()
	defer b.mu.Unlock()

	return b.counter
}

// connectionPool is a way for us to manage multiple connections to a Kafka broker in a way
// that balances out throughput with overall number of connections.
type connectionPool struct {
	conf BrokerConf

	// mu protects the below members of this struct. This mutex must only be used by
	// connectionPool.
	mu       *sync.RWMutex
	closed   bool
	backends map[string]*backend
	addrs    []string
}

// newConnectionPool creates a connection pool and initializes it.
func newConnectionPool(conf BrokerConf) *connectionPool {
	return &connectionPool{
		conf:     conf,
		mu:       &sync.RWMutex{},
		backends: make(map[string]*backend),
		addrs:    make([]string, 0),
	}
}

// newBackend creates a new backend structure.
func (cp *connectionPool) newBackend(addr string) *backend {
	return &backend{
		mu:      &sync.Mutex{},
		conf:    cp.conf,
		addr:    addr,
		channel: make(chan *connection, cp.conf.IdleConnectionLimit),
	}
}

// getBackend fetches a channel for a given address. This takes the read lock. If no
// channel exists, nil is returned.
func (cp *connectionPool) getBackend(addr string) *backend {
	cp.mu.RLock()
	defer cp.mu.RUnlock()

	if cp.closed {
		return nil
	}

	if _, ok := cp.backends[addr]; !ok {
		return nil
	}
	return cp.backends[addr]
}

// getOrCreateBackend fetches a channel for a given address and, if one doesn't exist,
// creates it. This function takes the write lock against the pool.
func (cp *connectionPool) getOrCreateBackend(addr string) *backend {
	// Fast path: only gets a read lock
	if be := cp.getBackend(addr); be != nil {
		return be
	}

	// Did not exist, take the slow path and make a new backend
	cp.mu.Lock()
	defer cp.mu.Unlock()

	if cp.closed {
		return nil
	}

	if _, ok := cp.backends[addr]; !ok {
		cp.addrs = append(cp.addrs, addr)
		cp.backends[addr] = cp.newBackend(addr)
	}
	return cp.backends[addr]
}

// GetAllAddrs returns a slice of all addresses we've seen. Can be used for picking a random
// address or iterating the known brokers.
func (cp *connectionPool) GetAllAddrs() []string {
	cp.mu.RLock()
	defer cp.mu.RUnlock()

	ret := make([]string, len(cp.addrs))
	copy(ret, cp.addrs)
	return ret
}

// InitializeAddrs takes in a set of addresses and just sets up the structures for them. This
// doesn't start any connecting. This is done so that we have a set of addresses for other
// parts of the system to use.
func (cp *connectionPool) InitializeAddrs(addrs []string) {
	cp.mu.Lock()
	defer cp.mu.Unlock()

	for _, addr := range addrs {
		if _, ok := cp.backends[addr]; !ok {
			cp.addrs = append(cp.addrs, addr)
			cp.backends[addr] = cp.newBackend(addr)
		}
	}
}

// GetIdleConnection returns a random idle connection from the set of connections that we
// happen to have open. If no connections are available or idle, this returns nil.
func (cp *connectionPool) GetIdleConnection() *connection {
	addrs := cp.GetAllAddrs()

	for _, idx := range rndPerm(len(addrs)) {
		if be := cp.getOrCreateBackend(addrs[idx]); be != nil {
			if conn := be.GetIdleConnection(); conn != nil {
				return conn
			}
		}
	}
	return nil
}

// GetConnectionByAddr takes an address and returns a valid/open connection to this server.
// We attempt to reuse connections if we can, but if a connection is not available within
// IdleConnectionWait then we'll establish a new one. This can block a long time.
func (cp *connectionPool) GetConnectionByAddr(addr string) (*connection, error) {
	if cp.IsClosed() {
		return nil, errors.New("connection pool is closed")
	}

	if be := cp.getOrCreateBackend(addr); be != nil {
		if conn := be.GetConnection(); conn != nil {
			return conn, nil
		}
	}
	return nil, errors.New("failed to get connection")
}

// Close sets the connection pool's end state, no further connections will be returned
// and any existing connections will be closed out.
func (cp *connectionPool) Close() {
	cp.mu.Lock()
	defer cp.mu.Unlock()

	for _, backend := range cp.backends {
	Loop:
		for {
			select {
			case conn := <-backend.channel:
				defer conn.Close()
			default:
				break Loop
			}
		}
	}

	cp.closed = true
}

// IsClosed returns whether or not this pool is closed.
func (cp *connectionPool) IsClosed() bool {
	cp.mu.RLock()
	defer cp.mu.RUnlock()

	return cp.closed
}

// Idle takes a now idle connection and makes it available for other users. This should be
// called in a goroutine so as not to block the original caller, as this function may take
// some time to return.
func (cp *connectionPool) Idle(conn *connection) {
	if cp.IsClosed() {
		conn.Close()
		return
	}

	if be := cp.getOrCreateBackend(conn.addr); be != nil {
		be.Idle(conn)
	} else {
		conn.Close()
	}
}
<commit_msg>Do not block forever<commit_after>package kafka

import (
	"errors"
	"sync"
	"time"
)

// backend stores information about a given backend. All access to this data should be done
// through methods to ensure accurate counting and limiting.
type backend struct {
	conf    BrokerConf
	addr    string
	channel chan *connection

	// Used for storing links to all connections we ever make, this is a debugging
	// tool to try to help find leaks of connections. All access is protected by mu.
	mu        *sync.Mutex
	conns     []*connection
	counter   int
	debugTime time.Time
}

// getIdleConnection returns a connection if and only if there is an active, idle connection
// that already exists.
func (b *backend) GetIdleConnection() *connection {
	for {
		select {
		case conn := <-b.channel:
			if !conn.IsClosed() {
				return conn
			}
			b.removeConnection(conn)

		default:
			return nil
		}
	}
}

// GetConnection does a full connection logic: attempt to return an idle connection, if
// none are available then wait for up to the IdleConnectionWait time for one, else finally
// establish a new connection if we aren't at the limit. If we are, then continue waiting
// in increments of the idle time for a connection or the limit to come down before making
// a new connection. This could potentially block up to the DialTimeout.
func (b *backend) GetConnection() *connection {
	dialTimeout := time.After(b.conf.DialTimeout)
	for {
		select {
		case <-dialTimeout:
			return nil

		case conn := <-b.channel:
			if !conn.IsClosed() {
				return conn
			}
			b.removeConnection(conn)

		case <-time.After(time.Duration(rndIntn(int(b.conf.IdleConnectionWait)))):
			conn, err := b.getNewConnection()
			if err != nil {
				return nil
			} else if conn != nil {
				return conn
			}
		}
	}
}

// debugHitMaxConnections will potentially do some debugging output to help diagnose situations
// where we're hitting connection limits.
func (b *backend) debugHitMaxConnections() {
	b.mu.Lock()
	defer b.mu.Unlock()

	if time.Now().Before(b.debugTime) {
		return
	}
	b.debugTime = time.Now().Add(10 * time.Second)

	log.Warn("DEBUG: hit max connections",
		"counter", b.counter,
		"len(conns)", len(b.conns))
	for idx, conn := range b.conns {
		log.Warn("DEBUG: connection",
			"idx", idx,
			"conn", conn,
			"closed", conn.IsClosed(),
			"age", time.Now().Sub(conn.StartTime()))
	}
}

// getNewConnection establishes a new connection if and only if we haven't hit the limit, else
// it will return nil. If an error is returned, we failed to connect to the server and should
// abort the flow. This takes a lock on the mutex which means we can only have a single new
// connection request in-flight at one time. Takes the mutex.
func (b *backend) getNewConnection() (*connection, error) {
	b.mu.Lock()
	defer b.mu.Unlock()

	if b.counter >= b.conf.ConnectionLimit {
		go b.debugHitMaxConnections()
		return nil, nil
	}

	// Be careful about the situation where newTCPConnection could never return, so
	// we want to always make sure getNewConnection eventually returns. Else, we can
	// lose the connection pool.

	type connResult struct {
		conn *connection
		err  error
	}
	connChan := make(chan connResult, 1)

	go func() {
		log.Debug("making new connection", "addr", b.addr)
		if conn, err := newTCPConnection(b.addr, b.conf.DialTimeout); err != nil {
			log.Error("cannot connect", "addr", b.addr, "error", err)
			connChan <- connResult{nil, err}
		} else {
			connChan <- connResult{conn, nil}
		}
	}()

	select {
	case <-time.After(b.conf.DialTimeout):
		log.Error("DEBUG: timeout waiting for dial", "addr", b.addr)
		return nil, nil

	case result := <-connChan:
		if result.err != nil {
			return nil, result.err
		} else {
			b.counter++
			b.conns = append(b.conns, result.conn)
			return result.conn, nil
		}
	}

}

// removeConnection removes the given connection from our tracking. It also decrements the
// open connection count. This takes the mutex.
func (b *backend) removeConnection(conn *connection) {
	b.mu.Lock()
	defer b.mu.Unlock()

	for idx, c := range b.conns {
		if c == conn {
			b.counter--
			b.conns = append(b.conns[0:idx], b.conns[idx+1:]...)
			return
		}
	}
	log.Error("unknown connection in removeConnection", "conn", conn)
}

// Idle is called when a connection should be returned to the store.
func (b *backend) Idle(conn *connection) {
	// If the connection is closed, throw it away. But if the connection pool is closed, then
	// close the connection.
	if conn.IsClosed() {
		b.removeConnection(conn)
		return
	}

	// If we're above the idle connection limit, discard the connection.
	if len(b.channel) >= b.conf.IdleConnectionLimit {
		conn.Close()
		b.removeConnection(conn)
		return
	}

	select {
	case b.channel <- conn:
		// Do nothing, connection was requeued.
	case <-time.After(b.conf.IdleConnectionWait):
		// The queue is full for a while, discard this connection.
		b.removeConnection(conn)
		conn.Close()
	}
}

// NumOpenConnections returns a counter of how may connections are open.
func (b *backend) NumOpenConnections() int {
	b.mu.Lock()
	defer b.mu.Unlock()

	return b.counter
}

// connectionPool is a way for us to manage multiple connections to a Kafka broker in a way
// that balances out throughput with overall number of connections.
type connectionPool struct {
	conf BrokerConf

	// mu protects the below members of this struct. This mutex must only be used by
	// connectionPool.
	mu       *sync.RWMutex
	closed   bool
	backends map[string]*backend
	addrs    []string
}

// newConnectionPool creates a connection pool and initializes it.
func newConnectionPool(conf BrokerConf) *connectionPool {
	return &connectionPool{
		conf:     conf,
		mu:       &sync.RWMutex{},
		backends: make(map[string]*backend),
		addrs:    make([]string, 0),
	}
}

// newBackend creates a new backend structure.
func (cp *connectionPool) newBackend(addr string) *backend {
	return &backend{
		mu:      &sync.Mutex{},
		conf:    cp.conf,
		addr:    addr,
		channel: make(chan *connection, cp.conf.IdleConnectionLimit),
	}
}

// getBackend fetches a channel for a given address. This takes the read lock. If no
// channel exists, nil is returned.
func (cp *connectionPool) getBackend(addr string) *backend {
	cp.mu.RLock()
	defer cp.mu.RUnlock()

	if cp.closed {
		return nil
	}

	if _, ok := cp.backends[addr]; !ok {
		return nil
	}
	return cp.backends[addr]
}

// getOrCreateBackend fetches a channel for a given address and, if one doesn't exist,
// creates it. This function takes the write lock against the pool.
func (cp *connectionPool) getOrCreateBackend(addr string) *backend {
	// Fast path: only gets a read lock
	if be := cp.getBackend(addr); be != nil {
		return be
	}

	// Did not exist, take the slow path and make a new backend
	cp.mu.Lock()
	defer cp.mu.Unlock()

	if cp.closed {
		return nil
	}

	if _, ok := cp.backends[addr]; !ok {
		cp.addrs = append(cp.addrs, addr)
		cp.backends[addr] = cp.newBackend(addr)
	}
	return cp.backends[addr]
}

// GetAllAddrs returns a slice of all addresses we've seen. Can be used for picking a random
// address or iterating the known brokers.
func (cp *connectionPool) GetAllAddrs() []string {
	cp.mu.RLock()
	defer cp.mu.RUnlock()

	ret := make([]string, len(cp.addrs))
	copy(ret, cp.addrs)
	return ret
}

// InitializeAddrs takes in a set of addresses and just sets up the structures for them. This
// doesn't start any connecting. This is done so that we have a set of addresses for other
// parts of the system to use.
func (cp *connectionPool) InitializeAddrs(addrs []string) {
	cp.mu.Lock()
	defer cp.mu.Unlock()

	for _, addr := range addrs {
		if _, ok := cp.backends[addr]; !ok {
			cp.addrs = append(cp.addrs, addr)
			cp.backends[addr] = cp.newBackend(addr)
		}
	}
}

// GetIdleConnection returns a random idle connection from the set of connections that we
// happen to have open. If no connections are available or idle, this returns nil.
func (cp *connectionPool) GetIdleConnection() *connection {
	addrs := cp.GetAllAddrs()

	for _, idx := range rndPerm(len(addrs)) {
		if be := cp.getOrCreateBackend(addrs[idx]); be != nil {
			if conn := be.GetIdleConnection(); conn != nil {
				return conn
			}
		}
	}
	return nil
}

// GetConnectionByAddr takes an address and returns a valid/open connection to this server.
// We attempt to reuse connections if we can, but if a connection is not available within
// IdleConnectionWait then we'll establish a new one. This can block a long time.
func (cp *connectionPool) GetConnectionByAddr(addr string) (*connection, error) {
	if cp.IsClosed() {
		return nil, errors.New("connection pool is closed")
	}

	if be := cp.getOrCreateBackend(addr); be != nil {
		if conn := be.GetConnection(); conn != nil {
			return conn, nil
		}
	}
	return nil, errors.New("failed to get connection")
}

// Close sets the connection pool's end state, no further connections will be returned
// and any existing connections will be closed out.
func (cp *connectionPool) Close() {
	cp.mu.Lock()
	defer cp.mu.Unlock()

	for _, backend := range cp.backends {
	Loop:
		for {
			select {
			case conn := <-backend.channel:
				defer conn.Close()
			default:
				break Loop
			}
		}
	}

	cp.closed = true
}

// IsClosed returns whether or not this pool is closed.
func (cp *connectionPool) IsClosed() bool {
	cp.mu.RLock()
	defer cp.mu.RUnlock()

	return cp.closed
}

// Idle takes a now idle connection and makes it available for other users. This should be
// called in a goroutine so as not to block the original caller, as this function may take
// some time to return.
func (cp *connectionPool) Idle(conn *connection) {
	if cp.IsClosed() {
		conn.Close()
		return
	}

	if be := cp.getOrCreateBackend(conn.addr); be != nil {
		be.Idle(conn)
	} else {
		conn.Close()
	}
}
<|endoftext|>


<commit_before>package nats

import (
	"io"
	"net"
	"testing"
	"bytes"
	"time"
)

type FakeAddr int

func (fa FakeAddr) Network() string {
	panic("FakeAddr#Network")
}

func (fa FakeAddr) String() string {
	panic("FakeAddr#String")
}

type FakeConnection struct {
	rin  *io.PipeReader
	win  *io.PipeWriter
	rout *io.PipeReader
	wout *io.PipeWriter
}

func NewFakeConnection() *FakeConnection {
	var fc FakeConnection

	fc.rin, fc.wout = io.Pipe()
	fc.rout, fc.win = io.Pipe()

	return &fc
}

func (fc *FakeConnection) Read(b []byte) (n int, err error) {
	return fc.rin.Read(b)
}

func (fc *FakeConnection) Write(b []byte) (n int, err error) {
	return fc.win.Write(b)
}

func (fc *FakeConnection) Close() error {
	err1 := fc.rin.Close()
	err2 := fc.win.Close()

	if err1 != nil {
		panic(err1)
	}

	if err2 != nil {
		panic(err2)
	}

	return nil
}

func (fc *FakeConnection) LocalAddr() net.Addr {
	var fa FakeAddr
	return fa
}

func (fc *FakeConnection) RemoteAddr() net.Addr {
	var fa FakeAddr
	return fa
}

func (fc *FakeConnection) SetDeadline(t time.Time) error {
	return nil
}

func (fc *FakeConnection) SetReadDeadline(t time.Time) error {
	return nil
}

func (fc *FakeConnection) SetWriteDeadline(t time.Time) error {
	return nil
}

func writePingReadPong(t *testing.T, fc *FakeConnection) {
	var err error

	// Write PING
	_, err = fc.wout.Write([]byte("ping\r\n"))

	if err != nil {
		t.Errorf("\nerror: %#v\n", err)
		return
	}

	// Read PONG
	var buf []byte
	var n int

	buf = make([]byte, 16)
	n, err = fc.rout.Read(buf)

	if err != nil {
		t.Errorf("\nerror: %#v\n", err)
		return
	}

	var expected []byte = []byte("pong\r\n")
	var actual []byte = bytes.ToLower(buf[0:n])
	if !bytes.Equal(expected, actual) {
		t.Errorf("\nexpected: %#v\ngot: %#v\n", string(expected), string(actual))
		return
	}
}

func TestConnectionPongOnPing(t *testing.T) {
	var c = NewConnection()
	var fc = NewFakeConnection()
	var done = make(chan bool)

	go func() {
		c.Run(fc)
		done <- true
	}()

	writePingReadPong(t, fc)

	// Close connection
	fc.Close()

	// Wait for goroutine
	<-done
}
<commit_msg>Also close test-side of pipe for FakeConnection<commit_after>package nats

import (
	"io"
	"net"
	"testing"
	"bytes"
	"time"
)

type FakeAddr int

func (fa FakeAddr) Network() string {
	panic("FakeAddr#Network")
}

func (fa FakeAddr) String() string {
	panic("FakeAddr#String")
}

type FakeConnection struct {
	rin  *io.PipeReader
	win  *io.PipeWriter
	rout *io.PipeReader
	wout *io.PipeWriter
}

func NewFakeConnection() *FakeConnection {
	var fc FakeConnection

	fc.rin, fc.wout = io.Pipe()
	fc.rout, fc.win = io.Pipe()

	return &fc
}

func (fc *FakeConnection) Read(b []byte) (n int, err error) {
	return fc.rin.Read(b)
}

func (fc *FakeConnection) Write(b []byte) (n int, err error) {
	return fc.win.Write(b)
}

func (fc *FakeConnection) Close() error {
	var err error

	err = fc.rin.Close()
	if err != nil {
		panic(err)
	}

	err = fc.win.Close()
	if err != nil {
		panic(err)
	}

	err = fc.rout.Close()
	if err != nil {
		panic(err)
	}

	err = fc.wout.Close()
	if err != nil {
		panic(err)
	}

	return nil
}

func (fc *FakeConnection) LocalAddr() net.Addr {
	var fa FakeAddr
	return fa
}

func (fc *FakeConnection) RemoteAddr() net.Addr {
	var fa FakeAddr
	return fa
}

func (fc *FakeConnection) SetDeadline(t time.Time) error {
	return nil
}

func (fc *FakeConnection) SetReadDeadline(t time.Time) error {
	return nil
}

func (fc *FakeConnection) SetWriteDeadline(t time.Time) error {
	return nil
}

func writePingReadPong(t *testing.T, fc *FakeConnection) {
	var err error

	// Write PING
	_, err = fc.wout.Write([]byte("ping\r\n"))

	if err != nil {
		t.Errorf("\nerror: %#v\n", err)
		return
	}

	// Read PONG
	var buf []byte
	var n int

	buf = make([]byte, 16)
	n, err = fc.rout.Read(buf)

	if err != nil {
		t.Errorf("\nerror: %#v\n", err)
		return
	}

	var expected []byte = []byte("pong\r\n")
	var actual []byte = bytes.ToLower(buf[0:n])
	if !bytes.Equal(expected, actual) {
		t.Errorf("\nexpected: %#v\ngot: %#v\n", string(expected), string(actual))
		return
	}
}

func TestConnectionPongOnPing(t *testing.T) {
	var c = NewConnection()
	var fc = NewFakeConnection()
	var done = make(chan bool)

	go func() {
		c.Run(fc)
		done <- true
	}()

	writePingReadPong(t, fc)

	// Close connection
	fc.Close()

	// Wait for goroutine
	<-done
}
<|endoftext|>


<commit_before>package hdhomerun

import (
	"net"
	"reflect"
	"sync"
	"testing"
)

func TestTCPConnection(t *testing.T) {
	tests := []struct {
		txPackets []*Packet
		rxPackets []*Packet
	}{
		{
			txPackets: []*Packet{getReq.p},
			rxPackets: []*Packet{getRpy.p},
		},
	}

	for _, test := range tests {
		var wg sync.WaitGroup
		listener, _ := net.ListenTCP("tcp", &net.TCPAddr{net.IP{127, 0, 0, 1}, 65001, ""})

		wg.Add(1)
		go func() {
			conn, _ := listener.Accept()
			io := NewIOConnection(conn)
			for i, expectedTx := range test.txPackets {
				receivedTx, _ := io.Recv()
				if !reflect.DeepEqual(expectedTx, receivedTx) {
					t.Errorf("Expected:\n%s\nGot:\n%s\n", expectedTx.Dump(), receivedTx.Dump())
				}
				io.Send(test.rxPackets[i])
			}
			conn.Close()
			wg.Done()
		}()

		d := NewDevice(NewTCPConnection(&net.TCPAddr{net.IP{127, 0, 0, 1}, 65001, ""}), []byte{1, 2, 3, 4})
		d.Connect()
		for i, expectedRx := range test.rxPackets {
			d.Send(test.txPackets[i])
			receivedRx, _ := d.Recv()
			if !reflect.DeepEqual(expectedRx, receivedRx) {
				t.Errorf("Expected:\n%s\nGot:\n%s\n", expectedRx.Dump(), receivedRx.Dump())
			}
		}
		d.Close()
		wg.Wait()
	}
}
<commit_msg>Device no longer stores ID<commit_after>package hdhomerun

import (
	"net"
	"reflect"
	"sync"
	"testing"
)

func TestTCPConnection(t *testing.T) {
	tests := []struct {
		txPackets []*Packet
		rxPackets []*Packet
	}{
		{
			txPackets: []*Packet{getReq.p},
			rxPackets: []*Packet{getRpy.p},
		},
	}

	for _, test := range tests {
		var wg sync.WaitGroup
		listener, _ := net.ListenTCP("tcp", &net.TCPAddr{net.IP{127, 0, 0, 1}, 65001, ""})

		wg.Add(1)
		go func() {
			conn, _ := listener.Accept()
			io := NewIOConnection(conn)
			for i, expectedTx := range test.txPackets {
				receivedTx, _ := io.Recv()
				if !reflect.DeepEqual(expectedTx, receivedTx) {
					t.Errorf("Expected:\n%s\nGot:\n%s\n", expectedTx.Dump(), receivedTx.Dump())
				}
				io.Send(test.rxPackets[i])
			}
			conn.Close()
			wg.Done()
		}()

		d := NewDevice(NewTCPConnection(&net.TCPAddr{net.IP{127, 0, 0, 1}, 65001, ""}))
		d.Connect()
		for i, expectedRx := range test.rxPackets {
			d.Send(test.txPackets[i])
			receivedRx, _ := d.Recv()
			if !reflect.DeepEqual(expectedRx, receivedRx) {
				t.Errorf("Expected:\n%s\nGot:\n%s\n", expectedRx.Dump(), receivedRx.Dump())
			}
		}
		d.Close()
		wg.Wait()
	}
}
<|endoftext|>


<commit_before>package amqp

import (
	"log"
	"net"
	"sync"
	"testing"
)

func TestChannelOpenOnAClosedConnectionFails(t *testing.T) {
	conn, err := Dial("amqp://guest:guest@localhost:5672/")
	if err != nil {
		log.Fatalf("Could't connect to RabbitMQ at localhost:5672, err = %s", err)
	}
	conn.Close()

	_, err = conn.Channel()
	if err != ErrClosed {
		log.Fatalf("channel.open on a closed connection %s is expected to fail", conn)
	}
}

func TestQueueDeclareOnAClosedConnectionFails(t *testing.T) {
	conn, err := Dial("amqp://guest:guest@localhost:5672/")
	if err != nil {
		log.Fatalf("Could't connect to RabbitMQ at localhost:5672, err = %s", err)
	}
	ch, _ := conn.Channel()

	conn.Close()

	_, err = ch.QueueDeclare("an example", false, false, false, false, nil)
	if err != ErrClosed {
		log.Fatalf("queue.declare on a closed connection %s is expected to fail", conn)
	}
}

func TestConcurrentClose(t *testing.T) {
	conn, err := Dial("amqp://guest:guest@localhost:5672/")
	if err != nil {
		log.Fatalf("Could't connect to amqp server, err = %s", err)
	}

	n := 32
	wg := sync.WaitGroup{}
	wg.Add(n)
	for i := 0; i < n; i++ {
		go func() {
			err := conn.Close()
			if err != nil && err != ErrClosed {
				switch err.(type) {
				case *Error:
					log.Fatalf("Expected no error, or ErrClosed, or a net.OpError from conn.Close(), got %#v (%#v) of type %T", err, err.Error(), err)
				case *net.OpError:
					// this is acceptable: we got a net.OpError
					// before the connection was marked as closed
					break;
				}

			}
			wg.Done()
		}()
	}
	wg.Wait()
}
<commit_msg>Treat connection tests as integration tests<commit_after>// Copyright (c) 2016, Sean Treadway, SoundCloud Ltd.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Source code and contact info at http://github.com/streadway/amqp

// +build integration

package amqp

import (
	"net"
	"sync"
	"testing"
)

func TestChannelOpenOnAClosedConnectionFails(t *testing.T) {
	conn := integrationConnection(t, "channel on close")

	conn.Close()

	if _, err := conn.Channel(); err != ErrClosed {
		t.Fatalf("channel.open on a closed connection %s is expected to fail", conn)
	}
}

func TestQueueDeclareOnAClosedConnectionFails(t *testing.T) {
	conn := integrationConnection(t, "queue declare on close")
	ch, _ := conn.Channel()

	conn.Close()

	if _, err := ch.QueueDeclare("an example", false, false, false, false, nil); err != ErrClosed {
		t.Fatalf("queue.declare on a closed connection %s is expected to return ErrClosed, returned: %#v", conn, err)
	}
}

func TestConcurrentClose(t *testing.T) {
	const concurrency = 32

	conn := integrationConnection(t, "concurrent close")
	defer conn.Close()

	wg := sync.WaitGroup{}
	wg.Add(concurrency)
	for i := 0; i < concurrency; i++ {
		go func() {
			defer wg.Done()

			err := conn.Close()

			if err == nil {
				t.Log("first concurrent close was successful")
				return
			}

			if err == ErrClosed {
				t.Log("later concurrent close were successful and returned ErrClosed")
				return
			}

			// BUG(st) is this really acceptable? we got a net.OpError before the
			// connection was marked as closed means a race condition between the
			// network connection and handshake state. It should be a package error
			// returned.
			if _, neterr := err.(*net.OpError); neterr {
				t.Log("unknown net.OpError during close, ignoring: %+v", err)
				return
			}

			// A different/protocol error occured indicating a race or missed condition
			if _, other := err.(*Error); other {
				t.Fatalf("Expected no error, or ErrClosed, or a net.OpError from conn.Close(), got %#v (%s) of type %T", err, err, err)
			}
		}()
	}
	wg.Wait()
}
<|endoftext|>


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

package main

import (
	"github.com/ligato/cn-infra.bak/logging/logrus"
	"github.com/ligato/cn-infra/logging"
)

// create logger instance
var logger = log.New()

func init() {
	logger.SetLevel(logging.DebugLevel)
	// set formatter
	logger.SetFormatter(log.NewCustomFormatter())
}

func main() {

	// assign a tag for the current go routine
	logger.SetTag("main-thread")

	// setup fields that will be added to all subsequent log entries
	logger.SetStaticFields(map[string]interface{}{"component": "componentXY", "key": "value"})

	logger.WithFields(log.Fields{
		"CM_IP": "10.1.10",
	}).Debug("Cable modem is online")

	logger.Warn("This should not be happening.")

	logger.WithFields(log.Fields{
		"errCode":       42,
		"retryAttempts": 122,
		"string":        "quoted",
	}).Error("The connection failed!")

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

package main

import (
	"github.com/ligato/cn-infra/logging"
	"github.com/ligato/cn-infra/logging/logrus"
)

// create logger instance
var logger = log.New()

func init() {
	logger.SetLevel(logging.DebugLevel)
	// set formatter
	logger.SetFormatter(log.NewCustomFormatter())
}

func main() {

	// assign a tag for the current go routine
	logger.SetTag("main-thread")

	// setup fields that will be added to all subsequent log entries
	logger.SetStaticFields(map[string]interface{}{"component": "componentXY", "key": "value"})

	logger.WithFields(log.Fields{
		"CM_IP": "10.1.10",
	}).Debug("Cable modem is online")

	logger.Warn("This should not be happening.")

	logger.WithFields(log.Fields{
		"errCode":       42,
		"retryAttempts": 122,
		"string":        "quoted",
	}).Error("The connection failed!")

}
<|endoftext|>


<commit_before>// Copyright (c) 2003-2005 Maxim Sobolev. All rights reserved.
// Copyright (c) 2006-2014 Sippy Software, Inc. All rights reserved.
// Copyright (c) 2016 Andriy Pylypenko. All rights reserved.
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this
// list of conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation and/or
// other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
package sippy

import (
    "crypto/rand"
    "fmt"
    "math/big"
    "runtime"
    "sync"

    "sippy/conf"
    "sippy/sdp"
    "sippy/types"
)

type Rtp_proxy_session struct {
    caller_session_exists   bool
    call_id                 string
    from_tag                string
    to_tag                  string
    rtp_proxy_client        sippy_types.RtpProxyClient
    max_index               int
    l4r                     *local4remote
    notify_socket           string
    notify_tag              string
    insert_nortpp           bool
    caller                  _rtpps_side
    callee                  _rtpps_side
    session_lock            sync.Locker
    config                  sippy_conf.Config
}

type rtpproxy_update_result struct {
    rtpproxy_address    string
    rtpproxy_port       string
    family              string
    sendonly            bool
}

func (self *rtpproxy_update_result) Address() string {
    return self.rtpproxy_address
}

func NewRtp_proxy_session(config sippy_conf.Config, rtp_proxy_clients []sippy_types.RtpProxyClient, call_id, from_tag, to_tag, notify_socket, notify_tag string, session_lock sync.Locker, callee_origin *sippy_sdp.SdpOrigin) (*Rtp_proxy_session, error) {
    self := &Rtp_proxy_session{
        notify_socket   : notify_socket,
        notify_tag      : notify_tag,
        call_id         : call_id,
        from_tag        : from_tag,
        to_tag          : to_tag,
        insert_nortpp   : false,
        max_index       : -1,
        session_lock    : session_lock,
        config          : config,
    }
    self.caller.otherside = &self.callee
    self.callee.otherside = &self.caller
    self.caller.owner = self
    self.callee.owner = self
    self.caller.session_exists = false
    self.callee.session_exists = false
    // RFC4566
    // *******
    // For privacy reasons, it is sometimes desirable to obfuscate the
    // username and IP address of the session originator.  If this is a
    // concern, an arbitrary <username> and private <unicast-address> MAY be
    // chosen to populate the "o=" field, provided that these are selected
    // in a manner that does not affect the global uniqueness of the field.
    // *******
    addr := "192.0.2.1" // 192.0.2.0/24 (TEST-NET-1)
    self.caller.origin, _ = sippy_sdp.NewSdpOrigin(addr)
    if callee_origin != nil {
        self.callee.origin = callee_origin.GetCopy()
        // New session means new RTP port so the SDP is now different and the SDP
        // version must be increased.
        self.callee.origin.IncVersion()
    } else {
        self.callee.origin, _ = sippy_sdp.NewSdpOrigin(addr)
    }
    online_clients := []sippy_types.RtpProxyClient{}
    for _, cl := range rtp_proxy_clients {
        if cl.IsOnline() {
            online_clients = append(online_clients, cl)
        }
    }
    n := len(online_clients)
    if n == 0 {
        return nil, fmt.Errorf("No online RTP proxy client has been found")
    }
    idx, err := rand.Int(rand.Reader, big.NewInt(int64(n)))
    if err != nil {
        self.rtp_proxy_client = online_clients[0]
    } else {
        self.rtp_proxy_client = online_clients[idx.Int64()]
    }
    if self.call_id == "" {
        buf := make([]byte, 16)
        rand.Read(buf)
        self.call_id = fmt.Sprintf("%x", buf)
    }
    if from_tag == "" {
        buf := make([]byte, 16)
        rand.Read(buf)
        self.from_tag = fmt.Sprintf("%x", buf)
    }
    if to_tag == "" {
        buf := make([]byte, 16)
        rand.Read(buf)
        self.to_tag = fmt.Sprintf("%x", buf)
    }
    runtime.SetFinalizer(self, rtp_proxy_session_destructor)
    return self, nil
}
/*
    def version(self, result_callback):
        self.rtp_proxy_client.SendCommand("V", self.version_result, result_callback)

    def version_result(self, result, result_callback):
        result_callback(result)
*/
func (self *Rtp_proxy_session) PlayCaller(prompt_name string, times int/*= 1*/, result_callback func(string)/*= nil*/, index int /*= 0*/) {
    self.caller._play(prompt_name, times, result_callback, index)
}

func (self *Rtp_proxy_session) StopPlayCaller(result_callback func(string)/*= nil*/, index int/*= 0*/) {
    if ! self.caller_session_exists {
        return
    }
    command := fmt.Sprintf("S %s-%d %s %s", self.call_id, index, self.from_tag, self.to_tag)
    self.rtp_proxy_client.SendCommand(command, func(r string) { self.command_result(r, result_callback) }, self.session_lock)
}

func (self *Rtp_proxy_session) StartRecording(rname/*= nil*/ string, result_callback func(string)/*= nil*/, index int/*= 0*/) {
    if ! self.caller.session_exists {
        self.caller.update("0.0.0.0", "0", func(*rtpproxy_update_result) { self._start_recording(rname, result_callback, index) }, "", index, "IP4")
        return
    }
    self._start_recording(rname, result_callback, index)
}

func (self *Rtp_proxy_session) _start_recording(rname string, result_callback func(string), index int) {
    if rname == "" {
        command := fmt.Sprintf("R %s-%d %s %s", self.call_id, index, self.from_tag, self.to_tag)
        self.rtp_proxy_client.SendCommand(command, func (r string) { self.command_result(r, result_callback) }, self.session_lock)
        return
    }
    command := fmt.Sprintf("C %s-%d %s.a %s %s", self.call_id, index, rname, self.from_tag, self.to_tag)
    self.rtp_proxy_client.SendCommand(command, func(string) { self._start_recording1(rname, result_callback, index) }, self.session_lock)
}

func (self *Rtp_proxy_session) _start_recording1(rname string, result_callback func(string), index int) {
    command := fmt.Sprintf("C %s-%d %s.o %s %s", self.call_id, index, rname, self.to_tag, self.from_tag)
    self.rtp_proxy_client.SendCommand(command, func (r string) { self.command_result(r, result_callback) }, self.session_lock)
}

func (self *Rtp_proxy_session) command_result(result string, result_callback func(string)) {
    //print "%s.command_result(%s)" % (id(self), result)
    if result_callback != nil {
        result_callback(result)
    }
}

func (self *Rtp_proxy_session) Delete() {
    if self.rtp_proxy_client == nil {
        return
    }
    for self.max_index >= 0 {
        command := fmt.Sprintf("D %s-%d %s %s", self.call_id, self.max_index, self.from_tag, self.to_tag)
        self.rtp_proxy_client.SendCommand(command, nil, self.session_lock)
        self.max_index--
    }
    self.rtp_proxy_client = nil
}

func (self *Rtp_proxy_session) OnCallerSdpChange(sdp_body sippy_types.MsgBody, cc_event sippy_types.CCEvent, result_callback func(sippy_types.MsgBody)) error {
    return self.caller._on_sdp_change(sdp_body, result_callback)
}

func (self *Rtp_proxy_session) OnCalleeSdpChange(sdp_body sippy_types.MsgBody, msg sippy_types.SipMsg, result_callback func(sippy_types.MsgBody)) error {
    return self.callee._on_sdp_change(sdp_body, result_callback)
}

func rtp_proxy_session_destructor(self *Rtp_proxy_session) {
    self.Delete()
}

func (self *Rtp_proxy_session) CallerSessionExists() bool { return self.caller_session_exists }

func (self *Rtp_proxy_session) SetCallerLaddress(addr string) {
    self.caller.laddress = addr
}

func (self *Rtp_proxy_session) SetCallerRaddress(addr *sippy_conf.HostPort) {
    self.caller.raddress = addr
}

func (self *Rtp_proxy_session) SetCalleeLaddress(addr string) {
    self.callee.laddress = addr
}

func (self *Rtp_proxy_session) SetCalleeRaddress(addr *sippy_conf.HostPort) {
    self.callee.raddress = addr
}

func (self *Rtp_proxy_session) SetInsertNortpp(v bool) {
    self.insert_nortpp = v
}

func (self *Rtp_proxy_session) SetAfterCallerSdpChange(cb func(sippy_types.RtpProxyUpdateResult)) {
    self.caller.after_sdp_change = cb
}

func (self *Rtp_proxy_session) CalleeOrigin() *sippy_sdp.SdpOrigin {
    if self == nil {
        return nil
    }
    return self.callee.origin
}
<commit_msg>Prevent race condition when the RTP session already deleted and after that another command is to be sent.<commit_after>// Copyright (c) 2003-2005 Maxim Sobolev. All rights reserved.
// Copyright (c) 2006-2014 Sippy Software, Inc. All rights reserved.
// Copyright (c) 2016 Andriy Pylypenko. All rights reserved.
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this
// list of conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation and/or
// other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
package sippy

import (
    "crypto/rand"
    "fmt"
    "math/big"
    "runtime"
    "sync"

    "sippy/conf"
    "sippy/sdp"
    "sippy/types"
)

type Rtp_proxy_session struct {
    caller_session_exists   bool
    call_id                 string
    from_tag                string
    to_tag                  string
    rtp_proxy_client        sippy_types.RtpProxyClient
    max_index               int
    l4r                     *local4remote
    notify_socket           string
    notify_tag              string
    insert_nortpp           bool
    caller                  _rtpps_side
    callee                  _rtpps_side
    session_lock            sync.Locker
    config                  sippy_conf.Config
}

type rtpproxy_update_result struct {
    rtpproxy_address    string
    rtpproxy_port       string
    family              string
    sendonly            bool
}

func (self *rtpproxy_update_result) Address() string {
    return self.rtpproxy_address
}

func NewRtp_proxy_session(config sippy_conf.Config, rtp_proxy_clients []sippy_types.RtpProxyClient, call_id, from_tag, to_tag, notify_socket, notify_tag string, session_lock sync.Locker, callee_origin *sippy_sdp.SdpOrigin) (*Rtp_proxy_session, error) {
    self := &Rtp_proxy_session{
        notify_socket   : notify_socket,
        notify_tag      : notify_tag,
        call_id         : call_id,
        from_tag        : from_tag,
        to_tag          : to_tag,
        insert_nortpp   : false,
        max_index       : -1,
        session_lock    : session_lock,
        config          : config,
    }
    self.caller.otherside = &self.callee
    self.callee.otherside = &self.caller
    self.caller.owner = self
    self.callee.owner = self
    self.caller.session_exists = false
    self.callee.session_exists = false
    // RFC4566
    // *******
    // For privacy reasons, it is sometimes desirable to obfuscate the
    // username and IP address of the session originator.  If this is a
    // concern, an arbitrary <username> and private <unicast-address> MAY be
    // chosen to populate the "o=" field, provided that these are selected
    // in a manner that does not affect the global uniqueness of the field.
    // *******
    addr := "192.0.2.1" // 192.0.2.0/24 (TEST-NET-1)
    self.caller.origin, _ = sippy_sdp.NewSdpOrigin(addr)
    if callee_origin != nil {
        self.callee.origin = callee_origin.GetCopy()
        // New session means new RTP port so the SDP is now different and the SDP
        // version must be increased.
        self.callee.origin.IncVersion()
    } else {
        self.callee.origin, _ = sippy_sdp.NewSdpOrigin(addr)
    }
    online_clients := []sippy_types.RtpProxyClient{}
    for _, cl := range rtp_proxy_clients {
        if cl.IsOnline() {
            online_clients = append(online_clients, cl)
        }
    }
    n := len(online_clients)
    if n == 0 {
        return nil, fmt.Errorf("No online RTP proxy client has been found")
    }
    idx, err := rand.Int(rand.Reader, big.NewInt(int64(n)))
    if err != nil {
        self.rtp_proxy_client = online_clients[0]
    } else {
        self.rtp_proxy_client = online_clients[idx.Int64()]
    }
    if self.call_id == "" {
        buf := make([]byte, 16)
        rand.Read(buf)
        self.call_id = fmt.Sprintf("%x", buf)
    }
    if from_tag == "" {
        buf := make([]byte, 16)
        rand.Read(buf)
        self.from_tag = fmt.Sprintf("%x", buf)
    }
    if to_tag == "" {
        buf := make([]byte, 16)
        rand.Read(buf)
        self.to_tag = fmt.Sprintf("%x", buf)
    }
    runtime.SetFinalizer(self, rtp_proxy_session_destructor)
    return self, nil
}
/*
    def version(self, result_callback):
        self.send_command("V", self.version_result, result_callback)

    def version_result(self, result, result_callback):
        result_callback(result)
*/
func (self *Rtp_proxy_session) PlayCaller(prompt_name string, times int/*= 1*/, result_callback func(string)/*= nil*/, index int /*= 0*/) {
    self.caller._play(prompt_name, times, result_callback, index)
}

func (self *Rtp_proxy_session) send_command(cmd string, cb func(string)) {
    rtp_proxy_client := self.rtp_proxy_client
    if rtp_proxy_client != nil {
        rtp_proxy_client.SendCommand(cmd, cb, self.session_lock)
    }
}

func (self *Rtp_proxy_session) StopPlayCaller(result_callback func(string)/*= nil*/, index int/*= 0*/) {
    if ! self.caller_session_exists {
        return
    }
    command := fmt.Sprintf("S %s-%d %s %s", self.call_id, index, self.from_tag, self.to_tag)
    self.send_command(command, func(r string) { self.command_result(r, result_callback) })
}

func (self *Rtp_proxy_session) StartRecording(rname/*= nil*/ string, result_callback func(string)/*= nil*/, index int/*= 0*/) {
    if ! self.caller.session_exists {
        self.caller.update("0.0.0.0", "0", func(*rtpproxy_update_result) { self._start_recording(rname, result_callback, index) }, "", index, "IP4")
        return
    }
    self._start_recording(rname, result_callback, index)
}

func (self *Rtp_proxy_session) _start_recording(rname string, result_callback func(string), index int) {
    if rname == "" {
        command := fmt.Sprintf("R %s-%d %s %s", self.call_id, index, self.from_tag, self.to_tag)
        self.send_command(command, func (r string) { self.command_result(r, result_callback) })
        return
    }
    command := fmt.Sprintf("C %s-%d %s.a %s %s", self.call_id, index, rname, self.from_tag, self.to_tag)
    self.send_command(command, func(string) { self._start_recording1(rname, result_callback, index) })
}

func (self *Rtp_proxy_session) _start_recording1(rname string, result_callback func(string), index int) {
    command := fmt.Sprintf("C %s-%d %s.o %s %s", self.call_id, index, rname, self.to_tag, self.from_tag)
    self.send_command(command, func (r string) { self.command_result(r, result_callback) })
}

func (self *Rtp_proxy_session) command_result(result string, result_callback func(string)) {
    //print "%s.command_result(%s)" % (id(self), result)
    if result_callback != nil {
        result_callback(result)
    }
}

func (self *Rtp_proxy_session) Delete() {
    if self.rtp_proxy_client == nil {
        return
    }
    for self.max_index >= 0 {
        command := fmt.Sprintf("D %s-%d %s %s", self.call_id, self.max_index, self.from_tag, self.to_tag)
        self.send_command(command, nil)
        self.max_index--
    }
    self.rtp_proxy_client = nil
}

func (self *Rtp_proxy_session) OnCallerSdpChange(sdp_body sippy_types.MsgBody, cc_event sippy_types.CCEvent, result_callback func(sippy_types.MsgBody)) error {
    return self.caller._on_sdp_change(sdp_body, result_callback)
}

func (self *Rtp_proxy_session) OnCalleeSdpChange(sdp_body sippy_types.MsgBody, msg sippy_types.SipMsg, result_callback func(sippy_types.MsgBody)) error {
    return self.callee._on_sdp_change(sdp_body, result_callback)
}

func rtp_proxy_session_destructor(self *Rtp_proxy_session) {
    self.Delete()
}

func (self *Rtp_proxy_session) CallerSessionExists() bool { return self.caller_session_exists }

func (self *Rtp_proxy_session) SetCallerLaddress(addr string) {
    self.caller.laddress = addr
}

func (self *Rtp_proxy_session) SetCallerRaddress(addr *sippy_conf.HostPort) {
    self.caller.raddress = addr
}

func (self *Rtp_proxy_session) SetCalleeLaddress(addr string) {
    self.callee.laddress = addr
}

func (self *Rtp_proxy_session) SetCalleeRaddress(addr *sippy_conf.HostPort) {
    self.callee.raddress = addr
}

func (self *Rtp_proxy_session) SetInsertNortpp(v bool) {
    self.insert_nortpp = v
}

func (self *Rtp_proxy_session) SetAfterCallerSdpChange(cb func(sippy_types.RtpProxyUpdateResult)) {
    self.caller.after_sdp_change = cb
}

func (self *Rtp_proxy_session) CalleeOrigin() *sippy_sdp.SdpOrigin {
    if self == nil {
        return nil
    }
    return self.callee.origin
}
<|endoftext|>


<commit_before>package hash_table

func hash(s string) uint64 {
	var h uint64
	for _, r := range s {
		h = 101*h + uint64(r)
	}
	return h
}

func hashMod(s string, mod int) int {
	return int(hash(s) % uint64(mod))
}
<commit_msg>[hash_table/go] Change hash from uint64 to uint32<commit_after>package hash_table

func hash(s string) uint32 {
	var h uint32
	for _, r := range s {
		h = 101*h + uint32(r)
	}
	return h
}

func hashMod(s string, mod int) int {
	return int(hash(s) % uint32(mod))
}
<|endoftext|>


<commit_before>package blobserver

import (
	"hash"
	"net/http"

	"code.uber.internal/infra/kraken/client/store"
	storecfg "code.uber.internal/infra/kraken/configuration"
	"code.uber.internal/infra/kraken/lib/hrw"
	hashcfg "code.uber.internal/infra/kraken/origin/config"

	"github.com/pressly/chi"
	"github.com/spaolacci/murmur3"
)

// InitializeAPI instantiates a new web-app for the origin
func InitializeAPI(storeConfig *storecfg.Config, hashConfig hashcfg.HashConfig) http.Handler {
	r := chi.NewRouter()
	webApp := NewBlobWebApp(storeConfig, hashConfig)

	// Check data blob
	r.Head("/blobs/:digest", webApp.CheckBlob)

	// Pulling data blob
	r.Get("/blobs/:digest", webApp.GetBlob)

	// Delete data blob
	r.Delete("/blobs/:digest", webApp.DeleteBlob)

	// Pushing data blob
	r.Post("/blobs/uploads", webApp.PostUpload)
	r.Patch("/blobs/uploads/:uuid", webApp.PatchUpload)
	r.Put("/blobs/uploads/:uuid", webApp.PutUpload)

	return r
}

// NewBlobWebApp initializes a new BlobWebApp obj.
func NewBlobWebApp(storeConfig *storecfg.Config, hashConfig hashcfg.HashConfig) *BlobWebApp {
	if len(hashConfig.HashNodes) == 0 {
		panic("Hashstate has zero length: `0 any_operation X = 0`")
	}

	// Initalize hashing state
	hashState := hrw.NewRendezvousHash(
		func() hash.Hash { return murmur3.New64() },
		hrw.UInt64ToFloat64)

	// Add all configured nodes to a hashing state
	for _, node := range hashConfig.HashNodes {
		hashState.AddNode(node.Label, node.Weight)
	}

	ls, err := store.NewLocalStore(&storeConfig.Store, storeConfig.Registry.TagDeletion.Enable)
	if err != nil {
		panic("Could not create local store for blob web app")
	}

	return &BlobWebApp{
		hashConfig: hashConfig,
		hashState:  hashState,
		localStore: ls,
	}
}

// BlobWebApp defines a web-app that serves blob data for agent.
type BlobWebApp struct {
	hashConfig hashcfg.HashConfig

	hashState  *hrw.RendezvousHash
	localStore *store.LocalStore
}

// CheckBlob checks if blob data exists.
func (app BlobWebApp) CheckBlob(writer http.ResponseWriter, request *http.Request) {
	p := NewPipeline(request.Context(), app.hashConfig, app.hashState, app.localStore)
	p.AddRequestHandler(parseDigestHandler)
	p.AddRequestHandler(redirectByDigestHandler)
	p.AddRequestHandler(ensureDigestExistsHandler)
	p.AddResponseHandler(okHandler)
	p.Run(writer, request)
}

// GetBlob returns blob data for given digest.
func (app BlobWebApp) GetBlob(writer http.ResponseWriter, request *http.Request) {
	p := NewPipeline(request.Context(), app.hashConfig, app.hashState, app.localStore)
	p.AddRequestHandler(parseDigestHandler)
	p.AddRequestHandler(redirectByDigestHandler)
	p.AddResponseHandler(downloadBlobHandler)
	p.AddResponseHandler(okOctetStreamHandler)
	p.Run(writer, request)
}

// DeleteBlob removes blob data.
func (app BlobWebApp) DeleteBlob(writer http.ResponseWriter, request *http.Request) {
	p := NewPipeline(request.Context(), app.hashConfig, app.hashState, app.localStore)
	p.AddRequestHandler(parseDigestHandler)
	p.AddRequestHandler(deleteBlobHandler)
	p.AddResponseHandler(acceptedHandler)
	p.Run(writer, request)
}

// PostUpload start upload process for a blob.
// it returns a UUID, which is needed for subsequent uploads of this blob.
func (app BlobWebApp) PostUpload(writer http.ResponseWriter, request *http.Request) {
	p := NewPipeline(request.Context(), app.hashConfig, app.hashState, app.localStore)
	p.AddRequestHandler(parseDigestFromQueryHandler)
	p.AddRequestHandler(redirectByDigestHandler)
	p.AddRequestHandler(ensureDigestNotExistsHandler)
	p.AddRequestHandler(createUploadHandler)
	p.AddResponseHandler(returnUploadLocationHandler)
	p.Run(writer, request)
}

// PatchUpload upload a chunk of the blob.
func (app BlobWebApp) PatchUpload(writer http.ResponseWriter, request *http.Request) {
	p := NewPipeline(request.Context(), app.hashConfig, app.hashState, app.localStore)
	p.AddRequestHandler(parseDigestFromQueryHandler)
	p.AddRequestHandler(redirectByDigestHandler)
	p.AddRequestHandler(parseUUIDHandler)
	p.AddRequestHandler(parseContentRangeHandler)
	p.AddRequestHandler(ensureDigestNotExistsHandler)
	p.AddRequestHandler(uploadBlobChunkHandler)
	p.AddResponseHandler(returnUploadLocationHandler)
	p.Run(writer, request)
}

// PutUpload commits the upload.
func (app BlobWebApp) PutUpload(writer http.ResponseWriter, request *http.Request) {
	p := NewPipeline(request.Context(), app.hashConfig, app.hashState, app.localStore)
	p.AddRequestHandler(parseDigestFromQueryHandler)
	p.AddRequestHandler(redirectByDigestHandler)
	p.AddRequestHandler(parseUUIDHandler)
	p.AddRequestHandler(parseContentRangeHandler)
	p.AddRequestHandler(commitUploadHandler)
	p.AddResponseHandler(createdHandler)
	p.Run(writer, request)
}
<commit_msg>Fix merge error<commit_after>package blobserver

import (
	"hash"
	"net/http"

	"code.uber.internal/infra/kraken/client/store"
	"code.uber.internal/infra/kraken/lib/hrw"
	hashcfg "code.uber.internal/infra/kraken/origin/config"

	"github.com/pressly/chi"
	"github.com/spaolacci/murmur3"
)

// InitializeAPI instantiates a new web-app for the origin
func InitializeAPI(storeConfig *store.Config, hashConfig hashcfg.HashConfig) http.Handler {
	r := chi.NewRouter()
	webApp := NewBlobWebApp(storeConfig, hashConfig)

	// Check data blob
	r.Head("/blobs/:digest", webApp.CheckBlob)

	// Pulling data blob
	r.Get("/blobs/:digest", webApp.GetBlob)

	// Delete data blob
	r.Delete("/blobs/:digest", webApp.DeleteBlob)

	// Pushing data blob
	r.Post("/blobs/uploads", webApp.PostUpload)
	r.Patch("/blobs/uploads/:uuid", webApp.PatchUpload)
	r.Put("/blobs/uploads/:uuid", webApp.PutUpload)

	return r
}

// NewBlobWebApp initializes a new BlobWebApp obj.
func NewBlobWebApp(storeConfig *store.Config, hashConfig hashcfg.HashConfig) *BlobWebApp {
	if len(hashConfig.HashNodes) == 0 {
		panic("Hashstate has zero length: `0 any_operation X = 0`")
	}

	// Initalize hashing state
	hashState := hrw.NewRendezvousHash(
		func() hash.Hash { return murmur3.New64() },
		hrw.UInt64ToFloat64)

	// Add all configured nodes to a hashing state
	for _, node := range hashConfig.HashNodes {
		hashState.AddNode(node.Label, node.Weight)
	}

	ls, err := store.NewLocalStore(storeConfig, true)
	if err != nil {
		panic("Could not create local store for blob web app")
	}

	return &BlobWebApp{
		hashConfig: hashConfig,
		hashState:  hashState,
		localStore: ls,
	}
}

// BlobWebApp defines a web-app that serves blob data for agent.
type BlobWebApp struct {
	hashConfig hashcfg.HashConfig

	hashState  *hrw.RendezvousHash
	localStore *store.LocalStore
}

// CheckBlob checks if blob data exists.
func (app BlobWebApp) CheckBlob(writer http.ResponseWriter, request *http.Request) {
	p := NewPipeline(request.Context(), app.hashConfig, app.hashState, app.localStore)
	p.AddRequestHandler(parseDigestHandler)
	p.AddRequestHandler(redirectByDigestHandler)
	p.AddRequestHandler(ensureDigestExistsHandler)
	p.AddResponseHandler(okHandler)
	p.Run(writer, request)
}

// GetBlob returns blob data for given digest.
func (app BlobWebApp) GetBlob(writer http.ResponseWriter, request *http.Request) {
	p := NewPipeline(request.Context(), app.hashConfig, app.hashState, app.localStore)
	p.AddRequestHandler(parseDigestHandler)
	p.AddRequestHandler(redirectByDigestHandler)
	p.AddResponseHandler(downloadBlobHandler)
	p.AddResponseHandler(okOctetStreamHandler)
	p.Run(writer, request)
}

// DeleteBlob removes blob data.
func (app BlobWebApp) DeleteBlob(writer http.ResponseWriter, request *http.Request) {
	p := NewPipeline(request.Context(), app.hashConfig, app.hashState, app.localStore)
	p.AddRequestHandler(parseDigestHandler)
	p.AddRequestHandler(deleteBlobHandler)
	p.AddResponseHandler(acceptedHandler)
	p.Run(writer, request)
}

// PostUpload start upload process for a blob.
// it returns a UUID, which is needed for subsequent uploads of this blob.
func (app BlobWebApp) PostUpload(writer http.ResponseWriter, request *http.Request) {
	p := NewPipeline(request.Context(), app.hashConfig, app.hashState, app.localStore)
	p.AddRequestHandler(parseDigestFromQueryHandler)
	p.AddRequestHandler(redirectByDigestHandler)
	p.AddRequestHandler(ensureDigestNotExistsHandler)
	p.AddRequestHandler(createUploadHandler)
	p.AddResponseHandler(returnUploadLocationHandler)
	p.Run(writer, request)
}

// PatchUpload upload a chunk of the blob.
func (app BlobWebApp) PatchUpload(writer http.ResponseWriter, request *http.Request) {
	p := NewPipeline(request.Context(), app.hashConfig, app.hashState, app.localStore)
	p.AddRequestHandler(parseDigestFromQueryHandler)
	p.AddRequestHandler(redirectByDigestHandler)
	p.AddRequestHandler(parseUUIDHandler)
	p.AddRequestHandler(parseContentRangeHandler)
	p.AddRequestHandler(ensureDigestNotExistsHandler)
	p.AddRequestHandler(uploadBlobChunkHandler)
	p.AddResponseHandler(returnUploadLocationHandler)
	p.Run(writer, request)
}

// PutUpload commits the upload.
func (app BlobWebApp) PutUpload(writer http.ResponseWriter, request *http.Request) {
	p := NewPipeline(request.Context(), app.hashConfig, app.hashState, app.localStore)
	p.AddRequestHandler(parseDigestFromQueryHandler)
	p.AddRequestHandler(redirectByDigestHandler)
	p.AddRequestHandler(parseUUIDHandler)
	p.AddRequestHandler(parseContentRangeHandler)
	p.AddRequestHandler(commitUploadHandler)
	p.AddResponseHandler(createdHandler)
	p.Run(writer, request)
}
<|endoftext|>


<commit_before>package net

import (
	"os"
	"syscall"
	"testing"

	"github.com/shirou/gopsutil/internal/common"
	"github.com/stretchr/testify/assert"
)

func TestGetProcInodes(t *testing.T) {
	root := common.HostProc("")
	checkPid := os.Getpid() // process.test

	v, err := getProcInodes(root, int32(checkPid))
	assert.Nil(t, err)
	assert.NotEmpty(t, v)
}

type AddrTest struct {
	IP    string
	Port  int
	Error bool
}

func TestDecodeAddress(t *testing.T) {
	assert := assert.New(t)

	addr := map[string]AddrTest{
		"0500000A:0016": AddrTest{
			IP:   "10.0.0.5",
			Port: 22,
		},
		"0100007F:D1C2": AddrTest{
			IP:   "127.0.0.1",
			Port: 53698,
		},
		"11111:0035": AddrTest{
			Error: true,
		},
		"0100007F:BLAH": AddrTest{
			Error: true,
		},
		"0085002452100113070057A13F025401:0035": AddrTest{
			IP:   "2400:8500:1301:1052:a157:7:154:23f",
			Port: 53,
		},
		"00855210011307F025401:0035": AddrTest{
			Error: true,
		},
	}

	for src, dst := range addr {
		family := syscall.AF_INET
		if len(src) > 13 {
			family = syscall.AF_INET6
		}
		addr, err := decodeAddress(uint32(family), src)
		if dst.Error {
			assert.NotNil(err, src)
		} else {
			assert.Nil(err, src)
			assert.Equal(dst.IP, addr.IP, src)
			assert.Equal(dst.Port, int(addr.Port), src)
		}
	}
}
<commit_msg>[net]linux: TestGetProcInodes will fail on CI.<commit_after>package net

import (
	"syscall"
	"testing"

	"github.com/shirou/gopsutil/internal/common"
	"github.com/stretchr/testify/assert"
)

func TestGetProcInodesAll(t *testing.T) {
	root := common.HostProc("")
	v, err := getProcInodesAll(root)
	assert.Nil(t, err)
	assert.NotEmpty(t, v)
}

type AddrTest struct {
	IP    string
	Port  int
	Error bool
}

func TestDecodeAddress(t *testing.T) {
	assert := assert.New(t)

	addr := map[string]AddrTest{
		"0500000A:0016": AddrTest{
			IP:   "10.0.0.5",
			Port: 22,
		},
		"0100007F:D1C2": AddrTest{
			IP:   "127.0.0.1",
			Port: 53698,
		},
		"11111:0035": AddrTest{
			Error: true,
		},
		"0100007F:BLAH": AddrTest{
			Error: true,
		},
		"0085002452100113070057A13F025401:0035": AddrTest{
			IP:   "2400:8500:1301:1052:a157:7:154:23f",
			Port: 53,
		},
		"00855210011307F025401:0035": AddrTest{
			Error: true,
		},
	}

	for src, dst := range addr {
		family := syscall.AF_INET
		if len(src) > 13 {
			family = syscall.AF_INET6
		}
		addr, err := decodeAddress(uint32(family), src)
		if dst.Error {
			assert.NotNil(err, src)
		} else {
			assert.Nil(err, src)
			assert.Equal(dst.IP, addr.IP, src)
			assert.Equal(dst.Port, int(addr.Port), src)
		}
	}
}
<|endoftext|>