<commit_before>package main

import (
	"bufio"
	"bytes"
	"errors"
	"fmt"
	"os"
	"os/exec"
	"strconv"
	"time"

	"github.com/gi4nks/quant"
	"gopkg.in/urfave/cli.v1"
)

var parrot = quant.NewParrot("ambros")

var settings = Settings{}
var repository = Repository{}

var pathUtils = quant.NewPathUtils()

func initDB() {
	repository.InitDB()
	repository.InitSchema()
}

func closeDB() {
	repository.CloseDB()
}

func readSettings() {
	settings.LoadSettings()

	if settings.DebugMode() {
		parrot = quant.NewVerboseParrot("ambros")
	}
}

func main() {
	readSettings()
	initDB()

	// -------------------
	app := cli.NewApp()
	app.Name = "ambros"
	app.Usage = "the personal command butler!!!!"
	app.Version = "0.2.1"
	app.Copyright = "gi4nks - 2016"

	//app.EnableBashCompletion = true

	app.Commands = []cli.Command{
		{
			Name:    "settings",
			Aliases: []string{"st"},
			Usage:   "settings sub menu",
			Subcommands: []cli.Command{
				{
					Name:    "list",
					Aliases: []string{"ls"},
					Usage:   "list current configuration settings",
					Action:  CmdSettingsList,
				},
				{
					Name:    "revive",
					Aliases: []string{"re"},
					Usage:   "revive ambros",
					Subcommands: []cli.Command{
						{
							Name:    "complete",
							Aliases: []string{"com"},
							Usage:   "revive ambros deleting completely the database",
							Action:  CmdSettingsReviveComplete,
						},
						{
							Name:    "partial",
							Aliases: []string{"par"},
							Usage:   "revive ambros preserving the stored commands",
							Action:  CmdSettingsRevivePartial,
						},
					},
				},
				{
					Name:    "logs",
					Aliases: []string{"lo"},
					Usage:   "show me the logs of ambros",
					Subcommands: []cli.Command{
						{
							Name:    "id",
							Aliases: []string{"id"},
							Usage:   "Get the log of specific id",
							Action:  CmdSettingsLogsById,
						},
						{
							Name:    "all",
							Aliases: []string{"all"},
							Usage:   "Get all the logs",
							Action:  CmdSettingsLogs,
						},
					},
				},
			},
		},
		{
			Name:    "run",
			Aliases: []string{"ru"},
			Usage:   "run a command, remember to run the command with -- before",
			Action:  CmdRun,
			Flags: []cli.Flag{
				StoreFlag,
			},
		},
		{
			Name:    "last",
			Aliases: []string{"ll"},
			Usage:   "show the last executed commands ",
			Action:  CmdLast,
		},
		{
			Name:    "output",
			Aliases: []string{"ou"},
			Usage:   "show me the output of a command executed with ambros",
			Action:  CmdOutput,
		},
		{
			Name:    "store",
			Aliases: []string{"so"},
			Usage:   "store functionalities sub commands",
			Subcommands: []cli.Command{
				{
					Name:    "id",
					Aliases: []string{"id"},
					Usage:   "stores an executed command ",
					Action:  CmdStoreRunId,
				},
				{
					Name:    "push",
					Aliases: []string{"pu"},
					Usage:   "push a not executed command in the stack",
					Action:  CmdStorePush,
				},
				{
					Name:    "show",
					Aliases: []string{"sh"},
					Usage:   "Show all the stored commands",
					Action:  CmdStoreShow,
				},
				{
					Name:  "delete",
					Usage: "Deletes the stored commands",
					Subcommands: []cli.Command{
						{
							Name:    "id",
							Aliases: []string{"id"},
							Usage:   "deletes specific command from the store",
							Action:  CmdStoreDeleteById,
						},
						{
							Name:    "all",
							Aliases: []string{"all"},
							Usage:   "deletes all stored commands",
							Action:  CmdStoreDeleteAll,
						},
					},
				},
				{
					Name:    "run",
					Aliases: []string{"ru"},
					Usage:   "pops a command from the list and executes it",
					Action:  CmdStoreRunId,
					Flags: []cli.Flag{
						StoreFlag,
					},
				},
			},
		},
		{
			Name:    "recall",
			Aliases: []string{"rc"},
			Usage:   "recall a command and executes it again",
			Action:  CmdRecall,
			Flags: []cli.Flag{
				HistoryFlag,
			},
		},
		{
			Name:    "export",
			Aliases: []string{"ex"},
			Usage:   "exports the output of a command to a file",
			Action:  CmdExport,
		},
	}

	app.Run(os.Args)

	defer closeDB()
}

// List of functions
func CmdExport(ctx *cli.Context) error {
	commandWrapper(ctx, func() {
		args, err := stringsFromArguments(ctx)
		check(err)

		var command = repository.FindById(args[0])

		fileHandle, _ := os.Create(args[1])
		writer := bufio.NewWriter(fileHandle)
		defer fileHandle.Close()

		if command.Output != "" {
			fmt.Fprintln(writer, command.Output)
		}

		if command.Error != "" {
			fmt.Fprintln(writer, command.Error)
		}

		writer.Flush()

		parrot.Println("Done!")
	})
	return nil
}

func CmdWrapper(ctx *cli.Context) {
}

// ----------------
// Arguments from command string
// ----------------
func stringsTailFromArguments(ctx *cli.Context) ([]string, error) {
	if !ctx.Args().Present() {
		return nil, errors.New("Value must be provided!")
	}

	str := ctx.Args().Tail()

	return str, nil
}

func stringsFromArguments(ctx *cli.Context) ([]string, error) {
	if !ctx.Args().Present() {
		return nil, errors.New("Value must be provided!")
	}

	str := ctx.Args()

	return str, nil
}

func stringFromArguments(ctx *cli.Context) (string, error) {
	if !ctx.Args().Present() {
		return "", errors.New("Value must be provided!")
	}

	str := ctx.Args()[0]

	return str, nil
}

func intFromArguments(ctx *cli.Context) (int, error) {
	if !ctx.Args().Present() {
		return -1, errors.New("Value must be provided!")
	}

	i, err := strconv.Atoi(ctx.Args()[0])
	if err != nil {
		return -1, err
	}

	return i, nil
}

// ----------------
// command management
// ----------------
func initializeCommand(name string, arguments []string) Command {
	var command = Command{}
	command.ID = random()

	command.Name = name
	command.Arguments = arguments

	command.CreatedAt = time.Now()
	return command
}

func finalizeCommand(command *Command) {
	command.TerminatedAt = time.Now()
	repository.Put(*command)

	parrot.Println("[" + command.ID + "]")
}

func pushCommand(command *Command, showid bool) {
	command.TerminatedAt = time.Now()
	repository.Push(*command)

	if showid {
		parrot.Println("[" + command.ID + "]")
	}
}

func executeCommand(command *Command) {
	var bufferOutput bytes.Buffer
	var bufferError bytes.Buffer

	cmd := exec.Command(command.Name, command.Arguments...)

	parrot.Debug("--> CommandName " + command.Name)
	parrot.Debug("--> Command Arguments " + asJson(command.Arguments))

	outputReader, err := cmd.StdoutPipe()
	if err != nil {
		parrot.Error("Error creating StdoutPipe for Cmd", err)
		command.Error = err.Error()
		command.Status = false
		return
	}

	errorReader, err := cmd.StderrPipe()
	if err != nil {
		parrot.Error("Error creating StderrPipe for Cmd", err)
		command.Error = err.Error()
		command.Status = false
		return
	}

	err = cmd.Start()
	if err != nil {
		parrot.Error("Error starting Cmd", err)
		command.Error = err.Error()
		command.Status = false
		return
	}

	stopOut := make(chan bool)
	stopErr := make(chan bool)

	scannerOutput := bufio.NewScanner(outputReader)
	go func(stop chan bool) {
		for scannerOutput.Scan() {
			parrot.Println(scannerOutput.Text())
			bufferOutput.WriteString(scannerOutput.Text() + "\n")
		}

		stop <- true
	}(stopOut)

	scannerError := bufio.NewScanner(errorReader)
	go func(stop chan bool) {
		for scannerError.Scan() {
			parrot.Println(scannerError.Text())
			bufferError.WriteString(scannerError.Text() + "\n")
		}

		stop <- true
	}(stopErr)

	<-stopOut
	<-stopErr

	err = cmd.Wait()
	if err != nil {
		parrot.Error("Error waiting for Cmd", err)
		command.Error = err.Error()
		command.Status = false
		return
	}

	command.Output = bufferOutput.String()
	command.Error = bufferError.String()

	command.Status = true
}

// -------------------------------
// Cli command wrapper
// -------------------------------
func commandWrapper(ctx *cli.Context, cmd quant.Action0) {
	CmdWrapper(ctx)

	cmd()
}
<commit_msg>fixed export<commit_after>package main

import (
	"bufio"
	"bytes"
	"errors"
	"fmt"
	"os"
	"os/exec"
	"strconv"
	"time"

	"github.com/gi4nks/quant"
	"gopkg.in/urfave/cli.v1"
)

var parrot = quant.NewParrot("ambros")

var settings = Settings{}
var repository = Repository{}

var pathUtils = quant.NewPathUtils()

func initDB() {
	repository.InitDB()
	repository.InitSchema()
}

func closeDB() {
	repository.CloseDB()
}

func readSettings() {
	settings.LoadSettings()

	if settings.DebugMode() {
		parrot = quant.NewVerboseParrot("ambros")
	}
}

func main() {
	readSettings()
	initDB()

	// -------------------
	app := cli.NewApp()
	app.Name = "ambros"
	app.Usage = "the personal command butler!!!!"
	app.Version = "0.2.2"
	app.Copyright = "gi4nks - 2016"

	//app.EnableBashCompletion = true

	app.Commands = []cli.Command{
		{
			Name:    "settings",
			Aliases: []string{"st"},
			Usage:   "settings sub menu",
			Subcommands: []cli.Command{
				{
					Name:    "list",
					Aliases: []string{"ls"},
					Usage:   "list current configuration settings",
					Action:  CmdSettingsList,
				},
				{
					Name:    "revive",
					Aliases: []string{"re"},
					Usage:   "revive ambros",
					Subcommands: []cli.Command{
						{
							Name:    "complete",
							Aliases: []string{"com"},
							Usage:   "revive ambros deleting completely the database",
							Action:  CmdSettingsReviveComplete,
						},
						{
							Name:    "partial",
							Aliases: []string{"par"},
							Usage:   "revive ambros preserving the stored commands",
							Action:  CmdSettingsRevivePartial,
						},
					},
				},
				{
					Name:    "logs",
					Aliases: []string{"lo"},
					Usage:   "show me the logs of ambros",
					Subcommands: []cli.Command{
						{
							Name:    "id",
							Aliases: []string{"id"},
							Usage:   "Get the log of specific id",
							Action:  CmdSettingsLogsById,
						},
						{
							Name:    "all",
							Aliases: []string{"all"},
							Usage:   "Get all the logs",
							Action:  CmdSettingsLogs,
						},
					},
				},
			},
		},
		{
			Name:    "run",
			Aliases: []string{"ru"},
			Usage:   "run a command, remember to run the command with -- before",
			Action:  CmdRun,
			Flags: []cli.Flag{
				StoreFlag,
			},
		},
		{
			Name:    "last",
			Aliases: []string{"ll"},
			Usage:   "show the last executed commands ",
			Action:  CmdLast,
		},
		{
			Name:    "output",
			Aliases: []string{"ou"},
			Usage:   "show me the output of a command executed with ambros",
			Action:  CmdOutput,
		},
		{
			Name:    "store",
			Aliases: []string{"so"},
			Usage:   "store functionalities sub commands",
			Subcommands: []cli.Command{
				{
					Name:    "id",
					Aliases: []string{"id"},
					Usage:   "stores an executed command ",
					Action:  CmdStoreRunId,
				},
				{
					Name:    "push",
					Aliases: []string{"pu"},
					Usage:   "push a not executed command in the stack",
					Action:  CmdStorePush,
				},
				{
					Name:    "show",
					Aliases: []string{"sh"},
					Usage:   "Show all the stored commands",
					Action:  CmdStoreShow,
				},
				{
					Name:  "delete",
					Usage: "Deletes the stored commands",
					Subcommands: []cli.Command{
						{
							Name:    "id",
							Aliases: []string{"id"},
							Usage:   "deletes specific command from the store",
							Action:  CmdStoreDeleteById,
						},
						{
							Name:    "all",
							Aliases: []string{"all"},
							Usage:   "deletes all stored commands",
							Action:  CmdStoreDeleteAll,
						},
					},
				},
				{
					Name:    "run",
					Aliases: []string{"ru"},
					Usage:   "pops a command from the list and executes it",
					Action:  CmdStoreRunId,
					Flags: []cli.Flag{
						StoreFlag,
					},
				},
			},
		},
		{
			Name:    "recall",
			Aliases: []string{"rc"},
			Usage:   "recall a command and executes it again",
			Action:  CmdRecall,
			Flags: []cli.Flag{
				HistoryFlag,
			},
		},
		{
			Name:    "export",
			Aliases: []string{"ex"},
			Usage:   "exports the output of a command to a file",
			Action:  CmdExport,
			Flags: []cli.Flag{
				HistoryFlag,
			},
		},
	}

	app.Run(os.Args)

	defer closeDB()
}

// List of functions
func CmdExport(ctx *cli.Context) error {
	commandWrapper(ctx, func() {
		args, err := stringsFromArguments(ctx)
		if err != nil {
			parrot.Println("Please provide a valid command id stored and valid output file")
			return
		}

		if len(args) != 2 {
			parrot.Println("Wrong number of arguments")
			return
		}

		id := args[0]
		fl := args[1]

		var stored Command
		if ctx.Bool("history") {
			stored = repository.FindInStoreById(id)
		} else {
			stored = repository.FindById(id)
		}

		fileHandle, _ := os.Create(fl)
		writer := bufio.NewWriter(fileHandle)
		defer fileHandle.Close()

		if stored.Output != "" {
			fmt.Fprintln(writer, stored.Output)
		}

		if stored.Error != "" {
			fmt.Fprintln(writer, stored.Error)
		}

		writer.Flush()

		parrot.Println("Done!")
	})
	return nil
}

