<commit_before>package gom

import (
	"reflect"
)

type CreateSql func(TableModel) (string, []interface{})

type SqlGenerator struct {
	createSql   CreateSql
	tableModels []TableModel
}
type SqlFactory interface {
	Insert(TableModel) (string, []interface{})
	Update(TableModel) (string, []interface{})
	Replace(TableModel) (string, []interface{})
	Delete(TableModel) (string, []interface{})
	Query(TableModel) (string, []interface{})
}
type RowChooser interface {
	Scan(dest ...interface{}) error
}

type TableModel struct {
	ModelType  reflect.Type
	ModelValue reflect.Value
	TableName  string
	Columns    []Column
	Primary    Column
	Cnd        Condition
}
type Column struct {
	ColumnType reflect.Type
	ColumnName string
	FieldName  string
	IsPrimary  bool
	Auto       bool
}
type Condition interface {
	State() string
	Value() []interface{}
}
type Conditions struct {
	states string
	values []interface{}
}

func Cnd(sql string, values ...interface{}) Conditions {
	return Conditions{sql, values}
}
func (c Conditions) State() string {
	return c.states
}
func (c Conditions) Value() []interface{} {
	return c.values
}
func (c Conditions) And(sql string, values ...interface{}) Conditions {
	if c.states != "" {
		c.states += " and " + sql
	}
	c.states += sql
	c.values = append(c.values, values)
	return c
}
func (c Conditions) Or(sql string, values ...interface{}) Conditions {
	if c.states != "" {
		c.states += " or " + sql
	}
	c.states += sql
	c.values = append(c.values, values)
	return c
}
func (c Conditions) AndIn(name string, values ...interface{}) Conditions {
	if len(values) > 0 {
		if c.states != "" {
			c.states += " and "
		}
		sql := name + " in ("
		for i := 0; i < len(values); i++ {
			if i == 0 {
				sql += " ? "
			} else {
				sql += ", ? "
			}
		}
		sql += ")"
		c.states += sql
		c.values = append(c.values, values)
	}
	return c
}
func (c Conditions) OrIn(name string, values ...interface{}) Conditions {
	if len(values) > 0 {
		if c.states != "" {
			c.states += " or "
		}
		sql := name + " in ("
		for i := 0; i < len(values); i++ {
			if i == 0 {
				sql += " ? "
			} else {
				sql += ", ? "
			}
		}
		sql += ")"
		c.states += sql
		c.values = append(c.values, values)
	}
	return c
}
func (c Conditions) Sql(sql string, values ...interface{}) Conditions {
	c.states += sql
	c.values = append(c.values, values)
	return c
}

func (mo TableModel) InsertValues() []interface{} {
	var interfaces []interface{}
	results := reflect.Indirect(reflect.ValueOf(&interfaces))
	for _, column := range mo.Columns {
		vars := reflect.ValueOf(mo.ModelValue.FieldByName(column.FieldName).Interface())
		if results.Kind() == reflect.Ptr {
			results.Set(reflect.Append(results, vars.Addr()))
		} else {
			results.Set(reflect.Append(results, vars))
		}
	}
	return interfaces
}
func (m TableModel) GetPrimary() interface{} {
	return m.ModelValue.FieldByName(m.Primary.FieldName).Interface()
}
func (m TableModel) GetPrimaryCondition() Condition {
	if IsEmpty(m.GetPrimary()) || m.Primary.IsPrimary == false {
		return nil
	} else {
		return Conditions{"`" + m.Primary.ColumnName + "` = ?", []interface{}{m.GetPrimary()}}
	}
}
<commit_msg>And sql拼写错误的bug修复<commit_after>package gom

import (
	"reflect"
)

type CreateSql func(TableModel) (string, []interface{})

type SqlGenerator struct {
	createSql   CreateSql
	tableModels []TableModel
}
type SqlFactory interface {
	Insert(TableModel) (string, []interface{})
	Update(TableModel) (string, []interface{})
	Replace(TableModel) (string, []interface{})
	Delete(TableModel) (string, []interface{})
	Query(TableModel) (string, []interface{})
}
type RowChooser interface {
	Scan(dest ...interface{}) error
}

type TableModel struct {
	ModelType  reflect.Type
	ModelValue reflect.Value
	TableName  string
	Columns    []Column
	Primary    Column
	Cnd        Condition
}
type Column struct {
	ColumnType reflect.Type
	ColumnName string
	FieldName  string
	IsPrimary  bool
	Auto       bool
}
type Condition interface {
	State() string
	Value() []interface{}
}
type Conditions struct {
	states string
	values []interface{}
}

func Cnd(sql string, values ...interface{}) Conditions {
	return Conditions{sql, values}
}
func (c Conditions) State() string {
	return c.states
}
func (c Conditions) Value() []interface{} {
	return c.values
}
func (c Conditions) And(sql string, values ...interface{}) Conditions {
	if c.states != "" {
		c.states += " and "
	}
	c.states += sql
	c.values = append(c.values, values)
	return c
}
func (c Conditions) Or(sql string, values ...interface{}) Conditions {
	if c.states != "" {
		c.states += " or "
	}
	c.states += sql
	c.values = append(c.values, values)
	return c
}
func (c Conditions) AndIn(name string, values ...interface{}) Conditions {
	if len(values) > 0 {
		if c.states != "" {
			c.states += " and "
		}
		sql := name + " in ("
		for i := 0; i < len(values); i++ {
			if i == 0 {
				sql += " ? "
			} else {
				sql += ", ? "
			}
		}
		sql += ")"
		c.states += sql
		c.values = append(c.values, values)
	}
	return c
}
func (c Conditions) OrIn(name string, values ...interface{}) Conditions {
	if len(values) > 0 {
		if c.states != "" {
			c.states += " or "
		}
		sql := name + " in ("
		for i := 0; i < len(values); i++ {
			if i == 0 {
				sql += " ? "
			} else {
				sql += ", ? "
			}
		}
		sql += ")"
		c.states += sql
		c.values = append(c.values, values)
	}
	return c
}
func (c Conditions) Sql(sql string, values ...interface{}) Conditions {
	c.states += sql
	c.values = append(c.values, values)
	return c
}

func (mo TableModel) InsertValues() []interface{} {
	var interfaces []interface{}
	results := reflect.Indirect(reflect.ValueOf(&interfaces))
	for _, column := range mo.Columns {
		vars := reflect.ValueOf(mo.ModelValue.FieldByName(column.FieldName).Interface())
		if results.Kind() == reflect.Ptr {
			results.Set(reflect.Append(results, vars.Addr()))
		} else {
			results.Set(reflect.Append(results, vars))
		}
	}
	return interfaces
}
func (m TableModel) GetPrimary() interface{} {
	return m.ModelValue.FieldByName(m.Primary.FieldName).Interface()
}
func (m TableModel) GetPrimaryCondition() Condition {
	if IsEmpty(m.GetPrimary()) || m.Primary.IsPrimary == false {
		return nil
	} else {
		return Conditions{"`" + m.Primary.ColumnName + "` = ?", []interface{}{m.GetPrimary()}}
	}
}
<|endoftext|>


<commit_before>package u

import (
	"bytes"
	"fmt"
	"os"
	"os/exec"
	"path/filepath"
)

var (
	ServerIPAddress  string
	IdentityFilePath string
)

func SshInteractive(user string) {
	panicIfServerInfoNotSet()
	cmd := exec.Command("ssh", "-i", IdentityFilePath, user)
	cmd.Stdin = os.Stdin
	RunCmdLoggedMust(cmd)
}

func LoginAsRoot() {
	user := fmt.Sprintf("root@%s", ServerIPAddress)
	SshInteractive(user)
}

// "-o StrictHostKeyChecking=no" is for the benefit of CI which start
// fresh environment
func ScpCopy(localSrcPath string, serverDstPath string) {
	panicIfServerInfoNotSet()
	cmd := exec.Command("scp", "-o", "StrictHostKeyChecking=no", "-i", IdentityFilePath, localSrcPath, serverDstPath)
	RunCmdLoggedMust(cmd)
}

// "-o StrictHostKeyChecking=no" is for the benefit of CI which start
// fresh environment
func SshExec(user string, script string) {
	panicIfServerInfoNotSet()
	cmd := exec.Command("ssh", "-o", "StrictHostKeyChecking=no", "-i", IdentityFilePath, user)
	r := bytes.NewBufferString(script)
	cmd.Stdin = r
	RunCmdLoggedMust(cmd)
}

func MakeExecScript(name string) string {
	script := fmt.Sprintf(`
chmod ug+x ./%s
./%s
rm ./%s
	`, name, name, name)
	return script
}

func panicIfServerInfoNotSet() {
	PanicIf(IdentityFilePath == "", "IdentityFilePath not set")
	PanicIf(!FileExists(IdentityFilePath), "IdentityFilePath '%s' doesn't exist", IdentityFilePath)
	PanicIf(ServerIPAddress == "", "ServerIPAddress not set")
}

// CopyAndExecServerScript copies a given script to the server and executes
// it under a given user name
func CopyAndExecServerScript(scriptLocalPath, user string) {
	panicIfServerInfoNotSet()
	PanicIf(!FileExists(scriptLocalPath), "script file '%s' doesn't exist", scriptLocalPath)

	serverAndUser := fmt.Sprintf("%s@%s", user, ServerIPAddress)
	scriptBaseName := filepath.Base(scriptLocalPath)
	scriptServerPath := "/root/" + scriptBaseName
	if user != "root" {
		scriptServerPath = "/home/" + user + "/" + scriptBaseName
	}
	{
		serverDstPath := fmt.Sprintf("%s:%s", serverAndUser, scriptServerPath)
		ScpCopy(scriptLocalPath, serverDstPath)
	}
	{
		script := MakeExecScript(scriptServerPath)
		SshExec(serverAndUser, script)
	}
}
<commit_msg>fix MakeExecScript()<commit_after>package u

import (
	"bytes"
	"fmt"
	"os"
	"os/exec"
	"path/filepath"
)

var (
	ServerIPAddress  string
	IdentityFilePath string
)

func SshInteractive(user string) {
	panicIfServerInfoNotSet()
	cmd := exec.Command("ssh", "-i", IdentityFilePath, user)
	cmd.Stdin = os.Stdin
	RunCmdLoggedMust(cmd)
}

func LoginAsRoot() {
	user := fmt.Sprintf("root@%s", ServerIPAddress)
	SshInteractive(user)
}

// "-o StrictHostKeyChecking=no" is for the benefit of CI which start
// fresh environment
func ScpCopy(localSrcPath string, serverDstPath string) {
	panicIfServerInfoNotSet()
	cmd := exec.Command("scp", "-o", "StrictHostKeyChecking=no", "-i", IdentityFilePath, localSrcPath, serverDstPath)
	RunCmdLoggedMust(cmd)
}

// "-o StrictHostKeyChecking=no" is for the benefit of CI which start
// fresh environment
func SshExec(user string, script string) {
	panicIfServerInfoNotSet()
	cmd := exec.Command("ssh", "-o", "StrictHostKeyChecking=no", "-i", IdentityFilePath, user)
	r := bytes.NewBufferString(script)
	cmd.Stdin = r
	RunCmdLoggedMust(cmd)
}

func MakeExecScript(name string) string {
	script := fmt.Sprintf(`
chmod ug+x %s
%s
rm %s
	`, name, name, name)
	return script
}

func panicIfServerInfoNotSet() {
	PanicIf(IdentityFilePath == "", "IdentityFilePath not set")
	PanicIf(!FileExists(IdentityFilePath), "IdentityFilePath '%s' doesn't exist", IdentityFilePath)
	PanicIf(ServerIPAddress == "", "ServerIPAddress not set")
}

// CopyAndExecServerScript copies a given script to the server and executes
// it under a given user name
func CopyAndExecServerScript(scriptLocalPath, user string) {
	panicIfServerInfoNotSet()
	PanicIf(!FileExists(scriptLocalPath), "script file '%s' doesn't exist", scriptLocalPath)

	serverAndUser := fmt.Sprintf("%s@%s", user, ServerIPAddress)
	scriptBaseName := filepath.Base(scriptLocalPath)
	scriptServerPath := "/root/" + scriptBaseName
	if user != "root" {
		scriptServerPath = "/home/" + user + "/" + scriptBaseName
	}
	{
		serverDstPath := fmt.Sprintf("%s:%s", serverAndUser, scriptServerPath)
		ScpCopy(scriptLocalPath, serverDstPath)
	}
	{
		script := MakeExecScript(scriptServerPath)
		SshExec(serverAndUser, script)
	}
}
<|endoftext|>


<commit_before>package main

import (
	"archive/tar"
	"bytes"
	"compress/gzip"
	"fmt"
	"github.com/bgentry/heroku-go"
	hk "github.com/heroku/hk/hkclient"
	// "io"
	"io/ioutil"
	"os"
	"path/filepath"
)

const (
	PLUGIN_NAME    = "deploy"
	PLUGIN_VERSION = 1
	// PLUGIN_USER_AGENT = "hk-" + PLUGIN_NAME "/1"
)

var client *heroku.Client
var nrc *hk.NetRc

func help() {}

func init() {
	nrc, err := hk.LoadNetRc()
	if err != nil && os.IsNotExist(err) {
		nrc = &hk.NetRc{}
	}

	clients, err := hk.New(nrc, "TODO user agent")

	if err == nil {
		client = clients.Client
	} else {
		// TODO
	}
}

func shouldIgnore(path string) bool {
	// TODO: gitignore-ish rules, if a .gitignore exists?
	return path == ".git"
}

