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

package state

import (
	"fmt"
	"strconv"

	"labix.org/v2/mgo/txn"

	"launchpad.net/juju-core/constraints"
	"launchpad.net/juju-core/errors"
	"launchpad.net/juju-core/instance"
	"launchpad.net/juju-core/state/api/params"
	"launchpad.net/juju-core/utils"
)

// MachineTemplate holds attributes that are to be associated
// with a newly created machine.
type MachineTemplate struct {
	// Series is the series to be associated with the new machine.
	Series string

	// Constraints are the constraints to be used when finding
	// an instance for the machine.
	Constraints constraints.Value

	// Jobs holds the jobs to run on the machine's instance.
	// A machine must have at least one job to do.
	Jobs []MachineJob

	// Addresses holds the addresses to be associated with the
	// new machine.
	Addresses []instance.Address

	// InstanceId holds the instance id to associate with the machine.
	// If this is empty, the provisioner will try to provision the machine.
	// If this is non-empty, the HardwareCharacteristics and Nonce
	// fields must be set appropriately.
	InstanceId instance.Id

	// HardwareCharacteristics holds the h/w characteristics to
	// be associated with the machine.
	HardwareCharacteristics instance.HardwareCharacteristics

	// Nonce holds a unique value that can be used to check
	// if a new instance was really started for this machine.
	// See Machine.SetProvisioned. This must be set if InstanceId is set.
	Nonce string

	// Dirty signifies whether the new machine will be treated
	// as unclean for unit-assignment purposes.
	Dirty bool

	// principals holds the principal units that will
	// associated with the machine.
	principals []string

	// instanceId holds the instance id to be associated with the
	// new machine. It should only be set by InjectMachine.
	instanceId instance.Id

	// nonce holds the nonce for the new machine.
	// It should only be set by InjectMachine.
	nonce string
}

// AddMachineInsideNewMachine creates a new machine within a container
// of the given type inside another new machine. The two given templates
// specify the form of the child and parent respectively.
func (st *State) AddMachineInsideNewMachine(template, parentTemplate MachineTemplate, containerType instance.ContainerType) (*Machine, error) {
	mdoc, ops, err := st.addMachineInsideNewMachineOps(template, parentTemplate, containerType)
	if err != nil {
		return nil, fmt.Errorf("cannot add a new machine: %v", err)
	}
	return st.addMachine(mdoc, ops)
}

// AddMachineInsideMachine adds a machine inside a container of the
// given type on the existing machine with id=parentId.
func (st *State) AddMachineInsideMachine(template MachineTemplate, parentId string, containerType instance.ContainerType) (*Machine, error) {
	mdoc, ops, err := st.addMachineInsideMachineOps(template, parentId, containerType)
	if err != nil {
		return nil, fmt.Errorf("cannot add a new machine: %v", err)
	}
	return st.addMachine(mdoc, ops)
}

// AddMachine adds a machine with the given series and jobs.
// It is deprecated and around for testing purposes only.
func (st *State) AddMachine(series string, jobs ...MachineJob) (*Machine, error) {
	ms, err := st.AddMachines(MachineTemplate{
		Series: series,
		Jobs:   jobs,
	})
	if err != nil {
		return nil, err
	}
	return ms[0], nil
}

// AddOne machine adds a new machine configured according to the
// given template.
func (st *State) AddOneMachine(template MachineTemplate) (*Machine, error) {
	ms, err := st.AddMachines(template)
	if err != nil {
		return nil, err
	}
	return ms[0], nil
}

// AddMachines adds new machines configured according to the
// given templates.
func (st *State) AddMachines(templates ...MachineTemplate) (_ []*Machine, err error) {
	defer utils.ErrorContextf(&err, "cannot add a new machine")
	var ms []*Machine
	var ops []txn.Op
	for _, template := range templates {
		mdoc, addOps, err := st.addMachineOps(template)
		if err != nil {
			return nil, err
		}
		ms = append(ms, newMachine(st, mdoc))
		ops = append(ops, addOps...)
	}
	if err := st.runTransaction(ops); err != nil {
		return nil, err
	}
	return ms, nil
}

func (st *State) addMachine(mdoc *machineDoc, ops []txn.Op) (*Machine, error) {
	env, err := st.Environment()
	if err != nil {
		return nil, err
	} else if env.Life() != Alive {
		return nil, fmt.Errorf("environment is no longer alive")
	}
	ops = append([]txn.Op{env.assertAliveOp()}, ops...)
	if err := st.runTransaction(ops); err != nil {
		enverr := env.Refresh()
		if (enverr == nil && env.Life() != Alive) || errors.IsNotFoundError(enverr) {
			return nil, fmt.Errorf("environment is no longer alive")
		} else if enverr != nil {
			err = enverr
		}
		return nil, err
	}
	return newMachine(st, mdoc), nil
}

// effectiveMachineTemplate verifies that the given template is
// valid and combines it with values from the state
// to produce a resulting template that more accurately
// represents the data that will be inserted into the state.
func (st *State) effectiveMachineTemplate(p MachineTemplate) (MachineTemplate, error) {
	if p.Series == "" {
		return MachineTemplate{}, fmt.Errorf("no series specified")
	}
	cons, err := st.EnvironConstraints()
	if err != nil {
		return MachineTemplate{}, err
	}
	p.Constraints = p.Constraints.WithFallbacks(cons)
	// Machine constraints do not use a container constraint value.
	// Both provisioning and deployment constraints use the same
	// constraints.Value struct so here we clear the container
	// value. Provisioning ignores the container value but clearing
	// it avoids potential confusion.
	p.Constraints.Container = nil

	if len(p.Jobs) == 0 {
		return MachineTemplate{}, fmt.Errorf("no jobs specified")
	}
	jset := make(map[MachineJob]bool)
	for _, j := range p.Jobs {
		if jset[j] {
			return MachineTemplate{}, fmt.Errorf("duplicate job: %s", j)
		}
		jset[j] = true
	}

	if p.InstanceId != "" {
		if p.Nonce == "" {
			return MachineTemplate{}, fmt.Errorf("cannot add a machine with an instance id and no nonce")
		}
	} else if p.Nonce != "" {
		return MachineTemplate{}, fmt.Errorf("cannot specify a nonce without an instance id")
	}
	return p, nil
}

// addMachineOps returns operations to add a new top level machine
// based on the given template. It also returns the machine document
// that will be inserted.
func (st *State) addMachineOps(template MachineTemplate) (*machineDoc, []txn.Op, error) {
	template, err := st.effectiveMachineTemplate(template)
	if err != nil {
		return nil, nil, err
	}
	seq, err := st.sequence("machine")
	if err != nil {
		return nil, nil, err
	}
	mdoc := machineDocForTemplate(template, strconv.Itoa(seq))
	var ops []txn.Op
	ops = append(ops, st.insertNewMachineOps(mdoc, template.Constraints)...)
	ops = append(ops, st.insertNewContainerRefOp(mdoc.Id))
	if template.InstanceId != "" {
		ops = append(ops, txn.Op{
			C:      st.instanceData.Name,
			Id:     mdoc.Id,
			Assert: txn.DocMissing,
			Insert: &instanceData{
				Id:         mdoc.Id,
				InstanceId: template.instanceId,
				Arch:       template.HardwareCharacteristics.Arch,
				Mem:        template.HardwareCharacteristics.Mem,
				RootDisk:   template.HardwareCharacteristics.RootDisk,
				CpuCores:   template.HardwareCharacteristics.CpuCores,
				CpuPower:   template.HardwareCharacteristics.CpuPower,
				Tags:       template.HardwareCharacteristics.Tags,
			},
		})
	}
	return mdoc, ops, nil
}

// supportsContainerType reports whether the machine supports the given
// container type. If the machine's supportedContainers attribute is
// set, this decision can be made right here, otherwise we assume that
// everything will be ok and later on put the container into an error
// state if necessary.
func (m *Machine) supportsContainerType(ctype instance.ContainerType) bool {
	supportedContainers, ok := m.SupportedContainers()
	if !ok {
		// We don't know yet, so we report that we support the container.
		return true
	}
	for _, ct := range supportedContainers {
		if ct == ctype {
			return true
		}
	}
	return false
}

// addMachineInsideMachineOps returns operations to add a machine inside
// a container of the given type on an existing machine.
func (st *State) addMachineInsideMachineOps(template MachineTemplate, parentId string, containerType instance.ContainerType) (*machineDoc, []txn.Op, error) {
	if template.InstanceId != "" {
		return nil, nil, fmt.Errorf("cannot specify instance id for a new container")
	}
	template, err := st.effectiveMachineTemplate(template)
	if err != nil {
		return nil, nil, err
	}
	if containerType == "" {
		return nil, nil, fmt.Errorf("no container type specified")
	}

	// If a parent machine is specified, make sure it exists
	// and can support the requested container type.
	parent, err := st.Machine(parentId)
	if err != nil {
		return nil, nil, err
	}
	if !parent.supportsContainerType(containerType) {
		return nil, nil, fmt.Errorf("machine %s cannot host %s containers", parentId, containerType)
	}
	newId, err := st.newContainerId(parentId, containerType)
	if err != nil {
		return nil, nil, err
	}
	mdoc := machineDocForTemplate(template, newId)
	mdoc.ContainerType = string(containerType)
	var ops []txn.Op
	ops = append(ops, st.insertNewMachineOps(mdoc, template.Constraints)...)
	ops = append(ops,
		// Update containers record for host machine.
		st.addChildToContainerRefOp(parentId, mdoc.Id),
		// Create a containers reference document for the container itself.
		st.insertNewContainerRefOp(mdoc.Id),
	)
	return mdoc, ops, nil
}

// newContainerId returns a new id for a machine within the machine
// with id parentId and the given container type.
func (st *State) newContainerId(parentId string, containerType instance.ContainerType) (string, error) {
	seq, err := st.sequence(fmt.Sprintf("machine%s%sContainer", parentId, containerType))
	if err != nil {
		return "", err
	}
	return fmt.Sprintf("%s/%s/%d", parentId, containerType, seq), nil
}

// addMachineInsideNewMachineOps returns operations to create a new
// machine within a container of the given type inside another
// new machine. The two given templates specify the form
// of the child and parent respectively.
func (st *State) addMachineInsideNewMachineOps(template, parentTemplate MachineTemplate, containerType instance.ContainerType) (*machineDoc, []txn.Op, error) {
	if template.InstanceId != "" || parentTemplate.InstanceId != "" {
		return nil, nil, fmt.Errorf("cannot specify instance id for a new container")
	}
	seq, err := st.sequence("machine")
	if err != nil {
		return nil, nil, err
	}
	parentTemplate, err = st.effectiveMachineTemplate(parentTemplate)
	if err != nil {
		return nil, nil, err
	}
	parentDoc := machineDocForTemplate(parentTemplate, strconv.Itoa(seq))
	newId, err := st.newContainerId(parentDoc.Id, containerType)
	if err != nil {
		return nil, nil, err
	}
	template, err = st.effectiveMachineTemplate(template)
	if err != nil {
		return nil, nil, err
	}
	mdoc := machineDocForTemplate(template, newId)
	mdoc.ContainerType = string(containerType)
	var ops []txn.Op
	ops = append(ops, st.insertNewMachineOps(parentDoc, parentTemplate.Constraints)...)
	ops = append(ops, st.insertNewMachineOps(mdoc, template.Constraints)...)
	ops = append(ops,
		// The host machine doesn't exist yet, create a new containers record.
		st.insertNewContainerRefOp(mdoc.Id),
		// Create a containers reference document for the container itself.
		st.insertNewContainerRefOp(parentDoc.Id, mdoc.Id),
	)
	return mdoc, ops, nil
}

func machineDocForTemplate(template MachineTemplate, id string) *machineDoc {
	return &machineDoc{
		Id:         id,
		Series:     template.Series,
		Jobs:       template.Jobs,
		Clean:      !template.Dirty,
		Principals: template.principals,
		Life:       Alive,
		InstanceId: template.InstanceId,
		Nonce:      template.Nonce,
		Addresses:  instanceAddressesToAddresses(template.Addresses),
	}
}

// insertNewMachineOps returns operations to insert the given machine
// document and its associated constraints into the database.
func (st *State) insertNewMachineOps(mdoc *machineDoc, cons constraints.Value) []txn.Op {
	return []txn.Op{
		{
			C:      st.machines.Name,
			Id:     mdoc.Id,
			Assert: txn.DocMissing,
			Insert: mdoc,
		},
		createConstraintsOp(st, machineGlobalKey(mdoc.Id), cons),
		createStatusOp(st, machineGlobalKey(mdoc.Id), statusDoc{
			Status: params.StatusPending,
		}),
	}
}
<commit_msg>state: fix addmachine<commit_after>// Copyright 2012, 2013 Canonical Ltd.
// Licensed under the AGPLv3, see LICENCE file for details.

package state

import (
	"fmt"
	"strconv"

	"labix.org/v2/mgo/txn"

	"launchpad.net/juju-core/constraints"
	"launchpad.net/juju-core/errors"
	"launchpad.net/juju-core/instance"
	"launchpad.net/juju-core/state/api/params"
	"launchpad.net/juju-core/utils"
)

// MachineTemplate holds attributes that are to be associated
// with a newly created machine.
type MachineTemplate struct {
	// Series is the series to be associated with the new machine.
	Series string

	// Constraints are the constraints to be used when finding
	// an instance for the machine.
	Constraints constraints.Value

	// Jobs holds the jobs to run on the machine's instance.
	// A machine must have at least one job to do.
	Jobs []MachineJob

	// Addresses holds the addresses to be associated with the
	// new machine.
	Addresses []instance.Address

	// InstanceId holds the instance id to associate with the machine.
	// If this is empty, the provisioner will try to provision the machine.
	// If this is non-empty, the HardwareCharacteristics and Nonce
	// fields must be set appropriately.
	InstanceId instance.Id

	// HardwareCharacteristics holds the h/w characteristics to
	// be associated with the machine.
	HardwareCharacteristics instance.HardwareCharacteristics

	// Nonce holds a unique value that can be used to check
	// if a new instance was really started for this machine.
	// See Machine.SetProvisioned. This must be set if InstanceId is set.
	Nonce string

	// Dirty signifies whether the new machine will be treated
	// as unclean for unit-assignment purposes.
	Dirty bool

	// principals holds the principal units that will
	// associated with the machine.
	principals []string

	// instanceId holds the instance id to be associated with the
	// new machine. It should only be set by InjectMachine.
	instanceId instance.Id

	// nonce holds the nonce for the new machine.
	// It should only be set by InjectMachine.
	nonce string
}

