<commit_before>// Package cli provides all methods to control command line functions
package cli

import (
	"encoding/json"
	"fmt"
	"github.com/mehrdadrad/mylg/banner"
	"gopkg.in/readline.v1"
	"io/ioutil"
	"net/http"
	"regexp"
	"strconv"
	"strings"
)

// Readline structure
type Readline struct {
	instance  *readline.Instance
	completer *readline.PrefixCompleter
	prompt    string
	next      chan struct{}
}

// Init set readline imain items
func Init(prompt, version string) *Readline {
	var (
		r         Readline
		err       error
		completer = readline.NewPrefixCompleter(
			readline.PcItem("ping"),
			readline.PcItem("trace"),
			readline.PcItem("bgp"),
			readline.PcItem("hping"),
			readline.PcItem("connect"),
			readline.PcItem("node"),
			readline.PcItem("local"),
			readline.PcItem("lg"),
			readline.PcItem("ns"),
			readline.PcItem("dig"),
			readline.PcItem("whois"),
			readline.PcItem("scan"),
			readline.PcItem("peering"),
			readline.PcItem("help"),
			readline.PcItem("exit"),
		)
	)
	r.completer = completer
	r.instance, err = readline.NewEx(&readline.Config{
		Prompt:          prompt + "> ",
		HistoryFile:     "/tmp/myping",
		InterruptPrompt: "^C",
		EOFPrompt:       "exit",
		AutoComplete:    completer,
	})
	if err != nil {
		panic(err)
	}
	banner.Println(version) // print banner
	checkUpdate(version)    // check update version
	r.prompt = prompt       // init local prompt
	return &r
}

// RemoveItemCompleter removes subitem(s) from a specific main item
func (r *Readline) RemoveItemCompleter(pcItem string) {
	child := []readline.PrefixCompleterInterface{}
	for _, p := range r.completer.Children {
		if strings.TrimSpace(string(p.GetName())) != pcItem {
			child = append(child, p)
		}
	}

	r.completer.Children = child

}

// AddCompleter updates subitem(s) from a specific main item
func (r *Readline) AddCompleter(pcItem string, pcSubItems []string) {
	var pc readline.PrefixCompleter
	c := []readline.PrefixCompleterInterface{}
	for _, item := range pcSubItems {
		c = append(c, readline.PcItem(item))
	}
	pc.Name = []rune(pcItem + " ")
	pc.Children = c
	r.completer.Children = append(r.completer.Children, &pc)
}

// UpdateCompleter updates subitem(s) from a specific main item
func (r *Readline) UpdateCompleter(pcItem string, pcSubItems []string) {
	child := []readline.PrefixCompleterInterface{}
	var pc readline.PrefixCompleter
	for _, p := range r.completer.Children {
		if strings.TrimSpace(string(p.GetName())) == pcItem {
			c := []readline.PrefixCompleterInterface{}
			for _, item := range pcSubItems {
				c = append(c, readline.PcItem(item))
			}
			pc.Name = []rune(pcItem + " ")
			pc.Children = c
			child = append(child, &pc)
		} else {
			child = append(child, p)
		}
	}
	if len(pc.Name) < 1 {
		// todo adding new
	}
	r.completer.Children = child
}

// SetPrompt set readline prompt and store it
func (r *Readline) SetPrompt(p string) {
	p = strings.ToLower(p)
	r.prompt = p
	r.instance.SetPrompt(p + "> ")
}

// UpdatePromptN appends readline prompt
func (r *Readline) UpdatePromptN(p string, n int) {
	var parts []string
	p = strings.ToLower(p)
	parts = strings.SplitAfterN(r.prompt, "/", n)
	if n <= len(parts) && n > -1 {
		parts[n-1] = p
		r.prompt = strings.Join(parts, "")
	} else {
		r.prompt += "/" + p
	}
	r.instance.SetPrompt(r.prompt + "> ")
}

// GetPrompt returns the current prompt string
func (r *Readline) GetPrompt() string {
	return r.prompt
}

// Refresh prompt
func (r *Readline) Refresh() {
	r.instance.Refresh()
}

// SetVim set mode to vim
func (r *Readline) SetVim() {
	if !r.instance.IsVimMode() {
		r.instance.SetVimMode(true)
		println("mode changed to vim")
	} else {
		println("mode already is vim")
	}
}

// SetEmacs set mode to emacs
func (r *Readline) SetEmacs() {
	if r.instance.IsVimMode() {
		r.instance.SetVimMode(false)
		println("mode changed to emacs")
	} else {
		println("mode already is emacs")
	}
}

// Next trigers to read next line
func (r *Readline) Next() {
	r.next <- struct{}{}
}

// Run the main loop
func (r *Readline) Run(cmd chan<- string, next chan struct{}) {
	r.next = next
	func() {
		for {
			line, err := r.instance.Readline()
			if err != nil { // io.EOF, readline.ErrInterrupt
				break
			}
			cmd <- line
			if _, ok := <-next; !ok {
				break
			}
		}
	}()
}

// Close the readline instance
func (r *Readline) Close(next chan struct{}) {
	r.instance.Close()
}

// Help print out the main help
func (r *Readline) Help() {
	fmt.Println(`Usage:
	The myLG tool developed to troubleshoot networking situations.
	The vi/emacs mode,almost all basic features is supported. press tab to see what options are available.

	connect <provider name>     connects to external looking glass, press tab to see the menu
	node <city/country name>    connects to specific node at current looking glass, press tab to see the available nodes
	local                       back to local
	lg                          change mode to extenal looking glass
	ns                          change mode to name server looking up
	ping                        ping ip address or domain name
	dig                         name server looking up
	whois                       resolve AS number/IP/CIDR to holder (provides by ripe ncc)
	hping						Ping through HTTP/HTTPS w/ GET/HEAD methods
	scan                        scan tcp ports (you can provide range >scan host minport maxport)
	peering                     peering information (provides by peeringdb.com)
	`)
}

// checkUpdate checks if any new version is available
func checkUpdate(version string) {
	type mylg struct {
		Version string
	}
	var appCtl mylg

	if version == "test" {
		return
	}

	resp, err := http.Get("http://mylg.io/appctl/mylg")
	if err != nil {
		println("error: check update has been failed ")
		return
	}
	defer resp.Body.Close()
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		println("error: check update has been failed (2)" + err.Error())
		return
	}
	err = json.Unmarshal(body, &appCtl)
	if err != nil {
		println(err.Error())
		return
	}
	if version != appCtl.Version {
		fmt.Printf("New version is available (v%s) mylg.io/download\n", appCtl.Version)
	}
}

//Flag parses the command arguments syntax:
// -flag=x
// -flag x
// help
func Flag(args string) (string, map[string]interface{}) {
	var (
		r   = make(map[string]interface{}, 10)
		err error
	)
	args = strings.TrimSpace(args)
	re := regexp.MustCompile(`(?i)-([a-z]+)={0,1}\s{0,1}([0-9|a-z|-]+)`)
	f := re.FindAllStringSubmatch(args, -1)
	for _, kv := range f {
		if len(kv) > 1 {
			r[kv[1]], err = strconv.Atoi(kv[2])
			if err != nil {
				r[kv[1]] = kv[2]
			}
			args = strings.Replace(args, kv[0], "", -1)
		}
	}
	if m, _ := regexp.MatchString(`(?i)help$`, args); m {
		r["help"] = true
	}
	args = strings.TrimSpace(args)
	return args, r
}

// SetFlag returns command option(s)
func SetFlag(flag map[string]interface{}, option string, v interface{}) interface{} {
	if sValue, ok := flag[option]; ok {
		switch v.(type) {
		case int:
			return sValue.(int)
		default:
			return sValue.(string)
		}
	} else {
		return v
	}
}
<commit_msg>fixed help format<commit_after>// Package cli provides all methods to control command line functions
package cli

import (
	"encoding/json"
	"fmt"
	"github.com/mehrdadrad/mylg/banner"
	"gopkg.in/readline.v1"
	"io/ioutil"
	"net/http"
	"regexp"
	"strconv"
	"strings"
)

// Readline structure
type Readline struct {
	instance  *readline.Instance
	completer *readline.PrefixCompleter
	prompt    string
	next      chan struct{}
}

// Init set readline imain items
func Init(prompt, version string) *Readline {
	var (
		r         Readline
		err       error
		completer = readline.NewPrefixCompleter(
			readline.PcItem("ping"),
			readline.PcItem("trace"),
			readline.PcItem("bgp"),
			readline.PcItem("hping"),
			readline.PcItem("connect"),
			readline.PcItem("node"),
			readline.PcItem("local"),
			readline.PcItem("lg"),
			readline.PcItem("ns"),
			readline.PcItem("dig"),
			readline.PcItem("whois"),
			readline.PcItem("scan"),
			readline.PcItem("peering"),
			readline.PcItem("help"),
			readline.PcItem("exit"),
		)
	)
	r.completer = completer
	r.instance, err = readline.NewEx(&readline.Config{
		Prompt:          prompt + "> ",
		HistoryFile:     "/tmp/myping",
		InterruptPrompt: "^C",
		EOFPrompt:       "exit",
		AutoComplete:    completer,
	})
	if err != nil {
		panic(err)
	}
	banner.Println(version) // print banner
	checkUpdate(version)    // check update version
	r.prompt = prompt       // init local prompt
	return &r
}

// RemoveItemCompleter removes subitem(s) from a specific main item
func (r *Readline) RemoveItemCompleter(pcItem string) {
	child := []readline.PrefixCompleterInterface{}
	for _, p := range r.completer.Children {
		if strings.TrimSpace(string(p.GetName())) != pcItem {
			child = append(child, p)
		}
	}

	r.completer.Children = child

}

// AddCompleter updates subitem(s) from a specific main item
func (r *Readline) AddCompleter(pcItem string, pcSubItems []string) {
	var pc readline.PrefixCompleter
	c := []readline.PrefixCompleterInterface{}
	for _, item := range pcSubItems {
		c = append(c, readline.PcItem(item))
	}
	pc.Name = []rune(pcItem + " ")
	pc.Children = c
	r.completer.Children = append(r.completer.Children, &pc)
}

// UpdateCompleter updates subitem(s) from a specific main item
func (r *Readline) UpdateCompleter(pcItem string, pcSubItems []string) {
	child := []readline.PrefixCompleterInterface{}
	var pc readline.PrefixCompleter
	for _, p := range r.completer.Children {
		if strings.TrimSpace(string(p.GetName())) == pcItem {
			c := []readline.PrefixCompleterInterface{}
			for _, item := range pcSubItems {
				c = append(c, readline.PcItem(item))
			}
			pc.Name = []rune(pcItem + " ")
			pc.Children = c
			child = append(child, &pc)
		} else {
			child = append(child, p)
		}
	}
	if len(pc.Name) < 1 {
		// todo adding new
	}
	r.completer.Children = child
}

// SetPrompt set readline prompt and store it
func (r *Readline) SetPrompt(p string) {
	p = strings.ToLower(p)
	r.prompt = p
	r.instance.SetPrompt(p + "> ")
}

// UpdatePromptN appends readline prompt
func (r *Readline) UpdatePromptN(p string, n int) {
	var parts []string
	p = strings.ToLower(p)
	parts = strings.SplitAfterN(r.prompt, "/", n)
	if n <= len(parts) && n > -1 {
		parts[n-1] = p
		r.prompt = strings.Join(parts, "")
	} else {
		r.prompt += "/" + p
	}
	r.instance.SetPrompt(r.prompt + "> ")
}

// GetPrompt returns the current prompt string
func (r *Readline) GetPrompt() string {
	return r.prompt
}

// Refresh prompt
func (r *Readline) Refresh() {
	r.instance.Refresh()
}

// SetVim set mode to vim
func (r *Readline) SetVim() {
	if !r.instance.IsVimMode() {
		r.instance.SetVimMode(true)
		println("mode changed to vim")
	} else {
		println("mode already is vim")
	}
}