func CmdWrapper(ctx *cli.Context) {
}

// ----------------
// Arguments from command string
// ----------------
func stringsTailFromArguments(ctx *cli.Context) ([]string, error) {
	if !ctx.Args().Present() {
		return nil, errors.New("Value must be provided!")
	}

	str := ctx.Args().Tail()

	return str, nil
}

func stringsFromArguments(ctx *cli.Context) ([]string, error) {
	if !ctx.Args().Present() {
		return nil, errors.New("Value must be provided!")
	}

	str := ctx.Args()

	return str, nil
}

func stringFromArguments(ctx *cli.Context) (string, error) {
	if !ctx.Args().Present() {
		return "", errors.New("Value must be provided!")
	}

	str := ctx.Args()[0]

	return str, nil
}

func intFromArguments(ctx *cli.Context) (int, error) {
	if !ctx.Args().Present() {
		return -1, errors.New("Value must be provided!")
	}

	i, err := strconv.Atoi(ctx.Args()[0])
	if err != nil {
		return -1, err
	}

	return i, nil
}

// ----------------
// command management
// ----------------
func initializeCommand(name string, arguments []string) Command {
	var command = Command{}
	command.ID = random()

	command.Name = name
	command.Arguments = arguments

	command.CreatedAt = time.Now()
	return command
}

func finalizeCommand(command *Command) {
	command.TerminatedAt = time.Now()
	repository.Put(*command)

	parrot.Println("[" + command.ID + "]")
}

func pushCommand(command *Command, showid bool) {
	command.TerminatedAt = time.Now()
	repository.Push(*command)

	if showid {
		parrot.Println("[" + command.ID + "]")
	}
}

func executeCommand(command *Command) {
	var bufferOutput bytes.Buffer
	var bufferError bytes.Buffer

	cmd := exec.Command(command.Name, command.Arguments...)

	parrot.Debug("--> CommandName " + command.Name)
	parrot.Debug("--> Command Arguments " + asJson(command.Arguments))

	outputReader, err := cmd.StdoutPipe()
	if err != nil {
		parrot.Error("Error creating StdoutPipe for Cmd", err)
		command.Error = err.Error()
		command.Status = false
		return
	}

	errorReader, err := cmd.StderrPipe()
	if err != nil {
		parrot.Error("Error creating StderrPipe for Cmd", err)
		command.Error = err.Error()
		command.Status = false
		return
	}

	err = cmd.Start()
	if err != nil {
		parrot.Error("Error starting Cmd", err)
		command.Error = err.Error()
		command.Status = false
		return
	}

	stopOut := make(chan bool)
	stopErr := make(chan bool)

	scannerOutput := bufio.NewScanner(outputReader)
	go func(stop chan bool) {
		for scannerOutput.Scan() {
			parrot.Println(scannerOutput.Text())
			bufferOutput.WriteString(scannerOutput.Text() + "\n")
		}

		stop <- true
	}(stopOut)

	scannerError := bufio.NewScanner(errorReader)
	go func(stop chan bool) {
		for scannerError.Scan() {
			parrot.Println(scannerError.Text())
			bufferError.WriteString(scannerError.Text() + "\n")
		}

		stop <- true
	}(stopErr)

	<-stopOut
	<-stopErr

	err = cmd.Wait()
	if err != nil {
		parrot.Error("Error waiting for Cmd", err)
		command.Error = err.Error()
		command.Status = false
		return
	}

	command.Output = bufferOutput.String()
	command.Error = bufferError.String()

	command.Status = true
}

// -------------------------------
// Cli command wrapper
// -------------------------------
func commandWrapper(ctx *cli.Context, cmd quant.Action0) {
	CmdWrapper(ctx)

	cmd()
}
<|endoftext|>


<commit_before>// Copyright 2015 Reed O'Brien <reed@reedobrien.com>.
// All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

package main

import (
	"fmt"
)

func main() {
	fmt.Print("code appears here")
}
<commit_msg>Add initial whack at flags.<commit_after>// Copyright 2015 Reed O'Brien <reed@reedobrien.com>.
// All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

package main

import (
	"flag"
	"fmt"
	"time"
)

var (
	err    error
	secret string // The hex or base32 secret
	// otp string 	// If a value is supplied for varification

	//// Flags
	// common flags add in flagParse method
	// base32 = flag.Bool("b", false, "Use base32 encoding instead of hex")
	// digits = flag.Int("d", 6, "The number of digits in the OTP")
	// window = flag.Int("w", 1, "Window of counter values to test when validating OTPs")

	hFlag   = flag.NewFlagSet("hotp", flag.ContinueOnError)
	counter = hFlag.Int64("c", 0, "HOTP counter Value")

	tFlag = flag.NewFlagSet("totp", flag.ContinueOnError)
	now   = tFlag.Int64("N", time.Now().UTC().Unix(), "Use this time as current time for TOTP")
	step  = tFlag.Int64("s", 30, "The time-step duration")
	epoch = tFlag.String("S", "1970−01−01 00:00:00 UTC", "When to start counting time-steps for TOTP")
)

func main() {
	fmt.Print("code appears here")
}
<|endoftext|>


<commit_before>package main

import (
	"encoding/xml"
	"fmt"
	"net"
	"os"
	"regexp"
	"sort"
	"strconv"
	"strings"
	"sync"
	"time"

	"github.com/cheggaaa/pb"
	"github.com/olekukonko/tablewriter"
	"github.com/parnurzeal/gorequest"
	"gopkg.in/alecthomas/kingpin.v2"
)

const (
	iloPort = 17988
)

var (
	ipNetwork   = kingpin.Arg("network", "Scan network, format 10.0.0.0/24").Required().String()
	ipNetParsed []string
)

// ILOInfo ...
type ILOInfo struct {
	IP     string
	HW     string
	Model  string
	FW     string
	Serial string
}

// ILOSorter ...
type ILOSorter struct {
	ilo []ILOInfo
	by  func(i1, i2 *ILOInfo) bool
}

// By is the type of a "less" function that defines the ordering of its Planet arguments.
type By func(i1, i2 *ILOInfo) bool

// Sort is a method on the function type, By, that sorts the argument slice according to the function.
func (by By) Sort(ilo []ILOInfo) {
	ps := &ILOSorter{
		ilo: ilo,
		by:  by, // The Sort method's receiver is the function (closure) that defines the sort order.
	}
	sort.Sort(ps)
}

// Len is part of sort.Interface.
func (s *ILOSorter) Len() int {
	return len(s.ilo)
}

// Swap is part of sort.Interface.
func (s *ILOSorter) Swap(i, j int) {
	s.ilo[i], s.ilo[j] = s.ilo[j], s.ilo[i]
}

// Less is part of sort.Interface. It is implemented by calling the "by" closure in the sorter.
func (s *ILOSorter) Less(i, j int) bool {
	return s.by(&s.ilo[i], &s.ilo[j])
}

// RIMP ...
type RIMP struct {
	XMLName xml.Name `xml:"RIMP"`
	SBSN    string   `xml:"HSI>SBSN"`
	SPN     string   `xml:"HSI>SPN"`
	PN      string   `xml:"MP>PN"`
	FWRI    string   `xml:"MP>FWRI"`
	HWRI    string   `xml:"MP>HWRI"`
}

// HW ...
func (r *RIMP) HW() string {
	var iloRevision = regexp.MustCompile(`\((.*)\)`)
	if len(r.PN) == 0 {
		return "N/A"
	}
	return strings.TrimSpace(iloRevision.FindAllStringSubmatch(r.PN, 1)[0][1])
}

// Model ...
func (r *RIMP) Model() string {
	if len(r.SPN) == 0 {
		return "N/A"
	}
	return strings.TrimSpace(r.SPN)
}

// FW ...
func (r *RIMP) FW() string {
	if len(r.FWRI) == 0 {
		return "N/A"
	}
	return strings.TrimSpace(r.FWRI)
}

func inc(ip net.IP) {
	for j := len(ip) - 1; j >= 0; j-- {
		ip[j]++
		if ip[j] > 0 {
			break
		}
	}
}

// IsOpen ...
func IsOpen(host string, port int) bool {

	tcpAddr, err := net.ResolveTCPAddr("tcp4", fmt.Sprintf("%s:%d", host, port))
	if err != nil {
		return false
	}
	conn, err := net.DialTimeout("tcp", tcpAddr.String(), 250*time.Millisecond)

	if err != nil {
		return false
	}
	defer conn.Close()
	return true
}

func init() {
	kingpin.Parse()

	ip, ipnet, err := net.ParseCIDR(*ipNetwork)
	if err != nil {
		fmt.Println(err)
		os.Exit(1)
	}

	var ips []string
	for ip := ip.Mask(ipnet.Mask); ipnet.Contains(ip); inc(ip) {
		ips = append(ips, ip.String())
	}
	ipNetParsed = ips
}

func requestInfo(ip string) (*ILOInfo, error) {
	request := gorequest.New()
	rinfo := &RIMP{}

	_, body, err := request.Get(fmt.Sprintf("http://%s/xmldata?item=all", ip)).End()

	if err != nil {
		return nil, fmt.Errorf("%v", err)
	}
	if err := xml.Unmarshal([]byte(body), rinfo); err != nil {
		return nil, err
	}
	return &ILOInfo{
		IP:     ip,
		HW:     rinfo.HW(),
		FW:     rinfo.FW(),
		Model:  rinfo.Model(),
		Serial: strings.TrimSpace(rinfo.SBSN),
	}, nil
}

func makeJobs(ar []string, count int) [][]string {
	chunk := len(ar) / count
	start := 0
	end := count
	res := [][]string{}
	for end < len(ar) {
		res = append(res, ar[start:end])
		start = end
		end += chunk
	}
	res = append(res, ar[start:len(ar)])
	return res
}
func tableRender(ilo []ILOInfo) {
	data := [][]string{}
	table := tablewriter.NewWriter(os.Stdout)
	table.SetHeader([]string{"iLO IP Address", "iLO HW", "iLO FW", "Server S/N", "Server Model"})
	table.SetBorder(false) // Set Border to false
	version := func(i1, i2 *ILOInfo) bool {
		i1s := strings.Split(i1.HW, " ")
		i2s := strings.Split(i2.HW, " ")
		i1v := 1
		i2v := 1
		if len(i1s) > 1 {
			i1v, _ = strconv.Atoi(i1s[1])
		}
		if len(i2s) > 1 {
			i2v, _ = strconv.Atoi(i2s[1])
		}

		return i1v < i2v
	}
	By(version).Sort(ilo)
	for _, info := range ilo {
		data = append(data, []string{
			info.IP,
			info.HW,
			info.FW,
			info.Serial,
			info.Model,
		})
	}

	table.AppendBulk(data) // Add Bulk Data
	fmt.Println("")
	table.Render()
}
func scan(ips []string, out chan ILOInfo, bar *pb.ProgressBar, wg *sync.WaitGroup) {
	for _, host := range ips {
		if IsOpen(host, iloPort) {
			info, err := requestInfo(host)
			if err != nil {
				fmt.Print(err)
			}
			out <- *info
		}
		bar.Increment()
	}
	wg.Done()
}

func main() {
	jobs := makeJobs(ipNetParsed, 100)
	out := make(chan ILOInfo, 100)

	scanbar := pb.StartNew(len(ipNetParsed)).Prefix("Scan net")
	scanbar.ShowTimeLeft = false

	wg := new(sync.WaitGroup)
	//Запуск воркеров
	for _, job := range jobs {
		wg.Add(1)
		go scan(job, out, scanbar, wg)
	}

	wg.Wait()
	close(out)

	ilo := []ILOInfo{}
	for info := range out {
		ilo = append(ilo, info)
	}
	scanbar.Finish()
	tableRender(ilo)
	fmt.Println("")
}
<commit_msg>test codebeat<commit_after>package main

import (
	"encoding/xml"
	"fmt"
	"net"
	"os"
	"regexp"
	"sort"
	"strconv"
	"strings"
	"sync"
	"time"

	"github.com/cheggaaa/pb"
	"github.com/olekukonko/tablewriter"
	"github.com/parnurzeal/gorequest"
	"gopkg.in/alecthomas/kingpin.v2"
)

const (
	iloPort = 17988
)

var (
	ipNetwork   = kingpin.Arg("network", "Scan network, format 10.0.0.0/24").Required().String()
	ipNetParsed []string
)

// ILOInfo ...
type ILOInfo struct {
	IP     string
	HW     string
	Model  string
	FW     string
	Serial string
}

// ILOSorter ...
type ILOSorter struct {
	ilo []ILOInfo
	by  func(i1, i2 *ILOInfo) bool
}

// By is the type of a "less" function that defines the ordering of its Planet arguments.
type By func(i1, i2 *ILOInfo) bool

// Sort is a method on the function type, By, that sorts the argument slice according to the function.
func (by By) Sort(ilo []ILOInfo) {
	ps := &ILOSorter{
		ilo: ilo,
		by:  by, // The Sort method's receiver is the function (closure) that defines the sort order.
	}
	sort.Sort(ps)
}

// Len is part of sort.Interface.
func (s *ILOSorter) Len() int {
	return len(s.ilo)
}

// Swap is part of sort.Interface.
func (s *ILOSorter) Swap(i, j int) {
	s.ilo[i], s.ilo[j] = s.ilo[j], s.ilo[i]
}

// Less is part of sort.Interface. It is implemented by calling the "by" closure in the sorter.
func (s *ILOSorter) Less(i, j int) bool {
	return s.by(&s.ilo[i], &s.ilo[j])
}

