<commit_before>package device

import (
	"bufio"
	"crypto/rand"
	"encoding/hex"
	"fmt"
	"io/ioutil"
	"os"
	"strconv"
	"strings"

	"github.com/lxc/lxd/shared"
)

// NetworkSysctlGet retrieves the value of a sysctl file in /proc/sys/net.
func NetworkSysctlGet(path string) (string, error) {
	// Read the current content
	content, err := ioutil.ReadFile(fmt.Sprintf("/proc/sys/net/%s", path))
	if err != nil {
		return "", err
	}

	return string(content), nil
}

// NetworkSysctlSet writes a value to a sysctl file in /proc/sys/net.
func NetworkSysctlSet(path string, value string) error {
	// Get current value
	current, err := NetworkSysctlGet(path)
	if err == nil && current == value {
		// Nothing to update
		return nil
	}

	return ioutil.WriteFile(fmt.Sprintf("/proc/sys/net/%s", path), []byte(value), 0)
}

// NetworkGetDevMTU retrieves the current MTU setting for a named network device.
func NetworkGetDevMTU(devName string) (uint64, error) {
	content, err := ioutil.ReadFile(fmt.Sprintf("/sys/class/net/%s/mtu", devName))
	if err != nil {
		return 0, err
	}

	// Parse value
	mtu, err := strconv.ParseUint(strings.TrimSpace(string(content)), 10, 32)
	if err != nil {
		return 0, err
	}

	return mtu, nil
}

// NetworkSetDevMTU sets the MTU setting for a named network device if different from current.
func NetworkSetDevMTU(devName string, mtu uint64) error {
	curMTU, err := NetworkGetDevMTU(devName)
	if err != nil {
		return err
	}

	// Only try and change the MTU if the requested mac is different to current one.
	if curMTU != mtu {
		_, err := shared.RunCommand("ip", "link", "set", "dev", devName, "mtu", fmt.Sprintf("%d", mtu))
		if err != nil {
			return err
		}
	}

	return nil
}

// NetworkGetDevMAC retrieves the current MAC setting for a named network device.
func NetworkGetDevMAC(devName string) (string, error) {
	content, err := ioutil.ReadFile(fmt.Sprintf("/sys/class/net/%s/address", devName))
	if err != nil {
		return "", err
	}

	return strings.TrimSpace(fmt.Sprintf("%s", content)), nil
}

// NetworkSetDevMAC sets the MAC setting for a named network device if different from current.
func NetworkSetDevMAC(devName string, mac string) error {
	curMac, err := NetworkGetDevMAC(devName)
	if err != nil {
		return err
	}

	// Only try and change the MAC if the requested mac is different to current one.
	if curMac != mac {
		_, err := shared.RunCommand("ip", "link", "set", "dev", devName, "address", mac)
		if err != nil {
			return err
		}
	}

	return nil
}

// NetworkGetHostDevice figures out whether there is an existing interface for the supplied
// parent device and VLAN ID and returns it. Otherwise just returns the parent device name.
func NetworkGetHostDevice(parent string, vlan string) string {
	// If no VLAN, just use the raw device
	if vlan == "" {
		return parent
	}

	// If no VLANs are configured, use the default pattern
	defaultVlan := fmt.Sprintf("%s.%s", parent, vlan)
	if !shared.PathExists("/proc/net/vlan/config") {
		return defaultVlan
	}

	// Look for an existing VLAN
	f, err := os.Open("/proc/net/vlan/config")
	if err != nil {
		return defaultVlan
	}
	defer f.Close()

	scanner := bufio.NewScanner(f)
	for scanner.Scan() {
		// Only grab the lines we're interested in
		s := strings.Split(scanner.Text(), "|")
		if len(s) != 3 {
			continue
		}

		vlanIface := strings.TrimSpace(s[0])
		vlanID := strings.TrimSpace(s[1])
		vlanParent := strings.TrimSpace(s[2])

		if vlanParent == parent && vlanID == vlan {
			return vlanIface
		}
	}

	// Return the default pattern
	return defaultVlan
}

// NetworkRemoveInterface removes a network interface by name.
func NetworkRemoveInterface(nic string) error {
	_, err := shared.RunCommand("ip", "link", "del", "dev", nic)
	return err
}

// NetworkCreateVlanDeviceIfNeeded creates a VLAN device if doesn't already exist.
func NetworkCreateVlanDeviceIfNeeded(parent string, hostName string, vlan string) (bool, error) {
	if vlan != "" {
		if !shared.PathExists(fmt.Sprintf("/sys/class/net/%s", hostName)) {
			_, err := shared.RunCommand("ip", "link", "add", "link", parent, "name", hostName, "up", "type", "vlan", "id", vlan)
			if err != nil {
				return false, err
			}

			// Attempt to disable IPv6 router advertisement acceptance
			NetworkSysctlSet(fmt.Sprintf("ipv6/conf/%s/accept_ra", hostName), "0")

			// We created a new vlan interface, return true
			return true, nil
		}
	}

	return false, nil
}

// networkSnapshotPhysicalNic records properties of the NIC to volatile so they can be restored later.
func networkSnapshotPhysicalNic(hostName string, volatile map[string]string) error {
	// Store current MTU for restoration on detach.
	mtu, err := NetworkGetDevMTU(hostName)
	if err != nil {
		return err
	}
	volatile["last_state.mtu"] = fmt.Sprintf("%d", mtu)

	// Store current MAC for restoration on detach
	mac, err := NetworkGetDevMAC(hostName)
	if err != nil {
		return err
	}
	volatile["last_state.hwaddr"] = mac
	return nil
}

// networkRestorePhysicalNic restores NIC properties from volatile to what they were before it was attached.
func networkRestorePhysicalNic(hostName string, volatile map[string]string) error {
	// If we created the "physical" device and then it should be removed.
	if shared.IsTrue(volatile["last_state.created"]) {
		return NetworkRemoveInterface(hostName)
	}

	// Bring the interface down, as this is sometimes needed to change settings on the nic.
	_, err := shared.RunCommand("ip", "link", "set", "dev", hostName, "down")
	if err != nil {
		return fmt.Errorf("Failed to bring down \"%s\": %v", hostName, err)
	}

	// If MTU value is specified then there is an original MTU that needs restoring.
	if volatile["last_state.mtu"] != "" {
		mtuInt, err := strconv.ParseUint(volatile["last_state.mtu"], 10, 32)
		if err != nil {
			return fmt.Errorf("Failed to convert mtu for \"%s\" mtu \"%s\": %v", hostName, volatile["last_state.mtu"], err)
		}

		err = NetworkSetDevMTU(hostName, mtuInt)
		if err != nil {
			return fmt.Errorf("Failed to restore physical dev \"%s\" mtu to \"%d\": %v", hostName, mtuInt, err)
		}
	}

	// If MAC value is specified then there is an original MAC that needs restoring.
	if volatile["last_state.hwaddr"] != "" {
		err := NetworkSetDevMAC(hostName, volatile["last_state.hwaddr"])
		if err != nil {
			return fmt.Errorf("Failed to restore physical dev \"%s\" mac to \"%s\": %v", hostName, volatile["last_state.hwaddr"], err)
		}
	}

	return nil
}

// NetworkRandomDevName returns a random device name with prefix.
// If the random string combined with the prefix exceeds 13 characters then empty string is returned.
// This is to ensure we support buggy dhclient applications: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=858580
func NetworkRandomDevName(prefix string) string {
	// Return a new random veth device name
	randBytes := make([]byte, 4)
	rand.Read(randBytes)
	iface := prefix + hex.EncodeToString(randBytes)
	if len(iface) > 13 {
		return ""
	}

	return iface
}

// NetworkAttachInterface attaches an interface to a bridge.
func NetworkAttachInterface(netName string, devName string) error {
	if shared.PathExists(fmt.Sprintf("/sys/class/net/%s/bridge", netName)) {
		_, err := shared.RunCommand("ip", "link", "set", "dev", devName, "master", netName)
		if err != nil {
			return err
		}
	} else {
		_, err := shared.RunCommand("ovs-vsctl", "port-to-br", devName)
		if err != nil {
			_, err := shared.RunCommand("ovs-vsctl", "add-port", netName, devName)
			if err != nil {
				return err
			}
		}
	}

	return nil
}
<commit_msg>device/utils: Brings VLAN parent interface up<commit_after>package device

import (
	"bufio"
	"crypto/rand"
	"encoding/hex"
	"fmt"
	"io/ioutil"
	"os"
	"strconv"
	"strings"

	"github.com/lxc/lxd/shared"
)

// NetworkSysctlGet retrieves the value of a sysctl file in /proc/sys/net.
func NetworkSysctlGet(path string) (string, error) {
	// Read the current content
	content, err := ioutil.ReadFile(fmt.Sprintf("/proc/sys/net/%s", path))
	if err != nil {
		return "", err
	}

	return string(content), nil
}

// NetworkSysctlSet writes a value to a sysctl file in /proc/sys/net.
func NetworkSysctlSet(path string, value string) error {
	// Get current value
	current, err := NetworkSysctlGet(path)
	if err == nil && current == value {
		// Nothing to update
		return nil
	}

	return ioutil.WriteFile(fmt.Sprintf("/proc/sys/net/%s", path), []byte(value), 0)
}

// NetworkGetDevMTU retrieves the current MTU setting for a named network device.
func NetworkGetDevMTU(devName string) (uint64, error) {
	content, err := ioutil.ReadFile(fmt.Sprintf("/sys/class/net/%s/mtu", devName))
	if err != nil {
		return 0, err
	}

	// Parse value
	mtu, err := strconv.ParseUint(strings.TrimSpace(string(content)), 10, 32)
	if err != nil {
		return 0, err
	}

	return mtu, nil
}

// NetworkSetDevMTU sets the MTU setting for a named network device if different from current.
func NetworkSetDevMTU(devName string, mtu uint64) error {
	curMTU, err := NetworkGetDevMTU(devName)
	if err != nil {
		return err
	}

	// Only try and change the MTU if the requested mac is different to current one.
	if curMTU != mtu {
		_, err := shared.RunCommand("ip", "link", "set", "dev", devName, "mtu", fmt.Sprintf("%d", mtu))
		if err != nil {
			return err
		}
	}

	return nil
}

// NetworkGetDevMAC retrieves the current MAC setting for a named network device.
func NetworkGetDevMAC(devName string) (string, error) {
	content, err := ioutil.ReadFile(fmt.Sprintf("/sys/class/net/%s/address", devName))
	if err != nil {
		return "", err
	}

	return strings.TrimSpace(fmt.Sprintf("%s", content)), nil
}

// NetworkSetDevMAC sets the MAC setting for a named network device if different from current.
func NetworkSetDevMAC(devName string, mac string) error {
	curMac, err := NetworkGetDevMAC(devName)
	if err != nil {
		return err
	}

	// Only try and change the MAC if the requested mac is different to current one.
	if curMac != mac {
		_, err := shared.RunCommand("ip", "link", "set", "dev", devName, "address", mac)
		if err != nil {
			return err
		}
	}

	return nil
}

// NetworkGetHostDevice figures out whether there is an existing interface for the supplied
// parent device and VLAN ID and returns it. Otherwise just returns the parent device name.
func NetworkGetHostDevice(parent string, vlan string) string {
	// If no VLAN, just use the raw device
	if vlan == "" {
		return parent
	}

	// If no VLANs are configured, use the default pattern
	defaultVlan := fmt.Sprintf("%s.%s", parent, vlan)
	if !shared.PathExists("/proc/net/vlan/config") {
		return defaultVlan
	}

	// Look for an existing VLAN
	f, err := os.Open("/proc/net/vlan/config")
	if err != nil {
		return defaultVlan
	}
	defer f.Close()

	scanner := bufio.NewScanner(f)
	for scanner.Scan() {
		// Only grab the lines we're interested in
		s := strings.Split(scanner.Text(), "|")
		if len(s) != 3 {
			continue
		}

		vlanIface := strings.TrimSpace(s[0])
		vlanID := strings.TrimSpace(s[1])
		vlanParent := strings.TrimSpace(s[2])

		if vlanParent == parent && vlanID == vlan {
			return vlanIface
		}
	}

	// Return the default pattern
	return defaultVlan
}

