<commit_before>package redlot

import (
	"strconv"

	"github.com/syndtr/goleveldb/leveldb/util"
)

func encodeHashKey(name, key []byte) (buf []byte) {
	buf = append(buf, typeHASH)
	buf = append(buf, uint32ToBytes(uint32(len(name)))...)
	buf = append(buf, name...)
	buf = append(buf, key...)
	return
}

func decodeHashKey(b []byte) (name, key []byte) {
	nameLen := bytesToUint32(b[1:5])
	name = b[5 : 5+nameLen]
	key = b[5+nameLen:]
	return
}

func encodeHsizeKey(name []byte) (buf []byte) {
	buf = append(buf, typeHSIZE)
	buf = append(buf, name...)
	return
}

func decodeHsizeKey(b []byte) (key []byte) {
	return b[1:]
}

func hashSizeIncr(name []byte, incr int) {
	hsize := encodeHsizeKey(name)

	var size uint32
	if b, err := db.Get(hsize, nil); err == nil {
		size = bytesToUint32(b)
	}

	if incr > 0 {
		size += uint32(incr)
	}
	if incr < 0 && size > 0 {
		size = size - uint32(0-incr)
	}

	if size == 0 {
		db.Delete(hsize, nil)
	}
	if size > 0 {
		db.Put(hsize, uint32ToBytes(size), nil)
	}
}

// Hset will set a hashmap value by the key.
// Args: name string, key string, value any
func Hset(args [][]byte) (r interface{}, err error) {
	if len(args) < 3 {
		return nil, errNosArgs
	}
	key := encodeHashKey(args[0], args[1])

	if exists, _ := db.Has(key, nil); !exists {
		hashSizeIncr(args[0], 1)
	}

	err = db.Put(key, args[2], nil)
	if err != nil {
		hashSizeIncr(args[0], -1)
		return nil, err
	}

	return
}

// Hset will return a hashmap value by the key.
// Args: name string, key string
func Hget(args [][]byte) (r interface{}, err error) {
	if len(args) < 2 {
		return nil, errNosArgs
	}
	var b []byte
	b, err = db.Get(encodeHashKey(args[0], args[1]), nil)
	return string(b), err
}

// Hdel will delete a hashmap value by the key.
// Args: name string, key string
func Hdel(args [][]byte) (r interface{}, err error) {
	if len(args) < 2 {
		return nil, errNosArgs
	}
	err = db.Delete(encodeHashKey(args[0], args[1]), nil)
	if err == nil {
		hashSizeIncr(args[0], -1)
	}
	return
}

func hincr(name, key []byte, increment int) (r int64, err error) {
	hash := encodeHashKey(name, key)
	v, _ := db.Get(hash, nil)
	var number int
	var exists bool
	if len(v) != 0 {
		number, err = strconv.Atoi(string(v))
		exists = true
		if err != nil {
			return -1, errNotInt
		}
	}
	number += increment
	r = int64(number)
	err = db.Put(hash, []byte(strconv.Itoa(number)), nil)
	if err == nil && !exists {
		hashSizeIncr(name, 1)
	}
	return
}

// Hincr will incr a hashmap value by the key.
// Args: name string, key string
func Hincr(args [][]byte) (r interface{}, err error) {
	if len(args) < 2 {
		return nil, errNosArgs
	}

	return hincr(args[0], args[1], 1)
}

// Hincrby will incr number a hashmap value by the key.
// Args: name string, key string, value int
func Hincrby(args [][]byte) (r interface{}, err error) {
	if len(args) < 3 {
		return nil, errNosArgs
	}
	i, e := strconv.Atoi(string(args[2]))
	if e != nil {
		return -1, errNotInt
	}

	return hincr(args[0], args[1], i)
}

// Hexists will check the hashmap key is exists.
// Args: name string, key string
func Hexists(args [][]byte) (r interface{}, err error) {
	if len(args) < 2 {
		return nil, errNosArgs
	}

	return
}

// Hsize will return the hashmap size.
// Args: name string
func Hsize(args [][]byte) (r interface{}, err error) {
	if len(args) < 1 {
		return nil, errNosArgs
	}

	var size int64
	if b, e := db.Get(encodeHsizeKey(args[0]), nil); e != nil {
		size = -1
	} else {
		size = int64(bytesToUint32(b))
	}

	return size, nil
}

// Hlist will list all hashmap in the range.
// Args: start string, end string, limit int
func Hlist(args [][]byte) (r []string, err error) {
	if len(args) < 3 {
		return nil, errNosArgs
	}

	return
}

// Hrlist will reverse list all hashmap in the range.
// Args: start string, end string, limit int
func Hrlist(args [][]byte) (r []string, err error) {
	if len(args) < 3 {
		return nil, errNosArgs
	}

	return
}

func hscan(args [][]byte, kv, reverse bool) (r []string, err error) {
	if _, err = db.Get(encodeHsizeKey(args[0]), nil); err != nil {
		return
	}

	if len(args[1]) != 0 && string(args[1]) >= string(args[2]) {
		return []string{""}, nil
	}

	var ks, ke []byte
	if len(args[1]) == 0 {
		ks = append(ks, typeHASH)
		ks = append(ks, uint32ToBytes(uint32(len(args[0])))...)
		ks = append(ks, args[0]...)
	} else {
		ks = encodeHashKey(args[0], args[1])
	}

	if len(args[2]) == 0 {
		ke = append(ks, []byte{0xff}...)
	} else {
		ke = encodeHashKey(args[0], args[2])
	}

	limit, _ := strconv.Atoi(string(args[3]))

	iter := db.NewIterator(&util.Range{Start: ks, Limit: ke}, nil)
	var iters func() bool
	if reverse {
		iter.Seek(ke)
		iters = iter.Prev
	} else {
		iters = iter.Next
	}
	for iters() {
		_, key := decodeHashKey(iter.Key())
		r = append(r, string(key))
		if kv {
			r = append(r, string(iter.Value()))
		}
		limit--
		if limit <= 0 {
			break
		}
	}

	iter.Release()
	err = iter.Error()

	return
}

// Hkeys will list the hashmap keys in the range.
// Args: name string, start string, end string, limit int
func Hkeys(args [][]byte) (r []string, err error) {
	if len(args) < 4 {
		return nil, errNosArgs
	}

	r, err = hscan(args, false, false)

	return
}

// Hrkeys will reverse list the hashmap keys in the range.
// Args: name string, start string, end string, limit int
func Hrkeys(args [][]byte) (r []string, err error) {
	if len(args) < 4 {
		return nil, errNosArgs
	}

	r, err = hscan(args, false, true)

	return
}

// Hgetall will list all keys/value in the hashmap.
// Args: name string
func Hgetall(args [][]byte) (r []string, err error) {
	if len(args) < 1 {
		return nil, errNosArgs
	}

	if _, err = db.Get(encodeHsizeKey(args[0]), nil); err != nil {
		return
	}

	var buf []byte
	buf = append(buf, typeHASH)
	buf = append(buf, uint32ToBytes(uint32(len(args[0])))...)
	buf = append(buf, args[0]...)
	ke := append(buf, []byte{0xff}...)

	iter := db.NewIterator(&util.Range{Start: buf, Limit: ke}, nil)
	for iter.Next() {
		_, key := decodeHashKey(iter.Key())
		r = append(r, string(key))
		r = append(r, string(iter.Value()))
	}
	iter.Release()
	err = iter.Error()
	return
}

// Hscan will list keys/value of the hashmap in the range.
// Args: name string, start string, end string, limit int
func Hscan(args [][]byte) (r []string, err error) {
	if len(args) < 4 {
		return nil, errNosArgs
	}

	r, err = hscan(args, true, false)

	return
}

// Hrscan will reverse list keys/value of the hashmap in the range.
// Args: name string, start string, end string, limit int
func Hrscan(args [][]byte) (r []string, err error) {
	if len(args) < 4 {
		return nil, errNosArgs
	}

	r, err = hscan(args, true, true)

	return
}

// Hclear will remove all value in the hashmap.
// Args: name string
func Hclear(args [][]byte) (r interface{}, err error) {
	if len(args) < 1 {
		return nil, errNosArgs
	}

	return
}

// MultiHget will return multi hashmap value by keys.
func MultiHget(args [][]byte) (r []string, err error) {
	if len(args) < 2 {
		return nil, errNosArgs
	}

	return
}

// MultiHset will set multi hashmap value by keys.
func MultiHset(args [][]byte) (r interface{}, err error) {
	if len(args) < 3 && len(args)%2 == 0 {
		return nil, errNosArgs
	}

	return
}

// MultiHdel will delete multi hashmap value by keys.
func MultiHdel(args [][]byte) (r interface{}, err error) {
	if len(args) < 2 {
		return nil, errNosArgs
	}

	return
}
<commit_msg>Implement Hlist and Hrlist.<commit_after>package redlot

import (
	"strconv"

	"github.com/syndtr/goleveldb/leveldb/util"
)

func encodeHashKey(name, key []byte) (buf []byte) {
	buf = append(buf, typeHASH)
	buf = append(buf, uint32ToBytes(uint32(len(name)))...)
	buf = append(buf, name...)
	buf = append(buf, key...)
	return
}

func decodeHashKey(b []byte) (name, key []byte) {
	nameLen := bytesToUint32(b[1:5])
	name = b[5 : 5+nameLen]
	key = b[5+nameLen:]
	return
}

func encodeHsizeKey(name []byte) (buf []byte) {
	buf = append(buf, typeHSIZE)
	buf = append(buf, name...)
	return
}

func decodeHsizeKey(b []byte) (key []byte) {
	return b[1:]
}

func hashSizeIncr(name []byte, incr int) {
	hsize := encodeHsizeKey(name)

	var size uint32
	if b, err := db.Get(hsize, nil); err == nil {
		size = bytesToUint32(b)
	}

	if incr > 0 {
		size += uint32(incr)
	}
	if incr < 0 && size > 0 {
		size = size - uint32(0-incr)
	}

	if size == 0 {
		db.Delete(hsize, nil)
	}
	if size > 0 {
		db.Put(hsize, uint32ToBytes(size), nil)
	}
}

// Hset will set a hashmap value by the key.
// Args: name string, key string, value any
func Hset(args [][]byte) (r interface{}, err error) {
	if len(args) < 3 {
		return nil, errNosArgs
	}
	key := encodeHashKey(args[0], args[1])

	if exists, _ := db.Has(key, nil); !exists {
		hashSizeIncr(args[0], 1)
	}

	err = db.Put(key, args[2], nil)
	if err != nil {
		hashSizeIncr(args[0], -1)
		return nil, err
	}

	return
}

// Hset will return a hashmap value by the key.
// Args: name string, key string
func Hget(args [][]byte) (r interface{}, err error) {
	if len(args) < 2 {
		return nil, errNosArgs
	}
	var b []byte
	b, err = db.Get(encodeHashKey(args[0], args[1]), nil)
	return string(b), err
}

// Hdel will delete a hashmap value by the key.
// Args: name string, key string
func Hdel(args [][]byte) (r interface{}, err error) {
	if len(args) < 2 {
		return nil, errNosArgs
	}
	err = db.Delete(encodeHashKey(args[0], args[1]), nil)
	if err == nil {
		hashSizeIncr(args[0], -1)
	}
	return
}

func hincr(name, key []byte, increment int) (r int64, err error) {
	hash := encodeHashKey(name, key)
	v, _ := db.Get(hash, nil)
	var number int
	var exists bool
	if len(v) != 0 {
		number, err = strconv.Atoi(string(v))
		exists = true
		if err != nil {
			return -1, errNotInt
		}
	}
	number += increment
	r = int64(number)
	err = db.Put(hash, []byte(strconv.Itoa(number)), nil)
	if err == nil && !exists {
		hashSizeIncr(name, 1)
	}
	return
}

// Hincr will incr a hashmap value by the key.
// Args: name string, key string
func Hincr(args [][]byte) (r interface{}, err error) {
	if len(args) < 2 {
		return nil, errNosArgs
	}

	return hincr(args[0], args[1], 1)
}

// Hincrby will incr number a hashmap value by the key.
// Args: name string, key string, value int
func Hincrby(args [][]byte) (r interface{}, err error) {
	if len(args) < 3 {
		return nil, errNosArgs
	}
	i, e := strconv.Atoi(string(args[2]))
	if e != nil {
		return -1, errNotInt
	}

	return hincr(args[0], args[1], i)
}

// Hexists will check the hashmap key is exists.
// Args: name string, key string
func Hexists(args [][]byte) (r interface{}, err error) {
	if len(args) < 2 {
		return nil, errNosArgs
	}

	return
}

// Hsize will return the hashmap size.
// Args: name string
func Hsize(args [][]byte) (r interface{}, err error) {
	if len(args) < 1 {
		return nil, errNosArgs
	}

	var size int64
	if b, e := db.Get(encodeHsizeKey(args[0]), nil); e != nil {
		size = -1
	} else {
		size = int64(bytesToUint32(b))
	}

	return size, nil
}