// AddMachineInsideNewMachine creates a new machine within a container
// of the given type inside another new machine. The two given templates
// specify the form of the child and parent respectively.
func (st *State) AddMachineInsideNewMachine(template, parentTemplate MachineTemplate, containerType instance.ContainerType) (*Machine, error) {
	mdoc, ops, err := st.addMachineInsideNewMachineOps(template, parentTemplate, containerType)
	if err != nil {
		return nil, fmt.Errorf("cannot add a new machine: %v", err)
	}
	return st.addMachine(mdoc, ops)
}

// AddMachineInsideMachine adds a machine inside a container of the
// given type on the existing machine with id=parentId.
func (st *State) AddMachineInsideMachine(template MachineTemplate, parentId string, containerType instance.ContainerType) (*Machine, error) {
	mdoc, ops, err := st.addMachineInsideMachineOps(template, parentId, containerType)
	if err != nil {
		return nil, fmt.Errorf("cannot add a new machine: %v", err)
	}
	return st.addMachine(mdoc, ops)
}

// AddMachine adds a machine with the given series and jobs.
// It is deprecated and around for testing purposes only.
func (st *State) AddMachine(series string, jobs ...MachineJob) (*Machine, error) {
	ms, err := st.AddMachines(MachineTemplate{
		Series: series,
		Jobs:   jobs,
	})
	if err != nil {
		return nil, err
	}
	return ms[0], nil
}

// AddOne machine adds a new machine configured according to the
// given template.
func (st *State) AddOneMachine(template MachineTemplate) (*Machine, error) {
	ms, err := st.AddMachines(template)
	if err != nil {
		return nil, err
	}
	return ms[0], nil
}

// AddMachines adds new machines configured according to the
// given templates.
func (st *State) AddMachines(templates ...MachineTemplate) (_ []*Machine, err error) {
	defer utils.ErrorContextf(&err, "cannot add a new machine")
	var ms []*Machine
	env, err := st.Environment()
	if err != nil {
		return nil, err
	} else if env.Life() != Alive {
		return nil, fmt.Errorf("environment is no longer alive")
	}
	var ops []txn.Op
	for _, template := range templates {
		mdoc, addOps, err := st.addMachineOps(template)
		if err != nil {
			return nil, err
		}
		ms = append(ms, newMachine(st, mdoc))
		ops = append(ops, addOps...)
	}
	ops = append(ops, env.assertAliveOp())
	if err := st.runTransaction(ops); err != nil {
		return nil, onAbort(err, fmt.Errorf("environment is no longer alive"))
	}
	return ms, nil
}

func (st *State) addMachine(mdoc *machineDoc, ops []txn.Op) (*Machine, error) {
	env, err := st.Environment()
	if err != nil {
		return nil, err
	} else if env.Life() != Alive {
		return nil, fmt.Errorf("environment is no longer alive")
	}
	ops = append([]txn.Op{env.assertAliveOp()}, ops...)
	if err := st.runTransaction(ops); err != nil {
		enverr := env.Refresh()
		if (enverr == nil && env.Life() != Alive) || errors.IsNotFoundError(enverr) {
			return nil, fmt.Errorf("environment is no longer alive")
		} else if enverr != nil {
			err = enverr
		}
		return nil, err
	}
	return newMachine(st, mdoc), nil
}

// effectiveMachineTemplate verifies that the given template is
// valid and combines it with values from the state
// to produce a resulting template that more accurately
// represents the data that will be inserted into the state.
func (st *State) effectiveMachineTemplate(p MachineTemplate) (MachineTemplate, error) {
	if p.Series == "" {
		return MachineTemplate{}, fmt.Errorf("no series specified")
	}
	cons, err := st.EnvironConstraints()
	if err != nil {
		return MachineTemplate{}, err
	}
	p.Constraints = p.Constraints.WithFallbacks(cons)
	// Machine constraints do not use a container constraint value.
	// Both provisioning and deployment constraints use the same
	// constraints.Value struct so here we clear the container
	// value. Provisioning ignores the container value but clearing
	// it avoids potential confusion.
	p.Constraints.Container = nil

	if len(p.Jobs) == 0 {
		return MachineTemplate{}, fmt.Errorf("no jobs specified")
	}
	jset := make(map[MachineJob]bool)
	for _, j := range p.Jobs {
		if jset[j] {
			return MachineTemplate{}, fmt.Errorf("duplicate job: %s", j)
		}
		jset[j] = true
	}

	if p.InstanceId != "" {
		if p.Nonce == "" {
			return MachineTemplate{}, fmt.Errorf("cannot add a machine with an instance id and no nonce")
		}
	} else if p.Nonce != "" {
		return MachineTemplate{}, fmt.Errorf("cannot specify a nonce without an instance id")
	}
	return p, nil
}

// addMachineOps returns operations to add a new top level machine
// based on the given template. It also returns the machine document
// that will be inserted.
func (st *State) addMachineOps(template MachineTemplate) (*machineDoc, []txn.Op, error) {
	template, err := st.effectiveMachineTemplate(template)
	if err != nil {
		return nil, nil, err
	}
	seq, err := st.sequence("machine")
	if err != nil {
		return nil, nil, err
	}
	mdoc := machineDocForTemplate(template, strconv.Itoa(seq))
	var ops []txn.Op
	ops = append(ops, st.insertNewMachineOps(mdoc, template.Constraints)...)
	ops = append(ops, st.insertNewContainerRefOp(mdoc.Id))
	if template.InstanceId != "" {
		ops = append(ops, txn.Op{
			C:      st.instanceData.Name,
			Id:     mdoc.Id,
			Assert: txn.DocMissing,
			Insert: &instanceData{
				Id:         mdoc.Id,
				InstanceId: template.instanceId,
				Arch:       template.HardwareCharacteristics.Arch,
				Mem:        template.HardwareCharacteristics.Mem,
				RootDisk:   template.HardwareCharacteristics.RootDisk,
				CpuCores:   template.HardwareCharacteristics.CpuCores,
				CpuPower:   template.HardwareCharacteristics.CpuPower,
				Tags:       template.HardwareCharacteristics.Tags,
			},
		})
	}
	return mdoc, ops, nil
}

// supportsContainerType reports whether the machine supports the given
// container type. If the machine's supportedContainers attribute is
// set, this decision can be made right here, otherwise we assume that
// everything will be ok and later on put the container into an error
// state if necessary.
func (m *Machine) supportsContainerType(ctype instance.ContainerType) bool {
	supportedContainers, ok := m.SupportedContainers()
	if !ok {
		// We don't know yet, so we report that we support the container.
		return true
	}
	for _, ct := range supportedContainers {
		if ct == ctype {
			return true
		}
	}
	return false
}

// addMachineInsideMachineOps returns operations to add a machine inside
// a container of the given type on an existing machine.
func (st *State) addMachineInsideMachineOps(template MachineTemplate, parentId string, containerType instance.ContainerType) (*machineDoc, []txn.Op, error) {
	if template.InstanceId != "" {
		return nil, nil, fmt.Errorf("cannot specify instance id for a new container")
	}
	template, err := st.effectiveMachineTemplate(template)
	if err != nil {
		return nil, nil, err
	}
	if containerType == "" {
		return nil, nil, fmt.Errorf("no container type specified")
	}

	// If a parent machine is specified, make sure it exists
	// and can support the requested container type.
	parent, err := st.Machine(parentId)
	if err != nil {
		return nil, nil, err
	}
	if !parent.supportsContainerType(containerType) {
		return nil, nil, fmt.Errorf("machine %s cannot host %s containers", parentId, containerType)
	}
	newId, err := st.newContainerId(parentId, containerType)
	if err != nil {
		return nil, nil, err
	}
	mdoc := machineDocForTemplate(template, newId)
	mdoc.ContainerType = string(containerType)
	var ops []txn.Op
	ops = append(ops, st.insertNewMachineOps(mdoc, template.Constraints)...)
	ops = append(ops,
		// Update containers record for host machine.
		st.addChildToContainerRefOp(parentId, mdoc.Id),
		// Create a containers reference document for the container itself.
		st.insertNewContainerRefOp(mdoc.Id),
	)
	return mdoc, ops, nil
}

// newContainerId returns a new id for a machine within the machine
// with id parentId and the given container type.
func (st *State) newContainerId(parentId string, containerType instance.ContainerType) (string, error) {
	seq, err := st.sequence(fmt.Sprintf("machine%s%sContainer", parentId, containerType))
	if err != nil {
		return "", err
	}
	return fmt.Sprintf("%s/%s/%d", parentId, containerType, seq), nil
}

// addMachineInsideNewMachineOps returns operations to create a new
// machine within a container of the given type inside another
// new machine. The two given templates specify the form
// of the child and parent respectively.
func (st *State) addMachineInsideNewMachineOps(template, parentTemplate MachineTemplate, containerType instance.ContainerType) (*machineDoc, []txn.Op, error) {
	if template.InstanceId != "" || parentTemplate.InstanceId != "" {
		return nil, nil, fmt.Errorf("cannot specify instance id for a new container")
	}
	seq, err := st.sequence("machine")
	if err != nil {
		return nil, nil, err
	}
	parentTemplate, err = st.effectiveMachineTemplate(parentTemplate)
	if err != nil {
		return nil, nil, err
	}
	parentDoc := machineDocForTemplate(parentTemplate, strconv.Itoa(seq))
	newId, err := st.newContainerId(parentDoc.Id, containerType)
	if err != nil {
		return nil, nil, err
	}
	template, err = st.effectiveMachineTemplate(template)
	if err != nil {
		return nil, nil, err
	}
	mdoc := machineDocForTemplate(template, newId)
	mdoc.ContainerType = string(containerType)
	var ops []txn.Op
	ops = append(ops, st.insertNewMachineOps(parentDoc, parentTemplate.Constraints)...)
	ops = append(ops, st.insertNewMachineOps(mdoc, template.Constraints)...)
	ops = append(ops,
		// The host machine doesn't exist yet, create a new containers record.
		st.insertNewContainerRefOp(mdoc.Id),
		// Create a containers reference document for the container itself.
		st.insertNewContainerRefOp(parentDoc.Id, mdoc.Id),
	)
	return mdoc, ops, nil
}

func machineDocForTemplate(template MachineTemplate, id string) *machineDoc {
	return &machineDoc{
		Id:         id,
		Series:     template.Series,
		Jobs:       template.Jobs,
		Clean:      !template.Dirty,
		Principals: template.principals,
		Life:       Alive,
		InstanceId: template.InstanceId,
		Nonce:      template.Nonce,
		Addresses:  instanceAddressesToAddresses(template.Addresses),
	}
}

// insertNewMachineOps returns operations to insert the given machine
// document and its associated constraints into the database.
func (st *State) insertNewMachineOps(mdoc *machineDoc, cons constraints.Value) []txn.Op {
	return []txn.Op{
		{
			C:      st.machines.Name,
			Id:     mdoc.Id,
			Assert: txn.DocMissing,
			Insert: mdoc,
		},
		createConstraintsOp(st, machineGlobalKey(mdoc.Id), cons),
		createStatusOp(st, machineGlobalKey(mdoc.Id), statusDoc{
			Status: params.StatusPending,
		}),
	}
}
<|endoftext|>


<commit_before>// +build ignore

// Run tests for all the remotes
//
// Run with go run test_all.go
package main

import (
	"flag"
	"log"
	"os"
	"os/exec"
	"regexp"
	"runtime"
	"strings"
	"time"

	"github.com/ncw/rclone/fs"
	_ "github.com/ncw/rclone/fs/all" // import all fs
	"github.com/ncw/rclone/fstest"
)

type remoteConfig struct {
	Name     string
	SubDir   bool
	FastList bool
}

var (
	remotes = []remoteConfig{
		{
			Name:     "TestAmazonCloudDrive:",
			SubDir:   false,
			FastList: false,
		},
		{
			Name:     "TestB2:",
			SubDir:   true,
			FastList: true,
		},
		{
			Name:     "TestCryptDrive:",
			SubDir:   false,
			FastList: false,
		},
		{
			Name:     "TestCryptSwift:",
			SubDir:   false,
			FastList: false,
		},
		{
			Name:     "TestDrive:",
			SubDir:   false,
			FastList: false,
		},
		{
			Name:     "TestDropbox:",
			SubDir:   false,
			FastList: false,
		},
		{
			Name:     "TestGoogleCloudStorage:",
			SubDir:   true,
			FastList: true,
		},
		{
			Name:     "TestHubic:",
			SubDir:   false,
			FastList: false,
		},
		{
			Name:     "TestOneDrive:",
			SubDir:   false,
			FastList: false,
		},
		{
			Name:     "TestS3:",
			SubDir:   true,
			FastList: true,
		},
		{
			Name:     "TestSftp:",
			SubDir:   false,
			FastList: false,
		},
		{
			Name:     "TestSwift:",
			SubDir:   true,
			FastList: true,
		},
		{
			Name:     "TestYandex:",
			SubDir:   false,
			FastList: false,
		},
		{
			Name:     "TestFTP:",
			SubDir:   false,
			FastList: false,
		},
		{
			Name:     "TestBox:",
			SubDir:   false,
			FastList: false,
		},
		{
			Name:     "TestQingStor:",
			SubDir:   false,
			FastList: false,
		},
		{
			Name:     "TestAzureBlob:",
			SubDir:   true,
			FastList: true,
		},
		{
			Name:     "TestPcloud:",
			SubDir:   false,
			FastList: false,
		},
		{
			Name:     "TestWebdav:",
			SubDir:   false,
			FastList: false,
		},
		{
			Name:     "TestCache:",
			SubDir:   true,
			FastList: true,
		},
	}
	binary = "fs.test"
	// Flags
	maxTries = flag.Int("maxtries", 5, "Number of times to try each test")
	runTests = flag.String("remotes", "", "Comma separated list of remotes to test, eg 'TestSwift:,TestS3'")
	clean    = flag.Bool("clean", false, "Instead of testing, clean all left over test directories")
	runOnly  = flag.String("run-only", "", "Run only those tests matching the regexp supplied")
	timeout  = flag.Duration("timeout", 30*time.Minute, "Maximum time to run each test for before giving up")
)