func buildTgz(root string) bytes.Buffer {
	buf := new(bytes.Buffer)
	gz := gzip.NewWriter(buf)
	tw := tar.NewWriter(gz)

	filepath.Walk(root, func(path string, info os.FileInfo, err error) error {
		// TODO: handle incoming err more meaningfully
		if err != nil {
			fmt.Println(err.Error())
			return err
		}

		if shouldIgnore(path) {
			// FIXME path may not always be a dir here
			return filepath.SkipDir
		}

		if info.IsDir() {
			return nil
		}

		fmt.Printf("Adding %s (size: %d).\n", path, info.Size())
		hdr, err := tar.FileInfoHeader(info, path)
		if err != nil {
			fmt.Println(err.Error())
			return err
		}
		hdr.Name = path

		if err = tw.WriteHeader(hdr); err != nil {
			fmt.Println(err.Error())
			return err
		}

		body, err := ioutil.ReadFile(path)
		if err != nil {
			fmt.Println(err.Error())
			return err
		}

		if _, err = tw.Write(body); err != nil {
			fmt.Println(err.Error())
			return err
		}

		return nil
	})

	if err := tw.Close(); err != nil {
		fmt.Println(err.Error())
	}

	if err := gz.Close(); err != nil {
		fmt.Println(err.Error())
	}

	return *buf
}

func main() {
	if os.Getenv("HKPLUGINMODE") == "info" {
		help()
		os.Exit(0)
	}

	if len(os.Args) < 2 {
		help()
		os.Exit(1)
	}

	dir := os.Args[1] // TODO: Maybe fallback to CWD or Git root?
	tgz := buildTgz(dir)
	fmt.Printf("%v %d\n", tgz.Bytes(), tgz.Len())
	// fmt.Println(string(tgz.Bytes()))

	/*
		TODO:
			* Check that we have an APP context or set it
			* upload tgz to S3 with an object expiry of ~5min
			* hit build API with that link
			* tail output (if build api has implemented that)
	*/
}
<commit_msg>Replace TODOs with some stubs<commit_after>package main

import (
	"archive/tar"
	"bytes"
	"compress/gzip"
	"fmt"
	"github.com/bgentry/heroku-go"
	hk "github.com/heroku/hk/hkclient"
	// "io"
	"io/ioutil"
	"os"
	"path/filepath"
)

const (
	PLUGIN_NAME    = "deploy"
	PLUGIN_VERSION = 1
	// PLUGIN_USER_AGENT = "hk-" + PLUGIN_NAME "/1"
)

var client *heroku.Client
var nrc *hk.NetRc

func help() {}

func init() {
	nrc, err := hk.LoadNetRc()
	if err != nil && os.IsNotExist(err) {
		nrc = &hk.NetRc{}
	}

	clients, err := hk.New(nrc, "TODO user agent")

	if err == nil {
		client = clients.Client
	} else {
		// TODO
	}
}

func shouldIgnore(path string) bool {
	// TODO: gitignore-ish rules, if a .gitignore exists?
	return path == ".git"
}

func buildTgz(root string) bytes.Buffer {
	buf := new(bytes.Buffer)
	gz := gzip.NewWriter(buf)
	tw := tar.NewWriter(gz)

	filepath.Walk(root, func(path string, info os.FileInfo, err error) error {
		// TODO: handle incoming err more meaningfully
		if err != nil {
			fmt.Println(err.Error())
			return err
		}

		if shouldIgnore(path) {
			// FIXME path may not always be a dir here
			return filepath.SkipDir
		}

		if info.IsDir() {
			return nil
		}

		fmt.Printf("  Adding %s (%d bytes)\n", path, info.Size())

		hdr, err := tar.FileInfoHeader(info, path)
		if err != nil {
			fmt.Println(err.Error())
			return err
		}
		hdr.Name = path

		if err = tw.WriteHeader(hdr); err != nil {
			fmt.Println(err.Error())
			return err
		}

		body, err := ioutil.ReadFile(path)
		if err != nil {
			fmt.Println(err.Error())
			return err
		}

		if _, err = tw.Write(body); err != nil {
			fmt.Println(err.Error())
			return err
		}

		return nil
	})

	if err := tw.Close(); err != nil {
		fmt.Println(err.Error())
	}

	if err := gz.Close(); err != nil {
		fmt.Println(err.Error())
	}

	return *buf
}

func main() {
	if os.Getenv("HKPLUGINMODE") == "info" {
		help()
		os.Exit(0)
	}

	if len(os.Args) < 2 {
		help()
		os.Exit(1)
	}

	dir := os.Args[1] // TODO: Maybe fallback to CWD or Git root?

	fullPath, _ := filepath.Abs(dir)
	fmt.Printf("Creating .tgz of %s...\n", fullPath)
	tgz := buildTgz(dir)
	fmt.Printf("done (%d bytes)\n", tgz.Len())

	fmt.Println("Requesting upload slot... not implemented")
	fmt.Println("Requesting download link... not implemented")
	fmt.Println("Submitting build with download link... not implemented")
	fmt.Println("Commenting build... not implemented")
}
<|endoftext|>