// RIMP ...
type RIMP struct {
	XMLName xml.Name `xml:"RIMP"`
	SBSN    string   `xml:"HSI>SBSN"`
	SPN     string   `xml:"HSI>SPN"`
	PN      string   `xml:"MP>PN"`
	FWRI    string   `xml:"MP>FWRI"`
	HWRI    string   `xml:"MP>HWRI"`
}

// HW ...
func (r *RIMP) HW() string {
	var iloRevision = regexp.MustCompile(`\((.*)\)`)
	if len(r.PN) == 0 {
		return "N/A"
	}
	return strings.TrimSpace(iloRevision.FindAllStringSubmatch(r.PN, 1)[0][1])
}

// Model ...
func (r *RIMP) Model() string {
	if len(r.SPN) == 0 {
		return "N/A"
	}
	return strings.TrimSpace(r.SPN)
}

// FW ...
func (r *RIMP) FW() string {
	if len(r.FWRI) == 0 {
		return "N/A"
	}
	return strings.TrimSpace(r.FWRI)
}

func inc(ip net.IP) {
	for j := len(ip) - 1; j >= 0; j-- {
		ip[j]++
		if ip[j] > 0 {
			break
		}
	}
}

// IsOpen ...
func IsOpen(host string, port int) bool {

	tcpAddr, err := net.ResolveTCPAddr("tcp4", fmt.Sprintf("%s:%d", host, port))
	if err != nil {
		return false
	}
	conn, err := net.DialTimeout("tcp", tcpAddr.String(), 250*time.Millisecond)

	if err != nil {
		return false
	}
	defer conn.Close()
	return true
}

func init() {
	kingpin.Parse()

	ip, ipnet, err := net.ParseCIDR(*ipNetwork)
	if err != nil {
		fmt.Println(err)
		os.Exit(1)
	}

	var ips []string
	for ip := ip.Mask(ipnet.Mask); ipnet.Contains(ip); inc(ip) {
		ips = append(ips, ip.String())
	}
	ipNetParsed = ips
}

func requestInfo(ip string) (*ILOInfo, error) {
	request := gorequest.New()
	rinfo := &RIMP{}

	_, body, err := request.Get(fmt.Sprintf("http://%s/xmldata?item=all", ip)).End()

	if err != nil {
		return nil, fmt.Errorf("%v", err)
	}
	if err := xml.Unmarshal([]byte(body), rinfo); err != nil {
		return nil, err
	}
	return &ILOInfo{
		IP:     ip,
		HW:     rinfo.HW(),
		FW:     rinfo.FW(),
		Model:  rinfo.Model(),
		Serial: strings.TrimSpace(rinfo.SBSN),
	}, nil
}

func makeJobs(ar []string, count int) [][]string {
	chunk := len(ar) / count
	start := 0
	end := count
	res := [][]string{}
	for end < len(ar) {
		res = append(res, ar[start:end])
		start = end
		end += chunk
	}
	res = append(res, ar[start:len(ar)])
	return res
}
func tableRender(ilo []ILOInfo) {
	data := [][]string{}
	table := tablewriter.NewWriter(os.Stdout)
	table.SetHeader([]string{"iLO IP Address", "iLO HW", "iLO FW", "Server S/N", "Server Model"})
	table.SetBorder(false) // Set Border to false
	version := func(i1, i2 *ILOInfo) bool {
		i1s := strings.Split(i1.HW, " ")
		i2s := strings.Split(i2.HW, " ")
		i1v := 1
		i2v := 1
		if len(i1s) > 1 {
			i1v, _ = strconv.Atoi(i1s[1])
		}
		if len(i2s) > 1 {
			i2v, _ = strconv.Atoi(i2s[1])
		}

		return i1v < i2v
	}
	By(version).Sort(ilo)
	for _, info := range ilo {
		data = append(data, []string{
			info.IP,
			info.HW,
			info.FW,
			info.Serial,
			info.Model,
		})
	}

	table.AppendBulk(data) // Add Bulk Data
	fmt.Println("")
	table.Render()
}

func scan(ips []string, out chan ILOInfo, bar *pb.ProgressBar, wg *sync.WaitGroup) {
	for _, host := range ips {
		if IsOpen(host, iloPort) {
			info, err := requestInfo(host)
			if err != nil {
				fmt.Print(err)
			}
			out <- *info
		}
		bar.Increment()
	}
	wg.Done()
}

func main() {
	jobs := makeJobs(ipNetParsed, 100)
	out := make(chan ILOInfo, 100)
	ipNetLen := len(ipNetParsed)

	scanbar := pb.StartNew(ipNetLen)
	scanbar = scanbar.Prefix("Scan net")
	scanbar.ShowTimeLeft = false

	wg := new(sync.WaitGroup)
	//Запуск воркеров
	for _, job := range jobs {
		wg.Add(1)
		go scan(job, out, scanbar, wg)
	}

	wg.Wait()
	close(out)

	ilo := []ILOInfo{}
	for info := range out {
		ilo = append(ilo, info)
	}
	scanbar.Finish()
	tableRender(ilo)
	fmt.Println("")
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"fmt"
	"io/ioutil"
	"log"
	"os"

	"github.com/artemnikitin/aws-config"
	"github.com/artemnikitin/devicefarm-ci-tool/errors"
	"github.com/artemnikitin/devicefarm-ci-tool/model"
	"github.com/artemnikitin/devicefarm-ci-tool/service"
	"github.com/artemnikitin/devicefarm-ci-tool/tools"
	"github.com/aws/aws-sdk-go/aws/session"
	"github.com/aws/aws-sdk-go/service/devicefarm"
	"github.com/aws/aws-sdk-go/service/devicefarm/devicefarmiface"
)

var (
	project    = flag.String("project", "", "Device Farm project name")
	runName    = flag.String("run", "", "Name of test run")
	appPath    = flag.String("app", "", "Path to an app")
	testPath   = flag.String("test", "", "Path to test app")
	devicePool = flag.String("devices", "Top Devices", "Specify list of devices for tests")
	configJSON = flag.String("config", "", "Path to JSON config")
	wait       = flag.Bool("wait", false, "Wait for run end")
	checkEvery = flag.Int("checkEvery", 5, "Specified time slice for checking status of run")
)

func main() {
	flag.Parse()

	if *project == "" || *appPath == "" {
		fmt.Println("Please specify correct parameters!")
		fmt.Println("You should specify:")
		fmt.Println("-project, name of a project in AWS Device Farm")
		fmt.Println("-app, path to an app you want to run")
		os.Exit(1)
	}

	runJob(getAWSClient(), getConfig())
}

func runJob(client devicefarmiface.DeviceFarmAPI, config *model.RunConfig) {
	svc := &service.DeviceFarmRun{
		Client:  client,
		Config:  config,
		Project: *project,
	}
	if svc.GetProjectArn() == "" {
		log.Fatal("Application finished, because it can't retrieve project ARN")
	}

	/*if svc.Config.DevicePoolArn != "" {
		svc.DeviceArn = svc.Config.DevicePoolArn
	} else {
		svc.DeviceArn = svc.GetDevicePoolArn(svc.Config.DevicePoolName)
	}*/
	svc.GetDevicePoolArn(svc.Config.DevicePoolName)

	appArn, url := svc.CreateUpload(*appPath)
	code := tools.UploadFile(*appPath, url)
	if code != 200 {
		log.Fatal("Can't upload an app to Device Farm")
	}
	svc.AppArn = appArn
	svc.WaitForAppProcessed(svc.AppArn, *checkEvery)
	runArn, status := svc.RunWithConfig()
	statusCheck(status)
	if *wait {
		result := svc.WaitForRunEnds(runArn, *checkEvery)
		printReportURL(runArn)
		if result != devicefarm.ExecutionResultPassed {
			fails := svc.GetListOfFailedTests(runArn)
			log.Printf("There are %d test fails, check it out!\n", len(fails))
			for i := 0; i < len(fails); i++ {
				fmt.Println(fails[i].ToString())
			}
			os.Exit(1)
		}
	}
}

func getConfig() *model.RunConfig {
	configFile := &model.RunConfig{}
	if *configJSON != "" {
		bytes, err := ioutil.ReadFile(*configJSON)
		errors.Validate(err, "Can't read model file")
		*configFile = model.Transform(bytes)
	}
	if configFile.DevicePoolArn == "" && configFile.DevicePoolName == "" {
		configFile.DevicePoolName = *devicePool
	}
	if *runName != "" {
		configFile.RunName = *runName
	}
	if *testPath != "" {
		configFile.Test.TestPackagePath = *testPath
	}
	return configFile
}

func getAWSClient() devicefarmiface.DeviceFarmAPI {
	config := awsconfig.New()
	if *config.Region != "us-west-2" {
		config.WithRegion("us-west-2")
	}
	session := session.New(config)
	return devicefarm.New(session)
}

func statusCheck(status string) {
	if status == devicefarm.ExecutionStatusScheduling {
		log.Println("Job is scheduled!")
	} else {
		log.Println("Status =", status)
		log.Fatal("Failed to start a job ...")
	}
}

func printReportURL(arn string) {
	log.Println("Test report URL:", tools.GenerateReportURL(arn))
}
<commit_msg>Made small improvements<commit_after>package main

import (
	"flag"
	"fmt"
	"io/ioutil"
	"log"
	"os"

	"github.com/artemnikitin/aws-config"
	"github.com/artemnikitin/devicefarm-ci-tool/errors"
	"github.com/artemnikitin/devicefarm-ci-tool/model"
	"github.com/artemnikitin/devicefarm-ci-tool/service"
	"github.com/artemnikitin/devicefarm-ci-tool/tools"
	"github.com/aws/aws-sdk-go/aws/session"
	"github.com/aws/aws-sdk-go/service/devicefarm"
	"github.com/aws/aws-sdk-go/service/devicefarm/devicefarmiface"
)

var (
	project    = flag.String("project", "", "Device Farm project name")
	runName    = flag.String("run", "", "Name of test run")
	appPath    = flag.String("app", "", "Path to an app")
	testPath   = flag.String("test", "", "Path to test app")
	devicePool = flag.String("devices", "Top Devices", "Specify list of devices for tests")
	configJSON = flag.String("config", "", "Path to JSON config")
	wait       = flag.Bool("wait", false, "Wait for run end")
	checkEvery = flag.Int("checkEvery", 5, "Specified time slice for checking status of run")
)

func main() {
	flag.Parse()

	if *project == "" || *appPath == "" {
		fmt.Println("Please specify correct parameters!")
		fmt.Println("You should specify:")
		fmt.Println("-project, name of a project in AWS Device Farm")
		fmt.Println("-app, path to an app you want to run")
		os.Exit(1)
	}

	runJob(getAWSClient(), getConfig())
}

func runJob(client devicefarmiface.DeviceFarmAPI, config *model.RunConfig) {
	svc := &service.DeviceFarmRun{
		Client:  client,
		Config:  config,
		Project: *project,
	}

	if svc.GetProjectArn() == "" {
		log.Fatal("Application finished, because it can't retrieve project ARN")
	}

	svc.GetDevicePoolArn(svc.Config.DevicePoolName)

	appArn, url := svc.CreateUpload(*appPath)
	code := tools.UploadFile(*appPath, url)
	if code != 200 {
		log.Fatal("Can't upload an app to Device Farm")
	}

	svc.AppArn = appArn
	svc.WaitForAppProcessed(svc.AppArn, *checkEvery)

	runArn, status := svc.RunWithConfig()
	statusCheck(status)

	if *wait {
		result := svc.WaitForRunEnds(runArn, *checkEvery)
		if result != devicefarm.ExecutionResultPassed {
			fails := svc.GetListOfFailedTests(runArn)
			log.Printf("There are %d test fails, check it out!\n", len(fails))
			for i := 0; i < len(fails); i++ {
				fmt.Println(fails[i].ToString())
			}
			printReportURL(runArn)
			os.Exit(1)
		} else {
			printReportURL(runArn)
		}
	} else {
		printReportURL(runArn)
	}
}

func getConfig() *model.RunConfig {
	configFile := &model.RunConfig{}
	if *configJSON != "" {
		bytes, err := ioutil.ReadFile(*configJSON)
		errors.Validate(err, "Can't read model file")
		*configFile = model.Transform(bytes)
	}
	if configFile.DevicePoolArn == "" && configFile.DevicePoolName == "" {
		configFile.DevicePoolName = *devicePool
	}
	if *runName != "" {
		configFile.RunName = *runName
	}
	if *testPath != "" {
		configFile.Test.TestPackagePath = *testPath
	}
	return configFile
}

func getAWSClient() devicefarmiface.DeviceFarmAPI {
	config := awsconfig.New()
	if *config.Region != "us-west-2" {
		config.WithRegion("us-west-2")
	}
	session := session.New(config)
	return devicefarm.New(session)
}

func statusCheck(status string) {
	if status == devicefarm.ExecutionStatusScheduling {
		log.Println("Job is scheduled!")
	} else {
		log.Println("Status =", status)
		log.Fatal("Failed to start a job ...")
	}
}

func printReportURL(arn string) {
	log.Println("Test report URL:", tools.GenerateReportURL(arn))
}
<|endoftext|>


<commit_before>package main

import (
	"log"
	"time"

	"github.com/pavel-paulau/gateload/api"
	"github.com/pavel-paulau/gateload/workload"
)

const (
	DocsPerUser = 1000000
	MaxSamplers = 100
)

var activeSamplers int

func measureLatency(c *api.SyncGatewayClient, doc api.Doc) {
	measurePushLatency(c, doc)
	measurePullLatency(c, doc)
	activeSamplers--
}

func measurePushLatency(c *api.SyncGatewayClient, doc api.Doc) {
	t0 := time.Now()
	c.PutSingleDoc(doc.Id, doc)
	t1 := time.Now()
	log.Printf("Push latency (ns): %11d\n", t1.Sub(t0)*time.Nanosecond)
}