// NetworkRemoveInterface removes a network interface by name.
func NetworkRemoveInterface(nic string) error {
	_, err := shared.RunCommand("ip", "link", "del", "dev", nic)
	return err
}

// NetworkCreateVlanDeviceIfNeeded creates a VLAN device if doesn't already exist.
func NetworkCreateVlanDeviceIfNeeded(parent string, vlanDevice string, vlanID string) (bool, error) {
	if vlanID != "" {
		if !shared.PathExists(fmt.Sprintf("/sys/class/net/%s", vlanDevice)) {
			// Bring the parent interface up so we can add a vlan to it.
			_, err := shared.RunCommand("ip", "link", "set", "dev", parent, "up")
			if err != nil {
				return false, fmt.Errorf("Failed to bring up parent %s: %v", parent, err)
			}

			// Add VLAN interface on top of parent.
			_, err = shared.RunCommand("ip", "link", "add", "link", parent, "name", vlanDevice, "up", "type", "vlan", "id", vlanID)
			if err != nil {
				return false, err
			}

			// Attempt to disable IPv6 router advertisement acceptance
			NetworkSysctlSet(fmt.Sprintf("ipv6/conf/%s/accept_ra", vlanDevice), "0")

			// We created a new vlan interface, return true
			return true, nil
		}
	}

	return false, nil
}

// networkSnapshotPhysicalNic records properties of the NIC to volatile so they can be restored later.
func networkSnapshotPhysicalNic(hostName string, volatile map[string]string) error {
	// Store current MTU for restoration on detach.
	mtu, err := NetworkGetDevMTU(hostName)
	if err != nil {
		return err
	}
	volatile["last_state.mtu"] = fmt.Sprintf("%d", mtu)

	// Store current MAC for restoration on detach
	mac, err := NetworkGetDevMAC(hostName)
	if err != nil {
		return err
	}
	volatile["last_state.hwaddr"] = mac
	return nil
}

// networkRestorePhysicalNic restores NIC properties from volatile to what they were before it was attached.
func networkRestorePhysicalNic(hostName string, volatile map[string]string) error {
	// If we created the "physical" device and then it should be removed.
	if shared.IsTrue(volatile["last_state.created"]) {
		return NetworkRemoveInterface(hostName)
	}

	// Bring the interface down, as this is sometimes needed to change settings on the nic.
	_, err := shared.RunCommand("ip", "link", "set", "dev", hostName, "down")
	if err != nil {
		return fmt.Errorf("Failed to bring down \"%s\": %v", hostName, err)
	}

	// If MTU value is specified then there is an original MTU that needs restoring.
	if volatile["last_state.mtu"] != "" {
		mtuInt, err := strconv.ParseUint(volatile["last_state.mtu"], 10, 32)
		if err != nil {
			return fmt.Errorf("Failed to convert mtu for \"%s\" mtu \"%s\": %v", hostName, volatile["last_state.mtu"], err)
		}

		err = NetworkSetDevMTU(hostName, mtuInt)
		if err != nil {
			return fmt.Errorf("Failed to restore physical dev \"%s\" mtu to \"%d\": %v", hostName, mtuInt, err)
		}
	}

	// If MAC value is specified then there is an original MAC that needs restoring.
	if volatile["last_state.hwaddr"] != "" {
		err := NetworkSetDevMAC(hostName, volatile["last_state.hwaddr"])
		if err != nil {
			return fmt.Errorf("Failed to restore physical dev \"%s\" mac to \"%s\": %v", hostName, volatile["last_state.hwaddr"], err)
		}
	}

	return nil
}

// NetworkRandomDevName returns a random device name with prefix.
// If the random string combined with the prefix exceeds 13 characters then empty string is returned.
// This is to ensure we support buggy dhclient applications: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=858580
func NetworkRandomDevName(prefix string) string {
	// Return a new random veth device name
	randBytes := make([]byte, 4)
	rand.Read(randBytes)
	iface := prefix + hex.EncodeToString(randBytes)
	if len(iface) > 13 {
		return ""
	}

	return iface
}

// NetworkAttachInterface attaches an interface to a bridge.
func NetworkAttachInterface(netName string, devName string) error {
	if shared.PathExists(fmt.Sprintf("/sys/class/net/%s/bridge", netName)) {
		_, err := shared.RunCommand("ip", "link", "set", "dev", devName, "master", netName)
		if err != nil {
			return err
		}
	} else {
		_, err := shared.RunCommand("ovs-vsctl", "port-to-br", devName)
		if err != nil {
			_, err := shared.RunCommand("ovs-vsctl", "add-port", netName, devName)
			if err != nil {
				return err
			}
		}
	}

	return nil
}
<|endoftext|>


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

package f64

import (
	"fmt"
	"math/rand"
	"testing"
)

var dscalTests = []struct {
	alpha float64
	x     []float64
	want  []float64
}{
	{
		alpha: 0,
		x:     []float64{1},
		want:  []float64{0},
	},
	{
		alpha: 1,
		x:     []float64{1},
		want:  []float64{1},
	},
	{
		alpha: 2,
		x:     []float64{1, -2},
		want:  []float64{2, -4},
	},
	{
		alpha: 2,
		x:     []float64{1, -2, 3},
		want:  []float64{2, -4, 6},
	},
	{
		alpha: 2,
		x:     []float64{1, -2, 3, 4},
		want:  []float64{2, -4, 6, 8},
	},
	{
		alpha: 2,
		x:     []float64{1, -2, 3, 4, -5},
		want:  []float64{2, -4, 6, 8, -10},
	},
	{
		alpha: 2,
		x:     []float64{0, 1, -2, 3, 4, -5, 6, -7},
		want:  []float64{0, 2, -4, 6, 8, -10, 12, -14},
	},
	{
		alpha: 2,
		x:     []float64{0, 1, -2, 3, 4, -5, 6, -7, 8},
		want:  []float64{0, 2, -4, 6, 8, -10, 12, -14, 16},
	},
	{
		alpha: 2,
		x:     []float64{0, 1, -2, 3, 4, -5, 6, -7, 8, 9},
		want:  []float64{0, 2, -4, 6, 8, -10, 12, -14, 16, 18},
	},
}

func TestDscalUnitary(t *testing.T) {
	for i, test := range dscalTests {
		const msgGuard = "%v: out-of-bounds write to %v argument\nfront guard: %v\nback guard: %v"

		prefix := fmt.Sprintf("test %v (x*=a)", i)
		x, xFront, xBack := newGuardedVector(test.x, 1)
		ScalUnitary(test.alpha, x)

		if !allNaN(xFront) || !allNaN(xBack) {
			t.Errorf(msgGuard, prefix, "x", xFront, xBack)
		}

		if !equalStrided(test.want, x, 1) {
			t.Errorf("%v: unexpected result:\nwant: %v\ngot: %v", prefix, test.want, x)
		}
	}
}

func TestDscalUnitaryTo(t *testing.T) {
	for i, test := range dscalTests {
		const msgGuard = "%v: out-of-bounds write to %v argument\nfront guard: %v\nback guard: %v"

		// Test dst = alpha * x.
		prefix := fmt.Sprintf("test %v (dst=a*x)", i)
		x, xFront, xBack := newGuardedVector(test.x, 1)
		dst, dstFront, dstBack := newGuardedVector(test.x, 1)
		ScalUnitaryTo(dst, test.alpha, x)

		if !allNaN(xFront) || !allNaN(xBack) {
			t.Errorf(msgGuard, prefix, "x", xFront, xBack)
		}
		if !allNaN(dstFront) || !allNaN(dstBack) {
			t.Errorf(msgGuard, prefix, "dst", dstFront, dstBack)
		}
		if !equalStrided(test.x, x, 1) {
			t.Errorf("%v: modified read-only x argument", prefix)
		}

		if !equalStrided(test.want, dst, 1) {
			t.Errorf("%v: unexpected result:\nwant: %v\ngot: %v", prefix, test.want, dst)
		}

		// Test x = alpha * x.
		prefix = fmt.Sprintf("test %v (x=a*x)", i)
		x, xFront, xBack = newGuardedVector(test.x, 1)
		ScalUnitaryTo(x, test.alpha, x)

		if !allNaN(xFront) || !allNaN(xBack) {
			t.Errorf(msgGuard, prefix, "x", xFront, xBack)
		}

		if !equalStrided(test.want, x, 1) {
			t.Errorf("%v: unexpected result:\nwant: %v\ngot: %v", prefix, test.want, x)
		}
	}
}

func TestDscalInc(t *testing.T) {
	const msgGuard = "%v: out-of-bounds write to %v argument\nfront guard: %v\nback guard: %v"

	for i, test := range dscalTests {
		n := len(test.x)
		for _, incX := range []int{1, 2, 3, 4, 7, 10} {
			prefix := fmt.Sprintf("test %v (x*=a), incX = %v", i, incX)
			x, xFront, xBack := newGuardedVector(test.x, incX)
			ScalInc(test.alpha, x, uintptr(n), uintptr(incX))

			if !allNaN(xFront) || !allNaN(xBack) {
				t.Errorf(msgGuard, prefix, "x", xFront, xBack)
			}
			if nonStridedWrite(x, incX) {
				t.Errorf("%v: modified x argument at non-stride position", prefix)
			}

			if !equalStrided(test.want, x, incX) {
				t.Errorf("%v: unexpected result:\nwant: %v\ngot: %v", prefix, test.want, x)
			}
		}
	}
}

func TestDscalIncTo(t *testing.T) {
	const msgGuard = "%v: out-of-bounds write to %v argument\nfront guard: %v\nback guard: %v"

	for i, test := range dscalTests {
		n := len(test.x)

		for _, incX := range []int{1, 2, 3, 4, 7, 10} {
			// Test x = alpha * x.
			prefix := fmt.Sprintf("test %v (x=a*x), incX = %v", i, incX)
			x, xFront, xBack := newGuardedVector(test.x, incX)
			ScalIncTo(x, uintptr(incX), test.alpha, x, uintptr(n), uintptr(incX))

			if !allNaN(xFront) || !allNaN(xBack) {
				t.Errorf(msgGuard, prefix, "x", xFront, xBack)
			}
			if nonStridedWrite(x, incX) {
				t.Errorf("%v: modified x argument at non-stride position", prefix)
			}
			if !equalStrided(test.want, x, incX) {
				t.Errorf("%v: unexpected result:\nwant: %v\ngot: %v", prefix, test.want, x)
			}

			for _, incDst := range []int{1, 2, 3, 4, 7, 10} {
				// Test dst = alpha * x.
				prefix = fmt.Sprintf("test %v (dst=a*x), incX = %v, incDst = %v", i, incX, incDst)
				x, xFront, xBack = newGuardedVector(test.x, incX)
				dst, dstFront, dstBack := newGuardedVector(test.x, incDst)
				ScalIncTo(dst, uintptr(incDst), test.alpha, x, uintptr(n), uintptr(incX))

				if !allNaN(xFront) || !allNaN(xBack) {
					t.Errorf(msgGuard, prefix, "x", xFront, xBack)
				}
				if !allNaN(dstFront) || !allNaN(dstBack) {
					t.Errorf(msgGuard, prefix, "dst", dstFront, dstBack)
				}
				if nonStridedWrite(x, incX) || !equalStrided(test.x, x, incX) {
					t.Errorf("%v: modified read-only x argument", prefix)
				}
				if nonStridedWrite(dst, incDst) {
					t.Errorf("%v: modified dst argument at non-stride position", prefix)
				}

				if !equalStrided(test.want, dst, incDst) {
					t.Errorf("%v: unexpected result:\nwant: %v\ngot: %v", prefix, test.want, dst)
				}
			}
		}
	}
}