<commit_before>/*
 Copyright 2015 Stack Inc.
 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 (
	"fmt"
	"github.com/micosa/stack/cli"
	"github.com/spf13/cobra"
	"log"
	"os"
	"strings"
)

var ExitOnFailure bool = false
var ExportAll bool = false
var ImportAll bool = false
var StackVersion string = "1.0"
var StackRepo *cli.Repo
var StackLogLevel string = ""

func StackUsage(cmd *cobra.Command, err error) {
	if err != nil {
		sErr := err.(*cli.StackError)
		log.Printf("[DEBUG] %s", sErr.StackTrace)

		fmt.Println("Error: ", sErr)
	}

	if cmd != nil {
		cmd.Usage()
	}
	os.Exit(1)
}

func targetSetCmd(cmd *cobra.Command, args []string) {
	if len(args) != 2 {
		StackUsage(cmd,
			cli.NewStackError("Must specify two arguments (sect & k=v) to set"))
	}

	t, err := cli.LoadTarget(StackRepo, args[0])
	if err != nil {
		StackUsage(cmd, err)
	}
	ar := strings.Split(args[1], "=")

	t.Vars[ar[0]] = ar[1]

	err = t.Save()
	if err != nil {
		StackUsage(cmd, err)
	}

	fmt.Printf("Target %s successfully set %s to %s\n", args[0],
		ar[0], ar[1])
}

func targetShowCmd(cmd *cobra.Command, args []string) {
	dispSect := ""
	if len(args) == 1 {
		dispSect = args[0]
	}

	targets, err := cli.GetTargets(StackRepo)
	if err != nil {
		StackUsage(cmd, err)
	}

	for _, target := range targets {
		if dispSect == "" || dispSect == target.Vars["name"] {
			fmt.Println(target.Vars["name"])
			vars := target.GetVars()
			for k, v := range vars {
				fmt.Printf("	%s: %s\n", k, v)
			}
		}
	}
}

func targetCreateCmd(cmd *cobra.Command, args []string) {
	if len(args) != 2 {
		StackUsage(cmd, cli.NewStackError("Wrong number of args to create cmd."))
	}

	fmt.Println("Creating target " + args[0])

	if cli.TargetExists(StackRepo, args[0]) {
		StackUsage(cmd, cli.NewStackError(
			"Target already exists, cannot create target with same name."))
	}

	target := &cli.Target{
		Repo: StackRepo,
		Vars: map[string]string{},
	}
	target.Vars["name"] = args[0]
	target.Vars["arch"] = args[1]

	err := target.Save()
	if err != nil {
		fmt.Println(err)
	} else {
		fmt.Printf("Target %s sucessfully created!\n", args[0])
	}
}

func targetBuildCmd(cmd *cobra.Command, args []string) {
	if len(args) < 1 {
		StackUsage(cmd, cli.NewStackError("Must specify target to build"))
	}

	t, err := cli.LoadTarget(StackRepo, args[0])
	if err != nil {
		StackUsage(cmd, err)
	}

	if len(args) > 1 && args[1] == "clean" {
		if len(args) > 2 && args[2] == "all" {
			err = t.BuildClean(true)
		} else {
			err = t.BuildClean(false)
		}
	} else {
		err = t.Build()
	}

	if err != nil {
		StackUsage(cmd, err)
	} else {
		fmt.Println("Successfully run!")
	}
}

func targetDelCmd(cmd *cobra.Command, args []string) {
	if len(args) < 1 {
		StackUsage(cmd, cli.NewStackError("Must specify target to delete"))
	}

	t, err := cli.LoadTarget(StackRepo, args[0])
	if err != nil {
		StackUsage(cmd, err)
	}

	if err := t.Remove(); err != nil {
		StackUsage(cmd, err)
	}

	fmt.Printf("Target %s successfully removed\n", args[0])
}

func targetTestCmd(cmd *cobra.Command, args []string) {
	if len(args) < 1 {
		StackUsage(cmd, cli.NewStackError("Must specify target to build"))
	}

	t, err := cli.LoadTarget(StackRepo, args[0])
	if err != nil {
		StackUsage(cmd, err)
	}

	if len(args) > 1 && args[1] == "clean" {
		if len(args) > 2 && args[2] == "all" {
			err = t.Test("testclean", true)
		} else {
			err = t.Test("testclean", false)
		}
	} else {
		err = t.Test("test", ExitOnFailure)
	}

	if err != nil {
		StackUsage(cmd, err)
	} else {
		fmt.Println("Successfully run!")
	}
}

func targetExportCmd(cmd *cobra.Command, args []string) {
	var targetName string
	if ExportAll {
		targetName = ""
	} else {
		if len(args) < 1 {
			StackUsage(cmd, cli.NewStackError("Must either specify -a flag or name of target to export"))
		}
		targetName = args[0]
	}

	err := cli.ExportTargets(StackRepo, targetName, ExportAll, os.Stdout)
	if err != nil {
		StackUsage(cmd, err)
	}
}

func targetImportCmd(cmd *cobra.Command, args []string) {
	var targetName string
	if ImportAll {
		targetName = ""
	} else {
		if len(args) < 1 {
			StackUsage(cmd, cli.NewStackError("Must either specify -a flag or name of target to import"))
		}

		targetName = args[0]
	}

	err := cli.ImportTargets(StackRepo, targetName, ImportAll, os.Stdin)
	if err != nil {
		StackUsage(cmd, err)
	}

	fmt.Println("Target(s) successfully imported!")
}

func targetAddCmds(base *cobra.Command) {
	targetCmd := &cobra.Command{
		Use:   "target",
		Short: "Set and view target information",
		PersistentPreRun: func(cmd *cobra.Command, args []string) {
			cli.Init(StackLogLevel)

			var err error
			StackRepo, err = cli.NewRepo()
			if err != nil {
				StackUsage(nil, err)
			}
		},
		Run: func(cmd *cobra.Command, args []string) {
			cmd.Usage()
		},
	}

	setCmd := &cobra.Command{
		Use:   "set",
		Short: "Set target configuration variable",
		Run:   targetSetCmd,
	}

	targetCmd.AddCommand(setCmd)

	delCmd := &cobra.Command{
		Use:   "delete",
		Short: "Delete target",
		Run:   targetDelCmd,
	}

	targetCmd.AddCommand(delCmd)

	createCmd := &cobra.Command{
		Use:   "create",
		Short: "Create a target",
		Run:   targetCreateCmd,
	}

	targetCmd.AddCommand(createCmd)

	showCmd := &cobra.Command{
		Use:   "show",
		Short: "View target configuration variables",
		Run:   targetShowCmd,
	}

	targetCmd.AddCommand(showCmd)

	buildCmd := &cobra.Command{
		Use:   "build",
		Short: "Build target",
		Run:   targetBuildCmd,
	}

	targetCmd.AddCommand(buildCmd)

	testCmd := &cobra.Command{
		Use:   "test",
		Short: "Test target",
		Run:   targetTestCmd,
	}

	targetCmd.AddCommand(testCmd)

	exportCmd := &cobra.Command{
		Use:   "export",
		Short: "Export target",
		Run:   targetExportCmd,
	}

	exportCmd.PersistentFlags().BoolVarP(&ExportAll, "export-all", "a", false,
		"If present, export all targets")

	targetCmd.AddCommand(exportCmd)

	importCmd := &cobra.Command{
		Use:   "import",
		Short: "Import target",
		Run:   targetImportCmd,
	}

	importCmd.PersistentFlags().BoolVarP(&ImportAll, "import-all", "a", false,
		"If present, import all targets")

	targetCmd.AddCommand(importCmd)

	base.AddCommand(targetCmd)
}

func repoCreateCmd(cmd *cobra.Command, args []string) {
	// must specify a repo name to create
	if len(args) != 1 {
		StackUsage(cmd, cli.NewStackError("Must specify a repo name to repo create"))
	}

	cwd, err := os.Getwd()
	if err != nil {
		StackUsage(cmd, err)
	}

	_, err = cli.CreateRepo(cwd, args[0])
	if err != nil {
		StackUsage(cmd, err)
	}

	fmt.Println("Repo " + args[0] + " successfully created!")
}

func repoAddCmds(baseCmd *cobra.Command) {
	repoCmd := &cobra.Command{
		Use:   "repo",
		Short: "Commands to manipulate the base repository",
		Run: func(cmd *cobra.Command, args []string) {
			cmd.Usage()
		},
	}

	createCmd := &cobra.Command{
		Use:   "create",
		Short: "Create a repository",
		Run:   repoCreateCmd,
	}

	repoCmd.AddCommand(createCmd)

	baseCmd.AddCommand(repoCmd)
}

func compilerCreateCmd(cmd *cobra.Command, args []string) {
	// must specify a compiler name to compiler create
	if len(args) != 1 {
		StackUsage(cmd, cli.NewStackError("Must specify a compiler name to compiler create"))
	}

	err := StackRepo.CreateCompiler(args[0])
	if err != nil {
		StackUsage(cmd, err)
	}

	fmt.Println("Compiler " + args[0] + " successfully created!")
}

func compilerInstallCmd(cmd *cobra.Command, args []string) {
	if len(args) < 1 {
		StackUsage(cmd, cli.NewStackError("Need to specify URL to install compiler "+
			"def from"))
	}

	var name string
	var err error

	if len(args) > 1 {
		name = args[1]
	} else {
		name, err = cli.UrlPath(args[0])
		if err != nil {
			StackUsage(cmd, err)
		}
	}

	dirName := StackRepo.BasePath + "/compiler/" + name + "/"
	if cli.NodeExist(dirName) {
		StackUsage(cmd, cli.NewStackError("Compiler "+name+" already installed."))
	}

	err = cli.CopyUrl(args[0], dirName)
	if err != nil {
		StackUsage(cmd, err)
	}

	fmt.Println("Compiler " + name + " successfully installed.")
}

func compilerAddCmds(baseCmd *cobra.Command) {
	compilerCmd := &cobra.Command{
		Use:   "compiler",
		Short: "Commands to install and create compiler definitions",
		PersistentPreRun: func(cmd *cobra.Command, args []string) {
			cli.Init(StackLogLevel)

			var err error
			StackRepo, err = cli.NewRepo()
			if err != nil {
				StackUsage(nil, err)
			}
		},
		Run: func(cmd *cobra.Command, args []string) {
			cmd.Usage()
		},
	}

	createCmd := &cobra.Command{
		Use:   "create",
		Short: "Create a new compiler definition",
		Run:   compilerCreateCmd,
	}

	compilerCmd.AddCommand(createCmd)

	installCmd := &cobra.Command{
		Use:   "install",
		Short: "Install a compiler from the specified URL",
		Run:   compilerInstallCmd,
	}

	compilerCmd.AddCommand(installCmd)

	baseCmd.AddCommand(compilerCmd)
}

func parseCmds() *cobra.Command {
	stackCmd := &cobra.Command{
		Use:   "stack",
		Short: "Stack is a tool to help you compose and build your own OS",
		Long: `Stack allows you to create your own embedded project based on the
		     stack operating system`,
		PersistentPreRun: func(cmd *cobra.Command, args []string) {
			cli.Init(StackLogLevel)
		},
		Run: func(cmd *cobra.Command, args []string) {
			cmd.Usage()
		},
	}

	stackCmd.PersistentFlags().StringVarP(&StackLogLevel, "loglevel", "l",
		"WARN", "Log level, defaults to WARN.")

	versCmd := &cobra.Command{
		Use:   "version",
		Short: "Print the stack version number",
		Run: func(cmd *cobra.Command, args []string) {
			fmt.Println("Stack version: ", StackVersion)
		},
	}

	stackCmd.AddCommand(versCmd)

	targetAddCmds(stackCmd)
	repoAddCmds(stackCmd)
	compilerAddCmds(stackCmd)

	return stackCmd
}

func main() {
	cmd := parseCmds()
	cmd.Execute()
}
<commit_msg>only display stack trace when -lDEBUG is present<commit_after>/*
 Copyright 2015 Stack Inc.
 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 (
	"fmt"
	"github.com/micosa/stack/cli"
	"github.com/spf13/cobra"
	"log"
	"os"
	"strings"
)

var ExitOnFailure bool = false
var ExportAll bool = false
var ImportAll bool = false
var StackVersion string = "1.0"
var StackRepo *cli.Repo
var StackLogLevel string = ""

func StackUsage(cmd *cobra.Command, err error) {
	if err != nil {
		sErr := err.(*cli.StackError)
		log.Printf("[DEBUG] %s", sErr.StackTrace)

		fmt.Println("Error: ", sErr.Text)
	}

	if cmd != nil {
		cmd.Usage()
	}
	os.Exit(1)
}

func targetSetCmd(cmd *cobra.Command, args []string) {
	if len(args) != 2 {
		StackUsage(cmd,
			cli.NewStackError("Must specify two arguments (sect & k=v) to set"))
	}

	t, err := cli.LoadTarget(StackRepo, args[0])
	if err != nil {
		StackUsage(cmd, err)
	}
	ar := strings.Split(args[1], "=")

	t.Vars[ar[0]] = ar[1]

	err = t.Save()
	if err != nil {
		StackUsage(cmd, err)
	}

	fmt.Printf("Target %s successfully set %s to %s\n", args[0],
		ar[0], ar[1])
}

func targetShowCmd(cmd *cobra.Command, args []string) {
	dispSect := ""
	if len(args) == 1 {
		dispSect = args[0]
	}

	targets, err := cli.GetTargets(StackRepo)
	if err != nil {
		StackUsage(cmd, err)
	}

	for _, target := range targets {
		if dispSect == "" || dispSect == target.Vars["name"] {
			fmt.Println(target.Vars["name"])
			vars := target.GetVars()
			for k, v := range vars {
				fmt.Printf("	%s: %s\n", k, v)
			}
		}
	}
}

func targetCreateCmd(cmd *cobra.Command, args []string) {
	if len(args) != 2 {
		StackUsage(cmd, cli.NewStackError("Wrong number of args to create cmd."))
	}

	fmt.Println("Creating target " + args[0])

	if cli.TargetExists(StackRepo, args[0]) {
		StackUsage(cmd, cli.NewStackError(
			"Target already exists, cannot create target with same name."))
	}

	target := &cli.Target{
		Repo: StackRepo,
		Vars: map[string]string{},
	}
	target.Vars["name"] = args[0]
	target.Vars["arch"] = args[1]

	err := target.Save()
	if err != nil {
		fmt.Println(err)
	} else {
		fmt.Printf("Target %s sucessfully created!\n", args[0])
	}
}

func targetBuildCmd(cmd *cobra.Command, args []string) {
	if len(args) < 1 {
		StackUsage(cmd, cli.NewStackError("Must specify target to build"))
	}

	t, err := cli.LoadTarget(StackRepo, args[0])
	if err != nil {
		StackUsage(cmd, err)
	}

	if len(args) > 1 && args[1] == "clean" {
		if len(args) > 2 && args[2] == "all" {
			err = t.BuildClean(true)
		} else {
			err = t.BuildClean(false)
		}
	} else {
		err = t.Build()
	}

	if err != nil {
		StackUsage(cmd, err)
	} else {
		fmt.Println("Successfully run!")
	}
}

func targetDelCmd(cmd *cobra.Command, args []string) {
	if len(args) < 1 {
		StackUsage(cmd, cli.NewStackError("Must specify target to delete"))
	}

	t, err := cli.LoadTarget(StackRepo, args[0])
	if err != nil {
		StackUsage(cmd, err)
	}

	if err := t.Remove(); err != nil {
		StackUsage(cmd, err)
	}

	fmt.Printf("Target %s successfully removed\n", args[0])
}

func targetTestCmd(cmd *cobra.Command, args []string) {
	if len(args) < 1 {
		StackUsage(cmd, cli.NewStackError("Must specify target to build"))
	}

	t, err := cli.LoadTarget(StackRepo, args[0])
	if err != nil {
		StackUsage(cmd, err)
	}

	if len(args) > 1 && args[1] == "clean" {
		if len(args) > 2 && args[2] == "all" {
			err = t.Test("testclean", true)
		} else {
			err = t.Test("testclean", false)
		}
	} else {
		err = t.Test("test", ExitOnFailure)
	}

	if err != nil {
		StackUsage(cmd, err)
	} else {
		fmt.Println("Successfully run!")
	}
}

func targetExportCmd(cmd *cobra.Command, args []string) {
	var targetName string
	if ExportAll {
		targetName = ""
	} else {
		if len(args) < 1 {
			StackUsage(cmd, cli.NewStackError("Must either specify -a flag or name of target to export"))
		}
		targetName = args[0]
	}

	err := cli.ExportTargets(StackRepo, targetName, ExportAll, os.Stdout)
	if err != nil {
		StackUsage(cmd, err)
	}
}

func targetImportCmd(cmd *cobra.Command, args []string) {
	var targetName string
	if ImportAll {
		targetName = ""
	} else {
		if len(args) < 1 {
			StackUsage(cmd, cli.NewStackError("Must either specify -a flag or name of target to import"))
		}

		targetName = args[0]
	}

	err := cli.ImportTargets(StackRepo, targetName, ImportAll, os.Stdin)
	if err != nil {
		StackUsage(cmd, err)
	}

	fmt.Println("Target(s) successfully imported!")
}

func targetAddCmds(base *cobra.Command) {
	targetCmd := &cobra.Command{
		Use:   "target",
		Short: "Set and view target information",
		PersistentPreRun: func(cmd *cobra.Command, args []string) {
			cli.Init(StackLogLevel)

			var err error
			StackRepo, err = cli.NewRepo()
			if err != nil {
				StackUsage(nil, err)
			}
		},
		Run: func(cmd *cobra.Command, args []string) {
			cmd.Usage()
		},
	}

	setCmd := &cobra.Command{
		Use:   "set",
		Short: "Set target configuration variable",
		Run:   targetSetCmd,
	}

	targetCmd.AddCommand(setCmd)

	delCmd := &cobra.Command{
		Use:   "delete",
		Short: "Delete target",
		Run:   targetDelCmd,
	}

	targetCmd.AddCommand(delCmd)

	createCmd := &cobra.Command{
		Use:   "create",
		Short: "Create a target",
		Run:   targetCreateCmd,
	}

	targetCmd.AddCommand(createCmd)

	showCmd := &cobra.Command{
		Use:   "show",
		Short: "View target configuration variables",
		Run:   targetShowCmd,
	}

	targetCmd.AddCommand(showCmd)

	buildCmd := &cobra.Command{
		Use:   "build",
		Short: "Build target",
		Run:   targetBuildCmd,
	}

	targetCmd.AddCommand(buildCmd)

	testCmd := &cobra.Command{
		Use:   "test",
		Short: "Test target",
		Run:   targetTestCmd,
	}

	targetCmd.AddCommand(testCmd)

	exportCmd := &cobra.Command{
		Use:   "export",
		Short: "Export target",
		Run:   targetExportCmd,
	}

	exportCmd.PersistentFlags().BoolVarP(&ExportAll, "export-all", "a", false,
		"If present, export all targets")

	targetCmd.AddCommand(exportCmd)

	importCmd := &cobra.Command{
		Use:   "import",
		Short: "Import target",
		Run:   targetImportCmd,
	}

	importCmd.PersistentFlags().BoolVarP(&ImportAll, "import-all", "a", false,
		"If present, import all targets")

	targetCmd.AddCommand(importCmd)

	base.AddCommand(targetCmd)
}

func repoCreateCmd(cmd *cobra.Command, args []string) {
	// must specify a repo name to create
	if len(args) != 1 {
		StackUsage(cmd, cli.NewStackError("Must specify a repo name to repo create"))
	}

	cwd, err := os.Getwd()
	if err != nil {
		StackUsage(cmd, err)
	}

	_, err = cli.CreateRepo(cwd, args[0])
	if err != nil {
		StackUsage(cmd, err)
	}

	fmt.Println("Repo " + args[0] + " successfully created!")
}

func repoAddCmds(baseCmd *cobra.Command) {
	repoCmd := &cobra.Command{
		Use:   "repo",
		Short: "Commands to manipulate the base repository",
		Run: func(cmd *cobra.Command, args []string) {
			cmd.Usage()
		},
	}

	createCmd := &cobra.Command{
		Use:   "create",
		Short: "Create a repository",
		Run:   repoCreateCmd,
	}

	repoCmd.AddCommand(createCmd)

	baseCmd.AddCommand(repoCmd)
}

func compilerCreateCmd(cmd *cobra.Command, args []string) {
	// must specify a compiler name to compiler create
	if len(args) != 1 {
		StackUsage(cmd, cli.NewStackError("Must specify a compiler name to compiler create"))
	}

	err := StackRepo.CreateCompiler(args[0])
	if err != nil {
		StackUsage(cmd, err)
	}

	fmt.Println("Compiler " + args[0] + " successfully created!")
}

func compilerInstallCmd(cmd *cobra.Command, args []string) {
	if len(args) < 1 {
		StackUsage(cmd, cli.NewStackError("Need to specify URL to install compiler "+
			"def from"))
	}

	var name string
	var err error

	if len(args) > 1 {
		name = args[1]
	} else {
		name, err = cli.UrlPath(args[0])
		if err != nil {
			StackUsage(cmd, err)
		}
	}

	dirName := StackRepo.BasePath + "/compiler/" + name + "/"
	if cli.NodeExist(dirName) {
		StackUsage(cmd, cli.NewStackError("Compiler "+name+" already installed."))
	}

	err = cli.CopyUrl(args[0], dirName)
	if err != nil {
		StackUsage(cmd, err)
	}

	fmt.Println("Compiler " + name + " successfully installed.")
}

func compilerAddCmds(baseCmd *cobra.Command) {
	compilerCmd := &cobra.Command{
		Use:   "compiler",
		Short: "Commands to install and create compiler definitions",
		PersistentPreRun: func(cmd *cobra.Command, args []string) {
			cli.Init(StackLogLevel)

			var err error
			StackRepo, err = cli.NewRepo()
			if err != nil {
				StackUsage(nil, err)
			}
		},
		Run: func(cmd *cobra.Command, args []string) {
			cmd.Usage()
		},
	}

	createCmd := &cobra.Command{
		Use:   "create",
		Short: "Create a new compiler definition",
		Run:   compilerCreateCmd,
	}

	compilerCmd.AddCommand(createCmd)

	installCmd := &cobra.Command{
		Use:   "install",
		Short: "Install a compiler from the specified URL",
		Run:   compilerInstallCmd,
	}

	compilerCmd.AddCommand(installCmd)

	baseCmd.AddCommand(compilerCmd)
}

func parseCmds() *cobra.Command {
	stackCmd := &cobra.Command{
		Use:   "stack",
		Short: "Stack is a tool to help you compose and build your own OS",
		Long: `Stack allows you to create your own embedded project based on the
		     stack operating system`,
		PersistentPreRun: func(cmd *cobra.Command, args []string) {
			cli.Init(StackLogLevel)
		},
		Run: func(cmd *cobra.Command, args []string) {
			cmd.Usage()
		},
	}

	stackCmd.PersistentFlags().StringVarP(&StackLogLevel, "loglevel", "l",
		"WARN", "Log level, defaults to WARN.")

	versCmd := &cobra.Command{
		Use:   "version",
		Short: "Print the stack version number",
		Run: func(cmd *cobra.Command, args []string) {
			fmt.Println("Stack version: ", StackVersion)
		},
	}

	stackCmd.AddCommand(versCmd)

	targetAddCmds(stackCmd)
	repoAddCmds(stackCmd)
	compilerAddCmds(stackCmd)

	return stackCmd
}

func main() {
	cmd := parseCmds()
	cmd.Execute()
}
<|endoftext|>


<commit_before>package utils

import (
	"bytes"
	"encoding/json"
	"errors"
	"fmt"
	"net"
	"regexp"
	"sort"
	"strconv"
	"strings"

	log "github.com/Sirupsen/logrus"
)

func IpFromInterfaces(raw json.RawMessage) (string, error) {
	interfaces, ifaceErr := ParseInterfaces(raw)
	if ifaceErr != nil {
		return "", ifaceErr
	}

	if ipAddress, err := GetIP(interfaces); err != nil {
		return "", err
	} else {
		return ipAddress, nil
	}
}

func ParseInterfaces(raw json.RawMessage) ([]string, error) {
	if raw == nil {
		return []string{}, nil
	}
	// Parse as a string
	var jsonString string
	if err := json.Unmarshal(raw, &jsonString); err == nil {
		return []string{jsonString}, nil
	}

	var jsonArray []string
	if err := json.Unmarshal(raw, &jsonArray); err == nil {
		return jsonArray, nil
	}

	return []string{}, errors.New("interfaces must be a string or an array")
}

// GetIP determines the IP address of the container
func GetIP(specList []string) (string, error) {

	if specList == nil || len(specList) == 0 {
		// Use a sane default
		specList = []string{"eth0:inet"}
	}

	specs, err := parseInterfaceSpecs(specList)
	if err != nil {
		return "", err
	}

	interfaces, interfacesErr := net.Interfaces()

	if interfacesErr != nil {
		return "", interfacesErr
	}

	interfaceIPs, interfaceIPsErr := getinterfaceIPs(interfaces)

	/* We had an error and there were no interfaces returned, this is clearly
	 * an error state. */
	if interfaceIPsErr != nil && len(interfaceIPs) < 1 {
		return "", interfaceIPsErr
	}
	/* We had error(s) and there were interfaces returned, this is potentially
	 * recoverable. Let's pass on the parsed interfaces and log the error
	 * state. */
	if interfaceIPsErr != nil && len(interfaceIPs) > 0 {
		log.Warnf("We had a problem reading information about some network "+
			"interfaces. If everything works, it is safe to ignore this "+
			"message. Details:\n%s\n", interfaceIPsErr)
	}

	return findIPWithSpecs(specs, interfaceIPs)
}