func measurePullLatency(c *api.SyncGatewayClient, doc api.Doc) {
	t0 := time.Now()
	c.GetSingleDoc(doc.Id)
	t1 := time.Now()
	log.Printf("Pull latency (ns): %11d\n", t1.Sub(t0)*time.Nanosecond)
}

func main() {
	var config workload.Config
	workload.ReadConfig(&config)

	c := api.SyncGatewayClient{}
	c.Init(config.Hostname, config.Database)

	user := api.UserAuth{"collector", "password", []string{"stats"}}
	c.AddUser(user.Name, user)
	session := api.Session{Name: user.Name, TTL: 2592000}
	cookie := c.CreateSession(user.Name, session)
	c.AddCookie(&cookie)

	activeSamplers = 0
	for doc := range workload.DocIterator(0, DocsPerUser, config.DocSize, "stats") {
		if activeSamplers < MaxSamplers {
			activeSamplers++
			go measureLatency(&c, doc)
		}
		time.Sleep(time.Duration(1000) * time.Millisecond)
	}
}
<commit_msg>don't rely on env. variables and tune GOMAXPROCS<commit_after>package main

import (
	"log"
	"runtime"
	"time"

	"github.com/pavel-paulau/gateload/api"
	"github.com/pavel-paulau/gateload/workload"
)

const (
	DocsPerUser = 1000000
	MaxSamplers = 100
)

var activeSamplers int

func measureLatency(c *api.SyncGatewayClient, doc api.Doc) {
	measurePushLatency(c, doc)
	measurePullLatency(c, doc)
	activeSamplers--
}

func measurePushLatency(c *api.SyncGatewayClient, doc api.Doc) {
	t0 := time.Now()
	c.PutSingleDoc(doc.Id, doc)
	t1 := time.Now()
	log.Printf("Push latency (ns): %11d\n", t1.Sub(t0)*time.Nanosecond)
}

func measurePullLatency(c *api.SyncGatewayClient, doc api.Doc) {
	t0 := time.Now()
	c.GetSingleDoc(doc.Id)
	t1 := time.Now()
	log.Printf("Pull latency (ns): %11d\n", t1.Sub(t0)*time.Nanosecond)
}

func main() {
	runtime.GOMAXPROCS(runtime.NumCPU())

	var config workload.Config
	workload.ReadConfig(&config)

	c := api.SyncGatewayClient{}
	c.Init(config.Hostname, config.Database)

	user := api.UserAuth{"collector", "password", []string{"stats"}}
	c.AddUser(user.Name, user)
	session := api.Session{Name: user.Name, TTL: 2592000}
	cookie := c.CreateSession(user.Name, session)
	c.AddCookie(&cookie)

	activeSamplers = 0
	for doc := range workload.DocIterator(0, DocsPerUser, config.DocSize, "stats") {
		if activeSamplers < MaxSamplers {
			activeSamplers++
			go measureLatency(&c, doc)
		}
		time.Sleep(time.Duration(1000) * time.Millisecond)
	}
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"fmt"
	"os"
	"strings"

	"github.com/mizkei/rundeck-cli/rundeck"
	"github.com/peterh/liner"
	"golang.org/x/crypto/ssh/terminal"
)

func main() {
	if !terminal.IsTerminal(0) {
		fmt.Println("no support")
		return
	}

	var confPath string
	flag.StringVar(&confPath, "conf", "$HOME/.config/rundeck-cli/conf.json", "config path")
	flag.Parse()

	conf, err := loadConf(os.ExpandEnv(confPath))
	if err != nil {
		fmt.Printf("failed to load config file. filepath:%s\n", confPath)
		return
	}

	line := liner.NewLiner()
	defer line.Close()
	line.SetCtrlCAborts(true)
	line.SetTabCompletionStyle(liner.TabPrints)

	var rd *rundeck.Rundeck
	if conf.Token == "" {
		username, err := line.Prompt("username: ")
		if err != nil {
			fmt.Println("failed to read 'username'")
			return
		}
		pass, err := line.PasswordPrompt("password: ")
		if err != nil {
			fmt.Println("failed to read 'password'")
			return
		}

		rd, err = rundeck.AuthWithPass(username, pass, conf.Schema, conf.Host, conf.Project, os.Stdout)
		if err != nil {
			fmt.Println("failed to password authentication")
			return
		}
	} else {
		var err error
		rd, err = rundeck.AuthWithToken(conf.Token, conf.Schema, conf.Host, conf.Project, os.Stdout)
		if err != nil {
			fmt.Println("failed to token authentication")
			return
		}
	}

	labels, err := rd.GetJobLabels()
	if err != nil {
		fmt.Println("failed to get jobs definition")
		return
	}

	cmpl := completer{
		cmds:    rundeck.Cmds(),
		subCmds: rundeck.SubCmds(),
		jobs:    labels,
	}
	line.SetWordCompleter(cmpl.completeCmd)

	for {
		l, err := line.Prompt("rundeck> ")
		if err != nil {
			fmt.Println(err)
			return
		}

		l = re.ReplaceAllString(strings.TrimSpace(l), " ")
		strs := strings.Split(l, " ")
		if l == "" || len(strs) == 0 {
			continue
		}

		cmd, args := strs[0], strs[1:]

		if cmd == "exit" {
			break
		}

		if err := rd.Do(cmd, args); err != nil {
			fmt.Println(err)
		}

		line.AppendHistory(l)
	}
}
<commit_msg>コマンドライン引数に値を指定されたらそれを投げる<commit_after>package main

import (
	"flag"
	"fmt"
	"os"
	"strings"

	"github.com/mizkei/rundeck-cli/rundeck"
	"github.com/peterh/liner"
	"golang.org/x/crypto/ssh/terminal"
)

func main() {
	if !terminal.IsTerminal(0) {
		fmt.Println("no support")
		return
	}

	var confPath string
	flag.StringVar(&confPath, "conf", "$HOME/.config/rundeck-cli/conf.json", "config path")
	flag.Parse()

	conf, err := loadConf(os.ExpandEnv(confPath))
	if err != nil {
		fmt.Printf("failed to load config file. filepath:%s\n", confPath)
		return
	}

	line := liner.NewLiner()
	defer line.Close()
	line.SetCtrlCAborts(true)
	line.SetTabCompletionStyle(liner.TabPrints)

	var rd *rundeck.Rundeck
	if conf.Token == "" {
		username, err := line.Prompt("username: ")
		if err != nil {
			fmt.Println("failed to read 'username'")
			return
		}
		pass, err := line.PasswordPrompt("password: ")
		if err != nil {
			fmt.Println("failed to read 'password'")
			return
		}

		rd, err = rundeck.AuthWithPass(username, pass, conf.Schema, conf.Host, conf.Project, os.Stdout)
		if err != nil {
			fmt.Println("failed to password authentication")
			return
		}
	} else {
		var err error
		rd, err = rundeck.AuthWithToken(conf.Token, conf.Schema, conf.Host, conf.Project, os.Stdout)
		if err != nil {
			fmt.Println("failed to token authentication")
			return
		}
	}

	if args := flag.Args(); len(args) > 0 {
		if err := rd.Do(args[0], args[1:]); err != nil {
			fmt.Println(err)
		}

		return
	}

	labels, err := rd.GetJobLabels()
	if err != nil {
		fmt.Println("failed to get jobs definition")
		return
	}

	cmpl := completer{
		cmds:    rundeck.Cmds(),
		subCmds: rundeck.SubCmds(),
		jobs:    labels,
	}
	line.SetWordCompleter(cmpl.completeCmd)

	for {
		l, err := line.Prompt("rundeck> ")
		if err != nil {
			fmt.Println(err)
			return
		}

		l = re.ReplaceAllString(strings.TrimSpace(l), " ")
		strs := strings.Split(l, " ")
		if l == "" || len(strs) == 0 {
			continue
		}

		cmd, args := strs[0], strs[1:]

		if cmd == "exit" {
			break
		}

		if err := rd.Do(cmd, args); err != nil {
			fmt.Println(err)
		}

		line.AppendHistory(l)
	}
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"fmt"
	"github.com/boltdb/bolt"
	"github.com/technoweenie/grohl"
	"os"
	"os/signal"
	"syscall"
	"time"
)

func main() {
	grohl.AddContext("app", "buttered-scones")

	var configFile string
	flag.StringVar(&configFile, "config", "", "configuration file path")
	flag.Parse()

	if configFile == "" {
		flag.Usage()
		os.Exit(1)
	}

	config, err := LoadConfiguration(configFile)
	if err != nil {
		fmt.Printf("error opening configuration file: %s\n", err.Error())
		os.Exit(1)
	}

	clients := make([]Client, 0, len(config.Network.Servers))
	for _, serverName := range config.Network.Servers {
		tlsConfig, err := config.BuildTLSConfig()
		if err != nil {
			fmt.Printf("%s\n", err.Error())
			os.Exit(1)
		}

		client := NewLumberjackClient(&LumberjackClientOptions{
			Network:           "tcp",
			Address:           serverName,
			TLSConfig:         tlsConfig,
			ConnectionTimeout: time.Duration(config.Network.Timeout) * time.Second,
			SendTimeout:       time.Duration(config.Network.Timeout) * time.Second,
		})
		clients = append(clients, client)
	}

	// client := &StdoutClient{}

	db, err := bolt.Open(config.State, 0600, &bolt.Options{Timeout: 2 * time.Second})
	if err != nil {
		fmt.Printf("error opening state database: %s\n", err.Error())
		os.Exit(1)
	}
	snapshotter := &BoltSnapshotter{DB: db}

	if config.Statistics.Addr != "" {
		stats_server := &StatisticsServer{
			Statistics: GlobalStatistics,
			Addr:       config.Statistics.Addr,
		}

		go func() {
			err := stats_server.ListenAndServe()
			grohl.Report(err, grohl.Data{"msg": "stats server failed to start"})
		}()
	}

	supervisor := &Supervisor{
		Files:        config.Files,
		Clients:      clients,
		Snapshotter:  snapshotter,
		SpoolSize:    256,
		SpoolTimeout: 1 * time.Second,
		GlobRefresh:  30 * time.Second,
	}

	done := make(chan interface{})
	go supervisor.Serve(done)

	signalCh := make(chan os.Signal, 1)
	go signal.Notify(signalCh, syscall.SIGTERM, syscall.SIGINT)

	signal := <-signalCh
	fmt.Printf("Received %s, shutting down cleanly ...\n", signal)
	done <- struct{}{}
	fmt.Printf("Done shutting down\n")
}
<commit_msg>Tweaks spool size<commit_after>package main

import (
	"flag"
	"fmt"
	"github.com/boltdb/bolt"
	"github.com/technoweenie/grohl"
	"os"
	"os/signal"
	"syscall"
	"time"
)

func main() {
	grohl.AddContext("app", "buttered-scones")

	var configFile string
	flag.StringVar(&configFile, "config", "", "configuration file path")
	flag.Parse()

	if configFile == "" {
		flag.Usage()
		os.Exit(1)
	}

	config, err := LoadConfiguration(configFile)
	if err != nil {
		fmt.Printf("error opening configuration file: %s\n", err.Error())
		os.Exit(1)
	}

	clients := make([]Client, 0, len(config.Network.Servers))
	for _, serverName := range config.Network.Servers {
		tlsConfig, err := config.BuildTLSConfig()
		if err != nil {
			fmt.Printf("%s\n", err.Error())
			os.Exit(1)
		}

		client := NewLumberjackClient(&LumberjackClientOptions{
			Network:           "tcp",
			Address:           serverName,
			TLSConfig:         tlsConfig,
			ConnectionTimeout: time.Duration(config.Network.Timeout) * time.Second,
			SendTimeout:       time.Duration(config.Network.Timeout) * time.Second,
		})
		clients = append(clients, client)
	}

	// client := &StdoutClient{}

	db, err := bolt.Open(config.State, 0600, &bolt.Options{Timeout: 2 * time.Second})
	if err != nil {
		fmt.Printf("error opening state database: %s\n", err.Error())
		os.Exit(1)
	}
	snapshotter := &BoltSnapshotter{DB: db}

	if config.Statistics.Addr != "" {
		stats_server := &StatisticsServer{
			Statistics: GlobalStatistics,
			Addr:       config.Statistics.Addr,
		}

		go func() {
			err := stats_server.ListenAndServe()
			grohl.Report(err, grohl.Data{"msg": "stats server failed to start"})
		}()
	}

	supervisor := &Supervisor{
		Files:        config.Files,
		Clients:      clients,
		Snapshotter:  snapshotter,
		SpoolSize:    512,
		SpoolTimeout: 1 * time.Second,
		GlobRefresh:  30 * time.Second,
	}

	done := make(chan interface{})
	go supervisor.Serve(done)

	signalCh := make(chan os.Signal, 1)
	go signal.Notify(signalCh, syscall.SIGTERM, syscall.SIGINT)

	signal := <-signalCh
	fmt.Printf("Received %s, shutting down cleanly ...\n", signal)
	done <- struct{}{}
	fmt.Printf("Done shutting down\n")
}
<|endoftext|>


<commit_before>package main

import (
	"github.com/PreetamJinka/sflow"
	"github.com/PreetamJinka/udpchan"

	"bufio"
	"bytes"
	"flag"
	"fmt"
	"io/ioutil"
	"log"
	"net"
	"os"
	"runtime"
	"strconv"
	"strings"
	"time"
)

func main() {
	outbound := flag.String("outbound", "localhost:6343", "Address of collector")
	flag.Parse()

	ip := getIP()

	ch, err := udpchan.Connect(*outbound)
	if err != nil {
		log.Fatal(err)
	}

	buf := &bytes.Buffer{}

	enc := sflow.NewEncoder(ip, 23000, 100)

	for _ = range time.Tick(time.Second * 5) {
		stats := []sflow.Record{}

		cpu, err := getCpuStats()
		if err == nil {
			stats = append(stats, cpu)
		}

		mem, err := getMemStats()
		if err == nil {
			stats = append(stats, mem)
		}

		cs := &sflow.CounterSample{}
		cs.Records = stats

		err = enc.Encode(buf, []sflow.Sample{cs})

		if err == nil {
			ch <- buf.Bytes()
			log.Println("Sent a datagram")
		} else {
			log.Println(err)
		}

		buf.Reset()
	}
}