func hlist(args [][]byte, reverse bool) (r []string, err error) {
	if len(args) < 3 {
		return nil, errNosArgs
	}

	var ks, ke []byte
	if len(args[0]) == 0 {
		ks = []byte{0x48, 0x00}
	} else {
		ks = encodeHsizeKey(args[0])
	}
	if len(args[1]) == 0 {
		ke = []byte{0x48, 0xff}
	} else {
		ke = encodeHsizeKey(args[1])
	}

	iter := db.NewIterator(&util.Range{Start: ks, Limit: ke}, nil)
	limit, _ := strconv.Atoi(string(args[2]))

	var iters func() bool
	if reverse {
		iter.Seek([]byte{0x48, 0xff})
		iters = iter.Prev
	} else {
		iters = iter.Next
	}
	for iters() {
		key := decodeHsizeKey(iter.Key())
		r = append(r, string(key))
		limit--
		if limit <= 0 {
			break
		}
	}

	iter.Release()
	err = iter.Error()

	return
}

// Hlist will list all hashmap in the range.
// Args: start string, end string, limit int
func Hlist(args [][]byte) (r []string, err error) {
	r, err = hlist(args, false)
	return
}

// Hrlist will reverse list all hashmap in the range.
// Args: start string, end string, limit int
func Hrlist(args [][]byte) (r []string, err error) {
	r, err = hlist(args, true)

	return
}

func hscan(args [][]byte, kv, reverse bool) (r []string, err error) {
	if _, err = db.Get(encodeHsizeKey(args[0]), nil); err != nil {
		return
	}

	if len(args[1]) != 0 && string(args[1]) >= string(args[2]) {
		return []string{""}, nil
	}

	var ks, ke []byte
	if len(args[1]) == 0 {
		ks = append(ks, typeHASH)
		ks = append(ks, uint32ToBytes(uint32(len(args[0])))...)
		ks = append(ks, args[0]...)
	} else {
		ks = encodeHashKey(args[0], args[1])
	}

	if len(args[2]) == 0 {
		ke = append(ks, []byte{0xff}...)
	} else {
		ke = encodeHashKey(args[0], args[2])
	}

	limit, _ := strconv.Atoi(string(args[3]))

	iter := db.NewIterator(&util.Range{Start: ks, Limit: ke}, nil)
	var iters func() bool
	if reverse {
		iter.Seek(ke)
		iters = iter.Prev
	} else {
		iters = iter.Next
	}
	for iters() {
		_, key := decodeHashKey(iter.Key())
		r = append(r, string(key))
		if kv {
			r = append(r, string(iter.Value()))
		}
		limit--
		if limit <= 0 {
			break
		}
	}

	iter.Release()
	err = iter.Error()

	return
}

// Hkeys will list the hashmap keys in the range.
// Args: name string, start string, end string, limit int
func Hkeys(args [][]byte) (r []string, err error) {
	if len(args) < 4 {
		return nil, errNosArgs
	}

	r, err = hscan(args, false, false)

	return
}

// Hrkeys will reverse list the hashmap keys in the range.
// Args: name string, start string, end string, limit int
func Hrkeys(args [][]byte) (r []string, err error) {
	if len(args) < 4 {
		return nil, errNosArgs
	}

	r, err = hscan(args, false, true)

	return
}

// Hgetall will list all keys/value in the hashmap.
// Args: name string
func Hgetall(args [][]byte) (r []string, err error) {
	if len(args) < 1 {
		return nil, errNosArgs
	}

	if _, err = db.Get(encodeHsizeKey(args[0]), nil); err != nil {
		return
	}

	var buf []byte
	buf = append(buf, typeHASH)
	buf = append(buf, uint32ToBytes(uint32(len(args[0])))...)
	buf = append(buf, args[0]...)
	ke := append(buf, []byte{0xff}...)

	iter := db.NewIterator(&util.Range{Start: buf, Limit: ke}, nil)
	for iter.Next() {
		_, key := decodeHashKey(iter.Key())
		r = append(r, string(key))
		r = append(r, string(iter.Value()))
	}
	iter.Release()
	err = iter.Error()
	return
}

// Hscan will list keys/value of the hashmap in the range.
// Args: name string, start string, end string, limit int
func Hscan(args [][]byte) (r []string, err error) {
	if len(args) < 4 {
		return nil, errNosArgs
	}

	r, err = hscan(args, true, false)

	return
}

// Hrscan will reverse list keys/value of the hashmap in the range.
// Args: name string, start string, end string, limit int
func Hrscan(args [][]byte) (r []string, err error) {
	if len(args) < 4 {
		return nil, errNosArgs
	}

	r, err = hscan(args, true, true)

	return
}

// Hclear will remove all value in the hashmap.
// Args: name string
func Hclear(args [][]byte) (r interface{}, err error) {
	if len(args) < 1 {
		return nil, errNosArgs
	}

	return
}

// MultiHget will return multi hashmap value by keys.
func MultiHget(args [][]byte) (r []string, err error) {
	if len(args) < 2 {
		return nil, errNosArgs
	}

	return
}

// MultiHset will set multi hashmap value by keys.
func MultiHset(args [][]byte) (r interface{}, err error) {
	if len(args) < 3 && len(args)%2 == 0 {
		return nil, errNosArgs
	}

	return
}

// MultiHdel will delete multi hashmap value by keys.
func MultiHdel(args [][]byte) (r interface{}, err error) {
	if len(args) < 2 {
		return nil, errNosArgs
	}

	return
}
<|endoftext|>


<commit_before>// Copyright 2015 CoreOS, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package ip

import (
	"crypto/rand"
	"fmt"
	"net"
	"os"

	"github.com/vishvananda/netlink"
)

func makeVethPair(name, peer string, mtu int) (netlink.Link, error) {
	veth := &netlink.Veth{
		LinkAttrs: netlink.LinkAttrs{
			Name:  name,
			Flags: net.FlagUp,
			MTU:   mtu,
		},
		PeerName: peer,
	}
	if err := netlink.LinkAdd(veth); err != nil {
		return nil, err
	}

	return veth, nil
}

func makeVeth(name string, mtu int) (peerName string, veth netlink.Link, err error) {
	for i := 0; i < 10; i++ {
		peerName, err = RandomVethName()
		if err != nil {
			return
		}

		veth, err = makeVethPair(name, peerName, mtu)
		switch {
		case err == nil:
			return

		case os.IsExist(err):
			continue

		default:
			err = fmt.Errorf("failed to make veth pair: %v", err)
			return
		}
	}

	// should really never be hit
	err = fmt.Errorf("failed to find a unique veth name")
	return
}

// RandomVethName returns string "veth" with random prefix (hashed from entropy)
func RandomVethName() (string, error) {
	entropy := make([]byte, 4)
	_, err := rand.Reader.Read(entropy)
	if err != nil {
		return "", fmt.Errorf("failed to generate random veth name: %v", err)
	}

	// NetworkManager (recent versions) will ignore veth devices that start with "veth"
	return fmt.Sprintf("veth%x", entropy), nil
}

// SetupVeth creates the virtual ethernet pair and sets up the container's end in the container netns.
// Setting up the host end up has to be done in the host netns outside of this function.
// This is because moving the host veth end will cause it to be brought down automatically when it is moved to the host netns.
func SetupVeth(contVethName string, mtu int, hostNS *os.File) (hostVeth, contVeth netlink.Link, err error) {
	var hostVethName string
	hostVethName, contVeth, err = makeVeth(contVethName, mtu)
	if err != nil {
		return
	}

	if err = netlink.LinkSetUp(contVeth); err != nil {
		err = fmt.Errorf("failed to set %q up: %v", contVethName, err)
		return
	}

	hostVeth, err = netlink.LinkByName(hostVethName)
	if err != nil {
		err = fmt.Errorf("failed to lookup %q: %v", hostVethName, err)
		return
	}

	if err = netlink.LinkSetNsFd(hostVeth, int(hostNS.Fd())); err != nil {
		err = fmt.Errorf("failed to move veth to host netns: %v", err)
		return
	}

	return
}

// DelLinkByName removes an interface link.
func DelLinkByName(ifName string) error {
	iface, err := netlink.LinkByName(ifName)
	if err != nil {
		return fmt.Errorf("failed to lookup %q: %v", ifName, err)
	}

	if err = netlink.LinkDel(iface); err != nil {
		return fmt.Errorf("failed to delete %q: %v", ifName, err)
	}

	return nil
}

// DelLinkByNameAddr remove an interface returns its IP address
// of the specified family
func DelLinkByNameAddr(ifName string, family int) (*net.IPNet, error) {
	iface, err := netlink.LinkByName(ifName)
	if err != nil {
		return nil, fmt.Errorf("failed to lookup %q: %v", ifName, err)
	}

	addrs, err := netlink.AddrList(iface, family)
	if err != nil || len(addrs) == 0 {
		return nil, fmt.Errorf("failed to get IP addresses for %q: %v", ifName, err)
	}

	if err = netlink.LinkDel(iface); err != nil {
		return nil, fmt.Errorf("failed to delete %q: %v", ifName, err)
	}

	return addrs[0].IPNet, nil
}
<commit_msg>Revert "plugins/ptp: allow host veth to be UP"<commit_after>// Copyright 2015 CoreOS, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package ip

import (
	"crypto/rand"
	"fmt"
	"net"
	"os"

	"github.com/vishvananda/netlink"
)

func makeVethPair(name, peer string, mtu int) (netlink.Link, error) {
	veth := &netlink.Veth{
		LinkAttrs: netlink.LinkAttrs{
			Name:  name,
			Flags: net.FlagUp,
			MTU:   mtu,
		},
		PeerName: peer,
	}
	if err := netlink.LinkAdd(veth); err != nil {
		return nil, err
	}

	return veth, nil
}

func makeVeth(name string, mtu int) (peerName string, veth netlink.Link, err error) {
	for i := 0; i < 10; i++ {
		peerName, err = RandomVethName()
		if err != nil {
			return
		}

		veth, err = makeVethPair(name, peerName, mtu)
		switch {
		case err == nil:
			return

		case os.IsExist(err):
			continue

		default:
			err = fmt.Errorf("failed to make veth pair: %v", err)
			return
		}
	}

	// should really never be hit
	err = fmt.Errorf("failed to find a unique veth name")
	return
}

// RandomVethName returns string "veth" with random prefix (hashed from entropy)
func RandomVethName() (string, error) {
	entropy := make([]byte, 4)
	_, err := rand.Reader.Read(entropy)
	if err != nil {
		return "", fmt.Errorf("failed to generate random veth name: %v", err)
	}

	// NetworkManager (recent versions) will ignore veth devices that start with "veth"
	return fmt.Sprintf("veth%x", entropy), nil
}

// SetupVeth sets up a virtual ethernet link.
// Should be in container netns.
func SetupVeth(contVethName string, mtu int, hostNS *os.File) (hostVeth, contVeth netlink.Link, err error) {
	var hostVethName string
	hostVethName, contVeth, err = makeVeth(contVethName, mtu)
	if err != nil {
		return
	}

	if err = netlink.LinkSetUp(contVeth); err != nil {
		err = fmt.Errorf("failed to set %q up: %v", contVethName, err)
		return
	}

	hostVeth, err = netlink.LinkByName(hostVethName)
	if err != nil {
		err = fmt.Errorf("failed to lookup %q: %v", hostVethName, err)
		return
	}

	if err = netlink.LinkSetUp(hostVeth); err != nil {
		err = fmt.Errorf("failed to set %q up: %v", contVethName, err)
		return
	}

	if err = netlink.LinkSetNsFd(hostVeth, int(hostNS.Fd())); err != nil {
		err = fmt.Errorf("failed to move veth to host netns: %v", err)
		return
	}

	return
}

// DelLinkByName removes an interface link.
func DelLinkByName(ifName string) error {
	iface, err := netlink.LinkByName(ifName)
	if err != nil {
		return fmt.Errorf("failed to lookup %q: %v", ifName, err)
	}

	if err = netlink.LinkDel(iface); err != nil {
		return fmt.Errorf("failed to delete %q: %v", ifName, err)
	}

	return nil
}

// DelLinkByNameAddr remove an interface returns its IP address
// of the specified family
func DelLinkByNameAddr(ifName string, family int) (*net.IPNet, error) {
	iface, err := netlink.LinkByName(ifName)
	if err != nil {
		return nil, fmt.Errorf("failed to lookup %q: %v", ifName, err)
	}

	addrs, err := netlink.AddrList(iface, family)
	if err != nil || len(addrs) == 0 {
		return nil, fmt.Errorf("failed to get IP addresses for %q: %v", ifName, err)
	}

	if err = netlink.LinkDel(iface); err != nil {
		return nil, fmt.Errorf("failed to delete %q: %v", ifName, err)
	}

	return addrs[0].IPNet, nil
}
<|endoftext|>