func BenchmarkDscalUnitaryN1(b *testing.B)      { benchmarkDscalUnitary(b, 1) }
func BenchmarkDscalUnitaryN2(b *testing.B)      { benchmarkDscalUnitary(b, 2) }
func BenchmarkDscalUnitaryN3(b *testing.B)      { benchmarkDscalUnitary(b, 3) }
func BenchmarkDscalUnitaryN4(b *testing.B)      { benchmarkDscalUnitary(b, 4) }
func BenchmarkDscalUnitaryN10(b *testing.B)     { benchmarkDscalUnitary(b, 10) }
func BenchmarkDscalUnitaryN100(b *testing.B)    { benchmarkDscalUnitary(b, 100) }
func BenchmarkDscalUnitaryN1000(b *testing.B)   { benchmarkDscalUnitary(b, 1000) }
func BenchmarkDscalUnitaryN10000(b *testing.B)  { benchmarkDscalUnitary(b, 10000) }
func BenchmarkDscalUnitaryN100000(b *testing.B) { benchmarkDscalUnitary(b, 100000) }

func benchmarkDscalUnitary(b *testing.B, n int) {
	x := randomSlice(n, 1)
	b.ResetTimer()
	for i := 0; i < b.N; i += 2 {
		ScalUnitary(2, x)
		ScalUnitary(0.5, x)
	}
	benchSink = x
}

func BenchmarkDscalUnitaryToN1(b *testing.B)      { benchmarkDscalUnitaryTo(b, 1) }
func BenchmarkDscalUnitaryToN2(b *testing.B)      { benchmarkDscalUnitaryTo(b, 2) }
func BenchmarkDscalUnitaryToN3(b *testing.B)      { benchmarkDscalUnitaryTo(b, 3) }
func BenchmarkDscalUnitaryToN4(b *testing.B)      { benchmarkDscalUnitaryTo(b, 4) }
func BenchmarkDscalUnitaryToN10(b *testing.B)     { benchmarkDscalUnitaryTo(b, 10) }
func BenchmarkDscalUnitaryToN100(b *testing.B)    { benchmarkDscalUnitaryTo(b, 100) }
func BenchmarkDscalUnitaryToN1000(b *testing.B)   { benchmarkDscalUnitaryTo(b, 1000) }
func BenchmarkDscalUnitaryToN10000(b *testing.B)  { benchmarkDscalUnitaryTo(b, 10000) }
func BenchmarkDscalUnitaryToN100000(b *testing.B) { benchmarkDscalUnitaryTo(b, 100000) }

func benchmarkDscalUnitaryTo(b *testing.B, n int) {
	x := randomSlice(n, 1)
	dst := randomSlice(n, 1)
	a := rand.Float64()
	b.ResetTimer()
	for i := 0; i < b.N; i++ {
		ScalUnitaryTo(dst, a, x)
	}
	benchSink = dst
}

func BenchmarkDscalUnitaryToXN1(b *testing.B)      { benchmarkDscalUnitaryToX(b, 1) }
func BenchmarkDscalUnitaryToXN2(b *testing.B)      { benchmarkDscalUnitaryToX(b, 2) }
func BenchmarkDscalUnitaryToXN3(b *testing.B)      { benchmarkDscalUnitaryToX(b, 3) }
func BenchmarkDscalUnitaryToXN4(b *testing.B)      { benchmarkDscalUnitaryToX(b, 4) }
func BenchmarkDscalUnitaryToXN10(b *testing.B)     { benchmarkDscalUnitaryToX(b, 10) }
func BenchmarkDscalUnitaryToXN100(b *testing.B)    { benchmarkDscalUnitaryToX(b, 100) }
func BenchmarkDscalUnitaryToXN1000(b *testing.B)   { benchmarkDscalUnitaryToX(b, 1000) }
func BenchmarkDscalUnitaryToXN10000(b *testing.B)  { benchmarkDscalUnitaryToX(b, 10000) }
func BenchmarkDscalUnitaryToXN100000(b *testing.B) { benchmarkDscalUnitaryToX(b, 100000) }

func benchmarkDscalUnitaryToX(b *testing.B, n int) {
	x := randomSlice(n, 1)
	b.ResetTimer()
	for i := 0; i < b.N; i += 2 {
		ScalUnitaryTo(x, 2, x)
		ScalUnitaryTo(x, 0.5, x)
	}
	benchSink = x
}

func BenchmarkDscalIncN1Inc1(b *testing.B) { benchmarkDscalInc(b, 1, 1) }

func BenchmarkDscalIncN2Inc1(b *testing.B)  { benchmarkDscalInc(b, 2, 1) }
func BenchmarkDscalIncN2Inc2(b *testing.B)  { benchmarkDscalInc(b, 2, 2) }
func BenchmarkDscalIncN2Inc4(b *testing.B)  { benchmarkDscalInc(b, 2, 4) }
func BenchmarkDscalIncN2Inc10(b *testing.B) { benchmarkDscalInc(b, 2, 10) }

func BenchmarkDscalIncN3Inc1(b *testing.B)  { benchmarkDscalInc(b, 3, 1) }
func BenchmarkDscalIncN3Inc2(b *testing.B)  { benchmarkDscalInc(b, 3, 2) }
func BenchmarkDscalIncN3Inc4(b *testing.B)  { benchmarkDscalInc(b, 3, 4) }
func BenchmarkDscalIncN3Inc10(b *testing.B) { benchmarkDscalInc(b, 3, 10) }

func BenchmarkDscalIncN4Inc1(b *testing.B)  { benchmarkDscalInc(b, 4, 1) }
func BenchmarkDscalIncN4Inc2(b *testing.B)  { benchmarkDscalInc(b, 4, 2) }
func BenchmarkDscalIncN4Inc4(b *testing.B)  { benchmarkDscalInc(b, 4, 4) }
func BenchmarkDscalIncN4Inc10(b *testing.B) { benchmarkDscalInc(b, 4, 10) }

func BenchmarkDscalIncN10Inc1(b *testing.B)  { benchmarkDscalInc(b, 10, 1) }
func BenchmarkDscalIncN10Inc2(b *testing.B)  { benchmarkDscalInc(b, 10, 2) }
func BenchmarkDscalIncN10Inc4(b *testing.B)  { benchmarkDscalInc(b, 10, 4) }
func BenchmarkDscalIncN10Inc10(b *testing.B) { benchmarkDscalInc(b, 10, 10) }

func BenchmarkDscalIncN1000Inc1(b *testing.B)  { benchmarkDscalInc(b, 1000, 1) }
func BenchmarkDscalIncN1000Inc2(b *testing.B)  { benchmarkDscalInc(b, 1000, 2) }
func BenchmarkDscalIncN1000Inc4(b *testing.B)  { benchmarkDscalInc(b, 1000, 4) }
func BenchmarkDscalIncN1000Inc10(b *testing.B) { benchmarkDscalInc(b, 1000, 10) }

func BenchmarkDscalIncN100000Inc1(b *testing.B)  { benchmarkDscalInc(b, 100000, 1) }
func BenchmarkDscalIncN100000Inc2(b *testing.B)  { benchmarkDscalInc(b, 100000, 2) }
func BenchmarkDscalIncN100000Inc4(b *testing.B)  { benchmarkDscalInc(b, 100000, 4) }
func BenchmarkDscalIncN100000Inc10(b *testing.B) { benchmarkDscalInc(b, 100000, 10) }

func benchmarkDscalInc(b *testing.B, n, inc int) {
	x := randomSlice(n, inc)
	b.ResetTimer()
	for i := 0; i < b.N; i += 2 {
		ScalInc(2, x, uintptr(n), uintptr(inc))
		ScalInc(0.5, x, uintptr(n), uintptr(inc))
	}
	benchSink = x
}

func BenchmarkDscalIncToN1Inc1(b *testing.B) { benchmarkDscalIncTo(b, 1, 1) }

func BenchmarkDscalIncToN2Inc1(b *testing.B)  { benchmarkDscalIncTo(b, 2, 1) }
func BenchmarkDscalIncToN2Inc2(b *testing.B)  { benchmarkDscalIncTo(b, 2, 2) }
func BenchmarkDscalIncToN2Inc4(b *testing.B)  { benchmarkDscalIncTo(b, 2, 4) }
func BenchmarkDscalIncToN2Inc10(b *testing.B) { benchmarkDscalIncTo(b, 2, 10) }

func BenchmarkDscalIncToN3Inc1(b *testing.B)  { benchmarkDscalIncTo(b, 3, 1) }
func BenchmarkDscalIncToN3Inc2(b *testing.B)  { benchmarkDscalIncTo(b, 3, 2) }
func BenchmarkDscalIncToN3Inc4(b *testing.B)  { benchmarkDscalIncTo(b, 3, 4) }
func BenchmarkDscalIncToN3Inc10(b *testing.B) { benchmarkDscalIncTo(b, 3, 10) }

func BenchmarkDscalIncToN4Inc1(b *testing.B)  { benchmarkDscalIncTo(b, 4, 1) }
func BenchmarkDscalIncToN4Inc2(b *testing.B)  { benchmarkDscalIncTo(b, 4, 2) }
func BenchmarkDscalIncToN4Inc4(b *testing.B)  { benchmarkDscalIncTo(b, 4, 4) }
func BenchmarkDscalIncToN4Inc10(b *testing.B) { benchmarkDscalIncTo(b, 4, 10) }

func BenchmarkDscalIncToN10Inc1(b *testing.B)  { benchmarkDscalIncTo(b, 10, 1) }
func BenchmarkDscalIncToN10Inc2(b *testing.B)  { benchmarkDscalIncTo(b, 10, 2) }
func BenchmarkDscalIncToN10Inc4(b *testing.B)  { benchmarkDscalIncTo(b, 10, 4) }
func BenchmarkDscalIncToN10Inc10(b *testing.B) { benchmarkDscalIncTo(b, 10, 10) }

func BenchmarkDscalIncToN1000Inc1(b *testing.B)  { benchmarkDscalIncTo(b, 1000, 1) }
func BenchmarkDscalIncToN1000Inc2(b *testing.B)  { benchmarkDscalIncTo(b, 1000, 2) }
func BenchmarkDscalIncToN1000Inc4(b *testing.B)  { benchmarkDscalIncTo(b, 1000, 4) }
func BenchmarkDscalIncToN1000Inc10(b *testing.B) { benchmarkDscalIncTo(b, 1000, 10) }

func BenchmarkDscalIncToN100000Inc1(b *testing.B)  { benchmarkDscalIncTo(b, 100000, 1) }
func BenchmarkDscalIncToN100000Inc2(b *testing.B)  { benchmarkDscalIncTo(b, 100000, 2) }
func BenchmarkDscalIncToN100000Inc4(b *testing.B)  { benchmarkDscalIncTo(b, 100000, 4) }
func BenchmarkDscalIncToN100000Inc10(b *testing.B) { benchmarkDscalIncTo(b, 100000, 10) }

func benchmarkDscalIncTo(b *testing.B, n, inc int) {
	x := randomSlice(n, inc)
	dst := randomSlice(n, inc)
	a := rand.Float64()
	b.ResetTimer()
	for i := 0; i < b.N; i++ {
		ScalIncTo(dst, uintptr(inc), a, x, uintptr(n), uintptr(inc))
	}
	benchSink = dst
}
<commit_msg>asm/f64: Cleaned up and updated scal* test code.<commit_after>// Copyright ©2016 The gonum Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package f64

import (
	"fmt"
	"math/rand"
	"testing"
)