// test holds info about a running test
type test struct {
	remote      string
	subdir      bool
	cmdLine     []string
	cmdString   string
	try         int
	err         error
	output      []byte
	failedTests []string
	runFlag     string
}

// newTest creates a new test
func newTest(remote string, subdir bool, fastlist bool) *test {
	t := &test{
		remote:  remote,
		subdir:  subdir,
		cmdLine: []string{"./" + binary, "-test.timeout", (*timeout).String(), "-remote", remote},
		try:     1,
	}
	if *fstest.Verbose {
		t.cmdLine = append(t.cmdLine, "-test.v")
		fs.Config.LogLevel = fs.LogLevelDebug
	}
	if *runOnly != "" {
		t.cmdLine = append(t.cmdLine, "-test.run", *runOnly)
	}
	if subdir {
		t.cmdLine = append(t.cmdLine, "-subdir")
	}
	if fastlist {
		t.cmdLine = append(t.cmdLine, "-fast-list")
	}
	t.cmdString = toShell(t.cmdLine)
	return t
}

// dumpOutput prints the error output
func (t *test) dumpOutput() {
	log.Println("------------------------------------------------------------")
	log.Printf("---- %q ----", t.cmdString)
	log.Println(string(t.output))
	log.Println("------------------------------------------------------------")
}

var failRe = regexp.MustCompile(`(?m)^--- FAIL: (Test\w*) \(`)

// findFailures looks for all the tests which failed
func (t *test) findFailures() {
	oldFailedTests := t.failedTests
	t.failedTests = nil
	for _, matches := range failRe.FindAllSubmatch(t.output, -1) {
		t.failedTests = append(t.failedTests, string(matches[1]))
	}
	if len(t.failedTests) != 0 {
		t.runFlag = "^(" + strings.Join(t.failedTests, "|") + ")$"
	} else {
		t.runFlag = ""
	}
	if t.passed() && len(t.failedTests) != 0 {
		log.Printf("%q - Expecting no errors but got: %v", t.cmdString, t.failedTests)
		t.dumpOutput()
	} else if !t.passed() && len(t.failedTests) == 0 {
		log.Printf("%q - Expecting errors but got none: %v", t.cmdString, t.failedTests)
		t.dumpOutput()
		t.failedTests = oldFailedTests
	}
}

// nextCmdLine returns the next command line
func (t *test) nextCmdLine() []string {
	cmdLine := t.cmdLine[:]
	if t.runFlag != "" {
		cmdLine = append(cmdLine, "-test.run", t.runFlag)
	}
	return cmdLine
}

// if matches then is definitely OK in the shell
var shellOK = regexp.MustCompile("^[A-Za-z0-9./_:-]+$")

// converts a argv style input into a shell command
func toShell(args []string) (result string) {
	for _, arg := range args {
		if result != "" {
			result += " "
		}
		if shellOK.MatchString(arg) {
			result += arg
		} else {
			result += "'" + arg + "'"
		}
	}
	return result
}

// trial runs a single test
func (t *test) trial() {
	cmdLine := t.nextCmdLine()
	cmdString := toShell(cmdLine)
	log.Printf("%q - Starting (try %d/%d)", cmdString, t.try, *maxTries)
	cmd := exec.Command(cmdLine[0], cmdLine[1:]...)
	start := time.Now()
	t.output, t.err = cmd.CombinedOutput()
	duration := time.Since(start)
	t.findFailures()
	if t.passed() {
		log.Printf("%q - Finished OK in %v (try %d/%d)", cmdString, duration, t.try, *maxTries)
	} else {
		log.Printf("%q - Finished ERROR in %v (try %d/%d): %v: Failed %v", cmdString, duration, t.try, *maxTries, t.err, t.failedTests)
	}
}

// cleanFs runs a single clean fs for left over directories
func (t *test) cleanFs() error {
	f, err := fs.NewFs(t.remote)
	if err != nil {
		return err
	}
	entries, err := fs.ListDirSorted(f, true, "")
	if err != nil {
		return err
	}
	return entries.ForDirError(func(dir fs.Directory) error {
		remote := dir.Remote()
		if fstest.MatchTestRemote.MatchString(remote) {
			log.Printf("Purging %s%s", t.remote, remote)
			dir, err := fs.NewFs(t.remote + remote)
			if err != nil {
				return err
			}
			return fs.Purge(dir)
		}
		return nil
	})
}

// clean runs a single clean on a fs for left over directories
func (t *test) clean() {
	log.Printf("%q - Starting clean (try %d/%d)", t.remote, t.try, *maxTries)
	start := time.Now()
	t.err = t.cleanFs()
	if t.err != nil {
		log.Printf("%q - Failed to purge %v", t.remote, t.err)
	}
	duration := time.Since(start)
	if t.passed() {
		log.Printf("%q - Finished OK in %v (try %d/%d)", t.cmdString, duration, t.try, *maxTries)
	} else {
		log.Printf("%q - Finished ERROR in %v (try %d/%d): %v", t.cmdString, duration, t.try, *maxTries, t.err)
	}
}

// passed returns true if the test passed
func (t *test) passed() bool {
	return t.err == nil
}

// run runs all the trials for this test
func (t *test) run(result chan<- *test) {
	for t.try = 1; t.try <= *maxTries; t.try++ {
		if *clean {
			if !t.subdir {
				t.clean()
			}
		} else {
			t.trial()
		}
		if t.passed() {
			break
		}
	}
	if !t.passed() {
		t.dumpOutput()
	}
	result <- t
}

// makeTestBinary makes the binary we will run
func makeTestBinary() {
	if runtime.GOOS == "windows" {
		binary += ".exe"
	}
	log.Printf("Making test binary %q", binary)
	err := exec.Command("go", "test", "-c", "-o", binary).Run()
	if err != nil {
		log.Fatalf("Failed to make test binary: %v", err)
	}
	if _, err := os.Stat(binary); err != nil {
		log.Fatalf("Couldn't find test binary %q", binary)
	}
}

// removeTestBinary removes the binary made in makeTestBinary
func removeTestBinary() {
	err := os.Remove(binary) // Delete the binary when finished
	if err != nil {
		log.Printf("Error removing test binary %q: %v", binary, err)
	}
}

func main() {
	flag.Parse()
	if *runTests != "" {
		newRemotes := []remoteConfig{}
		for _, name := range strings.Split(*runTests, ",") {
			for i := range remotes {
				if remotes[i].Name == name {
					newRemotes = append(newRemotes, remotes[i])
					goto found
				}
			}
			log.Printf("Remote %q not found - inserting with default flags", name)
			newRemotes = append(newRemotes, remoteConfig{Name: name})
		found:
		}
		remotes = newRemotes
	}
	var names []string
	for _, remote := range remotes {
		names = append(names, remote.Name)
	}
	log.Printf("Testing remotes: %s", strings.Join(names, ", "))

	start := time.Now()
	if *clean {
		fs.LoadConfig()
	} else {
		makeTestBinary()
		defer removeTestBinary()
	}

	// start the tests
	results := make(chan *test, 8)
	awaiting := 0
	bools := []bool{false, true}
	if *clean {
		// Don't run -subdir and -fast-list if -clean
		bools = bools[:1]
	}
	for _, remote := range remotes {
		for _, subdir := range bools {
			for _, fastlist := range bools {
				if (!subdir || subdir && remote.SubDir) && (!fastlist || fastlist && remote.FastList) {
					go newTest(remote.Name, subdir, fastlist).run(results)
					awaiting++
				}
			}
		}
	}

	// Wait for the tests to finish
	var failed []*test
	for ; awaiting > 0; awaiting-- {
		t := <-results
		if !t.passed() {
			failed = append(failed, t)
		}
	}
	duration := time.Since(start)

	// Summarise results
	if len(failed) == 0 {
		log.Printf("PASS: All tests finished OK in %v", duration)
	} else {
		log.Printf("FAIL: %d tests failed in %v", len(failed), duration)
		for _, t := range failed {
			log.Printf("  * %s", toShell(t.nextCmdLine()))
			log.Printf("    * Failed tests: %v", t.failedTests)
		}
		os.Exit(1)
	}
}
<commit_msg>fs: integration tests: add SUMMARY heading for log scraping<commit_after>// +build ignore

// Run tests for all the remotes
//
// Run with go run test_all.go
package main

import (
	"flag"
	"log"
	"os"
	"os/exec"
	"regexp"
	"runtime"
	"strings"
	"time"

	"github.com/ncw/rclone/fs"
	_ "github.com/ncw/rclone/fs/all" // import all fs
	"github.com/ncw/rclone/fstest"
)

type remoteConfig struct {
	Name     string
	SubDir   bool
	FastList bool
}

var (
	remotes = []remoteConfig{
		{
			Name:     "TestAmazonCloudDrive:",
			SubDir:   false,
			FastList: false,
		},
		{
			Name:     "TestB2:",
			SubDir:   true,
			FastList: true,
		},
		{
			Name:     "TestCryptDrive:",
			SubDir:   false,
			FastList: false,
		},
		{
			Name:     "TestCryptSwift:",
			SubDir:   false,
			FastList: false,
		},
		{
			Name:     "TestDrive:",
			SubDir:   false,
			FastList: false,
		},
		{
			Name:     "TestDropbox:",
			SubDir:   false,
			FastList: false,
		},
		{
			Name:     "TestGoogleCloudStorage:",
			SubDir:   true,
			FastList: true,
		},
		{
			Name:     "TestHubic:",
			SubDir:   false,
			FastList: false,
		},
		{
			Name:     "TestOneDrive:",
			SubDir:   false,
			FastList: false,
		},
		{
			Name:     "TestS3:",
			SubDir:   true,
			FastList: true,
		},
		{
			Name:     "TestSftp:",
			SubDir:   false,
			FastList: false,
		},
		{
			Name:     "TestSwift:",
			SubDir:   true,
			FastList: true,
		},
		{
			Name:     "TestYandex:",
			SubDir:   false,
			FastList: false,
		},
		{
			Name:     "TestFTP:",
			SubDir:   false,
			FastList: false,
		},
		{
			Name:     "TestBox:",
			SubDir:   false,
			FastList: false,
		},
		{
			Name:     "TestQingStor:",
			SubDir:   false,
			FastList: false,
		},
		{
			Name:     "TestAzureBlob:",
			SubDir:   true,
			FastList: true,
		},
		{
			Name:     "TestPcloud:",
			SubDir:   false,
			FastList: false,
		},
		{
			Name:     "TestWebdav:",
			SubDir:   false,
			FastList: false,
		},
		{
			Name:     "TestCache:",
			SubDir:   true,
			FastList: true,
		},
	}
	binary = "fs.test"
	// Flags
	maxTries = flag.Int("maxtries", 5, "Number of times to try each test")
	runTests = flag.String("remotes", "", "Comma separated list of remotes to test, eg 'TestSwift:,TestS3'")
	clean    = flag.Bool("clean", false, "Instead of testing, clean all left over test directories")
	runOnly  = flag.String("run-only", "", "Run only those tests matching the regexp supplied")
	timeout  = flag.Duration("timeout", 30*time.Minute, "Maximum time to run each test for before giving up")
)

// test holds info about a running test
type test struct {
	remote      string
	subdir      bool
	cmdLine     []string
	cmdString   string
	try         int
	err         error
	output      []byte
	failedTests []string
	runFlag     string
}

// newTest creates a new test
func newTest(remote string, subdir bool, fastlist bool) *test {
	t := &test{
		remote:  remote,
		subdir:  subdir,
		cmdLine: []string{"./" + binary, "-test.timeout", (*timeout).String(), "-remote", remote},
		try:     1,
	}
	if *fstest.Verbose {
		t.cmdLine = append(t.cmdLine, "-test.v")
		fs.Config.LogLevel = fs.LogLevelDebug
	}
	if *runOnly != "" {
		t.cmdLine = append(t.cmdLine, "-test.run", *runOnly)
	}
	if subdir {
		t.cmdLine = append(t.cmdLine, "-subdir")
	}
	if fastlist {
		t.cmdLine = append(t.cmdLine, "-fast-list")
	}
	t.cmdString = toShell(t.cmdLine)
	return t
}

// dumpOutput prints the error output
func (t *test) dumpOutput() {
	log.Println("------------------------------------------------------------")
	log.Printf("---- %q ----", t.cmdString)
	log.Println(string(t.output))
	log.Println("------------------------------------------------------------")
}

var failRe = regexp.MustCompile(`(?m)^--- FAIL: (Test\w*) \(`)

// findFailures looks for all the tests which failed
func (t *test) findFailures() {
	oldFailedTests := t.failedTests
	t.failedTests = nil
	for _, matches := range failRe.FindAllSubmatch(t.output, -1) {
		t.failedTests = append(t.failedTests, string(matches[1]))
	}
	if len(t.failedTests) != 0 {
		t.runFlag = "^(" + strings.Join(t.failedTests, "|") + ")$"
	} else {
		t.runFlag = ""
	}
	if t.passed() && len(t.failedTests) != 0 {
		log.Printf("%q - Expecting no errors but got: %v", t.cmdString, t.failedTests)
		t.dumpOutput()
	} else if !t.passed() && len(t.failedTests) == 0 {
		log.Printf("%q - Expecting errors but got none: %v", t.cmdString, t.failedTests)
		t.dumpOutput()
		t.failedTests = oldFailedTests
	}
}

// nextCmdLine returns the next command line
func (t *test) nextCmdLine() []string {
	cmdLine := t.cmdLine[:]
	if t.runFlag != "" {
		cmdLine = append(cmdLine, "-test.run", t.runFlag)
	}
	return cmdLine
}

