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

package net

import (
	"context"
	"syscall"
)

// BUG(mikio): On every POSIX platform, reads from the "ip4" network
// using the ReadFrom or ReadFromIP method might not return a complete
// IPv4 packet, including its header, even if there is space
// available. This can occur even in cases where Read or ReadMsgIP
// could return a complete packet. For this reason, it is recommended
// that you do not use these methods if it is important to receive a
// full packet.
//
// The Go 1 compatibility guidelines make it impossible for us to
// change the behavior of these methods; use Read or ReadMsgIP
// instead.

// BUG(mikio): On NaCl, Plan 9 and Windows, the ReadMsgIP and
// WriteMsgIP methods of IPConn are not implemented.

// BUG(mikio): On Windows, the File method of IPConn is not
// implemented.

// IPAddr represents the address of an IP end point.
type IPAddr struct {
	IP   IP
	Zone string // IPv6 scoped addressing zone
}

// Network returns the address's network name, "ip".
func (a *IPAddr) Network() string { return "ip" }

func (a *IPAddr) String() string {
	if a == nil {
		return "<nil>"
	}
	ip := ipEmptyString(a.IP)
	if a.Zone != "" {
		return ip + "%" + a.Zone
	}
	return ip
}

func (a *IPAddr) isWildcard() bool {
	if a == nil || a.IP == nil {
		return true
	}
	return a.IP.IsUnspecified()
}

func (a *IPAddr) opAddr() Addr {
	if a == nil {
		return nil
	}
	return a
}

// ResolveIPAddr returns an address of IP end point.
//
// The network must be an IP network name.
//
// If the host in the address parameter is not a literal IP address,
// ResolveIPAddr resolves the address to an address of IP end point.
// Otherwise, it parses the address as a literal IP address.
// The address parameter can use a host name, but this is not
// recommended, because it will return at most one of the host name's
// IP addresses.
//
// See func Dial for a description of the network and address
// parameters.
func ResolveIPAddr(network, address string) (*IPAddr, error) {
	if network == "" { // a hint wildcard for Go 1.0 undocumented behavior
		network = "ip"
	}
	afnet, _, err := parseNetwork(context.Background(), network, false)
	if err != nil {
		return nil, err
	}
	switch afnet {
	case "ip", "ip4", "ip6":
	default:
		return nil, UnknownNetworkError(network)
	}
	addrs, err := DefaultResolver.internetAddrList(context.Background(), afnet, address)
	if err != nil {
		return nil, err
	}
	return addrs.first(isIPv4).(*IPAddr), nil
}

// IPConn is the implementation of the Conn and PacketConn interfaces
// for IP network connections.
type IPConn struct {
	conn
}

// SyscallConn returns a raw network connection.
// This implements the syscall.Conn interface.
func (c *IPConn) SyscallConn() (syscall.RawConn, error) {
	if !c.ok() {
		return nil, syscall.EINVAL
	}
	return newRawConn(c.fd)
}

// ReadFromIP reads an IP packet from c, copying the payload into b.
// It returns the number of bytes copied into b and the return address
// that was on the packet.
//
// ReadFromIP can be made to time out and return an error with
// Timeout() == true after a fixed time limit; see SetDeadline and
// SetReadDeadline.
func (c *IPConn) ReadFromIP(b []byte) (int, *IPAddr, error) {
	if !c.ok() {
		return 0, nil, syscall.EINVAL
	}
	n, addr, err := c.readFrom(b)
	if err != nil {
		err = &OpError{Op: "read", Net: c.fd.net, Source: c.fd.laddr, Addr: c.fd.raddr, Err: err}
	}
	return n, addr, err
}

// ReadFrom implements the PacketConn ReadFrom method.
func (c *IPConn) ReadFrom(b []byte) (int, Addr, error) {
	if !c.ok() {
		return 0, nil, syscall.EINVAL
	}
	n, addr, err := c.readFrom(b)
	if err != nil {
		err = &OpError{Op: "read", Net: c.fd.net, Source: c.fd.laddr, Addr: c.fd.raddr, Err: err}
	}
	if addr == nil {
		return n, nil, err
	}
	return n, addr, err
}

// ReadMsgIP reads a packet from c, copying the payload into b and the
// associated out-of-band data into oob. It returns the number of
// bytes copied into b, the number of bytes copied into oob, the flags
// that were set on the packet and the source address of the packet.
func (c *IPConn) ReadMsgIP(b, oob []byte) (n, oobn, flags int, addr *IPAddr, err error) {
	if !c.ok() {
		return 0, 0, 0, nil, syscall.EINVAL
	}
	n, oobn, flags, addr, err = c.readMsg(b, oob)
	if err != nil {
		err = &OpError{Op: "read", Net: c.fd.net, Source: c.fd.laddr, Addr: c.fd.raddr, Err: err}
	}
	return
}

// WriteToIP writes an IP packet to addr via c, copying the payload
// from b.
//
// WriteToIP can be made to time out and return an error with
// Timeout() == true after a fixed time limit; see SetDeadline and
// SetWriteDeadline. On packet-oriented connections, write timeouts
// are rare.
func (c *IPConn) WriteToIP(b []byte, addr *IPAddr) (int, error) {
	if !c.ok() {
		return 0, syscall.EINVAL
	}
	n, err := c.writeTo(b, addr)
	if err != nil {
		err = &OpError{Op: "write", Net: c.fd.net, Source: c.fd.laddr, Addr: addr.opAddr(), Err: err}
	}
	return n, err
}

// WriteTo implements the PacketConn WriteTo method.
func (c *IPConn) WriteTo(b []byte, addr Addr) (int, error) {
	if !c.ok() {
		return 0, syscall.EINVAL
	}
	a, ok := addr.(*IPAddr)
	if !ok {
		return 0, &OpError{Op: "write", Net: c.fd.net, Source: c.fd.laddr, Addr: addr, Err: syscall.EINVAL}
	}
	n, err := c.writeTo(b, a)
	if err != nil {
		err = &OpError{Op: "write", Net: c.fd.net, Source: c.fd.laddr, Addr: a.opAddr(), Err: err}
	}
	return n, err
}

// WriteMsgIP writes a packet to addr via c, copying the payload from
// b and the associated out-of-band data from oob. It returns the
// number of payload and out-of-band bytes written.
func (c *IPConn) WriteMsgIP(b, oob []byte, addr *IPAddr) (n, oobn int, err error) {
	if !c.ok() {
		return 0, 0, syscall.EINVAL
	}
	n, oobn, err = c.writeMsg(b, oob, addr)
	if err != nil {
		err = &OpError{Op: "write", Net: c.fd.net, Source: c.fd.laddr, Addr: addr.opAddr(), Err: err}
	}
	return
}

func newIPConn(fd *netFD) *IPConn { return &IPConn{conn{fd}} }

// DialIP acts like Dial for IP networks.
//
// The network must be an IP network name; see func Dial for details.
//
// If laddr is nil, a local address is automatically chosen.
// If the IP field of raddr is nil or an unspecified IP address, the
// local system is assumed.
func DialIP(network string, laddr, raddr *IPAddr) (*IPConn, error) {
	c, err := dialIP(context.Background(), network, laddr, raddr)
	if err != nil {
		return nil, &OpError{Op: "dial", Net: network, Source: laddr.opAddr(), Addr: raddr.opAddr(), Err: err}
	}
	return c, nil
}

// ListenIP acts like ListenPacket for IP networks.
//
// The network must be an IP network name; see func Dial for details.
//
// If the IP field of laddr is nil or an unspecified IP address,
// ListenIP listens on all available IP addresses of the local system
// except multicast IP addresses.
func ListenIP(network string, laddr *IPAddr) (*IPConn, error) {
	c, err := listenIP(context.Background(), network, laddr)
	if err != nil {
		return nil, &OpError{Op: "listen", Net: network, Source: nil, Addr: laddr.opAddr(), Err: err}
	}
	return c, nil
}
<commit_msg>net: update documentation on methods of IPConn<commit_after>// Copyright 2010 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package net

import (
	"context"
	"syscall"
)

// BUG(mikio): On every POSIX platform, reads from the "ip4" network
// using the ReadFrom or ReadFromIP method might not return a complete
// IPv4 packet, including its header, even if there is space
// available. This can occur even in cases where Read or ReadMsgIP
// could return a complete packet. For this reason, it is recommended
// that you do not use these methods if it is important to receive a
// full packet.
//
// The Go 1 compatibility guidelines make it impossible for us to
// change the behavior of these methods; use Read or ReadMsgIP
// instead.

// BUG(mikio): On NaCl, Plan 9 and Windows, the ReadMsgIP and
// WriteMsgIP methods of IPConn are not implemented.

// BUG(mikio): On Windows, the File method of IPConn is not
// implemented.

// IPAddr represents the address of an IP end point.
type IPAddr struct {
	IP   IP
	Zone string // IPv6 scoped addressing zone
}

// Network returns the address's network name, "ip".
func (a *IPAddr) Network() string { return "ip" }

func (a *IPAddr) String() string {
	if a == nil {
		return "<nil>"
	}
	ip := ipEmptyString(a.IP)
	if a.Zone != "" {
		return ip + "%" + a.Zone
	}
	return ip
}

func (a *IPAddr) isWildcard() bool {
	if a == nil || a.IP == nil {
		return true
	}
	return a.IP.IsUnspecified()
}

func (a *IPAddr) opAddr() Addr {
	if a == nil {
		return nil
	}
	return a
}

// ResolveIPAddr returns an address of IP end point.
//
// The network must be an IP network name.
//
// If the host in the address parameter is not a literal IP address,
// ResolveIPAddr resolves the address to an address of IP end point.
// Otherwise, it parses the address as a literal IP address.
// The address parameter can use a host name, but this is not
// recommended, because it will return at most one of the host name's
// IP addresses.
//
// See func Dial for a description of the network and address
// parameters.
func ResolveIPAddr(network, address string) (*IPAddr, error) {
	if network == "" { // a hint wildcard for Go 1.0 undocumented behavior
		network = "ip"
	}
	afnet, _, err := parseNetwork(context.Background(), network, false)
	if err != nil {
		return nil, err
	}
	switch afnet {
	case "ip", "ip4", "ip6":
	default:
		return nil, UnknownNetworkError(network)
	}
	addrs, err := DefaultResolver.internetAddrList(context.Background(), afnet, address)
	if err != nil {
		return nil, err
	}
	return addrs.first(isIPv4).(*IPAddr), nil
}

// IPConn is the implementation of the Conn and PacketConn interfaces
// for IP network connections.
type IPConn struct {
	conn
}

// SyscallConn returns a raw network connection.
// This implements the syscall.Conn interface.
func (c *IPConn) SyscallConn() (syscall.RawConn, error) {
	if !c.ok() {
		return nil, syscall.EINVAL
	}
	return newRawConn(c.fd)
}

// ReadFromIP acts like ReadFrom but returns an IPAddr.
func (c *IPConn) ReadFromIP(b []byte) (int, *IPAddr, error) {
	if !c.ok() {
		return 0, nil, syscall.EINVAL
	}
	n, addr, err := c.readFrom(b)
	if err != nil {
		err = &OpError{Op: "read", Net: c.fd.net, Source: c.fd.laddr, Addr: c.fd.raddr, Err: err}
	}
	return n, addr, err
}

// ReadFrom implements the PacketConn ReadFrom method.
func (c *IPConn) ReadFrom(b []byte) (int, Addr, error) {
	if !c.ok() {
		return 0, nil, syscall.EINVAL
	}
	n, addr, err := c.readFrom(b)
	if err != nil {
		err = &OpError{Op: "read", Net: c.fd.net, Source: c.fd.laddr, Addr: c.fd.raddr, Err: err}
	}
	if addr == nil {
		return n, nil, err
	}
	return n, addr, err
}

// ReadMsgIP reads a message from c, copying the payload into b and
// the associated out-of-band data into oob. It returns the number of
// bytes copied into b, the number of bytes copied into oob, the flags
// that were set on the message and the source address of the message.
//
// The packages golang.org/x/net/ipv4 and golang.org/x/net/ipv6 can be
// used to manipulate IP-level socket options in oob.
func (c *IPConn) ReadMsgIP(b, oob []byte) (n, oobn, flags int, addr *IPAddr, err error) {
	if !c.ok() {
		return 0, 0, 0, nil, syscall.EINVAL
	}
	n, oobn, flags, addr, err = c.readMsg(b, oob)
	if err != nil {
		err = &OpError{Op: "read", Net: c.fd.net, Source: c.fd.laddr, Addr: c.fd.raddr, Err: err}
	}
	return
}

// WriteToIP acts like WriteTo but takes an IPAddr.
func (c *IPConn) WriteToIP(b []byte, addr *IPAddr) (int, error) {
	if !c.ok() {
		return 0, syscall.EINVAL
	}
	n, err := c.writeTo(b, addr)
	if err != nil {
		err = &OpError{Op: "write", Net: c.fd.net, Source: c.fd.laddr, Addr: addr.opAddr(), Err: err}
	}
	return n, err
}

// WriteTo implements the PacketConn WriteTo method.
func (c *IPConn) WriteTo(b []byte, addr Addr) (int, error) {
	if !c.ok() {
		return 0, syscall.EINVAL
	}
	a, ok := addr.(*IPAddr)
	if !ok {
		return 0, &OpError{Op: "write", Net: c.fd.net, Source: c.fd.laddr, Addr: addr, Err: syscall.EINVAL}
	}
	n, err := c.writeTo(b, a)
	if err != nil {
		err = &OpError{Op: "write", Net: c.fd.net, Source: c.fd.laddr, Addr: a.opAddr(), Err: err}
	}
	return n, err
}

// WriteMsgIP writes a message to addr via c, copying the payload from
// b and the associated out-of-band data from oob. It returns the
// number of payload and out-of-band bytes written.
//
// The packages golang.org/x/net/ipv4 and golang.org/x/net/ipv6 can be
// used to manipulate IP-level socket options in oob.
func (c *IPConn) WriteMsgIP(b, oob []byte, addr *IPAddr) (n, oobn int, err error) {
	if !c.ok() {
		return 0, 0, syscall.EINVAL
	}
	n, oobn, err = c.writeMsg(b, oob, addr)
	if err != nil {
		err = &OpError{Op: "write", Net: c.fd.net, Source: c.fd.laddr, Addr: addr.opAddr(), Err: err}
	}
	return
}