<commit_before>// Copyright (c) 2017 Intel Corporation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package main

import (
	"github.com/01org/ciao/ciao-controller/internal/datastore"
	"github.com/01org/ciao/ciao-controller/internal/quotas"
	"github.com/01org/ciao/ciao-controller/types"
	"github.com/01org/ciao/payloads"
	"github.com/pkg/errors"
)

func (c *controller) UpdateQuotas(tenantID string, qds []types.QuotaDetails) error {
	err := c.ds.UpdateQuotas(tenantID, qds)
	if err != nil {
		return errors.Wrap(err, "error updating quotas in database")
	}
	c.qs.Update(tenantID, qds)
	return nil
}

func (c *controller) ListQuotas(tenantID string) []types.QuotaDetails {
	return c.qs.DumpQuotas(tenantID)
}

func populateQuotasFromDatastore(qs *quotas.Quotas, ds *datastore.Datastore) error {
	ts, err := ds.GetAllTenants()
	if err != nil {
		return errors.Wrap(err, "error getting tenants")
	}

	for _, t := range ts {
		// Populate quotas/limits from datastore
		qds, err := ds.GetQuotas(t.ID)
		if err != nil {
			return errors.Wrapf(err, "error getting quotas for tenant %s", t.ID)
		}
		qs.Update(t.ID, qds)

		// Populate volume usage
		// TODO: populate instance usage
		// TODO: populate image usage
		// TODO: populate external IP usage
		bds, err := ds.GetBlockDevices(t.ID)
		if err != nil {
			return errors.Wrapf(err, "error getting block devices for tenant %s", t.ID)
		}
		var size, count int
		for _, bd := range bds {
			size += bd.Size
			count++
		}

		// With initial population we disregard the result of consumption
		<-qs.Consume(t.ID,
			payloads.RequestedResource{Type: payloads.Volume, Value: count},
			payloads.RequestedResource{Type: payloads.SharedDiskGiB, Value: size})
	}

	return nil
}
<commit_msg>ciao-controller: Populate quota service with instances from database<commit_after>// Copyright (c) 2017 Intel Corporation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package main

import (
	"github.com/01org/ciao/ciao-controller/internal/datastore"
	"github.com/01org/ciao/ciao-controller/internal/quotas"
	"github.com/01org/ciao/ciao-controller/types"
	"github.com/01org/ciao/payloads"
	"github.com/pkg/errors"
)

func (c *controller) UpdateQuotas(tenantID string, qds []types.QuotaDetails) error {
	err := c.ds.UpdateQuotas(tenantID, qds)
	if err != nil {
		return errors.Wrap(err, "error updating quotas in database")
	}
	c.qs.Update(tenantID, qds)
	return nil
}

func (c *controller) ListQuotas(tenantID string) []types.QuotaDetails {
	return c.qs.DumpQuotas(tenantID)
}

func populateQuotasFromDatastore(qs *quotas.Quotas, ds *datastore.Datastore) error {
	ts, err := ds.GetAllTenants()
	if err != nil {
		return errors.Wrap(err, "error getting tenants")
	}

	for _, t := range ts {
		// Populate quotas/limits from datastore
		qds, err := ds.GetQuotas(t.ID)
		if err != nil {
			return errors.Wrapf(err, "error getting quotas for tenant %s", t.ID)
		}
		qs.Update(t.ID, qds)

		// Populate volume usage
		// TODO: populate image usage
		// TODO: populate external IP usage
		bds, err := ds.GetBlockDevices(t.ID)
		if err != nil {
			return errors.Wrapf(err, "error getting block devices for tenant %s", t.ID)
		}
		var size, count int
		for _, bd := range bds {
			size += bd.Size
			count++
		}
		// With initial population we disregard the result of consumption
		<-qs.Consume(t.ID,
			payloads.RequestedResource{Type: payloads.Volume, Value: count},
			payloads.RequestedResource{Type: payloads.SharedDiskGiB, Value: size})

		instances, err := ds.GetAllInstancesFromTenant(t.ID)
		if err != nil {
			return errors.Wrapf(err, "error getting tenant instances")
		}

		for _, instance := range instances {
			wl, err := ds.GetWorkload(t.ID, instance.WorkloadID)
			if err != nil {
				return errors.Wrapf(err, "error getting workload")
			}
			resources := []payloads.RequestedResource{{Type: payloads.Instance, Value: 1}}
			resources = append(resources, wl.Defaults...)
			<-qs.Consume(t.ID, resources...)
		}
	}

	return nil
}
<|endoftext|>


<commit_before>// Copyright 2013 The StudyGolang Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// http://studygolang.com
// Author：polaris	studygolang@gmail.com

package controller

import (
	"strconv"
	"sync"
	"time"

	"go.net/websocket"
	"logger"
	"service"
	"util"
)

var ServerId int
var mutex sync.Mutex

// websocket，统计在线用户数
// uri: /ws
func WsHandler(wsConn *websocket.Conn) {
	mutex.Lock()
	ServerId++
	serverId := ServerId
	mutex.Unlock()
	req := wsConn.Request()
	user, err := strconv.Atoi(req.FormValue("uid"))
	if err != nil || user == 0 {
		ip := util.Ip(req)
		logger.Debugln("user ip:", ip)
		user = int(util.Ip2long(ip))
	}
	userData := service.Book.AddUser(user, serverId)
	// 给自己发送消息，告诉当前在线用户数、历史最高在线人数
	onlineInfo := map[string]int{"online": service.Book.Len() + 50, "maxonline": service.MaxOnlineNum()}
	message := service.NewMessage(service.WsMsgOnline, onlineInfo)
	err = websocket.JSON.Send(wsConn, message)
	if err != nil {
		logger.Errorln("Sending onlineusers error:", err)
	}
	var clientClosed = false
	for {
		select {
		case message := <-userData.MessageQueue(serverId):
			if err := websocket.JSON.Send(wsConn, message); err != nil {
				clientClosed = true
			}
			// 心跳
		case <-time.After(30e9):
			if err := websocket.JSON.Send(wsConn, ""); err != nil {
				clientClosed = true
			}
		}
		if clientClosed {
			service.Book.DelUser(user, serverId)
			break
		}
	}
	// 用户退出时需要变更其他用户看到的在线用户数
	if !service.Book.UserIsOnline(user) {
		message := service.NewMessage(service.WsMsgOnline, map[string]int{"online": service.Book.Len()})
		go service.Book.BroadcastAllUsersMessage(message)
	}
}
<commit_msg>bugfix<commit_after>// Copyright 2013 The StudyGolang Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// http://studygolang.com
// Author：polaris	studygolang@gmail.com

package controller

import (
	"strconv"
	"sync"
	"time"

	"go.net/websocket"
	"logger"
	"service"
	"util"
)

var ServerId int
var mutex sync.Mutex

// websocket，统计在线用户数
// uri: /ws
func WsHandler(wsConn *websocket.Conn) {
	mutex.Lock()
	ServerId++
	serverId := ServerId
	mutex.Unlock()
	req := wsConn.Request()
	user, err := strconv.Atoi(req.FormValue("uid"))
	if err != nil || user == 0 {
		ip := util.Ip(req)
		logger.Debugln("user ip:", ip)
		user = int(util.Ip2long(ip))
	}
	userData := service.Book.AddUser(user, serverId)
	// 给自己发送消息，告诉当前在线用户数、历史最高在线人数
	onlineInfo := map[string]int{"online": service.Book.Len() + 50, "maxonline": service.MaxOnlineNum()}
	message := service.NewMessage(service.WsMsgOnline, onlineInfo)
	err = websocket.JSON.Send(wsConn, message)
	if err != nil {
		logger.Errorln("Sending onlineusers error:", err)
	}
	var clientClosed = false
	for {
		select {
		case message := <-userData.MessageQueue(serverId):
			if err := websocket.JSON.Send(wsConn, message); err != nil {
				clientClosed = true
			}
			// 心跳
		case <-time.After(30e9):
			if err := websocket.JSON.Send(wsConn, ""); err != nil {
				clientClosed = true
			}
		}
		if clientClosed {
			service.Book.DelUser(user, serverId)
			break
		}
	}
	// 用户退出时需要变更其他用户看到的在线用户数
	if !service.Book.UserIsOnline(user) {
		message := service.NewMessage(service.WsMsgOnline, map[string]int{"online": service.Book.Len() + 50})
		go service.Book.BroadcastAllUsersMessage(message)
	}
}
<|endoftext|>


<commit_before>package leap

const testVersion = 3

// IsLeapYear tests if a given int value represents a Leap Year
func IsLeapYear(year int) bool {
	if year%4 == 0 && (year%100 != 0 || year%400 == 0) {
		return true
	}
	return false
}
<commit_msg>simplified return statement<commit_after>package leap

const testVersion = 3

// IsLeapYear tests if a given int value represents a Leap Year
func IsLeapYear(year int) bool {
	return year%4 == 0 && (year%100 != 0 || year%400 == 0)
}
<|endoftext|>


<commit_before>package models

import (
	"adexchange/lib"
	"github.com/astaxie/beego"
	"github.com/astaxie/beego/orm"
)

func GetMatrixData() (adspaceMap map[string]AdspaceData, adspaceDemandMap map[string][]int, err error) {
	o := orm.NewOrm()

	sql := "select matrix.pmp_adspace_id, adspace.pmp_adspace_key, matrix.demand_id as demand_id,demand.demand_adspace_key as demand_adspace_key,demand.secret_key as demand_adspace_secret from pmp_adspace_matrix as matrix inner join pmp_adspace as adspace on matrix.pmp_adspace_id=adspace.id inner join pmp_demand_adspace as demand on matrix.demand_adspace_id=demand.id order by adspace.pmp_adspace_key,matrix.priority"

	var dataList []PmpAdplaceInfo

	_, err = o.Raw(sql).QueryRows(&dataList)

	if err != nil {
		return nil, nil, err
	}

	var oldAdspaceKey string
	var pmpDemandInfo *PmpDemandInfo

	//key:<adspace_key>_<demand_id>; value:<demand_adspace_key>,<demand_secret_key>
	adspaceMap = make(map[string]AdspaceData)

	//key:<adspace_key>; value:<demand_id1>,<demand_id2>...
	adspaceDemandMap = make(map[string][]int)

	for _, record := range dataList {
		adspaceData := AdspaceData{AdspaceKey: record.DemandAdspaceKey}
		adspaceData.SecretKey = record.DemandSecretKey
		adspaceMap[record.PmpAdspaceKey+"_"+lib.ConvertIntToString(record.DemandId)] = adspaceData

		if oldAdspaceKey != record.PmpAdspaceKey {
			oldAdspaceKey = record.PmpAdspaceKey

			if pmpDemandInfo != nil {
				demandIds := pmpDemandInfo.GetDemandIds()
				adspaceDemandMap[pmpDemandInfo.AdspaceKey] = demandIds
			}
			pmpDemandInfo = new(PmpDemandInfo)
			pmpDemandInfo.InitDemand()
			pmpDemandInfo.AdspaceKey = record.PmpAdspaceKey
			pmpDemandInfo.AddDemand(record.DemandId)
		} else {
			pmpDemandInfo.AddDemand(record.DemandId)
		}
	}

	demandIds := pmpDemandInfo.GetDemandIds()
	adspaceDemandMap[pmpDemandInfo.AdspaceKey] = demandIds

	return adspaceMap, adspaceDemandMap, err
}

func GetDemandInfo() (demandMap map[int]DemandInfo, err error) {
	o := orm.NewOrm()

	sql := "select id as demand_id, request_url_template, name, timeout, invoke_func_name from pmp_demand_platform_desk"

	var dataList []DemandInfo

	_, err = o.Raw(sql).QueryRows(&dataList)

	if err != nil {
		return nil, err
	}

	demandMap = make(map[int]DemandInfo)

	for _, record := range dataList {
		demandMap[record.DemandId] = record
	}

	return demandMap, nil
}

//todo
func validUrl(url string) bool {
	return true
}