// if matches then is definitely OK in the shell
var shellOK = regexp.MustCompile("^[A-Za-z0-9./_:-]+$")

// converts a argv style input into a shell command
func toShell(args []string) (result string) {
	for _, arg := range args {
		if result != "" {
			result += " "
		}
		if shellOK.MatchString(arg) {
			result += arg
		} else {
			result += "'" + arg + "'"
		}
	}
	return result
}

// trial runs a single test
func (t *test) trial() {
	cmdLine := t.nextCmdLine()
	cmdString := toShell(cmdLine)
	log.Printf("%q - Starting (try %d/%d)", cmdString, t.try, *maxTries)
	cmd := exec.Command(cmdLine[0], cmdLine[1:]...)
	start := time.Now()
	t.output, t.err = cmd.CombinedOutput()
	duration := time.Since(start)
	t.findFailures()
	if t.passed() {
		log.Printf("%q - Finished OK in %v (try %d/%d)", cmdString, duration, t.try, *maxTries)
	} else {
		log.Printf("%q - Finished ERROR in %v (try %d/%d): %v: Failed %v", cmdString, duration, t.try, *maxTries, t.err, t.failedTests)
	}
}

// cleanFs runs a single clean fs for left over directories
func (t *test) cleanFs() error {
	f, err := fs.NewFs(t.remote)
	if err != nil {
		return err
	}
	entries, err := fs.ListDirSorted(f, true, "")
	if err != nil {
		return err
	}
	return entries.ForDirError(func(dir fs.Directory) error {
		remote := dir.Remote()
		if fstest.MatchTestRemote.MatchString(remote) {
			log.Printf("Purging %s%s", t.remote, remote)
			dir, err := fs.NewFs(t.remote + remote)
			if err != nil {
				return err
			}
			return fs.Purge(dir)
		}
		return nil
	})
}

// clean runs a single clean on a fs for left over directories
func (t *test) clean() {
	log.Printf("%q - Starting clean (try %d/%d)", t.remote, t.try, *maxTries)
	start := time.Now()
	t.err = t.cleanFs()
	if t.err != nil {
		log.Printf("%q - Failed to purge %v", t.remote, t.err)
	}
	duration := time.Since(start)
	if t.passed() {
		log.Printf("%q - Finished OK in %v (try %d/%d)", t.cmdString, duration, t.try, *maxTries)
	} else {
		log.Printf("%q - Finished ERROR in %v (try %d/%d): %v", t.cmdString, duration, t.try, *maxTries, t.err)
	}
}

// passed returns true if the test passed
func (t *test) passed() bool {
	return t.err == nil
}

// run runs all the trials for this test
func (t *test) run(result chan<- *test) {
	for t.try = 1; t.try <= *maxTries; t.try++ {
		if *clean {
			if !t.subdir {
				t.clean()
			}
		} else {
			t.trial()
		}
		if t.passed() {
			break
		}
	}
	if !t.passed() {
		t.dumpOutput()
	}
	result <- t
}

// makeTestBinary makes the binary we will run
func makeTestBinary() {
	if runtime.GOOS == "windows" {
		binary += ".exe"
	}
	log.Printf("Making test binary %q", binary)
	err := exec.Command("go", "test", "-c", "-o", binary).Run()
	if err != nil {
		log.Fatalf("Failed to make test binary: %v", err)
	}
	if _, err := os.Stat(binary); err != nil {
		log.Fatalf("Couldn't find test binary %q", binary)
	}
}

// removeTestBinary removes the binary made in makeTestBinary
func removeTestBinary() {
	err := os.Remove(binary) // Delete the binary when finished
	if err != nil {
		log.Printf("Error removing test binary %q: %v", binary, err)
	}
}

func main() {
	flag.Parse()
	if *runTests != "" {
		newRemotes := []remoteConfig{}
		for _, name := range strings.Split(*runTests, ",") {
			for i := range remotes {
				if remotes[i].Name == name {
					newRemotes = append(newRemotes, remotes[i])
					goto found
				}
			}
			log.Printf("Remote %q not found - inserting with default flags", name)
			newRemotes = append(newRemotes, remoteConfig{Name: name})
		found:
		}
		remotes = newRemotes
	}
	var names []string
	for _, remote := range remotes {
		names = append(names, remote.Name)
	}
	log.Printf("Testing remotes: %s", strings.Join(names, ", "))

	start := time.Now()
	if *clean {
		fs.LoadConfig()
	} else {
		makeTestBinary()
		defer removeTestBinary()
	}

	// start the tests
	results := make(chan *test, 8)
	awaiting := 0
	bools := []bool{false, true}
	if *clean {
		// Don't run -subdir and -fast-list if -clean
		bools = bools[:1]
	}
	for _, remote := range remotes {
		for _, subdir := range bools {
			for _, fastlist := range bools {
				if (!subdir || subdir && remote.SubDir) && (!fastlist || fastlist && remote.FastList) {
					go newTest(remote.Name, subdir, fastlist).run(results)
					awaiting++
				}
			}
		}
	}

	// Wait for the tests to finish
	var failed []*test
	for ; awaiting > 0; awaiting-- {
		t := <-results
		if !t.passed() {
			failed = append(failed, t)
		}
	}
	duration := time.Since(start)

	// Summarise results
	log.Printf("SUMMARY")
	if len(failed) == 0 {
		log.Printf("PASS: All tests finished OK in %v", duration)
	} else {
		log.Printf("FAIL: %d tests failed in %v", len(failed), duration)
		for _, t := range failed {
			log.Printf("  * %s", toShell(t.nextCmdLine()))
			log.Printf("    * Failed tests: %v", t.failedTests)
		}
		os.Exit(1)
	}
}
<|endoftext|>


<commit_before>package main

import (
	"eaciit/gdrj/model"
	"eaciit/gdrj/modules"
	"os"

	"github.com/eaciit/dbox"
	"github.com/eaciit/orm/v1"
	"github.com/eaciit/toolkit"
	// "strings"
	"sync"
	"time"
)

var conn dbox.IConnection
var count, ird, irddisc, iexp, idiscount int
var mwg sync.WaitGroup

func setinitialconnection() {
	var err error
	conn, err = modules.GetDboxIConnection("db_godrej")

	if err != nil {
		toolkit.Println("Initial connection found : ", err)
		os.Exit(1)
	}

	err = gdrj.SetDb(conn)
	if err != nil {
		toolkit.Println("Initial connection found : ", err)
		os.Exit(1)
	}
}

func getCursor(obj orm.IModel) dbox.ICursor {
	c, e := gdrj.Find(obj, nil, nil)
	if e != nil {
		return nil
	}
	return c
}

func main() {
	setinitialconnection()
	defer gdrj.CloseDb()

	toolkit.Println("START...")

	crx, err := gdrj.Find(new(gdrj.SalesTrx),
		nil,
		toolkit.M{})

	if err != nil {
		toolkit.Println("Error Found : ", err.Error())
		os.Exit(1)
	}
	defer crx.Close()

	count = crx.Count()

	jobs := make(chan *gdrj.SalesTrx, count)
	toolkit.Println("Prepare Worker")
	for wi := 0; wi < 10; wi++ {
		mwg.Add(1)
		go worker(wi, jobs)
	}

	toolkit.Println("Total Data : ", count)
	step := count / 100
	i := 0
	t0 := time.Now()
	for {
		i++
		st := new(gdrj.SalesTrx)
		e := crx.Fetch(&st, 1, false)
		if e != nil {
			toolkit.Println("Error Found : ", e.Error())
			break
		}

		num := 0

		switch st.Src {
		case "RD":
			ird++
			num = ird
		case "RD-DISC":
			irddisc++
			num = irddisc
		case "DISCOUNT":
			idiscount++
			num = idiscount
		case "EXPORT":
			iexp++
			num = iexp
		default:
			st.Src = "VDIST"
		}

		if st.Src != "VDIST" {
			st.SalesHeaderID = toolkit.Sprintf("%v_%v_%v_%v_%v", st.Src, st.Year, st.Month, st.SKUID, num)
			st.ID = st.SalesHeaderID
		} else if st.Customer != nil && st.Customer.ChannelID == "I1" {
			continue
		}

		jobs <- st
		if i > step {
			toolkit.Printfn("Processing %d of %d in %s",
				i, count,
				time.Since(t0).String())
			step += count / 100
		}
	}

	close(jobs)
	mwg.Wait()

	toolkit.Printfn("Processing done in %s",
		time.Since(t0).String())
}

func worker(wi int, jobs <-chan *gdrj.SalesTrx) {
	workerConn, _ := modules.GetDboxIConnection("db_godrej")
	defer workerConn.Close()

	var j *gdrj.SalesTrx
	table := toolkit.Sprintf("%v_1", j.TableName())

	for j = range jobs {
		workerConn.NewQuery().From(table).
			Save().Exec(toolkit.M{}.Set("data", j))
	}

	mwg.Done()
}
<commit_msg>inject<commit_after>package main

import (
	"eaciit/gdrj/model"
	"eaciit/gdrj/modules"
	"os"

	"github.com/eaciit/dbox"
	"github.com/eaciit/orm/v1"
	"github.com/eaciit/toolkit"
	// "strings"
	"sync"
	"time"
)

var conn dbox.IConnection
var count, ird, irddisc, iexp, idiscount int

// var mwg sync.WaitGroup

func setinitialconnection() {
	var err error
	conn, err = modules.GetDboxIConnection("db_godrej")

	if err != nil {
		toolkit.Println("Initial connection found : ", err)
		os.Exit(1)
	}

	err = gdrj.SetDb(conn)
	if err != nil {
		toolkit.Println("Initial connection found : ", err)
		os.Exit(1)
	}
}

func getCursor(obj orm.IModel) dbox.ICursor {
	c, e := gdrj.Find(obj, nil, nil)
	if e != nil {
		return nil
	}
	return c
}

func main() {
	setinitialconnection()
	defer gdrj.CloseDb()

	toolkit.Println("START...")

	crx, err := gdrj.Find(new(gdrj.SalesPL),
		nil,
		toolkit.M{})

	if err != nil {
		toolkit.Println("Error Found : ", err.Error())
		os.Exit(1)
	}
	defer crx.Close()

	count = crx.Count()

	jobs := make(chan *gdrj.SalesTrx, count)
	result := make(chan int, count)
	toolkit.Println("Prepare Worker")
	for wi := 0; wi < 10; wi++ {
		go worker(wi, jobs, result)
	}

	toolkit.Println("Total Data : ", count)
	step := count / 100
	i := 0
	t0 := time.Now()
	for {
		i++
		st := new(gdrj.SalesTrx)
		e := crx.Fetch(&st, 1, false)
		if e != nil {
			toolkit.Println("Error Found : ", e.Error())
			break
		}

		num := 0

		switch st.Src {
		case "RD":
			ird++
			num = ird
		case "RD-DISC":
			irddisc++
			num = irddisc
		case "DISCOUNT":
			idiscount++
			num = idiscount
		case "EXPORT":
			iexp++
			num = iexp
		default:
			st.Src = "VDIST"
		}

		if st.Src != "VDIST" {
			st.SalesHeaderID = toolkit.Sprintf("%v_%v_%v_%v_%v", st.Src, st.Year, st.Month, st.SKUID, num)
			st.ID = st.SalesHeaderID
		} else if st.Customer != nil && st.Customer.ChannelID == "I1" {
			continue
		}

		jobs <- st
		if i > step {
			toolkit.Printfn("Processing %d of %d in %s",
				i, count,
				time.Since(t0).String())
			step += count / 100
		}
	}

	close(jobs)
	mwg.Wait()

	toolkit.Printfn("Processing done in %s",
		time.Since(t0).String())
}

func worker(wi int, jobs <-chan *gdrj.SalesTrx, result chan<- string) {
	workerConn, _ := modules.GetDboxIConnection("db_godrej")
	defer workerConn.Close()

	var j *gdrj.SalesTrx
	table := toolkit.Sprintf("%v_1", j.TableName())

	for j = range jobs {
		workerConn.NewQuery().From(table).
			Save().Exec(toolkit.M{}.Set("data", j))
	}

	mwg.Done()
}
<|endoftext|>


<commit_before>package router

import (
	"time"

	"github.com/smancke/guble/protocol"
	"github.com/smancke/guble/server/store"
)

// Matcher is a func type that receives two route configurations pointers as parameters and
// returns true if the routes are matching
type Matcher func(RouteConfig, RouteConfig, ...string) bool

type RouteConfig struct {
	RouteParams

	Path protocol.Path

	ChannelSize int

	// queueSize specifies the size of the internal queue slice
	// (how many items to hold before the channel is closed).
	// If set to `0` then the queue will have no capacity and the messages
	// are directly sent, without buffering.
	queueSize int

	// timeout defines how long to wait for the message to be read on the channel.
	// If timeout is reached the route is closed.
	timeout time.Duration

	// Matcher if set will be used to check equality of the routes
	Matcher Matcher `json:"-"`

	// FetchRequest to fetch messages before subscribing
	// The Partition field of the FetchRequest is overrided with the Partition of the Route topic
	FetchRequest *store.FetchRequest
}

func (rc *RouteConfig) Equal(other RouteConfig, keys ...string) bool {
	if rc.Matcher != nil {
		return rc.Matcher(*rc, other, keys...)
	}
	return rc.Path == other.Path && rc.RouteParams.Equal(other.RouteParams, keys...)
}

// messageFilter returns true if the route matches message filters
func (rc *RouteConfig) messageFilter(m *protocol.Message) bool {
	if m.Filters == nil {
		return true
	}

	return rc.Filter(m.Filters)
}

// Filter returns true if all filters are matched on the route
func (rc *RouteConfig) Filter(filters map[string]string) bool {
	for key, value := range filters {
		if rc.Get(key) != value {
			return false
		}
	}

	return true
}
<commit_msg>pr refactor.<commit_after>package router

import (
	"time"

	"github.com/smancke/guble/protocol"
	"github.com/smancke/guble/server/store"
)