func newIPConn(fd *netFD) *IPConn { return &IPConn{conn{fd}} }

// DialIP acts like Dial for IP networks.
//
// The network must be an IP network name; see func Dial for details.
//
// If laddr is nil, a local address is automatically chosen.
// If the IP field of raddr is nil or an unspecified IP address, the
// local system is assumed.
func DialIP(network string, laddr, raddr *IPAddr) (*IPConn, error) {
	c, err := dialIP(context.Background(), network, laddr, raddr)
	if err != nil {
		return nil, &OpError{Op: "dial", Net: network, Source: laddr.opAddr(), Addr: raddr.opAddr(), Err: err}
	}
	return c, nil
}

// ListenIP acts like ListenPacket for IP networks.
//
// The network must be an IP network name; see func Dial for details.
//
// If the IP field of laddr is nil or an unspecified IP address,
// ListenIP listens on all available IP addresses of the local system
// except multicast IP addresses.
func ListenIP(network string, laddr *IPAddr) (*IPConn, error) {
	c, err := listenIP(context.Background(), network, laddr)
	if err != nil {
		return nil, &OpError{Op: "listen", Net: network, Source: nil, Addr: laddr.opAddr(), Err: err}
	}
	return c, nil
}
<|endoftext|>


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

package runtime

import (
	"runtime/internal/atomic"
	"runtime/internal/sys"
	"unsafe"
)

// The compiler knows that a print of a value of this type
// should use printhex instead of printuint (decimal).
type hex uint64

func bytes(s string) (ret []byte) {
	rp := (*slice)(unsafe.Pointer(&ret))
	sp := stringStructOf(&s)
	rp.array = sp.str
	rp.len = sp.len
	rp.cap = sp.len
	return
}

var (
	// printBacklog is a circular buffer of messages written with the builtin
	// print* functions, for use in postmortem analysis of core dumps.
	printBacklog      [512]byte
	printBacklogIndex int
)

// recordForPanic maintains a circular buffer of messages written by the
// runtime leading up to a process crash, allowing the messages to be
// extracted from a core dump.
//
// The text written during a process crash (following "panic" or "fatal
// error") is not saved, since the goroutine stacks will generally be readable
// from the runtime datastructures in the core file.
func recordForPanic(b []byte) {
	printlock()

	if atomic.Load(&panicking) == 0 {
		// Not actively crashing: maintain circular buffer of print output.
		for i := 0; i < len(b); {
			n := copy(printBacklog[printBacklogIndex:], b[i:])
			i += n
			printBacklogIndex += n
			printBacklogIndex %= len(printBacklog)
		}
	}

	printunlock()
}

var debuglock mutex

// The compiler emits calls to printlock and printunlock around
// the multiple calls that implement a single Go print or println
// statement. Some of the print helpers (printslice, for example)
// call print recursively. There is also the problem of a crash
// happening during the print routines and needing to acquire
// the print lock to print information about the crash.
// For both these reasons, let a thread acquire the printlock 'recursively'.

func printlock() {
	mp := getg().m
	mp.locks++ // do not reschedule between printlock++ and lock(&debuglock).
	mp.printlock++
	if mp.printlock == 1 {
		lock(&debuglock)
	}
	mp.locks-- // now we know debuglock is held and holding up mp.locks for us.
}

func printunlock() {
	mp := getg().m
	mp.printlock--
	if mp.printlock == 0 {
		unlock(&debuglock)
	}
}

// write to goroutine-local buffer if diverting output,
// or else standard error.
func gwrite(b []byte) {
	if len(b) == 0 {
		return
	}
	recordForPanic(b)
	gp := getg()
	// Don't use the writebuf if gp.m is dying. We want anything
	// written through gwrite to appear in the terminal rather
	// than be written to in some buffer, if we're in a panicking state.
	// Note that we can't just clear writebuf in the gp.m.dying case
	// because a panic isn't allowed to have any write barriers.
	if gp == nil || gp.writebuf == nil || gp.m.dying > 0 {
		writeErr(b)
		return
	}

	n := copy(gp.writebuf[len(gp.writebuf):cap(gp.writebuf)], b)
	gp.writebuf = gp.writebuf[:len(gp.writebuf)+n]
}

func printsp() {
	printstring(" ")
}

func printnl() {
	printstring("\n")
}

func printbool(v bool) {
	if v {
		printstring("true")
	} else {
		printstring("false")
	}
}

func printfloat(v float64) {
	switch {
	case v != v:
		printstring("NaN")
		return
	case v+v == v && v > 0:
		printstring("+Inf")
		return
	case v+v == v && v < 0:
		printstring("-Inf")
		return
	}

	const n = 7 // digits printed
	var buf [n + 7]byte
	buf[0] = '+'
	e := 0 // exp
	if v == 0 {
		if 1/v < 0 {
			buf[0] = '-'
		}
	} else {
		if v < 0 {
			v = -v
			buf[0] = '-'
		}

		// normalize
		for v >= 10 {
			e++
			v /= 10
		}
		for v < 1 {
			e--
			v *= 10
		}

		// round
		h := 5.0
		for i := 0; i < n; i++ {
			h /= 10
		}
		v += h
		if v >= 10 {
			e++
			v /= 10
		}
	}

	// format +d.dddd+edd
	for i := 0; i < n; i++ {
		s := int(v)
		buf[i+2] = byte(s + '0')
		v -= float64(s)
		v *= 10
	}
	buf[1] = buf[2]
	buf[2] = '.'

	buf[n+2] = 'e'
	buf[n+3] = '+'
	if e < 0 {
		e = -e
		buf[n+3] = '-'
	}

	buf[n+4] = byte(e/100) + '0'
	buf[n+5] = byte(e/10)%10 + '0'
	buf[n+6] = byte(e%10) + '0'
	gwrite(buf[:])
}

func printcomplex(c complex128) {
	print("(", real(c), imag(c), "i)")
}

func printuint(v uint64) {
	var buf [100]byte
	i := len(buf)
	for i--; i > 0; i-- {
		buf[i] = byte(v%10 + '0')
		if v < 10 {
			break
		}
		v /= 10
	}
	gwrite(buf[i:])
}

func printint(v int64) {
	if v < 0 {
		printstring("-")
		v = -v
	}
	printuint(uint64(v))
}

func printhex(v uint64) {
	const dig = "0123456789abcdef"
	var buf [100]byte
	i := len(buf)
	for i--; i > 0; i-- {
		buf[i] = dig[v%16]
		if v < 16 {
			break
		}
		v /= 16
	}
	i--
	buf[i] = 'x'
	i--
	buf[i] = '0'
	gwrite(buf[i:])
}

func printpointer(p unsafe.Pointer) {
	printhex(uint64(uintptr(p)))
}
func printuintptr(p uintptr) {
	printhex(uint64(p))
}

func printstring(s string) {
	gwrite(bytes(s))
}

func printslice(s []byte) {
	sp := (*slice)(unsafe.Pointer(&s))
	print("[", len(s), "/", cap(s), "]")
	printpointer(sp.array)
}

func printeface(e eface) {
	print("(", e._type, ",", e.data, ")")
}

func printiface(i iface) {
	print("(", i.tab, ",", i.data, ")")
}

// hexdumpWords prints a word-oriented hex dump of [p, end).
//
// If mark != nil, it will be called with each printed word's address
// and should return a character mark to appear just before that
// word's value. It can return 0 to indicate no mark.
func hexdumpWords(p, end uintptr, mark func(uintptr) byte) {
	p1 := func(x uintptr) {
		var buf [2 * sys.PtrSize]byte
		for i := len(buf) - 1; i >= 0; i-- {
			if x&0xF < 10 {
				buf[i] = byte(x&0xF) + '0'
			} else {
				buf[i] = byte(x&0xF) - 10 + 'a'
			}
			x >>= 4
		}
		gwrite(buf[:])
	}

	printlock()
	var markbuf [1]byte
	markbuf[0] = ' '
	for i := uintptr(0); p+i < end; i += sys.PtrSize {
		if i%16 == 0 {
			if i != 0 {
				println()
			}
			p1(p + i)
			print(": ")
		}

		if mark != nil {
			markbuf[0] = mark(p + i)
			if markbuf[0] == 0 {
				markbuf[0] = ' '
			}
		}
		gwrite(markbuf[:])
		val := *(*uintptr)(unsafe.Pointer(p + i))
		p1(val)
		print(" ")

		// Can we symbolize val?
		fn := findfunc(val)
		if fn.valid() {
			print("<", funcname(fn), "+", val-fn.entry, "> ")
		}
	}
	println()
	printunlock()
}
<commit_msg>runtime: print hex numbers with hex prefixes in traceback debug<commit_after>// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package runtime

import (
	"runtime/internal/atomic"
	"runtime/internal/sys"
	"unsafe"
)

// The compiler knows that a print of a value of this type
// should use printhex instead of printuint (decimal).
type hex uint64

func bytes(s string) (ret []byte) {
	rp := (*slice)(unsafe.Pointer(&ret))
	sp := stringStructOf(&s)
	rp.array = sp.str
	rp.len = sp.len
	rp.cap = sp.len
	return
}

var (
	// printBacklog is a circular buffer of messages written with the builtin
	// print* functions, for use in postmortem analysis of core dumps.
	printBacklog      [512]byte
	printBacklogIndex int
)

// recordForPanic maintains a circular buffer of messages written by the
// runtime leading up to a process crash, allowing the messages to be
// extracted from a core dump.
//
// The text written during a process crash (following "panic" or "fatal
// error") is not saved, since the goroutine stacks will generally be readable
// from the runtime datastructures in the core file.
func recordForPanic(b []byte) {
	printlock()

	if atomic.Load(&panicking) == 0 {
		// Not actively crashing: maintain circular buffer of print output.
		for i := 0; i < len(b); {
			n := copy(printBacklog[printBacklogIndex:], b[i:])
			i += n
			printBacklogIndex += n
			printBacklogIndex %= len(printBacklog)
		}
	}

	printunlock()
}

var debuglock mutex

// The compiler emits calls to printlock and printunlock around
// the multiple calls that implement a single Go print or println
// statement. Some of the print helpers (printslice, for example)
// call print recursively. There is also the problem of a crash
// happening during the print routines and needing to acquire
// the print lock to print information about the crash.
// For both these reasons, let a thread acquire the printlock 'recursively'.

func printlock() {
	mp := getg().m
	mp.locks++ // do not reschedule between printlock++ and lock(&debuglock).
	mp.printlock++
	if mp.printlock == 1 {
		lock(&debuglock)
	}
	mp.locks-- // now we know debuglock is held and holding up mp.locks for us.
}

func printunlock() {
	mp := getg().m
	mp.printlock--
	if mp.printlock == 0 {
		unlock(&debuglock)
	}
}

// write to goroutine-local buffer if diverting output,
// or else standard error.
func gwrite(b []byte) {
	if len(b) == 0 {
		return
	}
	recordForPanic(b)
	gp := getg()
	// Don't use the writebuf if gp.m is dying. We want anything
	// written through gwrite to appear in the terminal rather
	// than be written to in some buffer, if we're in a panicking state.
	// Note that we can't just clear writebuf in the gp.m.dying case
	// because a panic isn't allowed to have any write barriers.
	if gp == nil || gp.writebuf == nil || gp.m.dying > 0 {
		writeErr(b)
		return
	}

	n := copy(gp.writebuf[len(gp.writebuf):cap(gp.writebuf)], b)
	gp.writebuf = gp.writebuf[:len(gp.writebuf)+n]
}

func printsp() {
	printstring(" ")
}

func printnl() {
	printstring("\n")
}

func printbool(v bool) {
	if v {
		printstring("true")
	} else {
		printstring("false")
	}
}

func printfloat(v float64) {
	switch {
	case v != v:
		printstring("NaN")
		return
	case v+v == v && v > 0:
		printstring("+Inf")
		return
	case v+v == v && v < 0:
		printstring("-Inf")
		return
	}

	const n = 7 // digits printed
	var buf [n + 7]byte
	buf[0] = '+'
	e := 0 // exp
	if v == 0 {
		if 1/v < 0 {
			buf[0] = '-'
		}
	} else {
		if v < 0 {
			v = -v
			buf[0] = '-'
		}

		// normalize
		for v >= 10 {
			e++
			v /= 10
		}
		for v < 1 {
			e--
			v *= 10
		}

		// round
		h := 5.0
		for i := 0; i < n; i++ {
			h /= 10
		}
		v += h
		if v >= 10 {
			e++
			v /= 10
		}
	}

	// format +d.dddd+edd
	for i := 0; i < n; i++ {
		s := int(v)
		buf[i+2] = byte(s + '0')
		v -= float64(s)
		v *= 10
	}
	buf[1] = buf[2]
	buf[2] = '.'

	buf[n+2] = 'e'
	buf[n+3] = '+'
	if e < 0 {
		e = -e
		buf[n+3] = '-'
	}

	buf[n+4] = byte(e/100) + '0'
	buf[n+5] = byte(e/10)%10 + '0'
	buf[n+6] = byte(e%10) + '0'
	gwrite(buf[:])
}

func printcomplex(c complex128) {
	print("(", real(c), imag(c), "i)")
}

func printuint(v uint64) {
	var buf [100]byte
	i := len(buf)
	for i--; i > 0; i-- {
		buf[i] = byte(v%10 + '0')
		if v < 10 {
			break
		}
		v /= 10
	}
	gwrite(buf[i:])
}

func printint(v int64) {
	if v < 0 {
		printstring("-")
		v = -v
	}
	printuint(uint64(v))
}

var minhexdigits = 0 // protected by printlock

func printhex(v uint64) {
	const dig = "0123456789abcdef"
	var buf [100]byte
	i := len(buf)
	for i--; i > 0; i-- {
		buf[i] = dig[v%16]
		if v < 16 && len(buf)-i >= minhexdigits {
			break
		}
		v /= 16
	}
	i--
	buf[i] = 'x'
	i--
	buf[i] = '0'
	gwrite(buf[i:])
}