// findIPWithSpecs will use the given interface specification list and will
// find the first IP in the interfaceIPs that matches a spec
func findIPWithSpecs(specs []interfaceSpec, interfaceIPs []interfaceIP) (string, error) {
	// Find the interface matching the name given
	for _, spec := range specs {
		// Static IP given
		origSpec, ok := spec.(staticInterfaceSpec)
		if ok {
			return origSpec.IP.String(), nil
		}
		index := 0
		iface := ""
		for _, iip := range interfaceIPs {
			// Since the interfaces are ordered by name
			// a change in interface name can safely reset the index
			if iface != iip.Name {
				index = 0
				iface = iip.Name
			} else {
				index++
			}
			if spec.Match(index, iip) {
				return iip.IPString(), nil
			}
		}
	}

	// Interface not found, return error
	return "", fmt.Errorf("None of the interface specifications were able to match\nSpecifications: %s\nInterfaces IPs: %s",
		specs, interfaceIPs)
}

// Interface Spec
type interfaceSpec interface {
	Match(index int, iip interfaceIP) bool
}

// -- matches inet, inet6, interface:inet, and interface:inet6
type inetInterfaceSpec struct {
	Spec string
	Name string
	IPv6 bool
}

// -- matches static
type staticInterfaceSpec struct {
	Spec string
	Name string
	IP net.IP
}

func (s staticInterfaceSpec) Match(index int, iip interfaceIP) bool {
	// Never matches
	return false
}

func (s inetInterfaceSpec) Match(index int, iip interfaceIP) bool {
	if s.Name != "*" && s.Name != iip.Name {
		return false
	}
	// Don't match loopback address for wildcard spec
	if s.Name == "*" && iip.IP.IsLoopback() {
		return false
	}
	return s.IPv6 != iip.IsIPv4()
}

// -- Indexed Interface Spec : eth0[1]
type indexInterfaceSpec struct {
	Spec  string
	Name  string
	Index int
}

func (spec indexInterfaceSpec) Match(index int, iip interfaceIP) bool {
	if spec.Name == iip.Name {
		return (spec.Index == index)
	}
	return false
}

// -- CIDR Interface Spec
type cidrInterfaceSpec struct {
	Spec    string
	Network *net.IPNet
}

func (spec cidrInterfaceSpec) Match(index int, iip interfaceIP) bool {
	return spec.Network.Contains(iip.IP)
}

func parseInterfaceSpecs(interfaces []string) ([]interfaceSpec, error) {
	var errors []string
	var specs []interfaceSpec
	for _, iface := range interfaces {
		spec, err := parseInterfaceSpec(iface)
		if err != nil {
			errors = append(errors, err.Error())
			continue
		}
		specs = append(specs, spec)
	}
	if len(errors) > 0 {
		err := fmt.Errorf(strings.Join(errors, "\n"))
		log.Errorln(err)
		return specs, err
	}
	return specs, nil
}

var (
	ifaceSpec = regexp.MustCompile(`^(?P<Name>\w+)(?:(?:\[(?P<Index>\d+)\])|(?::(?P<Version>inet6?)))?$`)
)

func parseInterfaceSpec(spec string) (interfaceSpec, error) {
	if spec == "inet" {
		return inetInterfaceSpec{Spec: spec, Name: "*", IPv6: false}, nil
	}
	if spec == "inet6" {
		return inetInterfaceSpec{Spec: spec, Name: "*", IPv6: true}, nil
	}
	if strings.HasPrefix(spec, "static:") {
		ip := strings.SplitAfter(spec, "static:")
		nip := net.ParseIP(ip[1])
		if nip == nil {
			return nil, fmt.Errorf("Unable to parse static ip %s in %s", ip[0], spec)
		}
		return staticInterfaceSpec{Spec: spec, Name: "static", IP: nip}, nil
	}

	if match := ifaceSpec.FindStringSubmatch(spec); match != nil {
		name := match[1]
		index := match[2]
		inet := match[3]
		if index != "" {
			i, err := strconv.Atoi(index)
			if err != nil {
				return nil, fmt.Errorf("Unable to parse index %s in %s", index, spec)
			}
			return indexInterfaceSpec{Spec: spec, Name: name, Index: i}, nil
		}
		if inet != "" {
			if inet == "inet" {
				return inetInterfaceSpec{Spec: spec, Name: name, IPv6: false}, nil
			}
			return inetInterfaceSpec{Spec: spec, Name: name, IPv6: true}, nil
		}
		return inetInterfaceSpec{Spec: spec, Name: name, IPv6: false}, nil
	}
	if _, net, err := net.ParseCIDR(spec); err == nil {
		return cidrInterfaceSpec{Spec: spec, Network: net}, nil
	}
	return nil, fmt.Errorf("Unable to parse interface spec: %s", spec)
}

type interfaceIP struct {
	Name string
	IP   net.IP
}

func (iip interfaceIP) To16() net.IP {
	return iip.IP.To16()
}

func (iip interfaceIP) To4() net.IP {
	return iip.IP.To4()
}

func (iip interfaceIP) IsIPv4() bool {
	return iip.To4() != nil
}

func (iip interfaceIP) IPString() string {
	if v4 := iip.To4(); v4 != nil {
		return v4.String()
	}
	return iip.IP.String()
}

func (iip interfaceIP) String() string {
	return fmt.Sprintf("%s:%s", iip.Name, iip.IPString())
}

// Queries the network interfaces on the running machine and returns a list
// of IPs for each interface.
func getinterfaceIPs(interfaces []net.Interface) ([]interfaceIP, error) {
	var ifaceIPs []interfaceIP
	var errors []string

	for _, intf := range interfaces {
		ipAddrs, addrErr := intf.Addrs()

		if addrErr != nil {
			errors = append(errors, addrErr.Error())
			continue
		}

		for _, ipAddr := range ipAddrs {
			// Addresses some times come in the form "192.168.100.1/24 2001:DB8::/48"
			// so they must be split on whitespace
			for _, splitIP := range strings.Split(ipAddr.String(), " ") {
				ip, _, err := net.ParseCIDR(splitIP)
				if err != nil {
					errors = append(errors, err.Error())
					continue
				}
				intfIP := interfaceIP{Name: intf.Name, IP: ip}
				ifaceIPs = append(ifaceIPs, intfIP)
			}
		}
	}

	// Stable Sort the interface IPs so that selecting the correct IP in GetIP
	// can be consistent
	sort.Stable(ByInterfaceThenIP(ifaceIPs))

	/* If we had any errors parsing interfaces, we accumulate them all and
	 * then return them so that the caller can decide what they want to do. */
	if len(errors) > 0 {
		err := fmt.Errorf(strings.Join(errors, "\n"))
		log.Errorln(err)
		return ifaceIPs, err
	}

	return ifaceIPs, nil
}

// ByInterfaceThenIP implements the Sort with the following properties:
// 1. Sort interfaces alphabetically
// 2. Sort IPs by bytes (normalized to 16 byte form)
type ByInterfaceThenIP []interfaceIP

func (se ByInterfaceThenIP) Len() int      { return len(se) }
func (se ByInterfaceThenIP) Swap(i, j int) { se[i], se[j] = se[j], se[i] }
func (se ByInterfaceThenIP) Less(i, j int) bool {
	iip1, iip2 := se[i], se[j]
	if cmp := strings.Compare(iip1.Name, iip2.Name); cmp != 0 {
		return cmp < 0
	}
	return bytes.Compare(iip1.To16(), iip2.To16()) < 0
}
<commit_msg>consider static:[0-9]+ alias interfaces<commit_after>package utils

import (
	"bytes"
	"encoding/json"
	"errors"
	"fmt"
	"net"
	"regexp"
	"sort"
	"strconv"
	"strings"

	log "github.com/Sirupsen/logrus"
)

func IpFromInterfaces(raw json.RawMessage) (string, error) {
	interfaces, ifaceErr := ParseInterfaces(raw)
	if ifaceErr != nil {
		return "", ifaceErr
	}

	if ipAddress, err := GetIP(interfaces); err != nil {
		return "", err
	} else {
		return ipAddress, nil
	}
}

func ParseInterfaces(raw json.RawMessage) ([]string, error) {
	if raw == nil {
		return []string{}, nil
	}
	// Parse as a string
	var jsonString string
	if err := json.Unmarshal(raw, &jsonString); err == nil {
		return []string{jsonString}, nil
	}

	var jsonArray []string
	if err := json.Unmarshal(raw, &jsonArray); err == nil {
		return jsonArray, nil
	}

	return []string{}, errors.New("interfaces must be a string or an array")
}

// GetIP determines the IP address of the container
func GetIP(specList []string) (string, error) {

	if specList == nil || len(specList) == 0 {
		// Use a sane default
		specList = []string{"eth0:inet"}
	}

	specs, err := parseInterfaceSpecs(specList)
	if err != nil {
		return "", err
	}

	interfaces, interfacesErr := net.Interfaces()

	if interfacesErr != nil {
		return "", interfacesErr
	}

	interfaceIPs, interfaceIPsErr := getinterfaceIPs(interfaces)

	/* We had an error and there were no interfaces returned, this is clearly
	 * an error state. */
	if interfaceIPsErr != nil && len(interfaceIPs) < 1 {
		return "", interfaceIPsErr
	}
	/* We had error(s) and there were interfaces returned, this is potentially
	 * recoverable. Let's pass on the parsed interfaces and log the error
	 * state. */
	if interfaceIPsErr != nil && len(interfaceIPs) > 0 {
		log.Warnf("We had a problem reading information about some network "+
			"interfaces. If everything works, it is safe to ignore this "+
			"message. Details:\n%s\n", interfaceIPsErr)
	}

	return findIPWithSpecs(specs, interfaceIPs)
}

// findIPWithSpecs will use the given interface specification list and will
// find the first IP in the interfaceIPs that matches a spec
func findIPWithSpecs(specs []interfaceSpec, interfaceIPs []interfaceIP) (string, error) {
	// Find the interface matching the name given
	for _, spec := range specs {
		// Static IP given
		origSpec, ok := spec.(staticInterfaceSpec)
		if ok {
			return origSpec.IP.String(), nil
		}
		index := 0
		iface := ""
		for _, iip := range interfaceIPs {
			// Since the interfaces are ordered by name
			// a change in interface name can safely reset the index
			if iface != iip.Name {
				index = 0
				iface = iip.Name
			} else {
				index++
			}
			if spec.Match(index, iip) {
				return iip.IPString(), nil
			}
		}
	}

	// Interface not found, return error
	return "", fmt.Errorf("None of the interface specifications were able to match\nSpecifications: %s\nInterfaces IPs: %s",
		specs, interfaceIPs)
}

// Interface Spec
type interfaceSpec interface {
	Match(index int, iip interfaceIP) bool
}

// -- matches inet, inet6, interface:inet, and interface:inet6
type inetInterfaceSpec struct {
	Spec string
	Name string
	IPv6 bool
}

// -- matches static
type staticInterfaceSpec struct {
	Spec string
	Name string
	IP net.IP
}

func (s staticInterfaceSpec) Match(index int, iip interfaceIP) bool {
	// Never matches
	return false
}

func (s inetInterfaceSpec) Match(index int, iip interfaceIP) bool {
	if s.Name != "*" && s.Name != iip.Name {
		return false
	}
	// Don't match loopback address for wildcard spec
	if s.Name == "*" && iip.IP.IsLoopback() {
		return false
	}
	return s.IPv6 != iip.IsIPv4()
}

// -- Indexed Interface Spec : eth0[1]
type indexInterfaceSpec struct {
	Spec  string
	Name  string
	Index int
}

func (spec indexInterfaceSpec) Match(index int, iip interfaceIP) bool {
	if spec.Name == iip.Name {
		return (spec.Index == index)
	}
	return false
}

// -- CIDR Interface Spec
type cidrInterfaceSpec struct {
	Spec    string
	Network *net.IPNet
}

func (spec cidrInterfaceSpec) Match(index int, iip interfaceIP) bool {
	return spec.Network.Contains(iip.IP)
}