// Matcher is a func type that receives two route configurations pointers as parameters and
// returns true if the routes are matching
type Matcher func(RouteConfig, RouteConfig, ...string) bool

type RouteConfig struct {
	RouteParams

	Path protocol.Path

	ChannelSize int

	// queueSize specifies the size of the internal queue slice
	// (how many items to hold before the channel is closed).
	// If set to `0` then the queue will have no capacity and the messages
	// are directly sent, without buffering.
	queueSize int

	// timeout defines how long to wait for the message to be read on the channel.
	// If timeout is reached the route is closed.
	timeout time.Duration

	// Matcher if set will be used to check equality of the routes
	Matcher Matcher `json:"-"`

	// FetchRequest to fetch messages before subscribing
	// The Partition field of the FetchRequest is overrided with the Partition of the Route topic
	FetchRequest *store.FetchRequest `json:"-"`
}

func (rc *RouteConfig) Equal(other RouteConfig, keys ...string) bool {
	if rc.Matcher != nil {
		return rc.Matcher(*rc, other, keys...)
	}
	return rc.Path == other.Path && rc.RouteParams.Equal(other.RouteParams, keys...)
}

// messageFilter returns true if the route matches message filters
func (rc *RouteConfig) messageFilter(m *protocol.Message) bool {
	if m.Filters == nil {
		return true
	}

	return rc.Filter(m.Filters)
}

// Filter returns true if all filters are matched on the route
func (rc *RouteConfig) Filter(filters map[string]string) bool {
	for key, value := range filters {
		if rc.Get(key) != value {
			return false
		}
	}

	return true
}
<|endoftext|>


<commit_before>package server_test

import (
	"context"

	"github.com/cri-o/cri-o/server/cri/types"
	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
)

// The actual test suite
var _ = t.Describe("Status", func() {
	// Prepare the sut
	BeforeEach(func() {
		beforeEach()
		setupSUT()
	})

	AfterEach(afterEach)

	t.Describe("Status", func() {
		It("should succeed", func() {
			// When
			response, err := sut.Status(context.Background(),
				&types.StatusRequest{})

			// Then
			Expect(err).To(BeNil())
			Expect(response).NotTo(BeNil())
			Expect(len(response.Status.Conditions)).To(BeEquivalentTo(2))
			Expect(response.Status.Conditions[0].Status).To(BeTrue())
		})

		It("should succeed when CNI plugin status errors", func() {
			// When
			response, err := sut.Status(context.Background(),
				&types.StatusRequest{})

			// Then
			Expect(err).To(BeNil())
			Expect(response).NotTo(BeNil())
			Expect(len(response.Status.Conditions)).To(BeEquivalentTo(2))
			Expect(response.Status.Conditions[0].Status).To(BeTrue())
		})
	})
})
<commit_msg>make runtime_status_test more accurate.<commit_after>package server_test

import (
	"context"

	"github.com/cri-o/cri-o/server/cri/types"
	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
)

// The actual test suite
var _ = t.Describe("Status", func() {
	// Prepare the sut
	BeforeEach(func() {
		beforeEach()
		setupSUT()
	})

	AfterEach(afterEach)

	t.Describe("Status", func() {
		It("should succeed", func() {
			// When
			response, err := sut.Status(context.Background(),
				&types.StatusRequest{})

			// Then
			Expect(err).To(BeNil())
			Expect(response).NotTo(BeNil())
			Expect(len(response.Status.Conditions)).To(BeEquivalentTo(2))
			for _, condition := range response.Status.Conditions {
				Expect(condition.Status).To(BeTrue())
			}
		})

		It("should succeed when CNI plugin status errors", func() {
			// When
			response, err := sut.Status(context.Background(),
				&types.StatusRequest{})

			// Then
			Expect(err).To(BeNil())
			Expect(response).NotTo(BeNil())
			Expect(len(response.Status.Conditions)).To(BeEquivalentTo(2))
			for _, condition := range response.Status.Conditions {
				Expect(condition.Status).To(BeTrue())
			}
		})
	})
})
<|endoftext|>


<commit_before>package yarn

import (
	"bufio"
	"fmt"
	"io"
	"log"
	"math/rand"
	"os/exec"
	"os/user"
	"regexp"
	"strconv"
	"strings"
	"syscall"
	"time"

	"github.com/pkg/errors"
)

func kInit(username, keytab string, uid, gid uint32) error {
	cmd := exec.Command("kinit", username, "-k", "-t", keytab)
	cmd.SysProcAttr = &syscall.SysProcAttr{}
	cmd.SysProcAttr.Credential = &syscall.Credential{Uid: uid, Gid: gid}

	if err := cmd.Run(); err != nil {
		return errors.Wrap(err, "failed executing kinit")
	}

	return nil
}

func kDest(uid, gid uint32) {
	cmd := exec.Command("kdestroy")
	cmd.SysProcAttr = &syscall.SysProcAttr{}
	cmd.SysProcAttr.Credential = &syscall.Credential{Uid: uid, Gid: gid}

	if err := cmd.Run(); err != nil {
		panic(fmt.Sprintf("failed executing kdestroy: %v", err))
	}
}

func randStr(strlen int) string {
	rand.Seed(time.Now().UTC().UnixNano())
	const chars = "abcdefghijklmnopqrstuvwxyz0123456789"
	r := make([]byte, strlen)
	for i := 0; i < strlen; i++ {
		r[i] = chars[rand.Intn(len(chars))]
	}
	return string(r)
}

func cleanDir(dir string) {
	// log.Printf("Removing empty directory %s", dir)
	cmdClean := exec.Command("hadoop", "fs", "-rmdir", dir)
	if out, err := cmdClean.Output(); err != nil {
		panic(fmt.Sprintf("failed to remove outdir: %v", string(out)))
	}
}

func getUser(username string) (uint32, uint32, error) {
	u, err := user.Lookup(username)
	if err != nil {
		return 0, 0, errors.Wrap(err, "failed to lookup user")
	}
	uid64, err := strconv.ParseUint(u.Uid, 10, 32)
	if err != nil {
		return 0, 0, errors.Wrap(err, "failed parsing uid to uint32")
	}
	gid64, err := strconv.ParseUint(u.Gid, 10, 32)
	if err != nil {
		return 0, 0, errors.Wrap(err, "failed parsing gid to unit32")
	}

	return uint32(uid64), uint32(gid64), nil
}

func yarnScan(r io.Reader, name string, appID, address, err *string) {
	reNode := regexp.MustCompile(`H2O node (\d+\.\d+\.\d+\.\d+:\d+)`)
	reApID := regexp.MustCompile(`application_(\d+_\d+)`)

	in := bufio.NewScanner(r)
	for in.Scan() {
		log.Println(fmt.Sprintf("YARN CLUSTER %s %v", name, in.Text()))

		if appID != nil {
			if s := reNode.FindSubmatch(in.Bytes()); s != nil {
				*address = string(s[1])
			}
		}
		if address != nil {
			if s := reApID.FindSubmatch(in.Bytes()); s != nil {
				*appID = string(s[1])
			}
		}
		if err != nil {
			if strings.Contains(in.Text(), "ERROR") {
				*err += in.Text() + "\n"
			}
		}
	}
}

// StartCloud starts a yarn cloud by shelling out to hadoop
//
// This process needs to store the job-ID to kill the process in the future
func StartCloud(size int, kerberos bool, mem, name, enginePath, username, keytab string) (string, string, string, error) {
	// Get user information for Kerberos and Yarn reasons
	uid, gid, err := getUser(username)
	if err != nil {
		return "", "", "", errors.Wrap(err, "failed getting user")
	}

	// If kerberos enabled, initialize and defer destroy
	if kerberos {
		if err := kInit(username, keytab, uid, gid); err != nil {
			return "", "", "", errors.Wrap(err, "failed initializing kerberos")
		}
		defer kDest(uid, gid)
	}

	// Randomize outfile name
	out := "steam/" + name + "_" + randStr(5) + "_out"

	cmdArgs := []string{
		"jar", enginePath,
		"-jobname", "STEAM_" + name,
		"-n", strconv.Itoa(size),
		"-mapperXmx", mem,
		"-output", out,
		"-disown",
	}

	// Execute command as user
	cmd := exec.Command("hadoop", cmdArgs...)
	cmd.SysProcAttr = &syscall.SysProcAttr{}
	cmd.SysProcAttr.Credential = &syscall.Credential{Uid: uid, Gid: gid}

	stdOut, err := cmd.StdoutPipe()
	if err != nil {
		return "", "", "", err
	}
	defer stdOut.Close()
	stdErr, err := cmd.StderrPipe()
	if err != nil {
		return "", "", "", err
	}
	defer stdErr.Close()

	if err := cmd.Start(); err != nil {
		return "", "", "", err
	}

	var appID, address, cmdErr string
	go yarnScan(stdOut, name, &appID, &address, &cmdErr)
	go yarnScan(stdOut, name, nil, nil, nil)

	if err := cmd.Wait(); err != nil {
		// cleanDir(out)
		// recover()
		return "", "", "", errors.Wrapf(err, "failed waiting on exec: %v", cmdErr)
	}

	return appID, address, out, nil
}

// StopCloud kills a hadoop cloud by shelling out a command based on the job-ID
//
// In the future this
func StopCloud(kerberos bool, name, id, outdir, username, keytab string) error {
	uid, gid, err := getUser(username)
	if err != nil {
		return errors.Wrap(err, "failed getting user")
	}

	if kerberos {
		if err := kInit(username, keytab, uid, gid); err != nil {
			return errors.Wrap(err, "failed initializing kerberos")
		}
		defer kDest(uid, gid)
	}

	cmd := exec.Command("hadoop", "job", "-kill", "job_"+id)
	cmd.SysProcAttr = &syscall.SysProcAttr{}
	cmd.SysProcAttr.Credential = &syscall.Credential{Uid: uid, Gid: gid}
	stdOut, err := cmd.StdoutPipe()
	if err != nil {
		return err
	}
	defer stdOut.Close()
	stdErr, err := cmd.StderrPipe()
	if err != nil {
		return err
	}
	defer stdErr.Close()
	go yarnScan(stdOut, name, nil, nil, nil)
	go yarnScan(stdErr, name, nil, nil, nil)

	defer cleanDir(outdir)
	return cmd.Run()
}
<commit_msg>STEAM-139: finishing up logs<commit_after>package yarn

import (
	"bufio"
	"fmt"
	"io"
	"log"
	"math/rand"
	"os/exec"
	"os/user"
	"regexp"
	"strconv"
	"strings"
	"syscall"
	"time"

	"github.com/pkg/errors"
)

func kInit(username, keytab string, uid, gid uint32) error {
	cmd := exec.Command("kinit", username, "-k", "-t", keytab)
	cmd.SysProcAttr = &syscall.SysProcAttr{}
	cmd.SysProcAttr.Credential = &syscall.Credential{Uid: uid, Gid: gid}

	if err := cmd.Run(); err != nil {
		return errors.Wrap(err, "failed executing kinit")
	}

	return nil
}

func kDest(uid, gid uint32) {
	cmd := exec.Command("kdestroy")
	cmd.SysProcAttr = &syscall.SysProcAttr{}
	cmd.SysProcAttr.Credential = &syscall.Credential{Uid: uid, Gid: gid}

	if err := cmd.Run(); err != nil {
		panic(fmt.Sprintf("failed executing kdestroy: %v", err))
	}
}

func randStr(strlen int) string {
	rand.Seed(time.Now().UTC().UnixNano())
	const chars = "abcdefghijklmnopqrstuvwxyz0123456789"
	r := make([]byte, strlen)
	for i := 0; i < strlen; i++ {
		r[i] = chars[rand.Intn(len(chars))]
	}
	return string(r)
}

func cleanDir(dir string) {
	// log.Printf("Removing empty directory %s", dir)
	cmdClean := exec.Command("hadoop", "fs", "-rmdir", dir)
	if out, err := cmdClean.Output(); err != nil {
		panic(fmt.Sprintf("failed to remove outdir: %v", string(out)))
	}
}

func getUser(username string) (uint32, uint32, error) {
	u, err := user.Lookup(username)
	if err != nil {
		return 0, 0, errors.Wrap(err, "failed to lookup user")
	}
	uid64, err := strconv.ParseUint(u.Uid, 10, 32)
	if err != nil {
		return 0, 0, errors.Wrap(err, "failed parsing uid to uint32")
	}
	gid64, err := strconv.ParseUint(u.Gid, 10, 32)
	if err != nil {
		return 0, 0, errors.Wrap(err, "failed parsing gid to unit32")
	}

	return uint32(uid64), uint32(gid64), nil
}

func yarnScan(r io.Reader, name, username string, appID, address, err *string) {
	reNode := regexp.MustCompile(`H2O node (\d+\.\d+\.\d+\.\d+:\d+)`)
	reApID := regexp.MustCompile(`application_(\d+_\d+)`)

	in := bufio.NewScanner(r)
	for in.Scan() {
		if in.Text() != "" {
			log.Println("YARN", name, username, in.Text())

			if appID != nil {
				if s := reNode.FindSubmatch(in.Bytes()); s != nil {
					*address = string(s[1])
				}
			}
			if address != nil {
				if s := reApID.FindSubmatch(in.Bytes()); s != nil {
					*appID = string(s[1])
				}
			}
			if err != nil {
				if strings.Contains(in.Text(), "ERROR") {
					*err += in.Text() + "\n"
				}
			}
		}
	}
}