func printpointer(p unsafe.Pointer) {
	printhex(uint64(uintptr(p)))
}
func printuintptr(p uintptr) {
	printhex(uint64(p))
}

func printstring(s string) {
	gwrite(bytes(s))
}

func printslice(s []byte) {
	sp := (*slice)(unsafe.Pointer(&s))
	print("[", len(s), "/", cap(s), "]")
	printpointer(sp.array)
}

func printeface(e eface) {
	print("(", e._type, ",", e.data, ")")
}

func printiface(i iface) {
	print("(", i.tab, ",", i.data, ")")
}

// hexdumpWords prints a word-oriented hex dump of [p, end).
//
// If mark != nil, it will be called with each printed word's address
// and should return a character mark to appear just before that
// word's value. It can return 0 to indicate no mark.
func hexdumpWords(p, end uintptr, mark func(uintptr) byte) {
	printlock()
	var markbuf [1]byte
	markbuf[0] = ' '
	minhexdigits = int(unsafe.Sizeof(uintptr(0)) * 2)
	for i := uintptr(0); p+i < end; i += sys.PtrSize {
		if i%16 == 0 {
			if i != 0 {
				println()
			}
			print(hex(p+i), ": ")
		}

		if mark != nil {
			markbuf[0] = mark(p + i)
			if markbuf[0] == 0 {
				markbuf[0] = ' '
			}
		}
		gwrite(markbuf[:])
		val := *(*uintptr)(unsafe.Pointer(p + i))
		print(hex(val))
		print(" ")

		// Can we symbolize val?
		fn := findfunc(val)
		if fn.valid() {
			print("<", funcname(fn), "+", hex(val-fn.entry), "> ")
		}
	}
	minhexdigits = 0
	println()
	printunlock()
}
<|endoftext|>


<commit_before>package singular

import (
	"encoding/binary"
	"net"
)

// Conn define a connect
type Conn struct {
	net.Conn
}

// NewConn return a new Conn
func NewConn(conn net.Conn) Conn {
	return Conn{
		Conn: conn,
	}
}

// Send conn send data
func (conn *Conn) Send(serialized []byte) (err error) {
	err = binary.Write(conn, binary.BigEndian, int32(len(serialized)))
	if err != nil {
		return err
	}
	_, err = conn.Write(serialized)
	return err
}

// Receive conn receive data
func (conn *Conn) Receive() (buf []byte, err error) {
	var msgLength int32
	err = binary.Read(conn, binary.BigEndian, &msgLength)
	if err != nil {
		return
	}

	buf = make([]byte, msgLength)
	err = binary.Read(conn, binary.BigEndian, buf)

	return buf, err
}
<commit_msg>Add request header<commit_after>package singular

import (
	"bytes"
	"encoding/binary"
	"errors"
	"net"
)

var (
	// Version request header
	Version = []byte("\x01MAGIC")
)

// Conn define a connect
type Conn struct {
	net.Conn
}

// NewConn return a new Conn
func NewConn(conn net.Conn) Conn {
	return Conn{
		Conn: conn,
	}
}

// Send conn send data
func (conn *Conn) Send(serialized []byte) (err error) {
	err = binary.Write(conn, binary.BigEndian, Version)
	if err != nil {
		return err
	}
	err = binary.Write(conn, binary.BigEndian, int32(len(serialized)))
	if err != nil {
		return err
	}
	_, err = conn.Write(serialized)
	return err
}

// Receive conn receive data
func (conn *Conn) Receive() (buf []byte, err error) {
	version := make([]byte, len(Version))
	err = binary.Read(conn, binary.BigEndian, &version)
	if err != nil || !bytes.Equal(version, Version) {
		return version, errors.New("Version not match")
	}
	var msgLength int32
	err = binary.Read(conn, binary.BigEndian, &msgLength)
	if err != nil {
		return
	}

	buf = make([]byte, msgLength)
	err = binary.Read(conn, binary.BigEndian, buf)

	return buf, err
}
<|endoftext|>


<commit_before>/*
	THIS IS NOT DONE AT ALL! USE AT YOUR OWN RISK!

	- it would be nice if cgo could grok several .go files,
	so far it can't; so all the C interface stuff has to be
	in one file; bummer that
*/

package sqlite3

/*
#include <stdlib.h>
#include "wrapper.h"
*/
import "C"
import "unsafe"

import "fmt"
import "os"
import "strconv"

/* these are not exported yet since I am not sure they are needed */
const (
	sqliteOk = iota; /* Successful result */
	sqliteError; /* SQL error or missing database */
	sqliteInternal; /* Internal logic error in SQLite */
	sqlitePerm; /* Access permission denied */
	sqliteAbort; /* Callback routine requested an abort */
	sqliteBusy; /* The database file is locked */
	sqliteLocked; /* A table in the database is locked */
	sqliteNomem; /* A malloc() failed */
	sqliteReadonly; /* Attempt to write a readonly database */
	sqliteInterrupt; /* Operation terminated by sqlite3_interrupt()*/
	sqliteIoerr; /* Some kind of disk I/O error occurred */
	sqliteCorrupt; /* The database disk image is malformed */
	sqlite_Notfound; /* NOT USED. Table or record not found */
	sqliteFull; /* Insertion failed because database is full */
	sqliteCantopen; /* Unable to open the database file */
	sqliteProtocol; /* NOT USED. Database lock protocol error */
	sqliteEmpty; /* Database is empty */
	sqliteSchema; /* The database schema changed */
	sqliteToobig; /* String or BLOB exceeds size limit */
	sqliteConstraint; /* Abort due to constraint violation */
	sqliteMismatch; /* Data type mismatch */
	sqliteMisuse; /* Library used incorrectly */
	sqliteNolfs; /* Uses OS features not supported on host */
	sqliteAuth; /* Authorization denied */
	sqliteFormat; /* Auxiliary database format error */
	sqliteRange; /* 2nd parameter to sqlite3_bind out of range */
	sqliteNotadb; /* File opened that is not a database file */
	sqliteRow = 100; /* sqlite3_step() has another row ready */
	sqliteDone = 101;  /* sqlite3_step() has finished executing */
)

type Connection struct {
	/* pointer to struct sqlite3 */
	handle C.wsq_db;
}

type Cursor struct {
	/* pointer to struct sqlite3_stmt */
	handle C.wsq_st;
	/* connection we were created on */
	connection *Connection;
	/* the last query yielded results */
	result bool;
}

func Version() (data map[string]string, error os.Error)
{
	data = make(map[string]string);

	cp := C.wsq_libversion();
	if (cp == nil) {
		error = &InterfaceError{"Version: couldn't get library version!"};
		return;
	}
	data["version"] = C.GoString(cp);
	// TODO: fake client and server keys?

	cp = C.wsq_sourceid();
	if (cp != nil) {
		data["sqlite3.sourceid"] = C.GoString(cp);
	}

	i := C.wsq_libversion_number();
	data["sqlite3.versionnumber"] = strconv.Itob(int(i), 10);

	return;
}

type Any interface{};
type ConnectionInfo map[string] Any;

func parseConnInfo(info ConnectionInfo) (name string, flags int, vfs *string, error os.Error)
{
	ok := false;
	any := Any(nil);

	any, ok = info["name"];
	if !ok {
		error = &InterfaceError{"Open: No \"name\" in arguments map."};
		return;
	}
	name, ok = any.(string);
	if !ok {
		error = &InterfaceError{"Open: \"name\" argument not a string."};
		return;
	}

	any, ok = info["sqlite.flags"];
	if ok {
		flags = any.(int);
	}

	any, ok = info["sqlite.vfs"];
	if ok {
		vfs = new(string);
		*vfs = any.(string);
	}

	return;
}

func Open(info ConnectionInfo) (conn *Connection, error os.Error)
{
	name, flags, vfs, error := parseConnInfo(info);
	if error != nil {
		return;
	}

	conn = new(Connection);

	rc := sqliteOk;
	p := C.CString(name);

	if vfs != nil {
		q := C.CString(*vfs);
		rc = int(C.wsq_open(p, &conn.handle, C.int(flags), q));
		C.free(unsafe.Pointer(q));
	}
	else {
		rc = int(C.wsq_open(p, &conn.handle, C.int(flags), nil));
	}

	C.free(unsafe.Pointer(p));
	if rc != sqliteOk {
		error = conn.error();
	}

	return;
}

func (self *Connection) error() (error os.Error) {
	e := new(DatabaseError);
	e.basic = int(C.wsq_errcode(self.handle));
	e.extended = int(C.wsq_extended_errcode(self.handle));
	e.message = C.GoString(C.wsq_errmsg(self.handle));
	return e;
}

func (self *Connection) Cursor() (cursor *Cursor, error os.Error) {
	cursor = new(Cursor);
	cursor.connection = self;
	return;
}

func (self *Connection) Close() (error os.Error) {
	rc := C.wsq_close(self.handle);
	if rc != sqliteOk {
		error = self.error();
	}
	return;
}

func (self *Cursor) Execute(query string, parameters ...) (error os.Error) {
	query = fmt.Sprintf(query, parameters);

	q := C.CString(query);

	rc := C.wsq_prepare(self.connection.handle, q, -1, &self.handle, nil);
	if rc != sqliteOk {
		error = self.connection.error();
		if self.handle != nil {
			// TODO: finalize
		}
		return;
	}

	rc = C.wsq_step(self.handle);
	switch rc {
		case sqliteDone:
			self.result = false;
			// TODO: finalize
		case sqliteRow:
			self.result = true;
			// TODO: obtain results somehow? or later call?
		default:
			error = self.connection.error();
			// TODO: finalize
			return;
	}

	C.free(unsafe.Pointer(q));
	return;
}

func (self *Cursor) FetchOne() (data []interface{}, error os.Error) {
	if !self.result {
		error = &InterfaceError{"FetchOne: No results to fetch!"};
		return;
	}

	nColumns := int(C.wsq_column_count(self.handle));
	if nColumns <= 0 {
		error = &InterfaceError{"FetchOne: No columns in result!"};
		return;
	}

	data = make([]interface{}, nColumns);
	for i := 0; i < nColumns; i++ {
		text := C.wsq_column_text(self.handle, C.int(i));
		data[i] = C.GoString(text);
	}

	rc := C.wsq_step(self.handle);
	switch rc {
		case sqliteDone:
			self.result = false;
			// TODO: finalize
		case sqliteRow:
			self.result = true;
		default:
			error = self.connection.error();
			// TODO: finalize
			return;
	}

	return;
}
func (self *Cursor) FetchRow() (data map[string]interface{}, error os.Error) {
	if !self.result {
		error = &InterfaceError{"FetchRow: No results to fetch!"};
		return;
	}

	nColumns := int(C.wsq_column_count(self.handle));
	if nColumns <= 0 {
		error = &InterfaceError{"FetchRow: No columns in result!"};
		return;
	}

	data = make(map[string]interface{}, nColumns);
	for i := 0; i < nColumns; i++ {
		text := C.wsq_column_text(self.handle, C.int(i));
		name := C.wsq_column_name(self.handle, C.int(i));
		data[C.GoString(name)] = C.GoString(text);
	}

	rc := C.wsq_step(self.handle);
	switch rc {
		case sqliteDone:
			self.result = false;
			// TODO: finalize
		case sqliteRow:
			self.result = true;
		default:
			error = self.connection.error();
			// TODO: finalize
			return;
	}

	return;
}

func (self *Cursor) Close() (error os.Error) {
	if self.handle != nil {
		rc := C.wsq_finalize(self.handle);
		if rc != sqliteOk {
			error = self.connection.error();
		}
	}
	return;
}
<commit_msg>Added flags for Open(). Added default busy timeout on all connections.<commit_after>/*
	THIS IS NOT DONE AT ALL! USE AT YOUR OWN RISK!

	- it would be nice if cgo could grok several .go files,
	so far it can't; so all the C interface stuff has to be
	in one file; bummer that
*/

package sqlite3

/*
#include <stdlib.h>
#include "wrapper.h"
*/
import "C"
import "unsafe"

import "fmt"
import "os"
import "strconv"

/* these are not exported yet since I am not sure they are needed */
const (
	sqliteOk = iota; /* Successful result */
	sqliteError; /* SQL error or missing database */
	sqliteInternal; /* Internal logic error in SQLite */
	sqlitePerm; /* Access permission denied */
	sqliteAbort; /* Callback routine requested an abort */
	sqliteBusy; /* The database file is locked */
	sqliteLocked; /* A table in the database is locked */
	sqliteNomem; /* A malloc() failed */
	sqliteReadonly; /* Attempt to write a readonly database */
	sqliteInterrupt; /* Operation terminated by sqlite3_interrupt()*/
	sqliteIoerr; /* Some kind of disk I/O error occurred */
	sqliteCorrupt; /* The database disk image is malformed */
	sqlite_Notfound; /* NOT USED. Table or record not found */
	sqliteFull; /* Insertion failed because database is full */
	sqliteCantopen; /* Unable to open the database file */
	sqliteProtocol; /* NOT USED. Database lock protocol error */
	sqliteEmpty; /* Database is empty */
	sqliteSchema; /* The database schema changed */
	sqliteToobig; /* String or BLOB exceeds size limit */
	sqliteConstraint; /* Abort due to constraint violation */
	sqliteMismatch; /* Data type mismatch */
	sqliteMisuse; /* Library used incorrectly */
	sqliteNolfs; /* Uses OS features not supported on host */
	sqliteAuth; /* Authorization denied */
	sqliteFormat; /* Auxiliary database format error */
	sqliteRange; /* 2nd parameter to sqlite3_bind out of range */
	sqliteNotadb; /* File opened that is not a database file */
	sqliteRow = 100; /* sqlite3_step() has another row ready */
	sqliteDone = 101;  /* sqlite3_step() has finished executing */
)

