<commit_before>package main

import (
	"time"
)

var lastKnownCluster []*Status

//
func DecisionStart() error {
	log.Info("[decision] starting")
	// wait for the cluster to come online
	waitForClusterFull()
	// start the database and perform actions on that database
	go func() {
		self := myself()
		log.Debug("[decision] myself %+v", self)
		if self.CRole == "monitor" {
			log.Debug("[decision] im a monitor.. i dont make decisions")
			return
		}
		// start the database up
		startupDB()
		lastKnownCluster, _ = Cluster()

		// start a timer that will trigger a cluster check
		timer := make(chan bool)
		go func() {
			for {
				time.Sleep(time.Second * 10)
				timer <- true
			}
		}()

		// check server on timer and listen for advice
		// if you notice a problem perform an action
		for {
			select {

			case adv := <-advice:
				// i need a new self to see if im currently the master
				self := myself()
				if adv == "demote" && self.DBRole == "master" {
					updateStatusRole("dead(master)")
					actions <- "kill"
				} else {
					log.Info("[decision] got some advice:" + adv)
					// what do i do with other advice?
					if clusterChanges() {
						performAction()
					}
				}
			case <-timer:
				if clusterChanges() {
					performAction()
				}
			}
		}
	}()
	return nil
}

// this will ping the cluster until it has the
// appropriate number of members
func waitForClusterFull() {
	for {
		c, _ := Cluster()
		if len(c) == 3 {
			log.Info("[decision] members are all online!")
			return
		}

		log.Info("[decision] waiting for members (cluster(%d), list(%d))\n", len(c), len(list.Members()))
		time.Sleep(time.Second)
	}
}

// figure out what to start as.
func startupDB() {
	log.Debug("[decision] Starting Db")
	self := myself()
	switch self.CRole {
	case "primary":
		r := startType("master")
		updateStatusRole(r)
		log.Info("[decision] I am starting as " + r)
		actions <- r
	case "secondary":
		r := startType("slave")
		updateStatusRole(r)
		log.Info("[decision] I am starting as " + r)
		actions <- r
	default:
		log.Warn("[decision] Monitors dont do anything. (and this shouldnt have been executed)")
	}
}

//
func startType(def string) string {
	self := myself()
	log.Debug("[decision] startType: self: %+v", self)
	switch self.DBRole {
	case "initialized":
		return def
	case "single":
		return "master"
	case "master", "dead(master)":
		// check the other node and see if it is single
		// if not i stay master
		// if so i go secondary
		other, _ := Whois(otherRole(self))
		log.Debug("[decision] startType: other: %+v", other)
		// if the other guy has transitioned to single
		if other.DBRole == "single" {
			return "slave"
		}
		// if the other guy detected i came back online and is already
		// switching to master
		if other.DBRole == "master" && other.UpdatedAt.After(self.UpdatedAt) {
			return "slave"
		}
		return "master"
	case "slave", "dead(slave)":
		return "slave"
	}
	log.Error("[decision] Error: Status: %+v\n", self)
	panic("i should have caught all scenarios")
	return def
}

//
func clusterChanges() bool {
	c, _ := Cluster()
	if len(lastKnownCluster) != len(c) {
		log.Debug("[decision] The cluster size changed from %d to %d", len(lastKnownCluster), len(c))
		lastKnownCluster, _ = Cluster()
		return true
	}
	for _, member := range lastKnownCluster {
		other, _ := Whois(member.CRole)
		if member.DBRole != other.DBRole {
			log.Debug("[decision] The cluster members(%s) role changed from %s to %s", member.DBRole, member.DBRole, other.DBRole)
			lastKnownCluster, _ = Cluster()
			return true
		}
	}
	return false
}

//
func performAction() {
	self := myself()
	other, _ := Whois(otherRole(self))

	log.Debug("[decision] performAction: self: %+v, other: %+v", self, other)
	switch self.DBRole {
	case "single":
		performActionFromSingle(self, other)
	case "master":
		performActionFromMaster(self, other)
	case "slave":
		performActionFromSlave(self, other)
	case "dead(master)", "dead(slave)":
		performActionFromDead(self, other)
	}
}

//
func performActionFromSingle(self, other *Status) {
	if other != nil {
		// i was in single but the other node came back online
		// I should be safe to assume master
		updateStatusRole("master")
		log.Info("[decision] performActionFromSingle: other came back online: going master")
		actions <- "master"
	}
}

//
func performActionFromMaster(self, other *Status) {
	if other != nil && other.DBRole == "slave" {
		// i lost the monitor
		// shouldnt hurt anything
		log.Info("[decision] performActionFromMaster: other is slave: im doing nothing")
		return
	}

	if other != nil && other.DBRole == "dead(slave)" {
		// my slave has died and i need to transition into single mode
		updateStatusRole("single")
		log.Info("[decision] performActionFromMaster: other is dead: going single")
		actions <- "single"
	}

	// see if im the odd man out or if it is the other guy
	time.Sleep(time.Duration(conf.DecisionTimeout) * time.Second)
	mon, _ := Whois("monitor")
	if mon != nil {
		// the other member died but i can still talk to the monitor
		// i can safely become a single
		updateStatusRole("single")
		log.Info("[decision] performActionFromMaster: other gone: going single")
		actions <- "single"
	} else {
		// I have lost communication with everything else
		// kill my server
		updateStatusRole("dead(master)")
		log.Info("[decision] performActionFromMaster: lost connection to cluster: going dead")
		actions <- "kill"
	}
}

//
func performActionFromSlave(self, other *Status) {
	if other != nil && other.DBRole == "master" {
		// i probably lost the monitor
		// shouldnt hurt anything
		log.Info("[decision] performActionFromSlave: other is master: im doing nothing")
		return
	}
	if other != nil && other.DBRole == "dead(master)" {
		// my master has died and i need to transition into single mode
		updateStatusRole("single")
		log.Info("[decision] performActionFromSlave: other is dead: going single")
		actions <- "single"
	}

	// see if im the odd man out or if it is the other guy
	time.Sleep(time.Duration(conf.DecisionTimeout) * time.Second)
	mon, _ := Whois("monitor")
	if mon != nil {
		// the other member died but i can still talk to the monitor
		// i can safely become a single
		updateStatusRole("single")
		log.Info("[decision] performActionFromSlave: other gone: going single")
		actions <- "single"
	} else {
		// I have lost communication with everything else
		// kill my server
		updateStatusRole("dead(slave)")
		log.Info("[decision] performActionFromSlave: lost connection to cluster: going dead")
		actions <- "kill"
	}
}

//
func performActionFromDead(self, other *Status) {
	c, _ := Cluster()
	if other != nil && len(c) == 3 {
		switch self.DBRole {
		case "dead(master)":
			newRole := startType("master")
			updateStatusRole(newRole)
			log.Info("[decision] performActionFromDead: other online: going " + newRole)
			actions <- newRole
		case "dead(slave)":
			newRole := startType("slave")
			updateStatusRole(newRole)
			log.Info("[decision] performActionFromDead: other online: going " + newRole)
			actions <- newRole
		default:
			panic("i dont know how to be a " + self.DBRole)
		}
	}
}

//
func updateStatusRole(r string) {
	status.SetDBRole(r)
	lastKnownCluster, _ = Cluster()
}

//
func otherRole(st *Status) string {
	if st.CRole == "primary" {
		return "secondary"
	}
	return "primary"
}

func myself() *Status {
	for i := 0; i < 10; i++ {
		self, err := Whoami()
		if err == nil {
			return self
		}
		log.Error("Decision: Myself: " + err.Error())
	}
	panic("Decision: Myself: I never found myself!")
	return nil
}
<commit_msg>more tweeking<commit_after>package main

import (
	"time"
)

var lastKnownCluster []*Status

//
func DecisionStart() error {
	log.Info("[decision] starting")
	// wait for the cluster to come online
	waitForClusterFull()
	// start the database and perform actions on that database
	go func() {
		self := myself()
		log.Debug("[decision] myself %+v", self)
		if self.CRole == "monitor" {
			log.Debug("[decision] im a monitor.. i dont make decisions")
			return
		}
		// start the database up
		startupDB()
		lastKnownCluster, _ = Cluster()

		// start a timer that will trigger a cluster check
		timer := make(chan bool)
		go func() {
			for {
				time.Sleep(time.Second * 10)
				timer <- true
			}
		}()

		// check server on timer and listen for advice
		// if you notice a problem perform an action
		for {
			select {

			case adv := <-advice:
				// i need a new self to see if im currently the master
				self := myself()
				if adv == "demote" && self.DBRole == "master" {
					updateStatusRole("dead(master)")
					actions <- "kill"
				} else {
					log.Info("[decision] got some advice:" + adv)
					// what do i do with other advice?
					if clusterChanges() {
						performAction()
					}
				}
			case <-timer:
				if clusterChanges() {
					performAction()
				}
			}
		}
	}()
	return nil
}

// this will ping the cluster until it has the
// appropriate number of members
func waitForClusterFull() {
	for {
		c, _ := Cluster()
		if len(c) == 3 {
			log.Info("[decision] members are all online!")
			return
		}

		log.Info("[decision] waiting for members (cluster(%d), list(%d))\n", len(c), len(list.Members()))
		time.Sleep(time.Second)
	}
}

// figure out what to start as.
func startupDB() {
	log.Debug("[decision] Starting Db")
	self := myself()
	switch self.CRole {
	case "primary":
		r := startType("master")
		updateStatusRole(r)
		log.Info("[decision] I am starting as " + r)
		actions <- r
	case "secondary":
		r := startType("slave")
		updateStatusRole(r)
		log.Info("[decision] I am starting as " + r)
		actions <- r
	default:
		log.Warn("[decision] Monitors dont do anything. (and this shouldnt have been executed)")
	}
}

//
func startType(def string) string {
	self := myself()
	log.Debug("[decision] startType: self: %+v", self)
	switch self.DBRole {
	case "initialized":
		return def
	case "single":
		return "master"
	case "master", "dead(master)":
		// check the other node and see if it is single
		// if not i stay master
		// if so i go secondary
		other, _ := Whois(otherRole(self))
		log.Debug("[decision] startType: other: %+v", other)
		// if the other guy has transitioned to single
		if other.DBRole == "single" {
			return "slave"
		}
		// if the other guy detected i came back online and is already
		// switching to master
		if other.DBRole == "master" && other.UpdatedAt.After(self.UpdatedAt) {
			return "slave"
		}
		return "master"
	case "slave", "dead(slave)":
		return "slave"
	}
	log.Error("[decision] Error: Status: %+v\n", self)
	panic("i should have caught all scenarios")
	return def
}

//
func clusterChanges() bool {
	c, _ := Cluster()
	if len(lastKnownCluster) != len(c) {
		log.Debug("[decision] The cluster size changed from %d to %d", len(lastKnownCluster), len(c))
		lastKnownCluster, _ = Cluster()
		return true
	}
	for _, member := range lastKnownCluster {
		other, err := Whois(member.CRole)
		if err != nil {
			log.Debug("[decision] The other member died while i was trying to pull its updats")
			lastKnownCluster, _ = Cluster()
			return true
		}
		if member.DBRole != other.DBRole {
			log.Debug("[decision] The cluster members(%s) role changed from %s to %s", member.DBRole, member.DBRole, other.DBRole)
			lastKnownCluster, _ = Cluster()
			return true
		}
	}
	return false
}

//
func performAction() {
	self := myself()
	other, _ := Whois(otherRole(self))

	log.Debug("[decision] performAction: self: %+v, other: %+v", self, other)
	switch self.DBRole {
	case "single":
		performActionFromSingle(self, other)
	case "master":
		performActionFromMaster(self, other)
	case "slave":
		performActionFromSlave(self, other)
	case "dead(master)", "dead(slave)":
		performActionFromDead(self, other)
	}
}