var scalTests = []struct {
	alpha float64
	x     []float64
	want  []float64
}{
	{
		alpha: 0,
		x:     []float64{},
		want:  []float64{},
	},
	{
		alpha: 0,
		x:     []float64{1},
		want:  []float64{0},
	},
	{
		alpha: 1,
		x:     []float64{1},
		want:  []float64{1},
	},
	{
		alpha: 2,
		x:     []float64{1, -2},
		want:  []float64{2, -4},
	},
	{
		alpha: 2,
		x:     []float64{1, -2, 3},
		want:  []float64{2, -4, 6},
	},
	{
		alpha: 2,
		x:     []float64{1, -2, 3, 4},
		want:  []float64{2, -4, 6, 8},
	},
	{
		alpha: 2,
		x:     []float64{1, -2, 3, 4, -5},
		want:  []float64{2, -4, 6, 8, -10},
	},
	{
		alpha: 2,
		x:     []float64{0, 1, -2, 3, 4, -5, 6, -7},
		want:  []float64{0, 2, -4, 6, 8, -10, 12, -14},
	},
	{
		alpha: 2,
		x:     []float64{0, 1, -2, 3, 4, -5, 6, -7, 8},
		want:  []float64{0, 2, -4, 6, 8, -10, 12, -14, 16},
	},
	{
		alpha: 2,
		x:     []float64{0, 1, -2, 3, 4, -5, 6, -7, 8, 9},
		want:  []float64{0, 2, -4, 6, 8, -10, 12, -14, 16, 18},
	},
	{
		alpha: 3,
		x:     []float64{0, 1, -2, 3, 4, -5, 6, -7, 8, 9, 12},
		want:  []float64{0, 3, -6, 9, 12, -15, 18, -21, 24, 27, 36},
	},
}

func TestScalUnitary(t *testing.T) {
	const xGdVal = -0.5
	for i, test := range scalTests {
		for _, align := range align1 {
			prefix := fmt.Sprintf("Test %v (x:%v)", i, align)
			xgLn := 4 + align
			xg := guardVector(test.x, xGdVal, xgLn)
			x := xg[xgLn : len(xg)-xgLn]

			ScalUnitary(test.alpha, x)

			for i := range test.want {
				if !same(x[i], test.want[i]) {
					t.Errorf(msgVal, prefix, i, x[i], test.want[i])
				}
			}
			if !isValidGuard(xg, xGdVal, xgLn) {
				t.Errorf(msgGuard, prefix, "x", xg[:xgLn], xg[len(xg)-xgLn:])
			}
		}
	}
}

func TestScalUnitaryTo(t *testing.T) {
	const xGdVal, dstGdVal = -1, 0.5
	rng := rand.New(rand.NewSource(42))
	for i, test := range scalTests {
		n := len(test.x)
		for _, align := range align2 {
			prefix := fmt.Sprintf("Test %v (x:%v dst:%v)", i, align.x, align.y)
			xgLn, dgLn := 4+align.x, 4+align.y
			xg := guardVector(test.x, xGdVal, xgLn)
			dg := guardVector(randSlice(n, 1, rng), dstGdVal, dgLn)
			x, dst := xg[xgLn:len(xg)-xgLn], dg[dgLn:len(dg)-dgLn]

			ScalUnitaryTo(dst, test.alpha, x)

			for i := range test.want {
				if !same(dst[i], test.want[i]) {
					t.Errorf(msgVal, prefix, i, dst[i], test.want[i])
				}
			}
			if !isValidGuard(xg, xGdVal, xgLn) {
				t.Errorf(msgGuard, prefix, "x", xg[:xgLn], xg[len(xg)-xgLn:])
			}
			if !isValidGuard(dg, dstGdVal, dgLn) {
				t.Errorf(msgGuard, prefix, "y", dg[:dgLn], dg[len(dg)-dgLn:])
			}
			if !equalStrided(test.x, x, 1) {
				t.Errorf("%v: modified read-only x argument", prefix)
			}
		}
	}
}

func TestScalInc(t *testing.T) {
	const xGdVal = -0.5
	gdLn := 4
	for i, test := range scalTests {
		n := len(test.x)
		for _, incX := range []int{1, 2, 3, 4, 7, 10} {
			prefix := fmt.Sprintf("Test %v (x:%v)", i, incX)
			xg := guardIncVector(test.x, xGdVal, incX, gdLn)
			x := xg[gdLn : len(xg)-gdLn]

			ScalInc(test.alpha, x, uintptr(n), uintptr(incX))

			for i := range test.want {
				if !same(x[i*incX], test.want[i]) {
					t.Errorf(msgVal, prefix, i, x[i*incX], test.want[i])
				}
			}
			checkValidIncGuard(t, xg, xGdVal, incX, gdLn)
		}
	}
}

func TestScalIncTo(t *testing.T) {
	const xGdVal, dstGdVal = -1, 0.5
	gdLn := 4
	rng := rand.New(rand.NewSource(42))
	for i, test := range scalTests {
		n := len(test.x)
		for _, inc := range newIncSet(1, 2, 3, 4, 7, 10) {
			prefix := fmt.Sprintf("test %v (x:%v dst:%v)", i, inc.x, inc.y)
			xg := guardIncVector(test.x, xGdVal, inc.x, gdLn)
			dg := guardIncVector(randSlice(n, 1, rng), dstGdVal, inc.y, gdLn)
			x, dst := xg[gdLn:len(xg)-gdLn], dg[gdLn:len(dg)-gdLn]

			ScalIncTo(dst, uintptr(inc.y), test.alpha, x, uintptr(n), uintptr(inc.x))

			for i := range test.want {
				if !same(dst[i*inc.y], test.want[i]) {
					t.Errorf(msgVal, prefix, i, dst[i*inc.y], test.want[i])
				}
			}
			checkValidIncGuard(t, xg, xGdVal, inc.x, gdLn)
			checkValidIncGuard(t, dg, dstGdVal, inc.y, gdLn)
			if !equalStrided(test.x, x, inc.x) {
				t.Errorf("%v: modified read-only x argument", prefix)
			}

		}
	}
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"net/http"
	"strconv"

	"golang.org/x/net/websocket"
)

var socket *websocket.Conn

// Start the sftp connection with the received JSON credentials
func sftpConnect(id int, data string) {
	auth := parse(data)
	if initClients(id, auth) {
		printDirectory(id, getHomeDir(id))
	}
}

// Map of functions to determine ui actions
var fxns = map[string]func(id int, data string){
	"LOGIN_REQUEST": sftpConnect,
}

// Main handler upon client web connection to the server
func handler(sock *websocket.Conn) {
	fmt.Println("- - - - - - - - - - - - - - - - - -")
	fmt.Println("Client has connected to the server!")

	socket = sock

	// Read the initial message upon client connection
	var msg = make([]byte, 512)
	_, _ = socket.Read(msg)
	fmt.Println(string(msg))

	for {
		// Receive the sftp auth information and store in a map
		data := make(map[string]string)
		websocket.JSON.Receive(socket, &data)
		if len(data) != 0 {
			fmt.Println("Received data from the client:")
			connId, _ := strconv.Atoi(data["id"])
			go fxns[data["fxn"]](connId, data["data"])
		}
	}
}

func main() {
	http.Handle("/connect", websocket.Handler(handler))
	http.Handle("/", http.FileServer(http.Dir("../")))
	http.ListenAndServe("localhost:1337", nil)
}
<commit_msg>Added checking for environment variables to host on remote servers<commit_after>package main

import (
	"fmt"
	"net/http"
	"os"
	"strconv"

	"golang.org/x/net/websocket"
)

var socket *websocket.Conn

// Start the sftp connection with the received JSON credentials
func sftpConnect(id int, data string) {
	auth := parse(data)
	if initClients(id, auth) {
		printDirectory(id, getHomeDir(id))
	}
}

// Map of functions to determine ui actions
var fxns = map[string]func(id int, data string){
	"LOGIN_REQUEST": sftpConnect,
}

// Main handler upon client web connection to the server
func handler(sock *websocket.Conn) {
	fmt.Println("- - - - - - - - - - - - - - - - - -")
	fmt.Println("Client has connected to the server!")

	socket = sock

	// Read the initial message upon client connection
	var msg = make([]byte, 512)
	_, _ = socket.Read(msg)
	fmt.Println(string(msg))

	for {
		// Receive the sftp auth information and store in a map
		data := make(map[string]string)
		websocket.JSON.Receive(socket, &data)
		if len(data) != 0 {
			fmt.Println("Received data from the client:")
			connId, _ := strconv.Atoi(data["id"])
			go fxns[data["fxn"]](connId, data["data"])
		}
	}
}

func main() {
	hostname := os.Getenv("hostname")
	if hostname == "" {
		hostname = "localhost"
	}

	http.Handle("/connect", websocket.Handler(handler))
	http.Handle("/", http.FileServer(http.Dir("../")))
	http.ListenAndServe(hostname+":1337", nil)
}
<|endoftext|>


<commit_before>/* RPC with a pool of providers each connected via a web-socket. */
package wsrpcpool
// The pool server module

import (
	"crypto/tls"
	"crypto/x509"
	"golang.org/x/net/websocket"
	"io/ioutil"
	"net/http"
	"net/rpc"
	"net/rpc/jsonrpc"
	"sync"
	"errors"
)

/* PoolServer is used to listen on a set of web-socket URLs for RPC
providers. */
type PoolServer struct {
	http.Server
	PoolMap     map[string]chan *rpc.Call
	DefaultPool chan *rpc.Call
}

/* NewPool returns a plain PoolServer instance. */
func NewPool() *PoolServer {
	return &PoolServer{}
}

/* NewPoolTLS returns a PoolServer instance equipped with the given
SSL certificate. */
func NewPoolTLS(certfile, keyfile string) (*PoolServer, error) {
	pool := NewPool()
	if err := pool.AppendCertificate(certfile, keyfile); err != nil {
		return nil, err
	}
	return pool, nil
}

/* NewPoolTLSAuth returns a PoolServer instance equipped with the given
SSL certificate and a root CA certificates for client authentication. */
func NewPoolTLSAuth(certfile, keyfile string, clientCAs ...string) (*PoolServer, error) {
	pool, err := NewPoolTLS(certfile, keyfile)
	if err != nil {
		return nil, err
	}

	err = pool.AppendClientCAs(clientCAs...)
	if err != nil {
		return nil, err
	}

	return pool, err
}

/* AppendCertificate appends an SSL certificate to the set of server
certificates loading it from the pair of public certificate and private
key files. */
func (pool *PoolServer) AppendCertificate(certfile, keyfile string) error {
	if pool.TLSConfig == nil {
		pool.TLSConfig = &tls.Config{}
	}
	return appendCertificate(pool.TLSConfig, certfile, keyfile)
}

/* appendCertificate appends an SSL certificate to the given tls.Config
loading it from the pair of public certificate and private key files. */
func appendCertificate(tlsConfig *tls.Config, certfile, keyfile string) error {
	cert, err := tls.LoadX509KeyPair(certfile, keyfile)
	if err != nil {
		return err
	}
	tlsConfig.Certificates = append(tlsConfig.Certificates, cert)
	tlsConfig.BuildNameToCertificate()
	return nil
}

/* AppendClientCAs appends the given SSL root CA certificate files to the
set of client CAs to verify client connections against. */
func (pool *PoolServer) AppendClientCAs(clientCAs ...string) error {
	if pool.TLSConfig == nil {
		pool.TLSConfig = &tls.Config{}
	}
	if pool.TLSConfig.ClientCAs == nil {
		pool.TLSConfig.ClientCAs = x509.NewCertPool()
	}
	err := appendCAs(pool.TLSConfig.ClientCAs, clientCAs...)
	if err == nil {
		pool.TLSConfig.ClientAuth = tls.RequireAndVerifyClientCert
	}
	return err
}