func parseInterfaceSpecs(interfaces []string) ([]interfaceSpec, error) {
	var errors []string
	var specs []interfaceSpec
	for _, iface := range interfaces {
		spec, err := parseInterfaceSpec(iface)
		if err != nil {
			errors = append(errors, err.Error())
			continue
		}
		specs = append(specs, spec)
	}
	if len(errors) > 0 {
		err := fmt.Errorf(strings.Join(errors, "\n"))
		log.Errorln(err)
		return specs, err
	}
	return specs, nil
}

var (
	ifaceSpec = regexp.MustCompile(`^(?P<Name>\w+)(?:(?:\[(?P<Index>\d+)\])|(?::(?P<Version>inet6?)))?$`)
)

func parseInterfaceSpec(spec string) (interfaceSpec, error) {
	if spec == "inet" {
		return inetInterfaceSpec{Spec: spec, Name: "*", IPv6: false}, nil
	}
	if spec == "inet6" {
		return inetInterfaceSpec{Spec: spec, Name: "*", IPv6: true}, nil
	}
	if strings.HasPrefix(spec, "static:") {
		ip := strings.SplitAfter(spec, "static:")
		if _, err := strconv.Atoi(ip[1]); err != nil {
			nip := net.ParseIP(ip[1])
			if nip == nil {
				return nil, fmt.Errorf("Unable to parse static ip %s in %s", ip[0], spec)
			}
			return staticInterfaceSpec{Spec: spec, Name: "static", IP: nip}, nil
		}
	}

	if match := ifaceSpec.FindStringSubmatch(spec); match != nil {
		name := match[1]
		index := match[2]
		inet := match[3]
		if index != "" {
			i, err := strconv.Atoi(index)
			if err != nil {
				return nil, fmt.Errorf("Unable to parse index %s in %s", index, spec)
			}
			return indexInterfaceSpec{Spec: spec, Name: name, Index: i}, nil
		}
		if inet != "" {
			if inet == "inet" {
				return inetInterfaceSpec{Spec: spec, Name: name, IPv6: false}, nil
			}
			return inetInterfaceSpec{Spec: spec, Name: name, IPv6: true}, nil
		}
		return inetInterfaceSpec{Spec: spec, Name: name, IPv6: false}, nil
	}
	if _, net, err := net.ParseCIDR(spec); err == nil {
		return cidrInterfaceSpec{Spec: spec, Network: net}, nil
	}
	return nil, fmt.Errorf("Unable to parse interface spec: %s", spec)
}

type interfaceIP struct {
	Name string
	IP   net.IP
}

func (iip interfaceIP) To16() net.IP {
	return iip.IP.To16()
}

func (iip interfaceIP) To4() net.IP {
	return iip.IP.To4()
}

func (iip interfaceIP) IsIPv4() bool {
	return iip.To4() != nil
}

func (iip interfaceIP) IPString() string {
	if v4 := iip.To4(); v4 != nil {
		return v4.String()
	}
	return iip.IP.String()
}

func (iip interfaceIP) String() string {
	return fmt.Sprintf("%s:%s", iip.Name, iip.IPString())
}

// Queries the network interfaces on the running machine and returns a list
// of IPs for each interface.
func getinterfaceIPs(interfaces []net.Interface) ([]interfaceIP, error) {
	var ifaceIPs []interfaceIP
	var errors []string

	for _, intf := range interfaces {
		ipAddrs, addrErr := intf.Addrs()

		if addrErr != nil {
			errors = append(errors, addrErr.Error())
			continue
		}

		for _, ipAddr := range ipAddrs {
			// Addresses some times come in the form "192.168.100.1/24 2001:DB8::/48"
			// so they must be split on whitespace
			for _, splitIP := range strings.Split(ipAddr.String(), " ") {
				ip, _, err := net.ParseCIDR(splitIP)
				if err != nil {
					errors = append(errors, err.Error())
					continue
				}
				intfIP := interfaceIP{Name: intf.Name, IP: ip}
				ifaceIPs = append(ifaceIPs, intfIP)
			}
		}
	}

	// Stable Sort the interface IPs so that selecting the correct IP in GetIP
	// can be consistent
	sort.Stable(ByInterfaceThenIP(ifaceIPs))

	/* If we had any errors parsing interfaces, we accumulate them all and
	 * then return them so that the caller can decide what they want to do. */
	if len(errors) > 0 {
		err := fmt.Errorf(strings.Join(errors, "\n"))
		log.Errorln(err)
		return ifaceIPs, err
	}

	return ifaceIPs, nil
}

// ByInterfaceThenIP implements the Sort with the following properties:
// 1. Sort interfaces alphabetically
// 2. Sort IPs by bytes (normalized to 16 byte form)
type ByInterfaceThenIP []interfaceIP

func (se ByInterfaceThenIP) Len() int      { return len(se) }
func (se ByInterfaceThenIP) Swap(i, j int) { se[i], se[j] = se[j], se[i] }
func (se ByInterfaceThenIP) Less(i, j int) bool {
	iip1, iip2 := se[i], se[j]
	if cmp := strings.Compare(iip1.Name, iip2.Name); cmp != 0 {
		return cmp < 0
	}
	return bytes.Compare(iip1.To16(), iip2.To16()) < 0
}
<|endoftext|>


<commit_before>package memberlist

import (
	"log"
	"net"
	"sync/atomic"
	"time"
)

const (
	StateAlive = iota
	StateSuspect
	StateDead
)

// Node is used to represent a known node
type Node struct {
	Name string // Remote node name
	Addr net.IP // Remote address
}

// NodeState is used to manage our state view of another node
type NodeState struct {
	Node
	Incarnation uint32    // Last known incarnation number
	State       int       // Current state
	StateChange time.Time // Time last state change happened
}

// ackHandler is used to register handlers for incoming acks
type ackHandler struct {
	handler func()
	timer   *time.Timer
}

// Schedule is used to ensure the Tick is performed periodically
func (m *Memberlist) schedule() {
	// Create a new ticker
	m.tickerLock.Lock()
	m.ticker = time.NewTicker(m.config.Interval)
	C := m.ticker.C
	m.tickerLock.Unlock()
	go func() {
		for {
			select {
			case <-C:
				m.tick()
			case <-m.stopTick:
				return
			}
		}
	}()
}

// Deschedule is used to stop the background maintenence
func (m *Memberlist) deschedule() {
	m.tickerLock.Lock()
	if m.ticker != nil {
		m.ticker.Stop()
		m.ticker = nil
	}
	m.tickerLock.Unlock()
	select {
	case m.stopTick <- struct{}{}:
	default:
	}
}

// Tick is used to perform a single round of failure detection and gossip
func (m *Memberlist) tick() {
	// Track the number of indexes we've considered probing
	numCheck := 0
START:
	// Make sure we don't wrap around infinitely
	if numCheck >= len(m.nodes) {
		return
	}

	// Handle the wrap around case
	if m.tickIndex > len(m.nodes) {
		m.resetNodes()
		m.tickIndex = 0
	}

	// Determine if we should probe this node
	skip := false
	var node *NodeState
	m.nodeLock.RLock()

	node = m.nodes[m.tickIndex]
	if node.Name == m.config.Name {
		skip = true
	} else if node.State == StateDead {
		skip = true
	}

	// Potentially skip
	m.nodeLock.RUnlock()
	if skip {
		numCheck++
		m.tickIndex++
		goto START
	}

	// Probe the specific node
	m.probeNode(node)
}

// probeNode handles a single round of failure checking on a node
func (m *Memberlist) probeNode(node *NodeState) {
	// Send a ping to the node
	ping := ping{SeqNo: m.nextSeqNo()}
	destAddr := &net.UDPAddr{IP: node.Addr, Port: m.config.UDPPort}

	// Setup an ack handler
	ackCh := make(chan bool, m.config.IndirectChecks+1)
	m.setAckChannel(ping.SeqNo, ackCh, m.config.Interval)

	// Send the ping message
	if err := m.encodeAndSendMsg(destAddr, pingMsg, &ping); err != nil {
		log.Printf("[ERR] Failed to send ping: %s", err)
		return
	}

	// Wait for response or round-trip-time
	select {
	case v := <-ackCh:
		if v == true {
			return
		}
	case <-time.After(m.config.RTT):
	}

	// Get some random live nodes
	m.nodeLock.RLock()
	excludes := []string{m.config.Name, node.Name}
	kNodes := kRandomNodes(m.config.IndirectChecks, excludes, m.nodes)
	m.nodeLock.RUnlock()

	// Attempt an indirect ping
	ind := indirectPingReq{SeqNo: ping.SeqNo, Target: node.Addr}
	for _, peer := range kNodes {
		destAddr := &net.UDPAddr{IP: peer.Addr, Port: m.config.UDPPort}
		if err := m.encodeAndSendMsg(destAddr, indirectPingMsg, &ind); err != nil {
			log.Printf("[ERR] Failed to send indirect ping: %s", err)
		}
	}

	// Wait for the acks or timeout
	select {
	case v := <-ackCh:
		if v == true {
			return
		}
	}

	// No acks received from target, suspect
	s := suspect{Incarnation: node.Incarnation, Node: node.Name}
	m.suspectNode(&s)
}

// resetNodes is used when the tick wraps around. It will reap the
// dead nodes and shuffle the node list.
func (m *Memberlist) resetNodes() {
	m.nodeLock.Lock()
	defer m.nodeLock.Unlock()

	// Move the dead nodes
	deadIdx := moveDeadNodes(m.nodes)

	// Deregister the dead nodes
	for i := deadIdx; i < len(m.nodes); i++ {
		delete(m.nodeMap, m.nodes[i].Name)
	}

	// Trim the nodes to exclude the dead nodes
	m.nodes = m.nodes[0:deadIdx]

	// Shuffle live nodes
	shuffleNodes(m.nodes)
}

// nextSeqNo returns a usable sequence number in a thread safe way
func (m *Memberlist) nextSeqNo() uint32 {
	return atomic.AddUint32(&m.sequenceNum, 1)
}

// setAckChannel is used to attach a channel to receive a message when
// an ack with a given sequence number is received. The channel gets sent
// false on timeout
func (m *Memberlist) setAckChannel(seqNo uint32, ch chan bool, timeout time.Duration) {
	// Create a handler function
	handler := func() {
		select {
		case ch <- true:
		default:
		}
	}

	// Add the handler
	ah := &ackHandler{handler, nil}
	m.ackLock.Lock()
	m.ackHandlers[seqNo] = ah
	m.ackLock.Unlock()

	// Setup a reaping routing
	ah.timer = time.AfterFunc(timeout, func() {
		m.ackLock.Lock()
		delete(m.ackHandlers, seqNo)
		m.ackLock.Unlock()
		select {
		case ch <- false:
		default:
		}
	})
}

// setAckHandler is used to attach a handler to be invoked when an
// ack with a given sequence number is received. If a timeout is reached,
// the handler is deleted
func (m *Memberlist) setAckHandler(seqNo uint32, handler func(), timeout time.Duration) {
	// Add the handler
	ah := &ackHandler{handler, nil}
	m.ackLock.Lock()
	m.ackHandlers[seqNo] = ah
	m.ackLock.Unlock()

	// Setup a reaping routing
	ah.timer = time.AfterFunc(timeout, func() {
		m.ackLock.Lock()
		delete(m.ackHandlers, seqNo)
		m.ackLock.Unlock()
	})
}

// Invokes an Ack handler if any is associated, and reaps the handler immediately
func (m *Memberlist) invokeAckHandler(seqNo uint32) {
	m.ackLock.Lock()
	ah, ok := m.ackHandlers[seqNo]
	delete(m.ackHandlers, seqNo)
	m.ackLock.Unlock()
	if !ok {
		return
	}
	ah.timer.Stop()
	ah.handler()
}

// aliveNode is invoked by the network layer when we get a message
// about a live node
func (m *Memberlist) aliveNode(a *alive) {
	// TODO: Ignore we are alive
	// TODO: Re-broadcast
	m.nodeLock.Lock()
	defer m.nodeLock.Unlock()
	state, ok := m.nodeMap[a.Node]

	// Check if we've never seen this node before
	if !ok {
		state = &NodeState{
			Node: Node{
				Name: a.Node,
				Addr: a.Addr,
			},
			State: StateDead,
		}

		// Add to map
		m.nodeMap[a.Node] = state

		// Get a random offset. This is important to ensure
		// the failure detection bound is low on average. If all
		// nodes did an append, failure detection bound would be
		// very high.
		n := len(m.nodes)
		offset := randomOffset(n)

		// Add at the end and swap with the node at the offset
		m.nodes = append(m.nodes, state)
		m.nodes[offset], m.nodes[n] = m.nodes[n], m.nodes[offset]
	}

	// Bail if the incarnation number is old
	if a.Incarnation <= state.Incarnation {
		return
	}

	// Update the state and incarnation number
	oldState := state.State
	state.Incarnation = a.Incarnation
	if state.State != StateAlive {
		state.State = StateAlive
		state.StateChange = time.Now()
	}

	// if Dead -> Alive, notify of join
	if oldState == StateDead {
		m.notifyLock.RLock()
		defer m.notifyLock.RUnlock()
		notifyAll(m.notifyJoin, &state.Node)
	}
}

// suspectNode is invoked by the network layer when we get a message
// about a suspect node
func (m *Memberlist) suspectNode(s *suspect) {
	// TODO: Refute if _we_ are suspected
	// TODO: Re-broadcast
	m.nodeLock.Lock()
	defer m.nodeLock.Unlock()
	state, ok := m.nodeMap[s.Node]

	// If we've never heard about this node before, ignore it
	if !ok {
		return
	}

	// Ignore old incarnation numbers
	if s.Incarnation < state.Incarnation {
		return
	}

	// Ignore non-alive nodes
	if state.State != StateAlive {
		return
	}

	// Update the state
	state.Incarnation = s.Incarnation
	state.State = StateSuspect
	changeTime := time.Now()
	state.StateChange = changeTime

	// Setup a timeout for this
	timeout := suspicionTimeout(m.config.SuspicionMult, len(m.nodes), m.config.Interval)
	time.AfterFunc(timeout, func() {
		if state.State == StateSuspect && state.StateChange == changeTime {
			m.suspectTimeout(state)
		}
	})
}

