<commit_before>package models

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

type ChangeDirection struct {
	Index     int
	Direction Direction
	Wait      *sync.WaitGroup
}

const (
	Initializing = iota
	InProgress
	Ended
)

type Field struct {
	mu *sync.Mutex //initially used while adding players

	Height, Width int
	needed        int //number of players needed to start the game

	Gophers []*Gopher
	Board   [][]bool

	Change chan ChangeDirection
	Remove chan *Gopher

	State     int
	cycles    int
	nextCycle interface{}
}

var (
	ErrInProgress = errors.New("game is already in progress")
	ErrMaxPlayers = errors.New("cannot add more than 4 players")
)

func NewField(height, width int, needed int) (*Field, error) {
	if needed > 4 {
		return nil, ErrMaxPlayers
	}

	field := &Field{
		Height:    height,
		needed:    needed,
		Width:     width,
		Board:     make([][]bool, height),
		Change:    make(chan ChangeDirection),
		Remove:    make(chan *Gopher),
		mu:        new(sync.Mutex),
		State:     Initializing,
		nextCycle: time.NewTicker(100 * time.Millisecond),
	}

	for i := range field.Board {
		field.Board[i] = make([]bool, width)
	}

	return field, nil
}

func (f *Field) Add(g *Gopher) (int, error) {
	f.mu.Lock()
	defer f.mu.Unlock()

	if f.State == InProgress {
		return 0, ErrInProgress
	}

	f.Gophers = append(f.Gophers, g)
	//set gopher's initial position and direction

	var initPositions = []struct {
		X int
		Y int
		D Direction
	}{
		{f.Width / 2, 0, North},
		{0, f.Height / 2, East},
		{f.Width / 2, f.Height - 1, South},
		{f.Width - 1, f.Height / 2, West},
	}
	for _, pos := range initPositions {
		if !f.Board[pos.X][pos.Y] {
			f.setPos(g, pos.X, pos.Y)
			g.Direction = pos.D
			break
		}
	}

	if len(f.Gophers) == f.needed {
		f.State = Ended
		go f.start()
	}

	return len(f.Gophers) - 1, nil
}

func (f *Field) setPos(g *Gopher, X, Y int) {
	f.Board[X][Y] = true
	g.X = X
	g.Y = Y
}

func (f *Field) remove(gopher *Gopher) {
	for i, currGopher := range f.Gophers {
		if currGopher == gopher {
			f.Gophers, f.Gophers[len(f.Gophers)-1] = append(f.Gophers[:i], f.Gophers[i+1:]...), nil
		}
	}
}

func (f *Field) PrintBoard() {
	for y := f.Height - 1; y >= 0; y-- {
		for x := 0; x < f.Width; x++ {
			if f.Board[x][y] {
				fmt.Print(1)
			} else {
				fmt.Print(0)
			}
			//fmt.Printf("(%d,%d)", x, y)
		}
		fmt.Println()
	}
	fmt.Println("-----")
}

func (f *Field) increment(g *Gopher) bool {
	g.Path = append(g.Path, Coordinate{g.X, g.Y})
	switch g.Direction {
	case North:
		g.Y++
	case South:
		g.Y--
	case East:
		g.X++
	case West:
		g.X--
	}

	if g.X == f.Height || g.Y == f.Width {
		return true
	}
	if f.Board[g.X][g.Y] {
		return true
	}

	f.Board[g.X][g.Y] = true
	g.Score++

	if f.cycles > 10 {
		f.Board[g.Path[0].X][g.Path[0].Y] = false
	} else {
		f.cycles++
	}

	return false
}

func (f *Field) clearPath(g *Gopher) {
	for _, c := range g.Path {
		f.Board[c.X][c.Y] = false
	}
}

func (f *Field) start() {
	channel := make(chan struct{})

	switch f.nextCycle.(type) {
	case *time.Ticker:
		go func() {
			for {
				<-f.nextCycle.(time.Ticker).C
				channel <- struct{}{}
			}
		}()
	default:
		//testing
		go func() {
			for {
				channel <- <-f.nextCycle.(chan struct{})
			}
		}()
	}

	for {
		select {
		case dir := <-f.Change:
			f.Gophers[dir.Index].Direction = dir.Direction
			dir.Wait.Done()
		case gopher := <-f.Remove:
			f.remove(gopher)
			if len(f.Gophers) == 1 {
				f.end()
				return
			}
		case <-channel:
			for _, gopher := range f.Gophers {
				if f.increment(gopher) {
					//fmt.Println(i, " collided")
					//gopher collided, clear it's path and remove it
					//from the field
					f.clearPath(gopher)
					f.remove(gopher)

					if len(f.Gophers) == 1 {
						f.end()
						return
					}
				}
			}
			//f.PrintBoard()
		}
	}
}

func (f *Field) end() {
	f.mu.Lock()
	f.State = Ended
	f.mu.Unlock()
	if _, ok := f.nextCycle.(*time.Ticker); ok {
		f.nextCycle.(*time.Ticker).Stop()
	}
}

func (f *Field) broadcast() {

}
<commit_msg>Use array indices for gopher operations, add id to (*Field)<commit_after>package models

import (
	"crypto/rand"
	"encoding/base64"
	"errors"
	"fmt"
	"sync"
	"time"
)

type ChangeDirection struct {
	Index     int
	Direction Direction
	Wait      *sync.WaitGroup
}

const (
	Initializing = iota
	InProgress
	Ended
)

type Field struct {
	mu *sync.Mutex //initially used while adding players

	id            string
	Height, Width int
	needed        int //number of players needed to start the game

	Gophers []*Gopher
	Board   [][]bool

	Change chan ChangeDirection
	Remove chan int

	State     int
	cycles    int
	nextCycle interface{}
}

var (
	ErrInProgress = errors.New("game is already in progress")
	ErrMaxPlayers = errors.New("cannot add more than 4 players")
	mapMu         = new(sync.RWMutex)
	activeFields  = make(map[string]*Field)
)

func GetGames() map[string]*Field {
	games := make(map[string]*Field)
	mapMu.RLock()
	defer mapMu.RUnlock()

	for id, field := range activeFields {
		games[id] = field
	}

	return games
}

func GetGame(id string) (*Field, bool) {
	mapMu.RLock()
	defer mapMu.RUnlock()
	field, ok := activeFields[id]

	return field, ok
}

func NewField(height, width int, needed int) (*Field, error) {
	if needed > 4 {
		return nil, ErrMaxPlayers
	}

	bytes := make([]byte, 10)
	rand.Read(bytes)
	id := base64.URLEncoding.EncodeToString(bytes)

	field := &Field{
		id:        id,
		Height:    height,
		needed:    needed,
		Width:     width,
		Board:     make([][]bool, height),
		Change:    make(chan ChangeDirection),
		Remove:    make(chan int),
		mu:        new(sync.Mutex),
		State:     Initializing,
		nextCycle: time.NewTicker(100 * time.Millisecond),
	}

	for i := range field.Board {
		field.Board[i] = make([]bool, width)
	}

	mapMu.Lock()
	defer mapMu.Unlock()
	activeFields[id] = field

	return field, nil
}

func (f *Field) Add(g *Gopher) (int, error) {
	f.mu.Lock()
	defer f.mu.Unlock()

	if f.State == InProgress {
		return 0, ErrInProgress
	}

	f.Gophers = append(f.Gophers, g)
	//set gopher's initial position and direction

	var initPositions = []struct {
		X int
		Y int
		D Direction
	}{
		{f.Width / 2, 0, North},
		{0, f.Height / 2, East},
		{f.Width / 2, f.Height - 1, South},
		{f.Width - 1, f.Height / 2, West},
	}
	for _, pos := range initPositions {
		if !f.Board[pos.X][pos.Y] {
			f.setPos(g, pos.X, pos.Y)
			g.Direction = pos.D
			break
		}
	}

	if len(f.Gophers) == f.needed {
		f.State = Ended
		go f.start()
	}

	return len(f.Gophers) - 1, nil
}

func (f *Field) setPos(g *Gopher, X, Y int) {
	f.Board[X][Y] = true
	g.X = X
	g.Y = Y
}

func (f *Field) remove(gopher *Gopher) {
	for i, currGopher := range f.Gophers {
		if currGopher == gopher {
			f.Gophers, f.Gophers[len(f.Gophers)-1] = append(f.Gophers[:i], f.Gophers[i+1:]...), nil
		}
	}
}

func (f *Field) PrintBoard() {
	for y := f.Height - 1; y >= 0; y-- {
		for x := 0; x < f.Width; x++ {
			if f.Board[x][y] {
				fmt.Print(1)
			} else {
				fmt.Print(0)
			}
			//fmt.Printf("(%d,%d)", x, y)
		}
		fmt.Println()
	}
	fmt.Println("-----")
}

func (f *Field) increment(g *Gopher) bool {
	g.Path = append(g.Path, Coordinate{g.X, g.Y})
	switch g.Direction {
	case North:
		g.Y++
	case South:
		g.Y--
	case East:
		g.X++
	case West:
		g.X--
	}

	if g.X == f.Height || g.Y == f.Width {
		return true
	}
	if f.Board[g.X][g.Y] {
		return true
	}

	f.Board[g.X][g.Y] = true
	g.Score++

	if f.cycles > 10 {
		f.Board[g.Path[0].X][g.Path[0].Y] = false
	} else {
		f.cycles++
	}

	return false
}

func (f *Field) clearPath(g *Gopher) {
	for _, c := range g.Path {
		f.Board[c.X][c.Y] = false
	}
}

func (f *Field) start() {
	channel := make(chan struct{})

	switch f.nextCycle.(type) {
	case *time.Ticker:
		go func() {
			for {
				<-f.nextCycle.(time.Ticker).C
				channel <- struct{}{}
			}
		}()
	default:
		//testing
		go func() {
			for {
				channel <- <-f.nextCycle.(chan struct{})
			}
		}()
	}

	for {
		select {
		case dir := <-f.Change:
			if f.State != InProgress {
				continue
			}
			f.Gophers[dir.Index].Direction = dir.Direction
			dir.Wait.Done()
		case index := <-f.Remove:
			f.remove(f.Gophers[index])
			if len(f.Gophers) == 1 {
				f.end()
				return
			}
		case <-channel:
			for _, gopher := range f.Gophers {
				if f.increment(gopher) {
					//fmt.Println(i, " collided")
					//gopher collided, clear it's path and remove it
					//from the field
					f.clearPath(gopher)
					f.remove(gopher)

					if len(f.Gophers) == 1 {
						f.end()
						return
					}
				}
			}
			//f.PrintBoard()
		}
	}
}

func (f *Field) end() {
	f.mu.Lock()
	f.State = Ended
	f.mu.Unlock()
	if _, ok := f.nextCycle.(*time.Ticker); ok {
		f.nextCycle.(*time.Ticker).Stop()
	}
	mapMu.Lock()
	delete(activeFields, f.id)
	mapMu.RUnlock()
}

func (f *Field) broadcast() {
	paths := make(map[int][]Coordinate)
	for i, gopher := range f.Gophers {
		copy(paths[i], gopher.Path)
		gopher.Paths <- paths
	}
}
<|endoftext|>


<commit_before>package examples

import (
	"bytes"
	"testing"

	. "launchpad.net/gocheck"

	ds "github.com/ipfs/go-datastore"
	fs "github.com/ipfs/go-datastore/fs"
	query "github.com/ipfs/go-datastore/query"
)

// Hook up gocheck into the "go test" runner.
func Test(t *testing.T) { TestingT(t) }

type DSSuite struct {
	dir string
	ds  ds.Datastore
}

var _ = Suite(&DSSuite{})

func (ks *DSSuite) SetUpTest(c *C) {
	ks.dir = c.MkDir()
	ks.ds, _ = fs.NewDatastore(ks.dir)
}

func (ks *DSSuite) TestOpen(c *C) {
	_, err := fs.NewDatastore("/tmp/foo/bar/baz")
	c.Assert(err, Not(Equals), nil)

	// setup ds
	_, err = fs.NewDatastore(ks.dir)
	c.Assert(err, Equals, nil)
}

func (ks *DSSuite) TestBasic(c *C) {

	keys := strsToKeys([]string{
		"foo",
		"foo/bar",
		"foo/bar/baz",
		"foo/barb",
		"foo/bar/bazb",
		"foo/bar/baz/barb",
	})

	for _, k := range keys {
		err := ks.ds.Put(k, []byte(k.String()))
		c.Check(err, Equals, nil)
	}

	for _, k := range keys {
		v, err := ks.ds.Get(k)
		c.Check(err, Equals, nil)
		c.Check(bytes.Equal(v.([]byte), []byte(k.String())), Equals, true)
	}

	r, err := ks.ds.Query(query.Query{Prefix: "/foo/bar/"})
	if err != nil {
		c.Check(err, Equals, nil)
	}

	expect := []string{
		"/foo/bar/baz",
		"/foo/bar/bazb",
		"/foo/bar/baz/barb",
	}
	all, err := r.Rest()
	if err != nil {
		c.Fatal(err)
	}
	c.Check(len(all), Equals, len(expect))

	for _, k := range expect {
		found := false
		for _, e := range all {
			if e.Key == k {
				found = true
			}
		}

		if !found {
			c.Error("did not find expected key: ", k)
		}
	}
}

func (ks *DSSuite) TestDiskUsage(c *C) {
	keys := strsToKeys([]string{
		"foo",
		"foo/bar",
		"foo/bar/baz",
		"foo/barb",
		"foo/bar/bazb",
		"foo/bar/baz/barb",
	})

	for _, k := range keys {
		err := ks.ds.Put(k, []byte(k.String()))
		c.Check(err, Equals, nil)
	}

	if ps, ok := ks.ds.(ds.PersistentDatastore); ok {
		if s, err := ps.DiskUsage(); s <= 100 || err != nil {
			c.Error("unexpected size is: ", s)
		}
	} else {
		c.Error("should implement PersistentDatastore")
	}
}