//
func performActionFromSingle(self, other *Status) {
	if other != nil {
		// i was in single but the other node came back online
		// I should be safe to assume master
		updateStatusRole("master")
		log.Info("[decision] performActionFromSingle: other came back online: going master")
		actions <- "master"
	}
}

//
func performActionFromMaster(self, other *Status) {
	if other != nil && other.DBRole == "slave" {
		// i lost the monitor
		// shouldnt hurt anything
		log.Info("[decision] performActionFromMaster: other is slave: im doing nothing")
		return
	}

	if other != nil && other.DBRole == "dead(slave)" {
		// my slave has died and i need to transition into single mode
		updateStatusRole("single")
		log.Info("[decision] performActionFromMaster: other is dead: going single")
		actions <- "single"
		return
	}

	// see if im the odd man out or if it is the other guy
	time.Sleep(time.Duration(conf.DecisionTimeout) * time.Second)
	mon, _ := Whois("monitor")
	if mon != nil {
		// the other member died but i can still talk to the monitor
		// i can safely become a single
		updateStatusRole("single")
		log.Info("[decision] performActionFromMaster: other gone: going single")
		actions <- "single"
		return
	} else {
		// I have lost communication with everything else
		// kill my server
		updateStatusRole("dead(master)")
		log.Info("[decision] performActionFromMaster: lost connection to cluster: going dead")
		actions <- "kill"
		return
	}
}

//
func performActionFromSlave(self, other *Status) {
	if other != nil && other.DBRole == "master" {
		// i probably lost the monitor
		// shouldnt hurt anything
		log.Info("[decision] performActionFromSlave: other is master: im doing nothing")
		return
	}
	if other != nil && other.DBRole == "dead(master)" {
		// my master has died and i need to transition into single mode
		updateStatusRole("single")
		log.Info("[decision] performActionFromSlave: other is dead: going single")
		actions <- "single"
		return
	}

	// see if im the odd man out or if it is the other guy
	time.Sleep(time.Duration(conf.DecisionTimeout) * time.Second)
	mon, _ := Whois("monitor")
	if mon != nil {
		// the other member died but i can still talk to the monitor
		// i can safely become a single
		updateStatusRole("single")
		log.Info("[decision] performActionFromSlave: other gone: going single")
		actions <- "single"
		return
	} else {
		// I have lost communication with everything else
		// kill my server
		updateStatusRole("dead(slave)")
		log.Info("[decision] performActionFromSlave: lost connection to cluster: going dead")
		actions <- "kill"
		return
	}
}

//
func performActionFromDead(self, other *Status) {
	c, _ := Cluster()
	if other != nil && len(c) == 3 {
		switch self.DBRole {
		case "dead(master)":
			newRole := startType("master")
			updateStatusRole(newRole)
			log.Info("[decision] performActionFromDead: other online: going " + newRole)
			actions <- newRole
		case "dead(slave)":
			newRole := startType("slave")
			updateStatusRole(newRole)
			log.Info("[decision] performActionFromDead: other online: going " + newRole)
			actions <- newRole
		default:
			panic("i dont know how to be a " + self.DBRole)
		}
	}
}

//
func updateStatusRole(r string) {
	status.SetDBRole(r)
	lastKnownCluster, _ = Cluster()
}

//
func otherRole(st *Status) string {
	if st.CRole == "primary" {
		return "secondary"
	}
	return "primary"
}

func myself() *Status {
	for i := 0; i < 10; i++ {
		self, err := Whoami()
		if err == nil {
			return self
		}
		log.Error("Decision: Myself: " + err.Error())
	}
	panic("Decision: Myself: I never found myself!")
	return nil
}
<|endoftext|>


<commit_before>package linode

import (
	"context"
	"fmt"

	"github.com/chiefy/linodego"
	"github.com/hashicorp/terraform/helper/schema"
)

func dataSourceLinodeComputeIPv6Pool() *schema.Resource {
	return &schema.Resource{
		Read: dataSourceLinodeComputeIPv6PoolRead,

		Schema: map[string]*schema.Schema{
			"range": &schema.Schema{
				Type:     schema.TypeString,
				Computed: true,
			},

			"region": &schema.Schema{
				Type:     schema.TypeString,
				Computed: true,
			},
		},
	}
}

func dataSourceLinodeComputeIPv6PoolRead(d *schema.ResourceData, meta interface{}) error {
	client := meta.(*linodego.Client)

	pools, err := client.ListIPv6Pools(context.TODO(), nil)
	if err != nil {
		return fmt.Errorf("Error listing pools: %s", err)
	}

	reqPool := d.Get("").(string)

	for _, pool := range pools {
		if pool.Range == reqPool {
			d.SetId(pool.Range)
			d.Set("region", pool.Region)
			return nil
		}
	}

	return fmt.Errorf("Pool not found")
}
<commit_msg>fix: lookup key for ipv6_pools should be range<commit_after>package linode

import (
	"context"
	"fmt"

	"github.com/chiefy/linodego"
	"github.com/hashicorp/terraform/helper/schema"
)

func dataSourceLinodeComputeIPv6Pool() *schema.Resource {
	return &schema.Resource{
		Read: dataSourceLinodeComputeIPv6PoolRead,

		Schema: map[string]*schema.Schema{
			"range": &schema.Schema{
				Type:     schema.TypeString,
				Computed: true,
			},

			"region": &schema.Schema{
				Type:     schema.TypeString,
				Computed: true,
			},
		},
	}
}

func dataSourceLinodeComputeIPv6PoolRead(d *schema.ResourceData, meta interface{}) error {
	client := meta.(*linodego.Client)

	pools, err := client.ListIPv6Pools(context.TODO(), nil)
	if err != nil {
		return fmt.Errorf("Error listing pools: %s", err)
	}

	reqPool := d.Get("range").(string)

	for _, pool := range pools {
		if pool.Range == reqPool {
			d.SetId(pool.Range)
			d.Set("region", pool.Region)
			return nil
		}
	}

	return fmt.Errorf("Pool not found")
}
<|endoftext|>


<commit_before>// Copyright 2013 tsuru authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package testing

import (
	"errors"
	"fmt"
	"github.com/globocom/tsuru/deploy"
	"github.com/globocom/tsuru/provision"
	"io"
	"strconv"
	"strings"
	"sync"
	"time"
)

func init() {
	provision.Register("fake", &FakeProvisioner{})
}

// Fake implementation for provision.Unit.
type FakeUnit struct {
	Name       string
	Ip         string
	InstanceId string
	Machine    int
	Status     provision.Status
}

func (u *FakeUnit) GetName() string {
	return u.Name
}

func (u *FakeUnit) GetMachine() int {
	return u.Machine
}

func (u *FakeUnit) GetStatus() provision.Status {
	return u.Status
}

func (u *FakeUnit) GetInstanceId() string {
	return u.InstanceId
}

func (u *FakeUnit) GetIp() string {
	return u.Ip
}

// Fake implementation for provision.App.
type FakeApp struct {
	name      string
	framework string
	units     []provision.AppUnit
	logs      []string
	Commands  []string
}

func NewFakeApp(name, framework string, units int) *FakeApp {
	app := FakeApp{
		name:      name,
		framework: framework,
		units:     make([]provision.AppUnit, units),
	}
	namefmt := "%s/%d"
	for i := 0; i < units; i++ {
		app.units[i] = &FakeUnit{
			Name:       fmt.Sprintf(namefmt, name, i),
			Machine:    i + 1,
			Status:     provision.StatusStarted,
			Ip:         fmt.Sprintf("10.10.10.%d", i+1),
			InstanceId: fmt.Sprintf("i-0%d", i+1),
		}
	}
	return &app
}

func (a *FakeApp) Log(message, source string) error {
	a.logs = append(a.logs, source+message)
	return nil
}

func (a *FakeApp) GetName() string {
	return a.name
}

func (a *FakeApp) GetFramework() string {
	return a.framework
}

func (a *FakeApp) ProvisionUnits() []provision.AppUnit {
	return a.units
}

func (a *FakeApp) SetUnitStatus(s provision.Status, index int) {
	if index < len(a.units) {
		a.units[index].(*FakeUnit).Status = s
	}
}

func (a *FakeApp) Command(stdout, stderr io.Writer, cmdArgs ...string) error {
	a.Commands = append(a.Commands, strings.Join(cmdArgs, " "))
	return nil
}

func (a *FakeApp) Restart(w io.Writer) error {
	a.Commands = append(a.Commands, "restart")
	return nil
}

func (a *FakeApp) InstallDeps(io.Writer) error {
	a.Commands = append(a.Commands, "install deps")
	return nil
}

func (a *FakeApp) Run(cmd string, w io.Writer) error {
	a.Commands = append(a.Commands, fmt.Sprintf("ran %s", cmd))
	return nil
}

type Cmd struct {
	Cmd  string
	Args []string
	App  provision.App
}

type failure struct {
	method string
	err    error
}

// Fake implementation for provision.Provisioner.
type FakeProvisioner struct {
	apps     []provision.App
	units    map[string][]provision.Unit
	unitLen  uint
	cmds     []Cmd
	outputs  chan []byte
	failures chan failure
	cmdMut   sync.Mutex
	unitMut  sync.Mutex
	restarts map[string]int
	restMut  sync.Mutex
}

func NewFakeProvisioner() *FakeProvisioner {
	p := FakeProvisioner{}
	p.outputs = make(chan []byte, 8)
	p.failures = make(chan failure, 8)
	p.units = make(map[string][]provision.Unit)
	p.restarts = make(map[string]int)
	p.unitLen = 0
	return &p
}

func (p *FakeProvisioner) getError(method string) error {
	select {
	case fail := <-p.failures:
		if fail.method == method {
			return fail.err
		}
		p.failures <- fail
	case <-time.After(1e6):
	}
	return nil
}

func (p *FakeProvisioner) Restarts(app provision.App) int {
	p.restMut.Lock()
	defer p.restMut.Unlock()
	return p.restarts[app.GetName()]
}

func (p *FakeProvisioner) Deploy(app deploy.App, w io.Writer) error {
	w.Write([]byte("Deploy called"))
	return nil
}

// Returns the number of calls to restart.
// GetCmds returns a list of commands executed in an app. If you don't specify
// the command (an empty string), it will return all commands executed in the
// given app.
func (p *FakeProvisioner) GetCmds(cmd string, app provision.App) []Cmd {
	var cmds []Cmd
	p.cmdMut.Lock()
	for _, c := range p.cmds {
		if (cmd == "" || c.Cmd == cmd) && app.GetName() == c.App.GetName() {
			cmds = append(cmds, c)
		}
	}
	p.cmdMut.Unlock()
	return cmds
}

func (p *FakeProvisioner) FindApp(app provision.App) int {
	for i, a := range p.apps {
		if a.GetName() == app.GetName() {
			return i
		}
	}
	return -1
}

func (p *FakeProvisioner) GetUnits(app provision.App) []provision.Unit {
	p.unitMut.Lock()
	defer p.unitMut.Unlock()
	return p.units[app.GetName()]
}

func (p *FakeProvisioner) PrepareOutput(b []byte) {
	p.outputs <- b
}

func (p *FakeProvisioner) PrepareFailure(method string, err error) {
	p.failures <- failure{method, err}
}

func (p *FakeProvisioner) Reset() {
	p.unitMut.Lock()
	p.units = make(map[string][]provision.Unit)
	p.unitMut.Unlock()

	p.cmdMut.Lock()
	p.cmds = nil
	p.cmdMut.Unlock()

	p.restMut.Lock()
	p.restarts = make(map[string]int)
	p.restMut.Unlock()

	for {
		select {
		case <-p.outputs:
		case <-p.failures:
		default:
			return
		}
	}
}