/* appendCAs appends the given SSL root CA certificate files to the
given CA pool. */
func appendCAs(caPool *x509.CertPool, caCerts ...string) error {
	for _, caFile := range caCerts {
		caCert, err := ioutil.ReadFile(caFile)
		if err != nil {
			return err
		}
		if !caPool.AppendCertsFromPEM(caCert) {
			return errors.New("No certificates parsed")
		}
	}
	return nil
}

/* invoke passes the given call to the client. */
func invoke(client *rpc.Client, call *rpc.Call) *rpc.Call {
	return client.Go(call.ServiceMethod, call.Args, call.Reply, call.Done)
}

/* BindPath associates the given path with the set of remote objects or
makes it the default path if no object names given. */
func (pool *PoolServer) BindPath(path string, names ...string) {
	if pool.Handler == nil {
		pool.Handler = http.NewServeMux()
	}

	mux := pool.Handler.(*http.ServeMux)

	if len(names) > 0 {
		if pool.PoolMap == nil {
			pool.PoolMap = make(map[string]chan *rpc.Call)
		}
		for _, name := range names {
			if pool.PoolMap[name] == nil {
				pool.PoolMap[name] = make(chan *rpc.Call)
			}
		}
		mux.Handle(path, websocket.Handler(func(ws *websocket.Conn) {
			var wg sync.WaitGroup
			client := jsonrpc.NewClient(ws)
			for _, name := range names {
				callIn := pool.PoolMap[name]
				go func() {
					defer wg.Done()
					for c := range callIn {
						invoke(client, c)
					}
				}()
			}
			wg.Add(len(names))
			wg.Wait()
			client.Close()
		}))
	} else {
		if pool.DefaultPool == nil {
			pool.DefaultPool = make(chan *rpc.Call)
		}
		chanIn := pool.DefaultPool
		mux.Handle(path, websocket.Handler(func(ws *websocket.Conn) {
			client := jsonrpc.NewClient(ws)
			for c := range chanIn {
				invoke(client, c)
			}
			client.Close()
		}))
	}
}

/* ListenAndServe listens the configured address (host and port) with
no SSL encryption. */
func (pool *PoolServer) ListenAndServe() error {
	return pool.Server.ListenAndServe()
}

/* ListenAndServeTLS listens the configured address (host and port)
with SSL encryption on. */
func (pool *PoolServer) ListenAndServeTLS() error {
	return pool.Server.ListenAndServeTLS("", "")
}
<commit_msg>Pool: Add Go and Call top-level functions<commit_after>/* RPC with a pool of providers each connected via a web-socket. */
package wsrpcpool
// The pool server module

import (
	"crypto/tls"
	"crypto/x509"
	"golang.org/x/net/websocket"
	"io/ioutil"
	"net/http"
	"net/rpc"
	"net/rpc/jsonrpc"
	"sync"
	"errors"
)

/* PoolServer is used to listen on a set of web-socket URLs for RPC
providers. */
type PoolServer struct {
	http.Server
	// Provider name to a call channel map
	PoolMap     map[string]chan *rpc.Call
	// Default call channel
	DefaultPool chan *rpc.Call
}

var (
	// ErrNoDefaultPool signals that provider isn't found and there is no default pool
	ErrNoDefaultPool = errors.New("No default path is bound")
	// ErrNoCertsParsed signals that no SSL certificates were found in the given file
	ErrNoCertsParsed = errors.New("No certificates parsed")
)

/* NewPool returns a plain PoolServer instance. */
func NewPool() *PoolServer {
	return &PoolServer{}
}

/* NewPoolTLS returns a PoolServer instance equipped with the given
SSL certificate. */
func NewPoolTLS(certfile, keyfile string) (*PoolServer, error) {
	pool := NewPool()
	if err := pool.AppendCertificate(certfile, keyfile); err != nil {
		return nil, err
	}
	return pool, nil
}

/* NewPoolTLSAuth returns a PoolServer instance equipped with the given
SSL certificate and a root CA certificates for client authentication. */
func NewPoolTLSAuth(certfile, keyfile string, clientCAs ...string) (*PoolServer, error) {
	pool, err := NewPoolTLS(certfile, keyfile)
	if err != nil {
		return nil, err
	}

	err = pool.AppendClientCAs(clientCAs...)
	if err != nil {
		return nil, err
	}

	return pool, err
}

/* AppendCertificate appends an SSL certificate to the set of server
certificates loading it from the pair of public certificate and private
key files. */
func (pool *PoolServer) AppendCertificate(certfile, keyfile string) error {
	if pool.TLSConfig == nil {
		pool.TLSConfig = &tls.Config{}
	}
	return appendCertificate(pool.TLSConfig, certfile, keyfile)
}

/* appendCertificate appends an SSL certificate to the given tls.Config
loading it from the pair of public certificate and private key files. */
func appendCertificate(tlsConfig *tls.Config, certfile, keyfile string) error {
	cert, err := tls.LoadX509KeyPair(certfile, keyfile)
	if err != nil {
		return err
	}
	tlsConfig.Certificates = append(tlsConfig.Certificates, cert)
	tlsConfig.BuildNameToCertificate()
	return nil
}

/* AppendClientCAs appends the given SSL root CA certificate files to the
set of client CAs to verify client connections against. */
func (pool *PoolServer) AppendClientCAs(clientCAs ...string) error {
	if pool.TLSConfig == nil {
		pool.TLSConfig = &tls.Config{}
	}
	if pool.TLSConfig.ClientCAs == nil {
		pool.TLSConfig.ClientCAs = x509.NewCertPool()
	}
	err := appendCAs(pool.TLSConfig.ClientCAs, clientCAs...)
	if err == nil {
		pool.TLSConfig.ClientAuth = tls.RequireAndVerifyClientCert
	}
	return err
}

/* appendCAs appends the given SSL root CA certificate files to the
given CA pool. */
func appendCAs(caPool *x509.CertPool, caCerts ...string) error {
	for _, caFile := range caCerts {
		caCert, err := ioutil.ReadFile(caFile)
		if err != nil {
			return err
		}
		if !caPool.AppendCertsFromPEM(caCert) {
			return ErrNoCertsParsed
		}
	}
	return nil
}

/* invoke passes the given call to the client. */
func invoke(client *rpc.Client, call *rpc.Call) *rpc.Call {
	return client.Go(call.ServiceMethod, call.Args, call.Reply, call.Done)
}

/* BindPath associates the given path with the set of remote providers or
makes it the default path if no object provider names given. */
func (pool *PoolServer) BindPath(path string, providers ...string) {
	if pool.Handler == nil {
		pool.Handler = http.NewServeMux()
	}

	mux := pool.Handler.(*http.ServeMux)

	if len(providers) > 0 {
		if pool.PoolMap == nil {
			pool.PoolMap = make(map[string]chan *rpc.Call)
		}
		for _, name := range providers {
			if pool.PoolMap[name] == nil {
				pool.PoolMap[name] = make(chan *rpc.Call)
			}
		}
		mux.Handle(path, websocket.Handler(func(ws *websocket.Conn) {
			var wg sync.WaitGroup
			client := jsonrpc.NewClient(ws)
			for _, name := range providers {
				callIn := pool.PoolMap[name]
				go func() {
					defer wg.Done()
					for c := range callIn {
						invoke(client, c)
					}
				}()
			}
			wg.Add(len(providers))
			wg.Wait()
			client.Close()
		}))
	} else {
		if pool.DefaultPool == nil {
			pool.DefaultPool = make(chan *rpc.Call)
		}
		chanIn := pool.DefaultPool
		mux.Handle(path, websocket.Handler(func(ws *websocket.Conn) {
			client := jsonrpc.NewClient(ws)
			for c := range chanIn {
				invoke(client, c)
			}
			client.Close()
		}))
	}
}

/* ListenAndServe listens the configured address (host and port) with
no SSL encryption. */
func (pool *PoolServer) ListenAndServe() error {
	return pool.Server.ListenAndServe()
}

/* ListenAndServeTLS listens the configured address (host and port)
with SSL encryption on. */
func (pool *PoolServer) ListenAndServeTLS() error {
	return pool.Server.ListenAndServeTLS("", "")
}

/* Go invokes the given remote function asynchronously. The name of the
provider is first searched in the PoolMap and the DefaultPool is used
if it isn't there. If done is nil, a new channel is allocated and
passed in the return value. See net/rpc package for details. */
func (pool *PoolServer) Go(provider, funcName string, args interface{}, reply interface{}, done chan *rpc.Call) (*rpc.Call, error) {
	callIn := pool.PoolMap[provider]
	if callIn == nil {
		callIn = pool.DefaultPool
	}
	if callIn == nil {
		return nil, ErrNoDefaultPool
	}

	call := &rpc.Call{
		ServiceMethod: provider + "." + funcName,
		Args: args,
		Reply: reply,
	}
	if done == nil {
		done = make(chan *rpc.Call, 1)
	}
	call.Done = done

	callIn <- call
	return call, nil
}

/* Call invokes the given remote function and waits for it to complete,
returning its error status. */
func (pool *PoolServer) Call(provider, funcName string, args interface{}, reply interface{}) error {
	if call, err := pool.Go(provider, funcName, args, reply, nil); err == nil {
		call = <-call.Done
		return call.Error
	} else {
		return err
	}
}
<|endoftext|>


<commit_before>package luar

import (
	"reflect"

	"github.com/yuin/gopher-lua"
)

// New creates and returns a new lua.LValue for the given value.
//
// The following table shows how Go types are converted to Lua types:
//  Kind            gopher-lua Type  Custom Metatable
//  --------------------------------------------------
//  nil             LNil             No
//  Bool            LBool            No
//  Int             LNumber          No
//  Int8            LNumber          No
//  Int16           LNumber          No
//  Int32           LNumber          No
//  Int64           LNumber          No
//  Uint            LNumber          No
//  Uint8           LNumber          No
//  Uint16          LNumber          No
//  Uint32          LNumber          No
//  Uint64          LNumber          No
//  Uintptr         *LUserData       No
//  Float32         LNumber          No
//  Float64         LNumber          No
//  Complex64       *LUserData       No
//  Complex128      *LUserData       No
//  Array           *LUserData       Yes
//  Chan            *LUserData       Yes
//  Func            *lua.LFunction   No
//  Interface       *LUserData       No
//  Map             *LUserData       Yes
//  Ptr             *LUserData       Yes
//  Slice           *LUserData       Yes
//  String          LString          No
//  Struct          *LUserData       Yes
//  UnsafePointer   *LUserData       No
func New(L *lua.LState, value interface{}) lua.LValue {
	if value == nil {
		return lua.LNil
	}
	if lval, ok := value.(lua.LValue); ok {
		return lval
	}

	val := reflect.ValueOf(value)
	switch val.Kind() {
	case reflect.Chan, reflect.Func, reflect.Interface, reflect.Map, reflect.Ptr, reflect.Slice:
		if val.IsNil() {
			return lua.LNil
		}
	}

	switch val.Kind() {
	case reflect.Bool:
		return lua.LBool(val.Bool())
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
		return lua.LNumber(float64(val.Int()))
	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
		return lua.LNumber(float64(val.Uint()))
	case reflect.Float32, reflect.Float64:
		return lua.LNumber(val.Float())
	case reflect.Array, reflect.Chan, reflect.Map, reflect.Ptr, reflect.Slice, reflect.Struct:
		ud := L.NewUserData()
		ud.Value = val.Interface()
		ud.Metatable = getMetatableFromValue(L, val)
		return ud
	case reflect.Func:
		return funcWrapper(L, val, false)
	case reflect.Interface:
		ud := L.NewUserData()
		ud.Value = val.Interface()
		return ud
	case reflect.String:
		return lua.LString(val.String())
	default:
		ud := L.NewUserData()
		ud.Value = val.Interface()
		return ud
	}
}

// NewType returns a new type creator for the given value's type.
//
// When the lua.LValue is called, a new value will be created that is the
// same type as value's type.
func NewType(L *lua.LState, value interface{}) lua.LValue {
	val := reflect.TypeOf(value)
	ud := L.NewUserData()
	ud.Value = val
	ud.Metatable = getTypeMetatable(L, val)

	return ud
}