func strsToKeys(strs []string) []ds.Key {
	keys := make([]ds.Key, len(strs))
	for i, s := range strs {
		keys[i] = ds.NewKey(s)
	}
	return keys
}
<commit_msg>fix fs example tests<commit_after>package examples

import (
	"bytes"
	"testing"

	. "launchpad.net/gocheck"

	ds "github.com/ipfs/go-datastore"
	query "github.com/ipfs/go-datastore/query"
)

// Hook up gocheck into the "go test" runner.
func Test(t *testing.T) { TestingT(t) }

type DSSuite struct {
	dir string
	ds  ds.Datastore
}

var _ = Suite(&DSSuite{})

func (ks *DSSuite) SetUpTest(c *C) {
	ks.dir = c.MkDir()
	ks.ds, _ = NewDatastore(ks.dir)
}

func (ks *DSSuite) TestOpen(c *C) {
	_, err := NewDatastore("/tmp/foo/bar/baz")
	c.Assert(err, Not(Equals), nil)

	// setup ds
	_, err = NewDatastore(ks.dir)
	c.Assert(err, Equals, nil)
}

func (ks *DSSuite) TestBasic(c *C) {

	keys := strsToKeys([]string{
		"foo",
		"foo/bar",
		"foo/bar/baz",
		"foo/barb",
		"foo/bar/bazb",
		"foo/bar/baz/barb",
	})

	for _, k := range keys {
		err := ks.ds.Put(k, []byte(k.String()))
		c.Check(err, Equals, nil)
	}

	for _, k := range keys {
		v, err := ks.ds.Get(k)
		c.Check(err, Equals, nil)
		c.Check(bytes.Equal(v.([]byte), []byte(k.String())), Equals, true)
	}

	r, err := ks.ds.Query(query.Query{Prefix: "/foo/bar/"})
	if err != nil {
		c.Check(err, Equals, nil)
	}

	expect := []string{
		"/foo/bar/baz",
		"/foo/bar/bazb",
		"/foo/bar/baz/barb",
	}
	all, err := r.Rest()
	if err != nil {
		c.Fatal(err)
	}
	c.Check(len(all), Equals, len(expect))

	for _, k := range expect {
		found := false
		for _, e := range all {
			if e.Key == k {
				found = true
			}
		}

		if !found {
			c.Error("did not find expected key: ", k)
		}
	}
}

func (ks *DSSuite) TestDiskUsage(c *C) {
	keys := strsToKeys([]string{
		"foo",
		"foo/bar",
		"foo/bar/baz",
		"foo/barb",
		"foo/bar/bazb",
		"foo/bar/baz/barb",
	})

	for _, k := range keys {
		err := ks.ds.Put(k, []byte(k.String()))
		c.Check(err, Equals, nil)
	}

	if ps, ok := ks.ds.(ds.PersistentDatastore); ok {
		if s, err := ps.DiskUsage(); s <= 100 || err != nil {
			c.Error("unexpected size is: ", s)
		}
	} else {
		c.Error("should implement PersistentDatastore")
	}
}

func strsToKeys(strs []string) []ds.Key {
	keys := make([]ds.Key, len(strs))
	for i, s := range strs {
		keys[i] = ds.NewKey(s)
	}
	return keys
}
<|endoftext|>


<commit_before>package main

import (
	"encoding/json"
	"errors"
	"io/ioutil"
	"net"
	"net/http"
	"os"
	"reflect"
	"strings"

	"github.com/spf13/cobra"

	"github.com/NebulousLabs/Sia/build"
)

var (
	addr         string
	force        bool
	initPassword bool
)

// apiGet wraps a GET request with a status code check, such that if the GET does
// not return 200, the error will be read and returned. The response body is
// not closed.
func apiGet(call string) (*http.Response, error) {
	if host, port, _ := net.SplitHostPort(addr); host == "" {
		addr = net.JoinHostPort("localhost", port)
	}
	client := &http.Client{}
	req, err := http.NewRequest("GET", "http://"+addr+call, nil)
	req.Header.Add("User-Agent", "Sia-Agent")
	resp, err := client.Do(req)
	if err != nil {
		return nil, errors.New("no response from daemon")
	}
	// check error code
	if resp.StatusCode == http.StatusNotFound {
		resp.Body.Close()
		err = errors.New("API call not recognized: " + call)
	} else if resp.StatusCode != http.StatusOK {
		errResp, _ := ioutil.ReadAll(resp.Body)
		resp.Body.Close()
		err = errors.New(strings.TrimSpace(string(errResp)))
	}
	return resp, err
}

// getAPI makes a GET API call and decodes the response.
func getAPI(call string, obj interface{}) error {
	resp, err := apiGet(call)
	if err != nil {
		return err
	}
	defer resp.Body.Close()
	err = json.NewDecoder(resp.Body).Decode(obj)
	if err != nil {
		return err
	}
	return nil
}

// get makes an API call and discards the response.
func get(call string) error {
	resp, err := apiGet(call)
	if err != nil {
		return err
	}
	resp.Body.Close()
	return nil
}

// apiPost wraps a POST request with a status code check, such that if the POST
// does not return 200, the error will be read and returned. The response body
// is not closed.
func apiPost(call, vals string) (*http.Response, error) {
	if host, port, _ := net.SplitHostPort(addr); host == "" {
		addr = net.JoinHostPort("localhost", port)
	}

	client := &http.Client{}
	req, err := http.NewRequest("POST", "http://"+addr+call, strings.NewReader(vals))
	req.Header.Add("User-Agent", "Sia-Agent")
	req.Header.Add("Content-Type", "application/x-www-form-urlencoded")
	resp, err := client.Do(req)
	if err != nil {
		return nil, errors.New("no response from daemon")
	}
	// check error code
	if resp.StatusCode == http.StatusNotFound {
		resp.Body.Close()
		err = errors.New("API call not recognized: " + call)
	} else if resp.StatusCode != http.StatusOK {
		errResp, _ := ioutil.ReadAll(resp.Body)
		resp.Body.Close()
		err = errors.New(strings.TrimSpace(string(errResp)))
	}
	return resp, err
}

// postResp makes a POST API call and decodes the response.
func postResp(call, vals string, obj interface{}) error {
	resp, err := apiPost(call, vals)
	if err != nil {
		return err
	}
	defer resp.Body.Close()
	err = json.NewDecoder(resp.Body).Decode(obj)
	if err != nil {
		return err
	}
	return nil
}

func post(call, vals string) error {
	resp, err := apiPost(call, vals)
	if err != nil {
		return err
	}
	resp.Body.Close()
	return nil
}

// wrap wraps a generic command with a check that the command has been
// passed the correct number of arguments. The command must take only strings
// as arguments.
func wrap(fn interface{}) func(*cobra.Command, []string) {
	fnVal, fnType := reflect.ValueOf(fn), reflect.TypeOf(fn)
	if fnType.Kind() != reflect.Func {
		panic("wrapped function has wrong type signature")
	}
	for i := 0; i < fnType.NumIn(); i++ {
		if fnType.In(i).Kind() != reflect.String {
			panic("wrapped function has wrong type signature")
		}
	}

	return func(cmd *cobra.Command, args []string) {
		if len(args) != fnType.NumIn() {
			cmd.Usage()
			return
		}
		argVals := make([]reflect.Value, fnType.NumIn())
		for i := range args {
			argVals[i] = reflect.ValueOf(args[i])
		}
		fnVal.Call(argVals)
	}
}

func version(*cobra.Command, []string) {
	println("Sia Client v" + build.Version)
}

func main() {
	root := &cobra.Command{
		Use:   os.Args[0],
		Short: "Sia Client v" + build.Version,
		Long:  "Sia Client v" + build.Version,
		Run:   version,
	}

	// create command tree
	root.AddCommand(&cobra.Command{
		Use:   "version",
		Short: "Print version information",
		Long:  "Print version information.",
		Run:   version,
	})

	root.AddCommand(hostCmd)
	hostCmd.AddCommand(hostConfigCmd, hostAnnounceCmd, hostStatusCmd)

	root.AddCommand(hostdbCmd)
	hostCmd.AddCommand(hostdbCmd)

	root.AddCommand(minerCmd)
	minerCmd.AddCommand(minerStartCmd, minerStopCmd, minerStatusCmd)

	root.AddCommand(walletCmd)
	walletCmd.AddCommand(walletAddressCmd, walletAddressesCmd, walletAddseedCmd, walletInitCmd, walletLoad033xCmd, walletLockCmd, walletSeedsCmd, walletSendCmd, walletStatusCmd, walletUnlockCmd)
	walletInitCmd.Flags().BoolVarP(&initPassword, "password", "p", false, "Prompt for a custom password")

	root.AddCommand(renterCmd)
	renterCmd.AddCommand(renterDownloadQueueCmd, renterFilesDeleteCmd, renterFilesDownloadCmd,
		renterFilesListCmd, renterFilesLoadCmd, renterFilesLoadASCIICmd, renterFilesRenameCmd,
		renterFilesShareCmd, renterFilesShareASCIICmd, renterFilesUploadCmd)

	root.AddCommand(gatewayCmd)
	gatewayCmd.AddCommand(gatewayAddCmd, gatewayRemoveCmd, gatewayStatusCmd)

	root.AddCommand(updateCmd)
	updateCmd.AddCommand(updateCheckCmd, updateApplyCmd)

	// consensus cmds have no leading qualifier
	root.AddCommand(consensusStatusCmd)
	root.AddCommand(stopCmd)

	// parse flags
	root.PersistentFlags().StringVarP(&addr, "addr", "a", "localhost:9980", "which host/port to communicate with (i.e. the host/port siad is listening on)")
	root.PersistentFlags().BoolVarP(&force, "force", "f", false, "force certain commands")

	// run
	root.Execute()
}
<commit_msg>Best practices<commit_after>package main

import (
	"encoding/json"
	"errors"
	"io/ioutil"
	"net"
	"net/http"
	"os"
	"reflect"
	"strings"

	"github.com/spf13/cobra"

	"github.com/NebulousLabs/Sia/build"
)

var (
	addr         string
	force        bool
	initPassword bool
)

// apiGet wraps a GET request with a status code check, such that if the GET does
// not return 200, the error will be read and returned. The response body is
// not closed.
func apiGet(call string) (*http.Response, error) {
	if host, port, _ := net.SplitHostPort(addr); host == "" {
		addr = net.JoinHostPort("localhost", port)
	}
	client := &http.Client{}
	req, _ := http.NewRequest("GET", "http://"+addr+call, nil)
	req.Header.Add("User-Agent", "Sia-Agent")
	resp, err := client.Do(req)
	if err != nil {
		return nil, errors.New("no response from daemon")
	}
	// check error code
	if resp.StatusCode == http.StatusNotFound {
		resp.Body.Close()
		err = errors.New("API call not recognized: " + call)
	} else if resp.StatusCode != http.StatusOK {
		errResp, _ := ioutil.ReadAll(resp.Body)
		resp.Body.Close()
		err = errors.New(strings.TrimSpace(string(errResp)))
	}
	return resp, err
}

// getAPI makes a GET API call and decodes the response.
func getAPI(call string, obj interface{}) error {
	resp, err := apiGet(call)
	if err != nil {
		return err
	}
	defer resp.Body.Close()
	err = json.NewDecoder(resp.Body).Decode(obj)
	if err != nil {
		return err
	}
	return nil
}

// get makes an API call and discards the response.
func get(call string) error {
	resp, err := apiGet(call)
	if err != nil {
		return err
	}
	resp.Body.Close()
	return nil
}

// apiPost wraps a POST request with a status code check, such that if the POST
// does not return 200, the error will be read and returned. The response body
// is not closed.
func apiPost(call, vals string) (*http.Response, error) {
	if host, port, _ := net.SplitHostPort(addr); host == "" {
		addr = net.JoinHostPort("localhost", port)
	}

	client := &http.Client{}
	req, _ := http.NewRequest("POST", "http://"+addr+call, strings.NewReader(vals))
	req.Header.Add("User-Agent", "Sia-Agent")
	req.Header.Add("Content-Type", "application/x-www-form-urlencoded")
	resp, err := client.Do(req)
	if err != nil {
		return nil, errors.New("no response from daemon")
	}
	// check error code
	if resp.StatusCode == http.StatusNotFound {
		resp.Body.Close()
		err = errors.New("API call not recognized: " + call)
	} else if resp.StatusCode != http.StatusOK {
		errResp, _ := ioutil.ReadAll(resp.Body)
		resp.Body.Close()
		err = errors.New(strings.TrimSpace(string(errResp)))
	}
	return resp, err
}

// postResp makes a POST API call and decodes the response.
func postResp(call, vals string, obj interface{}) error {
	resp, err := apiPost(call, vals)
	if err != nil {
		return err
	}
	defer resp.Body.Close()
	err = json.NewDecoder(resp.Body).Decode(obj)
	if err != nil {
		return err
	}
	return nil
}

func post(call, vals string) error {
	resp, err := apiPost(call, vals)
	if err != nil {
		return err
	}
	resp.Body.Close()
	return nil
}

// wrap wraps a generic command with a check that the command has been
// passed the correct number of arguments. The command must take only strings
// as arguments.
func wrap(fn interface{}) func(*cobra.Command, []string) {
	fnVal, fnType := reflect.ValueOf(fn), reflect.TypeOf(fn)
	if fnType.Kind() != reflect.Func {
		panic("wrapped function has wrong type signature")
	}
	for i := 0; i < fnType.NumIn(); i++ {
		if fnType.In(i).Kind() != reflect.String {
			panic("wrapped function has wrong type signature")
		}
	}

	return func(cmd *cobra.Command, args []string) {
		if len(args) != fnType.NumIn() {
			cmd.Usage()
			return
		}
		argVals := make([]reflect.Value, fnType.NumIn())
		for i := range args {
			argVals[i] = reflect.ValueOf(args[i])
		}
		fnVal.Call(argVals)
	}
}

func version(*cobra.Command, []string) {
	println("Sia Client v" + build.Version)
}