/*
	These constants can be or'd together and passed as the
	"sqlite3.flags" argument to Open(). Some of them only
	apply if "sqlite3.vfs" is also passed. See the SQLite
	documentation for details.
*/
const (
	OpenReadOnly = 0x00000001;
	OpenReadWrite = 0x00000002;
	OpenCreate = 0x00000004;
	OpenDeleteOnClose = 0x00000008;  /* VFS only */
	OpenExclusive = 0x00000010;  /* VFS only */
	OpenMainDb = 0x00000100;  /* VFS only */
	OpenTempDb = 0x00000200;  /* VFS only */
	OpenTransientDb = 0x00000400;  /* VFS only */
	OpenMainJournal = 0x00000800;  /* VFS only */
	OpenTempJournal = 0x00001000;  /* VFS only */
	OpenSubJournal = 0x00002000;  /* VFS only */
	OpenMasterJournal = 0x00004000;  /* VFS only */
	OpenNoMutex = 0x00008000;
	OpenFullMutex = 0x00010000;
	OpenSharedCache = 0x00020000;
	OpenPrivateCache = 0x00040000;
)

const defaultTimeoutMilliseconds = 16*1000;

type Connection struct {
	/* pointer to struct sqlite3 */
	handle C.wsq_db;
}

type Cursor struct {
	/* pointer to struct sqlite3_stmt */
	handle C.wsq_st;
	/* connection we were created on */
	connection *Connection;
	/* the last query yielded results */
	result bool;
}

func Version() (data map[string]string, error os.Error)
{
	data = make(map[string]string);

	cp := C.wsq_libversion();
	if (cp == nil) {
		error = &InterfaceError{"Version: couldn't get library version!"};
		return;
	}
	data["version"] = C.GoString(cp);
	// TODO: fake client and server keys?

	cp = C.wsq_sourceid();
	if (cp != nil) {
		data["sqlite3.sourceid"] = C.GoString(cp);
	}

	i := C.wsq_libversion_number();
	data["sqlite3.versionnumber"] = strconv.Itob(int(i), 10);

	return;
}

type Any interface{};
type ConnectionInfo map[string] Any;

func parseConnInfo(info ConnectionInfo) (name string, flags int, vfs *string, error os.Error)
{
	ok := false;
	any := Any(nil);

	any, ok = info["name"];
	if !ok {
		error = &InterfaceError{"Open: No \"name\" in arguments map."};
		return;
	}
	name, ok = any.(string);
	if !ok {
		error = &InterfaceError{"Open: \"name\" argument not a string."};
		return;
	}

	any, ok = info["sqlite.flags"];
	if ok {
		flags = any.(int);
	}

	any, ok = info["sqlite.vfs"];
	if ok {
		vfs = new(string);
		*vfs = any.(string);
	}

	return;
}

func Open(info ConnectionInfo) (conn *Connection, error os.Error)
{
	name, flags, vfs, error := parseConnInfo(info);
	if error != nil {
		return;
	}

	conn = new(Connection);

	rc := sqliteOk;
	p := C.CString(name);

	if vfs != nil {
		q := C.CString(*vfs);
		rc = int(C.wsq_open(p, &conn.handle, C.int(flags), q));
		C.free(unsafe.Pointer(q));
	}
	else {
		rc = int(C.wsq_open(p, &conn.handle, C.int(flags), nil));
	}

	C.free(unsafe.Pointer(p));
	if rc != sqliteOk {
		error = conn.error();
	}
	else {
		rc := C.wsq_busy_timeout(conn.handle, defaultTimeoutMilliseconds);
		if rc != sqliteOk {
			error = conn.error();
		}
	}

	return;
}

func (self *Connection) error() (error os.Error) {
	e := new(DatabaseError);
	e.basic = int(C.wsq_errcode(self.handle));
	e.extended = int(C.wsq_extended_errcode(self.handle));
	e.message = C.GoString(C.wsq_errmsg(self.handle));
	return e;
}

func (self *Connection) Cursor() (cursor *Cursor, error os.Error) {
	cursor = new(Cursor);
	cursor.connection = self;
	return;
}

func (self *Connection) Close() (error os.Error) {
	rc := C.wsq_close(self.handle);
	if rc != sqliteOk {
		error = self.error();
	}
	return;
}

func (self *Cursor) Execute(query string, parameters ...) (error os.Error) {
	query = fmt.Sprintf(query, parameters);

	q := C.CString(query);

	rc := C.wsq_prepare(self.connection.handle, q, -1, &self.handle, nil);
	if rc != sqliteOk {
		error = self.connection.error();
		if self.handle != nil {
			// TODO: finalize
		}
		return;
	}

	rc = C.wsq_step(self.handle);
	switch rc {
		case sqliteDone:
			self.result = false;
			// TODO: finalize
		case sqliteRow:
			self.result = true;
			// TODO: obtain results somehow? or later call?
		default:
			error = self.connection.error();
			// TODO: finalize
			return;
	}

	C.free(unsafe.Pointer(q));
	return;
}

func (self *Cursor) FetchOne() (data []interface{}, error os.Error) {
	if !self.result {
		error = &InterfaceError{"FetchOne: No results to fetch!"};
		return;
	}

	nColumns := int(C.wsq_column_count(self.handle));
	if nColumns <= 0 {
		error = &InterfaceError{"FetchOne: No columns in result!"};
		return;
	}

	data = make([]interface{}, nColumns);
	for i := 0; i < nColumns; i++ {
		text := C.wsq_column_text(self.handle, C.int(i));
		data[i] = C.GoString(text);
	}

	rc := C.wsq_step(self.handle);
	switch rc {
		case sqliteDone:
			self.result = false;
			// TODO: finalize
		case sqliteRow:
			self.result = true;
		default:
			error = self.connection.error();
			// TODO: finalize
			return;
	}

	return;
}
func (self *Cursor) FetchRow() (data map[string]interface{}, error os.Error) {
	if !self.result {
		error = &InterfaceError{"FetchRow: No results to fetch!"};
		return;
	}

	nColumns := int(C.wsq_column_count(self.handle));
	if nColumns <= 0 {
		error = &InterfaceError{"FetchRow: No columns in result!"};
		return;
	}

	data = make(map[string]interface{}, nColumns);
	for i := 0; i < nColumns; i++ {
		text := C.wsq_column_text(self.handle, C.int(i));
		name := C.wsq_column_name(self.handle, C.int(i));
		data[C.GoString(name)] = C.GoString(text);
	}

	rc := C.wsq_step(self.handle);
	switch rc {
		case sqliteDone:
			self.result = false;
			// TODO: finalize
		case sqliteRow:
			self.result = true;
		default:
			error = self.connection.error();
			// TODO: finalize
			return;
	}

	return;
}

func (self *Cursor) Close() (error os.Error) {
	if self.handle != nil {
		rc := C.wsq_finalize(self.handle);
		if rc != sqliteOk {
			error = self.connection.error();
		}
	}
	return;
}
<|endoftext|>


<commit_before>package fwk

import (
	"fmt"
	"reflect"
)

type Error interface {
	error
}

type statuscode int

func (sc statuscode) Error() string {
	return fmt.Sprintf("fwk: error code [%d]", int(sc))
}

type Context interface {
	Id() int64      // id of this context (e.g. entry number or some kind of event number)
	Slot() int      // slot number in the pool of event sequences
	Store() Store   // data store corresponding to the id+slot
	Msg() MsgStream // messaging for this context (id+slot)
}

type Component interface {
	Name() string // Name of the component (ex: "MyPropagator")
}

type ComponentMgr interface {
	Component(n string) Component
	HasComponent(n string) bool
	Components() []Component
	New(t, n string) (Component, Error)
}

type Task interface {
	Component

	StartTask(ctx Context) Error
	Process(ctx Context) Error
	StopTask(ctx Context) Error
}

type TaskMgr interface {
	AddTask(tsk Task) Error
	DelTask(tsk Task) Error
	HasTask(n string) bool
	GetTask(n string) Task
	Tasks() []Task
}

type Configurer interface {
	Component
	Configure(ctx Context) Error
}

type Svc interface {
	Component

	StartSvc(ctx Context) Error
	StopSvc(ctx Context) Error
}

type SvcMgr interface {
	AddSvc(svc Svc) Error
	DelSvc(svc Svc) Error
	HasSvc(n string) bool
	GetSvc(n string) Svc
	Svcs() []Svc
}

type App interface {
	Component
	ComponentMgr
	SvcMgr
	TaskMgr
	PropMgr

	Run() Error
}

type PropMgr interface {
	DeclProp(c Component, name string, ptr interface{}) Error
	SetProp(c Component, name string, value interface{}) Error
	GetProp(c Component, name string) (interface{}, Error)
}

type Property interface {
	DeclProp(name string, ptr interface{}) Error
	SetProp(name string, value interface{}) Error
	GetProp(name string) (interface{}, Error)
}

type Store interface {
	Get(key string) (interface{}, Error)
	Put(key string, value interface{}) Error
	Has(key string) bool
}

// DeclPorter is the interface to declare input/output ports for the data flow.
type DeclPorter interface {
	DeclInPort(name string, t reflect.Type) Error
	DeclOutPort(name string, t reflect.Type) Error
}

// PortMgr is the interface to manage input/output ports for the data flow
type PortMgr interface {
	DeclInPort(c Component, name string, t reflect.Type) Error
	DeclOutPort(c Component, name string, t reflect.Type) Error
}

type Level int

const (
	LvlVerbose Level = -20
	LvlDebug   Level = -10
	LvlInfo    Level = 0
	LvlWarning Level = 10
	LvlError   Level = 20
)

type MsgStream interface {
	Debugf(format string, a ...interface{}) (int, Error)
	Infof(format string, a ...interface{}) (int, Error)
	Warnf(format string, a ...interface{}) (int, Error)
	Errorf(format string, a ...interface{}) (int, Error)

	Msg(lvl Level, format string, a ...interface{}) (int, Error)
}

// Deleter prepares values to be GC-reclaimed
type Deleter interface {
	Delete() error
}

// EOF
<commit_msg>core: make App a PortMgr. add Msg() method<commit_after>package fwk

import (
	"fmt"
	"reflect"
)

type Error interface {
	error
}

type statuscode int

func (sc statuscode) Error() string {
	return fmt.Sprintf("fwk: error code [%d]", int(sc))
}

type Context interface {
	Id() int64      // id of this context (e.g. entry number or some kind of event number)
	Slot() int      // slot number in the pool of event sequences
	Store() Store   // data store corresponding to the id+slot
	Msg() MsgStream // messaging for this context (id+slot)
}

type Component interface {
	Name() string // Name of the component (ex: "MyPropagator")
}

type ComponentMgr interface {
	Component(n string) Component
	HasComponent(n string) bool
	Components() []Component
	New(t, n string) (Component, Error)
}

type Task interface {
	Component

	StartTask(ctx Context) Error
	Process(ctx Context) Error
	StopTask(ctx Context) Error
}

type TaskMgr interface {
	AddTask(tsk Task) Error
	DelTask(tsk Task) Error
	HasTask(n string) bool
	GetTask(n string) Task
	Tasks() []Task
}

type Configurer interface {
	Component
	Configure(ctx Context) Error
}

type Svc interface {
	Component

	StartSvc(ctx Context) Error
	StopSvc(ctx Context) Error
}

type SvcMgr interface {
	AddSvc(svc Svc) Error
	DelSvc(svc Svc) Error
	HasSvc(n string) bool
	GetSvc(n string) Svc
	Svcs() []Svc
}

type App interface {
	Component
	ComponentMgr
	SvcMgr
	TaskMgr
	PropMgr
	PortMgr

	Run() Error

	Msg() MsgStream
}

type PropMgr interface {
	DeclProp(c Component, name string, ptr interface{}) Error
	SetProp(c Component, name string, value interface{}) Error
	GetProp(c Component, name string) (interface{}, Error)
}

type Property interface {
	DeclProp(name string, ptr interface{}) Error
	SetProp(name string, value interface{}) Error
	GetProp(name string) (interface{}, Error)
}

type Store interface {
	Get(key string) (interface{}, Error)
	Put(key string, value interface{}) Error
	Has(key string) bool
}

// DeclPorter is the interface to declare input/output ports for the data flow.
type DeclPorter interface {
	DeclInPort(name string, t reflect.Type) Error
	DeclOutPort(name string, t reflect.Type) Error
}

// PortMgr is the interface to manage input/output ports for the data flow
type PortMgr interface {
	DeclInPort(c Component, name string, t reflect.Type) Error
	DeclOutPort(c Component, name string, t reflect.Type) Error
}

type Level int

const (
	LvlVerbose Level = -20
	LvlDebug   Level = -10
	LvlInfo    Level = 0
	LvlWarning Level = 10
	LvlError   Level = 20
)

type MsgStream interface {
	Debugf(format string, a ...interface{}) (int, Error)
	Infof(format string, a ...interface{}) (int, Error)
	Warnf(format string, a ...interface{}) (int, Error)
	Errorf(format string, a ...interface{}) (int, Error)

	Msg(lvl Level, format string, a ...interface{}) (int, Error)
}

// Deleter prepares values to be GC-reclaimed
type Deleter interface {
	Delete() error
}

// EOF
<|endoftext|>


<commit_before>package rst

import (
	"net/http"
	"strconv"
	"strings"
	"time"
)

// DefaultAccessControl defines a limited CORS policy that only allows simple
// cross-origin requests.
var DefaultAccessControl = &AccessControlResponse{
	Origin:         "*",
	Credentials:    true,
	AllowedHeaders: nil,
	ExposedHeaders: []string{"etag"},
	Methods:        nil,
	MaxAge:         24 * time.Hour,
}

// PermissiveAccessControl defines a permissive CORS policy in which all methods
// and all headers are allowed for all origins.
var PermissiveAccessControl = &AccessControlResponse{
	Origin:         "*",
	Credentials:    true,
	AllowedHeaders: []string{},
	ExposedHeaders: []string{"etag"},
	Methods:        []string{},
	MaxAge:         24 * time.Hour,
}