// StartCloud starts a yarn cloud by shelling out to hadoop
//
// This process needs to store the job-ID to kill the process in the future
func StartCloud(size int, kerberos bool, mem, name, enginePath, username, keytab string) (string, string, string, error) {
	// Get user information for Kerberos and Yarn reasons
	uid, gid, err := getUser(username)
	if err != nil {
		return "", "", "", errors.Wrap(err, "failed getting user")
	}

	// If kerberos enabled, initialize and defer destroy
	if kerberos {
		if err := kInit(username, keytab, uid, gid); err != nil {
			return "", "", "", errors.Wrap(err, "failed initializing kerberos")
		}
		defer kDest(uid, gid)
	}

	// Randomize outfile name
	out := "steam/" + name + "_" + randStr(5) + "_out"

	cmdArgs := []string{
		"jar", enginePath,
		"-jobname", "STEAM_" + name,
		"-n", strconv.Itoa(size),
		"-mapperXmx", mem,
		"-output", out,
		"-disown",
	}

	// Execute command as user
	cmd := exec.Command("hadoop", cmdArgs...)
	cmd.SysProcAttr = &syscall.SysProcAttr{}
	cmd.SysProcAttr.Credential = &syscall.Credential{Uid: uid, Gid: gid}

	stdOut, err := cmd.StdoutPipe()
	if err != nil {
		return "", "", "", err
	}
	defer stdOut.Close()
	stdErr, err := cmd.StderrPipe()
	if err != nil {
		return "", "", "", err
	}
	defer stdErr.Close()

	if err := cmd.Start(); err != nil {
		return "", "", "", err
	}

	var appID, address, cmdErr string
	go yarnScan(stdOut, name, username, &appID, &address, &cmdErr)
	go yarnScan(stdErr, name, username, nil, nil, nil)

	if err := cmd.Wait(); err != nil {
		// cleanDir(out)
		// recover()
		return "", "", "", errors.Wrapf(err, "failed waiting on exec: %v", cmdErr)
	}

	return appID, address, out, nil
}

// StopCloud kills a hadoop cloud by shelling out a command based on the job-ID
//
// In the future this
func StopCloud(kerberos bool, name, id, outdir, username, keytab string) error {
	uid, gid, err := getUser(username)
	if err != nil {
		return errors.Wrap(err, "failed getting user")
	}

	if kerberos {
		if err := kInit(username, keytab, uid, gid); err != nil {
			return errors.Wrap(err, "failed initializing kerberos")
		}
		defer kDest(uid, gid)
	}

	cmd := exec.Command("hadoop", "job", "-kill", "job_"+id)
	cmd.SysProcAttr = &syscall.SysProcAttr{}
	cmd.SysProcAttr.Credential = &syscall.Credential{Uid: uid, Gid: gid}
	stdOut, err := cmd.StdoutPipe()
	if err != nil {
		return err
	}
	defer stdOut.Close()
	stdErr, err := cmd.StderrPipe()
	if err != nil {
		return err
	}
	defer stdErr.Close()
	go yarnScan(stdOut, name, username, nil, nil, nil)
	go yarnScan(stdErr, name, username, nil, nil, nil)

	defer cleanDir(outdir)
	return cmd.Run()
}
<|endoftext|>


<commit_before>// Local filesystem interface
package local

import (
	"crypto/md5"
	"encoding/hex"
	"fmt"
	"hash"
	"io"
	"io/ioutil"
	"os"
	"path"
	"path/filepath"
	"sync"
	"time"

	"github.com/ncw/rclone/fs"
)

// Register with Fs
func init() {
	fs.Register(&fs.FsInfo{
		Name:  "local",
		NewFs: NewFs,
	})
}

// FsLocal represents a local filesystem rooted at root
type FsLocal struct {
	root        string        // The root directory
	precisionOk sync.Once     // Whether we need to read the precision
	precision   time.Duration // precision of local filesystem
}

// FsObjectLocal represents a local filesystem object
type FsObjectLocal struct {
	local  fs.Fs       // The Fs this object is part of
	remote string      // The remote path
	path   string      // The local path
	info   os.FileInfo // Interface for file info (always present)
	md5sum string      // the md5sum of the object or "" if not calculated
}

// ------------------------------------------------------------

// NewFs contstructs an FsLocal from the path
func NewFs(name, root string) (fs.Fs, error) {
	root = path.Clean(root)
	f := &FsLocal{root: root}
	// Check to see if this points to a file
	fi, err := os.Lstat(f.root)
	if err == nil && fi.Mode().IsRegular() {
		// It is a file, so use the parent as the root
		remote := path.Base(root)
		f.root = path.Dir(root)
		obj := f.NewFsObject(remote)
		// return a Fs Limited to this object
		return fs.NewLimited(f, obj), nil
	}
	return f, nil
}

// String converts this FsLocal to a string
func (f *FsLocal) String() string {
	return fmt.Sprintf("Local file system at %s", f.root)
}

// Return an FsObject from a path
//
// May return nil if an error occurred
func (f *FsLocal) newFsObjectWithInfo(remote string, info os.FileInfo) fs.Object {
	path := filepath.Join(f.root, remote)
	o := &FsObjectLocal{local: f, remote: remote, path: path}
	if info != nil {
		o.info = info
	} else {
		err := o.lstat()
		if err != nil {
			fs.Debug(o, "Failed to stat %s: %s", path, err)
			return nil
		}
	}
	return o
}

// Return an FsObject from a path
//
// May return nil if an error occurred
func (f *FsLocal) NewFsObject(remote string) fs.Object {
	return f.newFsObjectWithInfo(remote, nil)
}

// List the path returning a channel of FsObjects
//
// Ignores everything which isn't Storable, eg links etc
func (f *FsLocal) List() fs.ObjectsChan {
	out := make(fs.ObjectsChan, fs.Config.Checkers)
	go func() {
		err := filepath.Walk(f.root, func(path string, fi os.FileInfo, err error) error {
			if err != nil {
				fs.Stats.Error()
				fs.Log(f, "Failed to open directory: %s: %s", path, err)
			} else {
				remote, err := filepath.Rel(f.root, path)
				if err != nil {
					fs.Stats.Error()
					fs.Log(f, "Failed to get relative path %s: %s", path, err)
					return nil
				}
				if remote == "." {
					return nil
					// remote = ""
				}
				if fs := f.newFsObjectWithInfo(remote, fi); fs != nil {
					if fs.Storable() {
						out <- fs
					}
				}
			}
			return nil
		})
		if err != nil {
			fs.Stats.Error()
			fs.Log(f, "Failed to open directory: %s: %s", f.root, err)
		}
		close(out)
	}()
	return out
}

// Walk the path returning a channel of FsObjects
func (f *FsLocal) ListDir() fs.DirChan {
	out := make(fs.DirChan, fs.Config.Checkers)
	go func() {
		defer close(out)
		items, err := ioutil.ReadDir(f.root)
		if err != nil {
			fs.Stats.Error()
			fs.Log(f, "Couldn't find read directory: %s", err)
		} else {
			for _, item := range items {
				if item.IsDir() {
					dir := &fs.Dir{
						Name:  item.Name(),
						When:  item.ModTime(),
						Bytes: 0,
						Count: 0,
					}
					// Go down the tree to count the files and directories
					dirpath := path.Join(f.root, item.Name())
					err := filepath.Walk(dirpath, func(path string, fi os.FileInfo, err error) error {
						if err != nil {
							fs.Stats.Error()
							fs.Log(f, "Failed to open directory: %s: %s", path, err)
						} else {
							dir.Count += 1
							dir.Bytes += fi.Size()
						}
						return nil
					})
					if err != nil {
						fs.Stats.Error()
						fs.Log(f, "Failed to open directory: %s: %s", dirpath, err)
					}
					out <- dir
				}
			}
		}
		// err := f.findRoot(false)
	}()
	return out
}

// Puts the FsObject to the local filesystem
func (f *FsLocal) Put(in io.Reader, remote string, modTime time.Time, size int64) (fs.Object, error) {
	dstPath := filepath.Join(f.root, remote)
	// Temporary FsObject under construction - info filled in by Update()
	o := &FsObjectLocal{local: f, remote: remote, path: dstPath}
	err := o.Update(in, modTime, size)
	if err != nil {
		return nil, err
	}
	return o, nil
}

// Mkdir creates the directory if it doesn't exist
func (f *FsLocal) Mkdir() error {
	return os.MkdirAll(f.root, 0770)
}

// Rmdir removes the directory
//
// If it isn't empty it will return an error
func (f *FsLocal) Rmdir() error {
	return os.Remove(f.root)
}

// Return the precision
func (f *FsLocal) Precision() (precision time.Duration) {
	f.precisionOk.Do(func() {
		f.precision = f.readPrecision()
	})
	return f.precision
}

// Read the precision
func (f *FsLocal) readPrecision() (precision time.Duration) {
	// Default precision of 1s
	precision = time.Second

	// Create temporary file and test it
	fd, err := ioutil.TempFile("", "rclone")
	if err != nil {
		// If failed return 1s
		// fmt.Println("Failed to create temp file", err)
		return time.Second
	}
	path := fd.Name()
	// fmt.Println("Created temp file", path)
	err = fd.Close()
	if err != nil {
		return time.Second
	}

	// Delete it on return
	defer func() {
		// fmt.Println("Remove temp file")
		_ = os.Remove(path) // ignore error
	}()

	// Find the minimum duration we can detect
	for duration := time.Duration(1); duration < time.Second; duration *= 10 {
		// Current time with delta
		t := time.Unix(time.Now().Unix(), int64(duration))
		err := os.Chtimes(path, t, t)
		if err != nil {
			// fmt.Println("Failed to Chtimes", err)
			break
		}

		// Read the actual time back
		fi, err := os.Stat(path)
		if err != nil {
			// fmt.Println("Failed to Stat", err)
			break
		}

		// If it matches - have found the precision
		// fmt.Println("compare", fi.ModTime(), t)
		if fi.ModTime() == t {
			// fmt.Println("Precision detected as", duration)
			return duration
		}
	}
	return
}

// Purge deletes all the files and directories
//
// Optional interface: Only implement this if you have a way of
// deleting all the files quicker than just running Remove() on the
// result of List()
func (f *FsLocal) Purge() error {
	fi, err := os.Lstat(f.root)
	if err != nil {
		return err
	}
	if !fi.Mode().IsDir() {
		return fmt.Errorf("Can't Purge non directory: %q", f.root)
	}
	return os.RemoveAll(f.root)
}

// ------------------------------------------------------------

// Return the parent Fs
func (o *FsObjectLocal) Fs() fs.Fs {
	return o.local
}

// Return a string version
func (o *FsObjectLocal) String() string {
	if o == nil {
		return "<nil>"
	}
	return o.remote
}

// Return the remote path
func (o *FsObjectLocal) Remote() string {
	return o.remote
}

// Md5sum calculates the Md5sum of a file returning a lowercase hex string
func (o *FsObjectLocal) Md5sum() (string, error) {
	if o.md5sum != "" {
		return o.md5sum, nil
	}
	in, err := os.Open(o.path)
	if err != nil {
		fs.Stats.Error()
		fs.Log(o, "Failed to open: %s", err)
		return "", err
	}
	hash := md5.New()
	_, err = io.Copy(hash, in)
	closeErr := in.Close()
	if err != nil {
		fs.Stats.Error()
		fs.Log(o, "Failed to read: %s", err)
		return "", err
	}
	if closeErr != nil {
		fs.Stats.Error()
		fs.Log(o, "Failed to close: %s", closeErr)
		return "", closeErr
	}
	o.md5sum = hex.EncodeToString(hash.Sum(nil))
	return o.md5sum, nil
}

// Size returns the size of an object in bytes
func (o *FsObjectLocal) Size() int64 {
	return o.info.Size()
}

// ModTime returns the modification time of the object
func (o *FsObjectLocal) ModTime() time.Time {
	return o.info.ModTime()
}

// Sets the modification time of the local fs object
func (o *FsObjectLocal) SetModTime(modTime time.Time) {
	err := os.Chtimes(o.path, modTime, modTime)
	if err != nil {
		fs.Debug(o, "Failed to set mtime on file: %s", err)
		return
	}
	// Re-read metadata
	err = o.lstat()
	if err != nil {
		fs.Debug(o, "Failed to stat: %s", err)
		return
	}
}

// Is this object storable
func (o *FsObjectLocal) Storable() bool {
	mode := o.info.Mode()
	if mode&(os.ModeSymlink|os.ModeNamedPipe|os.ModeSocket|os.ModeDevice) != 0 {
		fs.Debug(o, "Can't transfer non file/directory")
		return false
	} else if mode&os.ModeDir != 0 {
		// fs.Debug(o, "Skipping directory")
		return false
	}
	return true
}

// localOpenFile wraps an io.ReadCloser and updates the md5sum of the
// object that is read
type localOpenFile struct {
	o    *FsObjectLocal // object that is open
	in   io.ReadCloser  // handle we are wrapping
	hash hash.Hash      // currently accumulating MD5
}

// Read bytes from the object - see io.Reader
func (file *localOpenFile) Read(p []byte) (n int, err error) {
	n, err = file.in.Read(p)
	if n > 0 {
		// Hash routines never return an error
		_, _ = file.hash.Write(p[:n])
	}
	return
}

// Close the object and update the md5sum
func (file *localOpenFile) Close() (err error) {
	err = file.in.Close()
	if err == nil {
		file.o.md5sum = hex.EncodeToString(file.hash.Sum(nil))
	} else {
		file.o.md5sum = ""
	}
	return err
}

// Open an object for read
func (o *FsObjectLocal) Open() (in io.ReadCloser, err error) {
	in, err = os.Open(o.path)
	if err != nil {
		return
	}
	// Update the md5sum as we go along
	in = &localOpenFile{
		o:    o,
		in:   in,
		hash: md5.New(),
	}
	return
}

// Update the object from in with modTime and size
func (o *FsObjectLocal) Update(in io.Reader, modTime time.Time, size int64) error {
	dir := path.Dir(o.path)
	err := os.MkdirAll(dir, 0770)
	if err != nil {
		return err
	}

	out, err := os.Create(o.path)
	if err != nil {
		return err
	}

	// Calculate the md5sum of the object we are reading as we go along
	hash := md5.New()
	in = io.TeeReader(in, hash)

	_, err = io.Copy(out, in)
	outErr := out.Close()
	if err != nil {
		return err
	}
	if outErr != nil {
		return outErr
	}

	// All successful so update the md5sum
	o.md5sum = hex.EncodeToString(hash.Sum(nil))

	// Set the mtime
	o.SetModTime(modTime)

	// ReRead info now that we have finished
	return o.lstat()
}