func getCpuStats() (*sflow.HostCpuCounters, error) {
	loadAvgBytes, err := ioutil.ReadFile("/proc/loadavg")
	if err != nil {
		return nil, err
	}

	c := sflow.HostCpuCounters{}

	fmt.Sscanf(string(loadAvgBytes), "%f %f %f %d/%d", &c.Load1m, &c.Load5m, &c.Load15m,
		&c.ProcsRunning, &c.ProcsTotal)

	c.NumCPU = uint32(runtime.NumCPU())

	uptimeBytes, err := ioutil.ReadFile("/proc/uptime")
	if err != nil {
		return nil, err
	}
	fmt.Sscanf(string(uptimeBytes), "%d", &c.Uptime)

	cpuStatBytes, err := ioutil.ReadFile("/proc/stat")
	if err != nil {
		return nil, err
	}
	fmt.Sscanf(string(cpuStatBytes), "cpu %d %d %d %d %d %d %d", &c.CpuUser, &c.CpuNice, &c.CpuSys, &c.CpuIdle,
		&c.CpuWio, &c.CpuIntr, &c.CpuSoftIntr)

	return &c, nil
}

func getMemStats() (*sflow.HostMemoryCounters, error) {
	f, err := os.Open("/proc/meminfo")
	if err != nil {
		return nil, err
	}

	m := sflow.HostMemoryCounters{}

	r := bufio.NewReader(f)
	for line, err := r.ReadString('\n'); err == nil; line, err = r.ReadString('\n') {
		lineStr := string(line)
		parts := strings.Split(lineStr, ":")
		switch parts[0] {
		case "MemTotal":
			m.Total = meminfoHelper(parts[1])
		case "MemFree":
			m.Free = meminfoHelper(parts[1])
		case "Buffers":
			m.Buffers = meminfoHelper(parts[1])
		case "Cached":
			m.Cached = meminfoHelper(parts[1])
		case "SwapTotal":
			m.SwapTotal = meminfoHelper(parts[1])
		case "SwapFree":
			m.SwapFree = meminfoHelper(parts[1])
		}
	}

	return &m, nil
}

func meminfoHelper(s string) uint64 {
	parts := strings.Split(strings.TrimSpace(s), " ")
	n, err := strconv.Atoi(parts[0])
	if err != nil {
		return 0
	}
	return uint64(n) * 1024
}

func getIP() net.IP {
	ifaces, err := net.Interfaces()
	if err != nil {
		return nil
	}

	for _, iface := range ifaces {
		if iface.Flags&net.FlagUp == 0 {
			continue // interface down
		}
		if iface.Flags&net.FlagLoopback != 0 {
			continue // loopback interface
		}
		addrs, err := iface.Addrs()
		if err != nil {
			return nil
		}
		for _, addr := range addrs {
			var ip net.IP
			switch v := addr.(type) {
			case *net.IPNet:
				ip = v.IP
			case *net.IPAddr:
				ip = v.IP
			}
			if ip == nil || ip.IsLoopback() {
				continue
			}
			return ip
		}
	}

	return net.IPv6loopback

}
<commit_msg>use updated sflow package<commit_after>package main

import (
	"github.com/PreetamJinka/sflow"
	"github.com/PreetamJinka/udpchan"

	"bufio"
	"bytes"
	"flag"
	"fmt"
	"io/ioutil"
	"log"
	"net"
	"os"
	"runtime"
	"strconv"
	"strings"
	"time"
)

func main() {
	outbound := flag.String("outbound", "localhost:6343", "Address of collector")
	flag.Parse()

	ip := getIP()

	ch, err := udpchan.Connect(*outbound)
	if err != nil {
		log.Fatal(err)
	}

	buf := &bytes.Buffer{}

	enc := sflow.NewEncoder(ip, 23000, 100)

	for _ = range time.Tick(time.Second * 5) {
		stats := []sflow.Record{}

		cpu, err := getCpuStats()
		if err == nil {
			stats = append(stats, cpu)
		}

		mem, err := getMemStats()
		if err == nil {
			stats = append(stats, mem)
		}

		cs := &sflow.CounterSample{}
		cs.Records = stats

		err = enc.Encode(buf, []sflow.Sample{cs})

		if err == nil {
			ch <- buf.Bytes()
			log.Println("Sent a datagram")
		} else {
			log.Println(err)
		}

		buf.Reset()
	}
}

func getCpuStats() (*sflow.HostCPUCounters, error) {
	loadAvgBytes, err := ioutil.ReadFile("/proc/loadavg")
	if err != nil {
		return nil, err
	}

	c := sflow.HostCPUCounters{}

	fmt.Sscanf(string(loadAvgBytes), "%f %f %f %d/%d", &c.Load1m, &c.Load5m, &c.Load15m,
		&c.ProcessesRunning, &c.ProcessesTotal)

	c.NumCPU = uint32(runtime.NumCPU())

	uptimeBytes, err := ioutil.ReadFile("/proc/uptime")
	if err != nil {
		return nil, err
	}
	fmt.Sscanf(string(uptimeBytes), "%d", &c.Uptime)

	cpuStatBytes, err := ioutil.ReadFile("/proc/stat")
	if err != nil {
		return nil, err
	}
	fmt.Sscanf(string(cpuStatBytes), "cpu %d %d %d %d %d %d %d", &c.CPUUser, &c.CPUNice, &c.CPUSys, &c.CPUIdle,
		&c.CPUWio, &c.CPUIntr, &c.CPUSoftIntr)

	return &c, nil
}

func getMemStats() (*sflow.HostMemoryCounters, error) {
	f, err := os.Open("/proc/meminfo")
	if err != nil {
		return nil, err
	}

	m := sflow.HostMemoryCounters{}

	r := bufio.NewReader(f)
	for line, err := r.ReadString('\n'); err == nil; line, err = r.ReadString('\n') {
		lineStr := string(line)
		parts := strings.Split(lineStr, ":")
		switch parts[0] {
		case "MemTotal":
			m.Total = meminfoHelper(parts[1])
		case "MemFree":
			m.Free = meminfoHelper(parts[1])
		case "Buffers":
			m.Buffers = meminfoHelper(parts[1])
		case "Cached":
			m.Cached = meminfoHelper(parts[1])
		case "SwapTotal":
			m.SwapTotal = meminfoHelper(parts[1])
		case "SwapFree":
			m.SwapFree = meminfoHelper(parts[1])
		}
	}

	return &m, nil
}

func meminfoHelper(s string) uint64 {
	parts := strings.Split(strings.TrimSpace(s), " ")
	n, err := strconv.Atoi(parts[0])
	if err != nil {
		return 0
	}
	return uint64(n) * 1024
}

func getIP() net.IP {
	ifaces, err := net.Interfaces()
	if err != nil {
		return nil
	}

	for _, iface := range ifaces {
		if iface.Flags&net.FlagUp == 0 {
			continue // interface down
		}
		if iface.Flags&net.FlagLoopback != 0 {
			continue // loopback interface
		}
		addrs, err := iface.Addrs()
		if err != nil {
			return nil
		}
		for _, addr := range addrs {
			var ip net.IP
			switch v := addr.(type) {
			case *net.IPNet:
				ip = v.IP
			case *net.IPAddr:
				ip = v.IP
			}
			if ip == nil || ip.IsLoopback() {
				continue
			}
			return ip
		}
	}

	return net.IPv6loopback

}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"regexp"
	"strconv"
	"time"

	"github.com/lucagrulla/cw/cloudwatch"
	"github.com/lucagrulla/cw/timeutil"
	"gopkg.in/alecthomas/kingpin.v2"
)

var (
	lsCommand      = kingpin.Command("ls", "Show an entity")
	lsGroups       = lsCommand.Command("groups", "Show all groups.")
	lsStreams      = lsCommand.Command("streams", "Show all streams in a given log group.")
	lsLogGroupName = lsStreams.Arg("group", "the group name").HintAction(groupsCompletion).Required().String()

	tailCommand = kingpin.Command("tail", "Tail a log group.")

	follow          = tailCommand.Flag("follow", "Don't stop when the end of stream is reached, but rather wait for additional data to be appended.").Short('f').Default("false").Bool()
	printTimestamp  = tailCommand.Flag("timestamp", "Print the event timestamp.").Short('t').Default("false").Bool()
	printEventId    = tailCommand.Flag("event Id", "Print the event Id").Short('i').Default("false").Bool()
	printStreamName = tailCommand.Flag("stream name", "Print the log stream name this event belongs to.").Short('s').Default("false").Bool()
	grep            = tailCommand.Flag("grep", "Pattern to filter logs by. See http://docs.aws.amazon.com/AmazonCloudWatch/latest/logs/FilterAndPatternSyntax.html for syntax.").Short('g').Default("").String()
	logGroupName    = tailCommand.Arg("group", "The log group name.").Required().HintAction(groupsCompletion).String()
	logStreamName   = tailCommand.Arg("stream", "The log stream name. Use \\* for tail all the group streams.").Default("*").HintAction(streamsCompletion).String()
	startTime       = tailCommand.Arg("start", "The tailing start time in UTC. If a timestamp is passed(format: hh[:mm]) it's expanded to today at the given time. Full format: 2017-02-27[T09:00[:00]].").
			Default(time.Now().UTC().Add(-30 * time.Second).Format(timeutil.TimeFormat)).String()
	endTime = tailCommand.Arg("end", "The tailing end time in UTC. If a timestamp is passed(format: hh[:mm]) it's expanded to today at the given time. Full format: 2017-02-27[T09:00[:00]].").String()
)

func groupsCompletion() []string {
	var groups []string
	for msg := range cloudwatch.LsGroups() {
		groups = append(groups, *msg)
	}
	return groups

}

func streamsCompletion() []string {
	var streams []string
	for msg := range cloudwatch.LsStreams(logGroupName, nil) {
		streams = append(streams, *msg)
	}
	return streams
}

func timestampToUTC(timeStamp *string) time.Time {
	if regexp.MustCompile("^\\d{4}-\\d{2}-\\d{2}$").MatchString(*timeStamp) {
		t, _ := time.ParseInLocation("2006-01-02", *timeStamp, time.UTC)
		return t
	} else if regexp.MustCompile("^\\d{4}-\\d{2}-\\d{2}T\\d{2}$").MatchString(*timeStamp) {
		t, _ := time.ParseInLocation("2006-01-02T15", *timeStamp, time.UTC)
		return t
	} else if regexp.MustCompile("^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}$").MatchString(*timeStamp) {
		t, _ := time.ParseInLocation("2006-01-02T15:04", *timeStamp, time.UTC)
		return t
	} else if regexp.MustCompile("^\\d{1,2}$").MatchString(*timeStamp) {
		y, m, d := time.Now().Date()
		t, _ := strconv.Atoi(*timeStamp)
		return time.Date(y, m, d, t, 0, 0, 0, time.UTC)
	} else if res := regexp.MustCompile(`^(?P<Hour>\d{1,2}):(?P<Minute>\d{2})$`).FindStringSubmatch(*timeStamp); res != nil {
		y, m, d := time.Now().Date()

		t, _ := strconv.Atoi(res[1])
		mm, _ := strconv.Atoi(res[2])

		return time.Date(y, m, d, t, mm, 0, 0, time.UTC)

	}
	//TODO check even last scenario and if it's not a recognized pattern throw an error
	t, _ := time.ParseInLocation("2006-01-02T15:04:05", *timeStamp, time.UTC)
	return t
}

func main() {
	kingpin.Version("1.3.1").Author("Luca Grulla")
	command := kingpin.Parse()

	switch command {
	case "ls groups":
		for msg := range cloudwatch.LsGroups() {
			fmt.Println(*msg)
		}
	case "ls streams":
		for msg := range cloudwatch.LsStreams(lsLogGroupName, nil) {
			fmt.Println(*msg)
		}
	case "tail":
		st := timestampToUTC(startTime)
		var et time.Time
		if *endTime != "" {
			et = timestampToUTC(endTime)
		}

		for msg := range cloudwatch.Tail(logGroupName, logStreamName, follow, &st, &et, grep, printTimestamp, printStreamName, printEventId) {
			fmt.Println(*msg)
		}
	}
}
<commit_msg>1.3.2<commit_after>package main

import (
	"fmt"
	"regexp"
	"strconv"
	"time"

	"github.com/lucagrulla/cw/cloudwatch"
	"github.com/lucagrulla/cw/timeutil"
	"gopkg.in/alecthomas/kingpin.v2"
)

var (
	lsCommand      = kingpin.Command("ls", "Show an entity")
	lsGroups       = lsCommand.Command("groups", "Show all groups.")
	lsStreams      = lsCommand.Command("streams", "Show all streams in a given log group.")
	lsLogGroupName = lsStreams.Arg("group", "the group name").HintAction(groupsCompletion).Required().String()

	tailCommand = kingpin.Command("tail", "Tail a log group.")

	follow          = tailCommand.Flag("follow", "Don't stop when the end of stream is reached, but rather wait for additional data to be appended.").Short('f').Default("false").Bool()
	printTimestamp  = tailCommand.Flag("timestamp", "Print the event timestamp.").Short('t').Default("false").Bool()
	printEventId    = tailCommand.Flag("event Id", "Print the event Id").Short('i').Default("false").Bool()
	printStreamName = tailCommand.Flag("stream name", "Print the log stream name this event belongs to.").Short('s').Default("false").Bool()
	grep            = tailCommand.Flag("grep", "Pattern to filter logs by. See http://docs.aws.amazon.com/AmazonCloudWatch/latest/logs/FilterAndPatternSyntax.html for syntax.").Short('g').Default("").String()
	logGroupName    = tailCommand.Arg("group", "The log group name.").Required().HintAction(groupsCompletion).String()
	logStreamName   = tailCommand.Arg("stream", "The log stream name. Use \\* for tail all the group streams.").Default("*").HintAction(streamsCompletion).String()
	startTime       = tailCommand.Arg("start", "The tailing start time in UTC. If a timestamp is passed(format: hh[:mm]) it's expanded to today at the given time. Full format: 2017-02-27[T09:00[:00]].").
			Default(time.Now().UTC().Add(-30 * time.Second).Format(timeutil.TimeFormat)).String()
	endTime = tailCommand.Arg("end", "The tailing end time in UTC. If a timestamp is passed(format: hh[:mm]) it's expanded to today at the given time. Full format: 2017-02-27[T09:00[:00]].").String()
)