//adDate: 2006-01-02
func GetAvbDemandMap(adDate string) (avbDemandMap map[string]*AvbDemand, err error) {
	o := orm.NewOrm()

	beego.Debug("Start update demand daily report")

	var records []*AvbDemand
	sql := "select allocation.id as allocation_id,allocation.pmp_adspace_id, allocation.demand_adspace_id, pmp.pmp_adspace_key,demand.demand_adspace_key,allocation.imp as plan_imp, allocation.clk as plan_clk,report.imp as actual_imp, report.clk as actual_clk from pmp_daily_allocation as allocation left join pmp_daily_report as report on allocation.ad_date=report.ad_date and allocation.pmp_adspace_id=report.pmp_adspace_id and allocation.demand_adspace_id=report.demand_adspace_id inner join pmp_adspace as pmp on allocation.pmp_adspace_id=pmp.id inner join pmp_demand_adspace as demand on allocation.demand_adspace_id=demand.id where allocation.ad_date=?"

	paramList := []interface{}{adDate}

	_, err = o.Raw(sql, paramList).QueryRows(&records)

	if err != nil {
		beego.Critical(err.Error())
		return
	}

	sql = "select targeting_type, targeting_code, plan_imp, plan_clk, actual_imp, actual_clk from pmp_daily_allocation_detail where allocation_id=? and targeting_type in ('PROVINCE','CITY') "

	avbDemandMap = make(map[string]*AvbDemand)

	for _, record := range records {
		var detailList []*AllocationDetail
		paramList = []interface{}{record.AllocationId}
		_, err = o.Raw(sql, paramList).QueryRows(&detailList)
		if err != nil {
			beego.Critical(err.Error())
			continue
		}

		if detailList != nil && len(detailList) > 0 {
			for _, detail := range detailList {
				record.SetDetailAllocation(detail)
			}
		}

		avbDemandMap[record.PmpAdspaceKey+"_"+record.DemandAdspaceKey] = record
		//if record.PlanImp > record.ActualImp {
		//	avbDemandMap[record.PmpAdspaceKey+"_"+record.DemandAdspaceKey] = true
		//}
	}

	return avbDemandMap, err
}

func GetPmpInfo() (pmpAdspaceMap map[string]PmpInfo, err error) {
	o := orm.NewOrm()

	sql := "select pmp_adspace_key, creative_type from pmp_adspace where status=0"

	var dataList []PmpInfo

	_, err = o.Raw(sql).QueryRows(&dataList)

	if err != nil {
		beego.Critical(err.Error())
		return
	}

	pmpAdspaceMap = make(map[string]PmpInfo)

	for _, record := range dataList {
		pmpAdspaceMap[record.PmpAdspaceKey] = record
	}

	return
}
<commit_msg>fix an sql issue for demand secret key<commit_after>package models

import (
	"adexchange/lib"
	"github.com/astaxie/beego"
	"github.com/astaxie/beego/orm"
)

func GetMatrixData() (adspaceMap map[string]AdspaceData, adspaceDemandMap map[string][]int, err error) {
	o := orm.NewOrm()

	sql := "select matrix.pmp_adspace_id, adspace.pmp_adspace_key, matrix.demand_id as demand_id,demand.demand_adspace_key as demand_adspace_key,demand.secret_key as demand_secret_key from pmp_adspace_matrix as matrix inner join pmp_adspace as adspace on matrix.pmp_adspace_id=adspace.id inner join pmp_demand_adspace as demand on matrix.demand_adspace_id=demand.id order by adspace.pmp_adspace_key,matrix.priority"

	var dataList []PmpAdplaceInfo

	_, err = o.Raw(sql).QueryRows(&dataList)

	if err != nil {
		return nil, nil, err
	}

	var oldAdspaceKey string
	var pmpDemandInfo *PmpDemandInfo

	//key:<adspace_key>_<demand_id>; value:<demand_adspace_key>,<demand_secret_key>
	adspaceMap = make(map[string]AdspaceData)

	//key:<adspace_key>; value:<demand_id1>,<demand_id2>...
	adspaceDemandMap = make(map[string][]int)

	for _, record := range dataList {
		adspaceData := AdspaceData{AdspaceKey: record.DemandAdspaceKey}
		adspaceData.SecretKey = record.DemandSecretKey
		adspaceMap[record.PmpAdspaceKey+"_"+lib.ConvertIntToString(record.DemandId)] = adspaceData

		if oldAdspaceKey != record.PmpAdspaceKey {
			oldAdspaceKey = record.PmpAdspaceKey

			if pmpDemandInfo != nil {
				demandIds := pmpDemandInfo.GetDemandIds()
				adspaceDemandMap[pmpDemandInfo.AdspaceKey] = demandIds
			}
			pmpDemandInfo = new(PmpDemandInfo)
			pmpDemandInfo.InitDemand()
			pmpDemandInfo.AdspaceKey = record.PmpAdspaceKey
			pmpDemandInfo.AddDemand(record.DemandId)
		} else {
			pmpDemandInfo.AddDemand(record.DemandId)
		}
	}

	demandIds := pmpDemandInfo.GetDemandIds()
	adspaceDemandMap[pmpDemandInfo.AdspaceKey] = demandIds

	return adspaceMap, adspaceDemandMap, err
}

func GetDemandInfo() (demandMap map[int]DemandInfo, err error) {
	o := orm.NewOrm()

	sql := "select id as demand_id, request_url_template, name, timeout, invoke_func_name from pmp_demand_platform_desk"

	var dataList []DemandInfo

	_, err = o.Raw(sql).QueryRows(&dataList)

	if err != nil {
		return nil, err
	}

	demandMap = make(map[int]DemandInfo)

	for _, record := range dataList {
		demandMap[record.DemandId] = record
	}

	return demandMap, nil
}

//todo
func validUrl(url string) bool {
	return true
}

//adDate: 2006-01-02
func GetAvbDemandMap(adDate string) (avbDemandMap map[string]*AvbDemand, err error) {
	o := orm.NewOrm()

	beego.Debug("Start update demand daily report")

	var records []*AvbDemand
	sql := "select allocation.id as allocation_id,allocation.pmp_adspace_id, allocation.demand_adspace_id, pmp.pmp_adspace_key,demand.demand_adspace_key,allocation.imp as plan_imp, allocation.clk as plan_clk,report.imp as actual_imp, report.clk as actual_clk from pmp_daily_allocation as allocation left join pmp_daily_report as report on allocation.ad_date=report.ad_date and allocation.pmp_adspace_id=report.pmp_adspace_id and allocation.demand_adspace_id=report.demand_adspace_id inner join pmp_adspace as pmp on allocation.pmp_adspace_id=pmp.id inner join pmp_demand_adspace as demand on allocation.demand_adspace_id=demand.id where allocation.ad_date=?"

	paramList := []interface{}{adDate}

	_, err = o.Raw(sql, paramList).QueryRows(&records)

	if err != nil {
		beego.Critical(err.Error())
		return
	}

	sql = "select targeting_type, targeting_code, plan_imp, plan_clk, actual_imp, actual_clk from pmp_daily_allocation_detail where allocation_id=? and targeting_type in ('PROVINCE','CITY') "

	avbDemandMap = make(map[string]*AvbDemand)

	for _, record := range records {
		var detailList []*AllocationDetail
		paramList = []interface{}{record.AllocationId}
		_, err = o.Raw(sql, paramList).QueryRows(&detailList)
		if err != nil {
			beego.Critical(err.Error())
			continue
		}

		if detailList != nil && len(detailList) > 0 {
			for _, detail := range detailList {
				record.SetDetailAllocation(detail)
			}
		}

		avbDemandMap[record.PmpAdspaceKey+"_"+record.DemandAdspaceKey] = record
		//if record.PlanImp > record.ActualImp {
		//	avbDemandMap[record.PmpAdspaceKey+"_"+record.DemandAdspaceKey] = true
		//}
	}

	return avbDemandMap, err
}

func GetPmpInfo() (pmpAdspaceMap map[string]PmpInfo, err error) {
	o := orm.NewOrm()

	sql := "select pmp_adspace_key, creative_type from pmp_adspace where status=0"

	var dataList []PmpInfo

	_, err = o.Raw(sql).QueryRows(&dataList)

	if err != nil {
		beego.Critical(err.Error())
		return
	}

	pmpAdspaceMap = make(map[string]PmpInfo)

	for _, record := range dataList {
		pmpAdspaceMap[record.PmpAdspaceKey] = record
	}

	return
}
<|endoftext|>


<commit_before>/**
 * Copyright (c) Mainflux
 *
 * Mainflux server is licensed under an Apache license, version 2.0.
 * All rights not explicitly granted in the Apache license, version 2.0 are reserved.
 * See the included LICENSE file for more details.
 */

package models

type (
	DeviceLocation struct {
		Name      string `json:"name"`
		Latitude  int    `json:"latitude"`
		Longitude int    `json:"longitude"`
		Elevation int    `json:"elevation"`
	}

	Device struct {
		Id   string `json:"id"`
		Name string `json:"name"`

		Description string         `json:"description"`
		Visibility  string         `json:"visibility"`
		Status      string         `json:"status"`
		Tags        []string       `json:"tags"`
		Location    DeviceLocation `json:"location"`

		Created string `json:"created"`
		Updated string `json:"updated"`

		Metadata  map[string]interface{} `json:"metadata"`
	}
)
<commit_msg>Added `service` field. Simplified `device` model.<commit_after>/**
 * Copyright (c) Mainflux
 *
 * Mainflux server is licensed under an Apache license, version 2.0.
 * All rights not explicitly granted in the Apache license, version 2.0 are reserved.
 * See the included LICENSE file for more details.
 */

package models

type (
	Device struct {
		Id   string `json:"id"`
		Name string `json:"name"`

		Description		string  `json:"description"`

		// Service (gateway) to which this device belongs to
		// If device connects directly to Mainflux, use `main` (default)
		Service			string	`json:"service"`

		Online			bool	`json:"online"`
		ConnectedAt		string	`json:"connected_at"`
		DisonnectedAt	string	`json:"disconnected_at"`

		Channels []Channel `json:"channels"`

		Created string `json:"created"`
		Updated string `json:"updated"`

		Metadata  map[string]interface{} `json:"metadata"`
	}
)
<|endoftext|>


<commit_before>package models

import (
	"net/http"
	"time"

	"github.com/NyaaPantsu/nyaa/config"
)

// TorrentReport model
// User can be null (anonymous reports)
// FIXME  can't preload field Torrents for models.TorrentReport
type TorrentReport struct {
	ID 	        uint   `gorm:"column:torrent_report_id;primary_key"`
	Description string `gorm:"column:type"`
	Message     string `gorm:"column:message"`
	TorrentID   uint   `gorm:"column:torrent_id"`
	UserID      uint   `gorm:"column:user_id"`

	CreatedAt time.Time `gorm:"column:created_at"`

	Torrent *Torrent `gorm:"AssociationForeignKey:TorrentID;ForeignKey:torrent_id"`
	User    *User    `gorm:"AssociationForeignKey:UserID;ForeignKey:user_id"`
}

// TableName : Return the name of torrent report table
func (report TorrentReport) TableName() string {
	return config.Get().Models.ReportsTableName
}

// TorrentReportJSON : Json struct of torrent report model
type TorrentReportJSON struct {
	ID          uint        `json:"id"`
	Description string      `json:"description"`
	Message     string      `json:"message"`
	Torrent     TorrentJSON `json:"torrent"`
	User        UserJSON    `json:"user"`
}

// ToJSON : conversion to json of a torrent report
func (report *TorrentReport) ToJSON() TorrentReportJSON {
	t := TorrentJSON{}
	if report.Torrent != nil { // FIXME: report.Torrent should never be nil
		t = report.Torrent.ToJSON()
	}
	u := UserJSON{}
	if report.User != nil {
		u = report.User.ToJSON()
	}
	json := TorrentReportJSON{report.ID, report.Description, report.Message, t, u}
	return json
}

// TorrentReportsToJSON : Conversion of multiple reports to json
func TorrentReportsToJSON(reports []TorrentReport) []TorrentReportJSON {
	json := make([]TorrentReportJSON, len(reports))
	for i := range reports {
		json[i] = reports[i].ToJSON()
	}
	return json
}

// Delete : Delete torrent report
func (report *TorrentReport) Delete(definitely bool) (int, error) {
	if definitely {
		return 0, ORM.Unscoped().Delete(report).Error
	}
	return http.StatusOK, nil
}
<commit_msg>Update report.go<commit_after>package models

import (
	"net/http"
	"time"

	"github.com/NyaaPantsu/nyaa/config"
)

// TorrentReport model
// User can be null (anonymous reports)
// FIXME  can't preload field Torrents for models.TorrentReport
type TorrentReport struct {
	ID 	        uint   `gorm:"column:torrent_report_id;primary_key"`
	Description string `gorm:"column:type"`
	Message     string `gorm:"column:message"`
	TorrentID   uint   `gorm:"column:torrent_id"`
	UserID      uint   `gorm:"column:user_id"`

	CreatedAt time.Time `gorm:"column:created_at"`

	Torrent *Torrent `gorm:"AssociationForeignKey:TorrentID;ForeignKey:torrent_id"`
	User    *User    `gorm:"AssociationForeignKey:UserID;ForeignKey:user_id"`
}

// TableName : Return the name of torrent report table
func (report TorrentReport) TableName() string {
	return config.Get().Models.ReportsTableName
}

// TorrentReportJSON : Json struct of torrent report model
type TorrentReportJSON struct {
	ID          uint        `json:"id"`
	Description string      `json:"description"`
	Message     string      `json:"message"`
	Torrent     TorrentJSON `json:"torrent"`
	User        UserJSON    `json:"user"`
}