func main() {
	root := &cobra.Command{
		Use:   os.Args[0],
		Short: "Sia Client v" + build.Version,
		Long:  "Sia Client v" + build.Version,
		Run:   version,
	}

	// create command tree
	root.AddCommand(&cobra.Command{
		Use:   "version",
		Short: "Print version information",
		Long:  "Print version information.",
		Run:   version,
	})

	root.AddCommand(hostCmd)
	hostCmd.AddCommand(hostConfigCmd, hostAnnounceCmd, hostStatusCmd)

	root.AddCommand(hostdbCmd)
	hostCmd.AddCommand(hostdbCmd)

	root.AddCommand(minerCmd)
	minerCmd.AddCommand(minerStartCmd, minerStopCmd, minerStatusCmd)

	root.AddCommand(walletCmd)
	walletCmd.AddCommand(walletAddressCmd, walletAddressesCmd, walletAddseedCmd, walletInitCmd, walletLoad033xCmd, walletLockCmd, walletSeedsCmd, walletSendCmd, walletStatusCmd, walletUnlockCmd)
	walletInitCmd.Flags().BoolVarP(&initPassword, "password", "p", false, "Prompt for a custom password")

	root.AddCommand(renterCmd)
	renterCmd.AddCommand(renterDownloadQueueCmd, renterFilesDeleteCmd, renterFilesDownloadCmd,
		renterFilesListCmd, renterFilesLoadCmd, renterFilesLoadASCIICmd, renterFilesRenameCmd,
		renterFilesShareCmd, renterFilesShareASCIICmd, renterFilesUploadCmd)

	root.AddCommand(gatewayCmd)
	gatewayCmd.AddCommand(gatewayAddCmd, gatewayRemoveCmd, gatewayStatusCmd)

	root.AddCommand(updateCmd)
	updateCmd.AddCommand(updateCheckCmd, updateApplyCmd)

	// consensus cmds have no leading qualifier
	root.AddCommand(consensusStatusCmd)
	root.AddCommand(stopCmd)

	// parse flags
	root.PersistentFlags().StringVarP(&addr, "addr", "a", "localhost:9980", "which host/port to communicate with (i.e. the host/port siad is listening on)")
	root.PersistentFlags().BoolVarP(&force, "force", "f", false, "force certain commands")

	// run
	root.Execute()
}
<|endoftext|>


<commit_before>// Package coreunsafe contains Core logic that is unsafe for
// production.
//
// It is used in the Developer Edition and in command-line
// utilities but shouldn't be used in production.
package coreunsafe

import (
	"context"
	"expvar"

	"chain/database/pg"
	"chain/errors"
)

func isProduction() bool {
	bt := expvar.Get("buildtag")
	return bt != nil && bt.String() != `"dev"`
}

// ResetBlockchain deletes all blockchain data, resulting in an
// unconfigured core. It does not delete access tokens or mockhsm
// keys.
func ResetBlockchain(ctx context.Context, db pg.DB) error {
	if isProduction() {
		// Shouldn't ever happen; This package shouldn't even be
		// included in a production binary.
		panic("reset called on production")
	}

	const q = `
		TRUNCATE
			account_control_programs,
			account_utxos,
			accounts,
			annotated_accounts,
			annotated_assets,
			annotated_outputs,
			annotated_txs,
			asset_tags,
			assets,
			block_processors,
			blocks,
			config,
			generator_pending_block,
			leader,
			pool_txs,
			query_blocks,
			reservations,
			signed_blocks,
			signers,
			snapshots,
			submitted_txs,
			txfeeds
			RESTART IDENTITY;
	`
	_, err := db.Exec(ctx, q)
	return errors.Wrap(err)
}

// ResetEverything deletes all of a Core's data.
func ResetEverything(ctx context.Context, db pg.DB) error {
	if isProduction() {
		// Shouldn't ever happen; This package shouldn't even be
		// included in a production binary.
		panic("reset called on production")
	}

	err := ResetBlockchain(ctx, db)
	if err != nil {
		return errors.Wrap(err)
	}

	const q = `TRUNCATE mockhsm, access_tokens RESTART IDENTITY;`
	_, err = db.Exec(ctx, q)
	return errors.Wrap(err)
}
<commit_msg>core/coreunsafe: remove explicit truncate list<commit_after>// Package coreunsafe contains Core logic that is unsafe for
// production.
//
// It is used in the Developer Edition and in command-line
// utilities but shouldn't be used in production.
package coreunsafe

import (
	"context"
	"expvar"
	"fmt"
	"strings"

	"github.com/lib/pq"

	"chain/database/pg"
	"chain/errors"
)

var (
	persistBlockchainReset = []string{"mockhsm", "access_tokens"}
	neverReset             = []string{"migrations"}
)

func isProduction() bool {
	bt := expvar.Get("buildtag")
	return bt != nil && bt.String() != `"dev"`
}

// ResetBlockchain deletes all blockchain data, resulting in an
// unconfigured core. It does not delete access tokens or mockhsm
// keys.
func ResetBlockchain(ctx context.Context, db pg.DB) error {
	if isProduction() {
		// Shouldn't ever happen; This package shouldn't even be
		// included in a production binary.
		panic("reset called on production")
	}

	var skip []string
	skip = append(skip, persistBlockchainReset...)
	skip = append(skip, neverReset...)

	const tableQ = `
		SELECT table_name
		FROM information_schema.tables
		WHERE table_schema='public' AND NOT (table_name=ANY($1::text[]))
	`
	var tables []string
	err := pg.ForQueryRows(ctx, db, tableQ, pq.StringArray(skip), func(table string) {
		tables = append(tables, table)
	})
	if err != nil {
		return errors.Wrap(err)
	}

	const q = `TRUNCATE %s RESTART IDENTITY;`
	_, err = db.Exec(ctx, fmt.Sprintf(q, strings.Join(tables, ", ")))
	return errors.Wrap(err)
}

// ResetEverything deletes all of a Core's data.
func ResetEverything(ctx context.Context, db pg.DB) error {
	if isProduction() {
		// Shouldn't ever happen; This package shouldn't even be
		// included in a production binary.
		panic("reset called on production")
	}

	err := ResetBlockchain(ctx, db)
	if err != nil {
		return errors.Wrap(err)
	}

	const q = `TRUNCATE %s RESTART IDENTITY;`
	_, err = db.Exec(ctx, fmt.Sprintf(q, strings.Join(persistBlockchainReset, ", ")))
	return errors.Wrap(err)
}
<|endoftext|>


<commit_before>package ping

import (
	"github.com/Sirupsen/logrus"
	"github.com/docker/docker/api/types"
	"github.com/docker/docker/client"
	"github.com/pkg/errors"
	"github.com/rancher/agent/core/hostInfo"
	"github.com/rancher/agent/model"
	"github.com/rancher/agent/utilities/config"
	"github.com/rancher/agent/utilities/constants"
	"github.com/rancher/agent/utilities/utils"
	revents "github.com/rancher/event-subscriber/events"
	"github.com/shirou/gopsutil/disk"
	"golang.org/x/net/context"
	"net"
	"os"
	"strconv"
	"strings"
	"time"
)

func addResource(ping *revents.Event, pong *model.PingResponse, dockerClient *client.Client, collectors []hostInfo.Collector) error {
	if !pingIncludeResource(ping) {
		return nil
	}
	stats := map[string]interface{}{}
	if pingIncludeStats(ping) {
		data := hostInfo.CollectData(collectors)
		stats = data
	}

	physicalHost, err := config.PhysicalHost()
	if err != nil {
		return errors.Wrap(err, constants.AddResourceError+"failed to get physical host")
	}

	hostname, err := config.Hostname()
	if err != nil {
		return errors.Wrap(err, constants.AddResourceError+"failed to get hostname")
	}
	labels, err := getHostLabels(collectors)
	if err != nil {
		logrus.Warnf("Failed to get Host Labels err msg: %v", err.Error())
	}
	rancherImage := os.Getenv("RANCHER_AGENT_IMAGE")
	labels[constants.RancherAgentImage] = rancherImage
	uuid, err := config.DockerUUID()
	if err != nil {
		return errors.Wrap(err, constants.AddResourceError+"failed to get docker UUID")
	}
	compute := model.PingResource{
		Type:             "host",
		Kind:             "docker",
		HostName:         hostname,
		CreateLabels:     config.Labels(),
		Labels:           labels,
		UUID:             uuid,
		PhysicalHostUUID: physicalHost.UUID,
		Info:             stats,
		APIProxy:         config.HostProxy(),
	}

	if memOverride := getResourceOverride("CATTLE_MEMORY_OVERRIDE"); memOverride != 0 {
		compute.Memory = memOverride
	} else if stats["memoryInfo"] != nil {
		if memTotal, ok := stats["memoryInfo"].(map[string]interface{})["memTotal"]; ok {
			compute.Memory = memTotal.(uint64) * 1024 * 1024
		}
	}

	if cpuOverride := getResourceOverride("CATTLE_MILLI_CPU_OVERRIDE"); cpuOverride != 0 {
		compute.MilliCPU = cpuOverride
	} else if stats["cpuInfo"] != nil {
		if cpuCount, ok := stats["cpuInfo"].(map[string]interface{})["count"].(int); ok {
			compute.MilliCPU = uint64(cpuCount) * 1000
		}
	}

	if storageOverride := getResourceOverride("CATTLE_LOCAL_STORAGE_MB_OVERRIDE"); storageOverride != 0 {
		compute.LocalStorageMb = storageOverride
	} else {
		usage, err := disk.Usage(".")
		if err != nil {
			logrus.Errorf("Error getting local storage usage: %v", err)
		} else {
			compute.LocalStorageMb = uint64(usage.Free) / 1000
		}
	}

	pool := model.PingResource{
		Type:     "storagePool",
		Kind:     "docker",
		Name:     compute.HostName + " Storage Pool",
		HostUUID: compute.UUID,
		UUID:     compute.UUID + "-pool",
	}

	resolvedIP, err := net.LookupIP(config.DockerHostIP())
	ipAddr := ""
	if err != nil {
		logrus.Warn(err)
	} else {
		ipAddr = resolvedIP[0].String()
	}
	ip := model.PingResource{
		Type:     "ipAddress",
		UUID:     ipAddr,
		Addresss: ipAddr,
		HostUUID: compute.UUID,
	}
	pong.Resources = append(pong.Resources, physicalHost, compute, pool, ip)
	return nil
}

func getResourceOverride(envVar string) uint64 {
	var resource uint64
	var err error
	if val := os.Getenv(envVar); val != "" {
		resource, err = strconv.ParseUint(val, 10, 64)
		if err != nil {
			logrus.Warnf("Couldn't parse %v %v. Will not use it.", envVar, val)
			return 0
		}
	}
	return resource
}

func addInstance(ping *revents.Event, pong *model.PingResponse, dockerClient *client.Client) error {
	if !pingIncludeInstance(ping) {
		return nil
	}
	uuid, err := config.DockerUUID()
	if err != nil {
		return errors.Wrap(err, constants.AddInstanceError+"failed to get docker UUID")
	}
	pong.Resources = append(pong.Resources, model.PingResource{
		Type: "hostUuid",
		UUID: uuid,
	})
	containers := []model.PingResource{}

	// if we can not get all container in 2s, we will skip it
	done := make(chan bool, 1)
	timeout := make(chan bool, 1)
	go func() {
		time.Sleep(2 * time.Second)
		timeout <- true
	}()
	running, nonrunning, err := getAllContainerByState(dockerClient, done)
	select {
	case <-done:
		if err != nil {
			return errors.Wrap(err, constants.AddInstanceError+"failed to get all containers")
		}
		for _, container := range running {
			containers = utils.AddContainer("running", container, containers, dockerClient)
		}
		for _, container := range nonrunning {
			containers = utils.AddContainer("stopped", container, containers, dockerClient)
		}
		pong.Resources = append(pong.Resources, containers...)
		pong.Options.Instances = true
		return nil
	case <-timeout:
		logrus.Warn("Can not get response from docker daemon")
		return nil
	}
}

func pingIncludeResource(ping *revents.Event) bool {
	value, ok := utils.GetFieldsIfExist(ping.Data, "options", "resources")
	if !ok {
		return false
	}
	return utils.InterfaceToBool(value)
}

func pingIncludeStats(ping *revents.Event) bool {
	value, ok := utils.GetFieldsIfExist(ping.Data, "options", "stats")
	if !ok {
		return false
	}
	return utils.InterfaceToBool(value)
}

func pingIncludeInstance(ping *revents.Event) bool {
	value, ok := utils.GetFieldsIfExist(ping.Data, "options", "instances")
	if !ok {
		return false
	}
	return utils.InterfaceToBool(value)
}

func getHostLabels(collectors []hostInfo.Collector) (map[string]string, error) {
	return hostInfo.HostLabels("io.rancher.host", collectors)
}

func getAllContainerByState(dockerClient *client.Client, done chan bool) (map[string]types.Container, map[string]types.Container, error) {
	// avoid calling API twice
	nonrunningContainers := map[string]types.Container{}
	containerList, err := dockerClient.ContainerList(context.Background(), types.ContainerListOptions{All: true})
	if err != nil {
		return map[string]types.Container{}, map[string]types.Container{}, errors.Wrap(err, constants.GetAllContainerByStateError+"failed to list containers")
	}
	for _, c := range containerList {
		if c.Status != "" && c.Status != "Created" {
			nonrunningContainers[c.ID] = c
		}
	}
	runningContainers := map[string]types.Container{}
	// if status is running, it is a running container
	for _, c := range containerList {
		if strings.Contains(c.Status, "Up") || c.State == "Running" {
			runningContainers[c.ID] = c
			delete(nonrunningContainers, c.ID)
		}
	}
	done <- true
	return runningContainers, nonrunningContainers, nil
}
<commit_msg>populate io.rancher.scheduler.ips label in each host<commit_after>package ping