func groupsCompletion() []string {
	var groups []string
	for msg := range cloudwatch.LsGroups() {
		groups = append(groups, *msg)
	}
	return groups

}

func streamsCompletion() []string {
	var streams []string
	for msg := range cloudwatch.LsStreams(logGroupName, nil) {
		streams = append(streams, *msg)
	}
	return streams
}

func timestampToUTC(timeStamp *string) time.Time {
	if regexp.MustCompile("^\\d{4}-\\d{2}-\\d{2}$").MatchString(*timeStamp) {
		t, _ := time.ParseInLocation("2006-01-02", *timeStamp, time.UTC)
		return t
	} else if regexp.MustCompile("^\\d{4}-\\d{2}-\\d{2}T\\d{2}$").MatchString(*timeStamp) {
		t, _ := time.ParseInLocation("2006-01-02T15", *timeStamp, time.UTC)
		return t
	} else if regexp.MustCompile("^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}$").MatchString(*timeStamp) {
		t, _ := time.ParseInLocation("2006-01-02T15:04", *timeStamp, time.UTC)
		return t
	} else if regexp.MustCompile("^\\d{1,2}$").MatchString(*timeStamp) {
		y, m, d := time.Now().Date()
		t, _ := strconv.Atoi(*timeStamp)
		return time.Date(y, m, d, t, 0, 0, 0, time.UTC)
	} else if res := regexp.MustCompile(`^(?P<Hour>\d{1,2}):(?P<Minute>\d{2})$`).FindStringSubmatch(*timeStamp); res != nil {
		y, m, d := time.Now().Date()

		t, _ := strconv.Atoi(res[1])
		mm, _ := strconv.Atoi(res[2])

		return time.Date(y, m, d, t, mm, 0, 0, time.UTC)

	}
	//TODO check even last scenario and if it's not a recognized pattern throw an error
	t, _ := time.ParseInLocation("2006-01-02T15:04:05", *timeStamp, time.UTC)
	return t
}

func main() {
	kingpin.Version("1.3.2").Author("Luca Grulla")
	command := kingpin.Parse()

	switch command {
	case "ls groups":
		for msg := range cloudwatch.LsGroups() {
			fmt.Println(*msg)
		}
	case "ls streams":
		for msg := range cloudwatch.LsStreams(lsLogGroupName, nil) {
			fmt.Println(*msg)
		}
	case "tail":
		st := timestampToUTC(startTime)
		var et time.Time
		if *endTime != "" {
			et = timestampToUTC(endTime)
		}

		for msg := range cloudwatch.Tail(logGroupName, logStreamName, follow, &st, &et, grep, printTimestamp, printStreamName, printEventId) {
			fmt.Println(*msg)
		}
	}
}
<|endoftext|>


<commit_before>// Version 1.82
// Supports Windows, Linux, Mac, and Raspberry Pi, Beagle Bone Black

package main

import (
	"flag"
	log "github.com/Sirupsen/logrus"
	"github.com/gin-gonic/gin"
	"github.com/itsjamie/gin-cors"
	"github.com/kardianos/osext"
	"github.com/vharitonsky/iniflags"
	"os"
	"os/user"
	"path/filepath"
	"runtime/debug"
	"text/template"
	"time"
	//"github.com/sanbornm/go-selfupdate/selfupdate" #included in update.go to change heavily
)

var (
	version              = "x.x.x-dev" //don't modify it, Jenkins will take care
	git_revision         = "xxxxxxxx"  //don't modify it, Jenkins will take care
	embedded_autoupdate  = true
	embedded_autoextract = false
	hibernate            = flag.Bool("hibernate", false, "start hibernated")
	addr                 = flag.String("addr", ":8989", "http service address")
	addrSSL              = flag.String("addrSSL", ":8990", "https service address")
	verbose              = flag.Bool("v", true, "show debug logging")
	//verbose = flag.Bool("v", false, "show debug logging")
	isLaunchSelf = flag.Bool("ls", false, "launch self 5 seconds later")
	configIni    = flag.String("configFile", "config.ini", "config file path")
	regExpFilter = flag.String("regex", "usb|acm|com", "Regular expression to filter serial port list")
	gcType       = flag.String("gc", "std", "Type of garbage collection. std = Normal garbage collection allowing system to decide (this has been known to cause a stop the world in the middle of a CNC job which can cause lost responses from the CNC controller and thus stalled jobs. use max instead to solve.), off = let memory grow unbounded (you have to send in the gc command manually to garbage collect or you will run out of RAM eventually), max = Force garbage collection on each recv or send on a serial port (this minimizes stop the world events and thus lost serial responses, but increases CPU usage)")
	logDump      = flag.String("log", "off", "off = (default)")
	// hostname. allow user to override, otherwise we look it up
	hostname       = flag.String("hostname", "unknown-hostname", "Override the hostname we get from the OS")
	updateUrl      = flag.String("updateUrl", "", "")
	appName        = flag.String("appName", "", "")
	globalToolsMap = make(map[string]string)
	tempToolsPath  = createToolsDir()
)

type NullWriter int

func (NullWriter) Write([]byte) (int, error) { return 0, nil }

type logWriter struct{}

func (u *logWriter) Write(p []byte) (n int, err error) {
	h.broadcastSys <- p
	return 0, nil
}

var logger_ws logWriter

func createToolsDir() string {
	usr, _ := user.Current()
	return usr.HomeDir + "/.arduino-create"
}

func homeHandler(c *gin.Context) {
	homeTemplate.Execute(c.Writer, c.Request.Host)
}

func launchSelfLater() {
	log.Println("Going to launch myself 2 seconds later.")
	time.Sleep(2 * 1000 * time.Millisecond)
	log.Println("Done waiting 2 secs. Now launching...")
}

func main() {

	flag.Parse()
	go func() {

		// autoextract self
		src, _ := osext.Executable()
		dest := filepath.Dir(src)

		os.Mkdir(tempToolsPath, 0777)
		hideFile(tempToolsPath)

		if embedded_autoextract {
			// save the config.ini (if it exists)
			if _, err := os.Stat(dest + "/" + *configIni); os.IsNotExist(err) {
				log.Println("First run, unzipping self")
				err := Unzip(src, dest)
				log.Println("Self extraction, err:", err)
			}

			if _, err := os.Stat(dest + "/" + *configIni); os.IsNotExist(err) {
				flag.Parse()
				log.Println("No config.ini at", *configIni)
			} else {
				flag.Parse()
				flag.Set("config", dest+"/"+*configIni)
				iniflags.Parse()
			}
		} else {
			flag.Set("config", dest+"/"+*configIni)
			iniflags.Parse()
		}

		//log.SetFormatter(&log.JSONFormatter{})

		log.SetLevel(log.InfoLevel)

		log.SetOutput(os.Stderr)

		// see if we are supposed to wait 5 seconds
		if *isLaunchSelf {
			launchSelfLater()
		}

		if embedded_autoupdate {

			var updater = &Updater{
				CurrentVersion: version,
				ApiURL:         *updateUrl,
				BinURL:         *updateUrl,
				DiffURL:        "",
				Dir:            "update/",
				CmdName:        *appName,
			}

			if updater != nil {
				go updater.BackgroundRun()
			}
		}

		f := flag.Lookup("addr")
		log.Println("Version:" + version)

		// hostname
		hn, _ := os.Hostname()
		if *hostname == "unknown-hostname" {
			*hostname = hn
		}
		log.Println("Hostname:", *hostname)

		// turn off garbage collection
		// this is dangerous, as u could overflow memory
		//if *isGC {
		if *gcType == "std" {
			log.Println("Garbage collection is on using Standard mode, meaning we just let Golang determine when to garbage collect.")
		} else if *gcType == "max" {
			log.Println("Garbage collection is on for MAXIMUM real-time collecting on each send/recv from serial port. Higher CPU, but less stopping of the world to garbage collect since it is being done on a constant basis.")
		} else {
			log.Println("Garbage collection is off. Memory use will grow unbounded. You WILL RUN OUT OF RAM unless you send in the gc command to manually force garbage collection. Lower CPU, but progressive memory footprint.")
			debug.SetGCPercent(-1)
		}

		ip := "0.0.0.0"
		log.Print("Starting server and websocket on " + ip + "" + f.Value.String())

		log.Println("The Arduino Create Agent is now running")

		// see if they provided a regex filter
		if len(*regExpFilter) > 0 {
			log.Printf("You specified a serial port regular expression filter: %v\n", *regExpFilter)
		}

		// list serial ports
		portList, _ := GetList(false)
		log.Println("Your serial ports:")
		if len(portList) == 0 {
			log.Println("\tThere are no serial ports to list.")
		}
		for _, element := range portList {
			log.Printf("\t%v\n", element)

		}

		if !*verbose {
			log.Println("You can enter verbose mode to see all logging by starting with the -v command line switch.")
			log.SetOutput(new(NullWriter)) //route all logging to nullwriter
		}

		// launch the hub routine which is the singleton for the websocket server
		go h.run()
		// launch our serial port routine
		go sh.run()
		// launch our dummy data routine
		//go d.run()

		go discoverLoop()

		r := gin.New()

		socketHandler := wsHandler().ServeHTTP

		r.Use(cors.Middleware(cors.Config{
			Origins:         "https://create.arduino.cc, http://create.arduino.cc, https://create-dev.arduino.cc, http://create-dev.arduino.cc, http://webide.arduino.cc:8080, http://create-staging.arduino.cc, https://create-staging.arduino.cc, http://localhost:8989, https://localhost:8990",
			Methods:         "GET, PUT, POST, DELETE",
			RequestHeaders:  "Origin, Authorization, Content-Type",
			ExposedHeaders:  "",
			MaxAge:          50 * time.Second,
			Credentials:     true,
			ValidateHeaders: false,
		}))

		r.GET("/", homeHandler)
		r.POST("/upload", uploadHandler)
		r.GET("/socket.io/", socketHandler)
		r.POST("/socket.io/", socketHandler)
		r.Handle("WS", "/socket.io/", socketHandler)
		r.Handle("WSS", "/socket.io/", socketHandler)
		go func() {
			if err := r.RunTLS(*addrSSL, filepath.Join(dest, "cert.pem"), filepath.Join(dest, "key.pem")); err != nil {
				log.Printf("Error trying to bind to port: %v, so exiting...", err)
				log.Fatal("Error ListenAndServe:", err)
			}
		}()

		if err := r.Run(*addr); err != nil {
			log.Printf("Error trying to bind to port: %v, so exiting...", err)
			log.Fatal("Error ListenAndServe:", err)
		}
	}()
	setupSysTray()
}

var homeTemplate = template.Must(template.New("home").Parse(homeTemplateHtml))

// If you navigate to this server's homepage, you'll get this HTML
// so you can directly interact with the serial port server
const homeTemplateHtml = `<!DOCTYPE html>

<title>Serial Port Example</title>

<form id="form">
    <input type="submit" value="Send" />
    <input type="text" id="msg" size="64"/>
    <input name="pause" type="checkbox" value="pause" id="myCheck"/> Pause

</form>

`
<commit_msg>add scheduled autoupdate check<commit_after>// Version 1.82
// Supports Windows, Linux, Mac, and Raspberry Pi, Beagle Bone Black

package main

import (
	"flag"
	log "github.com/Sirupsen/logrus"
	"github.com/carlescere/scheduler"
	"github.com/gin-gonic/gin"
	"github.com/itsjamie/gin-cors"
	"github.com/kardianos/osext"
	"github.com/vharitonsky/iniflags"
	"os"
	"os/user"
	"path/filepath"
	"runtime/debug"
	"text/template"
	"time"
	//"github.com/sanbornm/go-selfupdate/selfupdate" #included in update.go to change heavily
)

var (
	version              = "x.x.x-dev" //don't modify it, Jenkins will take care
	git_revision         = "xxxxxxxx"  //don't modify it, Jenkins will take care
	embedded_autoupdate  = true
	embedded_autoextract = false
	hibernate            = flag.Bool("hibernate", false, "start hibernated")
	addr                 = flag.String("addr", ":8989", "http service address")
	addrSSL              = flag.String("addrSSL", ":8990", "https service address")
	verbose              = flag.Bool("v", true, "show debug logging")
	//verbose = flag.Bool("v", false, "show debug logging")
	isLaunchSelf = flag.Bool("ls", false, "launch self 5 seconds later")
	configIni    = flag.String("configFile", "config.ini", "config file path")
	regExpFilter = flag.String("regex", "usb|acm|com", "Regular expression to filter serial port list")
	gcType       = flag.String("gc", "std", "Type of garbage collection. std = Normal garbage collection allowing system to decide (this has been known to cause a stop the world in the middle of a CNC job which can cause lost responses from the CNC controller and thus stalled jobs. use max instead to solve.), off = let memory grow unbounded (you have to send in the gc command manually to garbage collect or you will run out of RAM eventually), max = Force garbage collection on each recv or send on a serial port (this minimizes stop the world events and thus lost serial responses, but increases CPU usage)")
	logDump      = flag.String("log", "off", "off = (default)")
	// hostname. allow user to override, otherwise we look it up
	hostname       = flag.String("hostname", "unknown-hostname", "Override the hostname we get from the OS")
	updateUrl      = flag.String("updateUrl", "", "")
	appName        = flag.String("appName", "", "")
	globalToolsMap = make(map[string]string)
	tempToolsPath  = createToolsDir()
)