func lValueToReflect(L *lua.LState, v lua.LValue, hint reflect.Type, tryConvertPtr *bool) reflect.Value {
	if hint.Implements(refTypeLuaLValue) {
		return reflect.ValueOf(v)
	}

	isPtr := false

	switch converted := v.(type) {
	case lua.LBool:
		var val reflect.Value
		if hint.Kind() == reflect.String {
			val = reflect.ValueOf(converted.String())
		} else {
			val = reflect.ValueOf(bool(converted))
		}
		return val.Convert(hint)
	case lua.LChannel:
		return reflect.ValueOf(converted).Convert(hint)
	case lua.LNumber:
		var val reflect.Value
		if hint.Kind() == reflect.String {
			val = reflect.ValueOf(converted.String())
		} else {
			val = reflect.ValueOf(converted)
		}
		return val.Convert(hint)
	case *lua.LFunction:
		fn := func(args []reflect.Value) []reflect.Value {
			L.Push(converted)

			varadicCount := 0

			for i, arg := range args {
				if hint.IsVariadic() && i+1 == len(args) {
					// arg is the varadic slice
					varadicCount = arg.Len()
					for j := 0; j < varadicCount; j++ {
						arg := arg.Index(j)
						if !arg.CanInterface() {
							L.Pop(i + j + 1)
							L.RaiseError("unable to Interface argument %d", i+j)
						}
						L.Push(New(L, arg.Interface()))
					}
					// recount for varadic slice that appeared
					varadicCount--
					break
				}

				if !arg.CanInterface() {
					L.Pop(i + 1)
					L.RaiseError("unable to Interface argument %d", i)
				}
				L.Push(New(L, arg.Interface()))
			}

			L.Call(len(args)+varadicCount, hint.NumOut())
			defer L.Pop(hint.NumOut())

			ret := make([]reflect.Value, hint.NumOut())

			for i := 0; i < hint.NumOut(); i++ {
				outHint := hint.Out(i)
				ret[i] = lValueToReflect(L, L.Get(-hint.NumOut()+i), outHint, nil)
			}

			return ret
		}
		return reflect.MakeFunc(hint, fn)
	case *lua.LNilType:
		switch hint.Kind() {
		case reflect.Chan, reflect.Func, reflect.Interface, reflect.Map, reflect.Ptr, reflect.Slice, reflect.UnsafePointer:
			return reflect.Zero(hint)
		default:
			L.RaiseError("cannot convert nil to %s", hint.String())
		}
	case *lua.LState:
		return reflect.ValueOf(converted).Convert(hint)
	case lua.LString:
		return reflect.ValueOf(string(converted)).Convert(hint)
	case *lua.LTable:
		switch {
		case hint.Kind() == reflect.Slice:
			elemType := hint.Elem()
			length := converted.Len()
			s := reflect.MakeSlice(hint, length, length)

			for i := 0; i < length; i++ {
				value := converted.RawGetInt(i + 1)
				elemValue := lValueToReflect(L, value, elemType, nil)
				s.Index(i).Set(elemValue)
			}

			return s

		case hint.Kind() == reflect.Map:
			keyType := hint.Elem()
			elemType := hint.Elem()
			s := reflect.MakeMap(hint)

			converted.ForEach(func(key, value lua.LValue) {
				if _, ok := key.(lua.LString); !ok {
					return
				}

				lKey := lValueToReflect(L, key, keyType, nil)
				lValue := lValueToReflect(L, value, elemType, nil)
				s.SetMapIndex(lKey, lValue)
			})

			return s

		case hint.Kind() == reflect.Ptr && hint.Elem().Kind() == reflect.Struct:
			hint = hint.Elem()
			isPtr = true
			fallthrough
		case hint.Kind() == reflect.Struct:
			s := reflect.New(hint)
			t := s.Elem()

			mt := &Metatable{
				LTable: getMetatable(L, hint),
			}

			converted.ForEach(func(key, value lua.LValue) {
				if _, ok := key.(lua.LString); !ok {
					return
				}

				fieldName := key.String()
				index := mt.fieldIndex(fieldName)
				if index == nil {
					L.RaiseError("invalid field %s", fieldName)
				}
				field := hint.FieldByIndex(index)

				lValue := lValueToReflect(L, value, field.Type, nil)
				t.FieldByIndex(field.Index).Set(lValue)
			})

			if isPtr {
				return s
			}

			return t

		default:
			return reflect.ValueOf(converted).Convert(hint)
		}
	case *lua.LUserData:
		val := reflect.ValueOf(converted.Value)
		if tryConvertPtr != nil && val.Kind() != reflect.Ptr && hint.Kind() == reflect.Ptr && val.Type() == hint.Elem() {
			newVal := reflect.New(hint.Elem())
			newVal.Elem().Set(val)
			val = newVal
			*tryConvertPtr = true
		} else {
			val = val.Convert(hint)
			if tryConvertPtr != nil {
				*tryConvertPtr = false
			}
		}
		return val
	}
	L.RaiseError("fatal lValueToReflect error")
	return reflect.Value{} // never returns
}
<commit_msg>Fix bug in interface reflection for map key type<commit_after>package luar

import (
	"reflect"

	"github.com/yuin/gopher-lua"
)

// New creates and returns a new lua.LValue for the given value.
//
// The following table shows how Go types are converted to Lua types:
//  Kind            gopher-lua Type  Custom Metatable
//  --------------------------------------------------
//  nil             LNil             No
//  Bool            LBool            No
//  Int             LNumber          No
//  Int8            LNumber          No
//  Int16           LNumber          No
//  Int32           LNumber          No
//  Int64           LNumber          No
//  Uint            LNumber          No
//  Uint8           LNumber          No
//  Uint16          LNumber          No
//  Uint32          LNumber          No
//  Uint64          LNumber          No
//  Uintptr         *LUserData       No
//  Float32         LNumber          No
//  Float64         LNumber          No
//  Complex64       *LUserData       No
//  Complex128      *LUserData       No
//  Array           *LUserData       Yes
//  Chan            *LUserData       Yes
//  Func            *lua.LFunction   No
//  Interface       *LUserData       No
//  Map             *LUserData       Yes
//  Ptr             *LUserData       Yes
//  Slice           *LUserData       Yes
//  String          LString          No
//  Struct          *LUserData       Yes
//  UnsafePointer   *LUserData       No
func New(L *lua.LState, value interface{}) lua.LValue {
	if value == nil {
		return lua.LNil
	}
	if lval, ok := value.(lua.LValue); ok {
		return lval
	}

	val := reflect.ValueOf(value)
	switch val.Kind() {
	case reflect.Chan, reflect.Func, reflect.Interface, reflect.Map, reflect.Ptr, reflect.Slice:
		if val.IsNil() {
			return lua.LNil
		}
	}

	switch val.Kind() {
	case reflect.Bool:
		return lua.LBool(val.Bool())
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
		return lua.LNumber(float64(val.Int()))
	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
		return lua.LNumber(float64(val.Uint()))
	case reflect.Float32, reflect.Float64:
		return lua.LNumber(val.Float())
	case reflect.Array, reflect.Chan, reflect.Map, reflect.Ptr, reflect.Slice, reflect.Struct:
		ud := L.NewUserData()
		ud.Value = val.Interface()
		ud.Metatable = getMetatableFromValue(L, val)
		return ud
	case reflect.Func:
		return funcWrapper(L, val, false)
	case reflect.Interface:
		ud := L.NewUserData()
		ud.Value = val.Interface()
		return ud
	case reflect.String:
		return lua.LString(val.String())
	default:
		ud := L.NewUserData()
		ud.Value = val.Interface()
		return ud
	}
}

// NewType returns a new type creator for the given value's type.
//
// When the lua.LValue is called, a new value will be created that is the
// same type as value's type.
func NewType(L *lua.LState, value interface{}) lua.LValue {
	val := reflect.TypeOf(value)
	ud := L.NewUserData()
	ud.Value = val
	ud.Metatable = getTypeMetatable(L, val)

	return ud
}

func lValueToReflect(L *lua.LState, v lua.LValue, hint reflect.Type, tryConvertPtr *bool) reflect.Value {
	if hint.Implements(refTypeLuaLValue) {
		return reflect.ValueOf(v)
	}

	isPtr := false

	switch converted := v.(type) {
	case lua.LBool:
		var val reflect.Value
		if hint.Kind() == reflect.String {
			val = reflect.ValueOf(converted.String())
		} else {
			val = reflect.ValueOf(bool(converted))
		}
		return val.Convert(hint)
	case lua.LChannel:
		return reflect.ValueOf(converted).Convert(hint)
	case lua.LNumber:
		var val reflect.Value
		if hint.Kind() == reflect.String {
			val = reflect.ValueOf(converted.String())
		} else {
			val = reflect.ValueOf(converted)
		}
		return val.Convert(hint)
	case *lua.LFunction:
		fn := func(args []reflect.Value) []reflect.Value {
			L.Push(converted)

			varadicCount := 0

			for i, arg := range args {
				if hint.IsVariadic() && i+1 == len(args) {
					// arg is the varadic slice
					varadicCount = arg.Len()
					for j := 0; j < varadicCount; j++ {
						arg := arg.Index(j)
						if !arg.CanInterface() {
							L.Pop(i + j + 1)
							L.RaiseError("unable to Interface argument %d", i+j)
						}
						L.Push(New(L, arg.Interface()))
					}
					// recount for varadic slice that appeared
					varadicCount--
					break
				}

				if !arg.CanInterface() {
					L.Pop(i + 1)
					L.RaiseError("unable to Interface argument %d", i)
				}
				L.Push(New(L, arg.Interface()))
			}

			L.Call(len(args)+varadicCount, hint.NumOut())
			defer L.Pop(hint.NumOut())

			ret := make([]reflect.Value, hint.NumOut())

			for i := 0; i < hint.NumOut(); i++ {
				outHint := hint.Out(i)
				ret[i] = lValueToReflect(L, L.Get(-hint.NumOut()+i), outHint, nil)
			}

			return ret
		}
		return reflect.MakeFunc(hint, fn)
	case *lua.LNilType:
		switch hint.Kind() {
		case reflect.Chan, reflect.Func, reflect.Interface, reflect.Map, reflect.Ptr, reflect.Slice, reflect.UnsafePointer:
			return reflect.Zero(hint)
		default:
			L.RaiseError("cannot convert nil to %s", hint.String())
		}
	case *lua.LState:
		return reflect.ValueOf(converted).Convert(hint)
	case lua.LString:
		return reflect.ValueOf(string(converted)).Convert(hint)
	case *lua.LTable:
		switch {
		case hint.Kind() == reflect.Slice:
			elemType := hint.Elem()
			length := converted.Len()
			s := reflect.MakeSlice(hint, length, length)

			for i := 0; i < length; i++ {
				value := converted.RawGetInt(i + 1)
				elemValue := lValueToReflect(L, value, elemType, nil)
				s.Index(i).Set(elemValue)
			}

			return s

		case hint.Kind() == reflect.Map:
			keyType := hint.Key()
			elemType := hint.Elem()
			s := reflect.MakeMap(hint)

			converted.ForEach(func(key, value lua.LValue) {
				if _, ok := key.(lua.LString); !ok {
					return
				}

				lKey := lValueToReflect(L, key, keyType, nil)
				lValue := lValueToReflect(L, value, elemType, nil)
				s.SetMapIndex(lKey, lValue)
			})

			return s

		case hint.Kind() == reflect.Ptr && hint.Elem().Kind() == reflect.Struct:
			hint = hint.Elem()
			isPtr = true
			fallthrough
		case hint.Kind() == reflect.Struct:
			s := reflect.New(hint)
			t := s.Elem()

			mt := &Metatable{
				LTable: getMetatable(L, hint),
			}

			converted.ForEach(func(key, value lua.LValue) {
				if _, ok := key.(lua.LString); !ok {
					return
				}

				fieldName := key.String()
				index := mt.fieldIndex(fieldName)
				if index == nil {
					L.RaiseError("invalid field %s", fieldName)
				}
				field := hint.FieldByIndex(index)

				lValue := lValueToReflect(L, value, field.Type, nil)
				t.FieldByIndex(field.Index).Set(lValue)
			})

			if isPtr {
				return s
			}

			return t

		default:
			return reflect.ValueOf(converted).Convert(hint)
		}
	case *lua.LUserData:
		val := reflect.ValueOf(converted.Value)
		if tryConvertPtr != nil && val.Kind() != reflect.Ptr && hint.Kind() == reflect.Ptr && val.Type() == hint.Elem() {
			newVal := reflect.New(hint.Elem())
			newVal.Elem().Set(val)
			val = newVal
			*tryConvertPtr = true
		} else {
			val = val.Convert(hint)
			if tryConvertPtr != nil {
				*tryConvertPtr = false
			}
		}
		return val
	}
	L.RaiseError("fatal lValueToReflect error")
	return reflect.Value{} // never returns
}
<|endoftext|>