// suspectTimeout is invoked when a suspect timeout has occurred
func (m *Memberlist) suspectTimeout(n *NodeState) {
	// Construct a dead message
	d := dead{Incarnation: n.Incarnation, Node: n.Name}
	m.deadNode(&d)
}

// deadNode is invoked by the network layer when we get a message
// about a dead node
func (m *Memberlist) deadNode(d *dead) {
	// TODO: Re-broadcast
	// TODO: Refute if us?
	m.nodeLock.Lock()
	defer m.nodeLock.Unlock()
	state, ok := m.nodeMap[d.Node]

	// If we've never heard about this node before, ignore it
	if !ok {
		return
	}

	// Ignore old incarnation numbers
	if d.Incarnation < state.Incarnation {
		return
	}

	// Ignore if node is already dead
	if state.State == StateDead {
		return
	}

	// Update the state
	state.Incarnation = d.Incarnation
	state.State = StateDead
	state.StateChange = time.Now()

	// Notify of death
	m.notifyLock.RLock()
	defer m.notifyLock.RUnlock()
	notifyAll(m.notifyLeave, &state.Node)
}

// mergeState is invoked by the network layer when we get a Push/Pull
// state transfer
func (m *Memberlist) mergeState(remote []pushNodeState) {
	for _, r := range remote {
		// Look for a matching local node
		m.nodeLock.RLock()
		local, ok := m.nodeMap[r.Name]
		m.nodeLock.RUnlock()

		// Skip if we agree on states
		if ok && local.State == r.State {
			continue
		}

		switch r.State {
		case StateAlive:
			a := alive{Incarnation: r.Incarnation, Node: r.Name, Addr: r.Addr}
			m.aliveNode(&a)

		case StateSuspect:
			s := suspect{Incarnation: r.Incarnation, Node: r.Name}
			m.suspectNode(&s)

		case StateDead:
			d := dead{Incarnation: r.Incarnation, Node: r.Name}
			m.deadNode(&d)
		}
	}
}
<commit_msg>Avoid memory leak of dead nodes<commit_after>package memberlist

import (
	"log"
	"net"
	"sync/atomic"
	"time"
)

const (
	StateAlive = iota
	StateSuspect
	StateDead
)

// Node is used to represent a known node
type Node struct {
	Name string // Remote node name
	Addr net.IP // Remote address
}

// NodeState is used to manage our state view of another node
type NodeState struct {
	Node
	Incarnation uint32    // Last known incarnation number
	State       int       // Current state
	StateChange time.Time // Time last state change happened
}

// ackHandler is used to register handlers for incoming acks
type ackHandler struct {
	handler func()
	timer   *time.Timer
}

// Schedule is used to ensure the Tick is performed periodically
func (m *Memberlist) schedule() {
	// Create a new ticker
	m.tickerLock.Lock()
	m.ticker = time.NewTicker(m.config.Interval)
	C := m.ticker.C
	m.tickerLock.Unlock()
	go func() {
		for {
			select {
			case <-C:
				m.tick()
			case <-m.stopTick:
				return
			}
		}
	}()
}

// Deschedule is used to stop the background maintenence
func (m *Memberlist) deschedule() {
	m.tickerLock.Lock()
	if m.ticker != nil {
		m.ticker.Stop()
		m.ticker = nil
	}
	m.tickerLock.Unlock()
	select {
	case m.stopTick <- struct{}{}:
	default:
	}
}

// Tick is used to perform a single round of failure detection and gossip
func (m *Memberlist) tick() {
	// Track the number of indexes we've considered probing
	numCheck := 0
START:
	// Make sure we don't wrap around infinitely
	if numCheck >= len(m.nodes) {
		return
	}

	// Handle the wrap around case
	if m.tickIndex > len(m.nodes) {
		m.resetNodes()
		m.tickIndex = 0
	}

	// Determine if we should probe this node
	skip := false
	var node *NodeState
	m.nodeLock.RLock()

	node = m.nodes[m.tickIndex]
	if node.Name == m.config.Name {
		skip = true
	} else if node.State == StateDead {
		skip = true
	}

	// Potentially skip
	m.nodeLock.RUnlock()
	if skip {
		numCheck++
		m.tickIndex++
		goto START
	}

	// Probe the specific node
	m.probeNode(node)
}

// probeNode handles a single round of failure checking on a node
func (m *Memberlist) probeNode(node *NodeState) {
	// Send a ping to the node
	ping := ping{SeqNo: m.nextSeqNo()}
	destAddr := &net.UDPAddr{IP: node.Addr, Port: m.config.UDPPort}

	// Setup an ack handler
	ackCh := make(chan bool, m.config.IndirectChecks+1)
	m.setAckChannel(ping.SeqNo, ackCh, m.config.Interval)

	// Send the ping message
	if err := m.encodeAndSendMsg(destAddr, pingMsg, &ping); err != nil {
		log.Printf("[ERR] Failed to send ping: %s", err)
		return
	}

	// Wait for response or round-trip-time
	select {
	case v := <-ackCh:
		if v == true {
			return
		}
	case <-time.After(m.config.RTT):
	}

	// Get some random live nodes
	m.nodeLock.RLock()
	excludes := []string{m.config.Name, node.Name}
	kNodes := kRandomNodes(m.config.IndirectChecks, excludes, m.nodes)
	m.nodeLock.RUnlock()

	// Attempt an indirect ping
	ind := indirectPingReq{SeqNo: ping.SeqNo, Target: node.Addr}
	for _, peer := range kNodes {
		destAddr := &net.UDPAddr{IP: peer.Addr, Port: m.config.UDPPort}
		if err := m.encodeAndSendMsg(destAddr, indirectPingMsg, &ind); err != nil {
			log.Printf("[ERR] Failed to send indirect ping: %s", err)
		}
	}

	// Wait for the acks or timeout
	select {
	case v := <-ackCh:
		if v == true {
			return
		}
	}

	// No acks received from target, suspect
	s := suspect{Incarnation: node.Incarnation, Node: node.Name}
	m.suspectNode(&s)
}

// resetNodes is used when the tick wraps around. It will reap the
// dead nodes and shuffle the node list.
func (m *Memberlist) resetNodes() {
	m.nodeLock.Lock()
	defer m.nodeLock.Unlock()

	// Move the dead nodes
	deadIdx := moveDeadNodes(m.nodes)

	// Deregister the dead nodes
	for i := deadIdx; i < len(m.nodes); i++ {
		delete(m.nodeMap, m.nodes[i].Name)
		m.nodes[i] = nil
	}

	// Trim the nodes to exclude the dead nodes
	m.nodes = m.nodes[0:deadIdx]

	// Shuffle live nodes
	shuffleNodes(m.nodes)
}

// nextSeqNo returns a usable sequence number in a thread safe way
func (m *Memberlist) nextSeqNo() uint32 {
	return atomic.AddUint32(&m.sequenceNum, 1)
}

// setAckChannel is used to attach a channel to receive a message when
// an ack with a given sequence number is received. The channel gets sent
// false on timeout
func (m *Memberlist) setAckChannel(seqNo uint32, ch chan bool, timeout time.Duration) {
	// Create a handler function
	handler := func() {
		select {
		case ch <- true:
		default:
		}
	}

	// Add the handler
	ah := &ackHandler{handler, nil}
	m.ackLock.Lock()
	m.ackHandlers[seqNo] = ah
	m.ackLock.Unlock()

	// Setup a reaping routing
	ah.timer = time.AfterFunc(timeout, func() {
		m.ackLock.Lock()
		delete(m.ackHandlers, seqNo)
		m.ackLock.Unlock()
		select {
		case ch <- false:
		default:
		}
	})
}

// setAckHandler is used to attach a handler to be invoked when an
// ack with a given sequence number is received. If a timeout is reached,
// the handler is deleted
func (m *Memberlist) setAckHandler(seqNo uint32, handler func(), timeout time.Duration) {
	// Add the handler
	ah := &ackHandler{handler, nil}
	m.ackLock.Lock()
	m.ackHandlers[seqNo] = ah
	m.ackLock.Unlock()

	// Setup a reaping routing
	ah.timer = time.AfterFunc(timeout, func() {
		m.ackLock.Lock()
		delete(m.ackHandlers, seqNo)
		m.ackLock.Unlock()
	})
}

// Invokes an Ack handler if any is associated, and reaps the handler immediately
func (m *Memberlist) invokeAckHandler(seqNo uint32) {
	m.ackLock.Lock()
	ah, ok := m.ackHandlers[seqNo]
	delete(m.ackHandlers, seqNo)
	m.ackLock.Unlock()
	if !ok {
		return
	}
	ah.timer.Stop()
	ah.handler()
}

// aliveNode is invoked by the network layer when we get a message
// about a live node
func (m *Memberlist) aliveNode(a *alive) {
	// TODO: Ignore we are alive
	// TODO: Re-broadcast
	m.nodeLock.Lock()
	defer m.nodeLock.Unlock()
	state, ok := m.nodeMap[a.Node]

	// Check if we've never seen this node before
	if !ok {
		state = &NodeState{
			Node: Node{
				Name: a.Node,
				Addr: a.Addr,
			},
			State: StateDead,
		}

		// Add to map
		m.nodeMap[a.Node] = state

		// Get a random offset. This is important to ensure
		// the failure detection bound is low on average. If all
		// nodes did an append, failure detection bound would be
		// very high.
		n := len(m.nodes)
		offset := randomOffset(n)

		// Add at the end and swap with the node at the offset
		m.nodes = append(m.nodes, state)
		m.nodes[offset], m.nodes[n] = m.nodes[n], m.nodes[offset]
	}

	// Bail if the incarnation number is old
	if a.Incarnation <= state.Incarnation {
		return
	}

	// Update the state and incarnation number
	oldState := state.State
	state.Incarnation = a.Incarnation
	if state.State != StateAlive {
		state.State = StateAlive
		state.StateChange = time.Now()
	}

	// if Dead -> Alive, notify of join
	if oldState == StateDead {
		m.notifyLock.RLock()
		defer m.notifyLock.RUnlock()
		notifyAll(m.notifyJoin, &state.Node)
	}
}

// suspectNode is invoked by the network layer when we get a message
// about a suspect node
func (m *Memberlist) suspectNode(s *suspect) {
	// TODO: Refute if _we_ are suspected
	// TODO: Re-broadcast
	m.nodeLock.Lock()
	defer m.nodeLock.Unlock()
	state, ok := m.nodeMap[s.Node]

	// If we've never heard about this node before, ignore it
	if !ok {
		return
	}

	// Ignore old incarnation numbers
	if s.Incarnation < state.Incarnation {
		return
	}

	// Ignore non-alive nodes
	if state.State != StateAlive {
		return
	}

	// Update the state
	state.Incarnation = s.Incarnation
	state.State = StateSuspect
	changeTime := time.Now()
	state.StateChange = changeTime

	// Setup a timeout for this
	timeout := suspicionTimeout(m.config.SuspicionMult, len(m.nodes), m.config.Interval)
	time.AfterFunc(timeout, func() {
		if state.State == StateSuspect && state.StateChange == changeTime {
			m.suspectTimeout(state)
		}
	})
}

// suspectTimeout is invoked when a suspect timeout has occurred
func (m *Memberlist) suspectTimeout(n *NodeState) {
	// Construct a dead message
	d := dead{Incarnation: n.Incarnation, Node: n.Name}
	m.deadNode(&d)
}

// deadNode is invoked by the network layer when we get a message
// about a dead node
func (m *Memberlist) deadNode(d *dead) {
	// TODO: Re-broadcast
	// TODO: Refute if us?
	m.nodeLock.Lock()
	defer m.nodeLock.Unlock()
	state, ok := m.nodeMap[d.Node]

	// If we've never heard about this node before, ignore it
	if !ok {
		return
	}

	// Ignore old incarnation numbers
	if d.Incarnation < state.Incarnation {
		return
	}

	// Ignore if node is already dead
	if state.State == StateDead {
		return
	}

	// Update the state
	state.Incarnation = d.Incarnation
	state.State = StateDead
	state.StateChange = time.Now()

	// Notify of death
	m.notifyLock.RLock()
	defer m.notifyLock.RUnlock()
	notifyAll(m.notifyLeave, &state.Node)
}

// mergeState is invoked by the network layer when we get a Push/Pull
// state transfer
func (m *Memberlist) mergeState(remote []pushNodeState) {
	for _, r := range remote {
		// Look for a matching local node
		m.nodeLock.RLock()
		local, ok := m.nodeMap[r.Name]
		m.nodeLock.RUnlock()

		// Skip if we agree on states
		if ok && local.State == r.State {
			continue
		}

		switch r.State {
		case StateAlive:
			a := alive{Incarnation: r.Incarnation, Node: r.Name, Addr: r.Addr}
			m.aliveNode(&a)

		case StateSuspect:
			s := suspect{Incarnation: r.Incarnation, Node: r.Name}
			m.suspectNode(&s)

		case StateDead:
			d := dead{Incarnation: r.Incarnation, Node: r.Name}
			m.deadNode(&d)
		}
	}
}
<|endoftext|>


<commit_before>package version

// Version of Functions
var Version = "0.3.437"
<commit_msg>fnserver: 0.3.438 release [skip ci]<commit_after>package version

// Version of Functions
var Version = "0.3.438"
<|endoftext|>


<commit_before>package result

import (
	"errors"
	"reflect"
	"time"

	"github.com/RichardKnop/machinery/v1/backends/iface"
	"github.com/RichardKnop/machinery/v1/tasks"
)

var (
	// ErrBackendNotConfigured ...
	ErrBackendNotConfigured = errors.New("Result backend not configured")
	// ErrTimeoutReached ...
	ErrTimeoutReached = errors.New("Timeout reached")
)

// AsyncResult represents a task result
type AsyncResult struct {
	Signature *tasks.Signature
	taskState *tasks.TaskState
	backend   iface.Backend
}