type NullWriter int

func (NullWriter) Write([]byte) (int, error) { return 0, nil }

type logWriter struct{}

func (u *logWriter) Write(p []byte) (n int, err error) {
	h.broadcastSys <- p
	return 0, nil
}

var logger_ws logWriter

func createToolsDir() string {
	usr, _ := user.Current()
	return usr.HomeDir + "/.arduino-create"
}

func homeHandler(c *gin.Context) {
	homeTemplate.Execute(c.Writer, c.Request.Host)
}

func launchSelfLater() {
	log.Println("Going to launch myself 2 seconds later.")
	time.Sleep(2 * 1000 * time.Millisecond)
	log.Println("Done waiting 2 secs. Now launching...")
}

func main() {

	flag.Parse()
	go func() {

		// autoextract self
		src, _ := osext.Executable()
		dest := filepath.Dir(src)

		os.Mkdir(tempToolsPath, 0777)
		hideFile(tempToolsPath)

		if embedded_autoextract {
			// save the config.ini (if it exists)
			if _, err := os.Stat(dest + "/" + *configIni); os.IsNotExist(err) {
				log.Println("First run, unzipping self")
				err := Unzip(src, dest)
				log.Println("Self extraction, err:", err)
			}

			if _, err := os.Stat(dest + "/" + *configIni); os.IsNotExist(err) {
				flag.Parse()
				log.Println("No config.ini at", *configIni)
			} else {
				flag.Parse()
				flag.Set("config", dest+"/"+*configIni)
				iniflags.Parse()
			}
		} else {
			flag.Set("config", dest+"/"+*configIni)
			iniflags.Parse()
		}

		//log.SetFormatter(&log.JSONFormatter{})

		log.SetLevel(log.InfoLevel)

		log.SetOutput(os.Stderr)

		// see if we are supposed to wait 5 seconds
		if *isLaunchSelf {
			launchSelfLater()
		}

		if embedded_autoupdate {

			var updater = &Updater{
				CurrentVersion: version,
				ApiURL:         *updateUrl,
				BinURL:         *updateUrl,
				DiffURL:        "",
				Dir:            "update/",
				CmdName:        *appName,
			}

			if updater != nil {
				updater_job := func() {
					go updater.BackgroundRun()
				}
				scheduler.Every(5).Minutes().Run(updater_job)
			}
		}

		f := flag.Lookup("addr")
		log.Println("Version:" + version)

		// hostname
		hn, _ := os.Hostname()
		if *hostname == "unknown-hostname" {
			*hostname = hn
		}
		log.Println("Hostname:", *hostname)

		// turn off garbage collection
		// this is dangerous, as u could overflow memory
		//if *isGC {
		if *gcType == "std" {
			log.Println("Garbage collection is on using Standard mode, meaning we just let Golang determine when to garbage collect.")
		} else if *gcType == "max" {
			log.Println("Garbage collection is on for MAXIMUM real-time collecting on each send/recv from serial port. Higher CPU, but less stopping of the world to garbage collect since it is being done on a constant basis.")
		} else {
			log.Println("Garbage collection is off. Memory use will grow unbounded. You WILL RUN OUT OF RAM unless you send in the gc command to manually force garbage collection. Lower CPU, but progressive memory footprint.")
			debug.SetGCPercent(-1)
		}

		ip := "0.0.0.0"
		log.Print("Starting server and websocket on " + ip + "" + f.Value.String())

		log.Println("The Arduino Create Agent is now running")

		// see if they provided a regex filter
		if len(*regExpFilter) > 0 {
			log.Printf("You specified a serial port regular expression filter: %v\n", *regExpFilter)
		}

		// list serial ports
		portList, _ := GetList(false)
		log.Println("Your serial ports:")
		if len(portList) == 0 {
			log.Println("\tThere are no serial ports to list.")
		}
		for _, element := range portList {
			log.Printf("\t%v\n", element)

		}

		if !*verbose {
			log.Println("You can enter verbose mode to see all logging by starting with the -v command line switch.")
			log.SetOutput(new(NullWriter)) //route all logging to nullwriter
		}

		// launch the hub routine which is the singleton for the websocket server
		go h.run()
		// launch our serial port routine
		go sh.run()
		// launch our dummy data routine
		//go d.run()

		go discoverLoop()

		r := gin.New()

		socketHandler := wsHandler().ServeHTTP

		r.Use(cors.Middleware(cors.Config{
			Origins:         "https://create.arduino.cc, http://create.arduino.cc, https://create-dev.arduino.cc, http://create-dev.arduino.cc, http://webide.arduino.cc:8080, http://create-staging.arduino.cc, https://create-staging.arduino.cc, http://localhost:8989, https://localhost:8990",
			Methods:         "GET, PUT, POST, DELETE",
			RequestHeaders:  "Origin, Authorization, Content-Type",
			ExposedHeaders:  "",
			MaxAge:          50 * time.Second,
			Credentials:     true,
			ValidateHeaders: false,
		}))

		r.GET("/", homeHandler)
		r.POST("/upload", uploadHandler)
		r.GET("/socket.io/", socketHandler)
		r.POST("/socket.io/", socketHandler)
		r.Handle("WS", "/socket.io/", socketHandler)
		r.Handle("WSS", "/socket.io/", socketHandler)
		go func() {
			if err := r.RunTLS(*addrSSL, filepath.Join(dest, "cert.pem"), filepath.Join(dest, "key.pem")); err != nil {
				log.Printf("Error trying to bind to port: %v, so exiting...", err)
				log.Fatal("Error ListenAndServe:", err)
			}
		}()

		if err := r.Run(*addr); err != nil {
			log.Printf("Error trying to bind to port: %v, so exiting...", err)
			log.Fatal("Error ListenAndServe:", err)
		}
	}()
	setupSysTray()
}

var homeTemplate = template.Must(template.New("home").Parse(homeTemplateHtml))

// If you navigate to this server's homepage, you'll get this HTML
// so you can directly interact with the serial port server
const homeTemplateHtml = `<!DOCTYPE html>

<title>Serial Port Example</title>

<form id="form">
    <input type="submit" value="Send" />
    <input type="text" id="msg" size="64"/>
    <input name="pause" type="checkbox" value="pause" id="myCheck"/> Pause

</form>

`
<|endoftext|>


<commit_before>// Copyright 2017 XUEQIU.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 main

import (
	"net/http"
	"os"

	"github.com/urfave/cli"

	"fmt"

	"path/filepath"

	"github.com/dongmx/rdb"
	"github.com/elazarl/go-bindata-assetfs"
	"github.com/julienschmidt/httprouter"
	"github.com/xueqiu/rdr/static"
)

//go:generate go-bindata -prefix "static/" -o=static/static.go -pkg=static -ignore static.go static/...
//go:generate go-bindata -prefix "views/" -o=views/views.go -pkg=views -ignore views.go views/...

func decode(c *cli.Context, decoder *Decoder, filepath string) {
	f, err := os.Open(filepath)
	if err != nil {
		fmt.Fprintf(c.App.ErrWriter, "open rdbfile err: %v\n", err)
		close(decoder.Entries)
		return
	}
	err = rdb.Decode(f, decoder)
	if err != nil {
		fmt.Fprintf(c.App.ErrWriter, "decode rdbfile err: %v\n", err)
		close(decoder.Entries)
		return
	}
}

var counters = NewSafeMap()

// show parse rdbfile(s) and show statistical information by html
func show(c *cli.Context) {
	if c.NArg() < 1 {
		fmt.Fprintln(c.App.ErrWriter, "show requires at least 1 argument")
		cli.ShowCommandHelp(c, "show")
		return
	}

	// parse rdbfile
	fmt.Fprintln(c.App.Writer, "start parsing...")
	instances := []string{}
	for _, file := range c.Args() {
		decoder := NewDecoder()
		go decode(c, decoder, file)
		counter := NewCounter()
		counter.Count(decoder.Entries)
		filename := filepath.Base(file)
		counters.Set(filename, counter)
		instances = append(instances, filename)
		fmt.Fprintf(c.App.Writer, "parse %v  done\n", file)
	}

	// init html template
	// init common data in template
	initHTMLTmpl()
	tplCommonData["Instances"] = instances

	// start http server
	staticFS := assetfs.AssetFS{
		Asset:     static.Asset,
		AssetDir:  static.AssetDir,
		AssetInfo: static.AssetInfo,
	}
	router := httprouter.New()
	router.ServeFiles("/static/*filepath", &staticFS)
	router.GET("/", index)
	router.GET("/instance/:path", rdbReveal)
	fmt.Fprintln(c.App.Writer, "parsing finished, please access http://{$IP}:"+c.String("port"))
	listenErr := http.ListenAndServe(":"+c.String("port"), router)
	if listenErr != nil {
		fmt.Fprintf(c.App.ErrWriter, "Listen port err: %v\n", listenErr)
	}
}

// keys is function for command `keys`
// output all keys in rdbfile(s) get from args
func keys(c *cli.Context) {
	if c.NArg() < 1 {
		fmt.Fprintln(c.App.ErrWriter, "keys requires at least 1 argument")
		cli.ShowCommandHelp(c, "keys")
		return
	}
	for _, filepath := range c.Args() {
		decoder := NewDecoder()
		go decode(c, decoder, filepath)
		for e := range decoder.Entries {
			fmt.Fprintf(c.App.Writer, "%v\n", e.Key)
		}
	}
}

func main() {
	app := cli.NewApp()
	app.Name = "rdr"
	app.Usage = "a tool to parse redis rdbfile"
	app.Version = "v0.0.1"
	app.Writer = os.Stdout
	app.ErrWriter = os.Stderr
	app.Commands = []cli.Command{
		cli.Command{
			Name:      "show",
			Usage:     "show statistical information of rdbfile by webpage",
			ArgsUsage: "FILE1 [FILE2] [FILE3]...",
			Flags: []cli.Flag{
				cli.UintFlag{
					Name:  "port, p",
					Value: 8080,
					Usage: "Port for rdr to listen",
				},
			},
			Action: show,
		},
		cli.Command{
			Name:      "keys",
			Usage:     "get all keys from rdbfile",
			ArgsUsage: "FILE1 [FILE2] [FILE3]...",
			Action:    keys,
		},
	}
	app.CommandNotFound = func(c *cli.Context, command string) {
		fmt.Fprintf(c.App.ErrWriter, "command %q can not be found.\n", command)
		cli.ShowAppHelp(c)
	}
	app.Run(os.Args)
}
<commit_msg>添加Dump到STDOUT的功能 语法: rdr dump FILE1 [FILE2] [FILE3]...<commit_after>// Copyright 2017 XUEQIU.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 main

import (
	"net/http"
	"os"

	"github.com/urfave/cli"

	"fmt"

	"path/filepath"

	"github.com/dongmx/rdb"
	"github.com/elazarl/go-bindata-assetfs"
	"github.com/julienschmidt/httprouter"
	"github.com/xueqiu/rdr/static"
	"encoding/json"
)

//go:generate go-bindata -prefix "static/" -o=static/static.go -pkg=static -ignore static.go static/...
//go:generate go-bindata -prefix "views/" -o=views/views.go -pkg=views -ignore views.go views/...

func decode(c *cli.Context, decoder *Decoder, filepath string) {
	f, err := os.Open(filepath)
	if err != nil {
		fmt.Fprintf(c.App.ErrWriter, "open rdbfile err: %v\n", err)
		close(decoder.Entries)
		return
	}
	err = rdb.Decode(f, decoder)
	if err != nil {
		fmt.Fprintf(c.App.ErrWriter, "decode rdbfile err: %v\n", err)
		close(decoder.Entries)
		return
	}
}

var counters = NewSafeMap()

func getData(filename string, cnt *Counter) map[string]interface{} {
	data := make(map[string]interface{})
	data["CurrentInstance"] = filename
	data["LargestKeys"] = cnt.GetLargestEntries(100)

	largestKeyPrefixesByType := map[string][]*PrefixEntry{}
	for _, entry := range cnt.GetLargestKeyPrefixes() {
		// if mem usage is less than 1M, and the list is long enough, then it's unnecessary to add it.
		if entry.Bytes < 1000*1000 && len(largestKeyPrefixesByType[entry.Type]) > 50 {
			continue
		}
		largestKeyPrefixesByType[entry.Type] = append(largestKeyPrefixesByType[entry.Type], entry)
	}
	data["LargestKeyPrefixes"] = largestKeyPrefixesByType

	data["TypeBytes"] = cnt.typeBytes
	data["TypeNum"] = cnt.typeNum
	totalNum := uint64(0)
	for _, v := range cnt.typeNum {
		totalNum += v
	}
	totalBytes := uint64(0)
	for _, v := range cnt.typeBytes {
		totalBytes += v
	}
	data["TotleNum"] = totalNum
	data["TotleBytes"] = totalBytes

	lenLevelCount := map[string][]*PrefixEntry{}
	for _, entry := range cnt.GetLenLevelCount() {
		lenLevelCount[entry.Type] = append(lenLevelCount[entry.Type], entry)
	}
	data["LenLevelCount"] = lenLevelCount
	return data
}