/*
Preflighter is implemented by endpoints wishing to customize the response to
a CORS preflighted request.

	func (e *endpoint) Preflight(req *rst.AccessControlRequest, vars rst.RouteVars, r *http.Request) *rst.AccessControlResponse {
		if time.Now().Hour() < 12 {
			return &rst.AccessControlResponse{
				Origin: "morning.example.com",
				Methods: []string{"GET"},
			}
		}

		return &rst.AccessControlResponse{
			Origin: "afternoon.example.com",
			Methods: []string{"POST"},
		}
	}
*/
type Preflighter interface {
	Preflight(*AccessControlRequest, RouteVars, *http.Request) *AccessControlResponse
}

// AccessControlRequest represents the headers of a CORS access control request.
type AccessControlRequest struct {
	Origin  string
	Method  string
	Headers []string
}

func (ac *AccessControlRequest) isEmpty() bool {
	return ac.Origin == "" && ac.Method == "" && len(ac.Headers) == 0
}

// ParseAccessControlRequest returns a new instance of AccessControlRequest
// filled with CORS headers found in r.
func ParseAccessControlRequest(r *http.Request) *AccessControlRequest {
	var headers []string
	if h := r.Header.Get("Access-Control-Request-Headers"); h != "" {
		headers = strings.Split(strings.Replace(r.Header.Get("Access-Control-Request-Headers"), " ", "", -1), ",")
	}
	return &AccessControlRequest{
		Origin:  r.Header.Get("Origin"),
		Method:  r.Header.Get("Access-Control-Request-Method"),
		Headers: headers,
	}

	// TODO: remove duplicated headers before serving them back.
}

// AccessControlResponse defines the response headers to a CORS access control
// request.
type AccessControlResponse struct {
	Origin         string
	ExposedHeaders []string
	Methods        []string // Empty array means any, nil means none.
	AllowedHeaders []string // Empty array means any, nil means none.
	Credentials    bool
	MaxAge         time.Duration
}

type accessControlHandler struct {
	endpoint Endpoint
	*AccessControlResponse
}

func newAccessControlHandler(endpoint Endpoint, ac *AccessControlResponse) *accessControlHandler {
	return &accessControlHandler{
		endpoint:              endpoint,
		AccessControlResponse: ac,
	}
}

func (h *accessControlHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	if _, exists := r.Header["Origin"]; !exists {
		return
	}

	req := ParseAccessControlRequest(r)

	var resp *AccessControlResponse
	if h.endpoint == nil {
		resp = h.AccessControlResponse
	} else {
		if preflighter, implemented := h.endpoint.(Preflighter); implemented && strings.ToUpper(r.Method) == Options {
			// If Options and endpoint implements Preflighter, call Preflight.
			resp = preflighter.Preflight(req, getVars(r), r)
		} else {
			resp = h.AccessControlResponse
		}
	}

	// Adding a vary if an origin is specified in the response.
	defer func() {
		if allowed := w.Header().Get("Access-Control-Allow-Origin"); allowed != "" && allowed != "*" {
			w.Header().Add("Vary", "Origin")
		}
	}()

	// Writing response headers
	if resp.Origin != "" {
		w.Header().Set("Access-Control-Allow-Origin", resp.Origin)
	}
	w.Header().Set("Access-Control-Allow-Credentials", strconv.FormatBool(resp.Credentials))

	// Exposed headers
	if len(resp.ExposedHeaders) > 0 {
		w.Header().Set("Access-Control-Expose-Headers", strings.Join(resp.ExposedHeaders, ", "))
	}

	// OPTIONS only
	if strings.ToUpper(r.Method) != Options {
		return
	}

	w.Header().Set("Access-Control-Max-Age", strconv.Itoa(int(resp.MaxAge.Seconds())))

	if req.Method != "" && resp.Methods != nil {
		var methods []string
		if len(resp.Methods) == 0 {
			methods = AllowedMethods(h.endpoint)
		} else {
			methods = resp.Methods
		}
		w.Header().Set("Access-Control-Allow-Methods", strings.Join(methods, ", "))
	}

	if len(req.Headers) > 0 && resp.AllowedHeaders != nil {
		var headers []string
		if len(resp.AllowedHeaders) == 0 {
			headers = req.Headers
		} else {
			headers = resp.AllowedHeaders
		}
		w.Header().Set("Access-Control-Allow-Headers", strings.Join(headers, ", "))
	}
}
<commit_msg>Systematic normalization of header keys.<commit_after>package rst

import (
	"net/http"
	"strconv"
	"strings"
	"time"
)

func normalizeHeaderArray(headers []string) []string {
	for i, name := range headers {
		headers[i] = http.CanonicalHeaderKey(name)
	}
	return headers
}

var defaultExposedHeaders = []string{http.CanonicalHeaderKey("etag")}

// DefaultAccessControl defines a limited CORS policy that only allows simple
// cross-origin requests.
var DefaultAccessControl = &AccessControlResponse{
	Origin:         "*",
	Credentials:    true,
	AllowedHeaders: nil,
	ExposedHeaders: defaultExposedHeaders,
	Methods:        nil,
	MaxAge:         24 * time.Hour,
}

// PermissiveAccessControl defines a permissive CORS policy in which all methods
// and all headers are allowed for all origins.
var PermissiveAccessControl = &AccessControlResponse{
	Origin:         "*",
	Credentials:    true,
	AllowedHeaders: []string{},
	ExposedHeaders: defaultExposedHeaders,
	Methods:        []string{},
	MaxAge:         24 * time.Hour,
}

/*
Preflighter is implemented by endpoints wishing to customize the response to
a CORS preflighted request.

	func (e *endpoint) Preflight(req *rst.AccessControlRequest, vars rst.RouteVars, r *http.Request) *rst.AccessControlResponse {
		if time.Now().Hour() < 12 {
			return &rst.AccessControlResponse{
				Origin: "morning.example.com",
				Methods: []string{"GET"},
			}
		}

		return &rst.AccessControlResponse{
			Origin: "afternoon.example.com",
			Methods: []string{"POST"},
		}
	}
*/
type Preflighter interface {
	Preflight(*AccessControlRequest, RouteVars, *http.Request) *AccessControlResponse
}

// AccessControlRequest represents the headers of a CORS access control request.
type AccessControlRequest struct {
	Origin  string
	Method  string
	Headers []string
}

func (ac *AccessControlRequest) isEmpty() bool {
	return ac.Origin == "" && ac.Method == "" && len(ac.Headers) == 0
}

// ParseAccessControlRequest returns a new instance of AccessControlRequest
// filled with CORS headers found in r.
func ParseAccessControlRequest(r *http.Request) *AccessControlRequest {
	var headers []string
	if h := r.Header.Get("Access-Control-Request-Headers"); h != "" {
		headers = strings.Split(strings.Replace(r.Header.Get("Access-Control-Request-Headers"), " ", "", -1), ",")
	}
	return &AccessControlRequest{
		Origin:  r.Header.Get("Origin"),
		Method:  r.Header.Get("Access-Control-Request-Method"),
		Headers: headers,
	}

	// TODO: remove duplicated headers before serving them back.
}

// AccessControlResponse defines the response headers to a CORS access control
// request.
type AccessControlResponse struct {
	Origin         string
	ExposedHeaders []string
	Methods        []string // Empty array means any, nil means none.
	AllowedHeaders []string // Empty array means any, nil means none.
	Credentials    bool
	MaxAge         time.Duration
}

type accessControlHandler struct {
	endpoint Endpoint
	*AccessControlResponse
}

func newAccessControlHandler(endpoint Endpoint, ac *AccessControlResponse) *accessControlHandler {
	return &accessControlHandler{
		endpoint:              endpoint,
		AccessControlResponse: ac,
	}
}

func (h *accessControlHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	if _, exists := r.Header["Origin"]; !exists {
		return
	}

	req := ParseAccessControlRequest(r)

	var resp *AccessControlResponse
	if h.endpoint == nil {
		resp = h.AccessControlResponse
	} else {
		if preflighter, implemented := h.endpoint.(Preflighter); implemented && strings.ToUpper(r.Method) == Options {
			// If Options and endpoint implements Preflighter, call Preflight.
			resp = preflighter.Preflight(req, getVars(r), r)
		} else {
			resp = h.AccessControlResponse
		}
	}

	// Adding a vary if an origin is specified in the response.
	defer func() {
		if allowed := w.Header().Get("Access-Control-Allow-Origin"); allowed != "" && allowed != "*" {
			w.Header().Add("Vary", "Origin")
		}
	}()

	// Writing response headers
	if resp.Origin != "" {
		w.Header().Set("Access-Control-Allow-Origin", resp.Origin)
	}
	w.Header().Set("Access-Control-Allow-Credentials", strconv.FormatBool(resp.Credentials))

	// Exposed headers
	if len(resp.ExposedHeaders) > 0 {
		w.Header().Set("Access-Control-Expose-Headers", strings.Join(normalizeHeaderArray(resp.ExposedHeaders), ", "))
	}

	// OPTIONS only
	if strings.ToUpper(r.Method) != Options {
		return
	}

	w.Header().Set("Access-Control-Max-Age", strconv.Itoa(int(resp.MaxAge.Seconds())))

	if req.Method != "" && resp.Methods != nil {
		var methods []string
		if len(resp.Methods) == 0 {
			methods = AllowedMethods(h.endpoint)
		} else {
			methods = resp.Methods
		}
		w.Header().Set("Access-Control-Allow-Methods", strings.Join(methods, ", "))
	}

	if len(req.Headers) > 0 && resp.AllowedHeaders != nil {
		var headers []string
		if len(resp.AllowedHeaders) == 0 {
			headers = req.Headers
		} else {
			headers = resp.AllowedHeaders
		}
		w.Header().Set("Access-Control-Allow-Headers", strings.Join(normalizeHeaderArray(headers), ", "))
	}
}
<|endoftext|>


<commit_before>package cors

import (
	"fmt"
	"net/http"
	"strings"
)

type CorsHandler struct {
	ALLOWED_METHODS []string
	ALLOWED_ORIGINS []string
	ALLOWED_HEADERS []string
	handler         http.Handler
}

func New(handler http.Handler) *CorsHandler {
	return &CorsHandler{
		ALLOWED_METHODS: []string{"GET", "POST", "PUT", "DELETE", "HEAD", "OPTIONS"},
		ALLOWED_ORIGINS: []string{"*"},
		ALLOWED_HEADERS: []string{"Content-Type"},
		handler:         handler,
	}
}
func (cors *CorsHandler) init() {
	cors.ALLOWED_METHODS = []string{"GET", "POST", "PUT", "DELETE", "HEAD", "OPTIONS"}
	cors.ALLOWED_ORIGINS = []string{"*"}
	cors.ALLOWED_HEADERS = []string{"Content-Type"}
}
func (cors *CorsHandler) AllowOrigin(origin string) {
	if origin == "*" {
		cors.ALLOWED_ORIGINS = []string{"*"}
	}
	for i := 0; i < len(cors.ALLOWED_ORIGINS); i++ {
		if origin == cors.ALLOWED_ORIGINS[i] {
			return
		}
	}
	cors.ALLOWED_ORIGINS = append(cors.ALLOWED_ORIGINS, origin)
}
func (cors *CorsHandler) AllowMethod(method string) {
	method = strings.ToUpper(method)
	for i := 0; i < len(cors.ALLOWED_METHODS); i++ {
		if method == cors.ALLOWED_METHODS[i] {
			return
		}
	}
	cors.ALLOWED_METHODS = append(cors.ALLOWED_METHODS, method)
}
func (cors *CorsHandler) AllowHeader(header string) {
	for i := 0; i < len(cors.ALLOWED_HEADERS); i++ {
		if header == cors.ALLOWED_HEADERS[i] {
			return
		}
	}
	cors.ALLOWED_HEADERS = append(cors.ALLOWED_HEADERS, header)

}
func (cors *CorsHandler) RemoveOrigin(origin string) {
	for i := 0; i < len(cors.ALLOWED_ORIGINS); i++ {
		if origin == cors.ALLOWED_ORIGINS[i] {
			cors.ALLOWED_ORIGINS = cors.ALLOWED_ORIGINS[:i+copy(cors.ALLOWED_ORIGINS[i:], cors.ALLOWED_ORIGINS[i+1:])]
		}
	}

}
func (cors *CorsHandler) RemoveMethod(method string) {
	method = strings.ToUpper(method)
	for i := 0; i < len(cors.ALLOWED_METHODS); i++ {
		if method == cors.ALLOWED_METHODS[i] {
			cors.ALLOWED_METHODS = cors.ALLOWED_METHODS[:i+copy(cors.ALLOWED_METHODS[i:], cors.ALLOWED_METHODS[i+1:])]
		}
	}
}
func (cors *CorsHandler) RemoveHeader(header string) {
	for i := 0; i < len(cors.ALLOWED_HEADERS); i++ {
		if header == cors.ALLOWED_HEADERS[i] {
			cors.ALLOWED_HEADERS = cors.ALLOWED_HEADERS[:i+copy(cors.ALLOWED_HEADERS[i:], cors.ALLOWED_HEADERS[i+1:])]
		}
	}
}
func (cors *CorsHandler) IsOriginAllowed(origin string) bool {
	for i := 0; i < len(cors.ALLOWED_ORIGINS); i++ {
		if "*" == cors.ALLOWED_ORIGINS[i] {
			return true
		} else if origin == cors.ALLOWED_ORIGINS[i] {
			return true
		}
	}
	return false
}
func (cors *CorsHandler) IsMethodAllowed(method string) bool {
	method = strings.ToUpper(method)
	for i := 0; i < len(cors.ALLOWED_METHODS); i++ {
		if method == cors.ALLOWED_METHODS[i] {
			return true
		}
	}
	return false
}
func (cors *CorsHandler) IsHeaderAllowed(header string) bool {
	for i := 0; i < len(cors.ALLOWED_HEADERS); i++ {
		if header == cors.ALLOWED_HEADERS[i] {
			return true
		}
	}
	return false
}
func (cors *CorsHandler) AllowedMethods() string {
	methods := ""
	for i := 0; i < len(cors.ALLOWED_METHODS); i++ {
		if methods == "" {
			methods = cors.ALLOWED_METHODS[i]
		} else {
			methods = fmt.Sprintf("%s, %s", methods, cors.ALLOWED_METHODS[i])
		}
	}
	return methods
}
func (cors *CorsHandler) AllowedHeaders() string {
	headers := ""
	for i := 0; i < len(cors.ALLOWED_HEADERS); i++ {
		if headers == "" {
			headers = cors.ALLOWED_HEADERS[i]
		} else {
			headers = fmt.Sprintf("%s, %s", headers, cors.ALLOWED_HEADERS[i])
		}
	}
	return headers
}
func (cors *CorsHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
	origin := req.Header.Get("Origin")
	if origin != "" && cors.IsOriginAllowed(origin) {
		w.Header().Add("Access-Control-Allow-Origin", origin)
		w.Header().Add("Access-Control-Allow-Methods", cors.AllowedMethods())
		w.Header().Add("Access-Control-Allow-Headers", cors.AllowedHeaders())
	}
	cors.handler.ServeHTTP(w, req)
}
<commit_msg>Adding support for Access-Control-Allow-Credentials<commit_after>package cors