func (p *FakeProvisioner) Provision(app provision.App) error {
	if err := p.getError("Provision"); err != nil {
		return err
	}
	index := p.FindApp(app)
	if index > -1 {
		return &provision.Error{Reason: "App already provisioned."}
	}
	p.apps = append(p.apps, app)
	p.unitMut.Lock()
	p.units[app.GetName()] = []provision.Unit{
		{
			Name:       app.GetName() + "/0",
			AppName:    app.GetName(),
			Type:       app.GetFramework(),
			Status:     provision.StatusStarted,
			InstanceId: "i-080",
			Ip:         "10.10.10.1",
			Machine:    1,
		},
	}
	p.unitLen++
	p.unitMut.Unlock()
	return nil
}

func (p *FakeProvisioner) Restart(app provision.App) error {
	if err := p.getError("Restart"); err != nil {
		return err
	}
	p.restMut.Lock()
	v := p.restarts[app.GetName()]
	v++
	p.restarts[app.GetName()] = v
	p.restMut.Unlock()
	return nil
}

func (p *FakeProvisioner) Destroy(app provision.App) error {
	if err := p.getError("Destroy"); err != nil {
		return err
	}
	index := p.FindApp(app)
	if index == -1 {
		return &provision.Error{Reason: "App is not provisioned."}
	}
	copy(p.apps[index:], p.apps[index+1:])
	p.apps = p.apps[:len(p.apps)-1]
	p.unitMut.Lock()
	delete(p.units, app.GetName())
	p.unitLen = 0
	p.unitMut.Unlock()
	p.restMut.Lock()
	delete(p.restarts, app.GetName())
	p.restMut.Unlock()
	return nil
}

func (p *FakeProvisioner) AddUnits(app provision.App, n uint) ([]provision.Unit, error) {
	if err := p.getError("AddUnits"); err != nil {
		return nil, err
	}
	if n == 0 {
		return nil, errors.New("Cannot add 0 units.")
	}
	index := p.FindApp(app)
	if index < 0 {
		return nil, errors.New("App is not provisioned.")
	}
	name := app.GetName()
	framework := app.GetFramework()
	p.unitMut.Lock()
	defer p.unitMut.Unlock()
	length := uint(len(p.units[name]))
	for i := uint(0); i < n; i++ {
		unit := provision.Unit{
			Name:       fmt.Sprintf("%s/%d", name, p.unitLen),
			AppName:    name,
			Type:       framework,
			Status:     provision.StatusStarted,
			InstanceId: fmt.Sprintf("i-08%d", length+i),
			Ip:         fmt.Sprintf("10.10.10.%d", length+i),
			Machine:    int(length + i),
		}
		p.units[name] = append(p.units[name], unit)
		p.unitLen++
	}
	return p.units[name][length:], nil
}

func (p *FakeProvisioner) RemoveUnit(app provision.App, name string) error {
	if err := p.getError("RemoveUnit"); err != nil {
		return err
	}
	index := -1
	appName := app.GetName()
	if index := p.FindApp(app); index < 0 {
		return errors.New("App is not provisioned.")
	}
	p.unitMut.Lock()
	defer p.unitMut.Unlock()
	for i, unit := range p.units[appName] {
		if unit.Name == name {
			index = i
			break
		}
	}
	if index == -1 {
		return errors.New("Unit not found.")
	}
	copy(p.units[appName][index:], p.units[appName][index+1:])
	p.units[appName] = p.units[appName][:len(p.units[appName])-1]
	p.unitLen--
	return nil
}

func (p *FakeProvisioner) ExecuteCommand(stdout, stderr io.Writer, app provision.App, cmd string, args ...string) error {
	var (
		output []byte
		err    error
	)
	command := Cmd{
		Cmd:  cmd,
		Args: args,
		App:  app,
	}
	p.cmdMut.Lock()
	p.cmds = append(p.cmds, command)
	p.cmdMut.Unlock()
	select {
	case output = <-p.outputs:
		select {
		case fail := <-p.failures:
			if fail.method == "ExecuteCommand" {
				stderr.Write(output)
				return fail.err
			} else {
				p.failures <- fail
			}
		case <-time.After(1e6):
			stdout.Write(output)
		}
	case fail := <-p.failures:
		if fail.method == "ExecuteCommand" {
			err = fail.err
			select {
			case output = <-p.outputs:
				stderr.Write(output)
			case <-time.After(1e6):
			}
		} else {
			p.failures <- fail
		}
	case <-time.After(2e9):
		return errors.New("FakeProvisioner timed out waiting for output.")
	}
	return err
}

func (p *FakeProvisioner) CollectStatus() ([]provision.Unit, error) {
	if err := p.getError("CollectStatus"); err != nil {
		return nil, err
	}
	units := make([]provision.Unit, len(p.apps))
	for i, app := range p.apps {
		unit := provision.Unit{
			Name:       app.GetName() + "/0",
			AppName:    app.GetName(),
			Type:       app.GetFramework(),
			Status:     "started",
			InstanceId: fmt.Sprintf("i-0%d", 800+i+1),
			Ip:         "10.10.10." + strconv.Itoa(i+1),
			Machine:    i + 1,
		}
		units[i] = unit
	}
	return units, nil
}

func (p *FakeProvisioner) Addr(app provision.App) (string, error) {
	if err := p.getError("Addr"); err != nil {
		return "", err
	}
	return fmt.Sprintf("%s.fake-lb.tsuru.io", app.GetName()), nil
}

func (p *FakeProvisioner) InstallDeps(app provision.App, w io.Writer) error {
	return nil
}
<commit_msg>testing/provisioner.go: logging method call in InstallDeps<commit_after>// Copyright 2013 tsuru authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package testing

import (
	"errors"
	"fmt"
	"github.com/globocom/tsuru/deploy"
	"github.com/globocom/tsuru/provision"
	"io"
	"strconv"
	"strings"
	"sync"
	"time"
)

func init() {
	provision.Register("fake", &FakeProvisioner{})
}

// Fake implementation for provision.Unit.
type FakeUnit struct {
	Name       string
	Ip         string
	InstanceId string
	Machine    int
	Status     provision.Status
}

func (u *FakeUnit) GetName() string {
	return u.Name
}

func (u *FakeUnit) GetMachine() int {
	return u.Machine
}

func (u *FakeUnit) GetStatus() provision.Status {
	return u.Status
}

func (u *FakeUnit) GetInstanceId() string {
	return u.InstanceId
}

func (u *FakeUnit) GetIp() string {
	return u.Ip
}

// Fake implementation for provision.App.
type FakeApp struct {
	name      string
	framework string
	units     []provision.AppUnit
	logs      []string
	Commands  []string
}

func NewFakeApp(name, framework string, units int) *FakeApp {
	app := FakeApp{
		name:      name,
		framework: framework,
		units:     make([]provision.AppUnit, units),
	}
	namefmt := "%s/%d"
	for i := 0; i < units; i++ {
		app.units[i] = &FakeUnit{
			Name:       fmt.Sprintf(namefmt, name, i),
			Machine:    i + 1,
			Status:     provision.StatusStarted,
			Ip:         fmt.Sprintf("10.10.10.%d", i+1),
			InstanceId: fmt.Sprintf("i-0%d", i+1),
		}
	}
	return &app
}

func (a *FakeApp) Log(message, source string) error {
	a.logs = append(a.logs, source+message)
	return nil
}

func (a *FakeApp) GetName() string {
	return a.name
}

func (a *FakeApp) GetFramework() string {
	return a.framework
}

func (a *FakeApp) ProvisionUnits() []provision.AppUnit {
	return a.units
}

func (a *FakeApp) SetUnitStatus(s provision.Status, index int) {
	if index < len(a.units) {
		a.units[index].(*FakeUnit).Status = s
	}
}

func (a *FakeApp) Command(stdout, stderr io.Writer, cmdArgs ...string) error {
	a.Commands = append(a.Commands, strings.Join(cmdArgs, " "))
	return nil
}

func (a *FakeApp) Restart(w io.Writer) error {
	a.Commands = append(a.Commands, "restart")
	return nil
}

func (a *FakeApp) InstallDeps(io.Writer) error {
	a.Commands = append(a.Commands, "install deps")
	return nil
}

func (a *FakeApp) Run(cmd string, w io.Writer) error {
	a.Commands = append(a.Commands, fmt.Sprintf("ran %s", cmd))
	return nil
}

type Cmd struct {
	Cmd  string
	Args []string
	App  provision.App
}

type failure struct {
	method string
	err    error
}

// Fake implementation for provision.Provisioner.
type FakeProvisioner struct {
	apps     []provision.App
	units    map[string][]provision.Unit
	unitLen  uint
	cmds     []Cmd
	outputs  chan []byte
	failures chan failure
	cmdMut   sync.Mutex
	unitMut  sync.Mutex
	restarts map[string]int
	restMut  sync.Mutex
}

func NewFakeProvisioner() *FakeProvisioner {
	p := FakeProvisioner{}
	p.outputs = make(chan []byte, 8)
	p.failures = make(chan failure, 8)
	p.units = make(map[string][]provision.Unit)
	p.restarts = make(map[string]int)
	p.unitLen = 0
	return &p
}

func (p *FakeProvisioner) getError(method string) error {
	select {
	case fail := <-p.failures:
		if fail.method == method {
			return fail.err
		}
		p.failures <- fail
	case <-time.After(1e6):
	}
	return nil
}

func (p *FakeProvisioner) Restarts(app provision.App) int {
	p.restMut.Lock()
	defer p.restMut.Unlock()
	return p.restarts[app.GetName()]
}

func (p *FakeProvisioner) Deploy(app deploy.App, w io.Writer) error {
	w.Write([]byte("Deploy called"))
	return nil
}

// Returns the number of calls to restart.
// GetCmds returns a list of commands executed in an app. If you don't specify
// the command (an empty string), it will return all commands executed in the
// given app.
func (p *FakeProvisioner) GetCmds(cmd string, app provision.App) []Cmd {
	var cmds []Cmd
	p.cmdMut.Lock()
	for _, c := range p.cmds {
		if (cmd == "" || c.Cmd == cmd) && app.GetName() == c.App.GetName() {
			cmds = append(cmds, c)
		}
	}
	p.cmdMut.Unlock()
	return cmds
}

func (p *FakeProvisioner) FindApp(app provision.App) int {
	for i, a := range p.apps {
		if a.GetName() == app.GetName() {
			return i
		}
	}
	return -1
}

func (p *FakeProvisioner) GetUnits(app provision.App) []provision.Unit {
	p.unitMut.Lock()
	defer p.unitMut.Unlock()
	return p.units[app.GetName()]
}

func (p *FakeProvisioner) PrepareOutput(b []byte) {
	p.outputs <- b
}

func (p *FakeProvisioner) PrepareFailure(method string, err error) {
	p.failures <- failure{method, err}
}

func (p *FakeProvisioner) Reset() {
	p.unitMut.Lock()
	p.units = make(map[string][]provision.Unit)
	p.unitMut.Unlock()

	p.cmdMut.Lock()
	p.cmds = nil
	p.cmdMut.Unlock()

	p.restMut.Lock()
	p.restarts = make(map[string]int)
	p.restMut.Unlock()

	for {
		select {
		case <-p.outputs:
		case <-p.failures:
		default:
			return
		}
	}
}