// ToJSON : conversion to json of a torrent report
func (report *TorrentReport) ToJSON() TorrentReportJSON {
	t := TorrentJSON{}
	if report.Torrent != nil { // FIXME: report.Torrent should never be nil
		t = report.Torrent.ToJSON()
	}
	u := UserJSON{}
	if report.User != nil {
		u = report.User.ToJSON()
	}
	json := TorrentReportJSON{report.ID, report.Description, report.Message, t, u}
	return json
}

// TorrentReportsToJSON : Conversion of multiple reports to json
func TorrentReportsToJSON(reports []TorrentReport) []TorrentReportJSON {
	json := make([]TorrentReportJSON, len(reports))
	for i := range reports {
		json[i] = reports[i].ToJSON()
	}
	return json
}

// Delete : Delete torrent report
func (report *TorrentReport) Delete() (int, error) {
	return http.StatusOK, ORM.Unscoped().Delete(report).Error
}
<|endoftext|>


<commit_before>package irc

import (
	"bufio"
	"log"
	"net"
)

const delim byte = '\n'

var endline = []byte("\r\n")

type Connection struct {
	Network  string
	Input    chan Message
	Output   chan Message
	Reader   *bufio.Reader
	Writer   *bufio.Writer
	QuitSend chan struct{}
	QuitRecv chan struct{}
}

func (c *Connection) Sender() {
	for {
		select {
		case msg := <-c.Input:
			c.Writer.WriteString(msg.String())
            log.Println(c.Network, "-->", msg.String())
		case <-c.QuitSend:
			log.Println(c.Network, "closing Sender")
			close(c.Input)
			close(c.QuitSend)
			return
		}
	}
}

func (c *Connection) Receiver() {
	for {
		raw, err := c.Reader.ReadString(delim)
		if err != nil {
			log.Println(c.Network, "error reading message", err.Error())
		}
		msg, err := ParseMessage(raw)
		if err != nil {
			log.Println(c.Network, "error decoding message", err.Error())
		}
		select {
		case c.Output <- *msg:
            log.Println(c.Network, "<--", msg.String())
		case <-c.QuitRecv:
			log.Println(c.Network, "closing receiver")
			close(c.Output)
			close(c.QuitRecv)
			return
		}
	}
}

func (c *Connection) Dial(server string) error {

	conn, err := net.Dial("tcp", server)
	if err != nil {
		log.Println(c.Network, "Cannot connect to", server, "error:", err.Error())
		return err
	}
	log.Println(c.Network, "Connected to", server)
	c.Writer = bufio.NewWriter(conn)
	log.Println(c.Network, "Spawned bufio writer")
	c.Reader = bufio.NewReader(conn)
	log.Println(c.Network, "Spawned bufio reader")

	go c.Sender()
	go c.Receiver()

	return nil
}
<commit_msg>Receiver() is hosered and does a nil pointer dereference…<commit_after>package irc

import (
	"bufio"
	"log"
	"net"
)

const delim byte = '\n'

var endline = []byte("\r\n")

type Connection struct {
	Network  string
	Input    chan Message
	Output   chan Message
	Reader   *bufio.Reader
	Writer   *bufio.Writer
	QuitSend chan struct{}
	QuitRecv chan struct{}
}

func (c *Connection) Sender() {
	for {
		select {
		case msg := <-c.Input:
			c.Writer.WriteString(msg.String())
            log.Println(c.Network, "-->", msg.String())
		case <-c.QuitSend:
			log.Println(c.Network, "closing Sender")
			close(c.Input)
			close(c.QuitSend)
			return
		}
	}
}

func (c *Connection) Receiver() {
	for {
		raw, err := c.Reader.ReadString(delim)
		if err != nil {
			log.Println(c.Network, "error reading message", err.Error())
		}
        log.Println(c.Network, "<-- RAW", raw)
		msg, err := ParseMessage(raw)
		if err != nil {
			log.Println(c.Network, "error decoding message", err.Error())
		}
		select {
		case c.Output <- *msg:
            log.Println(c.Network, "<--", msg.String())
		case <-c.QuitRecv:
			log.Println(c.Network, "closing receiver")
			close(c.Output)
			close(c.QuitRecv)
			return
		}
	}
}

func (c *Connection) Dial(server string) error {

	conn, err := net.Dial("tcp", server)
	if err != nil {
		log.Println(c.Network, "Cannot connect to", server, "error:", err.Error())
		return err
	}
	log.Println(c.Network, "Connected to", server)
	c.Writer = bufio.NewWriter(conn)
	log.Println(c.Network, "Spawned bufio writer")
	c.Reader = bufio.NewReader(conn)
	log.Println(c.Network, "Spawned bufio reader")

	go c.Sender()
	go c.Receiver()

	return nil
}
<|endoftext|>


<commit_before>package irc

import (
	"bufio"
	"log"
	"math/rand"
	"net"
	"sync"
	"time"
)

const delim byte = '\n'
const endline string = "\r\n"

type Connection struct {
	Network   string
	Nick      string
	User      string
	RealName  string
	Input     chan Message
	Output    chan Message
	Reader    *bufio.Reader
	Writer    *bufio.Writer
	conn      net.Conn
	Reconnect chan struct{}
	Quit      chan struct{}
	QuitSend  chan struct{}
	QuitRecv  chan struct{}
	L sync.Mutex
}

func (c *Connection) Sender() {
	log.Println(c.Network, "spawned Sender")
	for {
		select {
		case msg := <-c.Input:
			c.Writer.WriteString(msg.String() + endline)
			log.Println(c.Network, "-->", msg.String())
			c.Writer.Flush()
		case <-c.QuitSend:
			log.Println(c.Network, "closing Sender")
			return
		}
	}
}

func (c *Connection) Receiver() {
	log.Println(c.Network, "spawned Receiver")
	for {
		raw, err := c.Reader.ReadString(delim)
		if err != nil {
			log.Println(c.Network, "error reading message", err.Error())
			log.Println(c.Network, "closing Receiver")
			c.Quit <- struct{}{}
			log.Println(c.Network, "sent quit message from Receiver")
			return
		}
		msg, err := ParseMessage(raw)
		if err != nil {
			log.Println(c.Network, "error decoding message", err.Error())
			log.Println(c.Network, "closing Receiver")
			c.Quit <- struct{}{}
			log.Println(c.Network, "sent quit message from Receiver")
			return
		} else {
			log.Println(c.Network, "<--", msg.String())
		}
		select {
		case c.Output <- *msg:
		case <-c.QuitRecv:
			log.Println(c.Network, "closing Receiver")
			return
		}
	}
}

func (c *Connection) Cleaner() {
	log.Println(c.Network, "spawned Cleaner")
	for {
		<-c.Quit
		log.Println(c.Network, "ceceived quit message")
		c.L.Lock()
		log.Println(c.Network, "cleaning up!")
		c.QuitSend <- struct{}{}
		c.QuitRecv <- struct{}{}
		c.Reconnect <- struct{}{}
		c.conn.Close()
		log.Println(c.Network, "closing Cleaner")
		c.L.Unlock()
	}
}

func (c *Connection) Keeper(servers []string) {
	log.Println(c.Network, "spawned Keeper")
	for {
		<-c.Reconnect
		c.L.Lock()
		if c.Input != nil {
			close(c.Input)
			close(c.Output)
			close(c.QuitSend)
			close(c.QuitRecv)
		}
		c.Input = make(chan Message, 1)
		c.Output = make(chan Message, 1)
		c.QuitSend = make(chan struct{}, 1)
		c.QuitRecv = make(chan struct{}, 1)
		server := servers[rand.Intn(len(servers))]
		log.Println(c.Network, "connecting to", server)
		c.Dial(server)
		c.L.Unlock()

		go c.Sender()
		go c.Receiver()

		log.Println(c.Network, "Initializing IRC connection")
		c.Input <- Message{
			Command:  "NICK",
			Trailing: c.Nick,
		}
		c.Input <- Message{
			Command:  "USER",
			Params:   []string{c.User, "0", "*"},
			Trailing: c.RealName,
		}

	}
}

func (c *Connection) Setup(network string, servers []string, nick string, user string, realname string) {
	rand.Seed(time.Now().UnixNano())

	c.Reconnect = make(chan struct{}, 1)
	c.Quit = make(chan struct{}, 1)
	c.Nick = nick
	c.User = user
	c.RealName = realname
	c.Network = network

	c.Reconnect <- struct{}{}
	go c.Keeper(servers)
	go c.Cleaner()
	return
}

func (c *Connection) Dial(server string) error {

	conn, err := net.Dial("tcp", server)
	if err != nil {
		log.Println(c.Network, "Cannot connect to", server, "error:", err.Error())
		return err
	}
	log.Println(c.Network, "Connected to", server)
	c.Writer = bufio.NewWriter(conn)
	c.Reader = bufio.NewReader(conn)
	c.conn = conn

	return nil
}
<commit_msg>Most of these fields don't need to be public anyway<commit_after>package irc

import (
	"bufio"
	"log"
	"math/rand"
	"net"
	"sync"
	"time"
)

const delim byte = '\n'
const endline string = "\r\n"

type Connection struct {
	Network   string
	Nick      string
	User      string
	RealName  string
	Input     chan Message
	Output    chan Message
	reader    *bufio.Reader
	writer    *bufio.Writer
	conn      net.Conn
	reconnect chan struct{}
	Quit      chan struct{}
	quitsend  chan struct{}
	quitrecv  chan struct{}
	l         sync.Mutex
}

func (c *Connection) Sender() {
	log.Println(c.Network, "spawned Sender")
	for {
		select {
		case msg := <-c.Input:
			c.writer.WriteString(msg.String() + endline)
			log.Println(c.Network, "-->", msg.String())
			c.writer.Flush()
		case <-c.quitsend:
			log.Println(c.Network, "closing Sender")
			return
		}
	}
}

func (c *Connection) Receiver() {
	log.Println(c.Network, "spawned Receiver")
	for {
		raw, err := c.reader.ReadString(delim)
		if err != nil {
			log.Println(c.Network, "error reading message", err.Error())
			log.Println(c.Network, "closing Receiver")
			c.Quit <- struct{}{}
			log.Println(c.Network, "sent quit message from Receiver")
			return
		}
		msg, err := ParseMessage(raw)
		if err != nil {
			log.Println(c.Network, "error decoding message", err.Error())
			log.Println(c.Network, "closing Receiver")
			c.Quit <- struct{}{}
			log.Println(c.Network, "sent quit message from Receiver")
			return
		} else {
			log.Println(c.Network, "<--", msg.String())
		}
		select {
		case c.Output <- *msg:
		case <-c.quitrecv:
			log.Println(c.Network, "closing Receiver")
			return
		}
	}
}

func (c *Connection) Cleaner() {
	log.Println(c.Network, "spawned Cleaner")
	for {
		<-c.Quit
		log.Println(c.Network, "ceceived quit message")
		c.l.Lock()
		log.Println(c.Network, "cleaning up!")
		c.quitsend <- struct{}{}
		c.quitrecv <- struct{}{}
		c.reconnect <- struct{}{}
		c.conn.Close()
		log.Println(c.Network, "closing Cleaner")
		c.l.Unlock()
	}
}

func (c *Connection) Keeper(servers []string) {
	log.Println(c.Network, "spawned Keeper")
	for {
		<-c.reconnect
		c.l.Lock()
		if c.Input != nil {
			close(c.Input)
			close(c.Output)
			close(c.quitsend)
			close(c.quitrecv)
		}
		c.Input = make(chan Message, 1)
		c.Output = make(chan Message, 1)
		c.quitsend = make(chan struct{}, 1)
		c.quitrecv = make(chan struct{}, 1)
		server := servers[rand.Intn(len(servers))]
		log.Println(c.Network, "connecting to", server)
		c.Dial(server)
		c.l.Unlock()

		go c.Sender()
		go c.Receiver()

		log.Println(c.Network, "Initializing IRC connection")
		c.Input <- Message{
			Command:  "NICK",
			Trailing: c.Nick,
		}
		c.Input <- Message{
			Command:  "USER",
			Params:   []string{c.User, "0", "*"},
			Trailing: c.RealName,
		}

	}
}

func (c *Connection) Setup(network string, servers []string, nick string, user string, realname string) {
	rand.Seed(time.Now().UnixNano())

	c.reconnect = make(chan struct{}, 1)
	c.Quit = make(chan struct{}, 1)
	c.Nick = nick
	c.User = user
	c.RealName = realname
	c.Network = network

	c.reconnect <- struct{}{}
	go c.Keeper(servers)
	go c.Cleaner()
	return
}

func (c *Connection) Dial(server string) error {

	conn, err := net.Dial("tcp", server)
	if err != nil {
		log.Println(c.Network, "Cannot connect to", server, "error:", err.Error())
		return err
	}
	log.Println(c.Network, "Connected to", server)
	c.writer = bufio.NewWriter(conn)
	c.reader = bufio.NewReader(conn)
	c.conn = conn

	return nil
}
<|endoftext|>