<commit_before>package cplayground

import (
	"sync"

	"github.com/ivan1993spb/snake-server/concurrent-map"
	"github.com/ivan1993spb/snake-server/engine"
)

const defaultShardCount = 32

func calcShardCount(size uint16) int {
	// TODO: Implement function.
	return defaultShardCount
}

type Playground struct {
	cMap *cmap.ConcurrentMap

	entities    []*entity
	entitiesMux *sync.RWMutex

	area engine.Area
}

type ErrCreatePlayground struct {
	Err error
}

func (e ErrCreatePlayground) Error() string {
	return "cannot create playground: " + e.Error()
}

func NewPlayground(width, height uint8) (*Playground, error) {
	area, err := engine.NewArea(height, width)
	if err != nil {
		return nil, ErrCreatePlayground{err}
	}

	cMap, err := cmap.New(calcShardCount(area.Size()))
	if err != nil {
		return nil, ErrCreatePlayground{err}
	}

	return &Playground{
		cMap:        cMap,
		entities:    make([]*entity, 0),
		entitiesMux: &sync.RWMutex{},
		area:        area,
	}, nil
}

func (pg *Playground) unsafeObjectExists(object interface{}) bool {
	for i := range pg.entities {
		if pg.entities[i].GetObject() == object {
			return true
		}
	}
	return false
}

func (pg *Playground) ObjectExists(object interface{}) bool {
	pg.entitiesMux.Lock()
	defer pg.entitiesMux.Unlock()
	return pg.unsafeObjectExists(object)
}

func (pg *Playground) unsafeLocationExists(location engine.Location) bool {
	for i := range pg.entities {
		if pg.entities[i].GetLocation().Equals(location) {
			return true
		}
	}
	return false
}

func (pg *Playground) LocationExists(location engine.Location) bool {
	pg.entitiesMux.Lock()
	defer pg.entitiesMux.Unlock()
	return pg.unsafeLocationExists(location)
}

func (pg *Playground) unsafeEntityExists(object interface{}, location engine.Location) bool {
	for i := range pg.entities {
		if pg.entities[i].GetObject() == object && pg.entities[i].GetLocation().Equals(location) {
			return true
		}
	}
	return false
}

func (pg *Playground) EntityExists(object interface{}, location engine.Location) bool {
	pg.entitiesMux.Lock()
	defer pg.entitiesMux.Unlock()
	return pg.unsafeEntityExists(object, location)
}

func (pg *Playground) unsafeGetObjectByLocation(location engine.Location) interface{} {
	for i := range pg.entities {
		if pg.entities[i].GetLocation().Equals(location) {
			return pg.entities[i].GetObject()
		}
	}
	return nil
}

func (pg *Playground) GetObjectByLocation(location engine.Location) interface{} {
	pg.entitiesMux.Lock()
	defer pg.entitiesMux.Unlock()
	return pg.unsafeGetObjectByLocation(location)
}

func (pg *Playground) GetObjectByDot(dot engine.Dot) interface{} {
	if v, ok := pg.cMap.Get(dot.Hash()); ok {
		if e, ok := v.(*entity); ok {
			return e.GetObject()
		}
	}
	return nil
}

func (pg *Playground) GetEntityByDot(dot engine.Dot) (interface{}, engine.Location) {
	if v, ok := pg.cMap.Get(dot.Hash()); ok {
		if e, ok := v.(*entity); ok {
			return e.GetObject(), e.GetLocation()
		}
	}
	return nil, nil
}

func (pg *Playground) GetObjectsByDots(dots []engine.Dot) []interface{} {
	if len(dots) == 0 {
		return nil
	}

	objects := make([]interface{}, 0)
	checked := make([]engine.Dot, 0, len(dots))

	for _, dot := range dots {
		flagDotChecked := false

		for i := range checked {
			if checked[i].Equals(dot) {
				flagDotChecked = true
				break
			}
		}

		if flagDotChecked {
			continue
		}

		if v, ok := pg.cMap.Get(dot.Hash()); ok {
			if e, ok := v.(*entity); ok {
				object := e.GetObject()
				flagObjectCreated := false

				for i := range objects {
					if objects[i] == object {
						flagObjectCreated = true
						break
					}
				}

				if !flagObjectCreated {
					objects = append(objects, object)
				}
			}
		}

		checked = append(checked, dot)
	}

	return objects
}

func (pg *Playground) CreateObject(object interface{}, location engine.Location) error {
	// TODO: Implement method.
	return nil
}

func (pg *Playground) CreateObjectAvailableDots(object interface{}, location engine.Location) (engine.Location, error) {
	// TODO: Implement method.
	return nil, nil
}

func (pg *Playground) DeleteObject(object interface{}, location engine.Location) error {
	// TODO: Implement method.
	return nil
}

func (pg *Playground) UpdateObject(object interface{}, old, new engine.Location) error {
	// TODO: Implement method.
	return nil
}

func (pg *Playground) UpdateObjectAvailableDots(object interface{}, old, new engine.Location) (engine.Location, error) {
	// TODO: Implement method.
	return nil, nil
}

func (pg *Playground) CreateObjectRandomDot(object interface{}) (engine.Location, error) {
	// TODO: Implement method.
	return nil, nil
}

func (pg *Playground) CreateObjectRandomRect(object interface{}, rw, rh uint8) (engine.Location, error) {
	// TODO: Implement method.
	return nil, nil
}

func (pg *Playground) CreateObjectRandomRectMargin(object interface{}, rw, rh, margin uint8) (engine.Location, error) {
	// TODO: Implement method.
	return nil, nil
}

func (pg *Playground) CreateObjectRandomByDotsMask(object interface{}, dm *engine.DotsMask) (engine.Location, error) {
	// TODO: Implement method.
	return nil, nil
}

func (pg *Playground) Navigate(dot engine.Dot, dir engine.Direction, dis uint8) (engine.Dot, error) {
	return pg.area.Navigate(dot, dir, dis)
}

func (pg *Playground) Size() uint16 {
	return pg.area.Size()
}

func (pg *Playground) Width() uint8 {
	return pg.area.Width()
}

func (pg *Playground) Height() uint8 {
	return pg.area.Height()
}

func (pg *Playground) unsafeGetObjects() []interface{} {
	objects := make([]interface{}, len(pg.entities))
	for i, entity := range pg.entities {
		objects[i] = entity.GetObject()
	}
	return objects
}

func (pg *Playground) GetObjects() []interface{} {
	pg.entitiesMux.RLock()
	defer pg.entitiesMux.RUnlock()
	return pg.unsafeGetObjects()
}
<commit_msg>Fix cplayground: use RLock to lock for reading, implement method CreateObjectRandomDot<commit_after>package cplayground

import (
	"errors"
	"sync"

	"github.com/ivan1993spb/snake-server/concurrent-map"
	"github.com/ivan1993spb/snake-server/engine"
)

const defaultShardCount = 32

func calcShardCount(size uint16) int {
	// TODO: Implement function.
	return defaultShardCount
}

var FindRetriesNumber = 32

var ErrRetriesLimit = errors.New("retries limit was reached")

type Playground struct {
	cMap *cmap.ConcurrentMap

	entities    []*entity
	entitiesMux *sync.RWMutex

	area engine.Area
}

type ErrCreatePlayground struct {
	Err error
}

func (e ErrCreatePlayground) Error() string {
	return "cannot create playground: " + e.Error()
}

func NewPlayground(width, height uint8) (*Playground, error) {
	area, err := engine.NewArea(height, width)
	if err != nil {
		return nil, ErrCreatePlayground{err}
	}

	cMap, err := cmap.New(calcShardCount(area.Size()))
	if err != nil {
		return nil, ErrCreatePlayground{err}
	}

	return &Playground{
		cMap:        cMap,
		entities:    make([]*entity, 0),
		entitiesMux: &sync.RWMutex{},
		area:        area,
	}, nil
}

func (pg *Playground) unsafeObjectExists(object interface{}) bool {
	for i := range pg.entities {
		if pg.entities[i].GetObject() == object {
			return true
		}
	}
	return false
}

func (pg *Playground) ObjectExists(object interface{}) bool {
	pg.entitiesMux.RLock()
	defer pg.entitiesMux.RUnlock()
	return pg.unsafeObjectExists(object)
}

func (pg *Playground) unsafeLocationExists(location engine.Location) bool {
	for i := range pg.entities {
		if pg.entities[i].GetLocation().Equals(location) {
			return true
		}
	}
	return false
}

func (pg *Playground) LocationExists(location engine.Location) bool {
	pg.entitiesMux.RLock()
	defer pg.entitiesMux.RUnlock()
	return pg.unsafeLocationExists(location)
}

func (pg *Playground) unsafeEntityExists(object interface{}, location engine.Location) bool {
	for i := range pg.entities {
		if pg.entities[i].GetObject() == object && pg.entities[i].GetLocation().Equals(location) {
			return true
		}
	}
	return false
}

func (pg *Playground) EntityExists(object interface{}, location engine.Location) bool {
	pg.entitiesMux.RLock()
	defer pg.entitiesMux.RUnlock()
	return pg.unsafeEntityExists(object, location)
}

func (pg *Playground) unsafeGetObjectByLocation(location engine.Location) interface{} {
	for i := range pg.entities {
		if pg.entities[i].GetLocation().Equals(location) {
			return pg.entities[i].GetObject()
		}
	}
	return nil
}

func (pg *Playground) GetObjectByLocation(location engine.Location) interface{} {
	pg.entitiesMux.RLock()
	defer pg.entitiesMux.RUnlock()
	return pg.unsafeGetObjectByLocation(location)
}

func (pg *Playground) GetObjectByDot(dot engine.Dot) interface{} {
	if v, ok := pg.cMap.Get(dot.Hash()); ok {
		if e, ok := v.(*entity); ok {
			return e.GetObject()
		}
	}
	return nil
}

func (pg *Playground) GetEntityByDot(dot engine.Dot) (interface{}, engine.Location) {
	if v, ok := pg.cMap.Get(dot.Hash()); ok {
		if e, ok := v.(*entity); ok {
			return e.GetObject(), e.GetLocation()
		}
	}
	return nil, nil
}

func (pg *Playground) GetObjectsByDots(dots []engine.Dot) []interface{} {
	if len(dots) == 0 {
		return nil
	}

	objects := make([]interface{}, 0)
	checked := make([]engine.Dot, 0, len(dots))

	for _, dot := range dots {
		flagDotChecked := false

		for i := range checked {
			if checked[i].Equals(dot) {
				flagDotChecked = true
				break
			}
		}

		if flagDotChecked {
			continue
		}

		if v, ok := pg.cMap.Get(dot.Hash()); ok {
			if e, ok := v.(*entity); ok {
				object := e.GetObject()
				flagObjectCreated := false

				for i := range objects {
					if objects[i] == object {
						flagObjectCreated = true
						break
					}
				}

				if !flagObjectCreated {
					objects = append(objects, object)
				}
			}
		}

		checked = append(checked, dot)
	}

	return objects
}