// ChordAsyncResult represents a result of a chord
type ChordAsyncResult struct {
	groupAsyncResults []*AsyncResult
	chordAsyncResult  *AsyncResult
	backend           iface.Backend
}

// ChainAsyncResult represents a result of a chain of tasks
type ChainAsyncResult struct {
	asyncResults []*AsyncResult
	backend      iface.Backend
}

// NewAsyncResult creates AsyncResult instance
func NewAsyncResult(signature *tasks.Signature, backend iface.Backend) *AsyncResult {
	return &AsyncResult{
		Signature: signature,
		taskState: new(tasks.TaskState),
		backend:   backend,
	}
}

// NewChordAsyncResult creates ChordAsyncResult instance
func NewChordAsyncResult(groupTasks []*tasks.Signature, chordCallback *tasks.Signature, backend iface.Backend) *ChordAsyncResult {
	asyncResults := make([]*AsyncResult, len(groupTasks))
	for i, task := range groupTasks {
		asyncResults[i] = NewAsyncResult(task, backend)
	}
	return &ChordAsyncResult{
		groupAsyncResults: asyncResults,
		chordAsyncResult:  NewAsyncResult(chordCallback, backend),
		backend:           backend,
	}
}

// NewChainAsyncResult creates ChainAsyncResult instance
func NewChainAsyncResult(tasks []*tasks.Signature, backend iface.Backend) *ChainAsyncResult {
	asyncResults := make([]*AsyncResult, len(tasks))
	for i, task := range tasks {
		asyncResults[i] = NewAsyncResult(task, backend)
	}
	return &ChainAsyncResult{
		asyncResults: asyncResults,
		backend:      backend,
	}
}

// Touch the state and don't wait
func (asyncResult *AsyncResult) Touch() ([]reflect.Value, error) {
	if asyncResult.backend == nil {
		return nil, ErrBackendNotConfigured
	}

	asyncResult.GetState()

	// Purge state if we are using AMQP backend
	if asyncResult.backend.IsAMQP() && asyncResult.taskState.IsCompleted() {
		asyncResult.backend.PurgeState(asyncResult.taskState.TaskUUID)
	}

	if asyncResult.taskState.IsFailure() {
		return nil, errors.New(asyncResult.taskState.Error)
	}

	if asyncResult.taskState.IsSuccess() {
		return tasks.ReflectTaskResults(asyncResult.taskState.Results)
	}

	return nil, nil
}

// Get returns task results (synchronous blocking call)
func (asyncResult *AsyncResult) Get(sleepDuration time.Duration) ([]reflect.Value, error) {
	for {
		results, err := asyncResult.Touch()

		if results == nil && err == nil {
			time.Sleep(sleepDuration)
		} else {
			return results, err
		}
	}
}

// GetWithTimeout returns task results with a timeout (synchronous blocking call)
func (asyncResult *AsyncResult) GetWithTimeout(timeoutDuration, sleepDuration time.Duration) ([]reflect.Value, error) {
	timeout := time.NewTimer(timeoutDuration)

	for {
		select {
		case <-timeout.C:
			return nil, ErrTimeoutReached
		default:
			results, err := asyncResult.Touch()

			if results == nil && err == nil {
				time.Sleep(sleepDuration)
			} else {
				return results, err
			}
		}
	}
}

// GetState returns latest task state
func (asyncResult *AsyncResult) GetState() *tasks.TaskState {
	if asyncResult.taskState.IsCompleted() {
		return asyncResult.taskState
	}

	taskState, err := asyncResult.backend.GetState(asyncResult.Signature.UUID)
	if err == nil {
		asyncResult.taskState = taskState
	}

	return asyncResult.taskState
}

// Get returns results of a chain of tasks (synchronous blocking call)
func (chainAsyncResult *ChainAsyncResult) Get(sleepDuration time.Duration) ([]reflect.Value, error) {
	if chainAsyncResult.backend == nil {
		return nil, ErrBackendNotConfigured
	}

	var (
		results []reflect.Value
		err     error
	)

	for _, asyncResult := range chainAsyncResult.asyncResults {
		results, err = asyncResult.Get(sleepDuration)
		if err != nil {
			return nil, err
		}
	}

	return results, err
}

// Get returns result of a chord (synchronous blocking call)
func (chordAsyncResult *ChordAsyncResult) Get(sleepDuration time.Duration) ([]reflect.Value, error) {
	if chordAsyncResult.backend == nil {
		return nil, ErrBackendNotConfigured
	}

	var err error
	for _, asyncResult := range chordAsyncResult.groupAsyncResults {
		_, err = asyncResult.Get(sleepDuration)
		if err != nil {
			return nil, err
		}
	}

	return chordAsyncResult.chordAsyncResult.Get(sleepDuration)
}

// GetWithTimeout returns results of a chain of tasks with timeout (synchronous blocking call)
func (chainAsyncResult *ChainAsyncResult) GetWithTimeout(timeoutDuration, sleepDuration time.Duration) ([]reflect.Value, error) {
	if chainAsyncResult.backend == nil {
		return nil, ErrBackendNotConfigured
	}

	var (
		results []reflect.Value
		err     error
	)

	timeout := time.NewTimer(timeoutDuration)
	ln := len(chainAsyncResult.asyncResults)
	lastResult := chainAsyncResult.asyncResults[ln-1]

	for {
		select {
		case <-timeout.C:
			return nil, ErrTimeoutReached
		default:

			for _, asyncResult := range chainAsyncResult.asyncResults {
				_, errcur := asyncResult.Touch()
				if errcur != nil {
					return nil, err
				}
			}

			results, err = lastResult.Touch()
			if err != nil {
				return nil, err
			}
			if results != nil {
				return results, err
			}
			time.Sleep(sleepDuration)
		}
	}
}