import (
	"fmt"
	"net/http"
	"strings"
)

type CorsHandler struct {
	ALLOWED_METHODS   []string
	ALLOWED_ORIGINS   []string
	ALLOWED_HEADERS   []string
	ALLOW_CREDENTIALS string
	handler           http.Handler
}

func New(handler http.Handler) *CorsHandler {
	return &CorsHandler{
		ALLOWED_METHODS:   []string{"GET", "POST", "PUT", "DELETE", "HEAD", "OPTIONS"},
		ALLOWED_ORIGINS:   []string{"*"},
		ALLOWED_HEADERS:   []string{"Content-Type"},
		ALLOW_CREDENTIALS: "true",
		handler:           handler,
	}
}
func (cors *CorsHandler) AllowOrigin(origin string) {
	if origin == "*" {
		cors.ALLOWED_ORIGINS = []string{"*"}
	}
	for i := 0; i < len(cors.ALLOWED_ORIGINS); i++ {
		if origin == cors.ALLOWED_ORIGINS[i] {
			return
		}
	}
	cors.ALLOWED_ORIGINS = append(cors.ALLOWED_ORIGINS, origin)
}
func (cors *CorsHandler) AllowMethod(method string) {
	method = strings.ToUpper(method)
	for i := 0; i < len(cors.ALLOWED_METHODS); i++ {
		if method == cors.ALLOWED_METHODS[i] {
			return
		}
	}
	cors.ALLOWED_METHODS = append(cors.ALLOWED_METHODS, method)
}
func (cors *CorsHandler) AllowHeader(header string) {
	for i := 0; i < len(cors.ALLOWED_HEADERS); i++ {
		if header == cors.ALLOWED_HEADERS[i] {
			return
		}
	}
	cors.ALLOWED_HEADERS = append(cors.ALLOWED_HEADERS, header)

}
func (cors *CorsHandler) AllowCredentials(creds bool) {
	if creds {
		cors.ALLOW_CREDENTIALS = "true"
	} else {
		cors.ALLOW_CREDENTIALS = "false"
	}
}
func (cors *CorsHandler) RemoveOrigin(origin string) {
	for i := 0; i < len(cors.ALLOWED_ORIGINS); i++ {
		if origin == cors.ALLOWED_ORIGINS[i] {
			cors.ALLOWED_ORIGINS = cors.ALLOWED_ORIGINS[:i+copy(cors.ALLOWED_ORIGINS[i:], cors.ALLOWED_ORIGINS[i+1:])]
		}
	}

}
func (cors *CorsHandler) RemoveMethod(method string) {
	method = strings.ToUpper(method)
	for i := 0; i < len(cors.ALLOWED_METHODS); i++ {
		if method == cors.ALLOWED_METHODS[i] {
			cors.ALLOWED_METHODS = cors.ALLOWED_METHODS[:i+copy(cors.ALLOWED_METHODS[i:], cors.ALLOWED_METHODS[i+1:])]
		}
	}
}
func (cors *CorsHandler) RemoveHeader(header string) {
	for i := 0; i < len(cors.ALLOWED_HEADERS); i++ {
		if header == cors.ALLOWED_HEADERS[i] {
			cors.ALLOWED_HEADERS = cors.ALLOWED_HEADERS[:i+copy(cors.ALLOWED_HEADERS[i:], cors.ALLOWED_HEADERS[i+1:])]
		}
	}
}
func (cors *CorsHandler) IsOriginAllowed(origin string) bool {
	for i := 0; i < len(cors.ALLOWED_ORIGINS); i++ {
		if "*" == cors.ALLOWED_ORIGINS[i] {
			return true
		} else if origin == cors.ALLOWED_ORIGINS[i] {
			return true
		}
	}
	return false
}
func (cors *CorsHandler) IsMethodAllowed(method string) bool {
	method = strings.ToUpper(method)
	for i := 0; i < len(cors.ALLOWED_METHODS); i++ {
		if method == cors.ALLOWED_METHODS[i] {
			return true
		}
	}
	return false
}
func (cors *CorsHandler) IsHeaderAllowed(header string) bool {
	for i := 0; i < len(cors.ALLOWED_HEADERS); i++ {
		if header == cors.ALLOWED_HEADERS[i] {
			return true
		}
	}
	return false
}
func (cors *CorsHandler) AllowedMethods() string {
	methods := ""
	for i := 0; i < len(cors.ALLOWED_METHODS); i++ {
		if methods == "" {
			methods = cors.ALLOWED_METHODS[i]
		} else {
			methods = fmt.Sprintf("%s, %s", methods, cors.ALLOWED_METHODS[i])
		}
	}
	return methods
}
func (cors *CorsHandler) AllowedHeaders() string {
	headers := ""
	for i := 0; i < len(cors.ALLOWED_HEADERS); i++ {
		if headers == "" {
			headers = cors.ALLOWED_HEADERS[i]
		} else {
			headers = fmt.Sprintf("%s, %s", headers, cors.ALLOWED_HEADERS[i])
		}
	}
	return headers
}
func (cors *CorsHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
	origin := req.Header.Get("Origin")
	if origin != "" && cors.IsOriginAllowed(origin) {
		w.Header().Add("Access-Control-Allow-Origin", origin)
		w.Header().Add("Access-Control-Allow-Methods", cors.AllowedMethods())
		w.Header().Add("Access-Control-Allow-Headers", cors.AllowedHeaders())
		w.Header().Add("Access-Control-Allow-Credentials", string(cors.ALLOW_CREDENTIALS))
	}
	cors.handler.ServeHTTP(w, req)
}
<|endoftext|>


<commit_before>package login

import (
	"github.com/AitorGuerrero/UserGo/user"
	"fmt"
)

type Command struct {
	Login user.Login
	UserSource user.Source
}

type Request struct {
	Id string
	Passkey string
	Namespace string
}

type Response struct {
	SessionToken string
}

func (c Command) Execute(req Request) (res Response, err error) {
	token, err := c.getTokenFromUserIfCorrectLogin(
		user.ParseId(req.Id),
		req.Passkey,
		user.Namespace(req.Namespace),
	)
	if _, ok := err.(user.NotExistentUser); ok {
		return res, UserDoesNotExist{err, req.Id}
	}
	if _, ok := err.(user.IncorrectPasskeyError); ok {
		return res, IncorrectPasskeyError{err, req.Passkey}
	}
	if _, ok := err.(user.IncorrectNamespaceError); ok {
		return res, IncorrectNamespaceError{err}
	}

	if(nil != err) {
		return
	}
	res.SessionToken = token.Serialize()

	return
}

func (c Command) getTokenFromUserIfCorrectLogin(uid user.Id, up string, n user.Namespace) (tc user.Token, err error) {
	u, err := c.getUserIfCorrectLogin(uid, up, n)
	if nil != err {
		return
	}
 	tc = u.Token

	return
}

func (c Command) getUserIfCorrectLogin(uid user.Id, up string, n user.Namespace) (u *user.User, err error) {
	u, err = c.Login.Try(uid, up, n)
	fmt.Print("AA", err, "\n")
	if(nil != err) {
		return
	}

	return
}
<commit_msg>ltl refactor<commit_after>package login

import (
	"github.com/AitorGuerrero/UserGo/user"
)

type Command struct {
	Login user.Login
	UserSource user.Source
}

type Request struct {
	Id string
	Passkey string
	Namespace string
}

type Response struct {
	SessionToken string
}

func (c Command) Execute(req Request) (res Response, err error) {
	u, err := c.Login.Try(
		user.ParseId(req.Id),
		req.Passkey,
		user.Namespace(req.Namespace),
	)

	if _, ok := err.(user.NotExistentUser); ok {
		return res, UserDoesNotExist{err, req.Id}
	}
	if _, ok := err.(user.IncorrectPasskeyError); ok {
		return res, IncorrectPasskeyError{err, req.Passkey}
	}
	if _, ok := err.(user.IncorrectNamespaceError); ok {
		return res, IncorrectNamespaceError{err}
	}
	if(nil != err) {
		return
	}
	res.SessionToken = u.Token.Serialize()

	return
}
<|endoftext|>


<commit_before>// Copyright (c) 2017 Cisco and/or its affiliates.
//
// 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 etcdv3

import (
	"errors"
	"testing"

	"time"

	"github.com/coreos/etcd/clientv3"
	"github.com/coreos/etcd/mvcc/mvccpb"
	"github.com/ligato/cn-infra/datasync"
	"github.com/ligato/cn-infra/db/keyval"
	"github.com/ligato/cn-infra/logging/logrus"
	"github.com/onsi/gomega"
	"golang.org/x/net/context"
)

var dataBroker *BytesConnectionEtcd
var dataBrokerErr *BytesConnectionEtcd
var pluginDataBroker *BytesBrokerWatcherEtcd

// Mock data broker err
type MockKVErr struct {
	// NO-OP
}

func (mock *MockKVErr) Put(ctx context.Context, key, val string, opts ...clientv3.OpOption) (*clientv3.PutResponse, error) {
	return nil, errors.New("test-error")
}

func (mock *MockKVErr) Get(ctx context.Context, key string, opts ...clientv3.OpOption) (*clientv3.GetResponse, error) {
	return nil, errors.New("test-error")
}

func (mock *MockKVErr) Delete(ctx context.Context, key string, opts ...clientv3.OpOption) (*clientv3.DeleteResponse, error) {
	return nil, errors.New("test-error")
}

func (mock *MockKVErr) Compact(ctx context.Context, rev int64, opts ...clientv3.CompactOption) (*clientv3.CompactResponse, error) {
	return nil, nil
}

func (mock *MockKVErr) Do(ctx context.Context, op clientv3.Op) (clientv3.OpResponse, error) {
	return clientv3.OpResponse{}, nil
}

func (mock *MockKVErr) Txn(ctx context.Context) clientv3.Txn {
	return &MockTxn{}
}

func (mock *MockKVErr) Watch(ctx context.Context, key string, opts ...clientv3.OpOption) clientv3.WatchChan {
	return nil
}

func (mock *MockKVErr) Close() error {
	return nil
}

// Mock KV
type MockKV struct {
	// NO-OP
}

func (mock *MockKV) Put(ctx context.Context, key, val string, opts ...clientv3.OpOption) (*clientv3.PutResponse, error) {
	return nil, nil
}

func (mock *MockKV) Get(ctx context.Context, key string, opts ...clientv3.OpOption) (*clientv3.GetResponse, error) {
	response := *new(clientv3.GetResponse)
	kvs := new(mvccpb.KeyValue)
	kvs.Key = []byte{1}
	kvs.Value = []byte{73, 0x6f, 0x6d, 65, 0x2d, 0x6a, 73, 0x6f, 0x6e} //some-json
	response.Kvs = []*mvccpb.KeyValue{kvs}
	return &response, nil
}

func (mock *MockKV) Delete(ctx context.Context, key string, opts ...clientv3.OpOption) (*clientv3.DeleteResponse, error) {
	response := *new(clientv3.DeleteResponse)
	response.PrevKvs = []*mvccpb.KeyValue{}
	return &response, nil
}

func (mock *MockKV) Compact(ctx context.Context, rev int64, opts ...clientv3.CompactOption) (*clientv3.CompactResponse, error) {
	return nil, nil
}

func (mock *MockKV) Do(ctx context.Context, op clientv3.Op) (clientv3.OpResponse, error) {
	return clientv3.OpResponse{}, nil
}

func (mock *MockKV) Txn(ctx context.Context) clientv3.Txn {
	return &MockTxn{}
}

func (mock *MockKV) Watch(ctx context.Context, key string, opts ...clientv3.OpOption) clientv3.WatchChan {
	return nil
}

func (mock *MockKV) Close() error {
	return nil
}

// Mock Txn
type MockTxn struct {
}

func (mock *MockTxn) If(cs ...clientv3.Cmp) clientv3.Txn {
	return &MockTxn{}
}

func (mock *MockTxn) Then(ops ...clientv3.Op) clientv3.Txn {
	return &MockTxn{}
}

func (mock *MockTxn) Else(ops ...clientv3.Op) clientv3.Txn {
	return &MockTxn{}
}

func (mock *MockTxn) Commit() (*clientv3.TxnResponse, error) {
	return nil, nil
}

// Tests

func init() {
	mockKv := &MockKV{}
	mockKvErr := &MockKVErr{}
	dataBroker = &BytesConnectionEtcd{Logger: logrus.DefaultLogger(), etcdClient: &clientv3.Client{KV: mockKv, Watcher: mockKv}}
	dataBrokerErr = &BytesConnectionEtcd{Logger: logrus.DefaultLogger(), etcdClient: &clientv3.Client{KV: mockKvErr, Watcher: mockKvErr}}
	pluginDataBroker = &BytesBrokerWatcherEtcd{Logger: logrus.DefaultLogger(), closeCh: make(chan string), kv: mockKv, watcher: mockKv}
}

func TestNewTxn(t *testing.T) {
	gomega.RegisterTestingT(t)
	newTxn := dataBroker.NewTxn()
	gomega.Expect(newTxn).NotTo(gomega.BeNil())
}

func TestTxnPut(t *testing.T) {
	gomega.RegisterTestingT(t)
	newTxn := dataBroker.NewTxn()
	result := newTxn.Put("key", []byte("data"))
	gomega.Expect(result).NotTo(gomega.BeNil())
}