import (
	"github.com/Sirupsen/logrus"
	"github.com/docker/docker/api/types"
	"github.com/docker/docker/client"
	"github.com/pkg/errors"
	"github.com/rancher/agent/core/hostInfo"
	"github.com/rancher/agent/model"
	"github.com/rancher/agent/utilities/config"
	"github.com/rancher/agent/utilities/constants"
	"github.com/rancher/agent/utilities/utils"
	revents "github.com/rancher/event-subscriber/events"
	"github.com/shirou/gopsutil/disk"
	"golang.org/x/net/context"
	"net"
	"os"
	"strconv"
	"strings"
	"time"
)

const (
	ipLabel    = "io.rancher.scheduler.ips"
	agentImage = "RANCHER_AGENT_IMAGE"
	ipset      = "CATTLE_SCHEDULER_IPS"
)

func addResource(ping *revents.Event, pong *model.PingResponse, dockerClient *client.Client, collectors []hostInfo.Collector) error {
	if !pingIncludeResource(ping) {
		return nil
	}
	stats := map[string]interface{}{}
	if pingIncludeStats(ping) {
		data := hostInfo.CollectData(collectors)
		stats = data
	}

	physicalHost, err := config.PhysicalHost()
	if err != nil {
		return errors.Wrap(err, constants.AddResourceError+"failed to get physical host")
	}

	hostname, err := config.Hostname()
	if err != nil {
		return errors.Wrap(err, constants.AddResourceError+"failed to get hostname")
	}
	labels, err := getHostLabels(collectors)
	if err != nil {
		logrus.Warnf("Failed to get Host Labels err msg: %v", err.Error())
	}
	rancherImage := os.Getenv(agentImage)
	labels[constants.RancherAgentImage] = rancherImage
	if os.Getenv(ipset) != "" {
		labels[ipLabel] = os.Getenv(ipset)
	}
	uuid, err := config.DockerUUID()
	if err != nil {
		return errors.Wrap(err, constants.AddResourceError+"failed to get docker UUID")
	}
	compute := model.PingResource{
		Type:             "host",
		Kind:             "docker",
		HostName:         hostname,
		CreateLabels:     config.Labels(),
		Labels:           labels,
		UUID:             uuid,
		PhysicalHostUUID: physicalHost.UUID,
		Info:             stats,
		APIProxy:         config.HostProxy(),
	}

	if memOverride := getResourceOverride("CATTLE_MEMORY_OVERRIDE"); memOverride != 0 {
		compute.Memory = memOverride
	} else if stats["memoryInfo"] != nil {
		if memTotal, ok := stats["memoryInfo"].(map[string]interface{})["memTotal"]; ok {
			compute.Memory = memTotal.(uint64) * 1024 * 1024
		}
	}

	if cpuOverride := getResourceOverride("CATTLE_MILLI_CPU_OVERRIDE"); cpuOverride != 0 {
		compute.MilliCPU = cpuOverride
	} else if stats["cpuInfo"] != nil {
		if cpuCount, ok := stats["cpuInfo"].(map[string]interface{})["count"].(int); ok {
			compute.MilliCPU = uint64(cpuCount) * 1000
		}
	}

	if storageOverride := getResourceOverride("CATTLE_LOCAL_STORAGE_MB_OVERRIDE"); storageOverride != 0 {
		compute.LocalStorageMb = storageOverride
	} else {
		usage, err := disk.Usage(".")
		if err != nil {
			logrus.Errorf("Error getting local storage usage: %v", err)
		} else {
			compute.LocalStorageMb = uint64(usage.Free) / 1000
		}
	}

	pool := model.PingResource{
		Type:     "storagePool",
		Kind:     "docker",
		Name:     compute.HostName + " Storage Pool",
		HostUUID: compute.UUID,
		UUID:     compute.UUID + "-pool",
	}

	resolvedIP, err := net.LookupIP(config.DockerHostIP())
	ipAddr := ""
	if err != nil {
		logrus.Warn(err)
	} else {
		ipAddr = resolvedIP[0].String()
	}
	ip := model.PingResource{
		Type:     "ipAddress",
		UUID:     ipAddr,
		Addresss: ipAddr,
		HostUUID: compute.UUID,
	}
	pong.Resources = append(pong.Resources, physicalHost, compute, pool, ip)
	return nil
}

func getResourceOverride(envVar string) uint64 {
	var resource uint64
	var err error
	if val := os.Getenv(envVar); val != "" {
		resource, err = strconv.ParseUint(val, 10, 64)
		if err != nil {
			logrus.Warnf("Couldn't parse %v %v. Will not use it.", envVar, val)
			return 0
		}
	}
	return resource
}

func addInstance(ping *revents.Event, pong *model.PingResponse, dockerClient *client.Client) error {
	if !pingIncludeInstance(ping) {
		return nil
	}
	uuid, err := config.DockerUUID()
	if err != nil {
		return errors.Wrap(err, constants.AddInstanceError+"failed to get docker UUID")
	}
	pong.Resources = append(pong.Resources, model.PingResource{
		Type: "hostUuid",
		UUID: uuid,
	})
	containers := []model.PingResource{}

	// if we can not get all container in 2s, we will skip it
	done := make(chan bool, 1)
	timeout := make(chan bool, 1)
	go func() {
		time.Sleep(2 * time.Second)
		timeout <- true
	}()
	running, nonrunning, err := getAllContainerByState(dockerClient, done)
	select {
	case <-done:
		if err != nil {
			return errors.Wrap(err, constants.AddInstanceError+"failed to get all containers")
		}
		for _, container := range running {
			containers = utils.AddContainer("running", container, containers, dockerClient)
		}
		for _, container := range nonrunning {
			containers = utils.AddContainer("stopped", container, containers, dockerClient)
		}
		pong.Resources = append(pong.Resources, containers...)
		pong.Options.Instances = true
		return nil
	case <-timeout:
		logrus.Warn("Can not get response from docker daemon")
		return nil
	}
}

func pingIncludeResource(ping *revents.Event) bool {
	value, ok := utils.GetFieldsIfExist(ping.Data, "options", "resources")
	if !ok {
		return false
	}
	return utils.InterfaceToBool(value)
}

func pingIncludeStats(ping *revents.Event) bool {
	value, ok := utils.GetFieldsIfExist(ping.Data, "options", "stats")
	if !ok {
		return false
	}
	return utils.InterfaceToBool(value)
}

func pingIncludeInstance(ping *revents.Event) bool {
	value, ok := utils.GetFieldsIfExist(ping.Data, "options", "instances")
	if !ok {
		return false
	}
	return utils.InterfaceToBool(value)
}

func getHostLabels(collectors []hostInfo.Collector) (map[string]string, error) {
	return hostInfo.HostLabels("io.rancher.host", collectors)
}

func getAllContainerByState(dockerClient *client.Client, done chan bool) (map[string]types.Container, map[string]types.Container, error) {
	// avoid calling API twice
	nonrunningContainers := map[string]types.Container{}
	containerList, err := dockerClient.ContainerList(context.Background(), types.ContainerListOptions{All: true})
	if err != nil {
		return map[string]types.Container{}, map[string]types.Container{}, errors.Wrap(err, constants.GetAllContainerByStateError+"failed to list containers")
	}
	for _, c := range containerList {
		if c.Status != "" && c.Status != "Created" {
			nonrunningContainers[c.ID] = c
		}
	}
	runningContainers := map[string]types.Container{}
	// if status is running, it is a running container
	for _, c := range containerList {
		if strings.Contains(c.Status, "Up") || c.State == "Running" {
			runningContainers[c.ID] = c
			delete(nonrunningContainers, c.ID)
		}
	}
	done <- true
	return runningContainers, nonrunningContainers, nil
}
<|endoftext|>


<commit_before>package bot

import (
	"fmt"
	"sync"

	"github.com/robfig/cron"
)

var taskRunner *cron.Cron
var schedMutex sync.Mutex

func scheduleTasks() {
	schedMutex.Lock()
	if taskRunner != nil {
		taskRunner.Stop()
	}
	botCfg.RLock()
	scheduled := botCfg.scheduledTasks
	tz := botCfg.timeZone
	botCfg.RUnlock()
	if tz != nil {
		Log(Info, fmt.Sprintf("Scheduling tasks in TimeZone: %s", tz))
		taskRunner = cron.NewWithLocation(tz)
	} else {
		Log(Info, "Scheduling tasks in system default timezone")
		taskRunner = cron.New()
	}
	currentTasks.Lock()
	tasks := taskList{
		currentTasks.t,
		currentTasks.nameMap,
		currentTasks.idMap,
		currentTasks.nameSpaces,
	}
	currentTasks.Unlock()
	confLock.RLock()
	repolist := repositories
	confLock.RUnlock()
	for _, st := range scheduled {
		t := tasks.getTaskByName(st.Name)
		if t == nil {
			Log(Error, fmt.Sprintf("Task not found when scheduling task: %s", st.Name))
			continue
		}
		task, _, _ := getTask(t)
		if task.Disabled {
			Log(Error, fmt.Sprintf("Not scheduling disabled task '%s'; reason: %s", st.Name, task.reason))
			continue
		}
		// NOTE: bare tasks ALWAYS have zero-length Channel, and can't be scheduled by design;
		// TODO: A task would only need a Channel to be scheduled
		if len(task.Channel) == 0 {
			Log(Error, fmt.Sprintf("Not scheduling task '%s'; zero-length Channel", st.Name))
			continue
		}
		Log(Info, fmt.Sprintf("Scheduling job '%s' with schedule: %s", st.Name, st.Schedule))
		taskRunner.AddFunc(st.Schedule, func() { runScheduledTask(t, st.taskSpec, tasks, repolist) })
	}
	taskRunner.Start()
	schedMutex.Unlock()
}

func runScheduledTask(t interface{}, ts taskSpec, tasks taskList, repolist map[string]repository) {
	task, plugin, _ := getTask(t)
	isPlugin := plugin != nil
	if isPlugin && len(ts.Command) == 0 {
		Log(Error, fmt.Sprintf("Empty 'Command' when running scheduled task '%s' of type plugin", ts.Name))
		return
	}

	// Create the botContext to carry state through the pipeline.
	// startPipeline will take care of registerActive()
	c := &botContext{
		Channel:          task.Channel,
		tasks:            tasks,
		repositories:     repolist,
		isCommand:        isPlugin,
		directMsg:        false,
		automaticTask:    true, // scheduled jobs don't get authorization / elevation checks
		workingDirectory: botCfg.workSpace,
		environment:      make(map[string]string),
	}
	var command string
	if isPlugin {
		command = ts.Command
	} else {
		command = "run"
	}
	Log(Debug, fmt.Sprintf("Starting scheduled task: %s", task.name))
	c.startPipeline(nil, t, scheduled, command, ts.Arguments...)
}
<commit_msg>Info logging for scheduled job starts<commit_after>package bot

import (
	"fmt"
	"sync"

	"github.com/robfig/cron"
)

var taskRunner *cron.Cron
var schedMutex sync.Mutex

func scheduleTasks() {
	schedMutex.Lock()
	if taskRunner != nil {
		taskRunner.Stop()
	}
	botCfg.RLock()
	scheduled := botCfg.scheduledTasks
	tz := botCfg.timeZone
	botCfg.RUnlock()
	if tz != nil {
		Log(Info, fmt.Sprintf("Scheduling tasks in TimeZone: %s", tz))
		taskRunner = cron.NewWithLocation(tz)
	} else {
		Log(Info, "Scheduling tasks in system default timezone")
		taskRunner = cron.New()
	}
	currentTasks.Lock()
	tasks := taskList{
		currentTasks.t,
		currentTasks.nameMap,
		currentTasks.idMap,
		currentTasks.nameSpaces,
	}
	currentTasks.Unlock()
	confLock.RLock()
	repolist := repositories
	confLock.RUnlock()
	for _, st := range scheduled {
		t := tasks.getTaskByName(st.Name)
		if t == nil {
			Log(Error, fmt.Sprintf("Task not found when scheduling task: %s", st.Name))
			continue
		}
		task, _, _ := getTask(t)
		if task.Disabled {
			Log(Error, fmt.Sprintf("Not scheduling disabled task '%s'; reason: %s", st.Name, task.reason))
			continue
		}
		// NOTE: bare tasks ALWAYS have zero-length Channel, and can't be scheduled by design;
		// TODO: A task would only need a Channel to be scheduled
		if len(task.Channel) == 0 {
			Log(Error, fmt.Sprintf("Not scheduling task '%s'; zero-length Channel", st.Name))
			continue
		}
		Log(Info, fmt.Sprintf("Scheduling job '%s' with schedule: %s", st.Name, st.Schedule))
		taskRunner.AddFunc(st.Schedule, func() { runScheduledTask(t, st.taskSpec, tasks, repolist) })
	}
	taskRunner.Start()
	schedMutex.Unlock()
}

func runScheduledTask(t interface{}, ts taskSpec, tasks taskList, repolist map[string]repository) {
	task, plugin, _ := getTask(t)
	isPlugin := plugin != nil
	if isPlugin && len(ts.Command) == 0 {
		Log(Error, fmt.Sprintf("Empty 'Command' when running scheduled task '%s' of type plugin", ts.Name))
		return
	}

	// Create the botContext to carry state through the pipeline.
	// startPipeline will take care of registerActive()
	c := &botContext{
		Channel:          task.Channel,
		tasks:            tasks,
		repositories:     repolist,
		isCommand:        isPlugin,
		directMsg:        false,
		automaticTask:    true, // scheduled jobs don't get authorization / elevation checks
		workingDirectory: botCfg.workSpace,
		environment:      make(map[string]string),
	}
	var command string
	if isPlugin {
		command = ts.Command
	} else {
		command = "run"
	}
	Log(Info, fmt.Sprintf("Starting scheduled task: %s", task.name))
	c.startPipeline(nil, t, scheduled, command, ts.Arguments...)
}
<|endoftext|>


<commit_before>// Copyright 2012, 2013 Canonical Ltd.
// Licensed under the AGPLv3, see LICENCE file for details.

package rpcreflect

import (
	"errors"
	"reflect"
	"sort"
	"sync"
)