// Stat a FsObject into info
func (o *FsObjectLocal) lstat() error {
	info, err := os.Lstat(o.path)
	o.info = info
	return err
}

// Remove an object
func (o *FsObjectLocal) Remove() error {
	return os.Remove(o.path)
}

// Check the interfaces are satisfied
var _ fs.Fs = &FsLocal{}
var _ fs.Purger = &FsLocal{}
var _ fs.Object = &FsObjectLocal{}
<commit_msg>local: Fix directory separators on Windows - fixes #24<commit_after>// Local filesystem interface
package local

// Note that all rclone paths should be / separated.  Anything coming
// from the filepath module will have \ separators on windows so
// should be converted using filepath.ToSlash.  Windows is quite happy
// with / separators so there is no need to convert them back.

import (
	"crypto/md5"
	"encoding/hex"
	"fmt"
	"hash"
	"io"
	"io/ioutil"
	"os"
	"path"
	"path/filepath"
	"sync"
	"time"

	"github.com/ncw/rclone/fs"
)

// Register with Fs
func init() {
	fs.Register(&fs.FsInfo{
		Name:  "local",
		NewFs: NewFs,
	})
}

// FsLocal represents a local filesystem rooted at root
type FsLocal struct {
	root        string        // The root directory
	precisionOk sync.Once     // Whether we need to read the precision
	precision   time.Duration // precision of local filesystem
}

// FsObjectLocal represents a local filesystem object
type FsObjectLocal struct {
	local  fs.Fs       // The Fs this object is part of
	remote string      // The remote path
	path   string      // The local path
	info   os.FileInfo // Interface for file info (always present)
	md5sum string      // the md5sum of the object or "" if not calculated
}

// ------------------------------------------------------------

// NewFs contstructs an FsLocal from the path
func NewFs(name, root string) (fs.Fs, error) {
	root = filepath.ToSlash(path.Clean(root))
	f := &FsLocal{root: root}
	// Check to see if this points to a file
	fi, err := os.Lstat(f.root)
	if err == nil && fi.Mode().IsRegular() {
		// It is a file, so use the parent as the root
		remote := path.Base(root)
		f.root = path.Dir(root)
		obj := f.NewFsObject(remote)
		// return a Fs Limited to this object
		return fs.NewLimited(f, obj), nil
	}
	return f, nil
}

// String converts this FsLocal to a string
func (f *FsLocal) String() string {
	return fmt.Sprintf("Local file system at %s", f.root)
}

// Return an FsObject from a path
//
// May return nil if an error occurred
func (f *FsLocal) newFsObjectWithInfo(remote string, info os.FileInfo) fs.Object {
	remote = filepath.ToSlash(remote)
	path := path.Join(f.root, remote)
	o := &FsObjectLocal{local: f, remote: remote, path: path}
	if info != nil {
		o.info = info
	} else {
		err := o.lstat()
		if err != nil {
			fs.Debug(o, "Failed to stat %s: %s", path, err)
			return nil
		}
	}
	return o
}

// Return an FsObject from a path
//
// May return nil if an error occurred
func (f *FsLocal) NewFsObject(remote string) fs.Object {
	return f.newFsObjectWithInfo(remote, nil)
}

// List the path returning a channel of FsObjects
//
// Ignores everything which isn't Storable, eg links etc
func (f *FsLocal) List() fs.ObjectsChan {
	out := make(fs.ObjectsChan, fs.Config.Checkers)
	go func() {
		err := filepath.Walk(f.root, func(path string, fi os.FileInfo, err error) error {
			if err != nil {
				fs.Stats.Error()
				fs.Log(f, "Failed to open directory: %s: %s", path, err)
			} else {
				remote, err := filepath.Rel(f.root, path)
				if err != nil {
					fs.Stats.Error()
					fs.Log(f, "Failed to get relative path %s: %s", path, err)
					return nil
				}
				if remote == "." {
					return nil
					// remote = ""
				}
				if fs := f.newFsObjectWithInfo(remote, fi); fs != nil {
					if fs.Storable() {
						out <- fs
					}
				}
			}
			return nil
		})
		if err != nil {
			fs.Stats.Error()
			fs.Log(f, "Failed to open directory: %s: %s", f.root, err)
		}
		close(out)
	}()
	return out
}

// Walk the path returning a channel of FsObjects
func (f *FsLocal) ListDir() fs.DirChan {
	out := make(fs.DirChan, fs.Config.Checkers)
	go func() {
		defer close(out)
		items, err := ioutil.ReadDir(f.root)
		if err != nil {
			fs.Stats.Error()
			fs.Log(f, "Couldn't find read directory: %s", err)
		} else {
			for _, item := range items {
				if item.IsDir() {
					dir := &fs.Dir{
						Name:  item.Name(),
						When:  item.ModTime(),
						Bytes: 0,
						Count: 0,
					}
					// Go down the tree to count the files and directories
					dirpath := path.Join(f.root, item.Name())
					err := filepath.Walk(dirpath, func(path string, fi os.FileInfo, err error) error {
						if err != nil {
							fs.Stats.Error()
							fs.Log(f, "Failed to open directory: %s: %s", path, err)
						} else {
							dir.Count += 1
							dir.Bytes += fi.Size()
						}
						return nil
					})
					if err != nil {
						fs.Stats.Error()
						fs.Log(f, "Failed to open directory: %s: %s", dirpath, err)
					}
					out <- dir
				}
			}
		}
		// err := f.findRoot(false)
	}()
	return out
}

// Puts the FsObject to the local filesystem
func (f *FsLocal) Put(in io.Reader, remote string, modTime time.Time, size int64) (fs.Object, error) {
	dstPath := path.Join(f.root, remote)
	// Temporary FsObject under construction - info filled in by Update()
	o := &FsObjectLocal{local: f, remote: remote, path: dstPath}
	err := o.Update(in, modTime, size)
	if err != nil {
		return nil, err
	}
	return o, nil
}

// Mkdir creates the directory if it doesn't exist
func (f *FsLocal) Mkdir() error {
	return os.MkdirAll(f.root, 0770)
}

// Rmdir removes the directory
//
// If it isn't empty it will return an error
func (f *FsLocal) Rmdir() error {
	return os.Remove(f.root)
}

// Return the precision
func (f *FsLocal) Precision() (precision time.Duration) {
	f.precisionOk.Do(func() {
		f.precision = f.readPrecision()
	})
	return f.precision
}

// Read the precision
func (f *FsLocal) readPrecision() (precision time.Duration) {
	// Default precision of 1s
	precision = time.Second

	// Create temporary file and test it
	fd, err := ioutil.TempFile("", "rclone")
	if err != nil {
		// If failed return 1s
		// fmt.Println("Failed to create temp file", err)
		return time.Second
	}
	path := fd.Name()
	// fmt.Println("Created temp file", path)
	err = fd.Close()
	if err != nil {
		return time.Second
	}

	// Delete it on return
	defer func() {
		// fmt.Println("Remove temp file")
		_ = os.Remove(path) // ignore error
	}()

	// Find the minimum duration we can detect
	for duration := time.Duration(1); duration < time.Second; duration *= 10 {
		// Current time with delta
		t := time.Unix(time.Now().Unix(), int64(duration))
		err := os.Chtimes(path, t, t)
		if err != nil {
			// fmt.Println("Failed to Chtimes", err)
			break
		}

		// Read the actual time back
		fi, err := os.Stat(path)
		if err != nil {
			// fmt.Println("Failed to Stat", err)
			break
		}

		// If it matches - have found the precision
		// fmt.Println("compare", fi.ModTime(), t)
		if fi.ModTime() == t {
			// fmt.Println("Precision detected as", duration)
			return duration
		}
	}
	return
}

// Purge deletes all the files and directories
//
// Optional interface: Only implement this if you have a way of
// deleting all the files quicker than just running Remove() on the
// result of List()
func (f *FsLocal) Purge() error {
	fi, err := os.Lstat(f.root)
	if err != nil {
		return err
	}
	if !fi.Mode().IsDir() {
		return fmt.Errorf("Can't Purge non directory: %q", f.root)
	}
	return os.RemoveAll(f.root)
}

// ------------------------------------------------------------

// Return the parent Fs
func (o *FsObjectLocal) Fs() fs.Fs {
	return o.local
}

// Return a string version
func (o *FsObjectLocal) String() string {
	if o == nil {
		return "<nil>"
	}
	return o.remote
}

// Return the remote path
func (o *FsObjectLocal) Remote() string {
	return o.remote
}

// Md5sum calculates the Md5sum of a file returning a lowercase hex string
func (o *FsObjectLocal) Md5sum() (string, error) {
	if o.md5sum != "" {
		return o.md5sum, nil
	}
	in, err := os.Open(o.path)
	if err != nil {
		fs.Stats.Error()
		fs.Log(o, "Failed to open: %s", err)
		return "", err
	}
	hash := md5.New()
	_, err = io.Copy(hash, in)
	closeErr := in.Close()
	if err != nil {
		fs.Stats.Error()
		fs.Log(o, "Failed to read: %s", err)
		return "", err
	}
	if closeErr != nil {
		fs.Stats.Error()
		fs.Log(o, "Failed to close: %s", closeErr)
		return "", closeErr
	}
	o.md5sum = hex.EncodeToString(hash.Sum(nil))
	return o.md5sum, nil
}

// Size returns the size of an object in bytes
func (o *FsObjectLocal) Size() int64 {
	return o.info.Size()
}

// ModTime returns the modification time of the object
func (o *FsObjectLocal) ModTime() time.Time {
	return o.info.ModTime()
}

// Sets the modification time of the local fs object
func (o *FsObjectLocal) SetModTime(modTime time.Time) {
	err := os.Chtimes(o.path, modTime, modTime)
	if err != nil {
		fs.Debug(o, "Failed to set mtime on file: %s", err)
		return
	}
	// Re-read metadata
	err = o.lstat()
	if err != nil {
		fs.Debug(o, "Failed to stat: %s", err)
		return
	}
}

// Is this object storable
func (o *FsObjectLocal) Storable() bool {
	mode := o.info.Mode()
	if mode&(os.ModeSymlink|os.ModeNamedPipe|os.ModeSocket|os.ModeDevice) != 0 {
		fs.Debug(o, "Can't transfer non file/directory")
		return false
	} else if mode&os.ModeDir != 0 {
		// fs.Debug(o, "Skipping directory")
		return false
	}
	return true
}

// localOpenFile wraps an io.ReadCloser and updates the md5sum of the
// object that is read
type localOpenFile struct {
	o    *FsObjectLocal // object that is open
	in   io.ReadCloser  // handle we are wrapping
	hash hash.Hash      // currently accumulating MD5
}

// Read bytes from the object - see io.Reader
func (file *localOpenFile) Read(p []byte) (n int, err error) {
	n, err = file.in.Read(p)
	if n > 0 {
		// Hash routines never return an error
		_, _ = file.hash.Write(p[:n])
	}
	return
}

// Close the object and update the md5sum
func (file *localOpenFile) Close() (err error) {
	err = file.in.Close()
	if err == nil {
		file.o.md5sum = hex.EncodeToString(file.hash.Sum(nil))
	} else {
		file.o.md5sum = ""
	}
	return err
}

// Open an object for read
func (o *FsObjectLocal) Open() (in io.ReadCloser, err error) {
	in, err = os.Open(o.path)
	if err != nil {
		return
	}
	// Update the md5sum as we go along
	in = &localOpenFile{
		o:    o,
		in:   in,
		hash: md5.New(),
	}
	return
}

// Update the object from in with modTime and size
func (o *FsObjectLocal) Update(in io.Reader, modTime time.Time, size int64) error {
	dir := path.Dir(o.path)
	err := os.MkdirAll(dir, 0770)
	if err != nil {
		return err
	}

	out, err := os.Create(o.path)
	if err != nil {
		return err
	}

	// Calculate the md5sum of the object we are reading as we go along
	hash := md5.New()
	in = io.TeeReader(in, hash)

	_, err = io.Copy(out, in)
	outErr := out.Close()
	if err != nil {
		return err
	}
	if outErr != nil {
		return outErr
	}

	// All successful so update the md5sum
	o.md5sum = hex.EncodeToString(hash.Sum(nil))

	// Set the mtime
	o.SetModTime(modTime)

	// ReRead info now that we have finished
	return o.lstat()
}

// Stat a FsObject into info
func (o *FsObjectLocal) lstat() error {
	info, err := os.Lstat(o.path)
	o.info = info
	return err
}

// Remove an object
func (o *FsObjectLocal) Remove() error {
	return os.Remove(o.path)
}

// Check the interfaces are satisfied
var _ fs.Fs = &FsLocal{}
var _ fs.Purger = &FsLocal{}
var _ fs.Object = &FsObjectLocal{}
<|endoftext|>


<commit_before>// full_test
package Testing

import (
	"Graphics"
	"Window"
	"fmt"
	"math/rand"
	"testing"
	//"time"
)

func random(min, max int) int {
	//srand.Seed(time.Now().Unix())
	return rand.Intn(max-min) + min
}

func Test_Graphics(t *testing.T) {
	w := Window.NewWindowedWindow("test", 800, 600)

	w.Open()

	img, e := Graphics.NewImage("test.png")
	s1 := Graphics.NewBasicSprite(img)
	img2, e := Graphics.NewImage("smiley.png")
	sprites := []*Graphics.Sprite{}

	for i := 0; i < 500; i += 1 {
		x := random(1, 800)
		y := random(1, 600)

		fmt.Println("x:", x)
		fmt.Println("y:", y)

		s := Graphics.NewBasicSprite(img2)
		s.SetLocation(float32(x), float32(y))

		scale := random(2, 6)
		fmt.Println("scale", float32(scale)/10.0)
		s.Scale(float32(scale)/10.0, float32(scale)/10.0)
		sprites = append(sprites, &s)
	}

	s2 := Graphics.NewBasicSprite(img2)
	s2.SetLocation(400, 400)

	for w.IsOpen() == true {
		w.Clear()
		s1.Move(.1, .2)
		s2.Move(-.1, -.2)
		s2.Rotate(20.0)

		w.Draw(s1)
		w.Draw(s2)

		for _, mys := range sprites {
			dx := random(0, 20) / 10
			dy := random(0, 20) / 10

			mys.Move(float32(dx), float32(dy))
			mys.Rotate(float32(dx))

			w.Draw(mys)
		}

		w.Refresh()
	}

	if e != nil {
		t.Error(e.Error())
	}

}
<commit_msg>added new test for vbo<commit_after>// full_test
package Testing