func TestTxnDelete(t *testing.T) {
	gomega.RegisterTestingT(t)
	newTxn := dataBroker.NewTxn()
	gomega.Expect(newTxn).NotTo(gomega.BeNil())
	result := newTxn.Delete("key")
	gomega.Expect(result).NotTo(gomega.BeNil())
}

func TestTxnCommit(t *testing.T) {
	gomega.RegisterTestingT(t)
	newTxn := dataBroker.NewTxn()
	result := newTxn.Commit()
	gomega.Expect(result).To(gomega.BeNil())
}

func TestPut(t *testing.T) {
	// regular case
	gomega.RegisterTestingT(t)
	err := dataBroker.Put("key", []byte("data"))
	gomega.Expect(err).ShouldNot(gomega.HaveOccurred())
	// error case
	err = dataBrokerErr.Put("key", []byte("data"))
	gomega.Expect(err).Should(gomega.HaveOccurred())
	gomega.Expect(err.Error()).To(gomega.BeEquivalentTo("test-error"))
}

func TestGetValue(t *testing.T) {
	// regular case
	gomega.RegisterTestingT(t)
	result, found, _, err := dataBroker.GetValue("key")
	gomega.Expect(err).ShouldNot(gomega.HaveOccurred())
	gomega.Expect(result).NotTo(gomega.BeNil())
	// error case
	result, found, _, err = dataBrokerErr.GetValue("key")
	gomega.Expect(err).Should(gomega.HaveOccurred())
	gomega.Expect(found).To(gomega.BeFalse())
	gomega.Expect(result).To(gomega.BeNil())
	gomega.Expect(err.Error()).To(gomega.BeEquivalentTo("test-error"))
}

func TestListValues(t *testing.T) {
	// regular case
	gomega.RegisterTestingT(t)
	result, err := dataBroker.ListValues("key")
	gomega.Expect(err).ShouldNot(gomega.HaveOccurred())
	gomega.Expect(result).ToNot(gomega.BeNil())

	// error case
	result, err = dataBrokerErr.ListValues("key")
	gomega.Expect(err).Should(gomega.HaveOccurred())
	gomega.Expect(result).To(gomega.BeNil())
	gomega.Expect(err.Error()).To(gomega.BeEquivalentTo("test-error"))
}

func TestListValuesRange(t *testing.T) {
	// regular case
	gomega.RegisterTestingT(t)
	result, err := dataBroker.ListValuesRange("AKey", "ZKey")
	gomega.Expect(err).ShouldNot(gomega.HaveOccurred())
	gomega.Expect(result).ToNot(gomega.BeNil())

	// error case
	result, err = dataBrokerErr.ListValuesRange("AKey", "ZKey")
	gomega.Expect(err).Should(gomega.HaveOccurred())
	gomega.Expect(result).To(gomega.BeNil())
	gomega.Expect(err.Error()).To(gomega.BeEquivalentTo("test-error"))
}

func TestDelete(t *testing.T) {
	// regular case
	gomega.RegisterTestingT(t)
	response, err := dataBroker.Delete("vnf")
	gomega.Expect(err).ShouldNot(gomega.HaveOccurred())
	gomega.Expect(response).To(gomega.BeFalse())
	// error case
	response, err = dataBrokerErr.Delete("vnf")
	gomega.Expect(err).Should(gomega.HaveOccurred())
	gomega.Expect(response).To(gomega.BeFalse())
	gomega.Expect(err.Error()).To(gomega.BeEquivalentTo("test-error"))
}

func TestNewBroker(t *testing.T) {
	gomega.RegisterTestingT(t)
	pdb := dataBroker.NewBroker("/pluginname")
	gomega.Expect(pdb).NotTo(gomega.BeNil())
}

func TestNewWatcher(t *testing.T) {
	gomega.RegisterTestingT(t)
	pdb := dataBroker.NewWatcher("/pluginname")
	gomega.Expect(pdb).NotTo(gomega.BeNil())
}

func TestWatch(t *testing.T) {
	gomega.RegisterTestingT(t)
	err := pluginDataBroker.Watch(func(keyval.BytesWatchResp) {}, nil, "key")
	gomega.Expect(err).ShouldNot(gomega.HaveOccurred())
}

func TestWatchPutResp(t *testing.T) {
	var rev int64 = 1
	value := []byte("data")
	prevVal := []byte("prevData")
	key := "key"
	gomega.RegisterTestingT(t)
	createResp := NewBytesWatchPutResp(key, value, prevVal, rev)
	gomega.Expect(createResp).NotTo(gomega.BeNil())
	gomega.Expect(createResp.GetChangeType()).To(gomega.BeEquivalentTo(datasync.Put))
	gomega.Expect(createResp.GetKey()).To(gomega.BeEquivalentTo(key))
	gomega.Expect(createResp.GetValue()).To(gomega.BeEquivalentTo(value))
	gomega.Expect(createResp.GetPrevValue()).To(gomega.BeEquivalentTo(prevVal))
	gomega.Expect(createResp.GetRevision()).To(gomega.BeEquivalentTo(rev))
}

func TestWatchDeleteResp(t *testing.T) {
	var rev int64 = 1
	key := "key"
	gomega.RegisterTestingT(t)
	createResp := NewBytesWatchDelResp(key, rev)
	gomega.Expect(createResp).NotTo(gomega.BeNil())
	gomega.Expect(createResp.GetChangeType()).To(gomega.BeEquivalentTo(datasync.Delete))
	gomega.Expect(createResp.GetKey()).To(gomega.BeEquivalentTo(key))
	gomega.Expect(createResp.GetValue()).To(gomega.BeNil())
	gomega.Expect(createResp.GetRevision()).To(gomega.BeEquivalentTo(rev))
}

func TestConfig(t *testing.T) {
	gomega.RegisterTestingT(t)
	cfg := &Config{DialTimeout: time.Second, OpTimeout: time.Second}
	etcdCfg, err := ConfigToClientv3(cfg)
	gomega.Expect(err).To(gomega.BeNil())
	gomega.Expect(etcdCfg).NotTo(gomega.BeNil())
	gomega.Expect(etcdCfg.OpTimeout).To(gomega.BeEquivalentTo(time.Second))
	gomega.Expect(etcdCfg.DialTimeout).To(gomega.BeEquivalentTo(time.Second))
	gomega.Expect(etcdCfg.TLS).To(gomega.BeNil())
}
<commit_msg>fix test<commit_after>// Copyright (c) 2017 Cisco and/or its affiliates.
//
// 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 etcdv3

import (
	"errors"
	"testing"

	"time"

	"github.com/coreos/etcd/clientv3"
	"github.com/coreos/etcd/mvcc/mvccpb"
	"github.com/ligato/cn-infra/datasync"
	"github.com/ligato/cn-infra/db/keyval"
	"github.com/ligato/cn-infra/logging/logrus"
	"github.com/onsi/gomega"
	"golang.org/x/net/context"
)

var dataBroker *BytesConnectionEtcd
var dataBrokerErr *BytesConnectionEtcd
var pluginDataBroker *BytesBrokerWatcherEtcd

// Mock data broker err
type MockKVErr struct {
	// NO-OP
}

func (mock *MockKVErr) Put(ctx context.Context, key, val string, opts ...clientv3.OpOption) (*clientv3.PutResponse, error) {
	return nil, errors.New("test-error")
}

func (mock *MockKVErr) Get(ctx context.Context, key string, opts ...clientv3.OpOption) (*clientv3.GetResponse, error) {
	return nil, errors.New("test-error")
}

func (mock *MockKVErr) Delete(ctx context.Context, key string, opts ...clientv3.OpOption) (*clientv3.DeleteResponse, error) {
	return nil, errors.New("test-error")
}

func (mock *MockKVErr) Compact(ctx context.Context, rev int64, opts ...clientv3.CompactOption) (*clientv3.CompactResponse, error) {
	return nil, nil
}

func (mock *MockKVErr) Do(ctx context.Context, op clientv3.Op) (clientv3.OpResponse, error) {
	return clientv3.OpResponse{}, nil
}

func (mock *MockKVErr) Txn(ctx context.Context) clientv3.Txn {
	return &MockTxn{}
}

func (mock *MockKVErr) Watch(ctx context.Context, key string, opts ...clientv3.OpOption) clientv3.WatchChan {
	return nil
}

func (mock *MockKVErr) Close() error {
	return nil
}

// Mock KV
type MockKV struct {
	// NO-OP
}

func (mock *MockKV) Put(ctx context.Context, key, val string, opts ...clientv3.OpOption) (*clientv3.PutResponse, error) {
	return nil, nil
}

func (mock *MockKV) Get(ctx context.Context, key string, opts ...clientv3.OpOption) (*clientv3.GetResponse, error) {
	response := *new(clientv3.GetResponse)
	kvs := new(mvccpb.KeyValue)
	kvs.Key = []byte{1}
	kvs.Value = []byte{73, 0x6f, 0x6d, 65, 0x2d, 0x6a, 73, 0x6f, 0x6e} //some-json
	response.Kvs = []*mvccpb.KeyValue{kvs}
	return &response, nil
}

func (mock *MockKV) Delete(ctx context.Context, key string, opts ...clientv3.OpOption) (*clientv3.DeleteResponse, error) {
	response := *new(clientv3.DeleteResponse)
	response.PrevKvs = []*mvccpb.KeyValue{}
	return &response, nil
}

func (mock *MockKV) Compact(ctx context.Context, rev int64, opts ...clientv3.CompactOption) (*clientv3.CompactResponse, error) {
	return nil, nil
}

func (mock *MockKV) Do(ctx context.Context, op clientv3.Op) (clientv3.OpResponse, error) {
	return clientv3.OpResponse{}, nil
}

func (mock *MockKV) Txn(ctx context.Context) clientv3.Txn {
	return &MockTxn{}
}

func (mock *MockKV) Watch(ctx context.Context, key string, opts ...clientv3.OpOption) clientv3.WatchChan {
	return nil
}

func (mock *MockKV) Close() error {
	return nil
}

// Mock Txn
type MockTxn struct {
}

func (mock *MockTxn) If(cs ...clientv3.Cmp) clientv3.Txn {
	return &MockTxn{}
}

func (mock *MockTxn) Then(ops ...clientv3.Op) clientv3.Txn {
	return &MockTxn{}
}

func (mock *MockTxn) Else(ops ...clientv3.Op) clientv3.Txn {
	return &MockTxn{}
}

func (mock *MockTxn) Commit() (*clientv3.TxnResponse, error) {
	return nil, nil
}

// Tests

func init() {
	mockKv := &MockKV{}
	mockKvErr := &MockKVErr{}
	dataBroker = &BytesConnectionEtcd{Logger: logrus.DefaultLogger(), etcdClient: &clientv3.Client{KV: mockKv, Watcher: mockKv}}
	dataBrokerErr = &BytesConnectionEtcd{Logger: logrus.DefaultLogger(), etcdClient: &clientv3.Client{KV: mockKvErr, Watcher: mockKvErr}}
	pluginDataBroker = &BytesBrokerWatcherEtcd{Logger: logrus.DefaultLogger(), closeCh: make(chan string), kv: mockKv, watcher: mockKv}
}

func TestNewTxn(t *testing.T) {
	gomega.RegisterTestingT(t)
	newTxn := dataBroker.NewTxn()
	gomega.Expect(newTxn).NotTo(gomega.BeNil())
}

func TestTxnPut(t *testing.T) {
	gomega.RegisterTestingT(t)
	newTxn := dataBroker.NewTxn()
	result := newTxn.Put("key", []byte("data"))
	gomega.Expect(result).NotTo(gomega.BeNil())
}

func TestTxnDelete(t *testing.T) {
	gomega.RegisterTestingT(t)
	newTxn := dataBroker.NewTxn()
	gomega.Expect(newTxn).NotTo(gomega.BeNil())
	result := newTxn.Delete("key")
	gomega.Expect(result).NotTo(gomega.BeNil())
}

func TestTxnCommit(t *testing.T) {
	gomega.RegisterTestingT(t)
	newTxn := dataBroker.NewTxn()
	result := newTxn.Commit()
	gomega.Expect(result).To(gomega.BeNil())
}

func TestPut(t *testing.T) {
	// regular case
	gomega.RegisterTestingT(t)
	err := dataBroker.Put("key", []byte("data"))
	gomega.Expect(err).ShouldNot(gomega.HaveOccurred())
	// error case
	err = dataBrokerErr.Put("key", []byte("data"))
	gomega.Expect(err).Should(gomega.HaveOccurred())
	gomega.Expect(err.Error()).To(gomega.BeEquivalentTo("test-error"))
}

func TestGetValue(t *testing.T) {
	// regular case
	gomega.RegisterTestingT(t)
	result, found, _, err := dataBroker.GetValue("key")
	gomega.Expect(err).ShouldNot(gomega.HaveOccurred())
	gomega.Expect(result).NotTo(gomega.BeNil())
	// error case
	result, found, _, err = dataBrokerErr.GetValue("key")
	gomega.Expect(err).Should(gomega.HaveOccurred())
	gomega.Expect(found).To(gomega.BeFalse())
	gomega.Expect(result).To(gomega.BeNil())
	gomega.Expect(err.Error()).To(gomega.BeEquivalentTo("test-error"))
}

func TestListValues(t *testing.T) {
	// regular case
	gomega.RegisterTestingT(t)
	result, err := dataBroker.ListValues("key")
	gomega.Expect(err).ShouldNot(gomega.HaveOccurred())
	gomega.Expect(result).ToNot(gomega.BeNil())

	// error case
	result, err = dataBrokerErr.ListValues("key")
	gomega.Expect(err).Should(gomega.HaveOccurred())
	gomega.Expect(result).To(gomega.BeNil())
	gomega.Expect(err.Error()).To(gomega.BeEquivalentTo("test-error"))
}