var (
	errorType  = reflect.TypeOf((*error)(nil)).Elem()
	stringType = reflect.TypeOf("")
)

var (
	typeMutex     sync.RWMutex
	typesByGoType = make(map[reflect.Type]*Type)

	objTypeMutex     sync.RWMutex
	objTypesByGoType = make(map[reflect.Type]*ObjType)
)

var ErrMethodNotFound = errors.New("no such method")

// Type holds information about a type that implements RPC server methods,
// a root-level RPC type.
type Type struct {
	// root holds the root type.
	root reflect.Type

	// method maps from root-object method name to
	// information about that method. The term "obtain"
	// is because these methods obtain an object to
	// call an action on.
	method map[string]*RootMethod

	// discarded holds names of all discarded methods.
	discarded []string
}

// MethodNames returns the names of all the root object
// methods on the receiving object.
func (r *Type) MethodNames() []string {
	names := make([]string, 0, len(r.method))
	for name := range r.method {
		names = append(names, name)
	}
	sort.Strings(names)
	return names
}

// Method returns information on the method with the given name,
// or the zero Method and ErrMethodNotFound if there is no such method
// (the only possible error).
func (r *Type) Method(name string) (RootMethod, error) {
	m, ok := r.method[name]
	if !ok {
		return RootMethod{}, ErrMethodNotFound
	}
	return *m, nil
}

func (r *Type) DiscardedMethods() []string {
	return append([]string(nil), r.discarded...)
}

// RootMethod holds information on a root-level method.
type RootMethod struct {
	// Call invokes the method. The rcvr parameter must be
	// the same type as the root object. The given id is passed
	// as an argument to the method.
	Call func(rcvr reflect.Value, id string) (reflect.Value, error)

	// Methods holds RPC object-method information about
	// objects returned from the above call.
	ObjType *ObjType
}

// TypeOf returns information on all root-level RPC methods
// implemented by an object of the given Go type.
// If goType is nil, it returns nil.
func TypeOf(goType reflect.Type) *Type {
	if goType == nil {
		return nil
	}
	typeMutex.RLock()
	t := typesByGoType[goType]
	typeMutex.RUnlock()
	if t != nil {
		return t
	}
	typeMutex.Lock()
	defer typeMutex.Unlock()
	t = typesByGoType[goType]
	if t != nil {
		return t
	}
	t = typeOf(goType)
	typesByGoType[goType] = t
	return t
}

// typeOf is like TypeOf but without the cache - it
// always allocates. Called with rootTypeMutex locked.
func typeOf(goType reflect.Type) *Type {
	rm := &Type{
		method: make(map[string]*RootMethod),
	}
	for i := 0; i < goType.NumMethod(); i++ {
		m := goType.Method(i)
		if m.PkgPath != "" || isKillMethod(m) {
			// The Kill method gets a special exception because
			// it fulfils the Killer interface which we're expecting,
			// so it's not really discarded as such.
			continue
		}
		if o := newRootMethod(m); o != nil {
			rm.method[m.Name] = o
		} else {
			rm.discarded = append(rm.discarded, m.Name)
		}
	}
	return rm
}

func isKillMethod(m reflect.Method) bool {
	return m.Name == "Kill" && m.Type.NumIn() == 1 && m.Type.NumOut() == 0
}

func newRootMethod(m reflect.Method) *RootMethod {
	if m.PkgPath != "" {
		return nil
	}
	t := m.Type
	if t.NumIn() != 2 ||
		t.NumOut() != 2 ||
		t.In(1) != stringType ||
		t.Out(1) != errorType {
		return nil
	}
	f := func(rcvr reflect.Value, id string) (r reflect.Value, err error) {
		out := rcvr.Method(m.Index).Call([]reflect.Value{reflect.ValueOf(id)})
		if !out[1].IsNil() {
			err = out[1].Interface().(error)
		}
		r = out[0]
		return
	}
	return &RootMethod{
		Call:    f,
		ObjType: ObjTypeOf(t.Out(0)),
	}
}

// ObjType holds information on RPC methods implemented on
// an RPC object.
type ObjType struct {
	goType    reflect.Type
	method    map[string]*ObjMethod
	discarded []string
}

func (t *ObjType) GoType() reflect.Type {
	return t.goType
}

// Method returns information on the method with the given name,
// or the zero Method and ErrMethodNotFound if there is no such method
// (the only possible error).
func (t *ObjType) Method(name string) (ObjMethod, error) {
	m, ok := t.method[name]
	if !ok {
		return ObjMethod{}, ErrMethodNotFound
	}
	return *m, nil
}

// DiscardedMethods returns the names of all methods that cannot
// implement RPC calls because their type signature is inappropriate.
func (t *ObjType) DiscardedMethods() []string {
	return append([]string(nil), t.discarded...)
}

// MethodNames returns the names of all the RPC methods
// defined on the type.
func (t *ObjType) MethodNames() []string {
	names := make([]string, 0, len(t.method))
	for name := range t.method {
		names = append(names, name)
	}
	sort.Strings(names)
	return names
}

// ObjMethod holds information about an RPC method on an
// object returned by a root-level method.
type ObjMethod struct {
	// Params holds the argument type of the method, or nil
	// if there is no argument.
	Params reflect.Type

	// Result holds the return type of the method, or nil
	// if the method returns no value.
	Result reflect.Type

	// Call calls the method with the given argument
	// on the given receiver value. If the method does
	// not return a value, the returned value will not be valid.
	Call func(rcvr, arg reflect.Value) (reflect.Value, error)
}

// ObjTypeOf returns information on all RPC methods
// implemented by an object of the given Go type,
// as returned from a root-level method.
// If objType is nil, it returns nil.
func ObjTypeOf(objType reflect.Type) *ObjType {
	if objType == nil {
		return nil
	}
	objTypeMutex.RLock()
	methods := objTypesByGoType[objType]
	objTypeMutex.RUnlock()
	if methods != nil {
		return methods
	}
	objTypeMutex.Lock()
	defer objTypeMutex.Unlock()
	methods = objTypesByGoType[objType]
	if methods != nil {
		return methods
	}
	methods = objTypeOf(objType)
	objTypesByGoType[objType] = methods
	return methods
}

// objTypeOf is like ObjTypeOf but without the cache.
// Called with objTypeMutex locked.
func objTypeOf(goType reflect.Type) *ObjType {
	objType := &ObjType{
		method: make(map[string]*ObjMethod),
		goType: goType,
	}
	for i := 0; i < goType.NumMethod(); i++ {
		m := goType.Method(i)
		if m.PkgPath != "" {
			continue
		}
		if objm := newMethod(m, goType.Kind()); objm != nil {
			objType.method[m.Name] = objm
		} else {
			objType.discarded = append(objType.discarded, m.Name)
		}
	}
	return objType
}

func newMethod(m reflect.Method, receiverKind reflect.Kind) *ObjMethod {
	if m.PkgPath != "" {
		return nil
	}
	var p ObjMethod
	var assemble func(arg reflect.Value) []reflect.Value
	// N.B. The method type has the receiver as its first argument
	// unless the receiver is an interface.
	receiverArgCount := 1
	if receiverKind == reflect.Interface {
		receiverArgCount = 0
	}
	t := m.Type
	switch {
	case t.NumIn() == 0+receiverArgCount:
		// Method() ...
		assemble = func(arg reflect.Value) []reflect.Value {
			return nil
		}
	case t.NumIn() == 1+receiverArgCount:
		// Method(T) ...
		p.Params = t.In(receiverArgCount)
		assemble = func(arg reflect.Value) []reflect.Value {
			return []reflect.Value{arg}
		}
	default:
		return nil
	}

	switch {
	case t.NumOut() == 0:
		// Method(...)
		p.Call = func(rcvr, arg reflect.Value) (r reflect.Value, err error) {
			rcvr.Method(m.Index).Call(assemble(arg))
			return
		}
	case t.NumOut() == 1 && t.Out(0) == errorType:
		// Method(...) error
		p.Call = func(rcvr, arg reflect.Value) (r reflect.Value, err error) {
			out := rcvr.Method(m.Index).Call(assemble(arg))
			if !out[0].IsNil() {
				err = out[0].Interface().(error)
			}
			return
		}
	case t.NumOut() == 1:
		// Method(...) R
		p.Result = t.Out(0)
		p.Call = func(rcvr, arg reflect.Value) (reflect.Value, error) {
			out := rcvr.Method(m.Index).Call(assemble(arg))
			return out[0], nil
		}
	case t.NumOut() == 2 && t.Out(1) == errorType:
		// Method(...) (R, error)
		p.Result = t.Out(0)
		p.Call = func(rcvr, arg reflect.Value) (r reflect.Value, err error) {
			out := rcvr.Method(m.Index).Call(assemble(arg))
			r = out[0]
			if !out[1].IsNil() {
				err = out[1].Interface().(error)
			}
			return
		}
	default:
		return nil
	}
	// The parameters and return value must be of struct type.
	if p.Params != nil && p.Params.Kind() != reflect.Struct {
		return nil
	}
	if p.Result != nil && p.Result.Kind() != reflect.Struct {
		return nil
	}
	return &p
}
<commit_msg>Work around LP 1251076<commit_after>// Copyright 2012, 2013 Canonical Ltd.
// Licensed under the AGPLv3, see LICENCE file for details.

package rpcreflect

import (
	"errors"
	"reflect"
	"sort"
	"sync"
)

var (
	errorType  = reflect.TypeOf((*error)(nil)).Elem()
	stringType = reflect.TypeOf("")
)

var (
	typeMutex     sync.RWMutex
	typesByGoType = make(map[reflect.Type]*Type)

	objTypeMutex     sync.RWMutex
	objTypesByGoType = make(map[reflect.Type]*ObjType)
)

var ErrMethodNotFound = errors.New("no such method")

// Type holds information about a type that implements RPC server methods,
// a root-level RPC type.
type Type struct {
	// root holds the root type.
	root reflect.Type

	// method maps from root-object method name to
	// information about that method. The term "obtain"
	// is because these methods obtain an object to
	// call an action on.
	method map[string]*RootMethod

	// discarded holds names of all discarded methods.
	discarded []string
}

// MethodNames returns the names of all the root object
// methods on the receiving object.
func (r *Type) MethodNames() []string {
	names := make([]string, 0, len(r.method))
	for name := range r.method {
		names = append(names, name)
	}
	sort.Strings(names)
	return names
}

// Method returns information on the method with the given name,
// or the zero Method and ErrMethodNotFound if there is no such method
// (the only possible error).
func (r *Type) Method(name string) (RootMethod, error) {
	m, ok := r.method[name]
	if !ok {
		return RootMethod{}, ErrMethodNotFound
	}
	return *m, nil
}

func (r *Type) DiscardedMethods() []string {
	return append([]string(nil), r.discarded...)
}

// RootMethod holds information on a root-level method.
type RootMethod struct {
	// Call invokes the method. The rcvr parameter must be
	// the same type as the root object. The given id is passed
	// as an argument to the method.
	Call func(rcvr reflect.Value, id string) (reflect.Value, error)

	// Methods holds RPC object-method information about
	// objects returned from the above call.
	ObjType *ObjType
}

// TypeOf returns information on all root-level RPC methods
// implemented by an object of the given Go type.
// If goType is nil, it returns nil.
func TypeOf(goType reflect.Type) *Type {
	if goType == nil {
		return nil
	}
	typeMutex.RLock()
	t := typesByGoType[goType]
	typeMutex.RUnlock()
	if t != nil {
		return t
	}
	typeMutex.Lock()
	defer typeMutex.Unlock()
	t = typesByGoType[goType]
	if t != nil {
		return t
	}
	t = typeOf(goType)
	typesByGoType[goType] = t
	return t
}

// typeOf is like TypeOf but without the cache - it
// always allocates. Called with rootTypeMutex locked.
func typeOf(goType reflect.Type) *Type {
	rm := &Type{
		method: make(map[string]*RootMethod),
	}
	for i := 0; i < goType.NumMethod(); i++ {
		m := goType.Method(i)
		if m.PkgPath != "" || isKillMethod(m) {
			// The Kill method gets a special exception because
			// it fulfils the Killer interface which we're expecting,
			// so it's not really discarded as such.
			continue
		}
		if o := newRootMethod(m); o != nil {
			rm.method[m.Name] = o
		} else {
			rm.discarded = append(rm.discarded, m.Name)
		}
	}
	return rm
}

func isKillMethod(m reflect.Method) bool {
	return m.Name == "Kill" && m.Type.NumIn() == 1 && m.Type.NumOut() == 0
}

func newRootMethod(m reflect.Method) *RootMethod {
	if m.PkgPath != "" {
		return nil
	}
	t := m.Type
	if t.NumIn() != 2 ||
		t.NumOut() != 2 ||
		t.In(1) != stringType ||
		t.Out(1) != errorType {
		return nil
	}
	f := func(rcvr reflect.Value, id string) (r reflect.Value, err error) {
		out := rcvr.Method(m.Index).Call([]reflect.Value{reflect.ValueOf(id)})
		if !out[1].IsNil() {
			// Workaround LP 1251076.
			// gccgo appears to get confused and things that out[1] is not nil when
			// in fact it is an interface value of type error and value nil.
			// This workaround solves the problem by leaving error as nil if in fact
			// it was nil and causes no harm for gc because the predicates above
			// assert that if out[1] is not nil, then it is an error type.
			err, _ = out[1].Interface().(error)
		}
		r = out[0]
		return
	}
	return &RootMethod{
		Call:    f,
		ObjType: ObjTypeOf(t.Out(0)),
	}
}

// ObjType holds information on RPC methods implemented on
// an RPC object.
type ObjType struct {
	goType    reflect.Type
	method    map[string]*ObjMethod
	discarded []string
}

func (t *ObjType) GoType() reflect.Type {
	return t.goType
}

// Method returns information on the method with the given name,
// or the zero Method and ErrMethodNotFound if there is no such method
// (the only possible error).
func (t *ObjType) Method(name string) (ObjMethod, error) {
	m, ok := t.method[name]
	if !ok {
		return ObjMethod{}, ErrMethodNotFound
	}
	return *m, nil
}