// dump rdb file statistical information to STDOUT.
func dump(cli *cli.Context) {
	if cli.NArg() < 1 {
		fmt.Fprintln(cli.App.ErrWriter, " requires at least 1 argument")
		return
	}

	// parse rdbfile
	fmt.Fprintln(cli.App.Writer, "[")
	nargs := cli.NArg()
	for i := 0; i < nargs; i++ {
		file := cli.Args().Get(i)
		decoder := NewDecoder()
		go decode(cli, decoder, file)
		cnt := NewCounter()
		cnt.Count(decoder.Entries)
		filename := filepath.Base(file)
		data := getData(filename, cnt)
		jsonBytes, _ := json.MarshalIndent(data, "", "    ")
		fmt.Fprint(cli.App.Writer, string(jsonBytes))
		if i == nargs-1 {
			fmt.Fprintln(cli.App.Writer)
		} else {
			fmt.Fprintln(cli.App.Writer, ",")
		}
	}
	fmt.Fprintln(cli.App.Writer, "]")
}

// show parse rdbfile(s) and show statistical information by html
func show(c *cli.Context) {
	if c.NArg() < 1 {
		fmt.Fprintln(c.App.ErrWriter, "show requires at least 1 argument")
		cli.ShowCommandHelp(c, "show")
		return
	}

	// parse rdbfile
	fmt.Fprintln(c.App.Writer, "start parsing...")
	instances := []string{}
	for _, file := range c.Args() {
		decoder := NewDecoder()
		go decode(c, decoder, file)
		counter := NewCounter()
		counter.Count(decoder.Entries)
		filename := filepath.Base(file)
		counters.Set(filename, counter)
		instances = append(instances, filename)
		fmt.Fprintf(c.App.Writer, "parse %v  done\n", file)
	}

	// init html template
	// init common data in template
	initHTMLTmpl()
	tplCommonData["Instances"] = instances

	// start http server
	staticFS := assetfs.AssetFS{
		Asset:     static.Asset,
		AssetDir:  static.AssetDir,
		AssetInfo: static.AssetInfo,
	}
	router := httprouter.New()
	router.ServeFiles("/static/*filepath", &staticFS)
	router.GET("/", index)
	router.GET("/instance/:path", rdbReveal)
	fmt.Fprintln(c.App.Writer, "parsing finished, please access http://{$IP}:"+c.String("port"))
	listenErr := http.ListenAndServe(":"+c.String("port"), router)
	if listenErr != nil {
		fmt.Fprintf(c.App.ErrWriter, "Listen port err: %v\n", listenErr)
	}
}

// keys is function for command `keys`
// output all keys in rdbfile(s) get from args
func keys(c *cli.Context) {
	if c.NArg() < 1 {
		fmt.Fprintln(c.App.ErrWriter, "keys requires at least 1 argument")
		cli.ShowCommandHelp(c, "keys")
		return
	}
	for _, filepath := range c.Args() {
		decoder := NewDecoder()
		go decode(c, decoder, filepath)
		for e := range decoder.Entries {
			fmt.Fprintf(c.App.Writer, "%v\n", e.Key)
		}
	}
}

func main() {
	app := cli.NewApp()
	app.Name = "rdr"
	app.Usage = "a tool to parse redis rdbfile"
	app.Version = "v0.0.1"
	app.Writer = os.Stdout
	app.ErrWriter = os.Stderr
	app.Commands = []cli.Command{
		cli.Command{
		    Name: "dump",
		    Usage: "dump statistical information of rdbfile to STDOUT",
		    ArgsUsage: "FILE1 [FILE2] [FILE3]...",
		    Action: dump,
		},
		cli.Command{
			Name:      "show",
			Usage:     "show statistical information of rdbfile by webpage",
			ArgsUsage: "FILE1 [FILE2] [FILE3]...",
			Flags: []cli.Flag{
				cli.UintFlag{
					Name:  "port, p",
					Value: 8080,
					Usage: "Port for rdr to listen",
				},
			},
			Action: show,
		},
		cli.Command{
			Name:      "keys",
			Usage:     "get all keys from rdbfile",
			ArgsUsage: "FILE1 [FILE2] [FILE3]...",
			Action:    keys,
		},
	}
	app.CommandNotFound = func(c *cli.Context, command string) {
		fmt.Fprintf(c.App.ErrWriter, "command %q can not be found.\n", command)
		cli.ShowAppHelp(c)
	}
	app.Run(os.Args)
}

<|endoftext|>


<commit_before>package main

import (
	"bufio"
	"fmt"
	"log"
	"net"
	"net/textproto"
	"os"
	"strings"
)

// Connection stores messages sent in the last 30 seconds and the connection itself
type Connection struct {
	conn     net.Conn
	messages int
}

// NewConnection initialize a Connection struct
func NewConnection(conn net.Conn) Connection {
	return Connection{
		conn:     conn,
		messages: 0,
	}

}

// Bot struct for main config
type Bot struct {
	server      string
	groupserver string
	port        string
	oauth       string
	nick        string
	inconn      net.Conn
	mainconn    net.Conn
	connlist    []Connection
	groupconn   net.Conn
}

// NewBot main config
func NewBot() *Bot {
	return &Bot{
		server:      "irc.twitch.tv",
		groupserver: "group.tmi.twitch.tv",
		port:        "6667",
		oauth:       "",
		nick:        "",
		inconn:      nil,
		mainconn:    nil,
		connlist:    make([]Connection, 0),
		groupconn:   nil,
	}
}

// ListenToConnection listen
func (bot *Bot) ListenToConnection(conn net.Conn) {
	reader := bufio.NewReader(conn)
	tp := textproto.NewReader(reader)
	for {
		line, err := tp.ReadLine()
		if err != nil {
			break // break loop on errors
		}
		if strings.Contains(line, "PING") {
			pongdata := strings.Split(line, "PING ")
			fmt.Fprintf(conn, "PONG %s\r\n", pongdata[1])
		}
		bot.Handle(line)
	}
}

// CreateConnection Add a new connection
func (bot *Bot) CreateConnection() (conn net.Conn, err error) {
	conn, err = net.Dial("tcp", bot.server+":"+bot.port)
	if err != nil {
		log.Fatal("unable to connect to IRC server ", err)
		return nil, err
	}
	fmt.Fprintf(conn, "PASS %s\r\n", bot.oauth)
	fmt.Fprintf(conn, "USER %s\r\n", bot.nick)
	fmt.Fprintf(conn, "NICK %s\r\n", bot.nick)
	fmt.Fprintf(conn, "CAP REQ :twitch.tv/tags\r\n")     // enable ircv3 tags
	fmt.Fprintf(conn, "CAP REQ :twitch.tv/commands\r\n") // enable roomstate and such
	log.Printf("Connected to IRC server %s (%s)\n", bot.server, conn.RemoteAddr())

	connnection := NewConnection(conn)
	bot.connlist = append(bot.connlist, connnection)

	if len(bot.connlist) == 1 {
		bot.mainconn = conn
	}

	go bot.ListenToConnection(conn)

	return conn, nil
}

func main() {
	ret := TCPServer()
	log.Printf("got ret code %d\n", ret)
	os.Exit(ret)
}

// HandleJoin will slowly join all channels given
// 45 per 11 seconds to deal with twitch ratelimits
func (bot *Bot) HandleJoin(channels []string) {
	if bot.mainconn == nil {
		log.Printf("No main conn set, can't join channels yet.\n")
		return
	}
	for _, channel := range channels {
		log.Printf("Joining %s\n", channel)
		fmt.Fprintf(bot.mainconn, "JOIN %s\r\n", channel)
	}
}

// Message to send a message
func (bot *Bot) Message(channel string, message string, proxyconn net.Conn) {
	if message == "" {
		return
	}
	log.Printf("Sending message: %s\n", message)

	for _, connection := range bot.connlist {
		if connection.messages < 98 {
			fmt.Fprintf(connection.conn, "PRIVMSG %s :%s\r\n", channel, message)
			connection.messages++
			return
		}
	}
	newConn, _ := bot.CreateConnection()
	fmt.Fprintf(newConn, "PRIVMSG %s :%s\r\n", channel, message)
}

// Handle handles messages from irc
func (bot *Bot) Handle(line string) {
	if strings.Contains(line, ".tmi.twitch.tv PRIVMSG ") {
		bot.inconn.Write([]byte(line + "\r\n"))
		messageTMISplit := strings.Split(line, ".tmi.twitch.tv PRIVMSG ")
		messageChannelRaw := strings.Split(messageTMISplit[1], " :")
		channel := messageChannelRaw[0]
		bot.ProcessMessage(channel, line)
	} else if strings.Contains(line, ":tmi.twitch.tv ROOMSTATE") {
		messageTMISplit := strings.Split(line, ":tmi.twitch.tv ROOMSTATE ")
		channel := messageTMISplit[1]
		bot.ProcessMessage(channel, line)
	}
}

// ProcessMessage push message to local irc chat
func (bot *Bot) ProcessMessage(channel string, message string) {
	fmt.Println(channel + " ::: " + message)
}

// WriteToAllConns writes message to all connections for now
func (bot *Bot) WriteToAllConns(message string) {
	for _, connection := range bot.connlist {
		fmt.Fprintf(connection.conn, message+"\r\n")
	}
}
<commit_msg>added reducing of messages. new connections are not working out correctly<commit_after>package main

import (
	"bufio"
	"fmt"
	"log"
	"net"
	"net/textproto"
	"os"
	"strings"
	"time"
)

// Connection stores messages sent in the last 30 seconds and the connection itself
type Connection struct {
	conn     net.Conn
	messages int
}

// NewConnection initialize a Connection struct
func NewConnection(conn net.Conn) Connection {
	return Connection{
		conn:     conn,
		messages: 0,
	}

}

func (connection *Connection) reduceConnectionMessages() {
	connection.messages--
}

// Bot struct for main config
type Bot struct {
	server      string
	groupserver string
	port        string
	oauth       string
	nick        string
	inconn      net.Conn
	mainconn    net.Conn
	connlist    []Connection
	groupconn   net.Conn
}

// NewBot main config
func NewBot() *Bot {
	return &Bot{
		server:      "irc.twitch.tv",
		groupserver: "group.tmi.twitch.tv",
		port:        "6667",
		oauth:       "",
		nick:        "",
		inconn:      nil,
		mainconn:    nil,
		connlist:    make([]Connection, 0),
		groupconn:   nil,
	}
}

// ListenToConnection listen
func (bot *Bot) ListenToConnection(conn net.Conn) {
	reader := bufio.NewReader(conn)
	tp := textproto.NewReader(reader)
	for {
		line, err := tp.ReadLine()
		if err != nil {
			break // break loop on errors
		}
		if strings.Contains(line, "PING") {
			pongdata := strings.Split(line, "PING ")
			fmt.Fprintf(conn, "PONG %s\r\n", pongdata[1])
		}
		bot.Handle(line)
	}
}

// CreateConnection Add a new connection
func (bot *Bot) CreateConnection() (conn net.Conn, err error) {
	conn, err = net.Dial("tcp", bot.server+":"+bot.port)
	if err != nil {
		log.Fatal("unable to connect to IRC server ", err)
		return nil, err
	}
	fmt.Fprintf(conn, "PASS %s\r\n", bot.oauth)
	fmt.Fprintf(conn, "USER %s\r\n", bot.nick)
	fmt.Fprintf(conn, "NICK %s\r\n", bot.nick)
	fmt.Fprintf(conn, "CAP REQ :twitch.tv/tags\r\n")     // enable ircv3 tags
	fmt.Fprintf(conn, "CAP REQ :twitch.tv/commands\r\n") // enable roomstate and such
	log.Printf("Connected to IRC server %s (%s)\n", bot.server, conn.RemoteAddr())

	connnection := NewConnection(conn)
	bot.connlist = append(bot.connlist, connnection)

	if len(bot.connlist) == 1 {
		bot.mainconn = conn
	}

	go bot.ListenToConnection(conn)

	return conn, nil
}

func main() {
	ret := TCPServer()
	log.Printf("got ret code %d\n", ret)
	os.Exit(ret)
}

// HandleJoin will slowly join all channels given
// 45 per 11 seconds to deal with twitch ratelimits
func (bot *Bot) HandleJoin(channels []string) {
	if bot.mainconn == nil {
		log.Printf("No main conn set, can't join channels yet.\n")
		return
	}
	for _, channel := range channels {
		log.Printf("Joining %s\n", channel)
		fmt.Fprintf(bot.mainconn, "JOIN %s\r\n", channel)
	}
}

// Message to send a message
func (bot *Bot) Message(channel string, message string, proxyconn net.Conn) {
	if message == "" {
		return
	}
	log.Printf("Sending message: %s\n", message)

	for _, connection := range bot.connlist {
		if connection.messages < 98 {
			fmt.Fprintf(connection.conn, "PRIVMSG %s :%s\r\n", channel, message)
			connection.messages++
			time.AfterFunc(30*time.Second, connection.reduceConnectionMessages)
			return
		}
	}
	newConn, _ := bot.CreateConnection()
	fmt.Fprintf(newConn, "PRIVMSG %s :%s\r\n", channel, message)
}

// Handle handles messages from irc
func (bot *Bot) Handle(line string) {
	if strings.Contains(line, ".tmi.twitch.tv PRIVMSG ") {
		bot.inconn.Write([]byte(line + "\r\n"))
		messageTMISplit := strings.Split(line, ".tmi.twitch.tv PRIVMSG ")
		messageChannelRaw := strings.Split(messageTMISplit[1], " :")
		channel := messageChannelRaw[0]
		bot.ProcessMessage(channel, line)
	} else if strings.Contains(line, ":tmi.twitch.tv ROOMSTATE") {
		messageTMISplit := strings.Split(line, ":tmi.twitch.tv ROOMSTATE ")
		channel := messageTMISplit[1]
		bot.ProcessMessage(channel, line)
	}
}

// ProcessMessage push message to local irc chat
func (bot *Bot) ProcessMessage(channel string, message string) {
	fmt.Println(channel + " ::: " + message)
}

// WriteToAllConns writes message to all connections for now
func (bot *Bot) WriteToAllConns(message string) {
	for _, connection := range bot.connlist {
		fmt.Fprintf(connection.conn, message+"\r\n")
	}
}
<|endoftext|>