<commit_before>/*
Copyright 2019 The Vitess Authors.

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

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

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

package cluster

import (
	"fmt"
	"io/ioutil"
	"net/http"
	"os"
	"os/exec"
	"path"
	"strings"
	"syscall"
	"time"

	"vitess.io/vitess/go/vt/log"
)

// TopoProcess is a generic handle for a running Topo service .
// It can be spawned manually
type TopoProcess struct {
	Name               string
	Binary             string
	DataDirectory      string
	LogDirectory       string
	ListenClientURL    string
	AdvertiseClientURL string
	Port               int
	Host               string
	VerifyURL          string
	PeerURL            string
	ZKPorts            string

	proc *exec.Cmd
	exit chan error
}

// Setup starts a new topo service
func (topo *TopoProcess) Setup(topoFlavor string, cluster *LocalProcessCluster) (err error) {
	switch topoFlavor {
	case "zk2":
		return topo.SetupZookeeper(cluster)
	case "consul":
		return topo.SetupConsul(cluster)
	default:
		return topo.SetupEtcd()
	}
}

// SetupEtcd spawns a new etcd service and initializes it with the defaults.
// The service is kept running in the background until TearDown() is called.
func (topo *TopoProcess) SetupEtcd() (err error) {
	topo.proc = exec.Command(
		topo.Binary,
		"--name", topo.Name,
		"--data-dir", topo.DataDirectory,
		"--listen-client-urls", topo.ListenClientURL,
		"--advertise-client-urls", topo.AdvertiseClientURL,
		"--initial-advertise-peer-urls", topo.PeerURL,
		"--listen-peer-urls", topo.PeerURL,
		"--initial-cluster", fmt.Sprintf("%s=%s", topo.Name, topo.PeerURL),
		"--enable-v2=true",
	)

	err = createDirectory(topo.DataDirectory, 0700)
	if err != nil && !os.IsExist(err) {
		return err
	}
	errFile, err := os.Create(path.Join(topo.DataDirectory, "topo-stderr.txt"))
	if err != nil {
		return err
	}

	topo.proc.Stderr = errFile

	topo.proc.Env = append(topo.proc.Env, os.Environ()...)

	log.Errorf("Starting etcd with command: %v", strings.Join(topo.proc.Args, " "))

	err = topo.proc.Start()
	if err != nil {
		return
	}

	topo.exit = make(chan error)
	go func() {
		topo.exit <- topo.proc.Wait()
	}()

	timeout := time.Now().Add(60 * time.Second)
	for time.Now().Before(timeout) {
		if topo.IsHealthy() {
			return
		}
		select {
		case err := <-topo.exit:
			return fmt.Errorf("process '%s' exited prematurely (err: %s)", topo.Binary, err)
		default:
			time.Sleep(300 * time.Millisecond)
		}
	}

	return fmt.Errorf("process '%s' timed out after 60s (err: %s)", topo.Binary, <-topo.exit)
}

// SetupZookeeper spawns a new zookeeper topo service and initializes it with the defaults.
// The service is kept running in the background until TearDown() is called.
func (topo *TopoProcess) SetupZookeeper(cluster *LocalProcessCluster) (err error) {

	host, err := os.Hostname()
	if err != nil {
		return
	}

	topo.ZKPorts = fmt.Sprintf("%d:%d:%d", cluster.GetAndReservePort(), cluster.GetAndReservePort(), topo.Port)

	topo.proc = exec.Command(
		topo.Binary,
		"-log_dir", topo.LogDirectory,
		"-zk.cfg", fmt.Sprintf("1@%v:%s", host, topo.ZKPorts),
		"init",
	)

	errFile, _ := os.Create(path.Join(topo.DataDirectory, "topo-stderr.txt"))
	topo.proc.Stderr = errFile
	topo.proc.Env = append(topo.proc.Env, os.Environ()...)

	log.Infof("Starting zookeeper with args %v", strings.Join(topo.proc.Args, " "))
	err = topo.proc.Run()
	if err != nil {
		return
	}
	return
}

// SetupConsul spawns a new consul service and initializes it with the defaults.
// The service is kept running in the background until TearDown() is called.
func (topo *TopoProcess) SetupConsul(cluster *LocalProcessCluster) (err error) {

	topo.VerifyURL = fmt.Sprintf("http://%s:%d/v1/kv/?keys", topo.Host, topo.Port)

	configFile := path.Join(os.Getenv("VTDATAROOT"), "consul.json")

	config := fmt.Sprintf(`{"ports":{"dns":%d,"http":%d,"serf_lan":%d,"serf_wan":%d}}`,
		cluster.GetAndReservePort(), topo.Port, cluster.GetAndReservePort(), cluster.GetAndReservePort())

	err = ioutil.WriteFile(configFile, []byte(config), 0666)
	if err != nil {
		return
	}

	topo.proc = exec.Command(
		topo.Binary, "agent",
		"-dev",
		"-config-file", configFile,
	)

	errFile, _ := os.Create(path.Join(topo.DataDirectory, "topo-stderr.txt"))
	topo.proc.Stderr = errFile

	topo.proc.Env = append(topo.proc.Env, os.Environ()...)

	log.Infof("Starting consul with args %v", strings.Join(topo.proc.Args, " "))
	err = topo.proc.Start()
	if err != nil {
		return
	}

	topo.exit = make(chan error)
	go func() {
		topo.exit <- topo.proc.Wait()
	}()

	timeout := time.Now().Add(60 * time.Second)
	for time.Now().Before(timeout) {
		if topo.IsHealthy() {
			return
		}
		select {
		case err := <-topo.exit:
			return fmt.Errorf("process '%s' exited prematurely (err: %s)", topo.Binary, err)
		default:
			time.Sleep(300 * time.Millisecond)
		}
	}

	return fmt.Errorf("process '%s' timed out after 60s (err: %s)", topo.Binary, <-topo.exit)
}

// TearDown shutdowns the running topo service
func (topo *TopoProcess) TearDown(Cell string, originalVtRoot string, currentRoot string, keepdata bool, topoFlavor string) error {

	if topoFlavor == "zk2" {
		cmd := "shutdown"
		if keepdata {
			cmd = "teardown"
		}
		topo.proc = exec.Command(
			topo.Binary,
			"-log_dir", topo.LogDirectory,
			"-zk.cfg", fmt.Sprintf("1@%v:%s", topo.Host, topo.ZKPorts),
			cmd,
		)

		err := topo.proc.Run()
		if err != nil {
			return err
		}
	} else {
		if topo.proc == nil || topo.exit == nil {
			return nil
		}

		topo.removeTopoDirectories(Cell)

		// Attempt graceful shutdown with SIGTERM first
		_ = topo.proc.Process.Signal(syscall.SIGTERM)

		if !*keepData {
			_ = os.RemoveAll(topo.DataDirectory)
			_ = os.RemoveAll(currentRoot)
		}
		_ = os.Setenv("VTDATAROOT", originalVtRoot)

		select {
		case <-topo.exit:
			topo.proc = nil
			return nil

		case <-time.After(10 * time.Second):
			topo.proc.Process.Kill()
			topo.proc = nil
			return <-topo.exit
		}
	}

	return nil
}

// IsHealthy function checks if topo server is up and running
func (topo *TopoProcess) IsHealthy() bool {
	resp, err := http.Get(topo.VerifyURL)
	if err != nil {
		return false
	}
	if resp.StatusCode == 200 {
		return true
	}
	return false
}

func (topo *TopoProcess) removeTopoDirectories(Cell string) {
	_ = topo.ManageTopoDir("rmdir", "/vitess/global")
	_ = topo.ManageTopoDir("rmdir", "/vitess/"+Cell)
}

// ManageTopoDir creates global and zone in etcd2
func (topo *TopoProcess) ManageTopoDir(command string, directory string) (err error) {
	url := topo.VerifyURL + directory
	payload := strings.NewReader(`{"dir":"true"}`)
	if command == "mkdir" {
		req, _ := http.NewRequest("PUT", url, payload)
		req.Header.Add("content-type", "application/json")
		_, err = http.DefaultClient.Do(req)
		return err
	} else if command == "rmdir" {
		req, _ := http.NewRequest("DELETE", url+"?dir=true", payload)
		_, err = http.DefaultClient.Do(req)
		return err
	} else {
		return nil
	}
}

// TopoProcessInstance returns a TopoProcess handle for a etcd sevice,
// configured with the given Config.
// The process must be manually started by calling setup()
func TopoProcessInstance(port int, peerPort int, hostname string, flavor string, name string) *TopoProcess {
	binary := "etcd"
	if flavor == "zk2" {
		binary = "zkctl"
	}
	if flavor == "consul" {
		binary = "consul"
	}

	topo := &TopoProcess{
		Name:   name,
		Binary: binary,
		Port:   port,
		Host:   hostname,
	}

	topo.AdvertiseClientURL = fmt.Sprintf("http://%s:%d", topo.Host, topo.Port)
	topo.ListenClientURL = fmt.Sprintf("http://%s:%d", topo.Host, topo.Port)
	topo.DataDirectory = path.Join(os.Getenv("VTDATAROOT"), fmt.Sprintf("%s_%d", "topo", port))
	topo.LogDirectory = path.Join(os.Getenv("VTDATAROOT"), fmt.Sprintf("%s_%d", "topo", port), "logs")
	topo.VerifyURL = fmt.Sprintf("http://%s:%d/v2/keys", topo.Host, topo.Port)
	topo.PeerURL = fmt.Sprintf("http://%s:%d", hostname, peerPort)
	return topo
}
<commit_msg>make sure to keep data even when topo server is deleted<commit_after>/*
Copyright 2019 The Vitess Authors.

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

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

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

package cluster

import (
	"fmt"
	"io/ioutil"
	"net/http"
	"os"
	"os/exec"
	"path"
	"strings"
	"syscall"
	"time"

	"vitess.io/vitess/go/vt/log"
)

// TopoProcess is a generic handle for a running Topo service .
// It can be spawned manually
type TopoProcess struct {
	Name               string
	Binary             string
	DataDirectory      string
	LogDirectory       string
	ListenClientURL    string
	AdvertiseClientURL string
	Port               int
	Host               string
	VerifyURL          string
	PeerURL            string
	ZKPorts            string

	proc *exec.Cmd
	exit chan error
}

// Setup starts a new topo service
func (topo *TopoProcess) Setup(topoFlavor string, cluster *LocalProcessCluster) (err error) {
	switch topoFlavor {
	case "zk2":
		return topo.SetupZookeeper(cluster)
	case "consul":
		return topo.SetupConsul(cluster)
	default:
		return topo.SetupEtcd()
	}
}

// SetupEtcd spawns a new etcd service and initializes it with the defaults.
// The service is kept running in the background until TearDown() is called.
func (topo *TopoProcess) SetupEtcd() (err error) {
	topo.proc = exec.Command(
		topo.Binary,
		"--name", topo.Name,
		"--data-dir", topo.DataDirectory,
		"--listen-client-urls", topo.ListenClientURL,
		"--advertise-client-urls", topo.AdvertiseClientURL,
		"--initial-advertise-peer-urls", topo.PeerURL,
		"--listen-peer-urls", topo.PeerURL,
		"--initial-cluster", fmt.Sprintf("%s=%s", topo.Name, topo.PeerURL),
		"--enable-v2=true",
	)

	err = createDirectory(topo.DataDirectory, 0700)
	if err != nil && !os.IsExist(err) {
		return err
	}
	errFile, err := os.Create(path.Join(topo.DataDirectory, "topo-stderr.txt"))
	if err != nil {
		return err
	}

	topo.proc.Stderr = errFile

	topo.proc.Env = append(topo.proc.Env, os.Environ()...)

	log.Errorf("Starting etcd with command: %v", strings.Join(topo.proc.Args, " "))

	err = topo.proc.Start()
	if err != nil {
		return
	}

	topo.exit = make(chan error)
	go func() {
		topo.exit <- topo.proc.Wait()
	}()

	timeout := time.Now().Add(60 * time.Second)
	for time.Now().Before(timeout) {
		if topo.IsHealthy() {
			return
		}
		select {
		case err := <-topo.exit:
			return fmt.Errorf("process '%s' exited prematurely (err: %s)", topo.Binary, err)
		default:
			time.Sleep(300 * time.Millisecond)
		}
	}

	return fmt.Errorf("process '%s' timed out after 60s (err: %s)", topo.Binary, <-topo.exit)
}

// SetupZookeeper spawns a new zookeeper topo service and initializes it with the defaults.
// The service is kept running in the background until TearDown() is called.
func (topo *TopoProcess) SetupZookeeper(cluster *LocalProcessCluster) (err error) {

	host, err := os.Hostname()
	if err != nil {
		return
	}

	topo.ZKPorts = fmt.Sprintf("%d:%d:%d", cluster.GetAndReservePort(), cluster.GetAndReservePort(), topo.Port)

	topo.proc = exec.Command(
		topo.Binary,
		"-log_dir", topo.LogDirectory,
		"-zk.cfg", fmt.Sprintf("1@%v:%s", host, topo.ZKPorts),
		"init",
	)

	errFile, _ := os.Create(path.Join(topo.DataDirectory, "topo-stderr.txt"))
	topo.proc.Stderr = errFile
	topo.proc.Env = append(topo.proc.Env, os.Environ()...)

	log.Infof("Starting zookeeper with args %v", strings.Join(topo.proc.Args, " "))
	err = topo.proc.Run()
	if err != nil {
		return
	}
	return
}

// SetupConsul spawns a new consul service and initializes it with the defaults.
// The service is kept running in the background until TearDown() is called.
func (topo *TopoProcess) SetupConsul(cluster *LocalProcessCluster) (err error) {

	topo.VerifyURL = fmt.Sprintf("http://%s:%d/v1/kv/?keys", topo.Host, topo.Port)

	configFile := path.Join(os.Getenv("VTDATAROOT"), "consul.json")

	config := fmt.Sprintf(`{"ports":{"dns":%d,"http":%d,"serf_lan":%d,"serf_wan":%d}}`,
		cluster.GetAndReservePort(), topo.Port, cluster.GetAndReservePort(), cluster.GetAndReservePort())

	err = ioutil.WriteFile(configFile, []byte(config), 0666)
	if err != nil {
		return
	}

	topo.proc = exec.Command(
		topo.Binary, "agent",
		"-dev",
		"-config-file", configFile,
	)

	errFile, _ := os.Create(path.Join(topo.DataDirectory, "topo-stderr.txt"))
	topo.proc.Stderr = errFile

	topo.proc.Env = append(topo.proc.Env, os.Environ()...)

	log.Infof("Starting consul with args %v", strings.Join(topo.proc.Args, " "))
	err = topo.proc.Start()
	if err != nil {
		return
	}

	topo.exit = make(chan error)
	go func() {
		topo.exit <- topo.proc.Wait()
	}()

	timeout := time.Now().Add(60 * time.Second)
	for time.Now().Before(timeout) {
		if topo.IsHealthy() {
			return
		}
		select {
		case err := <-topo.exit:
			return fmt.Errorf("process '%s' exited prematurely (err: %s)", topo.Binary, err)
		default:
			time.Sleep(300 * time.Millisecond)
		}
	}

	return fmt.Errorf("process '%s' timed out after 60s (err: %s)", topo.Binary, <-topo.exit)
}

// TearDown shutdowns the running topo service
func (topo *TopoProcess) TearDown(Cell string, originalVtRoot string, currentRoot string, keepdata bool, topoFlavor string) error {

	if topoFlavor == "zk2" {
		cmd := "shutdown"
		if keepdata {
			cmd = "teardown"
		}
		topo.proc = exec.Command(
			topo.Binary,
			"-log_dir", topo.LogDirectory,
			"-zk.cfg", fmt.Sprintf("1@%v:%s", topo.Host, topo.ZKPorts),
			cmd,
		)

		err := topo.proc.Run()
		if err != nil {
			return err
		}
	} else {
		if topo.proc == nil || topo.exit == nil {
			return nil
		}

		topo.removeTopoDirectories(Cell)

		// Attempt graceful shutdown with SIGTERM first
		_ = topo.proc.Process.Signal(syscall.SIGTERM)

		if !(*keepData || keepdata) {
			_ = os.RemoveAll(topo.DataDirectory)
			_ = os.RemoveAll(currentRoot)
		}
		_ = os.Setenv("VTDATAROOT", originalVtRoot)

		select {
		case <-topo.exit:
			topo.proc = nil
			return nil

		case <-time.After(10 * time.Second):
			topo.proc.Process.Kill()
			topo.proc = nil
			return <-topo.exit
		}
	}

	return nil
}

// IsHealthy function checks if topo server is up and running
func (topo *TopoProcess) IsHealthy() bool {
	resp, err := http.Get(topo.VerifyURL)
	if err != nil {
		return false
	}
	if resp.StatusCode == 200 {
		return true
	}
	return false
}

func (topo *TopoProcess) removeTopoDirectories(Cell string) {
	_ = topo.ManageTopoDir("rmdir", "/vitess/global")
	_ = topo.ManageTopoDir("rmdir", "/vitess/"+Cell)
}

// ManageTopoDir creates global and zone in etcd2
func (topo *TopoProcess) ManageTopoDir(command string, directory string) (err error) {
	url := topo.VerifyURL + directory
	payload := strings.NewReader(`{"dir":"true"}`)
	if command == "mkdir" {
		req, _ := http.NewRequest("PUT", url, payload)
		req.Header.Add("content-type", "application/json")
		_, err = http.DefaultClient.Do(req)
		return err
	} else if command == "rmdir" {
		req, _ := http.NewRequest("DELETE", url+"?dir=true", payload)
		_, err = http.DefaultClient.Do(req)
		return err
	} else {
		return nil
	}
}

// TopoProcessInstance returns a TopoProcess handle for a etcd sevice,
// configured with the given Config.
// The process must be manually started by calling setup()
func TopoProcessInstance(port int, peerPort int, hostname string, flavor string, name string) *TopoProcess {
	binary := "etcd"
	if flavor == "zk2" {
		binary = "zkctl"
	}
	if flavor == "consul" {
		binary = "consul"
	}

	topo := &TopoProcess{
		Name:   name,
		Binary: binary,
		Port:   port,
		Host:   hostname,
	}

	topo.AdvertiseClientURL = fmt.Sprintf("http://%s:%d", topo.Host, topo.Port)
	topo.ListenClientURL = fmt.Sprintf("http://%s:%d", topo.Host, topo.Port)
	topo.DataDirectory = path.Join(os.Getenv("VTDATAROOT"), fmt.Sprintf("%s_%d", "topo", port))
	topo.LogDirectory = path.Join(os.Getenv("VTDATAROOT"), fmt.Sprintf("%s_%d", "topo", port), "logs")
	topo.VerifyURL = fmt.Sprintf("http://%s:%d/v2/keys", topo.Host, topo.Port)
	topo.PeerURL = fmt.Sprintf("http://%s:%d", hostname, peerPort)
	return topo
}
<|endoftext|>


<commit_before>/*
Copyright 2019 The Vitess Authors.

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

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

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

package vtgate

import (
	"fmt"
	"io/ioutil"
	"os"
	"path"
	"strings"
	"syscall"
	"testing"
	"time"

	"github.com/stretchr/testify/assert"

	"vitess.io/vitess/go/trace"

	"context"

	"vitess.io/vitess/go/mysql"
	"vitess.io/vitess/go/sqltypes"
	querypb "vitess.io/vitess/go/vt/proto/query"
	"vitess.io/vitess/go/vt/tlstest"
)

type testHandler struct {
	lastConn *mysql.Conn
}

func (th *testHandler) NewConnection(c *mysql.Conn) {
	th.lastConn = c
}

func (th *testHandler) ConnectionClosed(c *mysql.Conn) {
}

func (th *testHandler) ComQuery(c *mysql.Conn, q string, callback func(*sqltypes.Result) error) error {
	return nil
}

func (th *testHandler) ComPrepare(c *mysql.Conn, q string, b map[string]*querypb.BindVariable) ([]*querypb.Field, error) {
	return nil, nil
}

func (th *testHandler) ComResetConnection(c *mysql.Conn) {
}

func (th *testHandler) ComStmtExecute(c *mysql.Conn, prepare *mysql.PrepareData, callback func(*sqltypes.Result) error) error {
	return nil
}

func (th *testHandler) WarningCount(c *mysql.Conn) uint16 {
	return 0
}

func TestConnectionUnixSocket(t *testing.T) {
	th := &testHandler{}

	authServer := newTestAuthServerStatic()

	// Use tmp file to reserve a path, remove it immediately, we only care about
	// name in this context
	unixSocket, err := ioutil.TempFile("", "mysql_vitess_test.sock")
	if err != nil {
		t.Fatalf("Failed to create temp file")
	}
	os.Remove(unixSocket.Name())

	l, err := newMysqlUnixSocket(unixSocket.Name(), authServer, th)
	if err != nil {
		t.Fatalf("NewUnixSocket failed: %v", err)
	}
	defer l.Close()
	go l.Accept()

	params := &mysql.ConnParams{
		UnixSocket: unixSocket.Name(),
		Uname:      "user1",
		Pass:       "password1",
	}

	c, err := mysql.Connect(context.Background(), params)
	if err != nil {
		t.Errorf("Should be able to connect to server but found error: %v", err)
	}
	c.Close()
}

func TestConnectionStaleUnixSocket(t *testing.T) {
	th := &testHandler{}

	authServer := newTestAuthServerStatic()

	// First let's create a file. In this way, we simulate
	// having a stale socket on disk that needs to be cleaned up.
	unixSocket, err := ioutil.TempFile("", "mysql_vitess_test.sock")
	if err != nil {
		t.Fatalf("Failed to create temp file")
	}

	l, err := newMysqlUnixSocket(unixSocket.Name(), authServer, th)
	if err != nil {
		t.Fatalf("NewListener failed: %v", err)
	}
	defer l.Close()
	go l.Accept()

	params := &mysql.ConnParams{
		UnixSocket: unixSocket.Name(),
		Uname:      "user1",
		Pass:       "password1",
	}

	c, err := mysql.Connect(context.Background(), params)
	if err != nil {
		t.Errorf("Should be able to connect to server but found error: %v", err)
	}
	c.Close()
}

func TestConnectionRespectsExistingUnixSocket(t *testing.T) {
	th := &testHandler{}

	authServer := newTestAuthServerStatic()

	unixSocket, err := ioutil.TempFile("", "mysql_vitess_test.sock")
	if err != nil {
		t.Fatalf("Failed to create temp file")
	}
	os.Remove(unixSocket.Name())

	l, err := newMysqlUnixSocket(unixSocket.Name(), authServer, th)
	if err != nil {
		t.Errorf("NewListener failed: %v", err)
	}
	defer l.Close()
	go l.Accept()
	_, err = newMysqlUnixSocket(unixSocket.Name(), authServer, th)
	want := "listen unix"
	if err == nil || !strings.HasPrefix(err.Error(), want) {
		t.Errorf("Error: %v, want prefix %s", err, want)
	}
}

var newSpanOK = func(ctx context.Context, label string) (trace.Span, context.Context) {
	return trace.NoopSpan{}, context.Background()
}

var newFromStringOK = func(ctx context.Context, spanContext, label string) (trace.Span, context.Context, error) {
	return trace.NoopSpan{}, context.Background(), nil
}

func newFromStringFail(t *testing.T) func(ctx context.Context, parentSpan string, label string) (trace.Span, context.Context, error) {
	return func(ctx context.Context, parentSpan string, label string) (trace.Span, context.Context, error) {
		t.Fatalf("we didn't provide a parent span in the sql query. this should not have been called. got: %v", parentSpan)
		return trace.NoopSpan{}, context.Background(), nil
	}
}

func newFromStringError(t *testing.T) func(ctx context.Context, parentSpan string, label string) (trace.Span, context.Context, error) {
	return func(ctx context.Context, parentSpan string, label string) (trace.Span, context.Context, error) {
		return trace.NoopSpan{}, context.Background(), fmt.Errorf("")
	}
}

func newFromStringExpect(t *testing.T, expected string) func(ctx context.Context, parentSpan string, label string) (trace.Span, context.Context, error) {
	return func(ctx context.Context, parentSpan string, label string) (trace.Span, context.Context, error) {
		assert.Equal(t, expected, parentSpan)
		return trace.NoopSpan{}, context.Background(), nil
	}
}

func newSpanFail(t *testing.T) func(ctx context.Context, label string) (trace.Span, context.Context) {
	return func(ctx context.Context, label string) (trace.Span, context.Context) {
		t.Fatalf("we provided a span context but newFromString was not used as expected")
		return trace.NoopSpan{}, context.Background()
	}
}

func TestNoSpanContextPassed(t *testing.T) {
	_, _, err := startSpanTestable(context.Background(), "sql without comments", "someLabel", newSpanOK, newFromStringFail(t))
	assert.NoError(t, err)
}

func TestSpanContextNoPassedInButExistsInString(t *testing.T) {
	_, _, err := startSpanTestable(context.Background(), "SELECT * FROM SOMETABLE WHERE COL = \"/*VT_SPAN_CONTEXT=123*/", "someLabel", newSpanOK, newFromStringFail(t))
	assert.NoError(t, err)
}