func (p *FakeProvisioner) Provision(app provision.App) error {
	if err := p.getError("Provision"); err != nil {
		return err
	}
	index := p.FindApp(app)
	if index > -1 {
		return &provision.Error{Reason: "App already provisioned."}
	}
	p.apps = append(p.apps, app)
	p.unitMut.Lock()
	p.units[app.GetName()] = []provision.Unit{
		{
			Name:       app.GetName() + "/0",
			AppName:    app.GetName(),
			Type:       app.GetFramework(),
			Status:     provision.StatusStarted,
			InstanceId: "i-080",
			Ip:         "10.10.10.1",
			Machine:    1,
		},
	}
	p.unitLen++
	p.unitMut.Unlock()
	return nil
}

func (p *FakeProvisioner) Restart(app provision.App) error {
	if err := p.getError("Restart"); err != nil {
		return err
	}
	p.restMut.Lock()
	v := p.restarts[app.GetName()]
	v++
	p.restarts[app.GetName()] = v
	p.restMut.Unlock()
	return nil
}

func (p *FakeProvisioner) Destroy(app provision.App) error {
	if err := p.getError("Destroy"); err != nil {
		return err
	}
	index := p.FindApp(app)
	if index == -1 {
		return &provision.Error{Reason: "App is not provisioned."}
	}
	copy(p.apps[index:], p.apps[index+1:])
	p.apps = p.apps[:len(p.apps)-1]
	p.unitMut.Lock()
	delete(p.units, app.GetName())
	p.unitLen = 0
	p.unitMut.Unlock()
	p.restMut.Lock()
	delete(p.restarts, app.GetName())
	p.restMut.Unlock()
	return nil
}

func (p *FakeProvisioner) AddUnits(app provision.App, n uint) ([]provision.Unit, error) {
	if err := p.getError("AddUnits"); err != nil {
		return nil, err
	}
	if n == 0 {
		return nil, errors.New("Cannot add 0 units.")
	}
	index := p.FindApp(app)
	if index < 0 {
		return nil, errors.New("App is not provisioned.")
	}
	name := app.GetName()
	framework := app.GetFramework()
	p.unitMut.Lock()
	defer p.unitMut.Unlock()
	length := uint(len(p.units[name]))
	for i := uint(0); i < n; i++ {
		unit := provision.Unit{
			Name:       fmt.Sprintf("%s/%d", name, p.unitLen),
			AppName:    name,
			Type:       framework,
			Status:     provision.StatusStarted,
			InstanceId: fmt.Sprintf("i-08%d", length+i),
			Ip:         fmt.Sprintf("10.10.10.%d", length+i),
			Machine:    int(length + i),
		}
		p.units[name] = append(p.units[name], unit)
		p.unitLen++
	}
	return p.units[name][length:], nil
}

func (p *FakeProvisioner) RemoveUnit(app provision.App, name string) error {
	if err := p.getError("RemoveUnit"); err != nil {
		return err
	}
	index := -1
	appName := app.GetName()
	if index := p.FindApp(app); index < 0 {
		return errors.New("App is not provisioned.")
	}
	p.unitMut.Lock()
	defer p.unitMut.Unlock()
	for i, unit := range p.units[appName] {
		if unit.Name == name {
			index = i
			break
		}
	}
	if index == -1 {
		return errors.New("Unit not found.")
	}
	copy(p.units[appName][index:], p.units[appName][index+1:])
	p.units[appName] = p.units[appName][:len(p.units[appName])-1]
	p.unitLen--
	return nil
}

func (p *FakeProvisioner) ExecuteCommand(stdout, stderr io.Writer, app provision.App, cmd string, args ...string) error {
	var (
		output []byte
		err    error
	)
	command := Cmd{
		Cmd:  cmd,
		Args: args,
		App:  app,
	}
	p.cmdMut.Lock()
	p.cmds = append(p.cmds, command)
	p.cmdMut.Unlock()
	select {
	case output = <-p.outputs:
		select {
		case fail := <-p.failures:
			if fail.method == "ExecuteCommand" {
				stderr.Write(output)
				return fail.err
			} else {
				p.failures <- fail
			}
		case <-time.After(1e6):
			stdout.Write(output)
		}
	case fail := <-p.failures:
		if fail.method == "ExecuteCommand" {
			err = fail.err
			select {
			case output = <-p.outputs:
				stderr.Write(output)
			case <-time.After(1e6):
			}
		} else {
			p.failures <- fail
		}
	case <-time.After(2e9):
		return errors.New("FakeProvisioner timed out waiting for output.")
	}
	return err
}

func (p *FakeProvisioner) CollectStatus() ([]provision.Unit, error) {
	if err := p.getError("CollectStatus"); err != nil {
		return nil, err
	}
	units := make([]provision.Unit, len(p.apps))
	for i, app := range p.apps {
		unit := provision.Unit{
			Name:       app.GetName() + "/0",
			AppName:    app.GetName(),
			Type:       app.GetFramework(),
			Status:     "started",
			InstanceId: fmt.Sprintf("i-0%d", 800+i+1),
			Ip:         "10.10.10." + strconv.Itoa(i+1),
			Machine:    i + 1,
		}
		units[i] = unit
	}
	return units, nil
}

func (p *FakeProvisioner) Addr(app provision.App) (string, error) {
	if err := p.getError("Addr"); err != nil {
		return "", err
	}
	return fmt.Sprintf("%s.fake-lb.tsuru.io", app.GetName()), nil
}

func (p *FakeProvisioner) InstallDeps(app provision.App, w io.Writer) error {
	w.Write([]byte("InstallDeps called"))
	return nil
}
<|endoftext|>


<commit_before>// Copyright 2012 tsuru authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package testing

import (
	"errors"
	"github.com/globocom/tsuru/provision"
	"io"
	"strconv"
	"time"
)

func init() {
	provision.Register("fake", &FakeProvisioner{})
}

// Fake implementation for provision.Unit.
type FakeUnit struct {
	name    string
	machine int
	actions []string
}

func (u *FakeUnit) GetName() string {
	u.actions = append(u.actions, "getname")
	return u.name
}

func (u *FakeUnit) GetMachine() int {
	u.actions = append(u.actions, "getmachine")
	return u.machine
}

// Fake implementation for provision.App.
type FakeApp struct {
	name      string
	framework string
	units     []provision.AppUnit
	logs      []string
	actions   []string
}

func NewFakeApp(name, framework string, units int) *FakeApp {
	app := FakeApp{
		name:      name,
		framework: framework,
		units:     make([]provision.AppUnit, units),
	}
	for i := 0; i < units; i++ {
		app.units[i] = &FakeUnit{name: name, machine: i + 1}
	}
	return &app
}

func (a *FakeApp) Log(message, source string) error {
	a.logs = append(a.logs, source+message)
	a.actions = append(a.actions, "log "+source+" - "+message)
	return nil
}

func (a *FakeApp) GetName() string {
	a.actions = append(a.actions, "getname")
	return a.name
}

func (a *FakeApp) GetFramework() string {
	a.actions = append(a.actions, "getframework")
	return a.framework
}

func (a *FakeApp) ProvisionUnits() []provision.AppUnit {
	a.actions = append(a.actions, "getunits")
	return a.units
}

type Cmd struct {
	Cmd  string
	Args []string
	App  provision.App
}

type failure struct {
	method string
	err    error
}

// Fake implementation for provision.Provisioner.
type FakeProvisioner struct {
	apps     []provision.App
	Cmds     []Cmd
	outputs  chan []byte
	failures chan failure
}

func NewFakeProvisioner() *FakeProvisioner {
	p := FakeProvisioner{}
	p.outputs = make(chan []byte, 8)
	p.failures = make(chan failure, 8)
	return &p
}

func (p *FakeProvisioner) getError(method string) error {
	select {
	case fail := <-p.failures:
		if fail.method == method {
			return fail.err
		}
		p.failures <- fail
	case <-time.After(1e6):
	}
	return nil
}

// GetCmds returns a list of commands executed in an app. If you don't specify
// the command (""), it will return all commands executed in the given app.
func (p *FakeProvisioner) GetCmds(cmd string, app provision.App) []Cmd {
	var cmds []Cmd
	for _, c := range p.Cmds {
		if (cmd == "" || c.Cmd == cmd) && app.GetName() == c.App.GetName() {
			cmds = append(cmds, c)
		}
	}
	return cmds
}

func (p *FakeProvisioner) FindApp(app provision.App) int {
	for i, a := range p.apps {
		if a.GetName() == app.GetName() {
			return i
		}
	}
	return -1
}

func (p *FakeProvisioner) PrepareOutput(b []byte) {
	p.outputs <- b
}

func (p *FakeProvisioner) PrepareFailure(method string, err error) {
	p.failures <- failure{method, err}
}

func (p *FakeProvisioner) Reset() {
	close(p.outputs)
	close(p.failures)
	p.outputs = make(chan []byte, 8)
	p.failures = make(chan failure, 8)
	p.Cmds = nil
}

func (p *FakeProvisioner) Provision(app provision.App) error {
	if err := p.getError("Provision"); err != nil {
		return err
	}
	index := p.FindApp(app)
	if index > -1 {
		return &provision.Error{Reason: "App already provisioned."}
	}
	p.apps = append(p.apps, app)
	return nil
}

func (p *FakeProvisioner) Destroy(app provision.App) error {
	if err := p.getError("Destroy"); err != nil {
		return err
	}
	index := p.FindApp(app)
	if index == -1 {
		return &provision.Error{Reason: "App is not provisioned."}
	}
	copy(p.apps[index:], p.apps[index+1:])
	p.apps = p.apps[:len(p.apps)-1]
	return nil
}

func (p *FakeProvisioner) ExecuteCommand(stdout, stderr io.Writer, app provision.App, cmd string, args ...string) error {
	var (
		output []byte
		err    error
	)
	command := Cmd{
		Cmd:  cmd,
		Args: args,
		App:  app,
	}
	p.Cmds = append(p.Cmds, command)
	select {
	case output = <-p.outputs:
		select {
		case fail := <-p.failures:
			if fail.method == "ExecuteCommand" {
				stderr.Write(output)
				return fail.err
			} else {
				p.failures <- fail
			}
		case <-time.After(1e6):
			stdout.Write(output)
		}
	case fail := <-p.failures:
		if fail.method == "ExecuteCommand" {
			err = fail.err
			select {
			case output = <-p.outputs:
				stderr.Write(output)
			case <-time.After(1e6):
			}
		} else {
			p.failures <- fail
		}
	case <-time.After(2e9):
		return errors.New("FakeProvisiner timed out waiting for output.")
	}
	return err
}

func (p *FakeProvisioner) CollectStatus() ([]provision.Unit, error) {
	if err := p.getError("CollectStatus"); err != nil {
		return nil, err
	}
	units := make([]provision.Unit, len(p.apps))
	for i, app := range p.apps {
		unit := provision.Unit{
			Name:    "somename",
			AppName: app.GetName(),
			Type:    app.GetFramework(),
			Status:  "started",
			Ip:      "10.10.10." + strconv.Itoa(i+1),
			Machine: i + 1,
		}
		units = append(units, unit)
	}
	return units, nil
}
<commit_msg>testing: implement GetStatus method in FakeUnit<commit_after>// Copyright 2012 tsuru authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package testing

import (
	"errors"
	"github.com/globocom/tsuru/provision"
	"io"
	"strconv"
	"time"
)

func init() {
	provision.Register("fake", &FakeProvisioner{})
}

// Fake implementation for provision.Unit.
type FakeUnit struct {
	name    string
	machine int
	status  provision.Status
	actions []string
}

func (u *FakeUnit) GetName() string {
	u.actions = append(u.actions, "getname")
	return u.name
}

func (u *FakeUnit) GetMachine() int {
	u.actions = append(u.actions, "getmachine")
	return u.machine
}

func (u *FakeUnit) GetStatus() provision.Status {
	return u.status
}

// Fake implementation for provision.App.
type FakeApp struct {
	name      string
	framework string
	units     []provision.AppUnit
	logs      []string
	actions   []string
}