// DiscardedMethods returns the names of all methods that cannot
// implement RPC calls because their type signature is inappropriate.
func (t *ObjType) DiscardedMethods() []string {
	return append([]string(nil), t.discarded...)
}

// MethodNames returns the names of all the RPC methods
// defined on the type.
func (t *ObjType) MethodNames() []string {
	names := make([]string, 0, len(t.method))
	for name := range t.method {
		names = append(names, name)
	}
	sort.Strings(names)
	return names
}

// ObjMethod holds information about an RPC method on an
// object returned by a root-level method.
type ObjMethod struct {
	// Params holds the argument type of the method, or nil
	// if there is no argument.
	Params reflect.Type

	// Result holds the return type of the method, or nil
	// if the method returns no value.
	Result reflect.Type

	// Call calls the method with the given argument
	// on the given receiver value. If the method does
	// not return a value, the returned value will not be valid.
	Call func(rcvr, arg reflect.Value) (reflect.Value, error)
}

// ObjTypeOf returns information on all RPC methods
// implemented by an object of the given Go type,
// as returned from a root-level method.
// If objType is nil, it returns nil.
func ObjTypeOf(objType reflect.Type) *ObjType {
	if objType == nil {
		return nil
	}
	objTypeMutex.RLock()
	methods := objTypesByGoType[objType]
	objTypeMutex.RUnlock()
	if methods != nil {
		return methods
	}
	objTypeMutex.Lock()
	defer objTypeMutex.Unlock()
	methods = objTypesByGoType[objType]
	if methods != nil {
		return methods
	}
	methods = objTypeOf(objType)
	objTypesByGoType[objType] = methods
	return methods
}

// objTypeOf is like ObjTypeOf but without the cache.
// Called with objTypeMutex locked.
func objTypeOf(goType reflect.Type) *ObjType {
	objType := &ObjType{
		method: make(map[string]*ObjMethod),
		goType: goType,
	}
	for i := 0; i < goType.NumMethod(); i++ {
		m := goType.Method(i)
		if m.PkgPath != "" {
			continue
		}
		if objm := newMethod(m, goType.Kind()); objm != nil {
			objType.method[m.Name] = objm
		} else {
			objType.discarded = append(objType.discarded, m.Name)
		}
	}
	return objType
}

func newMethod(m reflect.Method, receiverKind reflect.Kind) *ObjMethod {
	if m.PkgPath != "" {
		return nil
	}
	var p ObjMethod
	var assemble func(arg reflect.Value) []reflect.Value
	// N.B. The method type has the receiver as its first argument
	// unless the receiver is an interface.
	receiverArgCount := 1
	if receiverKind == reflect.Interface {
		receiverArgCount = 0
	}
	t := m.Type
	switch {
	case t.NumIn() == 0+receiverArgCount:
		// Method() ...
		assemble = func(arg reflect.Value) []reflect.Value {
			return nil
		}
	case t.NumIn() == 1+receiverArgCount:
		// Method(T) ...
		p.Params = t.In(receiverArgCount)
		assemble = func(arg reflect.Value) []reflect.Value {
			return []reflect.Value{arg}
		}
	default:
		return nil
	}

	switch {
	case t.NumOut() == 0:
		// Method(...)
		p.Call = func(rcvr, arg reflect.Value) (r reflect.Value, err error) {
			rcvr.Method(m.Index).Call(assemble(arg))
			return
		}
	case t.NumOut() == 1 && t.Out(0) == errorType:
		// Method(...) error
		p.Call = func(rcvr, arg reflect.Value) (r reflect.Value, err error) {
			out := rcvr.Method(m.Index).Call(assemble(arg))
			if !out[0].IsNil() {
				err = out[0].Interface().(error)
			}
			return
		}
	case t.NumOut() == 1:
		// Method(...) R
		p.Result = t.Out(0)
		p.Call = func(rcvr, arg reflect.Value) (reflect.Value, error) {
			out := rcvr.Method(m.Index).Call(assemble(arg))
			return out[0], nil
		}
	case t.NumOut() == 2 && t.Out(1) == errorType:
		// Method(...) (R, error)
		p.Result = t.Out(0)
		p.Call = func(rcvr, arg reflect.Value) (r reflect.Value, err error) {
			out := rcvr.Method(m.Index).Call(assemble(arg))
			r = out[0]
			if !out[1].IsNil() {
				err = out[1].Interface().(error)
			}
			return
		}
	default:
		return nil
	}
	// The parameters and return value must be of struct type.
	if p.Params != nil && p.Params.Kind() != reflect.Struct {
		return nil
	}
	if p.Result != nil && p.Result.Kind() != reflect.Struct {
		return nil
	}
	return &p
}
<|endoftext|>


<commit_before>package runtime

import (
	"math"

	"github.com/ta2gch/iris/runtime/environment"
	"github.com/ta2gch/iris/runtime/ilos"
	"github.com/ta2gch/iris/runtime/ilos/class"
	"github.com/ta2gch/iris/runtime/ilos/instance"
)

// The value of MostPositiveFloat is the implementation-dependent
// ﬂoating-point number closest to positive infinity.
//
// The value of MostNegativeFloat is the implementation-dependent
// ﬂoating-point number closest to negative infinity.
var (
	MostPositiveFloat = instance.New(class.Float, math.MaxFloat64)
	MostNegativeFloat = instance.New(class.Float, -math.MaxFloat64)
)

// Floatp returns t if obj is a ﬂoat (instance of class float);
// otherwise, returns nil. The obj may be any ISLISP object.
func Floatp(_, _ *environment.Environment, obj ilos.Instance) (ilos.Instance, ilos.Instance) {
	if instance.Of(class.Float, obj) {
		return T, nil
	}
	return Nil, nil
}

// Float returns x itself if it is an instance of the class float
// and returns a ﬂoating-point approximation of x otherwise.
// An error shall be signaled if x is not a number (error-id. domain-error).
func Float(_, _ *environment.Environment, x ilos.Instance) (ilos.Instance, ilos.Instance) {
	f, _, err := convFloat64(x)
	if err != nil {
		return nil, err
	}
	return instance.New(class.Float, f), nil
}

// Floor returns the greatest integer less than or equal to x .
// That is, x is truncated towards negative infinity. An error
// shall be signaled if x is not a number (error-id. domain-error).
func Floor(_, _ *environment.Environment, x ilos.Instance) (ilos.Instance, ilos.Instance) {
	f, _, err := convFloat64(x)
	if err != nil {
		return nil, err
	}
	return instance.New(class.Integer, int(math.Floor(f))), nil
}

// Ceiling Returns the smallest integer that is not smaller than x.
// That is, x is truncated towards positive infinity. An error
// shall be signaled if x is not a number (error-id. domain-error).
func Ceiling(_, _ *environment.Environment, x ilos.Instance) (ilos.Instance, ilos.Instance) {
	f, _, err := convFloat64(x)
	if err != nil {
		return nil, err
	}
	return instance.New(class.Integer, int(math.Ceil(f))), nil
}

// Truncate returns the integer between 0 and x (inclusive) that is nearest to x.
// That is, x is truncated towards zero. An error shall be signaled
// if x is not a number (error-id. domain-error).
func Truncate(_, _ *environment.Environment, x ilos.Instance) (ilos.Instance, ilos.Instance) {
	f, _, err := convFloat64(x)
	if err != nil {
		return nil, err
	}
	return instance.New(class.Integer, int(math.Trunc(f))), nil
}

// Round returns the integer nearest to x.
//  If x is exactly halfway between two integers, the even one is chosen.
// An error shall be signaled if x is not a number (error-id. domain-error).
func Round(_, _ *environment.Environment, x ilos.Instance) (ilos.Instance, ilos.Instance) {
	f, _, err := convFloat64(x)
	if err != nil {
		return nil, err
	}
	return instance.New(class.Integer, int(math.Floor(f+.5))), nil
}
<commit_msg>Changed comment<commit_after>package runtime

import (
	"math"

	"github.com/ta2gch/iris/runtime/environment"
	"github.com/ta2gch/iris/runtime/ilos"
	"github.com/ta2gch/iris/runtime/ilos/class"
	"github.com/ta2gch/iris/runtime/ilos/instance"
)

// The value of MostPositiveFloat is the implementation-dependent
// ﬂoating-point number closest to positive infinity.
//
// The value of MostNegativeFloat is the implementation-dependent
// ﬂoating-point number closest to negative infinity.
var (
	MostPositiveFloat = instance.New(class.Float, math.MaxFloat64)
	MostNegativeFloat = instance.New(class.Float, -math.MaxFloat64)
)

// Floatp returns t if obj is a ﬂoat (instance of class float);
// otherwise, returns nil. The obj may be any ISLISP object.
func Floatp(_, _ *environment.Environment, obj ilos.Instance) (ilos.Instance, ilos.Instance) {
	if instance.Of(class.Float, obj) {
		return T, nil
	}
	return Nil, nil
}

// Float returns x itself if it is an instance of the class float
// and returns a ﬂoating-point approximation of x otherwise.
// An error shall be signaled if x is not a number (error-id. domain-error).
func Float(_, _ *environment.Environment, x ilos.Instance) (ilos.Instance, ilos.Instance) {
	f, _, err := convFloat64(x)
	if err != nil {
		return nil, err
	}
	return instance.New(class.Float, f), nil
}

// Floor returns the greatest integer less than or equal to x .
// That is, x is truncated towards negative infinity. An error
// shall be signaled if x is not a number (error-id. domain-error).
func Floor(_, _ *environment.Environment, x ilos.Instance) (ilos.Instance, ilos.Instance) {
	f, _, err := convFloat64(x)
	if err != nil {
		return nil, err
	}
	return instance.New(class.Integer, int(math.Floor(f))), nil
}

// Ceiling Returns the smallest integer that is not smaller than x.
// That is, x is truncated towards positive infinity. An error
// shall be signaled if x is not a number (error-id. domain-error).
func Ceiling(_, _ *environment.Environment, x ilos.Instance) (ilos.Instance, ilos.Instance) {
	f, _, err := convFloat64(x)
	if err != nil {
		return nil, err
	}
	return instance.New(class.Integer, int(math.Ceil(f))), nil
}

// Truncate returns the integer between 0 and x (inclusive) that is nearest to x.
// That is, x is truncated towards zero. An error shall be signaled
// if x is not a number (error-id. domain-error).
func Truncate(_, _ *environment.Environment, x ilos.Instance) (ilos.Instance, ilos.Instance) {
	f, _, err := convFloat64(x)
	if err != nil {
		return nil, err
	}
	return instance.New(class.Integer, int(math.Trunc(f))), nil
}

// Round returns the integer nearest to x.
// If x is exactly halfway between two integers, the even one is chosen.
// An error shall be signaled if x is not a number (error-id. domain-error).
func Round(_, _ *environment.Environment, x ilos.Instance) (ilos.Instance, ilos.Instance) {
	f, _, err := convFloat64(x)
	if err != nil {
		return nil, err
	}
	return instance.New(class.Integer, int(math.Floor(f+.5))), nil
}
<|endoftext|>


<commit_before>package gossip

func TestWatcher(t *testing.T) {
	w := newWatcher()
}
<commit_msg>Remove file<commit_after><|endoftext|>


<commit_before>package main

import (
	"bufio"
	"io"
	"net"
	"os"
	"os/exec"
	"strings"

	"github.com/CyCoreSystems/radius"
	"github.com/pborman/uuid"
)

// fortuned is a TCP service for service up fortunes

func main() {

	ln, err := net.Listen("tcp", "0.0.0.0:9191")
	if err != nil {
		panic(err)
	}

	rc := radius.NewClient(&radius.Options{
		Host:         "localhost:1813",
		SharedSecret: "testing123",
	})

	for {
		conn, err := ln.Accept()
		if err != nil {
			panic(err)
		}

		id := uuid.New()
		h, _ := os.Hostname()
		session := rc.NewSession(id,
			radius.StringAttribute(radius.AccessUserName, "admin"),
			radius.StringAttribute(32, h), // NAS-Identifier
		)

		go handle(conn, session)
	}
}

func handle(conn io.ReadWriteCloser, session *radius.Session) {

	a := &acct{
		session: session,
		w:       conn,
		r:       conn,
		closer:  conn,
	}

	conn = a

	for {
		conn.Write([]byte(" > "))

		r := bufio.NewReader(a)
		line, err := r.ReadString('\n')
		if err != nil {
			return
		}

		line = strings.TrimSpace(line)
		switch line {
		case "quit":
			session.Stop(radius.UserRequest)
			conn.Close()
			return
		case "fortune":
			cmd := exec.Command("fortune")
			out, err := cmd.Output()
			if err != nil {
				conn.Write([]byte("error running fortune: "))
				conn.Write([]byte(err.Error()))
				conn.Write([]byte("\n"))
			} else {
				conn.Write(out)
			}
		case "cowsay":
			func() {

				cowsay := exec.Command("cowsay")
				cowsayInput, err := cowsay.StdinPipe()
				if err != nil {
					conn.Write([]byte("error running cowsay: "))
					conn.Write([]byte(err.Error()))
					conn.Write([]byte("\n"))
					return
				}
				cowsayOutput, err := cowsay.StdoutPipe()
				if err != nil {
					conn.Write([]byte("error running cowsay: "))
					conn.Write([]byte(err.Error()))
					conn.Write([]byte("\n"))
					return
				}

				cowsay.Start()

				fortune := exec.Command("fortune")
				body, err := fortune.Output()
				if err != nil {
					conn.Write([]byte("error running fortune: "))
					conn.Write([]byte(err.Error()))
					conn.Write([]byte("\n"))
					return
				}
				cowsayInput.Write(body)
				cowsayInput.Close()

				io.Copy(conn, cowsayOutput)
			}()
		default:
			conn.Write([]byte("Unknown command: "))
			conn.Write([]byte(line))
			conn.Write([]byte("\n"))
		}

		session.InterimUpdate()
	}
}
<commit_msg>example: remove cowsay from goroutine<commit_after>package main