func TestSpanContextPassedIn(t *testing.T) {
	_, _, err := startSpanTestable(context.Background(), "/*VT_SPAN_CONTEXT=123*/SQL QUERY", "someLabel", newSpanFail(t), newFromStringOK)
	assert.NoError(t, err)
}

func TestSpanContextPassedInEvenAroundOtherComments(t *testing.T) {
	_, _, err := startSpanTestable(context.Background(), "/*VT_SPAN_CONTEXT=123*/SELECT /*vt+ SCATTER_ERRORS_AS_WARNINGS */ col1, col2 FROM TABLE ", "someLabel",
		newSpanFail(t),
		newFromStringExpect(t, "123"))
	assert.NoError(t, err)
}

func TestSpanContextNotParsable(t *testing.T) {
	hasRun := false
	_, _, err := startSpanTestable(context.Background(), "/*VT_SPAN_CONTEXT=123*/SQL QUERY", "someLabel",
		func(c context.Context, s string) (trace.Span, context.Context) {
			hasRun = true
			return trace.NoopSpan{}, context.Background()
		},
		newFromStringError(t))
	assert.NoError(t, err)
	assert.True(t, hasRun, "Should have continued execution despite failure to parse VT_SPAN_CONTEXT")
}

func newTestAuthServerStatic() *mysql.AuthServerStatic {
	jsonConfig := "{\"user1\":{\"Password\":\"password1\", \"UserData\":\"userData1\", \"SourceHost\":\"localhost\"}}"
	return mysql.NewAuthServerStatic("", jsonConfig, 0)
}