func TestListValuesRange(t *testing.T) {
	// regular case
	gomega.RegisterTestingT(t)
	result, err := dataBroker.ListValuesRange("AKey", "ZKey")
	gomega.Expect(err).ShouldNot(gomega.HaveOccurred())
	gomega.Expect(result).ToNot(gomega.BeNil())

	// error case
	result, err = dataBrokerErr.ListValuesRange("AKey", "ZKey")
	gomega.Expect(err).Should(gomega.HaveOccurred())
	gomega.Expect(result).To(gomega.BeNil())
	gomega.Expect(err.Error()).To(gomega.BeEquivalentTo("test-error"))
}

func TestDelete(t *testing.T) {
	// regular case
	gomega.RegisterTestingT(t)
	response, err := dataBroker.Delete("vnf")
	gomega.Expect(err).ShouldNot(gomega.HaveOccurred())
	gomega.Expect(response).To(gomega.BeFalse())
	// error case
	response, err = dataBrokerErr.Delete("vnf")
	gomega.Expect(err).Should(gomega.HaveOccurred())
	gomega.Expect(response).To(gomega.BeFalse())
	gomega.Expect(err.Error()).To(gomega.BeEquivalentTo("test-error"))
}

func TestNewBroker(t *testing.T) {
	gomega.RegisterTestingT(t)
	pdb := dataBroker.NewBroker("/pluginname")
	gomega.Expect(pdb).NotTo(gomega.BeNil())
}

func TestNewWatcher(t *testing.T) {
	gomega.RegisterTestingT(t)
	pdb := dataBroker.NewWatcher("/pluginname")
	gomega.Expect(pdb).NotTo(gomega.BeNil())
}

func TestWatch(t *testing.T) {
	gomega.RegisterTestingT(t)
	err := pluginDataBroker.Watch(func(keyval.BytesWatchResp) {}, nil, "key")
	gomega.Expect(err).ShouldNot(gomega.HaveOccurred())
}

func TestWatchPutResp(t *testing.T) {
	var rev int64 = 1
	value := []byte("data")
	prevVal := []byte("prevData")
	key := "key"
	gomega.RegisterTestingT(t)
	createResp := NewBytesWatchPutResp(key, value, prevVal, rev)
	gomega.Expect(createResp).NotTo(gomega.BeNil())
	gomega.Expect(createResp.GetChangeType()).To(gomega.BeEquivalentTo(datasync.Put))
	gomega.Expect(createResp.GetKey()).To(gomega.BeEquivalentTo(key))
	gomega.Expect(createResp.GetValue()).To(gomega.BeEquivalentTo(value))
	gomega.Expect(createResp.GetPrevValue()).To(gomega.BeEquivalentTo(prevVal))
	gomega.Expect(createResp.GetRevision()).To(gomega.BeEquivalentTo(rev))
}

func TestWatchDeleteResp(t *testing.T) {
	var rev int64 = 1
	key := "key"
	prevVal := []byte("prevVal")
	gomega.RegisterTestingT(t)
	createResp := NewBytesWatchDelResp(key, prevVal, rev)
	gomega.Expect(createResp).NotTo(gomega.BeNil())
	gomega.Expect(createResp.GetChangeType()).To(gomega.BeEquivalentTo(datasync.Delete))
	gomega.Expect(createResp.GetKey()).To(gomega.BeEquivalentTo(key))
	gomega.Expect(createResp.GetValue()).To(gomega.BeNil())
	gomega.Expect(createResp.GetPrevValue()).To(gomega.BeEquivalentTo(prevVal))
	gomega.Expect(createResp.GetRevision()).To(gomega.BeEquivalentTo(rev))
}

func TestConfig(t *testing.T) {
	gomega.RegisterTestingT(t)
	cfg := &Config{DialTimeout: time.Second, OpTimeout: time.Second}
	etcdCfg, err := ConfigToClientv3(cfg)
	gomega.Expect(err).To(gomega.BeNil())
	gomega.Expect(etcdCfg).NotTo(gomega.BeNil())
	gomega.Expect(etcdCfg.OpTimeout).To(gomega.BeEquivalentTo(time.Second))
	gomega.Expect(etcdCfg.DialTimeout).To(gomega.BeEquivalentTo(time.Second))
	gomega.Expect(etcdCfg.TLS).To(gomega.BeNil())
}
<|endoftext|>


<commit_before>package privatemessage

import (
	"errors"
	"koding/db/mongodb/modelhelper"
	"net/http"
	"net/url"
	"socialapi/models"
	"socialapi/workers/api/modules/helpers"

	"github.com/koding/bongo"
)

func fetchParticipantIds(participantNames []string) ([]int64, error) {
	participantIds := make([]int64, len(participantNames))
	for i, participantName := range participantNames {
		account, err := modelhelper.GetAccount(participantName)
		if err != nil {
			return nil, err
		}
		a := models.NewAccount()
		a.Id = account.SocialApiId
		a.OldId = account.Id.Hex()
		a.Nick = account.Profile.Nickname
		// fetch or create social api id
		if a.Id == 0 {
			if err := a.FetchOrCreate(); err != nil {
				return nil, err
			}
		}
		participantIds[i] = a.Id
	}

	return participantIds, nil
}

func appendCreatorIdIntoParticipantList(participants []int64, authorId int64) []int64 {
	for _, participant := range participants {
		if participant == authorId {
			return participants
		}
	}

	return append(participants, authorId)
}

func Send(u *url.URL, h http.Header, req *models.PrivateMessageRequest) (int, http.Header, interface{}, error) {
	if req.AccountId == 0 {
		return helpers.NewBadRequestResponse(errors.New("AcccountId is not defined"))
	}

	// // req.Recipients = append(req.Recipients, req.AccountId)
	cm := models.NewChannelMessage()
	cm.Body = req.Body
	participantNames := cm.GetMentionedUsernames()
	participantIds, err := fetchParticipantIds(participantNames)
	if err != nil {
		return helpers.NewBadRequestResponse(err)
	}

	// append creator to the recipients
	participantIds = appendCreatorIdIntoParticipantList(participantIds, req.AccountId)

	// author and atleast one recipient should be in the
	// recipient list
	if len(participantIds) < 2 {
		return helpers.NewBadRequestResponse(errors.New("You should define your recipients"))
	}

	if req.GroupName == "" {
		req.GroupName = models.Channel_KODING_NAME
	}

	//// first create the channel
	c := models.NewPrivateMessageChannel(req.AccountId, req.GroupName)
	if err := c.Create(); err != nil {
		return helpers.NewBadRequestResponse(err)
	}

	cm.TypeConstant = models.ChannelMessage_TYPE_PRIVATE_MESSAGE
	cm.AccountId = req.AccountId
	cm.InitialChannelId = c.Id
	if err := cm.Create(); err != nil {
		return helpers.NewBadRequestResponse(err)
	}

	messageContainer, err := cm.BuildEmptyMessageContainer()
	if err != nil {
		return helpers.NewBadRequestResponse(err)
	}

	_, err = c.AddMessage(cm.Id)
	if err != nil {
		return helpers.NewBadRequestResponse(err)
	}

	for _, participantId := range participantIds {
		_, err := c.AddParticipant(participantId)
		if err != nil {
			return helpers.NewBadRequestResponse(err)
		}
	}

	cmc := models.NewChannelContainer()
	cmc.Channel = *c
	cmc.IsParticipant = true
	cmc.LastMessage = messageContainer
	cmc.ParticipantCount = len(participantIds)
	participantOldIds, err := models.AccountOldsIdByIds(participantIds)
	if err != nil {
		return helpers.NewBadRequestResponse(err)
	}

	cmc.ParticipantsPreview = participantOldIds

	return helpers.NewOKResponse(cmc)
}

func List(u *url.URL, h http.Header, _ interface{}) (int, http.Header, interface{}, error) {
	q := helpers.GetQuery(u)

	channels, err := getPrivateMessageChannels(q)
	if err != nil {
		return helpers.NewBadRequestResponse(err)
	}

	return helpers.HandleResultAndError(
		models.PopulateChannelContainersWithUnreadCount(channels, q.AccountId),
	)
}

func getPrivateMessageChannels(q *models.Query) ([]models.Channel, error) {
	// build query for
	c := models.NewChannel()
	channelIds := make([]int64, 0)
	rows, err := bongo.B.DB.Table(c.TableName()).
		Select("api.channel_participant.channel_id").
		Joins("left join api.channel_participant on api.channel_participant.channel_id = api.channel.id").
		Where("api.channel_participant.account_id = ? and "+
		"api.channel.group_name = ? and "+
		"api.channel.type_constant = ? and "+
		"api.channel_participant.status_constant = ?",
		q.AccountId,
		q.GroupName,
		models.Channel_TYPE_PRIVATE_MESSAGE,
		models.ChannelParticipant_STATUS_ACTIVE).
		Limit(q.Limit).
		Offset(q.Skip).
		Rows()
	defer rows.Close()
	if err != nil {
		return nil, err
	}

	var channelId int64
	for rows.Next() {
		rows.Scan(&channelId)
		channelIds = append(channelIds, channelId)
	}

	channels, err := c.FetchByIds(channelIds)
	if err != nil {
		return nil, err
	}

	return channels, nil
}
<commit_msg>Social: add ordering into private message channel fetching<commit_after>package privatemessage

import (
	"errors"
	"koding/db/mongodb/modelhelper"
	"net/http"
	"net/url"
	"socialapi/models"
	"socialapi/workers/api/modules/helpers"

	"github.com/koding/bongo"
)

func fetchParticipantIds(participantNames []string) ([]int64, error) {
	participantIds := make([]int64, len(participantNames))
	for i, participantName := range participantNames {
		account, err := modelhelper.GetAccount(participantName)
		if err != nil {
			return nil, err
		}
		a := models.NewAccount()
		a.Id = account.SocialApiId
		a.OldId = account.Id.Hex()
		a.Nick = account.Profile.Nickname
		// fetch or create social api id
		if a.Id == 0 {
			if err := a.FetchOrCreate(); err != nil {
				return nil, err
			}
		}
		participantIds[i] = a.Id
	}

	return participantIds, nil
}

func appendCreatorIdIntoParticipantList(participants []int64, authorId int64) []int64 {
	for _, participant := range participants {
		if participant == authorId {
			return participants
		}
	}

	return append(participants, authorId)
}

func Send(u *url.URL, h http.Header, req *models.PrivateMessageRequest) (int, http.Header, interface{}, error) {
	if req.AccountId == 0 {
		return helpers.NewBadRequestResponse(errors.New("AcccountId is not defined"))
	}

	// // req.Recipients = append(req.Recipients, req.AccountId)
	cm := models.NewChannelMessage()
	cm.Body = req.Body
	participantNames := cm.GetMentionedUsernames()
	participantIds, err := fetchParticipantIds(participantNames)
	if err != nil {
		return helpers.NewBadRequestResponse(err)
	}

	// append creator to the recipients
	participantIds = appendCreatorIdIntoParticipantList(participantIds, req.AccountId)

	// author and atleast one recipient should be in the
	// recipient list
	if len(participantIds) < 2 {
		return helpers.NewBadRequestResponse(errors.New("You should define your recipients"))
	}

	if req.GroupName == "" {
		req.GroupName = models.Channel_KODING_NAME
	}

	//// first create the channel
	c := models.NewPrivateMessageChannel(req.AccountId, req.GroupName)
	if err := c.Create(); err != nil {
		return helpers.NewBadRequestResponse(err)
	}

	cm.TypeConstant = models.ChannelMessage_TYPE_PRIVATE_MESSAGE
	cm.AccountId = req.AccountId
	cm.InitialChannelId = c.Id
	if err := cm.Create(); err != nil {
		return helpers.NewBadRequestResponse(err)
	}

	messageContainer, err := cm.BuildEmptyMessageContainer()
	if err != nil {
		return helpers.NewBadRequestResponse(err)
	}

	_, err = c.AddMessage(cm.Id)
	if err != nil {
		return helpers.NewBadRequestResponse(err)
	}

	for _, participantId := range participantIds {
		_, err := c.AddParticipant(participantId)
		if err != nil {
			return helpers.NewBadRequestResponse(err)
		}
	}

	cmc := models.NewChannelContainer()
	cmc.Channel = *c
	cmc.IsParticipant = true
	cmc.LastMessage = messageContainer
	cmc.ParticipantCount = len(participantIds)
	participantOldIds, err := models.AccountOldsIdByIds(participantIds)
	if err != nil {
		return helpers.NewBadRequestResponse(err)
	}

	cmc.ParticipantsPreview = participantOldIds

	return helpers.NewOKResponse(cmc)
}

func List(u *url.URL, h http.Header, _ interface{}) (int, http.Header, interface{}, error) {
	q := helpers.GetQuery(u)

	channels, err := getPrivateMessageChannels(q)
	if err != nil {
		return helpers.NewBadRequestResponse(err)
	}

	return helpers.HandleResultAndError(
		models.PopulateChannelContainersWithUnreadCount(channels, q.AccountId),
	)
}

func getPrivateMessageChannels(q *models.Query) ([]models.Channel, error) {
	// build query for
	c := models.NewChannel()
	channelIds := make([]int64, 0)
	rows, err := bongo.B.DB.Table(c.TableName()).
		Select("api.channel_participant.channel_id").
		Joins("left join api.channel_participant on api.channel_participant.channel_id = api.channel.id").
		Where("api.channel_participant.account_id = ? and "+
		"api.channel.group_name = ? and "+
		"api.channel.type_constant = ? and "+
		"api.channel_participant.status_constant = ?",
		q.AccountId,
		q.GroupName,
		models.Channel_TYPE_PRIVATE_MESSAGE,
		models.ChannelParticipant_STATUS_ACTIVE).
		Limit(q.Limit).
		Offset(q.Skip).
		Order("api.channel.updated_at DESC").
		Rows()
	defer rows.Close()
	if err != nil {
		return nil, err
	}

	var channelId int64
	for rows.Next() {
		rows.Scan(&channelId)
		channelIds = append(channelIds, channelId)
	}

	channels, err := c.FetchByIds(channelIds)
	if err != nil {
		return nil, err
	}

	return channels, nil
}
<|endoftext|>


<commit_before><commit_msg>fix openstack provider to handle only Cinder volumes<commit_after><|endoftext|>