func NewFakeApp(name, framework string, units int) *FakeApp {
	app := FakeApp{
		name:      name,
		framework: framework,
		units:     make([]provision.AppUnit, units),
	}
	for i := 0; i < units; i++ {
		app.units[i] = &FakeUnit{name: name, machine: i + 1}
	}
	return &app
}

func (a *FakeApp) Log(message, source string) error {
	a.logs = append(a.logs, source+message)
	a.actions = append(a.actions, "log "+source+" - "+message)
	return nil
}

func (a *FakeApp) GetName() string {
	a.actions = append(a.actions, "getname")
	return a.name
}

func (a *FakeApp) GetFramework() string {
	a.actions = append(a.actions, "getframework")
	return a.framework
}

func (a *FakeApp) ProvisionUnits() []provision.AppUnit {
	a.actions = append(a.actions, "getunits")
	return a.units
}

type Cmd struct {
	Cmd  string
	Args []string
	App  provision.App
}

type failure struct {
	method string
	err    error
}

// Fake implementation for provision.Provisioner.
type FakeProvisioner struct {
	apps     []provision.App
	Cmds     []Cmd
	outputs  chan []byte
	failures chan failure
}

func NewFakeProvisioner() *FakeProvisioner {
	p := FakeProvisioner{}
	p.outputs = make(chan []byte, 8)
	p.failures = make(chan failure, 8)
	return &p
}

func (p *FakeProvisioner) getError(method string) error {
	select {
	case fail := <-p.failures:
		if fail.method == method {
			return fail.err
		}
		p.failures <- fail
	case <-time.After(1e6):
	}
	return nil
}

// GetCmds returns a list of commands executed in an app. If you don't specify
// the command (""), it will return all commands executed in the given app.
func (p *FakeProvisioner) GetCmds(cmd string, app provision.App) []Cmd {
	var cmds []Cmd
	for _, c := range p.Cmds {
		if (cmd == "" || c.Cmd == cmd) && app.GetName() == c.App.GetName() {
			cmds = append(cmds, c)
		}
	}
	return cmds
}

func (p *FakeProvisioner) FindApp(app provision.App) int {
	for i, a := range p.apps {
		if a.GetName() == app.GetName() {
			return i
		}
	}
	return -1
}

func (p *FakeProvisioner) PrepareOutput(b []byte) {
	p.outputs <- b
}

func (p *FakeProvisioner) PrepareFailure(method string, err error) {
	p.failures <- failure{method, err}
}

func (p *FakeProvisioner) Reset() {
	close(p.outputs)
	close(p.failures)
	p.outputs = make(chan []byte, 8)
	p.failures = make(chan failure, 8)
	p.Cmds = nil
}

func (p *FakeProvisioner) Provision(app provision.App) error {
	if err := p.getError("Provision"); err != nil {
		return err
	}
	index := p.FindApp(app)
	if index > -1 {
		return &provision.Error{Reason: "App already provisioned."}
	}
	p.apps = append(p.apps, app)
	return nil
}

func (p *FakeProvisioner) Destroy(app provision.App) error {
	if err := p.getError("Destroy"); err != nil {
		return err
	}
	index := p.FindApp(app)
	if index == -1 {
		return &provision.Error{Reason: "App is not provisioned."}
	}
	copy(p.apps[index:], p.apps[index+1:])
	p.apps = p.apps[:len(p.apps)-1]
	return nil
}

func (p *FakeProvisioner) ExecuteCommand(stdout, stderr io.Writer, app provision.App, cmd string, args ...string) error {
	var (
		output []byte
		err    error
	)
	command := Cmd{
		Cmd:  cmd,
		Args: args,
		App:  app,
	}
	p.Cmds = append(p.Cmds, command)
	select {
	case output = <-p.outputs:
		select {
		case fail := <-p.failures:
			if fail.method == "ExecuteCommand" {
				stderr.Write(output)
				return fail.err
			} else {
				p.failures <- fail
			}
		case <-time.After(1e6):
			stdout.Write(output)
		}
	case fail := <-p.failures:
		if fail.method == "ExecuteCommand" {
			err = fail.err
			select {
			case output = <-p.outputs:
				stderr.Write(output)
			case <-time.After(1e6):
			}
		} else {
			p.failures <- fail
		}
	case <-time.After(2e9):
		return errors.New("FakeProvisiner timed out waiting for output.")
	}
	return err
}

func (p *FakeProvisioner) CollectStatus() ([]provision.Unit, error) {
	if err := p.getError("CollectStatus"); err != nil {
		return nil, err
	}
	units := make([]provision.Unit, len(p.apps))
	for i, app := range p.apps {
		unit := provision.Unit{
			Name:    "somename",
			AppName: app.GetName(),
			Type:    app.GetFramework(),
			Status:  "started",
			Ip:      "10.10.10." + strconv.Itoa(i+1),
			Machine: i + 1,
		}
		units = append(units, unit)
	}
	return units, nil
}
<|endoftext|>


<commit_before>package pop

// SQLite is currently not supported due to cgo issues

import (
	"fmt"
	"log"
	"os"
	"path/filepath"
	"sync"
	"time"

	"github.com/markbates/going/defaults"
	. "github.com/markbates/pop/columns"
	"github.com/markbates/pop/fizz"
	"github.com/markbates/pop/fizz/translators"
)

type SQLite struct {
	gil               *sync.Mutex
	ConnectionDetails *ConnectionDetails
}

func (m *SQLite) Details() *ConnectionDetails {
	return m.ConnectionDetails
}

func (m *SQLite) URL() string {
	return m.ConnectionDetails.Database + "?cache=shared&mode=rwc"
}

func (m *SQLite) MigrationURL() string {
	return m.ConnectionDetails.URL
}

func (m *SQLite) Create(store Store, model *Model, cols Columns) error {
	return genericCreate(store, model, cols)

}

func (m *SQLite) Update(store Store, model *Model, cols Columns) error {
	return genericUpdate(store, model, cols)

}

func (m *SQLite) Destroy(store Store, model *Model) error {
	return genericDestroy(store, model)

}

func (m *SQLite) SelectOne(store Store, model *Model, query Query) error {
	return genericSelectOne(store, model, query)
}

func (m *SQLite) SelectMany(store Store, models *Model, query Query) error {
	return genericSelectMany(store, models, query)
}

func (m *SQLite) Lock(fn func() error) error {
	if defaults.String(m.Details().Options["lock"], "true") == "true" {
		defer m.gil.Unlock()
		m.gil.Lock()
	}
	err := fn()
	attempts := 0
	for err != nil && err.Error() == "database is locked" && attempts <= m.Details().RetryLimit() {
		time.Sleep(m.Details().RetrySleep())
		err = fn()
		attempts++
	}
	return err
}

func (m *SQLite) CreateDB() error {
	d := filepath.Dir(m.ConnectionDetails.Database)
	err := os.MkdirAll(d, 0766)
	if err != nil {
		log.Println(err)
	}
	return err
}

func (m *SQLite) DropDB() error {
	return os.Remove(m.ConnectionDetails.Database)
}

func (m *SQLite) TranslateSQL(sql string) string {
	return sql
}

func (m *SQLite) FizzTranslator() fizz.Translator {
	return translators.NewSQLite(m.Details().Database)
}

func NewSQLite(deets *ConnectionDetails) Dialect {
	deets.URL = fmt.Sprintf("sqlite3://%s", deets.Database)
	cd := &SQLite{
		gil:               &sync.Mutex{},
		ConnectionDetails: deets,
	}

	return cd
}
<commit_msg>do more locking with sqlite<commit_after>package pop

// SQLite is currently not supported due to cgo issues

import (
	"fmt"
	"log"
	"os"
	"path/filepath"
	"sync"
	"time"

	"github.com/markbates/going/defaults"
	. "github.com/markbates/pop/columns"
	"github.com/markbates/pop/fizz"
	"github.com/markbates/pop/fizz/translators"
)

type SQLite struct {
	gil               *sync.Mutex
	ConnectionDetails *ConnectionDetails
}

func (m *SQLite) Details() *ConnectionDetails {
	return m.ConnectionDetails
}

func (m *SQLite) URL() string {
	return m.ConnectionDetails.Database + "?cache=shared&mode=rwc"
}

func (m *SQLite) MigrationURL() string {
	return m.ConnectionDetails.URL
}

func (m *SQLite) Create(store Store, model *Model, cols Columns) error {
	return m.Lock(func() error {
		return genericCreate(store, model, cols)
	})
}

func (m *SQLite) Update(store Store, model *Model, cols Columns) error {
	return m.Lock(func() error {
		return genericUpdate(store, model, cols)
	})
}

func (m *SQLite) Destroy(store Store, model *Model) error {
	return m.Lock(func() error {
		return genericDestroy(store, model)
	})
}

func (m *SQLite) SelectOne(store Store, model *Model, query Query) error {
	return m.Lock(func() error {
		return genericSelectOne(store, model, query)
	})
}

func (m *SQLite) SelectMany(store Store, models *Model, query Query) error {
	return m.Lock(func() error {
		return genericSelectMany(store, models, query)
	})
}

func (m *SQLite) Lock(fn func() error) error {
	if defaults.String(m.Details().Options["lock"], "true") == "true" {
		defer m.gil.Unlock()
		m.gil.Lock()
	}
	err := fn()
	attempts := 0
	for err != nil && err.Error() == "database is locked" && attempts <= m.Details().RetryLimit() {
		time.Sleep(m.Details().RetrySleep())
		err = fn()
		attempts++
	}
	return err
}

func (m *SQLite) CreateDB() error {
	d := filepath.Dir(m.ConnectionDetails.Database)
	err := os.MkdirAll(d, 0766)
	if err != nil {
		log.Println(err)
	}
	return err
}

func (m *SQLite) DropDB() error {
	return os.Remove(m.ConnectionDetails.Database)
}

func (m *SQLite) TranslateSQL(sql string) string {
	return sql
}

func (m *SQLite) FizzTranslator() fizz.Translator {
	return translators.NewSQLite(m.Details().Database)
}

func NewSQLite(deets *ConnectionDetails) Dialect {
	deets.URL = fmt.Sprintf("sqlite3://%s", deets.Database)
	cd := &SQLite{
		gil:               &sync.Mutex{},
		ConnectionDetails: deets,
	}

	return cd
}
<|endoftext|>