import (
	"bufio"
	"io"
	"net"
	"os"
	"os/exec"
	"strings"

	"github.com/CyCoreSystems/radius"
	"github.com/pborman/uuid"
)

// fortuned is a TCP service for service up fortunes

func main() {

	ln, err := net.Listen("tcp", "0.0.0.0:9191")
	if err != nil {
		panic(err)
	}

	rc := radius.NewClient(&radius.Options{
		Host:         "localhost:1813",
		SharedSecret: "testing123",
	})

	for {
		conn, err := ln.Accept()
		if err != nil {
			panic(err)
		}

		id := uuid.New()
		h, _ := os.Hostname()
		session := rc.NewSession(id,
			radius.StringAttribute(radius.AccessUserName, "admin"),
			radius.StringAttribute(32, h), // NAS-Identifier
		)

		go handle(conn, session)
	}
}

func handle(conn io.ReadWriteCloser, session *radius.Session) {

	a := &acct{
		session: session,
		w:       conn,
		r:       conn,
		closer:  conn,
	}

	conn = a

	for {
		conn.Write([]byte(" > "))

		r := bufio.NewReader(a)
		line, err := r.ReadString('\n')
		if err != nil {
			return
		}

		line = strings.TrimSpace(line)
		switch line {
		case "quit":
			session.Stop(radius.UserRequest)
			conn.Close()
			return
		case "fortune":
			cmd := exec.Command("fortune")
			out, err := cmd.Output()
			if err != nil {
				conn.Write([]byte("error running fortune: "))
				conn.Write([]byte(err.Error()))
				conn.Write([]byte("\n"))
			} else {
				conn.Write(out)
			}
		case "cowsay":
			cowsay := exec.Command("cowsay")
			cowsayInput, err := cowsay.StdinPipe()
			if err != nil {
				conn.Write([]byte("error running cowsay: "))
				conn.Write([]byte(err.Error()))
				conn.Write([]byte("\n"))
				return
			}
			cowsayOutput, err := cowsay.StdoutPipe()
			if err != nil {
				conn.Write([]byte("error running cowsay: "))
				conn.Write([]byte(err.Error()))
				conn.Write([]byte("\n"))
				return
			}

			cowsay.Start()

			fortune := exec.Command("fortune")
			body, err := fortune.Output()
			if err != nil {
				conn.Write([]byte("error running fortune: "))
				conn.Write([]byte(err.Error()))
				conn.Write([]byte("\n"))
				return
			}
			cowsayInput.Write(body)
			cowsayInput.Close()

			io.Copy(conn, cowsayOutput)
		default:
			conn.Write([]byte("Unknown command: "))
			conn.Write([]byte(line))
			conn.Write([]byte("\n"))
		}

		session.InterimUpdate()
	}
}
<|endoftext|>


<commit_before>package main

import (
	"testing"
	"time"

	"github.com/MustWin/baremetal-sdk-go"
	"github.com/MustWin/terraform-Oracle-BareMetal-Provider/client"
	"github.com/hashicorp/terraform/helper/resource"
	"github.com/hashicorp/terraform/helper/schema"
	"github.com/hashicorp/terraform/terraform"

	"github.com/stretchr/testify/suite"
)

type ResourceCoreRouteTableTestSuite struct {
	suite.Suite
	Client       *client.MockClient
	Provider     terraform.ResourceProvider
	Providers    map[string]terraform.ResourceProvider
	TimeCreated  baremetal.Time
	Config       string
	ResourceName string
	Res          *baremetal.RouteTable
	DeletedRes   *baremetal.RouteTable
	Opts         []baremetal.Options
}

func (s *ResourceCoreRouteTableTestSuite) SetupTest() {
	s.Client = &client.MockClient{}

	s.Provider = Provider(
		func(d *schema.ResourceData) (interface{}, error) {
			return s.Client, nil
		},
	)

	s.Providers = map[string]terraform.ResourceProvider{
		"baremetal": s.Provider,
	}

	s.TimeCreated = baremetal.Time{Time: time.Now()}

	s.Config = `
		resource "baremetal_core_route_table" "t" {
			compartment_id = "compartment_id"
			display_name = "display_name"
      route_rules {
				cidr_block = "cidr_block"
				network_entity_id = "network_entity_id"
				network_entity_type = "network_entity_type"
			}
      route_rules {
				cidr_block = "cidr_block"
				network_entity_id = "network_entity_id"
				network_entity_type = "network_entity_type"
			}
			vcn_id = "vcn_id"
		}
	`
	s.Config += testProviderConfig

	s.ResourceName = "baremetal_core_route_table.t"

	routeRules := []baremetal.RouteRule{
		baremetal.RouteRule{
			CidrBlock:         "cidr_block",
			NetworkEntityID:   "network_entity_id",
			NetworkEntityType: "network_entity_type",
		},
		baremetal.RouteRule{
			CidrBlock:         "cidr_block",
			NetworkEntityID:   "network_entity_id",
			NetworkEntityType: "network_entity_type",
		},
	}

	s.Res = &baremetal.RouteTable{
		CompartmentID: "compartment_id",
		DisplayName:   "display_name",
		ID:            "id",
		RouteRules:    routeRules,
		TimeModified:  s.TimeCreated,
		State:         baremetal.ResourceAvailable,
		TimeCreated:   s.TimeCreated,
	}
	s.Res.ETag = "etag"
	s.Res.RequestID = "opcrequestid"

	s.DeletedRes = &baremetal.RouteTable{
		CompartmentID: "compartment_id",
		DisplayName:   "display_name",
		ID:            "id",
		RouteRules:    routeRules,
		TimeModified:  s.TimeCreated,
		State:         baremetal.ResourceTerminated,
		TimeCreated:   s.TimeCreated,
	}
	s.DeletedRes.ETag = "etag"
	s.DeletedRes.RequestID = "opcrequestid"

	opts := baremetal.Options{DisplayName: "display_name"}
	s.Opts = []baremetal.Options{opts}
	s.Client.On(
		"CreateRouteTable",
		"compartment_id",
		"vcn_id",
		routeRules,
		s.Opts).Return(s.Res, nil)
	s.Client.On("DeleteRouteTable", "id").Return(nil)
}

func (s *ResourceCoreRouteTableTestSuite) TestCreateResourceCoreRouteTable() {
	s.Client.On("GetRouteTable", "id", []baremetal.Options(nil)).Return(s.Res, nil).Times(2)
	s.Client.On("GetRouteTable", "id", []baremetal.Options(nil)).Return(s.DeletedRes, nil)

	resource.UnitTest(s.T(), resource.TestCase{
		Providers: s.Providers,
		Steps: []resource.TestStep{
			resource.TestStep{
				Config: s.Config,
				Check: resource.ComposeTestCheckFunc(
					resource.TestCheckResourceAttr(s.ResourceName, "compartment_id", s.Res.CompartmentID),
					resource.TestCheckResourceAttr(s.ResourceName, "display_name", s.Res.DisplayName),
					resource.TestCheckResourceAttr(s.ResourceName, "route_rules.0.cidr_block", "cidr_block"),
					resource.TestCheckResourceAttr(s.ResourceName, "route_rules.1.network_entity_type", "network_entity_type"),
				),
			},
		},
	})
}

func (s ResourceCoreRouteTableTestSuite) TestUpdateRouteTable() {
	s.Client.On("GetRouteTable", "id", []baremetal.Options(nil)).Return(s.Res, nil).Times(3)

	config := `
		resource "baremetal_core_route_table" "t" {
			compartment_id = "compartment_id"
			display_name = "display_name"
      route_rules {
				cidr_block = "new_cidr_block"
				network_entity_id = "network_entity_id"
				network_entity_type = "network_entity_type"
			}
			vcn_id = "vcn_id"
		}
	`
	config += testProviderConfig

	routeRules := []baremetal.RouteRule{
		baremetal.RouteRule{
			CidrBlock:         "new_cidr_block",
			NetworkEntityID:   "network_entity_id",
			NetworkEntityType: "network_entity_type",
		},
	}

	res := &baremetal.RouteTable{
		CompartmentID: "compartment_id",
		DisplayName:   "display_name",
		ID:            "id",
		RouteRules:    routeRules,
		TimeModified:  s.TimeCreated,
		State:         baremetal.ResourceAvailable,
		TimeCreated:   s.TimeCreated,
	}
	res.ETag = "etag"
	res.RequestID = "opcrequestid"

	s.Client.On("UpdateRouteTable", "id", []baremetal.Options(nil)).Return(res, nil)
	s.Client.On("GetRouteTable", "id", []baremetal.Options(nil)).Return(res, nil)

	resource.UnitTest(s.T(), resource.TestCase{
		Providers: s.Providers,
		Steps: []resource.TestStep{
			resource.TestStep{
				Config: s.Config,
			},
			resource.TestStep{
				Config: config,
				Check: resource.ComposeTestCheckFunc(
					resource.TestCheckResourceAttr(s.ResourceName, "route_rules.0.new_cidr_block", "cidr_block"),
				),
			},
		},
	})
}

func (s *ResourceCoreRouteTableTestSuite) TestDeleteRouteTable() {
	s.Client.On("GetRouteTable", "id", []baremetal.Options(nil)).Return(s.Res, nil).Times(2)
	s.Client.On("GetRouteTable", "id", []baremetal.Options(nil)).Return(s.DeletedRes, nil)

	resource.UnitTest(s.T(), resource.TestCase{
		Providers: s.Providers,
		Steps: []resource.TestStep{
			resource.TestStep{
				Config: s.Config,
			},
			resource.TestStep{
				Config:  s.Config,
				Destroy: true,
			},
		},
	})

	s.Client.AssertCalled(s.T(), "DeleteRouteTable", "id")
}

func TestResourceCoreRouteTableTestSuite(t *testing.T) {
	suite.Run(t, new(ResourceCoreRouteTableTestSuite))
}
<commit_msg>Remove extraneous testfunc wrapper.<commit_after>package main

import (
	"testing"
	"time"

	"github.com/MustWin/baremetal-sdk-go"
	"github.com/MustWin/terraform-Oracle-BareMetal-Provider/client"
	"github.com/hashicorp/terraform/helper/resource"
	"github.com/hashicorp/terraform/helper/schema"
	"github.com/hashicorp/terraform/terraform"

	"github.com/stretchr/testify/suite"
)

type ResourceCoreRouteTableTestSuite struct {
	suite.Suite
	Client       *client.MockClient
	Provider     terraform.ResourceProvider
	Providers    map[string]terraform.ResourceProvider
	TimeCreated  baremetal.Time
	Config       string
	ResourceName string
	Res          *baremetal.RouteTable
	DeletedRes   *baremetal.RouteTable
	Opts         []baremetal.Options
}

func (s *ResourceCoreRouteTableTestSuite) SetupTest() {
	s.Client = &client.MockClient{}

	s.Provider = Provider(
		func(d *schema.ResourceData) (interface{}, error) {
			return s.Client, nil
		},
	)

	s.Providers = map[string]terraform.ResourceProvider{
		"baremetal": s.Provider,
	}

	s.TimeCreated = baremetal.Time{Time: time.Now()}

	s.Config = `
		resource "baremetal_core_route_table" "t" {
			compartment_id = "compartment_id"
			display_name = "display_name"
      route_rules {
				cidr_block = "cidr_block"
				network_entity_id = "network_entity_id"
				network_entity_type = "network_entity_type"
			}
      route_rules {
				cidr_block = "cidr_block"
				network_entity_id = "network_entity_id"
				network_entity_type = "network_entity_type"
			}
			vcn_id = "vcn_id"
		}
	`
	s.Config += testProviderConfig

	s.ResourceName = "baremetal_core_route_table.t"

	routeRules := []baremetal.RouteRule{
		baremetal.RouteRule{
			CidrBlock:         "cidr_block",
			NetworkEntityID:   "network_entity_id",
			NetworkEntityType: "network_entity_type",
		},
		baremetal.RouteRule{
			CidrBlock:         "cidr_block",
			NetworkEntityID:   "network_entity_id",
			NetworkEntityType: "network_entity_type",
		},
	}

	s.Res = &baremetal.RouteTable{
		CompartmentID: "compartment_id",
		DisplayName:   "display_name",
		ID:            "id",
		RouteRules:    routeRules,
		TimeModified:  s.TimeCreated,
		State:         baremetal.ResourceAvailable,
		TimeCreated:   s.TimeCreated,
	}
	s.Res.ETag = "etag"
	s.Res.RequestID = "opcrequestid"

	s.DeletedRes = &baremetal.RouteTable{
		CompartmentID: "compartment_id",
		DisplayName:   "display_name",
		ID:            "id",
		RouteRules:    routeRules,
		TimeModified:  s.TimeCreated,
		State:         baremetal.ResourceTerminated,
		TimeCreated:   s.TimeCreated,
	}
	s.DeletedRes.ETag = "etag"
	s.DeletedRes.RequestID = "opcrequestid"

	opts := baremetal.Options{DisplayName: "display_name"}
	s.Opts = []baremetal.Options{opts}
	s.Client.On(
		"CreateRouteTable",
		"compartment_id",
		"vcn_id",
		routeRules,
		s.Opts).Return(s.Res, nil)
	s.Client.On("DeleteRouteTable", "id").Return(nil)
}

func (s *ResourceCoreRouteTableTestSuite) TestCreateResourceCoreRouteTable() {
	s.Client.On("GetRouteTable", "id", []baremetal.Options(nil)).Return(s.Res, nil).Times(2)
	s.Client.On("GetRouteTable", "id", []baremetal.Options(nil)).Return(s.DeletedRes, nil)

	resource.UnitTest(s.T(), resource.TestCase{
		Providers: s.Providers,
		Steps: []resource.TestStep{
			resource.TestStep{
				Config: s.Config,
				Check: resource.ComposeTestCheckFunc(
					resource.TestCheckResourceAttr(s.ResourceName, "compartment_id", s.Res.CompartmentID),
					resource.TestCheckResourceAttr(s.ResourceName, "display_name", s.Res.DisplayName),
					resource.TestCheckResourceAttr(s.ResourceName, "route_rules.0.cidr_block", "cidr_block"),
					resource.TestCheckResourceAttr(s.ResourceName, "route_rules.1.network_entity_type", "network_entity_type"),
				),
			},
		},
	})
}