func TestDefaultWorkloadEmpty(t *testing.T) {
	vh := &vtgateHandler{}
	sess := vh.session(&mysql.Conn{})
	if sess.Options.Workload != querypb.ExecuteOptions_OLTP {
		t.Fatalf("Expected default workload UNSPECIFIED")
	}
}

func TestDefaultWorkloadOLAP(t *testing.T) {
	vh := &vtgateHandler{}
	mysqlDefaultWorkload = int32(querypb.ExecuteOptions_OLAP)
	sess := vh.session(&mysql.Conn{})
	if sess.Options.Workload != querypb.ExecuteOptions_OLAP {
		t.Fatalf("Expected default workload OLAP")
	}
}

func TestInitTLSConfig(t *testing.T) {
	// Create the certs.
	root, err := ioutil.TempDir("", "TestInitTLSConfig")
	if err != nil {
		t.Fatalf("TempDir failed: %v", err)
	}
	defer os.RemoveAll(root)
	tlstest.CreateCA(root)
	tlstest.CreateSignedCert(root, tlstest.CA, "01", "server", "server.example.com")

	listener := &mysql.Listener{}
	if err := initTLSConfig(listener, path.Join(root, "server-cert.pem"), path.Join(root, "server-key.pem"), path.Join(root, "ca-cert.pem"), true); err != nil {
		t.Fatalf("init tls config failure due to: +%v", err)
	}

	serverConfig := listener.TLSConfig.Load()
	if serverConfig == nil {
		t.Fatalf("init tls config shouldn't create nil server config")
	}

	sigChan <- syscall.SIGHUP
	time.Sleep(100 * time.Millisecond) // wait for signal handler

	if listener.TLSConfig.Load() == serverConfig {
		t.Fatalf("init tls config should have been recreated after SIGHUP")
	}
}
<commit_msg>changed message in test to display default as OLTP<commit_after>/*
Copyright 2019 The Vitess Authors.

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

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

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

package vtgate

import (
	"fmt"
	"io/ioutil"
	"os"
	"path"
	"strings"
	"syscall"
	"testing"
	"time"

	"github.com/stretchr/testify/assert"

	"vitess.io/vitess/go/trace"

	"context"

	"vitess.io/vitess/go/mysql"
	"vitess.io/vitess/go/sqltypes"
	querypb "vitess.io/vitess/go/vt/proto/query"
	"vitess.io/vitess/go/vt/tlstest"
)

type testHandler struct {
	lastConn *mysql.Conn
}

func (th *testHandler) NewConnection(c *mysql.Conn) {
	th.lastConn = c
}

func (th *testHandler) ConnectionClosed(c *mysql.Conn) {
}

func (th *testHandler) ComQuery(c *mysql.Conn, q string, callback func(*sqltypes.Result) error) error {
	return nil
}

func (th *testHandler) ComPrepare(c *mysql.Conn, q string, b map[string]*querypb.BindVariable) ([]*querypb.Field, error) {
	return nil, nil
}

func (th *testHandler) ComResetConnection(c *mysql.Conn) {
}

func (th *testHandler) ComStmtExecute(c *mysql.Conn, prepare *mysql.PrepareData, callback func(*sqltypes.Result) error) error {
	return nil
}

func (th *testHandler) WarningCount(c *mysql.Conn) uint16 {
	return 0
}

func TestConnectionUnixSocket(t *testing.T) {
	th := &testHandler{}

	authServer := newTestAuthServerStatic()

	// Use tmp file to reserve a path, remove it immediately, we only care about
	// name in this context
	unixSocket, err := ioutil.TempFile("", "mysql_vitess_test.sock")
	if err != nil {
		t.Fatalf("Failed to create temp file")
	}
	os.Remove(unixSocket.Name())

	l, err := newMysqlUnixSocket(unixSocket.Name(), authServer, th)
	if err != nil {
		t.Fatalf("NewUnixSocket failed: %v", err)
	}
	defer l.Close()
	go l.Accept()

	params := &mysql.ConnParams{
		UnixSocket: unixSocket.Name(),
		Uname:      "user1",
		Pass:       "password1",
	}

	c, err := mysql.Connect(context.Background(), params)
	if err != nil {
		t.Errorf("Should be able to connect to server but found error: %v", err)
	}
	c.Close()
}

func TestConnectionStaleUnixSocket(t *testing.T) {
	th := &testHandler{}

	authServer := newTestAuthServerStatic()

	// First let's create a file. In this way, we simulate
	// having a stale socket on disk that needs to be cleaned up.
	unixSocket, err := ioutil.TempFile("", "mysql_vitess_test.sock")
	if err != nil {
		t.Fatalf("Failed to create temp file")
	}

	l, err := newMysqlUnixSocket(unixSocket.Name(), authServer, th)
	if err != nil {
		t.Fatalf("NewListener failed: %v", err)
	}
	defer l.Close()
	go l.Accept()

	params := &mysql.ConnParams{
		UnixSocket: unixSocket.Name(),
		Uname:      "user1",
		Pass:       "password1",
	}

	c, err := mysql.Connect(context.Background(), params)
	if err != nil {
		t.Errorf("Should be able to connect to server but found error: %v", err)
	}
	c.Close()
}

func TestConnectionRespectsExistingUnixSocket(t *testing.T) {
	th := &testHandler{}

	authServer := newTestAuthServerStatic()

	unixSocket, err := ioutil.TempFile("", "mysql_vitess_test.sock")
	if err != nil {
		t.Fatalf("Failed to create temp file")
	}
	os.Remove(unixSocket.Name())

	l, err := newMysqlUnixSocket(unixSocket.Name(), authServer, th)
	if err != nil {
		t.Errorf("NewListener failed: %v", err)
	}
	defer l.Close()
	go l.Accept()
	_, err = newMysqlUnixSocket(unixSocket.Name(), authServer, th)
	want := "listen unix"
	if err == nil || !strings.HasPrefix(err.Error(), want) {
		t.Errorf("Error: %v, want prefix %s", err, want)
	}
}

var newSpanOK = func(ctx context.Context, label string) (trace.Span, context.Context) {
	return trace.NoopSpan{}, context.Background()
}

var newFromStringOK = func(ctx context.Context, spanContext, label string) (trace.Span, context.Context, error) {
	return trace.NoopSpan{}, context.Background(), nil
}

func newFromStringFail(t *testing.T) func(ctx context.Context, parentSpan string, label string) (trace.Span, context.Context, error) {
	return func(ctx context.Context, parentSpan string, label string) (trace.Span, context.Context, error) {
		t.Fatalf("we didn't provide a parent span in the sql query. this should not have been called. got: %v", parentSpan)
		return trace.NoopSpan{}, context.Background(), nil
	}
}

func newFromStringError(t *testing.T) func(ctx context.Context, parentSpan string, label string) (trace.Span, context.Context, error) {
	return func(ctx context.Context, parentSpan string, label string) (trace.Span, context.Context, error) {
		return trace.NoopSpan{}, context.Background(), fmt.Errorf("")
	}
}

func newFromStringExpect(t *testing.T, expected string) func(ctx context.Context, parentSpan string, label string) (trace.Span, context.Context, error) {
	return func(ctx context.Context, parentSpan string, label string) (trace.Span, context.Context, error) {
		assert.Equal(t, expected, parentSpan)
		return trace.NoopSpan{}, context.Background(), nil
	}
}

func newSpanFail(t *testing.T) func(ctx context.Context, label string) (trace.Span, context.Context) {
	return func(ctx context.Context, label string) (trace.Span, context.Context) {
		t.Fatalf("we provided a span context but newFromString was not used as expected")
		return trace.NoopSpan{}, context.Background()
	}
}

func TestNoSpanContextPassed(t *testing.T) {
	_, _, err := startSpanTestable(context.Background(), "sql without comments", "someLabel", newSpanOK, newFromStringFail(t))
	assert.NoError(t, err)
}

func TestSpanContextNoPassedInButExistsInString(t *testing.T) {
	_, _, err := startSpanTestable(context.Background(), "SELECT * FROM SOMETABLE WHERE COL = \"/*VT_SPAN_CONTEXT=123*/", "someLabel", newSpanOK, newFromStringFail(t))
	assert.NoError(t, err)
}

func TestSpanContextPassedIn(t *testing.T) {
	_, _, err := startSpanTestable(context.Background(), "/*VT_SPAN_CONTEXT=123*/SQL QUERY", "someLabel", newSpanFail(t), newFromStringOK)
	assert.NoError(t, err)
}

func TestSpanContextPassedInEvenAroundOtherComments(t *testing.T) {
	_, _, err := startSpanTestable(context.Background(), "/*VT_SPAN_CONTEXT=123*/SELECT /*vt+ SCATTER_ERRORS_AS_WARNINGS */ col1, col2 FROM TABLE ", "someLabel",
		newSpanFail(t),
		newFromStringExpect(t, "123"))
	assert.NoError(t, err)
}

func TestSpanContextNotParsable(t *testing.T) {
	hasRun := false
	_, _, err := startSpanTestable(context.Background(), "/*VT_SPAN_CONTEXT=123*/SQL QUERY", "someLabel",
		func(c context.Context, s string) (trace.Span, context.Context) {
			hasRun = true
			return trace.NoopSpan{}, context.Background()
		},
		newFromStringError(t))
	assert.NoError(t, err)
	assert.True(t, hasRun, "Should have continued execution despite failure to parse VT_SPAN_CONTEXT")
}

func newTestAuthServerStatic() *mysql.AuthServerStatic {
	jsonConfig := "{\"user1\":{\"Password\":\"password1\", \"UserData\":\"userData1\", \"SourceHost\":\"localhost\"}}"
	return mysql.NewAuthServerStatic("", jsonConfig, 0)
}

func TestDefaultWorkloadEmpty(t *testing.T) {
	vh := &vtgateHandler{}
	sess := vh.session(&mysql.Conn{})
	if sess.Options.Workload != querypb.ExecuteOptions_OLTP {
		t.Fatalf("Expected default workload OLTP")
	}
}

func TestDefaultWorkloadOLAP(t *testing.T) {
	vh := &vtgateHandler{}
	mysqlDefaultWorkload = int32(querypb.ExecuteOptions_OLAP)
	sess := vh.session(&mysql.Conn{})
	if sess.Options.Workload != querypb.ExecuteOptions_OLAP {
		t.Fatalf("Expected default workload OLAP")
	}
}

func TestInitTLSConfig(t *testing.T) {
	// Create the certs.
	root, err := ioutil.TempDir("", "TestInitTLSConfig")
	if err != nil {
		t.Fatalf("TempDir failed: %v", err)
	}
	defer os.RemoveAll(root)
	tlstest.CreateCA(root)
	tlstest.CreateSignedCert(root, tlstest.CA, "01", "server", "server.example.com")

	listener := &mysql.Listener{}
	if err := initTLSConfig(listener, path.Join(root, "server-cert.pem"), path.Join(root, "server-key.pem"), path.Join(root, "ca-cert.pem"), true); err != nil {
		t.Fatalf("init tls config failure due to: +%v", err)
	}

	serverConfig := listener.TLSConfig.Load()
	if serverConfig == nil {
		t.Fatalf("init tls config shouldn't create nil server config")
	}

	sigChan <- syscall.SIGHUP
	time.Sleep(100 * time.Millisecond) // wait for signal handler

	if listener.TLSConfig.Load() == serverConfig {
		t.Fatalf("init tls config should have been recreated after SIGHUP")
	}
}
<|endoftext|>