import (
	"Graphics"
	"Window"
	"fmt"
	gl "github.com/chsc/gogl/gl21"
	"math/rand"
	"testing"
	"time"
)

func random(min, max int) int {
	//srand.Seed(time.Now().Unix())
	return rand.Intn(max-min) + min
}

func Test_VBO(t *testing.T) {
	w := Window.NewWindowedWindow("test", 800, 600)

	w.Open()

	w.Clear()
	w.Refresh()

	ID := make([]gl.Uint, 1)
	data := make([]float32, 6)
	data[0] = 50
	data[1] = 50
	data[2] = 100
	data[3] = 50
	data[4] = 74
	data[5] = 100
	gl.GenBuffers(1, &ID[0])
	gl.BindBuffer(gl.ARRAY_BUFFER, ID[0])
	gl.BufferData(gl.ARRAY_BUFFER, gl.Sizeiptr(4*len(data)), gl.Pointer(&data), gl.STATIC_DRAW)

	gl.Clear(gl.COLOR_BUFFER_BIT)
	gl.Color3f(0.0, 0.0, 0.0)
	gl.BindBuffer(gl.ARRAY_BUFFER, ID[0])
	// 4 is size of our float, but 2 objects each
	gl.VertexPointer(2, gl.FLOAT, 2*4, gl.Offset(nil, 0))
	gl.DrawArrays(gl.POLYGON, 0, 3)
	gl.Flush()
	w.Refresh()
	time.Sleep(3 * 10e8)
}

func Test_Graphics(t *testing.T) {
	w := Window.NewWindowedWindow("test", 800, 600)

	w.Open()

	img, e := Graphics.NewImage("test.png")
	s1 := Graphics.NewBasicSprite(img)
	img2, e := Graphics.NewImage("smiley.png")
	sprites := []*Graphics.Sprite{}

	for i := 0; i < 500; i += 1 {
		x := random(1, 800)
		y := random(1, 600)

		fmt.Println("x:", x)
		fmt.Println("y:", y)

		s := Graphics.NewBasicSprite(img2)
		s.SetLocation(float32(x), float32(y))

		scale := random(2, 6)
		fmt.Println("scale", float32(scale)/10.0)
		s.Scale(float32(scale)/10.0, float32(scale)/10.0)
		sprites = append(sprites, &s)
	}

	s2 := Graphics.NewBasicSprite(img2)
	s2.SetLocation(400, 400)

	for w.IsOpen() == true {
		w.Clear()
		s1.Move(.1, .2)
		s2.Move(-.1, -.2)
		s2.Rotate(20.0)

		w.Draw(s1)
		w.Draw(s2)

		for _, mys := range sprites {
			dx := random(0, 20) / 10
			dy := random(0, 20) / 10

			mys.Move(float32(dx), float32(dy))
			mys.Rotate(float32(dx))

			w.Draw(mys)
		}

		w.Refresh()
	}

	if e != nil {
		t.Error(e.Error())
	}

}
<|endoftext|>


<commit_before>package gocube

import (
	"sync"
)

// A EdgesGoal represents an abstract goal state for a depth-first search of the
// cube's edges.
type EdgesGoal interface {
	IsGoal(c CubieEdges) bool
}

// A EdgesPruner is used as a lower-bound heuristic for a depth-first search of
// the cube's edges.
type EdgesPruner interface {
	MinMoves(c CubieEdges) int
}

// An EOLineGoal is satisfied when a CubieEdges has the edge-orientation line as
// defined by the ZZ method.
type EOLineGoal struct{}

func (_ EOLineGoal) IsGoal(c CubieEdges) bool {
	// Make sure the edges are oriented.
	for _, p := range c {
		if p.Flip {
			return false
		}
	}

	// Make sure the line edges are solved.
	return c[2].Piece == 2 && c[8].Piece == 8
}

// An OrientEdgesGoal is satisfied when a CubieEdges has no flipped edges.
type OrientEdgesGoal struct{}

// IsGoal returns true if no edges are flipped.
func (_ OrientEdgesGoal) IsGoal(edges CubieEdges) bool {
	for _, x := range edges {
		if x.Flip {
			return false
		}
	}
	return true
}

// An OrientEdgesPruner stores the number of moves required to solve every EO
// configuration.
type OrientEdgesPruner [0x800]int

// MakeOrientEdgesPruner uses breadth-first search to generate an
// OrientEdgesHeuristic.
func MakeOrientEdgesPruner(moves []Move) *OrientEdgesPruner {
	var res OrientEdgesPruner

	for i := 0; i < 0x800; i++ {
		res[i] = -1
	}

	// Perform a very basic breadth-first search.
	nodes := []edgesSearchNode{edgesSearchNode{SolvedCubieEdges(), 0}}
	for len(nodes) > 0 {
		node := nodes[0]
		nodes = nodes[1:]
		idx := encodeEO(node.State)

		if res[idx] >= 0 {
			// Node was already visited
			continue
		}

		// Expand the node
		res[idx] = node.Depth
		for _, move := range moves {
			state := node.State
			state.Move(move)
			nodes = append(nodes, edgesSearchNode{state, node.Depth + 1})
		}
	}

	return &res
}

// MinMoves returns the number of moves required to orient all the edges.
func (o *OrientEdgesPruner) MinMoves(e CubieEdges) int {
	return o[encodeEO(e)]
}

// A SolveEdgesGoal is satisfied when a CubieEdges is completely solved.
type SolveEdgesGoal struct{}

// IsGoal returns edges.Solved().
func (_ SolveEdgesGoal) IsGoal(edges CubieEdges) bool {
	return edges.Solved()
}

// Search starts a search using the receiver as the starting state.
// If the specified EdgesPruner is nil, no pruning will be performed.
// The depth argument specifies the maximum depth for the search.
// The branch argument specifies how many levels of the search to parallelize.
func (c *CubieEdges) Search(g EdgesGoal, p EdgesPruner, moves []Move,
	depth, branch int) Search {
	res := &edgesSearch{newSimpleSearch(moves), g, p}
	go func(st CubieEdges) {
		prefix := make([]Move, 0, depth)
		searchEdgesBranch(st, res, depth, branch, prefix)
		close(res.channel)
	}(*c)
	return res
}

func searchEdges(st CubieEdges, s *edgesSearch, depth int, prefix []Move) {
	// If we can't search any further, check if it's the goal.
	if depth == 0 {
		if s.goal.IsGoal(st) {
			// We must make a copy of the prefix before sending it as a
			// solution, since it may be modified after we return.
			solution := make([]Move, len(prefix))
			copy(solution, prefix)
			s.channel <- solution
		}
		return
	}

	// Prune the state
	if s.prune(st) > depth {
		return
	}

	// Apply each move and recurse.
	for _, move := range s.moves {
		if depth > 5 && s.cancelled() {
			return
		}
		newState := st
		newState.Move(move)
		searchEdges(newState, s, depth-1, append(prefix, move))
	}
}

func searchEdgesBranch(st CubieEdges, s *edgesSearch, depth, branch int,
	prefix []Move) {
	// If we shouldn't branch, do a regular search.
	if branch == 0 || depth == 0 {
		searchEdges(st, s, depth, prefix)
		return
	}

	// Prune the state
	if s.prune(st) > depth {
		return
	}

	// Run each search on a different goroutine
	wg := sync.WaitGroup{}
	for _, move := range s.moves {
		wg.Add(1)
		go func(m Move, newState CubieEdges) {
			// Apply the move
			newState.Move(m)

			// Create the new prefix by copying the old one.
			pref := make([]Move, len(prefix)+1, len(prefix)+depth)
			copy(pref, prefix)
			pref[len(prefix)] = m

			// Branch out and search.
			searchEdgesBranch(newState, s, depth-1, branch-1, pref)

			wg.Done()
		}(move, st)
	}
	wg.Wait()
}

type edgesSearch struct {
	*simpleSearch
	goal   EdgesGoal
	pruner EdgesPruner
}

func (c *edgesSearch) prune(state CubieEdges) int {
	if c.pruner == nil {
		return 0
	}
	return c.pruner.MinMoves(state)
}

type edgesSearchNode struct {
	State CubieEdges
	Depth int
}

func encodeEO(e CubieEdges) int {
	res := 0
	for i := 0; i < 11; i++ {
		if e[i].Flip {
			res |= (1 << uint(i))
		}
	}
	return res
}
<commit_msg>fixed article adjective<commit_after>package gocube

import (
	"sync"
)

// An EdgesGoal represents an abstract goal state for a depth-first search of
// the cube's edges.
type EdgesGoal interface {
	IsGoal(c CubieEdges) bool
}

// An EdgesPruner is used as a lower-bound heuristic for a depth-first search of
// the cube's edges.
type EdgesPruner interface {
	MinMoves(c CubieEdges) int
}

// An EOLineGoal is satisfied when a CubieEdges has the edge-orientation line as
// defined by the ZZ method.
type EOLineGoal struct{}

func (_ EOLineGoal) IsGoal(c CubieEdges) bool {
	// Make sure the edges are oriented.
	for _, p := range c {
		if p.Flip {
			return false
		}
	}

	// Make sure the line edges are solved.
	return c[2].Piece == 2 && c[8].Piece == 8
}

// An OrientEdgesGoal is satisfied when a CubieEdges has no flipped edges.
type OrientEdgesGoal struct{}

// IsGoal returns true if no edges are flipped.
func (_ OrientEdgesGoal) IsGoal(edges CubieEdges) bool {
	for _, x := range edges {
		if x.Flip {
			return false
		}
	}
	return true
}

// An OrientEdgesPruner stores the number of moves required to solve every EO
// configuration.
type OrientEdgesPruner [0x800]int

// MakeOrientEdgesPruner uses breadth-first search to generate an
// OrientEdgesHeuristic.
func MakeOrientEdgesPruner(moves []Move) *OrientEdgesPruner {
	var res OrientEdgesPruner

	for i := 0; i < 0x800; i++ {
		res[i] = -1
	}

	// Perform a very basic breadth-first search.
	nodes := []edgesSearchNode{edgesSearchNode{SolvedCubieEdges(), 0}}
	for len(nodes) > 0 {
		node := nodes[0]
		nodes = nodes[1:]
		idx := encodeEO(node.State)

		if res[idx] >= 0 {
			// Node was already visited
			continue
		}

		// Expand the node
		res[idx] = node.Depth
		for _, move := range moves {
			state := node.State
			state.Move(move)
			nodes = append(nodes, edgesSearchNode{state, node.Depth + 1})
		}
	}

	return &res
}

// MinMoves returns the number of moves required to orient all the edges.
func (o *OrientEdgesPruner) MinMoves(e CubieEdges) int {
	return o[encodeEO(e)]
}

// A SolveEdgesGoal is satisfied when a CubieEdges is completely solved.
type SolveEdgesGoal struct{}

// IsGoal returns edges.Solved().
func (_ SolveEdgesGoal) IsGoal(edges CubieEdges) bool {
	return edges.Solved()
}

// Search starts a search using the receiver as the starting state.
// If the specified EdgesPruner is nil, no pruning will be performed.
// The depth argument specifies the maximum depth for the search.
// The branch argument specifies how many levels of the search to parallelize.
func (c *CubieEdges) Search(g EdgesGoal, p EdgesPruner, moves []Move,
	depth, branch int) Search {
	res := &edgesSearch{newSimpleSearch(moves), g, p}
	go func(st CubieEdges) {
		prefix := make([]Move, 0, depth)
		searchEdgesBranch(st, res, depth, branch, prefix)
		close(res.channel)
	}(*c)
	return res
}

func searchEdges(st CubieEdges, s *edgesSearch, depth int, prefix []Move) {
	// If we can't search any further, check if it's the goal.
	if depth == 0 {
		if s.goal.IsGoal(st) {
			// We must make a copy of the prefix before sending it as a
			// solution, since it may be modified after we return.
			solution := make([]Move, len(prefix))
			copy(solution, prefix)
			s.channel <- solution
		}
		return
	}

	// Prune the state
	if s.prune(st) > depth {
		return
	}

	// Apply each move and recurse.
	for _, move := range s.moves {
		if depth > 5 && s.cancelled() {
			return
		}
		newState := st
		newState.Move(move)
		searchEdges(newState, s, depth-1, append(prefix, move))
	}
}

func searchEdgesBranch(st CubieEdges, s *edgesSearch, depth, branch int,
	prefix []Move) {
	// If we shouldn't branch, do a regular search.
	if branch == 0 || depth == 0 {
		searchEdges(st, s, depth, prefix)
		return
	}

	// Prune the state
	if s.prune(st) > depth {
		return
	}

	// Run each search on a different goroutine
	wg := sync.WaitGroup{}
	for _, move := range s.moves {
		wg.Add(1)
		go func(m Move, newState CubieEdges) {
			// Apply the move
			newState.Move(m)

			// Create the new prefix by copying the old one.
			pref := make([]Move, len(prefix)+1, len(prefix)+depth)
			copy(pref, prefix)
			pref[len(prefix)] = m

			// Branch out and search.
			searchEdgesBranch(newState, s, depth-1, branch-1, pref)

			wg.Done()
		}(move, st)
	}
	wg.Wait()
}

type edgesSearch struct {
	*simpleSearch
	goal   EdgesGoal
	pruner EdgesPruner
}

func (c *edgesSearch) prune(state CubieEdges) int {
	if c.pruner == nil {
		return 0
	}
	return c.pruner.MinMoves(state)
}

type edgesSearchNode struct {
	State CubieEdges
	Depth int
}

func encodeEO(e CubieEdges) int {
	res := 0
	for i := 0; i < 11; i++ {
		if e[i].Flip {
			res |= (1 << uint(i))
		}
	}
	return res
}
<|endoftext|>