// SetEmacs set mode to emacs
func (r *Readline) SetEmacs() {
	if r.instance.IsVimMode() {
		r.instance.SetVimMode(false)
		println("mode changed to emacs")
	} else {
		println("mode already is emacs")
	}
}

// Next trigers to read next line
func (r *Readline) Next() {
	r.next <- struct{}{}
}

// Run the main loop
func (r *Readline) Run(cmd chan<- string, next chan struct{}) {
	r.next = next
	func() {
		for {
			line, err := r.instance.Readline()
			if err != nil { // io.EOF, readline.ErrInterrupt
				break
			}
			cmd <- line
			if _, ok := <-next; !ok {
				break
			}
		}
	}()
}

// Close the readline instance
func (r *Readline) Close(next chan struct{}) {
	r.instance.Close()
}

// Help print out the main help
func (r *Readline) Help() {
	fmt.Println(`Usage:
	The myLG tool developed to troubleshoot networking situations.
	The vi/emacs mode,almost all basic features is supported. press tab to see what options are available.

	connect <provider name>     connects to external looking glass, press tab to see the menu
	node <city/country name>    connects to specific node at current looking glass, press tab to see the available nodes
	local                       back to local
	lg                          change mode to extenal looking glass
	ns                          change mode to name server looking up
	ping                        ping ip address or domain name
	dig                         name server looking up
	whois                       resolve AS number/IP/CIDR to holder (provides by ripe ncc)
	hping                       Ping through HTTP/HTTPS w/ GET/HEAD methods
	scan                        scan tcp ports (you can provide range >scan host minport maxport)
	peering                     peering information (provides by peeringdb.com)
	`)
}

// checkUpdate checks if any new version is available
func checkUpdate(version string) {
	type mylg struct {
		Version string
	}
	var appCtl mylg

	if version == "test" {
		return
	}

	resp, err := http.Get("http://mylg.io/appctl/mylg")
	if err != nil {
		println("error: check update has been failed ")
		return
	}
	defer resp.Body.Close()
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		println("error: check update has been failed (2)" + err.Error())
		return
	}
	err = json.Unmarshal(body, &appCtl)
	if err != nil {
		println(err.Error())
		return
	}
	if version != appCtl.Version {
		fmt.Printf("New version is available (v%s) mylg.io/download\n", appCtl.Version)
	}
}

//Flag parses the command arguments syntax:
// -flag=x
// -flag x
// help
func Flag(args string) (string, map[string]interface{}) {
	var (
		r   = make(map[string]interface{}, 10)
		err error
	)
	args = strings.TrimSpace(args)
	re := regexp.MustCompile(`(?i)-([a-z]+)={0,1}\s{0,1}([0-9|a-z|-]+)`)
	f := re.FindAllStringSubmatch(args, -1)
	for _, kv := range f {
		if len(kv) > 1 {
			r[kv[1]], err = strconv.Atoi(kv[2])
			if err != nil {
				r[kv[1]] = kv[2]
			}
			args = strings.Replace(args, kv[0], "", -1)
		}
	}
	if m, _ := regexp.MatchString(`(?i)help$`, args); m {
		r["help"] = true
	}
	args = strings.TrimSpace(args)
	return args, r
}

// SetFlag returns command option(s)
func SetFlag(flag map[string]interface{}, option string, v interface{}) interface{} {
	if sValue, ok := flag[option]; ok {
		switch v.(type) {
		case int:
			return sValue.(int)
		default:
			return sValue.(string)
		}
	} else {
		return v
	}
}
<|endoftext|>


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

package edn

import (
	"bytes"
	"io"
)

func tokNeedsDelim(t tokenType) bool {
	switch t {
	case tokenString, tokenListStart, tokenListEnd, tokenVectorStart,
		tokenVectorEnd, tokenMapEnd, tokenMapStart, tokenSetStart, tokenDiscard, tokenError:
		return false
	}
	return true
}

func delimits(r rune) bool {
	switch r {
	case '{', '}', '[', ']', '(', ')', '\\', '"':
		return true
	}
	return isWhitespace(r)
}

// Compact appends to dst a compacted form of the EDN-encoded src. It does not
// remove discard values.
func Compact(dst *bytes.Buffer, src []byte) error {
	origLen := dst.Len()
	var lex lexer
	lex.reset()
	buf := bytes.NewBuffer(src)
	start, pos := 0, 0
	needsDelim := false
	prevIgnore := '\uFFFD'
	r, size, err := buf.ReadRune()
	for ; err == nil; r, size, err = buf.ReadRune() {
		ls := lex.state(r)
		ppos := pos
		pos += size
		switch ls {
		case lexCont:
			if ppos == start && needsDelim && !delimits(r) {
				dst.WriteRune(prevIgnore)
			}
			continue
		case lexIgnore:
			prevIgnore = r
			start = pos
		case lexError:
			dst.Truncate(origLen)
			return lex.err
		case lexEnd:
			// here we might want to discard #_ and the like. Currently we don't.
			dst.Write(src[start:pos])
			needsDelim = tokNeedsDelim(lex.token)
			lex.reset()
			start = pos
		case lexEndPrev:
			dst.Write(src[start:ppos])
			needsDelim = tokNeedsDelim(lex.token)
			lex.reset()
			lss := lex.state(r)
			switch lss {
			case lexIgnore:
				prevIgnore = r
				start = pos
			case lexCont:
				start = ppos
			case lexEnd:
				dst.WriteRune(r)
				lex.reset()
				start = pos
			case lexEndPrev:
				dst.Truncate(origLen)
				return errInternal
			case lexError:
				dst.Truncate(origLen)
				return lex.err
			}
		}
	}
	if err != io.EOF {
		return err
	}
	ls := lex.eof()
	switch ls {
	case lexEnd:
		dst.Write(src[start:pos])
	case lexError:
		dst.Truncate(origLen)
		return lex.err
	}
	return nil
}
<commit_msg>fix Compact bug<commit_after>// Copyright 2015 Jean Niklas L'orange.  All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package edn

import (
	"bytes"
	"io"
)

func tokNeedsDelim(t tokenType) bool {
	switch t {
	case tokenString, tokenListStart, tokenListEnd, tokenVectorStart,
		tokenVectorEnd, tokenMapEnd, tokenMapStart, tokenSetStart, tokenDiscard, tokenError:
		return false
	}
	return true
}

func delimits(r rune) bool {
	switch r {
	case '{', '}', '[', ']', '(', ')', '\\', '"':
		return true
	}
	return isWhitespace(r)
}

// Compact appends to dst a compacted form of the EDN-encoded src. It does not
// remove discard values.
func Compact(dst *bytes.Buffer, src []byte) error {
	origLen := dst.Len()
	var lex lexer
	lex.reset()
	buf := bytes.NewBuffer(src)
	start, pos := 0, 0
	needsDelim := false
	prevIgnore := '\uFFFD'
	r, size, err := buf.ReadRune()
	for ; err == nil; r, size, err = buf.ReadRune() {
		ls := lex.state(r)
		ppos := pos
		pos += size
		switch ls {
		case lexCont:
			if ppos == start && needsDelim && !delimits(r) {
				dst.WriteRune(prevIgnore)
			}
			continue
		case lexIgnore:
			prevIgnore = r
			start = pos
		case lexError:
			dst.Truncate(origLen)
			return lex.err
		case lexEnd:
			// here we might want to discard #_ and the like. Currently we don't.
			dst.Write(src[start:pos])
			needsDelim = tokNeedsDelim(lex.token)
			lex.reset()
			start = pos
		case lexEndPrev:
			dst.Write(src[start:ppos])
			lex.reset()
			lss := lex.state(r)
			needsDelim = tokNeedsDelim(lex.token)
			switch lss {
			case lexIgnore:
				prevIgnore = r
				start = pos
			case lexCont:
				start = ppos
			case lexEnd:
				dst.WriteRune(r)
				lex.reset()
				start = pos
			case lexEndPrev:
				dst.Truncate(origLen)
				return errInternal
			case lexError:
				dst.Truncate(origLen)
				return lex.err
			}
		}
	}
	if err != io.EOF {
		return err
	}
	ls := lex.eof()
	switch ls {
	case lexEnd:
		dst.Write(src[start:pos])
	case lexError:
		dst.Truncate(origLen)
		return lex.err
	}
	return nil
}
<|endoftext|>


<commit_before>package main

import "fmt"
import "time"
import "bytes"

import s "github.com/prataprc/gosettings"
import "github.com/prataprc/gostore/llrb"
import "github.com/prataprc/gostore/bogn"
import "github.com/bmatsuo/lmdb-go/lmdb"
import "github.com/bmatsuo/lmdb-go/lmdbscan"