<commit_before>/*
Copyright 2018 The Kubernetes Authors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package internal

import (
	"bytes"

	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"

	"sigs.k8s.io/structured-merge-diff/fieldpath"
)

// EmptyFields represents a set with no paths
// It looks like metav1.Fields{Raw: []byte("{}")}
var EmptyFields metav1.FieldsV1 = func() metav1.FieldsV1 {
	f, err := SetToFields(*fieldpath.NewSet())
	if err != nil {
		panic("should never happen")
	}
	return f
}()

// FieldsToSet creates a set paths from an input trie of fields
func FieldsToSet(f metav1.FieldsV1) (s fieldpath.Set, err error) {
	err = s.FromJSON(bytes.NewReader(f.Raw))
	return s, err
}

// SetToFields creates a trie of fields from an input set of paths
func SetToFields(s fieldpath.Set) (f metav1.FieldsV1, err error) {
	f.Raw, err = s.ToJSON()
	return f, err
}
<commit_msg>Fix golint failure not contained in .golint_failures<commit_after>/*
Copyright 2018 The Kubernetes Authors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package internal

import (
	"bytes"

	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"

	"sigs.k8s.io/structured-merge-diff/fieldpath"
)

// EmptyFields represents a set with no paths
// It looks like metav1.Fields{Raw: []byte("{}")}
var EmptyFields = func() metav1.FieldsV1 {
	f, err := SetToFields(*fieldpath.NewSet())
	if err != nil {
		panic("should never happen")
	}
	return f
}()

// FieldsToSet creates a set paths from an input trie of fields
func FieldsToSet(f metav1.FieldsV1) (s fieldpath.Set, err error) {
	err = s.FromJSON(bytes.NewReader(f.Raw))
	return s, err
}

// SetToFields creates a trie of fields from an input set of paths
func SetToFields(s fieldpath.Set) (f metav1.FieldsV1, err error) {
	f.Raw, err = s.ToJSON()
	return f, err
}
<|endoftext|>


<commit_before>package config_test

import (
	"reflect"
	"testing"

	"github.com/EscherAuth/escher/config"
	. "github.com/EscherAuth/escher/testing/env"
	"github.com/stretchr/testify/assert"
)

var exampleEscherConfig = `
{
    "vendorKey": 		"ZZ",
    "algoPrefix": 		"VV",
    "hashAlgo": 		"SHA512",
	"credentialScope": 	"us-east-1/host/aws4_request",
	"authHeaderName": "X-Escher-Auth",
	"dateHeaderName": "X-Escher-Date"
}
`

func TestNewFromENV_ConfigJSONIsPresentInTheEnv(t *testing.T) {
	defer SetEnvForTheTest(t, "ESCHER_CONFIG", exampleEscherConfig)()

	config, err := config.NewFromENV()

	if err != nil {
		t.Fatal(err)
	}

	assert.Equal(t, "ZZ", config.VendorKey)
	assert.Equal(t, "VV", config.AlgoPrefix)
	assert.Equal(t, "SHA512", config.HashAlgo)
	assert.Equal(t, "us-east-1/host/aws4_request", config.CredentialScope)
	assert.Equal(t, "", config.Date)

}

func TestNewFromENV_ValidJSONIsPresentButOnlyCredentialScopeIsProvided(t *testing.T) {
	defer SetEnvForTheTest(t, "ESCHER_CONFIG", `{"credentialScope": "a/b/c"}`)()

	config, err := config.NewFromENV()

	if err != nil {
		t.Fatal(err)
	}

	assert.Equal(t, "ESR", config.AlgoPrefix)
	assert.Equal(t, "SHA256", config.HashAlgo)
	assert.Equal(t, "Escher", config.VendorKey)
	assert.Equal(t, "X-Escher-Auth", config.AuthHeaderName)
	assert.Equal(t, "X-Escher-Date", config.DateHeaderName)
	assert.Equal(t, "a/b/c", config.CredentialScope)

}

func TestNewFromENV_EveryValueIsProvidedInEnvVariables(t *testing.T) {
	defer UnsetEnvForTheTest(t, "ESCHER_CONFIG")()
	defer SetEnvForTheTest(t, "ESCHER_ALGO_PREFIX", "ALGO_PREFIX")()
	defer SetEnvForTheTest(t, "ESCHER_HASH_ALGO", "HASH_ALGO")()
	defer SetEnvForTheTest(t, "ESCHER_VENDOR_KEY", "VENDOR_KEY")()
	defer SetEnvForTheTest(t, "ESCHER_AUTH_HEADER_NAME", "AUTH_HEADER_NAME")()
	defer SetEnvForTheTest(t, "ESCHER_DATE_HEADER_NAME", "DATE_HEADER_NAME")()
	defer SetEnvForTheTest(t, "ESCHER_CREDENTIAL_SCOPE", "CREDENTIAL_SCOPE")()

	config, err := config.NewFromENV()

	if err != nil {
		t.Fatal(err)
	}

	assert.Equal(t, "ALGO_PREFIX", config.AlgoPrefix)
	assert.Equal(t, "HASH_ALGO", config.HashAlgo)
	assert.Equal(t, "VENDOR_KEY", config.VendorKey)
	assert.Equal(t, "AUTH_HEADER_NAME", config.AuthHeaderName)
	assert.Equal(t, "DATE_HEADER_NAME", config.DateHeaderName)
	assert.Equal(t, "CREDENTIAL_SCOPE", config.CredentialScope)
}

func TestNewFromENV_OneValueAtLeastProvidedInTheENVWithExplicitValueSetting(t *testing.T) {
	defer UnsetEnvForTheTest(t, "ESCHER_CONFIG")()
	defer SetEnvForTheTest(t, "ESCHER_CREDENTIAL_SCOPE", "TEST")()

	cases := map[string]string{
		"ESCHER_ALGO_PREFIX":      "AlgoPrefix",
		"ESCHER_HASH_ALGO":        "HashAlgo",
		"ESCHER_VENDOR_KEY":       "VendorKey",
		"ESCHER_AUTH_HEADER_NAME": "AuthHeaderName",
		"ESCHER_DATE_HEADER_NAME": "DateHeaderName",
		"ESCHER_CREDENTIAL_SCOPE": "CredentialScope",
	}

	for envKey, envValue := range cases {
		tearDown := SetEnvForTheTest(t, envKey, envValue)

		config, err := config.NewFromENV()

		if err != nil {
			t.Fatal(err)
		}

		r := reflect.ValueOf(config)
		actuallyValue := reflect.Indirect(r).FieldByName(envValue).String()
		assert.Equal(t, envValue, actuallyValue)

		tearDown()
	}

}

func TestNewFromENV_InvalidJSONConfig_ErrorReturned(t *testing.T) {
	defer SetEnvForTheTest(t, "ESCHER_CONFIG", `{credentialScope:"not/valid/json"}`)()

	_, err := config.NewFromENV()

	assert.NotNil(t, err)
}

func TestNewFromENV_CredentialScopeIsNotGiven_ErrorIsReturned(t *testing.T) {
	defer UnsetEnvForTheTest(t, "ESCHER_CREDENTIAL_SCOPE")

	_, err := config.NewFromENV()

	assert.Error(t, err, "Credential Scope is missing")
}
<commit_msg>fix helper missuse, the actual env setup was never fired before.<commit_after>package config_test

import (
	"reflect"
	"testing"

	"github.com/EscherAuth/escher/config"
	. "github.com/EscherAuth/escher/testing/env"
	"github.com/stretchr/testify/assert"
)

var exampleEscherConfig = `
{
    "vendorKey": 		"ZZ",
    "algoPrefix": 		"VV",
    "hashAlgo": 		"SHA512",
	"credentialScope": 	"us-east-1/host/aws4_request",
	"authHeaderName": "X-Escher-Auth",
	"dateHeaderName": "X-Escher-Date"
}
`

func TestNewFromENV_ConfigJSONIsPresentInTheEnv(t *testing.T) {
	defer SetEnvForTheTest(t, "ESCHER_CONFIG", exampleEscherConfig)()

	config, err := config.NewFromENV()

	if err != nil {
		t.Fatal(err)
	}

	assert.Equal(t, "ZZ", config.VendorKey)
	assert.Equal(t, "VV", config.AlgoPrefix)
	assert.Equal(t, "SHA512", config.HashAlgo)
	assert.Equal(t, "us-east-1/host/aws4_request", config.CredentialScope)
	assert.Equal(t, "", config.Date)

}

func TestNewFromENV_ValidJSONIsPresentButOnlyCredentialScopeIsProvided(t *testing.T) {
	defer SetEnvForTheTest(t, "ESCHER_CONFIG", `{"credentialScope": "a/b/c"}`)()

	config, err := config.NewFromENV()

	if err != nil {
		t.Fatal(err)
	}

	assert.Equal(t, "ESR", config.AlgoPrefix)
	assert.Equal(t, "SHA256", config.HashAlgo)
	assert.Equal(t, "Escher", config.VendorKey)
	assert.Equal(t, "X-Escher-Auth", config.AuthHeaderName)
	assert.Equal(t, "X-Escher-Date", config.DateHeaderName)
	assert.Equal(t, "a/b/c", config.CredentialScope)

}

func TestNewFromENV_EveryValueIsProvidedInEnvVariables(t *testing.T) {
	defer UnsetEnvForTheTest(t, "ESCHER_CONFIG")()
	defer SetEnvForTheTest(t, "ESCHER_ALGO_PREFIX", "ALGO_PREFIX")()
	defer SetEnvForTheTest(t, "ESCHER_HASH_ALGO", "HASH_ALGO")()
	defer SetEnvForTheTest(t, "ESCHER_VENDOR_KEY", "VENDOR_KEY")()
	defer SetEnvForTheTest(t, "ESCHER_AUTH_HEADER_NAME", "AUTH_HEADER_NAME")()
	defer SetEnvForTheTest(t, "ESCHER_DATE_HEADER_NAME", "DATE_HEADER_NAME")()
	defer SetEnvForTheTest(t, "ESCHER_CREDENTIAL_SCOPE", "CREDENTIAL_SCOPE")()

	config, err := config.NewFromENV()

	if err != nil {
		t.Fatal(err)
	}

	assert.Equal(t, "ALGO_PREFIX", config.AlgoPrefix)
	assert.Equal(t, "HASH_ALGO", config.HashAlgo)
	assert.Equal(t, "VENDOR_KEY", config.VendorKey)
	assert.Equal(t, "AUTH_HEADER_NAME", config.AuthHeaderName)
	assert.Equal(t, "DATE_HEADER_NAME", config.DateHeaderName)
	assert.Equal(t, "CREDENTIAL_SCOPE", config.CredentialScope)
}

func TestNewFromENV_OneValueAtLeastProvidedInTheENVWithExplicitValueSetting(t *testing.T) {
	defer UnsetEnvForTheTest(t, "ESCHER_CONFIG")()
	defer SetEnvForTheTest(t, "ESCHER_CREDENTIAL_SCOPE", "TEST")()

	cases := map[string]string{
		"ESCHER_ALGO_PREFIX":      "AlgoPrefix",
		"ESCHER_HASH_ALGO":        "HashAlgo",
		"ESCHER_VENDOR_KEY":       "VendorKey",
		"ESCHER_AUTH_HEADER_NAME": "AuthHeaderName",
		"ESCHER_DATE_HEADER_NAME": "DateHeaderName",
		"ESCHER_CREDENTIAL_SCOPE": "CredentialScope",
	}

	for envKey, envValue := range cases {
		tearDown := SetEnvForTheTest(t, envKey, envValue)

		config, err := config.NewFromENV()

		if err != nil {
			t.Fatal(err)
		}

		r := reflect.ValueOf(config)
		actuallyValue := reflect.Indirect(r).FieldByName(envValue).String()
		assert.Equal(t, envValue, actuallyValue)

		tearDown()
	}

}

func TestNewFromENV_InvalidJSONConfig_ErrorReturned(t *testing.T) {
	defer SetEnvForTheTest(t, "ESCHER_CONFIG", `{credentialScope:"not/valid/json"}`)()

	_, err := config.NewFromENV()

	assert.NotNil(t, err)
}

func TestNewFromENV_CredentialScopeIsNotGiven_ErrorIsReturned(t *testing.T) {
	defer UnsetEnvForTheTest(t, "ESCHER_CREDENTIAL_SCOPE")()

	_, err := config.NewFromENV()

	assert.Error(t, err, "Credential Scope is missing")
}
<|endoftext|>


<commit_before>// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package os

import (
	"io"
	"runtime"
	"sync"
	"syscall"
	"unicode/utf16"
	"unicode/utf8"
)

// File represents an open file descriptor.
type File struct {
	*file
}

// file is the real representation of *File.
// The extra level of indirection ensures that no clients of os
// can overwrite this data, which could cause the finalizer
// to close the wrong file descriptor.
type file struct {
	fd      syscall.Handle
	name    string
	dirinfo *dirInfo   // nil unless directory being read
	l       sync.Mutex // used to implement windows pread/pwrite

	// only for console io
	isConsole bool
	lastbits  []byte // first few bytes of the last incomplete rune in last write
}

// Fd returns the Windows handle referencing the open file.
func (file *File) Fd() uintptr {
	if file == nil {
		return uintptr(syscall.InvalidHandle)
	}
	return uintptr(file.fd)
}

// NewFile returns a new File with the given file descriptor and name.
func NewFile(fd uintptr, name string) *File {
	h := syscall.Handle(fd)
	if h == syscall.InvalidHandle {
		return nil
	}
	f := &File{&file{fd: h, name: name}}
	var m uint32
	if syscall.GetConsoleMode(f.fd, &m) == nil {
		f.isConsole = true
	}
	runtime.SetFinalizer(f.file, (*file).close)
	return f
}

// Auxiliary information if the File describes a directory
type dirInfo struct {
	data     syscall.Win32finddata
	needdata bool
	path     string
}

func epipecheck(file *File, e error) {
}

const DevNull = "NUL"

func (f *file) isdir() bool { return f != nil && f.dirinfo != nil }

func openFile(name string, flag int, perm FileMode) (file *File, err error) {
	r, e := syscall.Open(name, flag|syscall.O_CLOEXEC, syscallMode(perm))
	if e != nil {
		return nil, &PathError{"open", name, e}
	}

	// There's a race here with fork/exec, which we are
	// content to live with.  See ../syscall/exec.go
	if syscall.O_CLOEXEC == 0 { // O_CLOEXEC not supported
		syscall.CloseOnExec(r)
	}

	return NewFile(uintptr(r), name), nil
}

func openDir(name string) (file *File, err error) {
	maskp, e := syscall.UTF16PtrFromString(name + `\*`)
	if e != nil {
		return nil, &PathError{"open", name, e}
	}
	d := new(dirInfo)
	r, e := syscall.FindFirstFile(maskp, &d.data)
	if e != nil {
		return nil, &PathError{"open", name, e}
	}
	d.path = name
	if !isAbs(d.path) {
		cwd, _ := Getwd()
		d.path = cwd + `\` + d.path
	}
	f := NewFile(uintptr(r), name)
	f.dirinfo = d
	return f, nil
}

// OpenFile is the generalized open call; most users will use Open
// or Create instead.  It opens the named file with specified flag
// (O_RDONLY etc.) and perm, (0666 etc.) if applicable.  If successful,
// methods on the returned File can be used for I/O.
// If there is an error, it will be of type *PathError.
func OpenFile(name string, flag int, perm FileMode) (file *File, err error) {
	if name == "" {
		return nil, &PathError{"open", name, syscall.ENOENT}
	}
	// TODO(brainman): not sure about my logic of assuming it is dir first, then fall back to file
	r, e := openDir(name)
	if e == nil {
		if flag&O_WRONLY != 0 || flag&O_RDWR != 0 {
			r.Close()
			return nil, &PathError{"open", name, syscall.EISDIR}
		}
		return r, nil
	}
	r, e = openFile(name, flag, perm)
	if e == nil {
		return r, nil
	}
	return nil, e
}

// Close closes the File, rendering it unusable for I/O.
// It returns an error, if any.
func (file *File) Close() error {
	return file.file.close()
}

func (file *file) close() error {
	if file == nil || file.fd == syscall.InvalidHandle {
		return syscall.EINVAL
	}
	var e error
	if file.isdir() {
		e = syscall.FindClose(syscall.Handle(file.fd))
	} else {
		e = syscall.CloseHandle(syscall.Handle(file.fd))
	}
	var err error
	if e != nil {
		err = &PathError{"close", file.name, e}
	}
	file.fd = syscall.InvalidHandle // so it can't be closed again

	// no need for a finalizer anymore
	runtime.SetFinalizer(file, nil)
	return err
}

func (file *File) readdir(n int) (fi []FileInfo, err error) {
	if file == nil || file.fd == syscall.InvalidHandle {
		return nil, syscall.EINVAL
	}
	if !file.isdir() {
		return nil, &PathError{"Readdir", file.name, syscall.ENOTDIR}
	}
	wantAll := n <= 0
	size := n
	if wantAll {
		n = -1
		size = 100
	}
	fi = make([]FileInfo, 0, size) // Empty with room to grow.
	d := &file.dirinfo.data
	for n != 0 {
		if file.dirinfo.needdata {
			e := syscall.FindNextFile(syscall.Handle(file.fd), d)
			if e != nil {
				if e == syscall.ERROR_NO_MORE_FILES {
					break
				} else {
					err = &PathError{"FindNextFile", file.name, e}
					if !wantAll {
						fi = nil
					}
					return
				}
			}
		}
		file.dirinfo.needdata = true
		name := string(syscall.UTF16ToString(d.FileName[0:]))
		if name == "." || name == ".." { // Useless names
			continue
		}
		f := &fileStat{
			name:    name,
			size:    mkSize(d.FileSizeHigh, d.FileSizeLow),
			modTime: mkModTime(d.LastWriteTime),
			mode:    mkMode(d.FileAttributes),
			sys:     mkSys(file.dirinfo.path+`\`+name, d.LastAccessTime, d.CreationTime),
		}
		n--
		fi = append(fi, f)
	}
	if !wantAll && len(fi) == 0 {
		return fi, io.EOF
	}
	return fi, nil
}

// read reads up to len(b) bytes from the File.
// It returns the number of bytes read and an error, if any.
func (f *File) read(b []byte) (n int, err error) {
	f.l.Lock()
	defer f.l.Unlock()
	return syscall.Read(f.fd, b)
}

// pread reads len(b) bytes from the File starting at byte offset off.
// It returns the number of bytes read and the error, if any.
// EOF is signaled by a zero count with err set to 0.
func (f *File) pread(b []byte, off int64) (n int, err error) {
	f.l.Lock()
	defer f.l.Unlock()
	curoffset, e := syscall.Seek(f.fd, 0, 1)
	if e != nil {
		return 0, e
	}
	defer syscall.Seek(f.fd, curoffset, 0)
	o := syscall.Overlapped{
		OffsetHigh: uint32(off >> 32),
		Offset:     uint32(off),
	}
	var done uint32
	e = syscall.ReadFile(syscall.Handle(f.fd), b, &done, &o)
	if e != nil {
		return 0, e
	}
	return int(done), nil
}

// writeConsole writes len(b) bytes to the console File.
// It returns the number of bytes written and an error, if any.
func (f *File) writeConsole(b []byte) (n int, err error) {
	n = len(b)
	runes := make([]rune, 0, 256)
	if len(f.lastbits) > 0 {
		b = append(f.lastbits, b...)
		f.lastbits = nil

	}
	for len(b) >= utf8.UTFMax || utf8.FullRune(b) {
		r, l := utf8.DecodeRune(b)
		runes = append(runes, r)
		b = b[l:]
	}
	if len(b) > 0 {
		f.lastbits = make([]byte, len(b))
		copy(f.lastbits, b)
	}
	// syscall.WriteConsole seems to fail, if given large buffer.
	// So limit the buffer to 16000 characters. This number was
	// discovered by experimenting with syscall.WriteConsole.
	const maxWrite = 16000
	for len(runes) > 0 {
		m := len(runes)
		if m > maxWrite {
			m = maxWrite
		}
		chunk := runes[:m]
		runes = runes[m:]
		uint16s := utf16.Encode(chunk)
		for len(uint16s) > 0 {
			var written uint32
			err = syscall.WriteConsole(f.fd, &uint16s[0], uint32(len(uint16s)), &written, nil)
			if err != nil {
				return 0, nil
			}
			uint16s = uint16s[written:]
		}
	}
	return n, nil
}

// write writes len(b) bytes to the File.
// It returns the number of bytes written and an error, if any.
func (f *File) write(b []byte) (n int, err error) {
	f.l.Lock()
	defer f.l.Unlock()
	if f.isConsole {
		return f.writeConsole(b)
	}
	return syscall.Write(f.fd, b)
}

// pwrite writes len(b) bytes to the File starting at byte offset off.
// It returns the number of bytes written and an error, if any.
func (f *File) pwrite(b []byte, off int64) (n int, err error) {
	f.l.Lock()
	defer f.l.Unlock()
	curoffset, e := syscall.Seek(f.fd, 0, 1)
	if e != nil {
		return 0, e
	}
	defer syscall.Seek(f.fd, curoffset, 0)
	o := syscall.Overlapped{
		OffsetHigh: uint32(off >> 32),
		Offset:     uint32(off),
	}
	var done uint32
	e = syscall.WriteFile(syscall.Handle(f.fd), b, &done, &o)
	if e != nil {
		return 0, e
	}
	return int(done), nil
}

// seek sets the offset for the next Read or Write on file to offset, interpreted
// according to whence: 0 means relative to the origin of the file, 1 means
// relative to the current offset, and 2 means relative to the end.
// It returns the new offset and an error, if any.
func (f *File) seek(offset int64, whence int) (ret int64, err error) {
	f.l.Lock()
	defer f.l.Unlock()
	return syscall.Seek(f.fd, offset, whence)
}

// Truncate changes the size of the named file.
// If the file is a symbolic link, it changes the size of the link's target.
func Truncate(name string, size int64) error {
	f, e := OpenFile(name, O_WRONLY|O_CREATE, 0666)
	if e != nil {
		return e
	}
	defer f.Close()
	e1 := f.Truncate(size)
	if e1 != nil {
		return e1
	}
	return nil
}

// Remove removes the named file or directory.
// If there is an error, it will be of type *PathError.
func Remove(name string) error {
	p, e := syscall.UTF16PtrFromString(name)
	if e != nil {
		return &PathError{"remove", name, e}
	}

	// Go file interface forces us to know whether
	// name is a file or directory. Try both.
	e = syscall.DeleteFile(p)
	if e == nil {
		return nil
	}
	e1 := syscall.RemoveDirectory(p)
	if e1 == nil {
		return nil
	}

	// Both failed: figure out which error to return.
	if e1 != e {
		a, e2 := syscall.GetFileAttributes(p)
		if e2 != nil {
			e = e2
		} else {
			if a&syscall.FILE_ATTRIBUTE_DIRECTORY != 0 {
				e = e1
			}
		}
	}
	return &PathError{"remove", name, e}
}

// Pipe returns a connected pair of Files; reads from r return bytes written to w.
// It returns the files and an error, if any.
func Pipe() (r *File, w *File, err error) {
	var p [2]syscall.Handle

	// See ../syscall/exec.go for description of lock.
	syscall.ForkLock.RLock()
	e := syscall.Pipe(p[0:])
	if e != nil {
		syscall.ForkLock.RUnlock()
		return nil, nil, NewSyscallError("pipe", e)
	}
	syscall.CloseOnExec(p[0])
	syscall.CloseOnExec(p[1])
	syscall.ForkLock.RUnlock()

	return NewFile(uintptr(p[0]), "|0"), NewFile(uintptr(p[1]), "|1"), nil
}

// TempDir returns the default directory to use for temporary files.
func TempDir() string {
	const pathSep = '\\'
	dirw := make([]uint16, syscall.MAX_PATH)
	n, _ := syscall.GetTempPath(uint32(len(dirw)), &dirw[0])
	if n > uint32(len(dirw)) {
		dirw = make([]uint16, n)
		n, _ = syscall.GetTempPath(uint32(len(dirw)), &dirw[0])
		if n > uint32(len(dirw)) {
			n = 0
		}
	}
	if n > 0 && dirw[n-1] == pathSep {
		n--
	}
	return string(utf16.Decode(dirw[0:n]))
}
<commit_msg>os: remove dead code<commit_after>// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package os

import (
	"io"
	"runtime"
	"sync"
	"syscall"
	"unicode/utf16"
	"unicode/utf8"
)

// File represents an open file descriptor.
type File struct {
	*file
}

// file is the real representation of *File.
// The extra level of indirection ensures that no clients of os
// can overwrite this data, which could cause the finalizer
// to close the wrong file descriptor.
type file struct {
	fd      syscall.Handle
	name    string
	dirinfo *dirInfo   // nil unless directory being read
	l       sync.Mutex // used to implement windows pread/pwrite

	// only for console io
	isConsole bool
	lastbits  []byte // first few bytes of the last incomplete rune in last write
}

// Fd returns the Windows handle referencing the open file.
func (file *File) Fd() uintptr {
	if file == nil {
		return uintptr(syscall.InvalidHandle)
	}
	return uintptr(file.fd)
}

// NewFile returns a new File with the given file descriptor and name.
func NewFile(fd uintptr, name string) *File {
	h := syscall.Handle(fd)
	if h == syscall.InvalidHandle {
		return nil
	}
	f := &File{&file{fd: h, name: name}}
	var m uint32
	if syscall.GetConsoleMode(f.fd, &m) == nil {
		f.isConsole = true
	}
	runtime.SetFinalizer(f.file, (*file).close)
	return f
}

// Auxiliary information if the File describes a directory
type dirInfo struct {
	data     syscall.Win32finddata
	needdata bool
	path     string
}

func epipecheck(file *File, e error) {
}

const DevNull = "NUL"

func (f *file) isdir() bool { return f != nil && f.dirinfo != nil }

func openFile(name string, flag int, perm FileMode) (file *File, err error) {
	r, e := syscall.Open(name, flag|syscall.O_CLOEXEC, syscallMode(perm))
	if e != nil {
		return nil, &PathError{"open", name, e}
	}
	return NewFile(uintptr(r), name), nil
}

func openDir(name string) (file *File, err error) {
	maskp, e := syscall.UTF16PtrFromString(name + `\*`)
	if e != nil {
		return nil, &PathError{"open", name, e}
	}
	d := new(dirInfo)
	r, e := syscall.FindFirstFile(maskp, &d.data)
	if e != nil {
		return nil, &PathError{"open", name, e}
	}
	d.path = name
	if !isAbs(d.path) {
		cwd, _ := Getwd()
		d.path = cwd + `\` + d.path
	}
	f := NewFile(uintptr(r), name)
	f.dirinfo = d
	return f, nil
}

// OpenFile is the generalized open call; most users will use Open
// or Create instead.  It opens the named file with specified flag
// (O_RDONLY etc.) and perm, (0666 etc.) if applicable.  If successful,
// methods on the returned File can be used for I/O.
// If there is an error, it will be of type *PathError.
func OpenFile(name string, flag int, perm FileMode) (file *File, err error) {
	if name == "" {
		return nil, &PathError{"open", name, syscall.ENOENT}
	}
	// TODO(brainman): not sure about my logic of assuming it is dir first, then fall back to file
	r, e := openDir(name)
	if e == nil {
		if flag&O_WRONLY != 0 || flag&O_RDWR != 0 {
			r.Close()
			return nil, &PathError{"open", name, syscall.EISDIR}
		}
		return r, nil
	}
	r, e = openFile(name, flag, perm)
	if e == nil {
		return r, nil
	}
	return nil, e
}

// Close closes the File, rendering it unusable for I/O.
// It returns an error, if any.
func (file *File) Close() error {
	return file.file.close()
}

func (file *file) close() error {
	if file == nil || file.fd == syscall.InvalidHandle {
		return syscall.EINVAL
	}
	var e error
	if file.isdir() {
		e = syscall.FindClose(syscall.Handle(file.fd))
	} else {
		e = syscall.CloseHandle(syscall.Handle(file.fd))
	}
	var err error
	if e != nil {
		err = &PathError{"close", file.name, e}
	}
	file.fd = syscall.InvalidHandle // so it can't be closed again

	// no need for a finalizer anymore
	runtime.SetFinalizer(file, nil)
	return err
}

func (file *File) readdir(n int) (fi []FileInfo, err error) {
	if file == nil || file.fd == syscall.InvalidHandle {
		return nil, syscall.EINVAL
	}
	if !file.isdir() {
		return nil, &PathError{"Readdir", file.name, syscall.ENOTDIR}
	}
	wantAll := n <= 0
	size := n
	if wantAll {
		n = -1
		size = 100
	}
	fi = make([]FileInfo, 0, size) // Empty with room to grow.
	d := &file.dirinfo.data
	for n != 0 {
		if file.dirinfo.needdata {
			e := syscall.FindNextFile(syscall.Handle(file.fd), d)
			if e != nil {
				if e == syscall.ERROR_NO_MORE_FILES {
					break
				} else {
					err = &PathError{"FindNextFile", file.name, e}
					if !wantAll {
						fi = nil
					}
					return
				}
			}
		}
		file.dirinfo.needdata = true
		name := string(syscall.UTF16ToString(d.FileName[0:]))
		if name == "." || name == ".." { // Useless names
			continue
		}
		f := &fileStat{
			name:    name,
			size:    mkSize(d.FileSizeHigh, d.FileSizeLow),
			modTime: mkModTime(d.LastWriteTime),
			mode:    mkMode(d.FileAttributes),
			sys:     mkSys(file.dirinfo.path+`\`+name, d.LastAccessTime, d.CreationTime),
		}
		n--
		fi = append(fi, f)
	}
	if !wantAll && len(fi) == 0 {
		return fi, io.EOF
	}
	return fi, nil
}

// read reads up to len(b) bytes from the File.
// It returns the number of bytes read and an error, if any.
func (f *File) read(b []byte) (n int, err error) {
	f.l.Lock()
	defer f.l.Unlock()
	return syscall.Read(f.fd, b)
}

// pread reads len(b) bytes from the File starting at byte offset off.
// It returns the number of bytes read and the error, if any.
// EOF is signaled by a zero count with err set to 0.
func (f *File) pread(b []byte, off int64) (n int, err error) {
	f.l.Lock()
	defer f.l.Unlock()
	curoffset, e := syscall.Seek(f.fd, 0, 1)
	if e != nil {
		return 0, e
	}
	defer syscall.Seek(f.fd, curoffset, 0)
	o := syscall.Overlapped{
		OffsetHigh: uint32(off >> 32),
		Offset:     uint32(off),
	}
	var done uint32
	e = syscall.ReadFile(syscall.Handle(f.fd), b, &done, &o)
	if e != nil {
		return 0, e
	}
	return int(done), nil
}

// writeConsole writes len(b) bytes to the console File.
// It returns the number of bytes written and an error, if any.
func (f *File) writeConsole(b []byte) (n int, err error) {
	n = len(b)
	runes := make([]rune, 0, 256)
	if len(f.lastbits) > 0 {
		b = append(f.lastbits, b...)
		f.lastbits = nil

	}
	for len(b) >= utf8.UTFMax || utf8.FullRune(b) {
		r, l := utf8.DecodeRune(b)
		runes = append(runes, r)
		b = b[l:]
	}
	if len(b) > 0 {
		f.lastbits = make([]byte, len(b))
		copy(f.lastbits, b)
	}
	// syscall.WriteConsole seems to fail, if given large buffer.
	// So limit the buffer to 16000 characters. This number was
	// discovered by experimenting with syscall.WriteConsole.
	const maxWrite = 16000
	for len(runes) > 0 {
		m := len(runes)
		if m > maxWrite {
			m = maxWrite
		}
		chunk := runes[:m]
		runes = runes[m:]
		uint16s := utf16.Encode(chunk)
		for len(uint16s) > 0 {
			var written uint32
			err = syscall.WriteConsole(f.fd, &uint16s[0], uint32(len(uint16s)), &written, nil)
			if err != nil {
				return 0, nil
			}
			uint16s = uint16s[written:]
		}
	}
	return n, nil
}

// write writes len(b) bytes to the File.
// It returns the number of bytes written and an error, if any.
func (f *File) write(b []byte) (n int, err error) {
	f.l.Lock()
	defer f.l.Unlock()
	if f.isConsole {
		return f.writeConsole(b)
	}
	return syscall.Write(f.fd, b)
}

// pwrite writes len(b) bytes to the File starting at byte offset off.
// It returns the number of bytes written and an error, if any.
func (f *File) pwrite(b []byte, off int64) (n int, err error) {
	f.l.Lock()
	defer f.l.Unlock()
	curoffset, e := syscall.Seek(f.fd, 0, 1)
	if e != nil {
		return 0, e
	}
	defer syscall.Seek(f.fd, curoffset, 0)
	o := syscall.Overlapped{
		OffsetHigh: uint32(off >> 32),
		Offset:     uint32(off),
	}
	var done uint32
	e = syscall.WriteFile(syscall.Handle(f.fd), b, &done, &o)
	if e != nil {
		return 0, e
	}
	return int(done), nil
}

// seek sets the offset for the next Read or Write on file to offset, interpreted
// according to whence: 0 means relative to the origin of the file, 1 means
// relative to the current offset, and 2 means relative to the end.
// It returns the new offset and an error, if any.
func (f *File) seek(offset int64, whence int) (ret int64, err error) {
	f.l.Lock()
	defer f.l.Unlock()
	return syscall.Seek(f.fd, offset, whence)
}

// Truncate changes the size of the named file.
// If the file is a symbolic link, it changes the size of the link's target.
func Truncate(name string, size int64) error {
	f, e := OpenFile(name, O_WRONLY|O_CREATE, 0666)
	if e != nil {
		return e
	}
	defer f.Close()
	e1 := f.Truncate(size)
	if e1 != nil {
		return e1
	}
	return nil
}

// Remove removes the named file or directory.
// If there is an error, it will be of type *PathError.
func Remove(name string) error {
	p, e := syscall.UTF16PtrFromString(name)
	if e != nil {
		return &PathError{"remove", name, e}
	}

	// Go file interface forces us to know whether
	// name is a file or directory. Try both.
	e = syscall.DeleteFile(p)
	if e == nil {
		return nil
	}
	e1 := syscall.RemoveDirectory(p)
	if e1 == nil {
		return nil
	}

	// Both failed: figure out which error to return.
	if e1 != e {
		a, e2 := syscall.GetFileAttributes(p)
		if e2 != nil {
			e = e2
		} else {
			if a&syscall.FILE_ATTRIBUTE_DIRECTORY != 0 {
				e = e1
			}
		}
	}
	return &PathError{"remove", name, e}
}

// Pipe returns a connected pair of Files; reads from r return bytes written to w.
// It returns the files and an error, if any.
func Pipe() (r *File, w *File, err error) {
	var p [2]syscall.Handle

	// See ../syscall/exec.go for description of lock.
	syscall.ForkLock.RLock()
	e := syscall.Pipe(p[0:])
	if e != nil {
		syscall.ForkLock.RUnlock()
		return nil, nil, NewSyscallError("pipe", e)
	}
	syscall.CloseOnExec(p[0])
	syscall.CloseOnExec(p[1])
	syscall.ForkLock.RUnlock()

	return NewFile(uintptr(p[0]), "|0"), NewFile(uintptr(p[1]), "|1"), nil
}

// TempDir returns the default directory to use for temporary files.
func TempDir() string {
	const pathSep = '\\'
	dirw := make([]uint16, syscall.MAX_PATH)
	n, _ := syscall.GetTempPath(uint32(len(dirw)), &dirw[0])
	if n > uint32(len(dirw)) {
		dirw = make([]uint16, n)
		n, _ = syscall.GetTempPath(uint32(len(dirw)), &dirw[0])
		if n > uint32(len(dirw)) {
			n = 0
		}
	}
	if n > 0 && dirw[n-1] == pathSep {
		n--
	}
	return string(utf16.Decode(dirw[0:n]))
}
<|endoftext|>