func (pg *Playground) CreateObject(object interface{}, location engine.Location) error {
	// TODO: Implement method.
	return nil
}

func (pg *Playground) CreateObjectAvailableDots(object interface{}, location engine.Location) (engine.Location, error) {
	// TODO: Implement method.
	return nil, nil
}

func (pg *Playground) DeleteObject(object interface{}, location engine.Location) error {
	// TODO: Implement method.
	return nil
}

func (pg *Playground) UpdateObject(object interface{}, old, new engine.Location) error {
	// TODO: Implement method.
	return nil
}

func (pg *Playground) UpdateObjectAvailableDots(object interface{}, old, new engine.Location) (engine.Location, error) {
	// TODO: Implement method.
	return nil, nil
}

func (pg *Playground) CreateObjectRandomDot(object interface{}) (engine.Location, error) {
	// TODO: Create specific error
	if pg.ObjectExists(object) {
		return nil, errors.New("object already exists")
	}

	for i := 0; i < FindRetriesNumber; i++ {
		dot := pg.area.NewRandomDot(0, 0)
		e := newEntity(object, engine.Location{dot})

		if pg.cMap.SetIfAbsent(dot.Hash(), e) {

			pg.entitiesMux.Lock()
			pg.entities = append(pg.entities, e)
			pg.entitiesMux.Unlock()

			return engine.Location{dot}, nil
		}
	}
	return nil, ErrRetriesLimit
}

func (pg *Playground) CreateObjectRandomRect(object interface{}, rw, rh uint8) (engine.Location, error) {
	// TODO: Implement method.
	return nil, nil
}

func (pg *Playground) CreateObjectRandomRectMargin(object interface{}, rw, rh, margin uint8) (engine.Location, error) {
	// TODO: Implement method.
	return nil, nil
}

func (pg *Playground) CreateObjectRandomByDotsMask(object interface{}, dm *engine.DotsMask) (engine.Location, error) {
	// TODO: Implement method.
	return nil, nil
}

func (pg *Playground) Navigate(dot engine.Dot, dir engine.Direction, dis uint8) (engine.Dot, error) {
	return pg.area.Navigate(dot, dir, dis)
}

func (pg *Playground) Size() uint16 {
	return pg.area.Size()
}

func (pg *Playground) Width() uint8 {
	return pg.area.Width()
}

func (pg *Playground) Height() uint8 {
	return pg.area.Height()
}

func (pg *Playground) unsafeGetObjects() []interface{} {
	objects := make([]interface{}, len(pg.entities))
	for i, entity := range pg.entities {
		objects[i] = entity.GetObject()
	}
	return objects
}

func (pg *Playground) GetObjects() []interface{} {
	pg.entitiesMux.RLock()
	defer pg.entitiesMux.RUnlock()
	return pg.unsafeGetObjects()
}
<|endoftext|>


<commit_before>package dns

import (
	"fmt"
	"strconv"
	"strings"
)

// Parse the $GENERATE statement as used in BIND9 zones.
// See http://www.zytrax.com/books/dns/ch8/generate.html for instance.
// We are called after '$GENERATE '. After which we expect:
// * the range (12-24/2)
// * lhs (ownername)
// * [[ttl][class]]
// * type
// * rhs (rdata)
// But we are lazy here, only the range is parsed *all* occurences
// of $ after that are interpreted.
// Any error are returned as a string value, the empty string signals
// "no error".
func generate(l lex, c chan lex, t chan *Token, o string) string {
	step := 1
	if i := strings.IndexAny(l.token, "/"); i != -1 {
		if i+1 == len(l.token) {
			return "bad step in $GENERATE range"
		}
		if s, e := strconv.Atoi(l.token[i+1:]); e == nil {
			if s < 0 {
				return "bad step in $GENERATE range"
			}
			step = s
		} else {
			return "bad step in $GENERATE range"
		}
		l.token = l.token[:i]
	}
	sx := strings.SplitN(l.token, "-", 2)
	if len(sx) != 2 {
		return "bad start-stop in $GENERATE range"
	}
	start, err := strconv.Atoi(sx[0])
	if err != nil {
		return "bad start in $GENERATE range"
	}
	end, err := strconv.Atoi(sx[1])
	if err != nil {
		return "bad stop in $GENERATE range"
	}
	if end < 0 || start < 0 || end <= start {
		return "bad range in $GENERATE range"
	}

	<-c // _BLANK
	// Create a complete new string, which we then parse again.
	s := ""
BuildRR:
	l = <-c
	if l.value != zNewline && l.value != zEOF {
		s += l.token
		goto BuildRR
	}
	for i := start; i <= end; i += step {
		var (
			escape bool
			dom    string
			mod    string
			err    string
			offset int
		)

		for j := 0; j < len(s); j++ { // No 'range' because we need to jump around
			switch s[j] {
			case '\\':
				if escape {
					dom += "\\"
					escape = false
					continue
				}
				escape = true
			case '$':
				mod = "%d"
				offset = 0
				if escape {
					dom += "$"
					escape = false
					continue
				}
				escape = false
				if j+1 >= len(s) { // End of the string
					dom += fmt.Sprintf(mod, i+offset)
					continue
				} else {
					if s[j+1] == '$' {
						dom += "$"
						j++
						continue
					}
				}
				// Search for { and }
				if s[j+1] == '{' { // Modifier block
					sep := strings.Index(s[j+2:], "}")
					if sep == -1 {
						return "bad modifier in $GENERATE"
					}
					mod, offset, err = modToPrintf(s[j+2 : j+2+sep])
					if err != "" {
						return err
					}
					j += 2 + sep // Jump to it
				}
				dom += fmt.Sprintf(mod, i+offset)
			default:
				if escape { // Pretty useless here
					escape = false
					continue
				}
				dom += string(s[j])
			}
		}
		// Re-parse the RR and send it on the current channel t
		rx, e := NewRR("$ORIGIN " + o + "\n" + dom)
		if e != nil {
			return e.(*ParseError).err
		}
		t <- &Token{RR: rx}
		// Its more efficient to first built the rrlist and then parse it in
		// one go! But is this a problem?
	}
	return ""
}

// Convert a $GENERATE modifier 0,0,d to something Printf can deal with.
func modToPrintf(s string) (string, int, string) {
	xs := strings.SplitN(s, ",", 3)
	if len(xs) != 3 {
		return "", 0, "bad modifier in $GENERATE"
	}
	// xs[0] is offset, xs[1] is width, xs[2] is base
	if xs[2] != "o" && xs[2] != "d" && xs[2] != "x" && xs[2] != "X" {
		return "", 0, "bad base in $GENERATE"
	}
	offset, err := strconv.Atoi(xs[0])
	if err != nil {
		return "", 0, "bad offset in $GENERATE"
	}
	width, err := strconv.Atoi(xs[1])
	if err != nil {
		return "", offset, "bad width in $GENERATE"
	}
	switch {
	case width < 0:
		return "", offset, "bad width in $GENERATE"
	case width == 0:
		return "%" + xs[1] + xs[2], offset, ""
	}
	return "%0" + xs[1] + xs[2], offset, ""
}
<commit_msg>Parsing: make it faster.<commit_after>package dns

import (
	"bytes"
	"fmt"
	"strconv"
	"strings"
)

// Parse the $GENERATE statement as used in BIND9 zones.
// See http://www.zytrax.com/books/dns/ch8/generate.html for instance.
// We are called after '$GENERATE '. After which we expect:
// * the range (12-24/2)
// * lhs (ownername)
// * [[ttl][class]]
// * type
// * rhs (rdata)
// But we are lazy here, only the range is parsed *all* occurences
// of $ after that are interpreted.
// Any error are returned as a string value, the empty string signals
// "no error".
func generate(l lex, c chan lex, t chan *Token, o string) string {
	step := 1
	if i := strings.IndexAny(l.token, "/"); i != -1 {
		if i+1 == len(l.token) {
			return "bad step in $GENERATE range"
		}
		if s, e := strconv.Atoi(l.token[i+1:]); e == nil {
			if s < 0 {
				return "bad step in $GENERATE range"
			}
			step = s
		} else {
			return "bad step in $GENERATE range"
		}
		l.token = l.token[:i]
	}
	sx := strings.SplitN(l.token, "-", 2)
	if len(sx) != 2 {
		return "bad start-stop in $GENERATE range"
	}
	start, err := strconv.Atoi(sx[0])
	if err != nil {
		return "bad start in $GENERATE range"
	}
	end, err := strconv.Atoi(sx[1])
	if err != nil {
		return "bad stop in $GENERATE range"
	}
	if end < 0 || start < 0 || end <= start {
		return "bad range in $GENERATE range"
	}

	<-c // _BLANK
	// Create a complete new string, which we then parse again.
	s := ""
BuildRR:
	l = <-c
	if l.value != zNewline && l.value != zEOF {
		s += l.token
		goto BuildRR
	}
	for i := start; i <= end; i += step {
		var (
			escape bool
			dom    bytes.Buffer
			mod    string
			err    string
			offset int
		)

		for j := 0; j < len(s); j++ { // No 'range' because we need to jump around
			switch s[j] {
			case '\\':
				if escape {
					dom.WriteByte('\\')
					escape = false
					continue
				}
				escape = true
			case '$':
				mod = "%d"
				offset = 0
				if escape {
					dom.WriteByte('$')
					escape = false
					continue
				}
				escape = false
				if j+1 >= len(s) { // End of the string
					dom.WriteString(fmt.Sprintf(mod, i+offset))
					continue
				} else {
					if s[j+1] == '$' {
						dom.WriteByte('$')
						j++
						continue
					}
				}
				// Search for { and }
				if s[j+1] == '{' { // Modifier block
					sep := strings.Index(s[j+2:], "}")
					if sep == -1 {
						return "bad modifier in $GENERATE"
					}
					mod, offset, err = modToPrintf(s[j+2 : j+2+sep])
					if err != "" {
						return err
					}
					j += 2 + sep // Jump to it
				}
				dom.WriteString(fmt.Sprintf(mod, i+offset))
			default:
				if escape { // Pretty useless here
					escape = false
					continue
				}
				dom.WriteByte(s[j])
			}
		}
		// Re-parse the RR and send it on the current channel t
		rx, e := NewRR("$ORIGIN " + o + "\n" + dom.String())
		if e != nil {
			return e.(*ParseError).err
		}
		t <- &Token{RR: rx}
		// Its more efficient to first built the rrlist and then parse it in
		// one go! But is this a problem?
	}
	return ""
}

// Convert a $GENERATE modifier 0,0,d to something Printf can deal with.
func modToPrintf(s string) (string, int, string) {
	xs := strings.SplitN(s, ",", 3)
	if len(xs) != 3 {
		return "", 0, "bad modifier in $GENERATE"
	}
	// xs[0] is offset, xs[1] is width, xs[2] is base
	if xs[2] != "o" && xs[2] != "d" && xs[2] != "x" && xs[2] != "X" {
		return "", 0, "bad base in $GENERATE"
	}
	offset, err := strconv.Atoi(xs[0])
	if err != nil {
		return "", 0, "bad offset in $GENERATE"
	}
	width, err := strconv.Atoi(xs[1])
	if err != nil {
		return "", offset, "bad width in $GENERATE"
	}
	switch {
	case width < 0:
		return "", offset, "bad width in $GENERATE"
	case width == 0:
		return "%" + xs[1] + xs[2], offset, ""
	}
	return "%0" + xs[1] + xs[2], offset, ""
}
<|endoftext|>