func compareLlrbLmdb(
	index *llrb.LLRB, lmdbenv *lmdb.Env, lmdbdbi lmdb.DBI) {

	lmdbcount := getlmdbCount(lmdbenv, lmdbdbi)
	llrbcount := index.Count()
	fmsg := "compareLlrbLmdb, lmdbcount:%v llrbcount:%v\n"
	fmt.Printf(fmsg, lmdbcount, llrbcount)

	epoch, cmpcount := time.Now(), 0

	iter := index.Scan()
	err := lmdbenv.View(func(txn *lmdb.Txn) error {
		lmdbs := lmdbscan.New(txn, lmdbdbi)
		defer lmdbs.Close()

		lmdbs.Scan()

		llrbkey, llrbval, _, llrbdel, llrberr := iter(false /*fin*/)
		lmdbkey, lmdbval, lmdberr := lmdbs.Key(), lmdbs.Val(), lmdbs.Err()

		for llrbkey != nil {
			if llrbdel == false {
				cmpcount++
				if llrberr != nil {
					panic(llrberr)
				} else if lmdberr != nil {
					panic(lmdberr)
				} else if bytes.Compare(llrbkey, lmdbkey) != 0 {
					fmsg := "expected %q, got %q"
					panic(fmt.Errorf(fmsg, lmdbkey, llrbkey))
				} else if bytes.Compare(llrbval, lmdbval) != 0 {
					fmsg := "for %q expected val %q, got val %q\n"
					x, y := lmdbval[:options.vallen], llrbval[:options.vallen]
					fmt.Printf(fmsg, llrbkey, x, y)
					fmsg = "for %q expected seqno %v, got %v\n"
					x, y = lmdbval[options.vallen:], llrbval[options.vallen:]
					fmt.Printf(fmsg, llrbkey, lmdbval, llrbval)
					panic("error")
				}
				//fmt.Printf("compareLlrbLmdb %q okay ...\n", llrbkey)
			}

			lmdbs.Scan()
			llrbkey, llrbval, _, llrbdel, llrberr = iter(false /*fin*/)
			lmdbkey, lmdbval, lmdberr = lmdbs.Key(), lmdbs.Val(), lmdbs.Err()
		}
		if lmdbkey != nil {
			return fmt.Errorf("found lmdb key %q\n", lmdbkey)
		}

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

	took := time.Since(epoch)
	fmt.Printf("Took %v to compare (%v) LLRB and LMDB\n\n", took, cmpcount)
}

func compareMvccLmdb(
	index *llrb.MVCC, lmdbenv *lmdb.Env, lmdbdbi lmdb.DBI) {

	lmdbcount := getlmdbCount(lmdbenv, lmdbdbi)
	mvcccount := index.Count()
	fmsg := "compareMvccLmdb, lmdbcount:%v mvcccount:%v\n"
	fmt.Printf(fmsg, lmdbcount, mvcccount)

	epoch, cmpcount := time.Now(), 0

	//fmt.Println("mvcc seqno", index.Getseqno())
	iter := index.Scan()
	err := lmdbenv.View(func(txn *lmdb.Txn) error {
		lmdbs := lmdbscan.New(txn, lmdbdbi)
		defer lmdbs.Close()

		lmdbs.Scan()

		mvcckey, mvccval, _, mvccdel, mvccerr := iter(false /*fin*/)
		lmdbkey, lmdbval, lmdberr := lmdbs.Key(), lmdbs.Val(), lmdbs.Err()

		for mvcckey != nil {
			if mvccdel == false {
				cmpcount++
				if mvccerr != nil {
					panic(mvccerr)
				} else if lmdberr != nil {
					panic(lmdberr)
				} else if bytes.Compare(mvcckey, lmdbkey) != 0 {
					fmsg := "expected %q, got %q"
					panic(fmt.Errorf(fmsg, lmdbkey, mvcckey))
				} else if bytes.Compare(mvccval, lmdbval) != 0 {
					fmsg := "for %q expected %q, got %q"
					panic(fmt.Errorf(fmsg, mvcckey, lmdbval, mvccval))
				}
				//fmt.Printf("compareMvccLmdb %q okay ...\n", llrbkey)
			}

			lmdbs.Scan()
			mvcckey, mvccval, _, mvccdel, mvccerr = iter(false /*fin*/)
			lmdbkey, lmdbval, lmdberr = lmdbs.Key(), lmdbs.Val(), lmdbs.Err()
		}
		if lmdbkey != nil {
			return fmt.Errorf("found lmdb key %q\n", lmdbkey)
		}

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

	took := time.Since(epoch)
	fmt.Printf("Took %v to compare (%v) MVCC and LMDB\n\n", took, cmpcount)
}

func compareBognLmdb(
	index *bogn.Bogn, lmdbenv *lmdb.Env, lmdbdbi lmdb.DBI) {

	epoch, cmpcount := time.Now(), 0

	//fmt.Println("bogn seqno", index.Getseqno())
	iter := index.Scan()
	err := lmdbenv.View(func(txn *lmdb.Txn) error {
		lmdbs := lmdbscan.New(txn, lmdbdbi)
		defer lmdbs.Close()

		lmdbs.Scan()

		bognkey, bognval, _, bogndel, bognerr := iter(false /*fin*/)
		lmdbkey, lmdbval, lmdberr := lmdbs.Key(), lmdbs.Val(), lmdbs.Err()

		for bognkey != nil {
			if bogndel == false {
				cmpcount++
				if bognerr != nil {
					panic(bognerr)
				} else if lmdberr != nil {
					panic(lmdberr)
				} else if bytes.Compare(bognkey, lmdbkey) != 0 {
					fmsg := "expected %q, got %q"
					panic(fmt.Errorf(fmsg, lmdbkey, bognkey))
				} else if bytes.Compare(bognval, lmdbval) != 0 {
					fmsg := "for %q expected %q, got %q"
					panic(fmt.Errorf(fmsg, bognkey, lmdbval, bognval))
				}
				//fmt.Printf("comparebognLmdb %q okay ...\n", llrbkey)
			}

			lmdbs.Scan()
			bognkey, bognval, _, bogndel, bognerr = iter(false /*fin*/)
			lmdbkey, lmdbval, lmdberr = lmdbs.Key(), lmdbs.Val(), lmdbs.Err()
		}
		if lmdbkey != nil {
			return fmt.Errorf("found lmdb key %q\n", lmdbkey)
		}

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

	took := time.Since(epoch)
	fmt.Printf("Took %v to compare (%v) BOGN and LMDB\n\n", took, cmpcount)
}

func diskBognLmdb(name, lmdbpath string, setts s.Settings) {
	if setts.Bool("durable") == false {
		return
	}

	fmt.Println("\n.......... Final disk check ..............\n")

	index, err := bogn.New(name /*dbtest*/, setts)
	if err != nil {
		panic(err)
	}
	index.Start()
	defer index.Close()

	lmdbenv, lmdbdbi, err := initlmdb(lmdbpath, lmdb.NoSync|lmdb.NoMetaSync)
	if err != nil {
		panic(err)
	}
	defer lmdbenv.Close()

	compareBognLmdb(index, lmdbenv, lmdbdbi)
}

func comparekeyvalue(key, value []byte, vlen int) bool {
	if vlen > 0 && len(value) > 0 {
		if bytes.Compare(key, value[:len(key)]) != 0 {
			panic(fmt.Errorf("expected %q, got %q", key, value))
		}
	}
	return true
}
<commit_msg>compare-functions to print values.<commit_after>package main

import "fmt"
import "time"
import "bytes"

import s "github.com/prataprc/gosettings"
import "github.com/prataprc/gostore/llrb"
import "github.com/prataprc/gostore/bogn"
import "github.com/bmatsuo/lmdb-go/lmdb"
import "github.com/bmatsuo/lmdb-go/lmdbscan"

func compareLlrbLmdb(
	index *llrb.LLRB, lmdbenv *lmdb.Env, lmdbdbi lmdb.DBI) {

	lmdbcount := getlmdbCount(lmdbenv, lmdbdbi)
	llrbcount := index.Count()
	fmsg := "compareLlrbLmdb, lmdbcount:%v llrbcount:%v\n"
	fmt.Printf(fmsg, lmdbcount, llrbcount)

	epoch, cmpcount := time.Now(), 0

	iter := index.Scan()
	err := lmdbenv.View(func(txn *lmdb.Txn) error {
		lmdbs := lmdbscan.New(txn, lmdbdbi)
		defer lmdbs.Close()

		lmdbs.Scan()

		llrbkey, llrbval, _, llrbdel, llrberr := iter(false /*fin*/)
		lmdbkey, lmdbval, lmdberr := lmdbs.Key(), lmdbs.Val(), lmdbs.Err()

		for llrbkey != nil {
			if llrbdel == false {
				cmpcount++
				if llrberr != nil {
					panic(llrberr)
				} else if lmdberr != nil {
					panic(lmdberr)
				} else if bytes.Compare(llrbkey, lmdbkey) != 0 {
					fmsg := "expected %q,%q, got %q,%q"
					panic(fmt.Errorf(fmsg, lmdbkey, lmdbval, llrbkey, llrbval))
				} else if bytes.Compare(llrbval, lmdbval) != 0 {
					fmsg := "for %q expected val %q, got val %q\n"
					x, y := lmdbval[:options.vallen], llrbval[:options.vallen]
					fmt.Printf(fmsg, llrbkey, x, y)
					fmsg = "for %q expected seqno %v, got %v\n"
					x, y = lmdbval[options.vallen:], llrbval[options.vallen:]
					fmt.Printf(fmsg, llrbkey, lmdbval, llrbval)
					panic("error")
				}
				//fmt.Printf("compareLlrbLmdb %q okay ...\n", llrbkey)
			}

			lmdbs.Scan()
			llrbkey, llrbval, _, llrbdel, llrberr = iter(false /*fin*/)
			lmdbkey, lmdbval, lmdberr = lmdbs.Key(), lmdbs.Val(), lmdbs.Err()
		}
		if lmdbkey != nil {
			return fmt.Errorf("found lmdb key %q\n", lmdbkey)
		}

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

	took := time.Since(epoch)
	fmt.Printf("Took %v to compare (%v) LLRB and LMDB\n\n", took, cmpcount)
}

func compareMvccLmdb(
	index *llrb.MVCC, lmdbenv *lmdb.Env, lmdbdbi lmdb.DBI) {

	lmdbcount := getlmdbCount(lmdbenv, lmdbdbi)
	mvcccount := index.Count()
	fmsg := "compareMvccLmdb, lmdbcount:%v mvcccount:%v\n"
	fmt.Printf(fmsg, lmdbcount, mvcccount)

	epoch, cmpcount := time.Now(), 0

	//fmt.Println("mvcc seqno", index.Getseqno())
	iter := index.Scan()
	err := lmdbenv.View(func(txn *lmdb.Txn) error {
		lmdbs := lmdbscan.New(txn, lmdbdbi)
		defer lmdbs.Close()

		lmdbs.Scan()

		mvcckey, mvccval, _, mvccdel, mvccerr := iter(false /*fin*/)
		lmdbkey, lmdbval, lmdberr := lmdbs.Key(), lmdbs.Val(), lmdbs.Err()

		for mvcckey != nil {
			if mvccdel == false {
				cmpcount++
				if mvccerr != nil {
					panic(mvccerr)
				} else if lmdberr != nil {
					panic(lmdberr)
				} else if bytes.Compare(mvcckey, lmdbkey) != 0 {
					fmsg := "expected %q,%q, got %q,%q"
					panic(fmt.Errorf(fmsg, lmdbkey, lmdbval, mvcckey, mvccval))
				} else if bytes.Compare(mvccval, lmdbval) != 0 {
					fmsg := "for %q expected %q, got %q"
					panic(fmt.Errorf(fmsg, mvcckey, lmdbval, mvccval))
				}
				//fmt.Printf("compareMvccLmdb %q okay ...\n", llrbkey)
			}

			lmdbs.Scan()
			mvcckey, mvccval, _, mvccdel, mvccerr = iter(false /*fin*/)
			lmdbkey, lmdbval, lmdberr = lmdbs.Key(), lmdbs.Val(), lmdbs.Err()
		}
		if lmdbkey != nil {
			return fmt.Errorf("found lmdb key %q\n", lmdbkey)
		}

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

	took := time.Since(epoch)
	fmt.Printf("Took %v to compare (%v) MVCC and LMDB\n\n", took, cmpcount)
}

func compareBognLmdb(
	index *bogn.Bogn, lmdbenv *lmdb.Env, lmdbdbi lmdb.DBI) {

	epoch, cmpcount := time.Now(), 0

	//fmt.Println("bogn seqno", index.Getseqno())
	iter := index.Scan()
	err := lmdbenv.View(func(txn *lmdb.Txn) error {
		lmdbs := lmdbscan.New(txn, lmdbdbi)
		defer lmdbs.Close()

		lmdbs.Scan()

		bognkey, bognval, _, bogndel, bognerr := iter(false /*fin*/)
		lmdbkey, lmdbval, lmdberr := lmdbs.Key(), lmdbs.Val(), lmdbs.Err()

		for bognkey != nil {
			if bogndel == false {
				cmpcount++
				if bognerr != nil {
					panic(bognerr)
				} else if lmdberr != nil {
					panic(lmdberr)
				} else if bytes.Compare(bognkey, lmdbkey) != 0 {
					fmsg := "expected %q,%q, got %q,%q"
					panic(fmt.Errorf(fmsg, lmdbkey, lmdbval, bognkey, bognval))
				} else if bytes.Compare(bognval, lmdbval) != 0 {
					fmsg := "for %q expected %q, got %q"
					panic(fmt.Errorf(fmsg, bognkey, lmdbval, bognval))
				}
				//fmt.Printf("comparebognLmdb %q okay ...\n", llrbkey)
			}

			lmdbs.Scan()
			bognkey, bognval, _, bogndel, bognerr = iter(false /*fin*/)
			lmdbkey, lmdbval, lmdberr = lmdbs.Key(), lmdbs.Val(), lmdbs.Err()
		}
		if lmdbkey != nil {
			return fmt.Errorf("found lmdb key %q\n", lmdbkey)
		}

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

	took := time.Since(epoch)
	fmt.Printf("Took %v to compare (%v) BOGN and LMDB\n\n", took, cmpcount)
}

func diskBognLmdb(name, lmdbpath string, setts s.Settings) {
	if setts.Bool("durable") == false {
		return
	}

	fmt.Println("\n.......... Final disk check ..............\n")

	index, err := bogn.New(name /*dbtest*/, setts)
	if err != nil {
		panic(err)
	}
	index.Start()
	defer index.Close()

	lmdbenv, lmdbdbi, err := initlmdb(lmdbpath, lmdb.NoSync|lmdb.NoMetaSync)
	if err != nil {
		panic(err)
	}
	defer lmdbenv.Close()

	compareBognLmdb(index, lmdbenv, lmdbdbi)
}

func comparekeyvalue(key, value []byte, vlen int) bool {
	if vlen > 0 && len(value) > 0 {
		if bytes.Compare(key, value[:len(key)]) != 0 {
			panic(fmt.Errorf("expected %q, got %q", key, value))
		}
	}
	return true
}
<|endoftext|>


<commit_before>package cmd

import (
	"fmt"
	"github.com/spf13/cobra"
	"github.com/whalebrew/whalebrew/packages"
	"golang.org/x/crypto/ssh/terminal"
	"os"
	"os/exec"
)

func init() {
	RootCmd.AddCommand(runCommand)
}

var runCommand = &cobra.Command{
	Use:                "run PACKAGEPATH [ARGS ...]",
	Short:              "Run a package",
	DisableFlagParsing: true,
	RunE: func(cmd *cobra.Command, args []string) error {
		pkg, err := packages.LoadPackageFromPath(args[0])
		if err != nil {
			return err
		}
		cwd, err := os.Getwd()
		if err != nil {
			return err
		}
		dockerArgs := []string{
			"run",
			"--interactive",
			"--workdir", "/workdir",
			"-v", fmt.Sprintf("%s:/workdir", cwd),
		}

		if terminal.IsTerminal(int(os.Stdin.Fd())) {
			dockerArgs = append(dockerArgs, "--tty")
		}

		dockerArgs = append(dockerArgs, pkg.Image)
		dockerArgs = append(dockerArgs, args[1:]...)
		c := exec.Command("docker", dockerArgs...)
		c.Stdin = os.Stdin
		c.Stdout = os.Stdout
		c.Stderr = os.Stderr
		return c.Run()
	},
}
<commit_msg>Use exec to run commands<commit_after>package cmd

import (
	"fmt"
	"github.com/spf13/cobra"
	"github.com/whalebrew/whalebrew/packages"
	"golang.org/x/crypto/ssh/terminal"
	"os"
	"os/exec"
	"syscall"
)

func init() {
	RootCmd.AddCommand(runCommand)
}

var runCommand = &cobra.Command{
	Use:                "run PACKAGEPATH [ARGS ...]",
	Short:              "Run a package",
	DisableFlagParsing: true,
	RunE: func(cmd *cobra.Command, args []string) error {
		pkg, err := packages.LoadPackageFromPath(args[0])
		if err != nil {
			return err
		}
		dockerPath, err := exec.LookPath("docker")
		if err != nil {
			return err
		}

		cwd, err := os.Getwd()
		if err != nil {
			return err
		}
		dockerArgs := []string{
			dockerPath,
			"run",
			"--interactive",
			"--rm",
			"--workdir", "/workdir",
			"-v", fmt.Sprintf("%s:/workdir", cwd),
		}
		if terminal.IsTerminal(int(os.Stdin.Fd())) {
			dockerArgs = append(dockerArgs, "--tty")
		}
		dockerArgs = append(dockerArgs, pkg.Image)
		dockerArgs = append(dockerArgs, args[1:]...)

		return syscall.Exec(dockerPath, dockerArgs, os.Environ())
	},
}
<|endoftext|>


<commit_before>// Copyright © 2017 Sascha Andres <sascha.andres@outlook.com>
//
// 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 cmd

import (
	"fmt"

	"github.com/spf13/cobra"
)

// webCmd represents the web command
var webCmd = &cobra.Command{
	Use:   "web",
	Short: "A brief description of your command",
	Long: `A longer description that spans multiple lines and likely contains examples
and usage of using your command. For example:

Cobra is a CLI library for Go that empowers applications.
This application is a tool to generate the needed files
to quickly create a Cobra application.`,
	Run: func(cmd *cobra.Command, args []string) {
		// TODO: Work your own magic here
		fmt.Println("web called")
	},
}

func init() {
	RootCmd.AddCommand(webCmd)

	// Here you will define your flags and configuration settings.

	// Cobra supports Persistent Flags which will work for this command
	// and all subcommands, e.g.:
	// webCmd.PersistentFlags().String("foo", "", "A help for foo")

	// Cobra supports local flags which will only run when this command
	// is called directly, e.g.:
	// webCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")

}
<commit_msg>Added context to Cobra command<commit_after>// Copyright © 2017 Sascha Andres <sascha.andres@outlook.com>
//
// 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 cmd

import (
	"fmt"

	"github.com/spf13/cobra"
	"github.com/spf13/viper"
)

// webCmd represents the web command
var webCmd = &cobra.Command{
	Use:   "web",
	Short: "Start a server instance with a web interface",
	Long: `Use web to start a web server. Navigate with your favorite
browser to localhost:8080 ( change the binding definition )
to see the logs in your browser.

  go-logsink web --serve ":80" --bind ":50051"`,
	Run: func(cmd *cobra.Command, args []string) {
		fmt.Println("web called")
	},
}

func init() {
	RootCmd.AddCommand(webCmd)
	webCmd.Flags().StringP("bind", "b", ":50051", "Provide bind definition")
	webCmd.Flags().StringP("serve", "s", ":8080", "Provide bind definition")
	viper.BindPFlag("web.bind", webCmd.Flags().Lookup("bind"))
	viper.BindPFlag("web.serve", webCmd.Flags().Lookup("serve"))
}
<|endoftext|>


<commit_before>package cmd

import (
    "github.com/ouqiang/gocron/modules/app"
    "github.com/ouqiang/gocron/routers"
    "github.com/urfave/cli"
    "gopkg.in/macaron.v1"
    "os"
    "os/signal"
    "syscall"
    "github.com/ouqiang/gocron/modules/logger"
    "github.com/ouqiang/gocron/service"
    "github.com/ouqiang/gocron/models"
    "github.com/ouqiang/gocron/modules/setting"
    "time"
)

// web服务器默认端口
const DefaultPort = 5920

var CmdWeb = cli.Command{
    Name:   "web",
    Usage:  "run web server",
    Action: run,
    Flags: []cli.Flag{
        cli.IntFlag{
            Name:  "port,p",
            Value: DefaultPort,
            Usage: "bind port number",
        },
        cli.StringFlag{
            Name: "env,e",
            Value: "prod",
            Usage: "runtime environment, dev|test|prod",
        },
    },
}

func run(ctx *cli.Context) {
    // 设置运行环境
    setEnvironment(ctx)
    // 初始化应用
    app.InitEnv()
    // 初始化模块 DB、定时任务等
    initModule()
    // 捕捉信号,配置热更新等
    go catchSignal()
    m := macaron.Classic()

    // 注册路由
    routers.Register(m)
    // 注册中间件.
    routers.RegisterMiddleware(m)
    port := parsePort(ctx)
    m.Run(port)
}

func initModule()  {
    if !app.Installed {
        return
    }

    config, err := setting.Read(app.AppConfig)
    if err != nil {
        logger.Fatal("读取应用配置失败", err)
    }
    app.Setting = config

    models.Db = models.CreateDb()

    // 初始化定时任务
    serviceTask := new(service.Task)
    serviceTask.Initialize()
}

// 解析端口
func parsePort(ctx *cli.Context) int {
    var port int = DefaultPort
    if ctx.IsSet("port") {
        port = ctx.Int("port")
    }
    if port <= 0 || port >= 65535 {
        port = DefaultPort
    }

    return port
}

func setEnvironment(ctx *cli.Context)  {
    var env string = "prod"
    if ctx.IsSet("env") {
        env = ctx.String("env")
    }

    switch env {
        case "prod":
            macaron.Env = macaron.PROD
        case "test":
            macaron.Env = macaron.TEST
        case "dev":
            macaron.Env = macaron.DEV
    }
}

// 捕捉信号
func catchSignal()  {
    c := make(chan os.Signal)
    // todo 配置热更新, windows 不支持 syscall.SIGUSR1, syscall.SIGUSR2
    signal.Notify(c, syscall.SIGHUP, syscall.SIGINT, syscall.SIGTERM)
    for {
        s := <- c
        logger.Info("收到信号 -- ", s)
        switch s {
            case syscall.SIGHUP:
            logger.Info("收到终端断开信号, 忽略")
            case  syscall.SIGINT, syscall.SIGTERM:
            shutdown()
        }
    }
}

func shutdown()  {
    logger.Info("应用准备退出\n停止任务调度")
    serviceTask := new(service.Task)
    // 停止所有任务调度
    serviceTask.StopAll()
    taskNumInRunning := service.TaskNum.Num()
    logger.Infof("正在运行的任务有%d个", taskNumInRunning)
    for {
        if taskNumInRunning <= 0 {
            break
        }
        time.Sleep(3 * time.Second)
        taskNumInRunning = service.TaskNum.Num()
    }
    logger.Info("已退出")
    os.Exit(0)
}<commit_msg>系统未安装时, 退出程序不做任何处理<commit_after>package cmd

import (
    "github.com/ouqiang/gocron/modules/app"
    "github.com/ouqiang/gocron/routers"
    "github.com/urfave/cli"
    "gopkg.in/macaron.v1"
    "os"
    "os/signal"
    "syscall"
    "github.com/ouqiang/gocron/modules/logger"
    "github.com/ouqiang/gocron/service"
    "github.com/ouqiang/gocron/models"
    "github.com/ouqiang/gocron/modules/setting"
    "time"
)

// web服务器默认端口
const DefaultPort = 5920

var CmdWeb = cli.Command{
    Name:   "web",
    Usage:  "run web server",
    Action: run,
    Flags: []cli.Flag{
        cli.IntFlag{
            Name:  "port,p",
            Value: DefaultPort,
            Usage: "bind port number",
        },
        cli.StringFlag{
            Name: "env,e",
            Value: "prod",
            Usage: "runtime environment, dev|test|prod",
        },
    },
}

func run(ctx *cli.Context) {
    // 设置运行环境
    setEnvironment(ctx)
    // 初始化应用
    app.InitEnv()
    // 初始化模块 DB、定时任务等
    initModule()
    // 捕捉信号,配置热更新等
    go catchSignal()
    m := macaron.Classic()

    // 注册路由
    routers.Register(m)
    // 注册中间件.
    routers.RegisterMiddleware(m)
    port := parsePort(ctx)
    m.Run(port)
}

func initModule()  {
    if !app.Installed {
        return
    }

    config, err := setting.Read(app.AppConfig)
    if err != nil {
        logger.Fatal("读取应用配置失败", err)
    }
    app.Setting = config

    models.Db = models.CreateDb()

    // 初始化定时任务
    serviceTask := new(service.Task)
    serviceTask.Initialize()
}

// 解析端口
func parsePort(ctx *cli.Context) int {
    var port int = DefaultPort
    if ctx.IsSet("port") {
        port = ctx.Int("port")
    }
    if port <= 0 || port >= 65535 {
        port = DefaultPort
    }

    return port
}

func setEnvironment(ctx *cli.Context)  {
    var env string = "prod"
    if ctx.IsSet("env") {
        env = ctx.String("env")
    }

    switch env {
        case "prod":
            macaron.Env = macaron.PROD
        case "test":
            macaron.Env = macaron.TEST
        case "dev":
            macaron.Env = macaron.DEV
    }
}

// 捕捉信号
func catchSignal()  {
    c := make(chan os.Signal)
    // todo 配置热更新, windows 不支持 syscall.SIGUSR1, syscall.SIGUSR2
    signal.Notify(c, syscall.SIGHUP, syscall.SIGINT, syscall.SIGTERM)
    for {
        s := <- c
        logger.Info("收到信号 -- ", s)
        switch s {
            case syscall.SIGHUP:
            logger.Info("收到终端断开信号, 忽略")
            case  syscall.SIGINT, syscall.SIGTERM:
            shutdown()
        }
    }
}

func shutdown()  {
    if !app.Installed {
        os.Exit(0)
        return
    }
    logger.Info("应用准备退出\n停止任务调度")
    serviceTask := new(service.Task)
    // 停止所有任务调度
    serviceTask.StopAll()
    taskNumInRunning := service.TaskNum.Num()
    logger.Infof("正在运行的任务有%d个", taskNumInRunning)
    for {
        if taskNumInRunning <= 0 {
            break
        }
        time.Sleep(3 * time.Second)
        taskNumInRunning = service.TaskNum.Num()
    }
    logger.Info("已退出")
    os.Exit(0)
}<|endoftext|>


<commit_before>package main

import (
	"bufio"
	"errors"
	"flag"
	"fmt"
	"log"
	"os"
	"os/exec"
	"strconv"
	"sync"
	"time"

	"github.com/montanaflynn/stats"
)

// global command line parameters
var runs *int
var cpus [2]string
var threads *string
var hermitcore *bool

func main() {
	commandFile := parseArgs()

	commands, err := readCommands(*commandFile)
	if err != nil {
		log.Fatalf("Error reading command file %v: %v", *commandFile, err)
	}
	if len(commands) < 2 {
		log.Fatal("You must provide at least 2 commands")
	}

	commandPairs := generateCommandPairs(commands)

	fmt.Println("Executing the following command pairs:")
	for _, c := range commandPairs {
		fmt.Println(c)
	}

	for i, c := range commandPairs {
		fmt.Printf("Running pair %v\n", i)
		fmt.Println(c)
		// TODO run for every combination of CAT setup
		err := runPair(c, i)
		if err != nil {
			log.Fatalf("Error while running pair %v (%v): %v", i, c, err)
		}
	}
}

func runCmdMinTimes(cmd *exec.Cmd, min int, wg *sync.WaitGroup, measurement *string, done chan int, errs chan error) {
	defer wg.Done()

	var runtime []float64

	for i := 1; ; i++ {
		// create a copy of the command
		cmd := *cmd

		start := time.Now()
		err := cmd.Run()
		elapsed := time.Since(start)

		if err != nil {
			errs <- fmt.Errorf("Error running %v: %v", cmd.Args, err)
			return
		}

		// did the other cmd result in an error?
		if len(errs) != 0 {
			return
		}

		d := <-done

		// check if the other application was running the whole time
		if d == 2 {
			// no
			*measurement += "# "
		} else {
			runtime = append(runtime, elapsed.Seconds())
		}
		*measurement += strconv.FormatInt(elapsed.Nanoseconds(), 10)
		*measurement += "\n"

		// did we run min times?
		if i == min {
			d++
		}
		done <- d

		// both applications are done
		if d == len(cpus) {
			// ignore error, stats returns NaN
			mean, _ := stats.Mean(runtime)
			stddev, _ := stats.StandardDeviation(runtime)
			vari, _ := stats.Variance(runtime)

			fmt.Printf("%v \t %9.2fs avg. runtime \t %1.6f std. dev. \t %1.6f variance \t %v runs\n", cmd.Args, mean, stddev, vari, i)
			return
		}
	}
}

func runPair(cPair [2]string, id int) error {
	env := os.Environ()

	var cmds [len(cpus)]*exec.Cmd
	// setup commands
	for i, _ := range cmds {
		if *hermitcore {
			cmds[i] = exec.Command("taskset", "-c", cpus[i], "/bin/sh", "-c", cPair[i])
			cmds[i].Env = append(env, "HERMIT_CPUS="+*threads, "HERMIT_MEM=4G", "HERMIT_ISLE=uhyve")
		} else {
			cmds[i] = exec.Command("/bin/sh", "-c", cPair[i])
			cmds[i].Env = append(env, "GOMP_CPU_AFFINITY="+cpus[i], "OMP_NUM_THREADS="+*threads)
		}

		outfile, err := os.Create(fmt.Sprintf("%v-%v.log", id, i))
		if err != nil {
			return fmt.Errorf("Error while creating file: %v", err)
		}
		defer outfile.Close()
		cmds[i].Stdout = outfile
	}

	var measurements [len(cmds)]string
	// used to count how many apps have reached there min limit
	done := make(chan int, 1)
	done <- 0

	// used to return an error from the go-routines
	errs := make(chan error, len(cmds))

	// used to wait for the following 2 goroutines
	var wg sync.WaitGroup
	wg.Add(len(cmds))

	for i, c := range cmds {
		go runCmdMinTimes(c, *runs, &wg, &measurements[i], done, errs)
	}

	wg.Wait()

	if len(errs) != 0 {
		return <-errs
	}

	for i, s := range measurements {
		measurementsFile, err := os.Create(fmt.Sprintf("%v-%v.time", id, i))
		if err != nil {
			return fmt.Errorf("Error while creating file: %v", err)
		}
		defer measurementsFile.Close()

		_, err = measurementsFile.WriteString("# runtime in nanoseconds of \"" + cPair[i] + "\" while \"" + cPair[(i+1)%2] + "\" is running\n" + s)
		if err != nil {
			return fmt.Errorf("Error while writing measurements file: %v", err)
		}
	}

	return nil
}

func generateCommandPairs(commands []string) [][2]string {
	var pairs [][2]string
	for i, c0 := range commands {
		for j, c1 := range commands {
			if i >= j {
				continue
			}
			pairs = append(pairs, [2]string{c0, c1})
		}
	}
	return pairs
}

func readCommands(filename string) ([]string, error) {
	file, err := os.Open(filename)
	if err != nil {
		return nil, errors.New("Error opening file " + filename + ": " + err.Error())
	}
	defer file.Close()

	var commands []string

	scanner := bufio.NewScanner(file)
	for scanner.Scan() {
		commands = append(commands, scanner.Text())
	}

	if err := scanner.Err(); err != nil {
		return nil, errors.New("Error scanning commands: " + err.Error())
	}

	return commands, nil
}

func parseArgs() *string {
	runs = flag.Int("arun", 2, "Number of times the applications are executed")
	commandFile := flag.String("cmd", "cmd.txt", "Text file containing the commands to execute")
	cpus0 := flag.String("cpus0", "0-4", "List of CPUs to be used for the 1st command")
	cpus1 := flag.String("cpus1", "5-9", "List of CPUs to be used for the 2nd command")
	threads = flag.String("threads", "5", "Number of threads to be used")
	hermitcore = flag.Bool("hermitcore", false, "Use if you are executing hermitcore binaries")
	//resctrlPath := flag.String("resctrl", "/sys/fs/resctrl/", "Root path of the resctrl file system")
	flag.Parse()

	cpus[0] = *cpus0
	cpus[1] = *cpus1

	return commandFile
}
<commit_msg>Changed hardcoded '2' to len(cpus).<commit_after>package main

import (
	"bufio"
	"errors"
	"flag"
	"fmt"
	"log"
	"os"
	"os/exec"
	"strconv"
	"sync"
	"time"

	"github.com/montanaflynn/stats"
)

// global command line parameters
var runs *int
var cpus [2]string
var threads *string
var hermitcore *bool

func main() {
	commandFile := parseArgs()

	commands, err := readCommands(*commandFile)
	if err != nil {
		log.Fatalf("Error reading command file %v: %v", *commandFile, err)
	}
	if len(commands) < 2 {
		log.Fatal("You must provide at least 2 commands")
	}

	commandPairs := generateCommandPairs(commands)

	fmt.Println("Executing the following command pairs:")
	for _, c := range commandPairs {
		fmt.Println(c)
	}

	for i, c := range commandPairs {
		fmt.Printf("Running pair %v\n", i)
		fmt.Println(c)
		// TODO run for every combination of CAT setup
		err := runPair(c, i)
		if err != nil {
			log.Fatalf("Error while running pair %v (%v): %v", i, c, err)
		}
	}
}

func runCmdMinTimes(cmd *exec.Cmd, min int, wg *sync.WaitGroup, measurement *string, done chan int, errs chan error) {
	defer wg.Done()

	var runtime []float64

	for i := 1; ; i++ {
		// create a copy of the command
		cmd := *cmd

		start := time.Now()
		err := cmd.Run()
		elapsed := time.Since(start)

		if err != nil {
			errs <- fmt.Errorf("Error running %v: %v", cmd.Args, err)
			return
		}

		// did the other cmd result in an error?
		if len(errs) != 0 {
			return
		}

		d := <-done

		// check if the other application was running the whole time
		if d == len(cpus) {
			// no
			*measurement += "# "
		} else {
			runtime = append(runtime, elapsed.Seconds())
		}
		*measurement += strconv.FormatInt(elapsed.Nanoseconds(), 10)
		*measurement += "\n"

		// did we run min times?
		if i == min {
			d++
		}
		done <- d

		// both applications are done
		if d == len(cpus) {
			// ignore error, stats returns NaN
			mean, _ := stats.Mean(runtime)
			stddev, _ := stats.StandardDeviation(runtime)
			vari, _ := stats.Variance(runtime)

			fmt.Printf("%v \t %9.2fs avg. runtime \t %1.6f std. dev. \t %1.6f variance \t %v runs\n", cmd.Args, mean, stddev, vari, i)
			return
		}
	}
}

func runPair(cPair [2]string, id int) error {
	env := os.Environ()

	var cmds [len(cpus)]*exec.Cmd
	// setup commands
	for i, _ := range cmds {
		if *hermitcore {
			cmds[i] = exec.Command("taskset", "-c", cpus[i], "/bin/sh", "-c", cPair[i])
			cmds[i].Env = append(env, "HERMIT_CPUS="+*threads, "HERMIT_MEM=4G", "HERMIT_ISLE=uhyve")
		} else {
			cmds[i] = exec.Command("/bin/sh", "-c", cPair[i])
			cmds[i].Env = append(env, "GOMP_CPU_AFFINITY="+cpus[i], "OMP_NUM_THREADS="+*threads)
		}

		outfile, err := os.Create(fmt.Sprintf("%v-%v.log", id, i))
		if err != nil {
			return fmt.Errorf("Error while creating file: %v", err)
		}
		defer outfile.Close()
		cmds[i].Stdout = outfile
	}

	var measurements [len(cmds)]string
	// used to count how many apps have reached there min limit
	done := make(chan int, 1)
	done <- 0

	// used to return an error from the go-routines
	errs := make(chan error, len(cmds))

	// used to wait for the following 2 goroutines
	var wg sync.WaitGroup
	wg.Add(len(cmds))

	for i, c := range cmds {
		go runCmdMinTimes(c, *runs, &wg, &measurements[i], done, errs)
	}

	wg.Wait()

	if len(errs) != 0 {
		return <-errs
	}

	for i, s := range measurements {
		measurementsFile, err := os.Create(fmt.Sprintf("%v-%v.time", id, i))
		if err != nil {
			return fmt.Errorf("Error while creating file: %v", err)
		}
		defer measurementsFile.Close()

		_, err = measurementsFile.WriteString("# runtime in nanoseconds of \"" + cPair[i] + "\" while \"" + cPair[(i+1)%2] + "\" is running\n" + s)
		if err != nil {
			return fmt.Errorf("Error while writing measurements file: %v", err)
		}
	}

	return nil
}

func generateCommandPairs(commands []string) [][2]string {
	var pairs [][2]string
	for i, c0 := range commands {
		for j, c1 := range commands {
			if i >= j {
				continue
			}
			pairs = append(pairs, [2]string{c0, c1})
		}
	}
	return pairs
}

func readCommands(filename string) ([]string, error) {
	file, err := os.Open(filename)
	if err != nil {
		return nil, errors.New("Error opening file " + filename + ": " + err.Error())
	}
	defer file.Close()

	var commands []string

	scanner := bufio.NewScanner(file)
	for scanner.Scan() {
		commands = append(commands, scanner.Text())
	}

	if err := scanner.Err(); err != nil {
		return nil, errors.New("Error scanning commands: " + err.Error())
	}

	return commands, nil
}

func parseArgs() *string {
	runs = flag.Int("arun", 2, "Number of times the applications are executed")
	commandFile := flag.String("cmd", "cmd.txt", "Text file containing the commands to execute")
	cpus0 := flag.String("cpus0", "0-4", "List of CPUs to be used for the 1st command")
	cpus1 := flag.String("cpus1", "5-9", "List of CPUs to be used for the 2nd command")
	threads = flag.String("threads", "5", "Number of threads to be used")
	hermitcore = flag.Bool("hermitcore", false, "Use if you are executing hermitcore binaries")
	//resctrlPath := flag.String("resctrl", "/sys/fs/resctrl/", "Root path of the resctrl file system")
	flag.Parse()

	cpus[0] = *cpus0
	cpus[1] = *cpus1

	return commandFile
}
<|endoftext|>


<commit_before>package main

import (
	"bytes"
	log "github.com/sirupsen/logrus"
	"github.com/xyproto/pinterface"
	"github.com/yuin/gopher-lua"
)

// Library class is for storing and loading Lua source code to and from a data structure.

const (
	defaultID = "__lua_code_library"

	// Identifier for the Library class in Lua
	lLibraryClass = "CODELIB"
)

// Get the first argument, "self", and cast it from userdata to a library (which is really a hash map).
func checkLibrary(L *lua.LState) pinterface.IHashMap {
	ud := L.CheckUserData(1)
	if hash, ok := ud.Value.(pinterface.IHashMap); ok {
		return hash
	}
	L.ArgError(1, "code library expected")
	return nil
}

// Given a namespace and an id, register Lua code.
// Takes three strings, returns a true if it is successful.
func libRegister(L *lua.LState) int {
	lualib := checkLibrary(L) // arg 1
	namespace := L.ToString(2)
	if namespace == "" {
		L.ArgError(2, "namespace expected")
	}
	id := L.ToString(3)
	if id == "" {
		L.ArgError(3, "id expected")
	}
	code := L.ToString(4)
	if code == "" {
		log.Warn("Empty Lua code given to codelib:set")
		L.Push(lua.LBool(false))
		return 1
	}
	// Return true if there were no problems
	L.Push(lua.LBool(nil == lualib.Set(namespace, id, code)))
	return 1 // number of results
}

// Given a namespace and an id, return Lua code, or an empty string.
func libGetFunction(L *lua.LState) int {
	lualib := checkLibrary(L) // arg 1
	namespace := L.ToString(2)
	if namespace == "" {
		L.ArgError(2, "namespace expected")
	}
	id := L.ToString(3)
	if id == "" {
		L.ArgError(3, "id expected")
	}
	// Retrieve the Lua code from the HashMap
	code, err := lualib.Get(namespace, id)
	if err != nil {
		// Return an empty string if there was an error
		L.Push(lua.LString(""))
	}
	// Return the requested Lua code
	L.Push(lua.LString(code))
	return 1 // number of results
}

// Given a namespace, return all registered Lua code as a string.
// May return an empty string.
func libImport(L *lua.LState) int {
	var (
		allcode bytes.Buffer
		code    string
		err     error
	)
	lualib := checkLibrary(L) // arg 1
	namespace := L.ToString(2)
	if namespace == "" {
		L.ArgError(2, "namespace expected")
	}
	keys, err := lualib.GetAll()
	if err != nil {
		// Return an empty string if there was an error
		L.Push(lua.LString(""))
	}
	// Retrieve the code from all the keys in the given namespace
	for _, key := range keys {
		code, err = lualib.Get(namespace, key)
		if err != nil {
			continue
		}
		allcode.WriteString(code + "\n\n")
	}
	// Returned all the requested Lua code, joined with double newlines
	L.Push(lua.LString(allcode.String()))
	return 1 // number of results
}

// String representation
func libToString(L *lua.LState) int {
	L.Push(lua.LString("Code Library"))
	return 1 // number of results
}

// Clear the current code library
func libClear(L *lua.LState) int {
	lualib := checkLibrary(L) // arg 1
	L.Push(lua.LBool(nil == lualib.Remove()))
	return 1 // number of results
}

// Create a new code library.
// id is the name of the hash map.
func newCodeLibrary(L *lua.LState, creator pinterface.ICreator, id string) (*lua.LUserData, error) {
	// Create a new Lua Library (hash map)
	lualib, err := creator.NewHashMap(id)
	if err != nil {
		return nil, err
	}
	// Create a new userdata struct
	ud := L.NewUserData()
	ud.Value = lualib
	L.SetMetatable(ud, L.GetTypeMetatable(lLibraryClass))
	return ud, nil
}

// The hash map methods that are to be registered
var libMethods = map[string]lua.LGFunction{
	"__tostring": libToString,
	"set":        libRegister,
	"get":        libGetFunction,
	"import":     libImport,
	"clear":      libClear,
}

// Make functions related to building a library of Lua code available
func exportCodeLibrary(L *lua.LState, userstate pinterface.IUserState) {
	creator := userstate.Creator()

	// Register the Library class and the methods that belongs with it.
	mt := L.NewTypeMetatable(lLibraryClass)
	mt.RawSetH(lua.LString("__index"), mt)
	L.SetFuncs(mt, libMethods)

	// The constructor for new Libraries takes only an optional id
	L.SetGlobal("CodeLib", L.NewFunction(func(L *lua.LState) int {
		// Check if the optional argument is given
		id := defaultID
		if L.GetTop() == 1 {
			id = L.ToString(1)
		}

		// Create a new Library in Lua
		userdata, err := newCodeLibrary(L, creator, id)
		if err != nil {
			L.Push(lua.LNil)
			L.Push(lua.LString(err.Error()))
			L.Push(lua.LNumber(1))
			return 3 // Number of returned values
		}

		// Return the hash map object
		L.Push(userdata)
		return 1 // number of results
	}))

}
<commit_msg>Changes to the code library<commit_after>package main

import (
	log "github.com/sirupsen/logrus"
	"github.com/xyproto/pinterface"
	"github.com/yuin/gopher-lua"
)

// Library class is for storing and loading Lua source code to and from a data structure.

const (
	defaultID = "__lua_code_library"

	// Identifier for the Library class in Lua
	lLibraryClass = "CODELIB"
)

// Get the first argument, "self", and cast it from userdata to a library (which is really a hash map).
func checkLibrary(L *lua.LState) pinterface.IKeyValue {
	ud := L.CheckUserData(1)
	if hash, ok := ud.Value.(pinterface.IKeyValue); ok {
		return hash
	}
	L.ArgError(1, "code library expected")
	return nil
}

// Given a namespace, register Lua code.
// Takes two strings, returns a true if it is successful.
func libAdd(L *lua.LState) int {
	lualib := checkLibrary(L) // arg 1
	namespace := L.ToString(2)
	if namespace == "" {
		L.ArgError(2, "namespace expected")
	}
	code := L.ToString(3)
	if code == "" {
		log.Warn("Empty Lua code given to codelib:add")
		L.Push(lua.LBool(false))
		return 1
	}
	// Append the new code to the old code, if any
	oldcode, err := lualib.Get(namespace)
	if err != nil {
		oldcode = ""
	} else {
		oldcode += "\n"
	}
	L.Push(lua.LBool(nil == lualib.Set(namespace, oldcode+code)))
	return 1 // number of results
}

// Given a namespace, register Lua code as the only code.
// Takes two strings, returns a true if it is successful.
func libSet(L *lua.LState) int {
	lualib := checkLibrary(L) // arg 1
	namespace := L.ToString(2)
	if namespace == "" {
		L.ArgError(2, "namespace expected")
	}
	code := L.ToString(3)
	if code == "" {
		log.Warn("Empty Lua code given to codelib:set")
		L.Push(lua.LBool(false))
		return 1
	}
	L.Push(lua.LBool(nil == lualib.Set(namespace, code)))
	return 1 // number of results
}

// Given a namespace, return Lua code, or an empty string.
func libGet(L *lua.LState) int {
	lualib := checkLibrary(L) // arg 1
	namespace := L.ToString(2)
	if namespace == "" {
		L.ArgError(2, "namespace expected")
	}
	// Retrieve the Lua code from the HashMap
	code, err := lualib.Get(namespace)
	if err != nil {
		// Return an empty string if there was an error
		L.Push(lua.LString(""))
	}
	// Return the requested Lua code
	L.Push(lua.LString(code))
	return 1 // number of results
}

// Given a namespace, fetch all registered Lua code as a string.
// Then run the Lua code for this LState.
// Returns true of successful.
func libImport(L *lua.LState) int {
	lualib := checkLibrary(L) // arg 1
	namespace := L.ToString(2)
	if namespace == "" {
		L.ArgError(2, "namespace expected")
	}

	code, err := lualib.Get(namespace)
	if err != nil {
		// Return false if there was an error
		L.Push(lua.LBool(false)) // error
		return 1
	}

	if err := L.DoString(code); err != nil {
		L.Close()

		log.Errorf("Error when importing Lua code:\n%s", err)
		L.Push(lua.LBool(false)) // error
		return 1                 // number of results
	}

	L.Push(lua.LBool(true)) // ok
	return 1                // number of results
}

// String representation
func libToString(L *lua.LState) int {
	L.Push(lua.LString("Code Library"))
	return 1 // number of results
}

// Clear the current code library
func libClear(L *lua.LState) int {
	lualib := checkLibrary(L) // arg 1
	L.Push(lua.LBool(nil == lualib.Remove()))
	return 1 // number of results
}

// Create a new code library.
// id is the name of the hash map.
func newCodeLibrary(L *lua.LState, creator pinterface.ICreator, id string) (*lua.LUserData, error) {
	// Create a new Lua Library (hash map)
	lualib, err := creator.NewKeyValue(id)
	if err != nil {
		return nil, err
	}
	// Create a new userdata struct
	ud := L.NewUserData()
	ud.Value = lualib
	L.SetMetatable(ud, L.GetTypeMetatable(lLibraryClass))
	return ud, nil
}

// The hash map methods that are to be registered
var libMethods = map[string]lua.LGFunction{
	"__tostring": libToString,
	"add":        libAdd,
	"set":        libSet,
	"get":        libGet,
	"import":     libImport,
	"clear":      libClear,
}

// Make functions related to building a library of Lua code available
func exportCodeLibrary(L *lua.LState, userstate pinterface.IUserState) {
	creator := userstate.Creator()

	// Register the Library class and the methods that belongs with it.
	mt := L.NewTypeMetatable(lLibraryClass)
	mt.RawSetH(lua.LString("__index"), mt)
	L.SetFuncs(mt, libMethods)

	// The constructor for new Libraries takes only an optional id
	L.SetGlobal("CodeLib", L.NewFunction(func(L *lua.LState) int {
		// Check if the optional argument is given
		id := defaultID
		if L.GetTop() == 1 {
			id = L.ToString(1)
		}

		// Create a new Library in Lua
		userdata, err := newCodeLibrary(L, creator, id)
		if err != nil {
			L.Push(lua.LNil)
			L.Push(lua.LString(err.Error()))
			L.Push(lua.LNumber(1))
			return 3 // Number of returned values
		}

		// Return the hash map object
		L.Push(userdata)
		return 1 // number of results
	}))

}
<|endoftext|>


<commit_before>package bootstrap

import (
	"fmt"
	"net"
	"net/http"
	"net/url"
	"strconv"
	"strings"
	"time"
)

type WaitAction struct {
	URL    string `json:"url"`
	Host   string `json:"host"`
	Status int    `json:"status"`
}

func init() {
	Register("wait", &WaitAction{})
}

func (a *WaitAction) Run(s *State) error {
	const waitMax = time.Minute
	const waitInterval = 500 * time.Millisecond

	if a.Status == 0 {
		a.Status = 200
	}

	u, err := url.Parse(interpolate(s, a.URL))
	if err != nil {
		return err
	}
	if err := lookupDiscoverdURLHost(s, u, waitMax); err != nil {
		return err
	}

	start := time.Now()
	for {
		var result string

		switch u.Scheme {
		case "http":
			req, err := http.NewRequest("GET", u.String(), nil)
			if err != nil {
				return err
			}
			if a.Host != "" {
				req.Host = interpolate(s, a.Host)
			}
			res, err := http.DefaultClient.Do(req)
			if err != nil {
				result = fmt.Sprintf("%q", err)
				goto fail
			}
			res.Body.Close()
			if res.StatusCode == a.Status {
				return nil
			}
			result = strconv.Itoa(res.StatusCode)
		case "tcp":
			conn, err := net.Dial("tcp", u.Host)
			if err != nil {
				result = fmt.Sprintf("%q", err)
				goto fail
			}
			conn.Close()
			return nil
		default:
			return fmt.Errorf("bootstrap: unknown protocol")
		}
	fail:
		if time.Now().Sub(start) >= waitMax {
			return fmt.Errorf("bootstrap: timed out waiting for %s, last response %s", a.URL, result)
		}
		time.Sleep(waitInterval)
	}
}

func lookupDiscoverdURLHost(s *State, u *url.URL, timeout time.Duration) error {
	if strings.HasSuffix(u.Host, ".discoverd") {
		d, err := s.DiscoverdClient()
		if err != nil {
			return err
		}
		instances, err := d.Instances(strings.Split(u.Host, ".")[0], timeout)
		if err != nil {
			return err
		}
		u.Host = instances[0].Addr
	}
	return nil
}
<commit_msg>bootstrap: Bump wait time to 5 minutes<commit_after>package bootstrap

import (
	"fmt"
	"net"
	"net/http"
	"net/url"
	"strconv"
	"strings"
	"time"
)

type WaitAction struct {
	URL    string `json:"url"`
	Host   string `json:"host"`
	Status int    `json:"status"`
}

func init() {
	Register("wait", &WaitAction{})
}

func (a *WaitAction) Run(s *State) error {
	const waitMax = 5 * time.Minute
	const waitInterval = 500 * time.Millisecond

	if a.Status == 0 {
		a.Status = 200
	}

	u, err := url.Parse(interpolate(s, a.URL))
	if err != nil {
		return err
	}
	if err := lookupDiscoverdURLHost(s, u, waitMax); err != nil {
		return err
	}

	start := time.Now()
	for {
		var result string

		switch u.Scheme {
		case "http":
			req, err := http.NewRequest("GET", u.String(), nil)
			if err != nil {
				return err
			}
			if a.Host != "" {
				req.Host = interpolate(s, a.Host)
			}
			res, err := http.DefaultClient.Do(req)
			if err != nil {
				result = fmt.Sprintf("%q", err)
				goto fail
			}
			res.Body.Close()
			if res.StatusCode == a.Status {
				return nil
			}
			result = strconv.Itoa(res.StatusCode)
		case "tcp":
			conn, err := net.Dial("tcp", u.Host)
			if err != nil {
				result = fmt.Sprintf("%q", err)
				goto fail
			}
			conn.Close()
			return nil
		default:
			return fmt.Errorf("bootstrap: unknown protocol")
		}
	fail:
		if time.Now().Sub(start) >= waitMax {
			return fmt.Errorf("bootstrap: timed out waiting for %s, last response %s", a.URL, result)
		}
		time.Sleep(waitInterval)
	}
}

func lookupDiscoverdURLHost(s *State, u *url.URL, timeout time.Duration) error {
	if strings.HasSuffix(u.Host, ".discoverd") {
		d, err := s.DiscoverdClient()
		if err != nil {
			return err
		}
		instances, err := d.Instances(strings.Split(u.Host, ".")[0], timeout)
		if err != nil {
			return err
		}
		u.Host = instances[0].Addr
	}
	return nil
}
<|endoftext|>


<commit_before>package cmd

import (
	"github.com/deployithq/deployit/cmd/daemon"
	"github.com/jawher/mow.cli"
	"os"
	"github.com/deployithq/deployit/cmd/daemon/context"
)

func Start() {

	var ctx = context.Get()
	ctx.Version = "0.1.0"

	app := cli.App("deployit", "deploy it tool service")

	app.Version("v version", "deployit "+ctx.Version)

	var help = app.Bool(cli.BoolOpt{Name: "h help", Value: false, Desc: "Show the help info and exit", HideValue: true})

	app.Before = func() {
		if *help {
			app.PrintLongHelp()
		}
	}

	app.Command("daemon", "Run deployit in daemon mode", daemon.Run)

	app.Run(os.Args)
}
<commit_msg>update<commit_after>package cmd

import (
	"github.com/deployithq/deployit/cmd/daemon"
	"github.com/deployithq/deployit/cmd/daemon/context"
	"github.com/jawher/mow.cli"
	"os"
)

func Start() {

	var ctx = context.Get()
	ctx.Version = "0.1.0"

	app := cli.App("deployit", "deploy it tool service")

	app.Version("v version", "deployit "+ctx.Version)

	var help = app.Bool(cli.BoolOpt{Name: "h help", Value: false, Desc: "Show the help info and exit", HideValue: true})

	app.Before = func() {
		if *help {
			app.PrintLongHelp()
		}
	}

	app.Command("daemon", "Run deployit in daemon mode", daemon.Run)

	app.Run(os.Args)
}
<|endoftext|>


<commit_before>// Package command holds support functions and types for writing gb and gb plugins
package cmd

import (
	"flag"
	"fmt"
	"os"
	"path/filepath"

	"github.com/constabulary/gb"
)

// Command represents a subcommand, or plugin that is executed within
// a gb project.
type Command struct {
	// Name of the command
	Name string

	// UsageLine demonstrates how to use this command
	UsageLine string

	// Single line description of the purpose of the command
	Short string

	// Description of this command
	Long string

	// Run is invoked with a Context derived from the Project and arguments
	// left over after flag parsing.
	Run func(ctx *gb.Context, args []string) error

	// AddFlags installs additional flags to be parsed before Run.
	AddFlags func(fs *flag.FlagSet)

	// Allow plugins to modify arguments
	FlagParse func(fs *flag.FlagSet, args []string) error

	// ParseArgs provides an alterntive method to parse arguments.
	// By default, arguments will be parsed as import paths with
	// ImportPaths
	ParseArgs func(ctx *gb.Context, cwd string, args []string) []string
}

// Runnable indicates this is a command that can be involved.
// Non runnable commands are only informational.
func (c *Command) Runnable() bool { return c.Run != nil }

// Hidden indicates this is a command which is hidden from help / alldoc.go.
func (c *Command) Hidden() bool { return c.Name == "depset" }

// RunCommand detects the project root, parses flags and runs the Command.
func RunCommand(fs *flag.FlagSet, cmd *Command, projectroot, goroot string, args []string) error {
	if cmd.AddFlags != nil {
		cmd.AddFlags(fs)
	}
	if err := fs.Parse(args); err != nil {
		fs.Usage()
		os.Exit(1)
	}
	args = fs.Args() // reset to the remaining arguments

	ctx, err := NewContext(projectroot, gb.GcToolchain())
	if err != nil {
		return fmt.Errorf("unable to construct context: %v", err)
	}

	gb.Debugf("args: %v", args)
	return cmd.Run(ctx, args)
}

// NewContext creates a gb.Context for the project root.
func NewContext(projectroot string, options ...func(*gb.Context) error) (*gb.Context, error) {
	if projectroot == "" {
		return nil, fmt.Errorf("project root is blank")
	}

	root, err := FindProjectroot(projectroot)
	if err != nil {
		return nil, fmt.Errorf("could not locate project root: %v", err)
	}
	project := gb.NewProject(root,
		gb.SourceDir(filepath.Join(root, "src")),
		gb.SourceDir(filepath.Join(root, "vendor", "src")),
	)

	gb.Debugf("project root %q", project.Projectdir())
	return project.NewContext(options...)
}

func mkdir(path string) error {
	return os.MkdirAll(path, 0755)
}
<commit_msg>fix typo<commit_after>// Package command holds support functions and types for writing gb and gb plugins
package cmd

import (
	"flag"
	"fmt"
	"os"
	"path/filepath"

	"github.com/constabulary/gb"
)

// Command represents a subcommand, or plugin that is executed within
// a gb project.
type Command struct {
	// Name of the command
	Name string

	// UsageLine demonstrates how to use this command
	UsageLine string

	// Single line description of the purpose of the command
	Short string

	// Description of this command
	Long string

	// Run is invoked with a Context derived from the Project and arguments
	// left over after flag parsing.
	Run func(ctx *gb.Context, args []string) error

	// AddFlags installs additional flags to be parsed before Run.
	AddFlags func(fs *flag.FlagSet)

	// Allow plugins to modify arguments
	FlagParse func(fs *flag.FlagSet, args []string) error

	// ParseArgs provides an alternative method to parse arguments.
	// By default, arguments will be parsed as import paths with
	// ImportPaths
	ParseArgs func(ctx *gb.Context, cwd string, args []string) []string
}

// Runnable indicates this is a command that can be involved.
// Non runnable commands are only informational.
func (c *Command) Runnable() bool { return c.Run != nil }

// Hidden indicates this is a command which is hidden from help / alldoc.go.
func (c *Command) Hidden() bool { return c.Name == "depset" }

// RunCommand detects the project root, parses flags and runs the Command.
func RunCommand(fs *flag.FlagSet, cmd *Command, projectroot, goroot string, args []string) error {
	if cmd.AddFlags != nil {
		cmd.AddFlags(fs)
	}
	if err := fs.Parse(args); err != nil {
		fs.Usage()
		os.Exit(1)
	}
	args = fs.Args() // reset to the remaining arguments

	ctx, err := NewContext(projectroot, gb.GcToolchain())
	if err != nil {
		return fmt.Errorf("unable to construct context: %v", err)
	}

	gb.Debugf("args: %v", args)
	return cmd.Run(ctx, args)
}

// NewContext creates a gb.Context for the project root.
func NewContext(projectroot string, options ...func(*gb.Context) error) (*gb.Context, error) {
	if projectroot == "" {
		return nil, fmt.Errorf("project root is blank")
	}

	root, err := FindProjectroot(projectroot)
	if err != nil {
		return nil, fmt.Errorf("could not locate project root: %v", err)
	}
	project := gb.NewProject(root,
		gb.SourceDir(filepath.Join(root, "src")),
		gb.SourceDir(filepath.Join(root, "vendor", "src")),
	)

	gb.Debugf("project root %q", project.Projectdir())
	return project.NewContext(options...)
}

func mkdir(path string) error {
	return os.MkdirAll(path, 0755)
}
<|endoftext|>


<commit_before>// Copyright © 2020 Karim Radhouani <medkarimrdi@gmail.com>
//
// 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 cmd

import (
	"context"
	"encoding/json"
	"fmt"
	"net"
	"strings"
	"sync"
	"time"

	"github.com/google/gnxi/utils/xpath"
	"github.com/openconfig/gnmi/proto/gnmi"
	"github.com/spf13/cobra"
	"github.com/spf13/viper"
	"google.golang.org/grpc/metadata"
	"google.golang.org/protobuf/encoding/prototext"
)

// getCmd represents the get command
var getCmd = &cobra.Command{
	Use:   "get",
	Short: "run gnmi get on targets",

	RunE: func(cmd *cobra.Command, args []string) error {
		ctx, cancel := context.WithCancel(context.Background())
		defer cancel()
		setupCloseHandler(cancel)
		var err error
		addresses := viper.GetStringSlice("address")
		if len(addresses) == 0 {
			fmt.Println("no grpc server address specified")
			return nil
		}
		username := viper.GetString("username")
		if username == "" {
			if username, err = readUsername(); err != nil {
				return err
			}
		}
		password := viper.GetString("password")
		if password == "" {
			if password, err = readPassword(); err != nil {
				return err
			}
		}
		encodingVal, ok := gnmi.Encoding_value[strings.Replace(strings.ToUpper(viper.GetString("encoding")), "-", "_", -1)]
		if !ok {
			return fmt.Errorf("invalid encoding type '%s'", viper.GetString("encoding"))
		}
		req := &gnmi.GetRequest{
			UseModels: make([]*gnmi.ModelData, 0),
			Path:      make([]*gnmi.Path, 0),
			Encoding:  gnmi.Encoding(encodingVal),
		}
		models := viper.GetStringSlice("get-model")
		prefix := viper.GetString("get-prefix")
		if prefix != "" {
			gnmiPrefix, err := xpath.ToGNMIPath(prefix)
			if err != nil {
				return fmt.Errorf("prefix parse error: %v", err)
			}
			req.Prefix = gnmiPrefix
		}
		paths := viper.GetStringSlice("get-path")
		for _, p := range paths {
			gnmiPath, err := xpath.ToGNMIPath(strings.TrimSpace(p))
			if err != nil {
				return fmt.Errorf("path parse error: %v", err)
			}
			req.Path = append(req.Path, gnmiPath)
		}
		dataType := viper.GetString("get-type")
		if dataType != "" {
			dti, ok := gnmi.GetRequest_DataType_value[strings.ToUpper(dataType)]
			if !ok {
				return fmt.Errorf("unknown data type %s", dataType)
			}
			req.Type = gnmi.GetRequest_DataType(dti)
		}
		wg := new(sync.WaitGroup)
		wg.Add(len(addresses))
		lock := new(sync.Mutex)
		for _, addr := range addresses {
			go func(address string) {
				defer wg.Done()
				_, _, err := net.SplitHostPort(address)
				if err != nil {
					if strings.Contains(err.Error(), "missing port in address") {
						address = net.JoinHostPort(address, defaultGrpcPort)
					} else {
						logger.Printf("error parsing address '%s': %v", address, err)
						return
					}
				}
				conn, err := createGrpcConn(address)
				if err != nil {
					logger.Printf("connection to %s failed: %v", address, err)
					return
				}
				client := gnmi.NewGNMIClient(conn)
				nctx, cancel := context.WithCancel(ctx)
				defer cancel()
				nctx = metadata.AppendToOutgoingContext(nctx, "username", username, "password", password)
				xreq := req
				if len(models) > 0 {
					spModels, unspModels, err := filterModels(ctx, client, models)
					if err != nil {
						logger.Printf("failed getting supported models from '%s': %v", address, err)
						return
					}
					if len(unspModels) > 0 {
						logger.Printf("found unsupported models for target '%s': %+v", address, unspModels)
					}
					for _, m := range spModels {
						xreq.UseModels = append(xreq.UseModels, m)
					}
				}
				logger.Printf("sending gNMI GetRequest: prefix='%v', path='%v', type='%v', encoding='%v', models='%+v', extension='%+v' to %s", xreq.Prefix, xreq.Path, xreq.Type, xreq.Encoding, xreq.UseModels, xreq.Extension, address)
				response, err := client.Get(nctx, xreq)
				if err != nil {
					logger.Printf("failed sending GetRequest to %s: %v", address, err)
					return
				}
				printPrefix := ""
				if len(addresses) > 1 && !viper.GetBool("no-prefix") {
					printPrefix = fmt.Sprintf("[%s] ", address)
				}
				lock.Lock()
				printGetResponse(printPrefix, response)
				lock.Unlock()
			}(addr)
		}
		wg.Wait()
		return nil
	},
}

func init() {
	rootCmd.AddCommand(getCmd)

	getCmd.Flags().StringSliceP("path", "", []string{""}, "get request paths")
	getCmd.MarkFlagRequired("path")
	getCmd.Flags().StringP("prefix", "", "", "get request prefix")
	getCmd.Flags().StringSliceP("model", "", []string{""}, "get request model(s)")
	getCmd.Flags().StringP("type", "t", "ALL", "the type of data that is requested from the target. one of: ALL, CONFIG, STATE, OPERATIONAL")
	viper.BindPFlag("get-path", getCmd.Flags().Lookup("path"))
	viper.BindPFlag("get-prefix", getCmd.Flags().Lookup("prefix"))
	viper.BindPFlag("get-model", getCmd.Flags().Lookup("model"))
	viper.BindPFlag("get-type", getCmd.Flags().Lookup("type"))
}

func printGetResponse(printPrefix string, response *gnmi.GetResponse) {
	if viper.GetString("format") == "textproto" {
		fmt.Printf("%s\n", indent(printPrefix, prototext.Format(response)))
		return
	}
	for _, notif := range response.Notification {
		msg := new(msg)
		msg.Timestamp = notif.Timestamp
		t := time.Unix(0, notif.Timestamp)
		msg.Time = &t
		msg.Prefix = gnmiPathToXPath(notif.Prefix)
		for i, upd := range notif.Update {
			if upd.Val == nil {
				if viper.GetBool("debug") {
					logger.Printf("DEBUG: got a nil val update: %+v", upd)
				}
				continue
			}
			pathElems := make([]string, 0, len(upd.Path.Elem))
			for _, pElem := range upd.Path.Elem {
				pathElems = append(pathElems, pElem.GetName())
			}
			value, err := getValue(upd.Val)
			if err != nil {
				logger.Println(err)
			}
			msg.Updates = append(msg.Updates,
				&update{
					Path:   gnmiPathToXPath(upd.Path),
					Values: make(map[string]interface{}),
				})
			msg.Updates[i].Values[strings.Join(pathElems, "/")] = value
		}
		dMsg, err := json.MarshalIndent(msg, printPrefix, "  ")
		if err != nil {
			logger.Printf("error marshling json msg:%v", err)
			return
		}
		fmt.Printf("%s%s\n", printPrefix, string(dMsg))
	}
	fmt.Println()
}

func stringInList(s string, l []string) bool {
	for _, ss := range l {
		if s == ss {
			return true
		}
	}
	return false
}
<commit_msg>deanonimize getrequest goroutine<commit_after>// Copyright © 2020 Karim Radhouani <medkarimrdi@gmail.com>
//
// 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 cmd

import (
	"context"
	"encoding/json"
	"fmt"
	"net"
	"strings"
	"sync"
	"time"

	"github.com/google/gnxi/utils/xpath"
	"github.com/openconfig/gnmi/proto/gnmi"
	"github.com/spf13/cobra"
	"github.com/spf13/viper"
	"google.golang.org/grpc/metadata"
	"google.golang.org/protobuf/encoding/prototext"
)

// getCmd represents the get command
var getCmd = &cobra.Command{
	Use:   "get",
	Short: "run gnmi get on targets",

	RunE: func(cmd *cobra.Command, args []string) error {
		ctx, cancel := context.WithCancel(context.Background())
		defer cancel()
		setupCloseHandler(cancel)
		var err error
		addresses := viper.GetStringSlice("address")
		if len(addresses) == 0 {
			fmt.Println("no grpc server address specified")
			return nil
		}
		username := viper.GetString("username")
		if username == "" {
			if username, err = readUsername(); err != nil {
				return err
			}
		}
		password := viper.GetString("password")
		if password == "" {
			if password, err = readPassword(); err != nil {
				return err
			}
		}
		encodingVal, ok := gnmi.Encoding_value[strings.Replace(strings.ToUpper(viper.GetString("encoding")), "-", "_", -1)]
		if !ok {
			return fmt.Errorf("invalid encoding type '%s'", viper.GetString("encoding"))
		}
		req := &gnmi.GetRequest{
			UseModels: make([]*gnmi.ModelData, 0),
			Path:      make([]*gnmi.Path, 0),
			Encoding:  gnmi.Encoding(encodingVal),
		}
		prefix := viper.GetString("get-prefix")
		if prefix != "" {
			gnmiPrefix, err := xpath.ToGNMIPath(prefix)
			if err != nil {
				return fmt.Errorf("prefix parse error: %v", err)
			}
			req.Prefix = gnmiPrefix
		}
		paths := viper.GetStringSlice("get-path")
		for _, p := range paths {
			gnmiPath, err := xpath.ToGNMIPath(strings.TrimSpace(p))
			if err != nil {
				return fmt.Errorf("path parse error: %v", err)
			}
			req.Path = append(req.Path, gnmiPath)
		}
		dataType := viper.GetString("get-type")
		if dataType != "" {
			dti, ok := gnmi.GetRequest_DataType_value[strings.ToUpper(dataType)]
			if !ok {
				return fmt.Errorf("unknown data type %s", dataType)
			}
			req.Type = gnmi.GetRequest_DataType(dti)
		}
		wg := new(sync.WaitGroup)
		wg.Add(len(addresses))
		lock := new(sync.Mutex)
		for _, addr := range addresses {
			go reqGet(ctx, req, addr, username, password, wg, lock)
		}
		wg.Wait()
		return nil
	},
}

func reqGet(ctx context.Context, req *gnmi.GetRequest, address, username, password string, wg *sync.WaitGroup, lock *sync.Mutex) {
	defer wg.Done()
	_, _, err := net.SplitHostPort(address)
	if err != nil {
		if strings.Contains(err.Error(), "missing port in address") {
			address = net.JoinHostPort(address, defaultGrpcPort)
		} else {
			logger.Printf("error parsing address '%s': %v", address, err)
			return
		}
	}
	conn, err := createGrpcConn(address)
	if err != nil {
		logger.Printf("connection to %s failed: %v", address, err)
		return
	}
	client := gnmi.NewGNMIClient(conn)
	nctx, cancel := context.WithCancel(ctx)
	defer cancel()
	nctx = metadata.AppendToOutgoingContext(nctx, "username", username, "password", password)
	xreq := req
	models := viper.GetStringSlice("get-model")
	if len(models) > 0 {
		spModels, unspModels, err := filterModels(ctx, client, models)
		if err != nil {
			logger.Printf("failed getting supported models from '%s': %v", address, err)
			return
		}
		if len(unspModels) > 0 {
			logger.Printf("found unsupported models for target '%s': %+v", address, unspModels)
		}
		for _, m := range spModels {
			xreq.UseModels = append(xreq.UseModels, m)
		}
	}
	logger.Printf("sending gNMI GetRequest: prefix='%v', path='%v', type='%v', encoding='%v', models='%+v', extension='%+v' to %s", xreq.Prefix, xreq.Path, xreq.Type, xreq.Encoding, xreq.UseModels, xreq.Extension, address)
	response, err := client.Get(nctx, xreq)
	if err != nil {
		logger.Printf("failed sending GetRequest to %s: %v", address, err)
		return
	}

	lock.Lock()
	printGetResponse(address, response)
	lock.Unlock()
}

func printGetResponse(address string, response *gnmi.GetResponse) {
	printPrefix := ""
	addresses := viper.GetStringSlice("address")
	if len(addresses) > 1 && !viper.GetBool("no-prefix") {
		printPrefix = fmt.Sprintf("[%s] ", address)
	}
	if viper.GetString("format") == "textproto" {
		fmt.Printf("%s\n", indent(printPrefix, prototext.Format(response)))
		return
	}
	for _, notif := range response.Notification {
		msg := new(msg)
		msg.Timestamp = notif.Timestamp
		t := time.Unix(0, notif.Timestamp)
		msg.Time = &t
		msg.Prefix = gnmiPathToXPath(notif.Prefix)
		for i, upd := range notif.Update {
			if upd.Val == nil {
				if viper.GetBool("debug") {
					logger.Printf("DEBUG: got a nil val update: %+v", upd)
				}
				continue
			}
			pathElems := make([]string, 0, len(upd.Path.Elem))
			for _, pElem := range upd.Path.Elem {
				pathElems = append(pathElems, pElem.GetName())
			}
			value, err := getValue(upd.Val)
			if err != nil {
				logger.Println(err)
			}
			msg.Updates = append(msg.Updates,
				&update{
					Path:   gnmiPathToXPath(upd.Path),
					Values: make(map[string]interface{}),
				})
			msg.Updates[i].Values[strings.Join(pathElems, "/")] = value
		}
		dMsg, err := json.MarshalIndent(msg, printPrefix, "  ")
		if err != nil {
			logger.Printf("error marshling json msg:%v", err)
			return
		}
		fmt.Printf("%s%s\n", printPrefix, string(dMsg))
	}
	fmt.Println()
}

func stringInList(s string, l []string) bool {
	for _, ss := range l {
		if s == ss {
			return true
		}
	}
	return false
}

func init() {
	rootCmd.AddCommand(getCmd)

	getCmd.Flags().StringSliceP("path", "", []string{""}, "get request paths")
	getCmd.MarkFlagRequired("path")
	getCmd.Flags().StringP("prefix", "", "", "get request prefix")
	getCmd.Flags().StringSliceP("model", "", []string{""}, "get request model(s)")
	getCmd.Flags().StringP("type", "t", "ALL", "the type of data that is requested from the target. one of: ALL, CONFIG, STATE, OPERATIONAL")
	viper.BindPFlag("get-path", getCmd.Flags().Lookup("path"))
	viper.BindPFlag("get-prefix", getCmd.Flags().Lookup("prefix"))
	viper.BindPFlag("get-model", getCmd.Flags().Lookup("model"))
	viper.BindPFlag("get-type", getCmd.Flags().Lookup("type"))
}
<|endoftext|>