func (s ResourceCoreRouteTableTestSuite) TestUpdateRouteTable() {
	s.Client.On("GetRouteTable", "id", []baremetal.Options(nil)).Return(s.Res, nil).Times(3)

	config := `
		resource "baremetal_core_route_table" "t" {
			compartment_id = "compartment_id"
			display_name = "display_name"
      route_rules {
				cidr_block = "new_cidr_block"
				network_entity_id = "network_entity_id"
				network_entity_type = "network_entity_type"
			}
			vcn_id = "vcn_id"
		}
	`
	config += testProviderConfig

	routeRules := []baremetal.RouteRule{
		baremetal.RouteRule{
			CidrBlock:         "new_cidr_block",
			NetworkEntityID:   "network_entity_id",
			NetworkEntityType: "network_entity_type",
		},
	}

	res := &baremetal.RouteTable{
		CompartmentID: "compartment_id",
		DisplayName:   "display_name",
		ID:            "id",
		RouteRules:    routeRules,
		TimeModified:  s.TimeCreated,
		State:         baremetal.ResourceAvailable,
		TimeCreated:   s.TimeCreated,
	}
	res.ETag = "etag"
	res.RequestID = "opcrequestid"

	s.Client.On("UpdateRouteTable", "id", []baremetal.Options(nil)).Return(res, nil)
	s.Client.On("GetRouteTable", "id", []baremetal.Options(nil)).Return(res, nil)

	resource.UnitTest(s.T(), resource.TestCase{
		Providers: s.Providers,
		Steps: []resource.TestStep{
			resource.TestStep{
				Config: s.Config,
			},
			resource.TestStep{
				Config: config,
				Check:  resource.TestCheckResourceAttr(s.ResourceName, "route_rules.0.new_cidr_block", "cidr_block"),
			},
		},
	})
}

func (s *ResourceCoreRouteTableTestSuite) TestDeleteRouteTable() {
	s.Client.On("GetRouteTable", "id", []baremetal.Options(nil)).Return(s.Res, nil).Times(2)
	s.Client.On("GetRouteTable", "id", []baremetal.Options(nil)).Return(s.DeletedRes, nil)

	resource.UnitTest(s.T(), resource.TestCase{
		Providers: s.Providers,
		Steps: []resource.TestStep{
			resource.TestStep{
				Config: s.Config,
			},
			resource.TestStep{
				Config:  s.Config,
				Destroy: true,
			},
		},
	})

	s.Client.AssertCalled(s.T(), "DeleteRouteTable", "id")
}

func TestResourceCoreRouteTableTestSuite(t *testing.T) {
	suite.Run(t, new(ResourceCoreRouteTableTestSuite))
}
<|endoftext|>


<commit_before>package main

import (
	"encoding/json"
	"github.com/coreos/go-etcd/etcd"
	"github.com/golang/glog"
	"regexp"
	"strings"
)

// A watcher loads and watch the etcd hierarchy for domains and services.
type watcher struct {
	client       *etcd.Client
	config       *Config
	domains      map[string]*Domain
	environments map[string]*EnvironmentCluster
}

// Constructor for a new watcher
func NewEtcdWatcher(config *Config, domains map[string]*Domain, envs map[string]*EnvironmentCluster) *watcher {
	client := etcd.NewClient([]string{config.etcdAddress})
	return &watcher{client, config, domains, envs}
}

//Init domains and environments.
func (w *watcher) init() {
	go w.loadAndWatch(w.config.domainPrefix, w.registerDomain)
	go w.loadAndWatch(w.config.envPrefix, w.registerEnvironment)

}

// Loads and watch an etcd directory to register objects like domains, environments
// etc... The register function is passed the etcd Node that has been loaded.
func (w *watcher) loadAndWatch(etcdDir string, registerFunc func(*etcd.Node, string)) {
	w.loadPrefix(etcdDir, registerFunc)

	updateChannel := make(chan *etcd.Response, 10)
	go w.watch(updateChannel, registerFunc)
	w.client.Watch(etcdDir, (uint64)(0), true, updateChannel, nil)

}

func (w *watcher) loadPrefix(etcDir string, registerFunc func(*etcd.Node, string)) {
	response, err := w.client.Get(etcDir, true, true)
	if err == nil {
		for _, serviceNode := range response.Node.Nodes {
			registerFunc(serviceNode, response.Action)

		}
	}

}

func (w *watcher) watch(updateChannel chan *etcd.Response, registerFunc func(*etcd.Node, string)) {
	for {
		response := <-updateChannel
		if response != nil {
			registerFunc(response.Node, response.Action)
		}

	}
}

func (w *watcher) registerDomain(node *etcd.Node, action string) {

	domainName := w.getDomainForNode(node)

	domainKey := w.config.domainPrefix + "/" + domainName
	response, err := w.client.Get(domainKey, true, false)

	if action == "delete" || action == "expire" {
		w.RemoveDomain(domainName)
		return
	}

	if err == nil {
		domain := &Domain{}
		for _, node := range response.Node.Nodes {
			switch node.Key {
			case domainKey + "/type":
				domain.typ = node.Value
			case domainKey + "/value":
				domain.value = node.Value
			}
		}

		actualDomain := w.domains[domainName]

		if domain.typ != "" && domain.value != "" && !domain.equals(actualDomain) {
			w.domains[domainName] = domain
			glog.Infof("Registered domain %s with (%s) %s", domainName, domain.typ, domain.value)

		}
	}

}

func (w *watcher) RemoveDomain(key string) {
	delete(w.domains, key)

}

func (w *watcher) getDomainForNode(node *etcd.Node) string {
	r := regexp.MustCompile(w.config.domainPrefix + "/(.*)")
	return strings.Split(r.FindStringSubmatch(node.Key)[1], "/")[0]
}

func (w *watcher) getEnvForNode(node *etcd.Node) string {
	r := regexp.MustCompile(w.config.envPrefix + "/(.*)(/.*)*")
	return strings.Split(r.FindStringSubmatch(node.Key)[1], "/")[0]
}

func (w *watcher) getEnvIndexForNode(node *etcd.Node) string {
	r := regexp.MustCompile(w.config.envPrefix + "/(.*)(/.*)*")
	return strings.Split(r.FindStringSubmatch(node.Key)[1], "/")[1]
}

func (w *watcher) RemoveEnv(envName string) {
	delete(w.environments, envName)
}

func (w *watcher) registerEnvironment(node *etcd.Node, action string) {
	envName := w.getEnvForNode(node)

	// Get service's root node instead of changed node.
	envNode, _ := w.client.Get(w.config.envPrefix+"/"+envName, true, true)

	for _, indexNode := range envNode.Node.Nodes {

		envIndex := w.getEnvIndexForNode(indexNode)
		envKey := w.config.envPrefix + "/" + envName + "/" + envIndex
		statusKey := envKey + "/status"

		response, err := w.client.Get(envKey, true, true)

		if err == nil {

			if w.environments[envName] == nil {
				w.environments[envName] = &EnvironmentCluster{}
			}

			env := &Environment{}
			env.key = envIndex

			if action == "delete" || action == "expire" {
				w.RemoveEnv(envName)
				return
			}

			for _, node := range response.Node.Nodes {
				switch node.Key {
				case envKey + "/location":
					location := &service{}
					err := json.Unmarshal([]byte(node.Value), location)
					if err != nil {
						panic(err)
					}

					env.location.Host = location.Host
					env.location.Port = location.Port
				case envKey + "/domain":
					env.domain = node.Value

				case statusKey:
					env.status = &Status{}

					for _, subNode := range node.Nodes {
						switch subNode.Key {
						case statusKey + "/alive":
							env.status.alive = subNode.Value
						case statusKey + "/current":
							env.status.current = subNode.Value
						case statusKey + "/expected":
							env.status.expected = subNode.Value
						}
					}
				}
			}

			actualEnv := w.environments[envName].Get(env.key)

			if(!actualEnv.equals(env)) {

				if env.location.Host != "" && env.location.Port != 0 {
					w.environments[envName].Add(env)
					glog.Infof("Registering environment %s with address : http://%s:%d/", envName, env.location.Host, env.location.Port)

				}

			}
		}
	}
}
<commit_msg>NXIO-176 check location is set<commit_after>package main

import (
	"encoding/json"
	"github.com/coreos/go-etcd/etcd"
	"github.com/golang/glog"
	"regexp"
	"strings"
)

// A watcher loads and watch the etcd hierarchy for domains and services.
type watcher struct {
	client       *etcd.Client
	config       *Config
	domains      map[string]*Domain
	environments map[string]*EnvironmentCluster
}

// Constructor for a new watcher
func NewEtcdWatcher(config *Config, domains map[string]*Domain, envs map[string]*EnvironmentCluster) *watcher {
	client := etcd.NewClient([]string{config.etcdAddress})
	return &watcher{client, config, domains, envs}
}

//Init domains and environments.
func (w *watcher) init() {
	go w.loadAndWatch(w.config.domainPrefix, w.registerDomain)
	go w.loadAndWatch(w.config.envPrefix, w.registerEnvironment)

}

// Loads and watch an etcd directory to register objects like domains, environments
// etc... The register function is passed the etcd Node that has been loaded.
func (w *watcher) loadAndWatch(etcdDir string, registerFunc func(*etcd.Node, string)) {
	w.loadPrefix(etcdDir, registerFunc)

	updateChannel := make(chan *etcd.Response, 10)
	go w.watch(updateChannel, registerFunc)
	w.client.Watch(etcdDir, (uint64)(0), true, updateChannel, nil)

}

func (w *watcher) loadPrefix(etcDir string, registerFunc func(*etcd.Node, string)) {
	response, err := w.client.Get(etcDir, true, true)
	if err == nil {
		for _, serviceNode := range response.Node.Nodes {
			registerFunc(serviceNode, response.Action)

		}
	}

}

func (w *watcher) watch(updateChannel chan *etcd.Response, registerFunc func(*etcd.Node, string)) {
	for {
		response := <-updateChannel
		if response != nil {
			registerFunc(response.Node, response.Action)
		}

	}
}

func (w *watcher) registerDomain(node *etcd.Node, action string) {

	domainName := w.getDomainForNode(node)

	domainKey := w.config.domainPrefix + "/" + domainName
	response, err := w.client.Get(domainKey, true, false)

	if action == "delete" || action == "expire" {
		w.RemoveDomain(domainName)
		return
	}

	if err == nil {
		domain := &Domain{}
		for _, node := range response.Node.Nodes {
			switch node.Key {
			case domainKey + "/type":
				domain.typ = node.Value
			case domainKey + "/value":
				domain.value = node.Value
			}
		}

		actualDomain := w.domains[domainName]

		if domain.typ != "" && domain.value != "" && !domain.equals(actualDomain) {
			w.domains[domainName] = domain
			glog.Infof("Registered domain %s with (%s) %s", domainName, domain.typ, domain.value)

		}
	}

}

func (w *watcher) RemoveDomain(key string) {
	delete(w.domains, key)

}

func (w *watcher) getDomainForNode(node *etcd.Node) string {
	r := regexp.MustCompile(w.config.domainPrefix + "/(.*)")
	return strings.Split(r.FindStringSubmatch(node.Key)[1], "/")[0]
}

func (w *watcher) getEnvForNode(node *etcd.Node) string {
	r := regexp.MustCompile(w.config.envPrefix + "/(.*)(/.*)*")
	return strings.Split(r.FindStringSubmatch(node.Key)[1], "/")[0]
}

func (w *watcher) getEnvIndexForNode(node *etcd.Node) string {
	r := regexp.MustCompile(w.config.envPrefix + "/(.*)(/.*)*")
	return strings.Split(r.FindStringSubmatch(node.Key)[1], "/")[1]
}

func (w *watcher) RemoveEnv(envName string) {
	delete(w.environments, envName)
}

func (w *watcher) registerEnvironment(node *etcd.Node, action string) {
	envName := w.getEnvForNode(node)

	// Get service's root node instead of changed node.
	envNode, _ := w.client.Get(w.config.envPrefix+"/"+envName, true, true)

	for _, indexNode := range envNode.Node.Nodes {

		envIndex := w.getEnvIndexForNode(indexNode)
		envKey := w.config.envPrefix + "/" + envName + "/" + envIndex
		statusKey := envKey + "/status"

		response, err := w.client.Get(envKey, true, true)

		if err == nil {

			if w.environments[envName] == nil {
				w.environments[envName] = &EnvironmentCluster{}
			}

			env := &Environment{}
			env.key = envIndex

			if action == "delete" || action == "expire" {
				w.RemoveEnv(envName)
				return
			}

			for _, node := range response.Node.Nodes {
				switch node.Key {
				case envKey + "/location":
					location := &service{}
					err := json.Unmarshal([]byte(node.Value), location)
					if err != nil {
						panic(err)
					}

					env.location.Host = location.Host
					env.location.Port = location.Port
				case envKey + "/domain":
					env.domain = node.Value

				case statusKey:
					env.status = &Status{}

					for _, subNode := range node.Nodes {
						switch subNode.Key {
						case statusKey + "/alive":
							env.status.alive = subNode.Value
						case statusKey + "/current":
							env.status.current = subNode.Value
						case statusKey + "/expected":
							env.status.expected = subNode.Value
						}
					}
				}
			}

			actualEnv := w.environments[envName].Get(env.key)

			if(!actualEnv.equals(env) && env.location != nil) {

				if env.location.Host != "" && env.location.Port != 0 {
					w.environments[envName].Add(env)
					glog.Infof("Registering environment %s with location : http://%s:%d/", envName, env.location.Host, env.location.Port)

				}

			}
		}
	}
}
<|endoftext|>