// GetWithTimeout returns result of a chord with a timeout (synchronous blocking call)
func (chordAsyncResult *ChordAsyncResult) GetWithTimeout(timeoutDuration, sleepDuration time.Duration) ([]reflect.Value, error) {
	if chordAsyncResult.backend == nil {
		return nil, ErrBackendNotConfigured
	}

	var (
		results []reflect.Value
		err     error
	)

	timeout := time.NewTimer(timeoutDuration)
	for {
		select {
		case <-timeout.C:
			return nil, ErrTimeoutReached
		default:
			for _, asyncResult := range chordAsyncResult.groupAsyncResults {
				_, errcur := asyncResult.Touch()
				if errcur != nil {
					return nil, err
				}
			}

			results, err = chordAsyncResult.chordAsyncResult.Touch()
			if err != nil {
				return nil, nil
			}
			if results != nil {
				return results, err
			}
			time.Sleep(sleepDuration)
		}
	}
}
<commit_msg>chain async getwithtimeout should use correct err (#579)<commit_after>package result

import (
	"errors"
	"reflect"
	"time"

	"github.com/RichardKnop/machinery/v1/backends/iface"
	"github.com/RichardKnop/machinery/v1/tasks"
)

var (
	// ErrBackendNotConfigured ...
	ErrBackendNotConfigured = errors.New("Result backend not configured")
	// ErrTimeoutReached ...
	ErrTimeoutReached = errors.New("Timeout reached")
)

// AsyncResult represents a task result
type AsyncResult struct {
	Signature *tasks.Signature
	taskState *tasks.TaskState
	backend   iface.Backend
}

// ChordAsyncResult represents a result of a chord
type ChordAsyncResult struct {
	groupAsyncResults []*AsyncResult
	chordAsyncResult  *AsyncResult
	backend           iface.Backend
}

// ChainAsyncResult represents a result of a chain of tasks
type ChainAsyncResult struct {
	asyncResults []*AsyncResult
	backend      iface.Backend
}

// NewAsyncResult creates AsyncResult instance
func NewAsyncResult(signature *tasks.Signature, backend iface.Backend) *AsyncResult {
	return &AsyncResult{
		Signature: signature,
		taskState: new(tasks.TaskState),
		backend:   backend,
	}
}

// NewChordAsyncResult creates ChordAsyncResult instance
func NewChordAsyncResult(groupTasks []*tasks.Signature, chordCallback *tasks.Signature, backend iface.Backend) *ChordAsyncResult {
	asyncResults := make([]*AsyncResult, len(groupTasks))
	for i, task := range groupTasks {
		asyncResults[i] = NewAsyncResult(task, backend)
	}
	return &ChordAsyncResult{
		groupAsyncResults: asyncResults,
		chordAsyncResult:  NewAsyncResult(chordCallback, backend),
		backend:           backend,
	}
}

// NewChainAsyncResult creates ChainAsyncResult instance
func NewChainAsyncResult(tasks []*tasks.Signature, backend iface.Backend) *ChainAsyncResult {
	asyncResults := make([]*AsyncResult, len(tasks))
	for i, task := range tasks {
		asyncResults[i] = NewAsyncResult(task, backend)
	}
	return &ChainAsyncResult{
		asyncResults: asyncResults,
		backend:      backend,
	}
}

// Touch the state and don't wait
func (asyncResult *AsyncResult) Touch() ([]reflect.Value, error) {
	if asyncResult.backend == nil {
		return nil, ErrBackendNotConfigured
	}

	asyncResult.GetState()

	// Purge state if we are using AMQP backend
	if asyncResult.backend.IsAMQP() && asyncResult.taskState.IsCompleted() {
		asyncResult.backend.PurgeState(asyncResult.taskState.TaskUUID)
	}

	if asyncResult.taskState.IsFailure() {
		return nil, errors.New(asyncResult.taskState.Error)
	}

	if asyncResult.taskState.IsSuccess() {
		return tasks.ReflectTaskResults(asyncResult.taskState.Results)
	}

	return nil, nil
}

// Get returns task results (synchronous blocking call)
func (asyncResult *AsyncResult) Get(sleepDuration time.Duration) ([]reflect.Value, error) {
	for {
		results, err := asyncResult.Touch()

		if results == nil && err == nil {
			time.Sleep(sleepDuration)
		} else {
			return results, err
		}
	}
}

// GetWithTimeout returns task results with a timeout (synchronous blocking call)
func (asyncResult *AsyncResult) GetWithTimeout(timeoutDuration, sleepDuration time.Duration) ([]reflect.Value, error) {
	timeout := time.NewTimer(timeoutDuration)

	for {
		select {
		case <-timeout.C:
			return nil, ErrTimeoutReached
		default:
			results, err := asyncResult.Touch()

			if results == nil && err == nil {
				time.Sleep(sleepDuration)
			} else {
				return results, err
			}
		}
	}
}

// GetState returns latest task state
func (asyncResult *AsyncResult) GetState() *tasks.TaskState {
	if asyncResult.taskState.IsCompleted() {
		return asyncResult.taskState
	}

	taskState, err := asyncResult.backend.GetState(asyncResult.Signature.UUID)
	if err == nil {
		asyncResult.taskState = taskState
	}

	return asyncResult.taskState
}

// Get returns results of a chain of tasks (synchronous blocking call)
func (chainAsyncResult *ChainAsyncResult) Get(sleepDuration time.Duration) ([]reflect.Value, error) {
	if chainAsyncResult.backend == nil {
		return nil, ErrBackendNotConfigured
	}

	var (
		results []reflect.Value
		err     error
	)

	for _, asyncResult := range chainAsyncResult.asyncResults {
		results, err = asyncResult.Get(sleepDuration)
		if err != nil {
			return nil, err
		}
	}

	return results, err
}

// Get returns result of a chord (synchronous blocking call)
func (chordAsyncResult *ChordAsyncResult) Get(sleepDuration time.Duration) ([]reflect.Value, error) {
	if chordAsyncResult.backend == nil {
		return nil, ErrBackendNotConfigured
	}

	var err error
	for _, asyncResult := range chordAsyncResult.groupAsyncResults {
		_, err = asyncResult.Get(sleepDuration)
		if err != nil {
			return nil, err
		}
	}

	return chordAsyncResult.chordAsyncResult.Get(sleepDuration)
}

// GetWithTimeout returns results of a chain of tasks with timeout (synchronous blocking call)
func (chainAsyncResult *ChainAsyncResult) GetWithTimeout(timeoutDuration, sleepDuration time.Duration) ([]reflect.Value, error) {
	if chainAsyncResult.backend == nil {
		return nil, ErrBackendNotConfigured
	}

	var (
		results []reflect.Value
		err     error
	)

	timeout := time.NewTimer(timeoutDuration)
	ln := len(chainAsyncResult.asyncResults)
	lastResult := chainAsyncResult.asyncResults[ln-1]

	for {
		select {
		case <-timeout.C:
			return nil, ErrTimeoutReached
		default:

			for _, asyncResult := range chainAsyncResult.asyncResults {
				_, err = asyncResult.Touch()
				if err != nil {
					return nil, err
				}
			}

			results, err = lastResult.Touch()
			if err != nil {
				return nil, err
			}
			if results != nil {
				return results, err
			}
			time.Sleep(sleepDuration)
		}
	}
}

// GetWithTimeout returns result of a chord with a timeout (synchronous blocking call)
func (chordAsyncResult *ChordAsyncResult) GetWithTimeout(timeoutDuration, sleepDuration time.Duration) ([]reflect.Value, error) {
	if chordAsyncResult.backend == nil {
		return nil, ErrBackendNotConfigured
	}

	var (
		results []reflect.Value
		err     error
	)

	timeout := time.NewTimer(timeoutDuration)
	for {
		select {
		case <-timeout.C:
			return nil, ErrTimeoutReached
		default:
			for _, asyncResult := range chordAsyncResult.groupAsyncResults {
				_, errcur := asyncResult.Touch()
				if errcur != nil {
					return nil, err
				}
			}

			results, err = chordAsyncResult.chordAsyncResult.Touch()
			if err != nil {
				return nil, nil
			}
			if results != nil {
				return results, err
			}
			time.Sleep(sleepDuration)
		}
	}
}
<|endoftext|>


<commit_before>package main

import (
	"encoding/json"
	"fmt"
	"math"
	"math/rand"
	"os"
	"sort"
	"time"
)

const (
	HISTORY_LENGTH    = 4
	CROSSOVER_LENGTH  = 10
	CROSSOVER_PERMILL = 500
	MUTATION_PERMILLI = 30
	MUTATION_LENGTH   = 10

	TOURNAMENT_TOTAL = 100
	TOURNAMENT_SIZE  = 35

	MAX_GENERATION = 30

	POINT_WIN = 1
	POINT_EVEN = 0
	POINT_LOSE = 0
)

type Hand int

const (
	Hand_Gu = Hand(iota)
	Hand_Choki
	Hand_Pa
)

func (h Hand) String() string {
	switch h {
	case Hand_Gu:
		return "G"
	case Hand_Choki:
		return "C"
	case Hand_Pa:
		return "P"
	}
	return "panic"
}

func (h Hand) Point(t Hand) int {
	point := 0
	switch h {
	case Hand_Gu:
		switch t {
		case Hand_Gu:
			point = POINT_EVEN
		case Hand_Choki:
			point = POINT_WIN
		case Hand_Pa:
			point = POINT_LOSE
		}
	case Hand_Choki:
		switch t {
		case Hand_Gu:
			point = POINT_LOSE
		case Hand_Choki:
			point = POINT_EVEN
		case Hand_Pa:
			point = POINT_WIN
		}
	case Hand_Pa:
		switch t {
		case Hand_Gu:
			point = POINT_WIN
		case Hand_Choki:
			point = POINT_LOSE
		case Hand_Pa:
			point = POINT_EVEN
		}
	}
	return point
}

func GetRandHand() Hand {
	return Hand(rand.Int() % 3)
}

type Gene struct {
	decision []Hand
}

func NewGene() *Gene {
	decision := make([]Hand, decisionlength())
	for i, _ := range decision {
		decision[i] = GetRandHand()
	}

	return &Gene{
		decision: decision,
	}
}

func (g *Gene) Score(hands []Hand) int {
	score := 0
	for i := HISTORY_LENGTH + 1; i < len(hands)-1; i++ {
		score += g.Hand(hands[i-HISTORY_LENGTH-1 : i-1]).Point(hands[i])
	}
	return score
}

func (g *Gene) Hand(history []Hand) Hand {
	if len(history) != HISTORY_LENGTH {
		panic("invalid history")
	}

	var index int
	for _, v := range history {
		index += index*3 + int(v)
	}
	return g.decision[index]
}
/*
func (g *Gene) CrossOver(partner *Gene) *Gene {
	new_decision := make([]Hand, decisionlength())
	copy(new_decision, g.decision)

	// crossover
	ptr := rand.Int() % (decisionlength() - CROSSOVER_LENGTH)
	for i := 0; i < CROSSOVER_LENGTH; i++ {
		new_decision[i+ptr] = partner.decision[i+ptr]
	}

	return &Gene{
		decision: new_decision,
	}
}
*/

func (g *Gene) CrossOver(partner *Gene) *Gene {
	new_decision := make([]Hand,decisionlength())
	copy(new_decision, g.decision)

	for i, _ := range new_decision {
		if rand.Int()%1000 < CROSSOVER_PERMILL {
			new_decision[i] = partner.decision[i]
		}
	}

	return &Gene{
		decision: new_decision,
	}
}

func (g *Gene) Mutation() {
	if r := rand.Int() % 1000; r < MUTATION_PERMILLI {
		g.doMutation()
	}
	return
}

func (g *Gene) doMutation() *Gene {
	ptr := rand.Int() % (decisionlength() - MUTATION_LENGTH)
	for i := 0; i < MUTATION_LENGTH; i++ {
		g.decision[i+ptr] = Hand(rand.Int() % 3)
	}
	return g
}

func CreateHistory(filename string, start, end time.Time) []Hand {
	f, err := os.Open(filename)
	if err != nil {
		panic(err)
	}

	buf := make([]map[string]interface{}, 0)
	err = json.NewDecoder(f).Decode(&buf)
	if err != nil {
		panic(err)
	}

	hands := make([]Hand, 0)
	for _, v := range buf {
		if t, _ := time.Parse(time.RFC3339, v["when"].(string)); t.Before(start) {
			continue
		}
		if t, _ := time.Parse(time.RFC3339, v["when"].(string)); t.After(end) {
			continue
		}
		if err != nil {
			panic(err)
		}
		hands = append(hands, Hand(int(v["hand"].(float64))))
	}

	return hands
}

type ResultList []Resulter
type Resulter struct {
	score  int
	number int
}

func (rl ResultList) Len() int {
	return len(rl)
}

func (rl ResultList) Swap(i, j int) {
	rl[i], rl[j] = rl[j], rl[i]
}

func (rl ResultList) Less(i, j int) bool {
	return rl[i].score > rl[j].score
}

func main() {
	// initialize history
	hist := CreateHistory("sazae.json", mustParseTime("2012-08-01T00:00:00Z"), mustParseTime("2014-08-01T00:00:00Z"))
	fmt.Println(len(hist))

	// initialize
	genes := make([]*Gene, TOURNAMENT_TOTAL)
	for i, _ := range genes {
		genes[i] = NewGene()
	}

	lasttop := 0
	for gen := 0; gen < MAX_GENERATION; gen++ {
		// Tournament
		results := make(ResultList, 0)
		for i, gene := range genes {
			results = append(results, Resulter{
				number: i,
				score:  gene.Score(hist),
			})
		}
		sort.Stable(results)

		fmt.Printf("gene:%3d / topscore:%3d / next:%s\n", gen, results[0].score, genes[results[0].number].Hand(hist[len(hist)-HISTORY_LENGTH:] ))
		lasttop = results[0].score

		// Get winner
		winner := make([]*Gene, TOURNAMENT_SIZE)
		for i:=0; i<TOURNAMENT_SIZE; i++ {
			winner[i] = genes[results[i].number]
		}

		next_genes := make([]*Gene, TOURNAMENT_TOTAL)
		for i:=0; i<TOURNAMENT_TOTAL-TOURNAMENT_SIZE; i++ {
			j := rand.Int()%(TOURNAMENT_SIZE-1)
			next_genes[i] = winner[j].CrossOver(winner[j+1])
		}
		for i:=0; i<TOURNAMENT_SIZE; i++ {
			next_genes[i+TOURNAMENT_TOTAL-TOURNAMENT_SIZE] = winner[i]
		}

		genes = next_genes
	}

	fmt.Println(float64(lasttop)/float64(len(hist)))
}

func init() {
	rand.Seed(time.Now().UnixNano())
}

func decisionlength() int {
	f64HistLen := float64(HISTORY_LENGTH)
	return int(math.Pow(f64HistLen, f64HistLen*2))
}

func mustParseTime(str string) time.Time {
	t, err := time.Parse(time.RFC3339, str)
	if err != nil {
		panic(err)
	}
	return t
}
<commit_msg>fix memory size culc<commit_after>package main

import (
	"encoding/json"
	"fmt"
	"math"
	"math/rand"
	"os"
	"sort"
	"time"
)

const (
	HISTORY_LENGTH    = 4
	CROSSOVER_LENGTH  = 10
	CROSSOVER_PERMILL = 500
	MUTATION_PERMILLI = 30
	MUTATION_LENGTH   = 10

	TOURNAMENT_TOTAL = 100
	TOURNAMENT_SIZE  = 35

	MAX_GENERATION = 30

	POINT_WIN = 1
	POINT_EVEN = 0
	POINT_LOSE = 0
)

type Hand int

const (
	Hand_Gu = Hand(iota)
	Hand_Choki
	Hand_Pa
)

func (h Hand) String() string {
	switch h {
	case Hand_Gu:
		return "G"
	case Hand_Choki:
		return "C"
	case Hand_Pa:
		return "P"
	}
	return "panic"
}

func (h Hand) Point(t Hand) int {
	point := 0
	switch h {
	case Hand_Gu:
		switch t {
		case Hand_Gu:
			point = POINT_EVEN
		case Hand_Choki:
			point = POINT_WIN
		case Hand_Pa:
			point = POINT_LOSE
		}
	case Hand_Choki:
		switch t {
		case Hand_Gu:
			point = POINT_LOSE
		case Hand_Choki:
			point = POINT_EVEN
		case Hand_Pa:
			point = POINT_WIN
		}
	case Hand_Pa:
		switch t {
		case Hand_Gu:
			point = POINT_WIN
		case Hand_Choki:
			point = POINT_LOSE
		case Hand_Pa:
			point = POINT_EVEN
		}
	}
	return point
}

func GetRandHand() Hand {
	return Hand(rand.Int() % 3)
}

type Gene struct {
	decision []Hand
}

func NewGene() *Gene {
	decision := make([]Hand, decisionlength())
	for i, _ := range decision {
		decision[i] = GetRandHand()
	}

	return &Gene{
		decision: decision,
	}
}

func (g *Gene) Score(hands []Hand) int {
	score := 0
	for i := HISTORY_LENGTH + 1; i < len(hands)-1; i++ {
		score += g.Hand(hands[i-HISTORY_LENGTH-1 : i-1]).Point(hands[i])
	}
	return score
}

func (g *Gene) Hand(history []Hand) Hand {
	if len(history) != HISTORY_LENGTH {
		panic("invalid history")
	}

	var index int
	for _, v := range history {
		index = index*3 + int(v)
	}
	return g.decision[index]
}
/*
func (g *Gene) CrossOver(partner *Gene) *Gene {
	new_decision := make([]Hand, decisionlength())
	copy(new_decision, g.decision)

	// crossover
	ptr := rand.Int() % (decisionlength() - CROSSOVER_LENGTH)
	for i := 0; i < CROSSOVER_LENGTH; i++ {
		new_decision[i+ptr] = partner.decision[i+ptr]
	}

	return &Gene{
		decision: new_decision,
	}
}
*/

func (g *Gene) CrossOver(partner *Gene) *Gene {
	new_decision := make([]Hand,decisionlength())
	copy(new_decision, g.decision)

	for i, _ := range new_decision {
		if rand.Int()%1000 < CROSSOVER_PERMILL {
			new_decision[i] = partner.decision[i]
		}
	}

	return &Gene{
		decision: new_decision,
	}
}

func (g *Gene) Mutation() {
	if r := rand.Int() % 1000; r < MUTATION_PERMILLI {
		g.doMutation()
	}
	return
}

func (g *Gene) doMutation() *Gene {
	ptr := rand.Int() % (decisionlength() - MUTATION_LENGTH)
	for i := 0; i < MUTATION_LENGTH; i++ {
		g.decision[i+ptr] = Hand(rand.Int() % 3)
	}
	return g
}

func CreateHistory(filename string, start, end time.Time) []Hand {
	f, err := os.Open(filename)
	if err != nil {
		panic(err)
	}

	buf := make([]map[string]interface{}, 0)
	err = json.NewDecoder(f).Decode(&buf)
	if err != nil {
		panic(err)
	}

	hands := make([]Hand, 0)
	for _, v := range buf {
		if t, _ := time.Parse(time.RFC3339, v["when"].(string)); t.Before(start) {
			continue
		}
		if t, _ := time.Parse(time.RFC3339, v["when"].(string)); t.After(end) {
			continue
		}
		if err != nil {
			panic(err)
		}
		hands = append(hands, Hand(int(v["hand"].(float64))))
	}

	return hands
}

type ResultList []Resulter
type Resulter struct {
	score  int
	number int
}

func (rl ResultList) Len() int {
	return len(rl)
}

func (rl ResultList) Swap(i, j int) {
	rl[i], rl[j] = rl[j], rl[i]
}

func (rl ResultList) Less(i, j int) bool {
	return rl[i].score > rl[j].score
}

func main() {
	// initialize history
	hist := CreateHistory("sazae.json", mustParseTime("2012-08-01T00:00:00Z"), mustParseTime("2014-08-01T00:00:00Z"))
	fmt.Println(len(hist))

	// initialize
	genes := make([]*Gene, TOURNAMENT_TOTAL)
	for i, _ := range genes {
		genes[i] = NewGene()
	}

	lasttop := 0
	for gen := 0; gen < MAX_GENERATION; gen++ {
		// Tournament
		results := make(ResultList, 0)
		for i, gene := range genes {
			results = append(results, Resulter{
				number: i,
				score:  gene.Score(hist),
			})
		}
		sort.Stable(results)

		fmt.Printf("gene:%3d / topscore:%3d / next:%s\n", gen, results[0].score, genes[results[0].number].Hand(hist[len(hist)-HISTORY_LENGTH:] ))
		lasttop = results[0].score

		// Get winner
		winner := make([]*Gene, TOURNAMENT_SIZE)
		for i:=0; i<TOURNAMENT_SIZE; i++ {
			winner[i] = genes[results[i].number]
		}

		next_genes := make([]*Gene, TOURNAMENT_TOTAL)
		for i:=0; i<TOURNAMENT_TOTAL-TOURNAMENT_SIZE; i++ {
			j := rand.Int()%(TOURNAMENT_SIZE-1)
			next_genes[i] = winner[j].CrossOver(winner[j+1])
		}
		for i:=0; i<TOURNAMENT_SIZE; i++ {
			next_genes[i+TOURNAMENT_TOTAL-TOURNAMENT_SIZE] = winner[i]
		}

		genes = next_genes
	}

	fmt.Println(float64(lasttop)/float64(len(hist)))
}

func init() {
	rand.Seed(time.Now().UnixNano())
}

func decisionlength() int {
	f64HistLen := float64(HISTORY_LENGTH)
	return int(math.Pow(3.0, f64HistLen))
}

func mustParseTime(str string) time.Time {
	t, err := time.Parse(time.RFC3339, str)
	if err != nil {
		panic(err)
	}
	return t
}
<|endoftext|>


<commit_before>// Ipnow prints the current IP address.
package main

import (
	"errors"
	"fmt"
	"log"
	"net"
)

func main() {
	log.SetFlags(0)
	log.SetPrefix("ipaddr: ")

	a, err := ipAddr()
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(a)
}

func ipAddr() (string, error) {
	ifaces, err := net.Interfaces()
	if err != nil {
		return "", err
	}
	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 "", err
		}
		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
			}
			ip = ip.To4()
			if ip == nil {
				continue // not an ipv4 address
			}
			return ip.String(), nil
		}
	}
	return "", errors.New("no ip")
}
<commit_msg>ipaddr: delete.<commit_after><|endoftext|>