<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 exec runs external commands. It wraps os.StartProcess to make it
// easier to remap stdin and stdout, connect I/O with pipes, and do other
// adjustments.
package exec

import (
	"bytes"
	"io"
	"os"
	"strconv"
)

// Error records the name of a binary that failed to be be executed
// and the reason it failed.
type Error struct {
	Name  string
	Error os.Error
}

func (e *Error) String() string {
	return "exec: " + strconv.Quote(e.Name) + ": " + e.Error.String()
}

// Cmd represents an external command being prepared or run.
type Cmd struct {
	// Path is the path of the command to run.
	//
	// This is the only field that must be set to a non-zero
	// value.
	Path string

	// Args holds command line arguments, including the command as Args[0].
	// If the Args field is empty or nil, Run uses {Path}.
	//
	// In typical use, both Path and Args are set by calling Command.
	Args []string

	// Env specifies the environment of the process.
	// If Env is nil, Run uses the current process's environment.
	Env []string

	// Dir specifies the working directory of the command.
	// If Dir is the empty string, Run runs the command in the
	// calling process's current directory.
	Dir string

	// Stdin specifies the process's standard input.
	// If Stdin is nil, the process reads from DevNull.
	Stdin io.Reader

	// Stdout and Stderr specify the process's standard output and error.
	//
	// If either is nil, Run connects the
	// corresponding file descriptor to /dev/null.
	//
	// If Stdout and Stderr are are the same writer, at most one
	// goroutine at a time will call Write.
	Stdout io.Writer
	Stderr io.Writer

	err             os.Error // last error (from LookPath, stdin, stdout, stderr)
	process         *os.Process
	finished        bool // when Wait was called
	childFiles      []*os.File
	closeAfterStart []io.Closer
	closeAfterWait  []io.Closer
	goroutine       []func() os.Error
	errch           chan os.Error // one send per goroutine
}

// Command returns the Cmd struct to execute the named program with
// the given arguments.
//
// It sets Path and Args in the returned structure and zeroes the
// other fields.
//
// If name contains no path separators, Command uses LookPath to
// resolve the path to a complete name if possible. Otherwise it uses
// name directly.
//
// The returned Cmd's Args field is constructed from the command name
// followed by the elements of arg, so arg should not include the
// command name itself. For example, Command("echo", "hello")
func Command(name string, arg ...string) *Cmd {
	aname, err := LookPath(name)
	if err != nil {
		aname = name
	}
	return &Cmd{
		Path: aname,
		Args: append([]string{name}, arg...),
		err:  err,
	}
}

// interfaceEqual protects against panics from doing equality tests on
// two interfaces with non-comparable underlying types
func interfaceEqual(a, b interface{}) bool {
	defer func() {
		recover()
	}()
	return a == b
}

func (c *Cmd) envv() []string {
	if c.Env != nil {
		return c.Env
	}
	return os.Environ()
}

func (c *Cmd) argv() []string {
	if len(c.Args) > 0 {
		return c.Args
	}
	return []string{c.Path}
}

func (c *Cmd) stdin() (f *os.File, err os.Error) {
	if c.Stdin == nil {
		f, err = os.Open(os.DevNull)
		c.closeAfterStart = append(c.closeAfterStart, f)
		return
	}

	if f, ok := c.Stdin.(*os.File); ok {
		return f, nil
	}

	pr, pw, err := os.Pipe()
	if err != nil {
		return
	}

	c.closeAfterStart = append(c.closeAfterStart, pr)
	c.closeAfterWait = append(c.closeAfterWait, pw)
	c.goroutine = append(c.goroutine, func() os.Error {
		_, err := io.Copy(pw, c.Stdin)
		if err1 := pw.Close(); err == nil {
			err = err1
		}
		return err
	})
	return pr, nil
}

func (c *Cmd) stdout() (f *os.File, err os.Error) {
	return c.writerDescriptor(c.Stdout)
}

func (c *Cmd) stderr() (f *os.File, err os.Error) {
	if c.Stderr != nil && interfaceEqual(c.Stderr, c.Stdout) {
		return c.childFiles[1], nil
	}
	return c.writerDescriptor(c.Stderr)
}

func (c *Cmd) writerDescriptor(w io.Writer) (f *os.File, err os.Error) {
	if w == nil {
		f, err = os.OpenFile(os.DevNull, os.O_WRONLY, 0)
		c.closeAfterStart = append(c.closeAfterStart, f)
		return
	}

	if f, ok := w.(*os.File); ok {
		return f, nil
	}

	pr, pw, err := os.Pipe()
	if err != nil {
		return
	}

	c.closeAfterStart = append(c.closeAfterStart, pw)
	c.closeAfterWait = append(c.closeAfterWait, pr)
	c.goroutine = append(c.goroutine, func() os.Error {
		_, err := io.Copy(w, pr)
		return err
	})
	return pw, nil
}

// Run starts the specified command and waits for it to complete.
//
// The returned error is nil if the command runs, has no problems
// copying stdin, stdout, and stderr, and exits with a zero exit
// status.
//
// If the command fails to run or doesn't complete successfully, the
// error is of type *os.Waitmsg. Other error types may be
// returned for I/O problems.
func (c *Cmd) Run() os.Error {
	if err := c.Start(); err != nil {
		return err
	}
	return c.Wait()
}

// Start starts the specified command but does not wait for it to complete.
func (c *Cmd) Start() os.Error {
	if c.err != nil {
		return c.err
	}
	if c.process != nil {
		return os.NewError("exec: already started")
	}

	type F func(*Cmd) (*os.File, os.Error)
	for _, setupFd := range []F{(*Cmd).stdin, (*Cmd).stdout, (*Cmd).stderr} {
		fd, err := setupFd(c)
		if err != nil {
			return err
		}
		c.childFiles = append(c.childFiles, fd)
	}

	var err os.Error
	c.process, err = os.StartProcess(c.Path, c.argv(), &os.ProcAttr{
		Dir:   c.Dir,
		Files: c.childFiles,
		Env:   c.envv(),
	})
	if err != nil {
		return err
	}

	for _, fd := range c.closeAfterStart {
		fd.Close()
	}

	c.errch = make(chan os.Error, len(c.goroutine))
	for _, fn := range c.goroutine {
		go func(fn func() os.Error) {
			c.errch <- fn()
		}(fn)
	}

	return nil
}

// Wait waits for the command to exit.
// It must have been started by Start.
//
// The returned error is nil if the command runs, has no problems
// copying stdin, stdout, and stderr, and exits with a zero exit
// status.
//
// If the command fails to run or doesn't complete successfully, the
// error is of type *os.Waitmsg. Other error types may be
// returned for I/O problems.
func (c *Cmd) Wait() os.Error {
	if c.process == nil {
		return os.NewError("exec: not started")
	}
	if c.finished {
		return os.NewError("exec: Wait was already called")
	}
	c.finished = true
	msg, err := c.process.Wait(0)

	var copyError os.Error
	for _ = range c.goroutine {
		if err := <-c.errch; err != nil && copyError == nil {
			copyError = err
		}
	}

	for _, fd := range c.closeAfterWait {
		fd.Close()
	}

	if err != nil {
		return err
	} else if !msg.Exited() || msg.ExitStatus() != 0 {
		return msg
	}

	return copyError
}

// Output runs the command and returns its standard output.
func (c *Cmd) Output() ([]byte, os.Error) {
	if c.Stdout != nil {
		return nil, os.NewError("exec: Stdout already set")
	}
	var b bytes.Buffer
	c.Stdout = &b
	err := c.Run()
	return b.Bytes(), err
}

// CombinedOutput runs the command and returns its combined standard
// output and standard error.
func (c *Cmd) CombinedOutput() ([]byte, os.Error) {
	if c.Stdout != nil {
		return nil, os.NewError("exec: Stdout already set")
	}
	if c.Stderr != nil {
		return nil, os.NewError("exec: Stderr already set")
	}
	var b bytes.Buffer
	c.Stdout = &b
	c.Stderr = &b
	err := c.Run()
	return b.Bytes(), err
}

// StdinPipe returns a pipe that will be connected to the command's
// standard input when the command starts.
func (c *Cmd) StdinPipe() (io.WriteCloser, os.Error) {
	if c.Stdin != nil {
		return nil, os.NewError("exec: Stdin already set")
	}
	if c.process != nil {
		return nil, os.NewError("exec: StdinPipe after process started")
	}
	pr, pw, err := os.Pipe()
	if err != nil {
		return nil, err
	}
	c.Stdin = pr
	c.closeAfterStart = append(c.closeAfterStart, pr)
	c.closeAfterWait = append(c.closeAfterStart, pw)
	return pw, nil
}

// StdoutPipe returns a pipe that will be connected to the command's
// standard output when the command starts.
func (c *Cmd) StdoutPipe() (io.Reader, os.Error) {
	if c.Stdout != nil {
		return nil, os.NewError("exec: Stdout already set")
	}
	if c.process != nil {
		return nil, os.NewError("exec: StdoutPipe after process started")
	}
	pr, pw, err := os.Pipe()
	if err != nil {
		return nil, err
	}
	c.Stdout = pw
	c.closeAfterStart = append(c.closeAfterStart, pw)
	c.closeAfterWait = append(c.closeAfterStart, pr)
	return pr, nil
}

// StderrPipe returns a pipe that will be connected to the command's
// standard error when the command starts.
func (c *Cmd) StderrPipe() (io.Reader, os.Error) {
	if c.Stderr != nil {
		return nil, os.NewError("exec: Stderr already set")
	}
	if c.process != nil {
		return nil, os.NewError("exec: StderrPipe after process started")
	}
	pr, pw, err := os.Pipe()
	if err != nil {
		return nil, err
	}
	c.Stderr = pw
	c.closeAfterStart = append(c.closeAfterStart, pw)
	c.closeAfterWait = append(c.closeAfterStart, pr)
	return pr, nil
}
<commit_msg>exec: export the underlying *os.Process in Cmd<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 exec runs external commands. It wraps os.StartProcess to make it
// easier to remap stdin and stdout, connect I/O with pipes, and do other
// adjustments.
package exec

import (
	"bytes"
	"io"
	"os"
	"strconv"
)

// Error records the name of a binary that failed to be be executed
// and the reason it failed.
type Error struct {
	Name  string
	Error os.Error
}

func (e *Error) String() string {
	return "exec: " + strconv.Quote(e.Name) + ": " + e.Error.String()
}

// Cmd represents an external command being prepared or run.
type Cmd struct {
	// Path is the path of the command to run.
	//
	// This is the only field that must be set to a non-zero
	// value.
	Path string

	// Args holds command line arguments, including the command as Args[0].
	// If the Args field is empty or nil, Run uses {Path}.
	//
	// In typical use, both Path and Args are set by calling Command.
	Args []string

	// Env specifies the environment of the process.
	// If Env is nil, Run uses the current process's environment.
	Env []string

	// Dir specifies the working directory of the command.
	// If Dir is the empty string, Run runs the command in the
	// calling process's current directory.
	Dir string

	// Stdin specifies the process's standard input.
	// If Stdin is nil, the process reads from DevNull.
	Stdin io.Reader

	// Stdout and Stderr specify the process's standard output and error.
	//
	// If either is nil, Run connects the
	// corresponding file descriptor to /dev/null.
	//
	// If Stdout and Stderr are are the same writer, at most one
	// goroutine at a time will call Write.
	Stdout io.Writer
	Stderr io.Writer

	// Process is the underlying process, once started.
	Process *os.Process

	err             os.Error // last error (from LookPath, stdin, stdout, stderr)
	finished        bool     // when Wait was called
	childFiles      []*os.File
	closeAfterStart []io.Closer
	closeAfterWait  []io.Closer
	goroutine       []func() os.Error
	errch           chan os.Error // one send per goroutine
}

// Command returns the Cmd struct to execute the named program with
// the given arguments.
//
// It sets Path and Args in the returned structure and zeroes the
// other fields.
//
// If name contains no path separators, Command uses LookPath to
// resolve the path to a complete name if possible. Otherwise it uses
// name directly.
//
// The returned Cmd's Args field is constructed from the command name
// followed by the elements of arg, so arg should not include the
// command name itself. For example, Command("echo", "hello")
func Command(name string, arg ...string) *Cmd {
	aname, err := LookPath(name)
	if err != nil {
		aname = name
	}
	return &Cmd{
		Path: aname,
		Args: append([]string{name}, arg...),
		err:  err,
	}
}

// interfaceEqual protects against panics from doing equality tests on
// two interfaces with non-comparable underlying types
func interfaceEqual(a, b interface{}) bool {
	defer func() {
		recover()
	}()
	return a == b
}

func (c *Cmd) envv() []string {
	if c.Env != nil {
		return c.Env
	}
	return os.Environ()
}

func (c *Cmd) argv() []string {
	if len(c.Args) > 0 {
		return c.Args
	}
	return []string{c.Path}
}

func (c *Cmd) stdin() (f *os.File, err os.Error) {
	if c.Stdin == nil {
		f, err = os.Open(os.DevNull)
		c.closeAfterStart = append(c.closeAfterStart, f)
		return
	}

	if f, ok := c.Stdin.(*os.File); ok {
		return f, nil
	}

	pr, pw, err := os.Pipe()
	if err != nil {
		return
	}

	c.closeAfterStart = append(c.closeAfterStart, pr)
	c.closeAfterWait = append(c.closeAfterWait, pw)
	c.goroutine = append(c.goroutine, func() os.Error {
		_, err := io.Copy(pw, c.Stdin)
		if err1 := pw.Close(); err == nil {
			err = err1
		}
		return err
	})
	return pr, nil
}

func (c *Cmd) stdout() (f *os.File, err os.Error) {
	return c.writerDescriptor(c.Stdout)
}

func (c *Cmd) stderr() (f *os.File, err os.Error) {
	if c.Stderr != nil && interfaceEqual(c.Stderr, c.Stdout) {
		return c.childFiles[1], nil
	}
	return c.writerDescriptor(c.Stderr)
}

func (c *Cmd) writerDescriptor(w io.Writer) (f *os.File, err os.Error) {
	if w == nil {
		f, err = os.OpenFile(os.DevNull, os.O_WRONLY, 0)
		c.closeAfterStart = append(c.closeAfterStart, f)
		return
	}

	if f, ok := w.(*os.File); ok {
		return f, nil
	}

	pr, pw, err := os.Pipe()
	if err != nil {
		return
	}

	c.closeAfterStart = append(c.closeAfterStart, pw)
	c.closeAfterWait = append(c.closeAfterWait, pr)
	c.goroutine = append(c.goroutine, func() os.Error {
		_, err := io.Copy(w, pr)
		return err
	})
	return pw, nil
}

// Run starts the specified command and waits for it to complete.
//
// The returned error is nil if the command runs, has no problems
// copying stdin, stdout, and stderr, and exits with a zero exit
// status.
//
// If the command fails to run or doesn't complete successfully, the
// error is of type *os.Waitmsg. Other error types may be
// returned for I/O problems.
func (c *Cmd) Run() os.Error {
	if err := c.Start(); err != nil {
		return err
	}
	return c.Wait()
}

// Start starts the specified command but does not wait for it to complete.
func (c *Cmd) Start() os.Error {
	if c.err != nil {
		return c.err
	}
	if c.Process != nil {
		return os.NewError("exec: already started")
	}

	type F func(*Cmd) (*os.File, os.Error)
	for _, setupFd := range []F{(*Cmd).stdin, (*Cmd).stdout, (*Cmd).stderr} {
		fd, err := setupFd(c)
		if err != nil {
			return err
		}
		c.childFiles = append(c.childFiles, fd)
	}

	var err os.Error
	c.Process, err = os.StartProcess(c.Path, c.argv(), &os.ProcAttr{
		Dir:   c.Dir,
		Files: c.childFiles,
		Env:   c.envv(),
	})
	if err != nil {
		return err
	}

	for _, fd := range c.closeAfterStart {
		fd.Close()
	}

	c.errch = make(chan os.Error, len(c.goroutine))
	for _, fn := range c.goroutine {
		go func(fn func() os.Error) {
			c.errch <- fn()
		}(fn)
	}

	return nil
}

// Wait waits for the command to exit.
// It must have been started by Start.
//
// The returned error is nil if the command runs, has no problems
// copying stdin, stdout, and stderr, and exits with a zero exit
// status.
//
// If the command fails to run or doesn't complete successfully, the
// error is of type *os.Waitmsg. Other error types may be
// returned for I/O problems.
func (c *Cmd) Wait() os.Error {
	if c.Process == nil {
		return os.NewError("exec: not started")
	}
	if c.finished {
		return os.NewError("exec: Wait was already called")
	}
	c.finished = true
	msg, err := c.Process.Wait(0)

	var copyError os.Error
	for _ = range c.goroutine {
		if err := <-c.errch; err != nil && copyError == nil {
			copyError = err
		}
	}

	for _, fd := range c.closeAfterWait {
		fd.Close()
	}

	if err != nil {
		return err
	} else if !msg.Exited() || msg.ExitStatus() != 0 {
		return msg
	}

	return copyError
}

// Output runs the command and returns its standard output.
func (c *Cmd) Output() ([]byte, os.Error) {
	if c.Stdout != nil {
		return nil, os.NewError("exec: Stdout already set")
	}
	var b bytes.Buffer
	c.Stdout = &b
	err := c.Run()
	return b.Bytes(), err
}

// CombinedOutput runs the command and returns its combined standard
// output and standard error.
func (c *Cmd) CombinedOutput() ([]byte, os.Error) {
	if c.Stdout != nil {
		return nil, os.NewError("exec: Stdout already set")
	}
	if c.Stderr != nil {
		return nil, os.NewError("exec: Stderr already set")
	}
	var b bytes.Buffer
	c.Stdout = &b
	c.Stderr = &b
	err := c.Run()
	return b.Bytes(), err
}

// StdinPipe returns a pipe that will be connected to the command's
// standard input when the command starts.
func (c *Cmd) StdinPipe() (io.WriteCloser, os.Error) {
	if c.Stdin != nil {
		return nil, os.NewError("exec: Stdin already set")
	}
	if c.Process != nil {
		return nil, os.NewError("exec: StdinPipe after process started")
	}
	pr, pw, err := os.Pipe()
	if err != nil {
		return nil, err
	}
	c.Stdin = pr
	c.closeAfterStart = append(c.closeAfterStart, pr)
	c.closeAfterWait = append(c.closeAfterStart, pw)
	return pw, nil
}

// StdoutPipe returns a pipe that will be connected to the command's
// standard output when the command starts.
func (c *Cmd) StdoutPipe() (io.Reader, os.Error) {
	if c.Stdout != nil {
		return nil, os.NewError("exec: Stdout already set")
	}
	if c.Process != nil {
		return nil, os.NewError("exec: StdoutPipe after process started")
	}
	pr, pw, err := os.Pipe()
	if err != nil {
		return nil, err
	}
	c.Stdout = pw
	c.closeAfterStart = append(c.closeAfterStart, pw)
	c.closeAfterWait = append(c.closeAfterStart, pr)
	return pr, nil
}

// StderrPipe returns a pipe that will be connected to the command's
// standard error when the command starts.
func (c *Cmd) StderrPipe() (io.Reader, os.Error) {
	if c.Stderr != nil {
		return nil, os.NewError("exec: Stderr already set")
	}
	if c.Process != nil {
		return nil, os.NewError("exec: StderrPipe after process started")
	}
	pr, pw, err := os.Pipe()
	if err != nil {
		return nil, err
	}
	c.Stderr = pw
	c.closeAfterStart = append(c.closeAfterStart, pw)
	c.closeAfterWait = append(c.closeAfterStart, pr)
	return pr, 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 exec runs external commands. It wraps os.StartProcess to make it
// easier to remap stdin and stdout, connect I/O with pipes, and do other
// adjustments.
package exec

import (
	"bytes"
	"io"
	"os"
	"strconv"
	"syscall"
)

// Error records the name of a binary that failed to be be executed
// and the reason it failed.
type Error struct {
	Name  string
	Error os.Error
}

func (e *Error) String() string {
	return "exec: " + strconv.Quote(e.Name) + ": " + e.Error.String()
}

// Cmd represents an external command being prepared or run.
type Cmd struct {
	// Path is the path of the command to run.
	//
	// This is the only field that must be set to a non-zero
	// value.
	Path string

	// Args holds command line arguments, including the command as Args[0].
	// If the Args field is empty or nil, Run uses {Path}.
	//
	// In typical use, both Path and Args are set by calling Command.
	Args []string

	// Env specifies the environment of the process.
	// If Env is nil, Run uses the current process's environment.
	Env []string

	// Dir specifies the working directory of the command.
	// If Dir is the empty string, Run runs the command in the
	// calling process's current directory.
	Dir string

	// Stdin specifies the process's standard input.
	// If Stdin is nil, the process reads from DevNull.
	Stdin io.Reader

	// Stdout and Stderr specify the process's standard output and error.
	//
	// If either is nil, Run connects the
	// corresponding file descriptor to /dev/null.
	//
	// If Stdout and Stderr are are the same writer, at most one
	// goroutine at a time will call Write.
	Stdout io.Writer
	Stderr io.Writer

	// SysProcAttr holds optional, operating system-specific attributes.
	// Run passes it to os.StartProcess as the os.ProcAttr's Sys field.
	SysProcAttr *syscall.SysProcAttr

	// Process is the underlying process, once started.
	Process *os.Process

	err             os.Error // last error (from LookPath, stdin, stdout, stderr)
	finished        bool     // when Wait was called
	childFiles      []*os.File
	closeAfterStart []io.Closer
	closeAfterWait  []io.Closer
	goroutine       []func() os.Error
	errch           chan os.Error // one send per goroutine
}

// Command returns the Cmd struct to execute the named program with
// the given arguments.
//
// It sets Path and Args in the returned structure and zeroes the
// other fields.
//
// If name contains no path separators, Command uses LookPath to
// resolve the path to a complete name if possible. Otherwise it uses
// name directly.
//
// The returned Cmd's Args field is constructed from the command name
// followed by the elements of arg, so arg should not include the
// command name itself. For example, Command("echo", "hello")
func Command(name string, arg ...string) *Cmd {
	aname, err := LookPath(name)
	if err != nil {
		aname = name
	}
	return &Cmd{
		Path: aname,
		Args: append([]string{name}, arg...),
		err:  err,
	}
}

// interfaceEqual protects against panics from doing equality tests on
// two interfaces with non-comparable underlying types
func interfaceEqual(a, b interface{}) bool {
	defer func() {
		recover()
	}()
	return a == b
}

func (c *Cmd) envv() []string {
	if c.Env != nil {
		return c.Env
	}
	return os.Environ()
}

func (c *Cmd) argv() []string {
	if len(c.Args) > 0 {
		return c.Args
	}
	return []string{c.Path}
}

func (c *Cmd) stdin() (f *os.File, err os.Error) {
	if c.Stdin == nil {
		f, err = os.Open(os.DevNull)
		c.closeAfterStart = append(c.closeAfterStart, f)
		return
	}

	if f, ok := c.Stdin.(*os.File); ok {
		return f, nil
	}

	pr, pw, err := os.Pipe()
	if err != nil {
		return
	}

	c.closeAfterStart = append(c.closeAfterStart, pr)
	c.closeAfterWait = append(c.closeAfterWait, pw)
	c.goroutine = append(c.goroutine, func() os.Error {
		_, err := io.Copy(pw, c.Stdin)
		if err1 := pw.Close(); err == nil {
			err = err1
		}
		return err
	})
	return pr, nil
}

func (c *Cmd) stdout() (f *os.File, err os.Error) {
	return c.writerDescriptor(c.Stdout)
}

func (c *Cmd) stderr() (f *os.File, err os.Error) {
	if c.Stderr != nil && interfaceEqual(c.Stderr, c.Stdout) {
		return c.childFiles[1], nil
	}
	return c.writerDescriptor(c.Stderr)
}

func (c *Cmd) writerDescriptor(w io.Writer) (f *os.File, err os.Error) {
	if w == nil {
		f, err = os.OpenFile(os.DevNull, os.O_WRONLY, 0)
		c.closeAfterStart = append(c.closeAfterStart, f)
		return
	}

	if f, ok := w.(*os.File); ok {
		return f, nil
	}

	pr, pw, err := os.Pipe()
	if err != nil {
		return
	}

	c.closeAfterStart = append(c.closeAfterStart, pw)
	c.closeAfterWait = append(c.closeAfterWait, pr)
	c.goroutine = append(c.goroutine, func() os.Error {
		_, err := io.Copy(w, pr)
		return err
	})
	return pw, nil
}

// Run starts the specified command and waits for it to complete.
//
// The returned error is nil if the command runs, has no problems
// copying stdin, stdout, and stderr, and exits with a zero exit
// status.
//
// If the command fails to run or doesn't complete successfully, the
// error is of type *os.Waitmsg. Other error types may be
// returned for I/O problems.
func (c *Cmd) Run() os.Error {
	if err := c.Start(); err != nil {
		return err
	}
	return c.Wait()
}

// Start starts the specified command but does not wait for it to complete.
func (c *Cmd) Start() os.Error {
	if c.err != nil {
		return c.err
	}
	if c.Process != nil {
		return os.NewError("exec: already started")
	}

	type F func(*Cmd) (*os.File, os.Error)
	for _, setupFd := range []F{(*Cmd).stdin, (*Cmd).stdout, (*Cmd).stderr} {
		fd, err := setupFd(c)
		if err != nil {
			return err
		}
		c.childFiles = append(c.childFiles, fd)
	}

	var err os.Error
	c.Process, err = os.StartProcess(c.Path, c.argv(), &os.ProcAttr{
		Dir:   c.Dir,
		Files: c.childFiles,
		Env:   c.envv(),
		Sys:   c.SysProcAttr,
	})
	if err != nil {
		return err
	}

	for _, fd := range c.closeAfterStart {
		fd.Close()
	}

	c.errch = make(chan os.Error, len(c.goroutine))
	for _, fn := range c.goroutine {
		go func(fn func() os.Error) {
			c.errch <- fn()
		}(fn)
	}

	return nil
}

// Wait waits for the command to exit.
// It must have been started by Start.
//
// The returned error is nil if the command runs, has no problems
// copying stdin, stdout, and stderr, and exits with a zero exit
// status.
//
// If the command fails to run or doesn't complete successfully, the
// error is of type *os.Waitmsg. Other error types may be
// returned for I/O problems.
func (c *Cmd) Wait() os.Error {
	if c.Process == nil {
		return os.NewError("exec: not started")
	}
	if c.finished {
		return os.NewError("exec: Wait was already called")
	}
	c.finished = true
	msg, err := c.Process.Wait(0)

	var copyError os.Error
	for _ = range c.goroutine {
		if err := <-c.errch; err != nil && copyError == nil {
			copyError = err
		}
	}

	for _, fd := range c.closeAfterWait {
		fd.Close()
	}

	if err != nil {
		return err
	} else if !msg.Exited() || msg.ExitStatus() != 0 {
		return msg
	}

	return copyError
}

// Output runs the command and returns its standard output.
func (c *Cmd) Output() ([]byte, os.Error) {
	if c.Stdout != nil {
		return nil, os.NewError("exec: Stdout already set")
	}
	var b bytes.Buffer
	c.Stdout = &b
	err := c.Run()
	return b.Bytes(), err
}

// CombinedOutput runs the command and returns its combined standard
// output and standard error.
func (c *Cmd) CombinedOutput() ([]byte, os.Error) {
	if c.Stdout != nil {
		return nil, os.NewError("exec: Stdout already set")
	}
	if c.Stderr != nil {
		return nil, os.NewError("exec: Stderr already set")
	}
	var b bytes.Buffer
	c.Stdout = &b
	c.Stderr = &b
	err := c.Run()
	return b.Bytes(), err
}

// StdinPipe returns a pipe that will be connected to the command's
// standard input when the command starts.
func (c *Cmd) StdinPipe() (io.WriteCloser, os.Error) {
	if c.Stdin != nil {
		return nil, os.NewError("exec: Stdin already set")
	}
	if c.Process != nil {
		return nil, os.NewError("exec: StdinPipe after process started")
	}
	pr, pw, err := os.Pipe()
	if err != nil {
		return nil, err
	}
	c.Stdin = pr
	c.closeAfterStart = append(c.closeAfterStart, pr)
	c.closeAfterWait = append(c.closeAfterStart, pw)
	return pw, nil
}

// StdoutPipe returns a pipe that will be connected to the command's
// standard output when the command starts.
func (c *Cmd) StdoutPipe() (io.Reader, os.Error) {
	if c.Stdout != nil {
		return nil, os.NewError("exec: Stdout already set")
	}
	if c.Process != nil {
		return nil, os.NewError("exec: StdoutPipe after process started")
	}
	pr, pw, err := os.Pipe()
	if err != nil {
		return nil, err
	}
	c.Stdout = pw
	c.closeAfterStart = append(c.closeAfterStart, pw)
	c.closeAfterWait = append(c.closeAfterStart, pr)
	return pr, nil
}

// StderrPipe returns a pipe that will be connected to the command's
// standard error when the command starts.
func (c *Cmd) StderrPipe() (io.Reader, os.Error) {
	if c.Stderr != nil {
		return nil, os.NewError("exec: Stderr already set")
	}
	if c.Process != nil {
		return nil, os.NewError("exec: StderrPipe after process started")
	}
	pr, pw, err := os.Pipe()
	if err != nil {
		return nil, err
	}
	c.Stderr = pw
	c.closeAfterStart = append(c.closeAfterStart, pw)
	c.closeAfterWait = append(c.closeAfterStart, pr)
	return pr, nil
}
<commit_msg>exec: closeAfterWait append bug<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 exec runs external commands. It wraps os.StartProcess to make it
// easier to remap stdin and stdout, connect I/O with pipes, and do other
// adjustments.
package exec

import (
	"bytes"
	"io"
	"os"
	"strconv"
	"syscall"
)

// Error records the name of a binary that failed to be be executed
// and the reason it failed.
type Error struct {
	Name  string
	Error os.Error
}

func (e *Error) String() string {
	return "exec: " + strconv.Quote(e.Name) + ": " + e.Error.String()
}

// Cmd represents an external command being prepared or run.
type Cmd struct {
	// Path is the path of the command to run.
	//
	// This is the only field that must be set to a non-zero
	// value.
	Path string

	// Args holds command line arguments, including the command as Args[0].
	// If the Args field is empty or nil, Run uses {Path}.
	//
	// In typical use, both Path and Args are set by calling Command.
	Args []string

	// Env specifies the environment of the process.
	// If Env is nil, Run uses the current process's environment.
	Env []string

	// Dir specifies the working directory of the command.
	// If Dir is the empty string, Run runs the command in the
	// calling process's current directory.
	Dir string

	// Stdin specifies the process's standard input.
	// If Stdin is nil, the process reads from DevNull.
	Stdin io.Reader

	// Stdout and Stderr specify the process's standard output and error.
	//
	// If either is nil, Run connects the
	// corresponding file descriptor to /dev/null.
	//
	// If Stdout and Stderr are are the same writer, at most one
	// goroutine at a time will call Write.
	Stdout io.Writer
	Stderr io.Writer

	// SysProcAttr holds optional, operating system-specific attributes.
	// Run passes it to os.StartProcess as the os.ProcAttr's Sys field.
	SysProcAttr *syscall.SysProcAttr

	// Process is the underlying process, once started.
	Process *os.Process

	err             os.Error // last error (from LookPath, stdin, stdout, stderr)
	finished        bool     // when Wait was called
	childFiles      []*os.File
	closeAfterStart []io.Closer
	closeAfterWait  []io.Closer
	goroutine       []func() os.Error
	errch           chan os.Error // one send per goroutine
}

// Command returns the Cmd struct to execute the named program with
// the given arguments.
//
// It sets Path and Args in the returned structure and zeroes the
// other fields.
//
// If name contains no path separators, Command uses LookPath to
// resolve the path to a complete name if possible. Otherwise it uses
// name directly.
//
// The returned Cmd's Args field is constructed from the command name
// followed by the elements of arg, so arg should not include the
// command name itself. For example, Command("echo", "hello")
func Command(name string, arg ...string) *Cmd {
	aname, err := LookPath(name)
	if err != nil {
		aname = name
	}
	return &Cmd{
		Path: aname,
		Args: append([]string{name}, arg...),
		err:  err,
	}
}

// interfaceEqual protects against panics from doing equality tests on
// two interfaces with non-comparable underlying types
func interfaceEqual(a, b interface{}) bool {
	defer func() {
		recover()
	}()
	return a == b
}

func (c *Cmd) envv() []string {
	if c.Env != nil {
		return c.Env
	}
	return os.Environ()
}

func (c *Cmd) argv() []string {
	if len(c.Args) > 0 {
		return c.Args
	}
	return []string{c.Path}
}

func (c *Cmd) stdin() (f *os.File, err os.Error) {
	if c.Stdin == nil {
		f, err = os.Open(os.DevNull)
		c.closeAfterStart = append(c.closeAfterStart, f)
		return
	}

	if f, ok := c.Stdin.(*os.File); ok {
		return f, nil
	}

	pr, pw, err := os.Pipe()
	if err != nil {
		return
	}

	c.closeAfterStart = append(c.closeAfterStart, pr)
	c.closeAfterWait = append(c.closeAfterWait, pw)
	c.goroutine = append(c.goroutine, func() os.Error {
		_, err := io.Copy(pw, c.Stdin)
		if err1 := pw.Close(); err == nil {
			err = err1
		}
		return err
	})
	return pr, nil
}

func (c *Cmd) stdout() (f *os.File, err os.Error) {
	return c.writerDescriptor(c.Stdout)
}

func (c *Cmd) stderr() (f *os.File, err os.Error) {
	if c.Stderr != nil && interfaceEqual(c.Stderr, c.Stdout) {
		return c.childFiles[1], nil
	}
	return c.writerDescriptor(c.Stderr)
}

func (c *Cmd) writerDescriptor(w io.Writer) (f *os.File, err os.Error) {
	if w == nil {
		f, err = os.OpenFile(os.DevNull, os.O_WRONLY, 0)
		c.closeAfterStart = append(c.closeAfterStart, f)
		return
	}

	if f, ok := w.(*os.File); ok {
		return f, nil
	}

	pr, pw, err := os.Pipe()
	if err != nil {
		return
	}

	c.closeAfterStart = append(c.closeAfterStart, pw)
	c.closeAfterWait = append(c.closeAfterWait, pr)
	c.goroutine = append(c.goroutine, func() os.Error {
		_, err := io.Copy(w, pr)
		return err
	})
	return pw, nil
}

// Run starts the specified command and waits for it to complete.
//
// The returned error is nil if the command runs, has no problems
// copying stdin, stdout, and stderr, and exits with a zero exit
// status.
//
// If the command fails to run or doesn't complete successfully, the
// error is of type *os.Waitmsg. Other error types may be
// returned for I/O problems.
func (c *Cmd) Run() os.Error {
	if err := c.Start(); err != nil {
		return err
	}
	return c.Wait()
}

// Start starts the specified command but does not wait for it to complete.
func (c *Cmd) Start() os.Error {
	if c.err != nil {
		return c.err
	}
	if c.Process != nil {
		return os.NewError("exec: already started")
	}

	type F func(*Cmd) (*os.File, os.Error)
	for _, setupFd := range []F{(*Cmd).stdin, (*Cmd).stdout, (*Cmd).stderr} {
		fd, err := setupFd(c)
		if err != nil {
			return err
		}
		c.childFiles = append(c.childFiles, fd)
	}

	var err os.Error
	c.Process, err = os.StartProcess(c.Path, c.argv(), &os.ProcAttr{
		Dir:   c.Dir,
		Files: c.childFiles,
		Env:   c.envv(),
		Sys:   c.SysProcAttr,
	})
	if err != nil {
		return err
	}

	for _, fd := range c.closeAfterStart {
		fd.Close()
	}

	c.errch = make(chan os.Error, len(c.goroutine))
	for _, fn := range c.goroutine {
		go func(fn func() os.Error) {
			c.errch <- fn()
		}(fn)
	}

	return nil
}

// Wait waits for the command to exit.
// It must have been started by Start.
//
// The returned error is nil if the command runs, has no problems
// copying stdin, stdout, and stderr, and exits with a zero exit
// status.
//
// If the command fails to run or doesn't complete successfully, the
// error is of type *os.Waitmsg. Other error types may be
// returned for I/O problems.
func (c *Cmd) Wait() os.Error {
	if c.Process == nil {
		return os.NewError("exec: not started")
	}
	if c.finished {
		return os.NewError("exec: Wait was already called")
	}
	c.finished = true
	msg, err := c.Process.Wait(0)

	var copyError os.Error
	for _ = range c.goroutine {
		if err := <-c.errch; err != nil && copyError == nil {
			copyError = err
		}
	}

	for _, fd := range c.closeAfterWait {
		fd.Close()
	}

	if err != nil {
		return err
	} else if !msg.Exited() || msg.ExitStatus() != 0 {
		return msg
	}

	return copyError
}

// Output runs the command and returns its standard output.
func (c *Cmd) Output() ([]byte, os.Error) {
	if c.Stdout != nil {
		return nil, os.NewError("exec: Stdout already set")
	}
	var b bytes.Buffer
	c.Stdout = &b
	err := c.Run()
	return b.Bytes(), err
}

// CombinedOutput runs the command and returns its combined standard
// output and standard error.
func (c *Cmd) CombinedOutput() ([]byte, os.Error) {
	if c.Stdout != nil {
		return nil, os.NewError("exec: Stdout already set")
	}
	if c.Stderr != nil {
		return nil, os.NewError("exec: Stderr already set")
	}
	var b bytes.Buffer
	c.Stdout = &b
	c.Stderr = &b
	err := c.Run()
	return b.Bytes(), err
}

// StdinPipe returns a pipe that will be connected to the command's
// standard input when the command starts.
func (c *Cmd) StdinPipe() (io.WriteCloser, os.Error) {
	if c.Stdin != nil {
		return nil, os.NewError("exec: Stdin already set")
	}
	if c.Process != nil {
		return nil, os.NewError("exec: StdinPipe after process started")
	}
	pr, pw, err := os.Pipe()
	if err != nil {
		return nil, err
	}
	c.Stdin = pr
	c.closeAfterStart = append(c.closeAfterStart, pr)
	c.closeAfterWait = append(c.closeAfterWait, pw)
	return pw, nil
}

// StdoutPipe returns a pipe that will be connected to the command's
// standard output when the command starts.
func (c *Cmd) StdoutPipe() (io.Reader, os.Error) {
	if c.Stdout != nil {
		return nil, os.NewError("exec: Stdout already set")
	}
	if c.Process != nil {
		return nil, os.NewError("exec: StdoutPipe after process started")
	}
	pr, pw, err := os.Pipe()
	if err != nil {
		return nil, err
	}
	c.Stdout = pw
	c.closeAfterStart = append(c.closeAfterStart, pw)
	c.closeAfterWait = append(c.closeAfterWait, pr)
	return pr, nil
}

// StderrPipe returns a pipe that will be connected to the command's
// standard error when the command starts.
func (c *Cmd) StderrPipe() (io.Reader, os.Error) {
	if c.Stderr != nil {
		return nil, os.NewError("exec: Stderr already set")
	}
	if c.Process != nil {
		return nil, os.NewError("exec: StderrPipe after process started")
	}
	pr, pw, err := os.Pipe()
	if err != nil {
		return nil, err
	}
	c.Stderr = pw
	c.closeAfterStart = append(c.closeAfterStart, pw)
	c.closeAfterWait = append(c.closeAfterWait, pr)
	return pr, nil
}
<|endoftext|>


<commit_before>// Copyright 2010 The W32 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 w32

import (
    "fmt"
    "syscall"
    "unsafe"
)

func MakeIntResource(id uint16) *uint16 {
    return (*uint16)(unsafe.Pointer(uintptr(id)))
}

func LOWORD(dw uint) uint16 {
    return uint16(dw)
}

func HIWORD(dw uint) uint16 {
    return uint16(dw >> 16 & 0xffff)
}

func LoadLib(name string) uintptr {
    lib, err := syscall.LoadLibrary(name)
    if err != 0 {
        panic(fmt.Sprintf("syscall.LoadLibrary('%s') failed: %s",
            name, syscall.Errstr(err)))
    }
    return uintptr(lib)
}

func GetProcAddr(lib uintptr, name string) uintptr {
    addr, err := syscall.GetProcAddress(syscall.Handle(lib), name)
    if err != 0 {
        panic(fmt.Sprintf("syscal.GetProcAddress(%d, '%s') failed: %s",
            lib, name, syscall.Errstr(err)))
    }
    return uintptr(addr)
}

func BoolToBOOL(value bool) BOOL {
	if value {
		return 1
	}

	return 0
}

func UTF16PtrToString(s *uint16) string {
	return syscall.UTF16ToString((*[1 << 30]uint16)(unsafe.Pointer(s))[0:])
}
<commit_msg>Update to be compatible with newest weekly release of Go.<commit_after>// Copyright 2010 The W32 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 w32

import (
    "fmt"
    "syscall"
    "unsafe"
)

func MakeIntResource(id uint16) *uint16 {
    return (*uint16)(unsafe.Pointer(uintptr(id)))
}

func LOWORD(dw uint) uint16 {
    return uint16(dw)
}

func HIWORD(dw uint) uint16 {
    return uint16(dw >> 16 & 0xffff)
}

func LoadLib(name string) uintptr {
    lib, err := syscall.LoadLibrary(name)
    if err != nil {
        panic(fmt.Sprintf("syscall.LoadLibrary('%s') failed: %s",
            name, err.Error()))
    }
    return uintptr(lib)
}

func GetProcAddr(lib uintptr, name string) uintptr {
    addr, err := syscall.GetProcAddress(syscall.Handle(lib), name)
    if err != nil {
        panic(fmt.Sprintf("syscal.GetProcAddress(%d, '%s') failed: %s",
            lib, name, err.Error()))
    }
    return uintptr(addr)
}

func BoolToBOOL(value bool) BOOL {
	if value {
		return 1
	}

	return 0
}

func UTF16PtrToString(s *uint16) string {
	return syscall.UTF16ToString((*[1 << 30]uint16)(unsafe.Pointer(s))[0:])
}
<|endoftext|>


<commit_before>package finago

//import "fmt"
import "net"
import "math/rand"
import "sync"
import "time"

type connEntry struct {
	conn net.Conn
	host string
	port string
	state int
}

type destEntry struct {
	dest string
	free []*connEntry
	used []*connEntry
	rwlock *sync.RWMutex
}

func (entry *destEntry) getConn() net.Conn {
	var conn net.Conn
	entry.rwlock.Lock()
	defer entry.rwlock.Unlock()
	if len(entry.free) > 0 {
		var front *connEntry
		front, entry.free = entry.free[0], entry.free[1:]
		front.state = 1
		entry.used = append(entry.used, front)
		conn = front.conn
	} else {
		conn, _ = net.DialTimeout("tcp", entry.dest, 10)
		host, port, _ := net.SplitHostPort(entry.dest)
		cEntry := &connEntry{
			conn: conn,
			host: host,
			port: port,
			state: 0,
		}
		entry.used = append(entry.used, cEntry)
	}
	return conn
}

type ConnectionPoolFactory struct {
	dests []string
	destMap map[string]*destEntry
}

type ConnectionPool struct {
	conn net.Conn
	factory *ConnectionPoolFactory
}

func NewConnectionPoolFactory(dests []string) *ConnectionPoolFactory {
	return &ConnectionPoolFactory{dests: dests, destMap: make(map[string]*destEntry)}
}

func (factory *ConnectionPoolFactory) Build() *ConnectionPool {
	return &ConnectionPool{conn: nil, factory: factory}
}

func (factory *ConnectionPoolFactory) freeConn(conn net.Conn) {

}

func (factory *ConnectionPoolFactory) chooseDest() string {
	size := len(factory.dests)
	choice := rand.Intn(size)
	dest := factory.dests[choice]
	return dest
}

func (factory *ConnectionPoolFactory) getConn() net.Conn {
	dest := factory.chooseDest()
	if dEntry, ok := factory.destMap[dest]; ok {
		return dEntry.getConn()
	}
	dEntry := &destEntry {
		dest: dest,
		free: nil,
		used: nil,
		rwlock: new(sync.RWMutex),
	}
	factory.destMap[dest] = dEntry
	return dEntry.getConn()
}

func (cp *ConnectionPool) getConn() net.Conn {
	if conn:= cp.conn; conn != nil {
		return conn
	}
	conn := cp.factory.getConn()
	cp.conn = conn
	return conn
}

func (cp *ConnectionPool) Read(b []byte) (n int, err error) {
	return cp.getConn().Read(b)
}

// Write writes data to the connection.
// Write can be made to time out and return a Error with Timeout() == true
// after a fixed time limit; see SetDeadline and SetWriteDeadline.
func (cp *ConnectionPool) Write(b []byte) (n int, err error) {
	return cp.getConn().Write(b)
}

// Close closes the connection.
// Any blocked Read or Write operations will be unblocked and return errors.
func (cp *ConnectionPool) Close() error {
	if cp.conn != nil {
		cp.factory.freeConn(cp.conn)
		cp.conn = nil
	}
	return nil
}

// LocalAddr returns the local network address.
func (cp *ConnectionPool) LocalAddr() net.Addr {
	return cp.getConn().LocalAddr()
}

// RemoteAddr returns the remote network address.
func (cp *ConnectionPool) RemoteAddr() net.Addr {
	return cp.getConn().RemoteAddr()
}

// SetDeadline sets the read and write deadlines associated
// with the connection. It is equivalent to calling both
// SetReadDeadline and SetWriteDeadline.
//
// A deadline is an absolute time after which I/O operations
// fail with a timeout (see type Error) instead of
// blocking. The deadline applies to all future I/O, not just
// the immediately following call to Read or Write.
//
// An idle timeout can be implemented by repeatedly extending
// the deadline after successful Read or Write calls.
//
// A zero value for t means I/O operations will not time out.
func (cp *ConnectionPool) SetDeadline(t time.Time) error {
	return cp.getConn().SetDeadline(t)
}

// SetReadDeadline sets the deadline for future Read calls.
// A zero value for t means Read will not time out.
func (cp *ConnectionPool) SetReadDeadline(t time.Time) error {
	return cp.getConn().SetReadDeadline(t)
}

// SetWriteDeadline sets the deadline for future Write calls.
// Even if write times out, it may return n > 0, indicating that
// some of the data was successfully written.
// A zero value for t means Write will not time out.
func (cp *ConnectionPool) SetWriteDeadline(t time.Time) error {
	return cp.getConn().SetWriteDeadline(t)
}
<commit_msg>updates<commit_after>package finago

//import "fmt"
import "net"
import "math/rand"
import "sync"
import "time"

type connEntry struct {
	conn net.Conn
	waitQueue int
}

type destEntry struct {
	dest string
	rwlock *sync.RWMutex
}

func (entry *destEntry) getConn() net.Conn {
	var conn net.Conn
	entry.rwlock.Lock()
	defer entry.rwlock.Unlock()
	if len(entry.free) > 0 {
		var front *connEntry
		front, entry.free = entry.free[0], entry.free[1:]
		front.state = 1
		entry.used = append(entry.used, front)
		conn = front.conn
	} else {
		conn, _ = net.DialTimeout("tcp", entry.dest, 10)
		host, port, _ := net.SplitHostPort(entry.dest)
		cEntry := &connEntry{
			conn: conn,
			host: host,
			port: port,
			state: 0,
		}
		entry.used = append(entry.used, cEntry)
	}
	return conn
}

type ConnectionPoolFactory struct {
	entries []*destEntry
}

type ConnectionPool struct {
	conn net.Conn
	factory *ConnectionPoolFactory
}

func NewConnectionPoolFactory(dests []string) *ConnectionPoolFactory {
	entries := make([]*destEntry, 0, len(dests))
	for _, dest := range dests {
		entry := &destEntry {
			dest: dest,
			rwlock: new(sync.RWMutex)
		}
		entries = append(entries, entry)
	}
	return &ConnectionPoolFactory{entries: entries}
}

func (factory *ConnectionPoolFactory) Build() *ConnectionPool {
	return &ConnectionPool{conn: nil, factory: factory}
}

func (factory *ConnectionPoolFactory) freeConn(conn net.Conn) {

}

func (factory *ConnectionPoolFactory) choose() *destEntry {
	size := len(factory.entries)
	choice := rand.Intn(size)
	dest := factory.dests[choice]
	return dest
}

func (factory *ConnectionPoolFactory) getConn() net.Conn {
	dest := factory.chooseDest()
	if dEntry, ok := factory.destMap[dest]; ok {
		return dEntry.getConn()
	}
	dEntry := &destEntry {
		dest: dest,
		free: nil,
		used: nil,
		rwlock: new(sync.RWMutex),
	}
	factory.destMap[dest] = dEntry
	return dEntry.getConn()
}

func (cp *ConnectionPool) getConn() net.Conn {
	if conn:= cp.conn; conn != nil {
		return conn
	}
	conn := cp.factory.getConn()
	cp.conn = conn
	return conn
}

func (cp *ConnectionPool) Read(b []byte) (n int, err error) {
	return cp.getConn().Read(b)
}

// Write writes data to the connection.
// Write can be made to time out and return a Error with Timeout() == true
// after a fixed time limit; see SetDeadline and SetWriteDeadline.
func (cp *ConnectionPool) Write(b []byte) (n int, err error) {
	return cp.getConn().Write(b)
}

// Close closes the connection.
// Any blocked Read or Write operations will be unblocked and return errors.
func (cp *ConnectionPool) Close() error {
	if cp.conn != nil {
		cp.factory.freeConn(cp.conn)
		cp.conn = nil
	}
	return nil
}

// LocalAddr returns the local network address.
func (cp *ConnectionPool) LocalAddr() net.Addr {
	return cp.getConn().LocalAddr()
}

// RemoteAddr returns the remote network address.
func (cp *ConnectionPool) RemoteAddr() net.Addr {
	return cp.getConn().RemoteAddr()
}

// SetDeadline sets the read and write deadlines associated
// with the connection. It is equivalent to calling both
// SetReadDeadline and SetWriteDeadline.
//
// A deadline is an absolute time after which I/O operations
// fail with a timeout (see type Error) instead of
// blocking. The deadline applies to all future I/O, not just
// the immediately following call to Read or Write.
//
// An idle timeout can be implemented by repeatedly extending
// the deadline after successful Read or Write calls.
//
// A zero value for t means I/O operations will not time out.
func (cp *ConnectionPool) SetDeadline(t time.Time) error {
	return cp.getConn().SetDeadline(t)
}

// SetReadDeadline sets the deadline for future Read calls.
// A zero value for t means Read will not time out.
func (cp *ConnectionPool) SetReadDeadline(t time.Time) error {
	return cp.getConn().SetReadDeadline(t)
}

// SetWriteDeadline sets the deadline for future Write calls.
// Even if write times out, it may return n > 0, indicating that
// some of the data was successfully written.
// A zero value for t means Write will not time out.
func (cp *ConnectionPool) SetWriteDeadline(t time.Time) error {
	return cp.getConn().SetWriteDeadline(t)
}
<|endoftext|>


<commit_before>package rbac

import (
	"reflect"

	"github.com/pkg/errors"
	"github.com/rancher/norman/types/convert"
	"github.com/rancher/norman/types/slice"
	v3 "github.com/rancher/types/apis/management.cattle.io/v3"
	"github.com/sirupsen/logrus"
	v1 "k8s.io/api/core/v1"
	rbacv1 "k8s.io/api/rbac/v1"
	apierrors "k8s.io/apimachinery/pkg/api/errors"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apimachinery/pkg/labels"
	"k8s.io/apimachinery/pkg/runtime"
)

const owner = "owner-user"

var globalResourcesNeededInProjects = map[string]map[string]bool{
	"persistentvolumes": {
		"":     true,
		"core": true,
	},
	"storageclasses": {
		"storage.k8s.io": true,
	},
	"apiservices": {
		"apiregistration.k8s.io": true,
	},
}

func newPRTBLifecycle(m *manager) *prtbLifecycle {
	return &prtbLifecycle{m: m}
}

type prtbLifecycle struct {
	m *manager
}

func (p *prtbLifecycle) Create(obj *v3.ProjectRoleTemplateBinding) (runtime.Object, error) {
	err := p.syncPRTB(obj)
	return obj, err
}

func (p *prtbLifecycle) Updated(obj *v3.ProjectRoleTemplateBinding) (runtime.Object, error) {
	err := p.syncPRTB(obj)
	return obj, err
}

func (p *prtbLifecycle) Remove(obj *v3.ProjectRoleTemplateBinding) (runtime.Object, error) {
	err := p.ensurePRTBDelete(obj)
	return obj, err
}

func (p *prtbLifecycle) syncPRTB(binding *v3.ProjectRoleTemplateBinding) error {
	if binding.RoleTemplateName == "" {
		logrus.Warnf("ProjectRoleTemplateBinding %v has no role template set. Skipping.", binding.Name)
		return nil
	}
	if binding.UserName == "" && binding.GroupPrincipalName == "" && binding.GroupName == "" && binding.ServiceAccount == "" {
		return nil
	}

	rt, err := p.m.rtLister.Get("", binding.RoleTemplateName)
	if err != nil {
		return errors.Wrapf(err, "couldn't get role template %v", binding.RoleTemplateName)
	}

	// Get namespaces belonging to project
	namespaces, err := p.m.nsIndexer.ByIndex(nsByProjectIndex, binding.ProjectName)
	if err != nil {
		return errors.Wrapf(err, "couldn't list namespaces with project ID %v", binding.ProjectName)
	}
	roles := map[string]*v3.RoleTemplate{}
	if err := p.m.gatherRoles(rt, roles); err != nil {
		return err
	}

	if err := p.m.ensureRoles(roles); err != nil {
		return errors.Wrap(err, "couldn't ensure roles")
	}

	for _, n := range namespaces {
		ns := n.(*v1.Namespace)
		if err := p.m.ensureProjectRoleBindings(ns.Name, roles, binding); err != nil {
			return errors.Wrapf(err, "couldn't ensure binding %v in %v", binding.Name, ns.Name)
		}
	}

	return p.reconcileProjectAccessToGlobalResources(binding, roles)
}

func (p *prtbLifecycle) ensurePRTBDelete(binding *v3.ProjectRoleTemplateBinding) error {
	// Get namespaces belonging to project
	namespaces, err := p.m.nsIndexer.ByIndex(nsByProjectIndex, binding.ProjectName)
	if err != nil {
		return errors.Wrapf(err, "couldn't list namespaces with project ID %v", binding.ProjectName)
	}

	set := labels.Set(map[string]string{rtbOwnerLabel: string(binding.UID)})
	for _, n := range namespaces {
		ns := n.(*v1.Namespace)
		bindingCli := p.m.workload.RBAC.RoleBindings(ns.Name)
		rbs, err := p.m.rbLister.List(ns.Name, set.AsSelector())
		if err != nil {
			return errors.Wrapf(err, "couldn't list rolebindings with selector %s", set.AsSelector())
		}

		for _, rb := range rbs {
			if err := bindingCli.Delete(rb.Name, &metav1.DeleteOptions{}); err != nil {
				if !apierrors.IsNotFound(err) {
					return errors.Wrapf(err, "error deleting rolebinding %v", rb.Name)
				}
			}
		}
	}

	return p.reconcileProjectAccessToGlobalResourcesForDelete(binding)
}

func (p *prtbLifecycle) reconcileProjectAccessToGlobalResources(binding *v3.ProjectRoleTemplateBinding, rts map[string]*v3.RoleTemplate) error {
	_, err := p.m.reconcileProjectAccessToGlobalResources(binding, rts)
	if err != nil {
		return err
	}
	return nil
}

func (p *prtbLifecycle) reconcileProjectAccessToGlobalResourcesForDelete(binding *v3.ProjectRoleTemplateBinding) error {
	bindingCli := p.m.workload.RBAC.ClusterRoleBindings("")
	rtbUID := string(binding.UID)
	set := labels.Set(map[string]string{rtbUID: owner})
	crbs, err := p.m.crbLister.List("", set.AsSelector())
	if err != nil {
		return err
	}

	for _, crb := range crbs {
		crb = crb.DeepCopy()
		for k, v := range crb.Labels {
			if k == rtbUID && v == owner {
				delete(crb.Labels, k)
			}
		}

		delete, err := p.m.noRemainingOwnerLabels(crb)
		if err != nil {
			return err
		}

		if delete {
			if err := bindingCli.Delete(crb.Name, &metav1.DeleteOptions{}); err != nil {
				if apierrors.IsNotFound(err) {
					continue
				}
				return err
			}
		} else {
			if _, err := bindingCli.Update(crb); err != nil {
				return err
			}
		}
	}

	return nil
}

func (m *manager) noRemainingOwnerLabels(crb *rbacv1.ClusterRoleBinding) (bool, error) {
	for k, v := range crb.Labels {
		if v == owner {
			if exists, err := m.ownerExists(k); exists || err != nil {
				return false, err
			}
		}

		if k == rtbOwnerLabel {
			if exists, err := m.ownerExists(v); exists || err != nil {
				return false, err
			}
		}
	}

	return true, nil
}

func (m *manager) ownerExists(uid interface{}) (bool, error) {
	prtbs, err := m.prtbIndexer.ByIndex(prtbByUIDIndex, convert.ToString(uid))
	return len(prtbs) > 0, err
}

// If the roleTemplate has rules granting access to non-namespaced (global) resource, return the verbs for those rules
func (m *manager) checkForGlobalResourceRules(role *v3.RoleTemplate, resource string) (map[string]bool, error) {
	var rules []rbacv1.PolicyRule
	if role.External {
		externalRole, err := m.crLister.Get("", role.Name)
		if err != nil && !apierrors.IsNotFound(err) {
			// dont error if it doesnt exist
			return nil, err
		}
		if externalRole != nil {
			rules = externalRole.Rules
		}
	} else {
		rules = role.Rules
	}

	verbs := map[string]bool{}
	for _, rule := range rules {
		if (slice.ContainsString(rule.Resources, resource) || slice.ContainsString(rule.Resources, "*")) && len(rule.ResourceNames) == 0 {
			if checkGroup(resource, rule) {
				for _, v := range rule.Verbs {
					verbs[v] = true
				}
			}
		}
	}

	return verbs, nil
}

// Ensure the clusterRole used to grant access of global resources to users/groups in projects has appropriate rulesfor the give resource and verbs
func (m *manager) reconcileRoleForProjectAccessToGlobalResource(resource string, rt *v3.RoleTemplate, newVerbs map[string]bool) (string, error) {
	clusterRoles := m.workload.RBAC.ClusterRoles("")
	roleName := rt.Name + "-promoted"
	if role, err := m.crLister.Get("", roleName); err == nil && role != nil {
		currentVerbs := map[string]bool{}
		for _, rule := range role.Rules {
			if slice.ContainsString(rule.Resources, resource) {
				for _, v := range rule.Verbs {
					currentVerbs[v] = true
				}
			}
		}

		if !reflect.DeepEqual(currentVerbs, newVerbs) {
			role = role.DeepCopy()
			added := false
			for i, rule := range role.Rules {
				if slice.ContainsString(rule.Resources, resource) {
					role.Rules[i] = buildRule(resource, newVerbs)
					added = true
				}
			}
			if !added {
				role.Rules = append(role.Rules, buildRule(resource, newVerbs))
			}
			logrus.Infof("Updating clusterRole %v for project access to global resource.", role.Name)
			_, err := clusterRoles.Update(role)
			return roleName, err
		}
		return roleName, nil
	}

	logrus.Infof("Creating clusterRole %v for project access to global resource.", roleName)
	rules := []rbacv1.PolicyRule{buildRule(resource, newVerbs)}
	_, err := clusterRoles.Create(&rbacv1.ClusterRole{
		ObjectMeta: metav1.ObjectMeta{
			Name: roleName,
		},
		Rules: rules,
	})
	if err != nil {
		return roleName, errors.Wrapf(err, "couldn't create role %v", roleName)
	}

	return roleName, nil
}

func checkGroup(resource string, rule rbacv1.PolicyRule) bool {
	if slice.ContainsString(rule.APIGroups, "*") {
		return true
	}

	groups, ok := globalResourcesNeededInProjects[resource]
	if !ok {
		return false
	}

	for _, rg := range rule.APIGroups {
		if _, ok := groups[rg]; ok {
			return true
		}
	}
	return false
}

func buildRule(resource string, verbs map[string]bool) rbacv1.PolicyRule {
	var vs []string
	for v := range verbs {
		vs = append(vs, v)
	}
	return rbacv1.PolicyRule{
		Resources: []string{resource},
		Verbs:     vs,
		APIGroups: []string{"*"},
	}
}
<commit_msg>Exist check<commit_after>package rbac

import (
	"reflect"

	"github.com/pkg/errors"
	"github.com/rancher/norman/types/convert"
	"github.com/rancher/norman/types/slice"
	v3 "github.com/rancher/types/apis/management.cattle.io/v3"
	"github.com/sirupsen/logrus"
	v1 "k8s.io/api/core/v1"
	rbacv1 "k8s.io/api/rbac/v1"
	apierrors "k8s.io/apimachinery/pkg/api/errors"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apimachinery/pkg/labels"
	"k8s.io/apimachinery/pkg/runtime"
)

const owner = "owner-user"

var globalResourcesNeededInProjects = map[string]map[string]bool{
	"persistentvolumes": {
		"":     true,
		"core": true,
	},
	"storageclasses": {
		"storage.k8s.io": true,
	},
	"apiservices": {
		"apiregistration.k8s.io": true,
	},
}

func newPRTBLifecycle(m *manager) *prtbLifecycle {
	return &prtbLifecycle{m: m}
}

type prtbLifecycle struct {
	m *manager
}

func (p *prtbLifecycle) Create(obj *v3.ProjectRoleTemplateBinding) (runtime.Object, error) {
	err := p.syncPRTB(obj)
	return obj, err
}

func (p *prtbLifecycle) Updated(obj *v3.ProjectRoleTemplateBinding) (runtime.Object, error) {
	err := p.syncPRTB(obj)
	return obj, err
}

func (p *prtbLifecycle) Remove(obj *v3.ProjectRoleTemplateBinding) (runtime.Object, error) {
	err := p.ensurePRTBDelete(obj)
	return obj, err
}

func (p *prtbLifecycle) syncPRTB(binding *v3.ProjectRoleTemplateBinding) error {
	if binding.RoleTemplateName == "" {
		logrus.Warnf("ProjectRoleTemplateBinding %v has no role template set. Skipping.", binding.Name)
		return nil
	}
	if binding.UserName == "" && binding.GroupPrincipalName == "" && binding.GroupName == "" && binding.ServiceAccount == "" {
		return nil
	}

	rt, err := p.m.rtLister.Get("", binding.RoleTemplateName)
	if err != nil {
		return errors.Wrapf(err, "couldn't get role template %v", binding.RoleTemplateName)
	}

	// Get namespaces belonging to project
	namespaces, err := p.m.nsIndexer.ByIndex(nsByProjectIndex, binding.ProjectName)
	if err != nil {
		return errors.Wrapf(err, "couldn't list namespaces with project ID %v", binding.ProjectName)
	}
	roles := map[string]*v3.RoleTemplate{}
	if err := p.m.gatherRoles(rt, roles); err != nil {
		return err
	}

	if err := p.m.ensureRoles(roles); err != nil {
		return errors.Wrap(err, "couldn't ensure roles")
	}

	for _, n := range namespaces {
		ns := n.(*v1.Namespace)
		if err := p.m.ensureProjectRoleBindings(ns.Name, roles, binding); err != nil {
			return errors.Wrapf(err, "couldn't ensure binding %v in %v", binding.Name, ns.Name)
		}
	}

	return p.reconcileProjectAccessToGlobalResources(binding, roles)
}

func (p *prtbLifecycle) ensurePRTBDelete(binding *v3.ProjectRoleTemplateBinding) error {
	// Get namespaces belonging to project
	namespaces, err := p.m.nsIndexer.ByIndex(nsByProjectIndex, binding.ProjectName)
	if err != nil {
		return errors.Wrapf(err, "couldn't list namespaces with project ID %v", binding.ProjectName)
	}

	set := labels.Set(map[string]string{rtbOwnerLabel: string(binding.UID)})
	for _, n := range namespaces {
		ns := n.(*v1.Namespace)
		bindingCli := p.m.workload.RBAC.RoleBindings(ns.Name)
		rbs, err := p.m.rbLister.List(ns.Name, set.AsSelector())
		if err != nil {
			return errors.Wrapf(err, "couldn't list rolebindings with selector %s", set.AsSelector())
		}

		for _, rb := range rbs {
			if err := bindingCli.Delete(rb.Name, &metav1.DeleteOptions{}); err != nil {
				if !apierrors.IsNotFound(err) {
					return errors.Wrapf(err, "error deleting rolebinding %v", rb.Name)
				}
			}
		}
	}

	return p.reconcileProjectAccessToGlobalResourcesForDelete(binding)
}

func (p *prtbLifecycle) reconcileProjectAccessToGlobalResources(binding *v3.ProjectRoleTemplateBinding, rts map[string]*v3.RoleTemplate) error {
	_, err := p.m.reconcileProjectAccessToGlobalResources(binding, rts)
	if err != nil {
		return err
	}
	return nil
}

func (p *prtbLifecycle) reconcileProjectAccessToGlobalResourcesForDelete(binding *v3.ProjectRoleTemplateBinding) error {
	bindingCli := p.m.workload.RBAC.ClusterRoleBindings("")
	rtbUID := string(binding.UID)
	set := labels.Set(map[string]string{rtbUID: owner})
	crbs, err := p.m.crbLister.List("", set.AsSelector())
	if err != nil {
		return err
	}

	for _, crb := range crbs {
		crb = crb.DeepCopy()
		for k, v := range crb.Labels {
			if k == rtbUID && v == owner {
				delete(crb.Labels, k)
			}
		}

		delete, err := p.m.noRemainingOwnerLabels(crb)
		if err != nil {
			return err
		}

		if delete {
			if err := bindingCli.Delete(crb.Name, &metav1.DeleteOptions{}); err != nil {
				if apierrors.IsNotFound(err) {
					continue
				}
				return err
			}
		} else {
			if _, err := bindingCli.Update(crb); err != nil {
				return err
			}
		}
	}

	return nil
}

func (m *manager) noRemainingOwnerLabels(crb *rbacv1.ClusterRoleBinding) (bool, error) {
	for k, v := range crb.Labels {
		if v == owner {
			if exists, err := m.ownerExists(k); exists || err != nil {
				return false, err
			}
		}

		if k == rtbOwnerLabel {
			if exists, err := m.ownerExists(v); exists || err != nil {
				return false, err
			}
		}
	}

	return true, nil
}

func (m *manager) ownerExists(uid interface{}) (bool, error) {
	prtbs, err := m.prtbIndexer.ByIndex(prtbByUIDIndex, convert.ToString(uid))
	return len(prtbs) > 0, err
}

// If the roleTemplate has rules granting access to non-namespaced (global) resource, return the verbs for those rules
func (m *manager) checkForGlobalResourceRules(role *v3.RoleTemplate, resource string) (map[string]bool, error) {
	var rules []rbacv1.PolicyRule
	if role.External {
		externalRole, err := m.crLister.Get("", role.Name)
		if err != nil && !apierrors.IsNotFound(err) {
			// dont error if it doesnt exist
			return nil, err
		}
		if externalRole != nil {
			rules = externalRole.Rules
		}
	} else {
		rules = role.Rules
	}

	verbs := map[string]bool{}
	for _, rule := range rules {
		if (slice.ContainsString(rule.Resources, resource) || slice.ContainsString(rule.Resources, "*")) && len(rule.ResourceNames) == 0 {
			if checkGroup(resource, rule) {
				for _, v := range rule.Verbs {
					verbs[v] = true
				}
			}
		}
	}

	return verbs, nil
}

// Ensure the clusterRole used to grant access of global resources to users/groups in projects has appropriate rulesfor the give resource and verbs
func (m *manager) reconcileRoleForProjectAccessToGlobalResource(resource string, rt *v3.RoleTemplate, newVerbs map[string]bool) (string, error) {
	clusterRoles := m.workload.RBAC.ClusterRoles("")
	roleName := rt.Name + "-promoted"
	if role, err := m.crLister.Get("", roleName); err == nil && role != nil {
		currentVerbs := map[string]bool{}
		for _, rule := range role.Rules {
			if slice.ContainsString(rule.Resources, resource) {
				for _, v := range rule.Verbs {
					currentVerbs[v] = true
				}
			}
		}

		if !reflect.DeepEqual(currentVerbs, newVerbs) {
			role = role.DeepCopy()
			added := false
			for i, rule := range role.Rules {
				if slice.ContainsString(rule.Resources, resource) {
					role.Rules[i] = buildRule(resource, newVerbs)
					added = true
				}
			}
			if !added {
				role.Rules = append(role.Rules, buildRule(resource, newVerbs))
			}
			logrus.Infof("Updating clusterRole %v for project access to global resource.", role.Name)
			_, err := clusterRoles.Update(role)
			return roleName, err
		}
		return roleName, nil
	}

	logrus.Infof("Creating clusterRole %v for project access to global resource.", roleName)
	rules := []rbacv1.PolicyRule{buildRule(resource, newVerbs)}
	_, err := clusterRoles.Create(&rbacv1.ClusterRole{
		ObjectMeta: metav1.ObjectMeta{
			Name: roleName,
		},
		Rules: rules,
	})
	if err != nil && !apierrors.IsAlreadyExists(err) {
		return roleName, errors.Wrapf(err, "couldn't create role %v", roleName)
	}

	return roleName, nil
}

func checkGroup(resource string, rule rbacv1.PolicyRule) bool {
	if slice.ContainsString(rule.APIGroups, "*") {
		return true
	}

	groups, ok := globalResourcesNeededInProjects[resource]
	if !ok {
		return false
	}

	for _, rg := range rule.APIGroups {
		if _, ok := groups[rg]; ok {
			return true
		}
	}
	return false
}

func buildRule(resource string, verbs map[string]bool) rbacv1.PolicyRule {
	var vs []string
	for v := range verbs {
		vs = append(vs, v)
	}
	return rbacv1.PolicyRule{
		Resources: []string{resource},
		Verbs:     vs,
		APIGroups: []string{"*"},
	}
}
<|endoftext|>


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

package transport

import (
	"gvisor.dev/gvisor/pkg/context"
	"gvisor.dev/gvisor/pkg/sync"
	"gvisor.dev/gvisor/pkg/syserr"
	"gvisor.dev/gvisor/pkg/tcpip"
	"gvisor.dev/gvisor/pkg/tcpip/buffer"
	"gvisor.dev/gvisor/pkg/waiter"
)

// queue is a buffer queue.
//
// +stateify savable
type queue struct {
	queueRefs

	ReaderQueue *waiter.Queue
	WriterQueue *waiter.Queue

	mu       sync.Mutex `state:"nosave"`
	closed   bool
	unread   bool
	used     int64
	limit    int64
	dataList messageList
}

// Close closes q for reading and writing. It is immediately not writable and
// will become unreadable when no more data is pending.
//
// Both the read and write queues must be notified after closing:
// q.ReaderQueue.Notify(waiter.ReadableEvents)
// q.WriterQueue.Notify(waiter.WritableEvents)
func (q *queue) Close() {
	q.mu.Lock()
	q.closed = true
	q.mu.Unlock()
}

// Reset empties the queue and Releases all of the Entries.
//
// Both the read and write queues must be notified after resetting:
// q.ReaderQueue.Notify(waiter.ReadableEvents)
// q.WriterQueue.Notify(waiter.WritableEvents)
func (q *queue) Reset(ctx context.Context) {
	q.mu.Lock()
	for cur := q.dataList.Front(); cur != nil; cur = cur.Next() {
		cur.Release(ctx)
	}
	q.dataList.Reset()
	q.used = 0
	q.mu.Unlock()
}

// DecRef implements RefCounter.DecRef.
func (q *queue) DecRef(ctx context.Context) {
	q.queueRefs.DecRef(func() {
		// We don't need to notify after resetting because no one cares about
		// this queue after all references have been dropped.
		q.Reset(ctx)
	})
}

// IsReadable determines if q is currently readable.
func (q *queue) IsReadable() bool {
	q.mu.Lock()
	defer q.mu.Unlock()

	return q.closed || q.dataList.Front() != nil
}

// bufWritable returns true if there is space for writing.
//
// N.B. Linux only considers a unix socket "writable" if >75% of the buffer is
// free.
//
// See net/unix/af_unix.c:unix_writeable.
func (q *queue) bufWritable() bool {
	return 4*q.used < q.limit
}

// IsWritable determines if q is currently writable.
func (q *queue) IsWritable() bool {
	q.mu.Lock()
	defer q.mu.Unlock()

	return q.closed || q.bufWritable()
}

// Enqueue adds an entry to the data queue if room is available.
//
// If discardEmpty is true and there are zero bytes of data, the packet is
// dropped.
//
// If truncate is true, Enqueue may truncate the message before enqueuing it.
// Otherwise, the entire message must fit. If l is less than the size of data,
// err indicates why.
//
// If notify is true, ReaderQueue.Notify must be called:
// q.ReaderQueue.Notify(waiter.ReadableEvents)
func (q *queue) Enqueue(ctx context.Context, data [][]byte, c ControlMessages, from tcpip.FullAddress, discardEmpty bool, truncate bool) (l int64, notify bool, err *syserr.Error) {
	q.mu.Lock()

	if q.closed {
		q.mu.Unlock()
		return 0, false, syserr.ErrClosedForSend
	}

	for _, d := range data {
		l += int64(len(d))
	}
	if discardEmpty && l == 0 {
		q.mu.Unlock()
		c.Release(ctx)
		return 0, false, nil
	}

	free := q.limit - q.used

	if l > free && truncate {
		if free <= 0 {
			// Message can't fit right now.
			q.mu.Unlock()
			return 0, false, syserr.ErrWouldBlock
		}

		l = free
		err = syserr.ErrWouldBlock
	}

	if l > q.limit {
		// Message is too big to ever fit.
		q.mu.Unlock()
		return 0, false, syserr.ErrMessageTooLong
	}

	if l > free {
		// Message can't fit right now, and could not be truncated.
		q.mu.Unlock()
		return 0, false, syserr.ErrWouldBlock
	}

	// Aggregate l bytes of data. This will truncate the data if l is less than
	// the total bytes held in data.
	v := make([]byte, l)
	for i, b := 0, v; i < len(data) && len(b) > 0; i++ {
		n := copy(b, data[i])
		b = b[n:]
	}

	notify = q.dataList.Front() == nil
	q.used += l
	q.dataList.PushBack(&message{
		Data:    buffer.View(v),
		Control: c,
		Address: from,
	})

	q.mu.Unlock()

	return l, notify, err
}

// Dequeue removes the first entry in the data queue, if one exists.
//
// If notify is true, WriterQueue.Notify must be called:
// q.WriterQueue.Notify(waiter.WritableEvents)
func (q *queue) Dequeue() (e *message, notify bool, err *syserr.Error) {
	q.mu.Lock()

	if q.dataList.Front() == nil {
		err := syserr.ErrWouldBlock
		if q.closed {
			err = syserr.ErrClosedForReceive
			if q.unread {
				err = syserr.ErrConnectionReset
			}
		}
		q.mu.Unlock()

		return nil, false, err
	}

	notify = !q.bufWritable()

	e = q.dataList.Front()
	q.dataList.Remove(e)
	q.used -= e.Length()

	notify = notify && q.bufWritable()

	q.mu.Unlock()

	return e, notify, nil
}

// Peek returns the first entry in the data queue, if one exists.
func (q *queue) Peek() (*message, *syserr.Error) {
	q.mu.Lock()
	defer q.mu.Unlock()

	if q.dataList.Front() == nil {
		err := syserr.ErrWouldBlock
		if q.closed {
			if err = syserr.ErrClosedForReceive; q.unread {
				err = syserr.ErrConnectionReset
			}
		}
		return nil, err
	}

	return q.dataList.Front().Peek(), nil
}

// QueuedSize returns the number of bytes currently in the queue, that is, the
// number of readable bytes.
func (q *queue) QueuedSize() int64 {
	q.mu.Lock()
	defer q.mu.Unlock()
	return q.used
}

// MaxQueueSize returns the maximum number of bytes storable in the queue.
func (q *queue) MaxQueueSize() int64 {
	q.mu.Lock()
	defer q.mu.Unlock()
	return q.limit
}

// SetMaxQueueSize sets the maximum number of bytes storable in the queue.
func (q *queue) SetMaxQueueSize(v int64) {
	q.mu.Lock()
	defer q.mu.Unlock()
	q.limit = v
}

// CloseUnread sets flag to indicate that the peer is closed (not shutdown)
// with unread data. So if read on this queue shall return ECONNRESET error.
func (q *queue) CloseUnread() {
	q.mu.Lock()
	defer q.mu.Unlock()
	q.unread = true
}
<commit_msg>socket/unix: clean up socket queue after releasing a queue lock<commit_after>// Copyright 2018 The gVisor Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package transport

import (
	"gvisor.dev/gvisor/pkg/context"
	"gvisor.dev/gvisor/pkg/sync"
	"gvisor.dev/gvisor/pkg/syserr"
	"gvisor.dev/gvisor/pkg/tcpip"
	"gvisor.dev/gvisor/pkg/tcpip/buffer"
	"gvisor.dev/gvisor/pkg/waiter"
)

// queue is a buffer queue.
//
// +stateify savable
type queue struct {
	queueRefs

	ReaderQueue *waiter.Queue
	WriterQueue *waiter.Queue

	mu       sync.Mutex `state:"nosave"`
	closed   bool
	unread   bool
	used     int64
	limit    int64
	dataList messageList
}

// Close closes q for reading and writing. It is immediately not writable and
// will become unreadable when no more data is pending.
//
// Both the read and write queues must be notified after closing:
// q.ReaderQueue.Notify(waiter.ReadableEvents)
// q.WriterQueue.Notify(waiter.WritableEvents)
func (q *queue) Close() {
	q.mu.Lock()
	q.closed = true
	q.mu.Unlock()
}

// Reset empties the queue and Releases all of the Entries.
//
// Both the read and write queues must be notified after resetting:
// q.ReaderQueue.Notify(waiter.ReadableEvents)
// q.WriterQueue.Notify(waiter.WritableEvents)
func (q *queue) Reset(ctx context.Context) {
	q.mu.Lock()
	dataList := q.dataList
	q.dataList.Reset()
	q.used = 0
	q.mu.Unlock()

	for cur := dataList.Front(); cur != nil; cur = cur.Next() {
		cur.Release(ctx)
	}
}

// DecRef implements RefCounter.DecRef.
func (q *queue) DecRef(ctx context.Context) {
	q.queueRefs.DecRef(func() {
		// We don't need to notify after resetting because no one cares about
		// this queue after all references have been dropped.
		q.Reset(ctx)
	})
}

// IsReadable determines if q is currently readable.
func (q *queue) IsReadable() bool {
	q.mu.Lock()
	defer q.mu.Unlock()

	return q.closed || q.dataList.Front() != nil
}

// bufWritable returns true if there is space for writing.
//
// N.B. Linux only considers a unix socket "writable" if >75% of the buffer is
// free.
//
// See net/unix/af_unix.c:unix_writeable.
func (q *queue) bufWritable() bool {
	return 4*q.used < q.limit
}

// IsWritable determines if q is currently writable.
func (q *queue) IsWritable() bool {
	q.mu.Lock()
	defer q.mu.Unlock()

	return q.closed || q.bufWritable()
}

// Enqueue adds an entry to the data queue if room is available.
//
// If discardEmpty is true and there are zero bytes of data, the packet is
// dropped.
//
// If truncate is true, Enqueue may truncate the message before enqueuing it.
// Otherwise, the entire message must fit. If l is less than the size of data,
// err indicates why.
//
// If notify is true, ReaderQueue.Notify must be called:
// q.ReaderQueue.Notify(waiter.ReadableEvents)
func (q *queue) Enqueue(ctx context.Context, data [][]byte, c ControlMessages, from tcpip.FullAddress, discardEmpty bool, truncate bool) (l int64, notify bool, err *syserr.Error) {
	q.mu.Lock()

	if q.closed {
		q.mu.Unlock()
		return 0, false, syserr.ErrClosedForSend
	}

	for _, d := range data {
		l += int64(len(d))
	}
	if discardEmpty && l == 0 {
		q.mu.Unlock()
		c.Release(ctx)
		return 0, false, nil
	}

	free := q.limit - q.used

	if l > free && truncate {
		if free <= 0 {
			// Message can't fit right now.
			q.mu.Unlock()
			return 0, false, syserr.ErrWouldBlock
		}

		l = free
		err = syserr.ErrWouldBlock
	}

	if l > q.limit {
		// Message is too big to ever fit.
		q.mu.Unlock()
		return 0, false, syserr.ErrMessageTooLong
	}

	if l > free {
		// Message can't fit right now, and could not be truncated.
		q.mu.Unlock()
		return 0, false, syserr.ErrWouldBlock
	}

	// Aggregate l bytes of data. This will truncate the data if l is less than
	// the total bytes held in data.
	v := make([]byte, l)
	for i, b := 0, v; i < len(data) && len(b) > 0; i++ {
		n := copy(b, data[i])
		b = b[n:]
	}

	notify = q.dataList.Front() == nil
	q.used += l
	q.dataList.PushBack(&message{
		Data:    buffer.View(v),
		Control: c,
		Address: from,
	})

	q.mu.Unlock()

	return l, notify, err
}

// Dequeue removes the first entry in the data queue, if one exists.
//
// If notify is true, WriterQueue.Notify must be called:
// q.WriterQueue.Notify(waiter.WritableEvents)
func (q *queue) Dequeue() (e *message, notify bool, err *syserr.Error) {
	q.mu.Lock()

	if q.dataList.Front() == nil {
		err := syserr.ErrWouldBlock
		if q.closed {
			err = syserr.ErrClosedForReceive
			if q.unread {
				err = syserr.ErrConnectionReset
			}
		}
		q.mu.Unlock()

		return nil, false, err
	}

	notify = !q.bufWritable()

	e = q.dataList.Front()
	q.dataList.Remove(e)
	q.used -= e.Length()

	notify = notify && q.bufWritable()

	q.mu.Unlock()

	return e, notify, nil
}

// Peek returns the first entry in the data queue, if one exists.
func (q *queue) Peek() (*message, *syserr.Error) {
	q.mu.Lock()
	defer q.mu.Unlock()

	if q.dataList.Front() == nil {
		err := syserr.ErrWouldBlock
		if q.closed {
			if err = syserr.ErrClosedForReceive; q.unread {
				err = syserr.ErrConnectionReset
			}
		}
		return nil, err
	}

	return q.dataList.Front().Peek(), nil
}

// QueuedSize returns the number of bytes currently in the queue, that is, the
// number of readable bytes.
func (q *queue) QueuedSize() int64 {
	q.mu.Lock()
	defer q.mu.Unlock()
	return q.used
}

// MaxQueueSize returns the maximum number of bytes storable in the queue.
func (q *queue) MaxQueueSize() int64 {
	q.mu.Lock()
	defer q.mu.Unlock()
	return q.limit
}

// SetMaxQueueSize sets the maximum number of bytes storable in the queue.
func (q *queue) SetMaxQueueSize(v int64) {
	q.mu.Lock()
	defer q.mu.Unlock()
	q.limit = v
}

// CloseUnread sets flag to indicate that the peer is closed (not shutdown)
// with unread data. So if read on this queue shall return ECONNRESET error.
func (q *queue) CloseUnread() {
	q.mu.Lock()
	defer q.mu.Unlock()
	q.unread = true
}
<|endoftext|>


<commit_before>// This file provides orchestrator provider's registry related features.
//
// NOTE:
//    This is the new file w.r.t the deprecated plugins.go file
package orchprovider

import (
	"fmt"
	"sync"

	"github.com/golang/glog"
	"github.com/openebs/maya/types/v1"
)

type OrchProviderFactory func(label v1.NameLabel, name v1.OrchProviderRegistry) (OrchestratorInterface, error)

// Registration is managed in a safe manner via these variables
var (
	orchProviderRegMutex sync.Mutex
	orchProviderRegistry = make(map[v1.OrchProviderRegistry]OrchProviderFactory)
)

// HasOrchestrator returns true if name corresponds to an already
// registered orchestration provider.
func HasOrchestrator(name v1.OrchProviderRegistry) bool {
	orchProviderRegMutex.Lock()
	defer orchProviderRegMutex.Unlock()

	_, found := orchProviderRegistry[name]
	return found
}

// RegisterOrchestrator registers a orchestration provider by the provider's name.
// This registers the orchestrator provider name with the provider's instance
// creating function i.e. a Factory.
//
// NOTE:
//    Each implementation of orchestrator plugin need to call
// RegisterOrchestrator inside their init() function.
func RegisterOrchestrator(name v1.OrchProviderRegistry, oInstFactory OrchProviderFactory) {
	orchProviderRegMutex.Lock()
	defer orchProviderRegMutex.Unlock()

	_, found := orchProviderRegistry[name]
	if found {
		glog.Fatalf("Duplicate orchestration provider '%s' registration", name)
	}

	//glog.V(1).Infof("Registered '%s' as orchestration provider", name)
	glog.Infof("Registered '%s' as orchestration provider", name)
	orchProviderRegistry[name] = oInstFactory
}

// GetOrchestrator creates a new instance of the named orchestration provider,
// or nil if the name is unknown.
func GetOrchestrator(name v1.OrchProviderRegistry) (OrchestratorInterface, error) {
	orchProviderRegMutex.Lock()
	defer orchProviderRegMutex.Unlock()

	oInstFactory, found := orchProviderRegistry[name]
	if !found {
		return nil, fmt.Errorf("'%s' is not a registered orchestration provider", name)
	}

	// Orchestration provider's instance creating function is invoked here
	// The orchestration provider label is decided here. The label is common to all
	// orchestration provider implementors.
	return oInstFactory(v1.OrchestratorNameLbl, name)
}
<commit_msg>Fixed golint issues in maya/orchprovider/registry.go (#693)<commit_after>// This file provides orchestrator provider's registry related features.
//
// NOTE:
//    This is the new file w.r.t the deprecated plugins.go file

package orchprovider

import (
	"fmt"
	"sync"

	"github.com/golang/glog"
	"github.com/openebs/maya/types/v1"
)

// OrchProviderFactory is the factory implementation of OrchProvider
type OrchProviderFactory func(label v1.NameLabel, name v1.OrchProviderRegistry) (OrchestratorInterface, error)

// Registration is managed in a safe manner via these variables
var (
	orchProviderRegMutex sync.Mutex
	orchProviderRegistry = make(map[v1.OrchProviderRegistry]OrchProviderFactory)
)

// HasOrchestrator returns true if name corresponds to an already
// registered orchestration provider.
func HasOrchestrator(name v1.OrchProviderRegistry) bool {
	orchProviderRegMutex.Lock()
	defer orchProviderRegMutex.Unlock()

	_, found := orchProviderRegistry[name]
	return found
}

// RegisterOrchestrator registers a orchestration provider by the provider's name.
// This registers the orchestrator provider name with the provider's instance
// creating function i.e. a Factory.
//
// NOTE:
//    Each implementation of orchestrator plugin need to call
// RegisterOrchestrator inside their init() function.
func RegisterOrchestrator(name v1.OrchProviderRegistry, oInstFactory OrchProviderFactory) {
	orchProviderRegMutex.Lock()
	defer orchProviderRegMutex.Unlock()

	_, found := orchProviderRegistry[name]
	if found {
		glog.Fatalf("Duplicate orchestration provider '%s' registration", name)
	}

	//glog.V(1).Infof("Registered '%s' as orchestration provider", name)
	glog.Infof("Registered '%s' as orchestration provider", name)
	orchProviderRegistry[name] = oInstFactory
}

// GetOrchestrator creates a new instance of the named orchestration provider,
// or nil if the name is unknown.
func GetOrchestrator(name v1.OrchProviderRegistry) (OrchestratorInterface, error) {
	orchProviderRegMutex.Lock()
	defer orchProviderRegMutex.Unlock()

	oInstFactory, found := orchProviderRegistry[name]
	if !found {
		return nil, fmt.Errorf("'%s' is not a registered orchestration provider", name)
	}

	// Orchestration provider's instance creating function is invoked here
	// The orchestration provider label is decided here. The label is common to all
	// orchestration provider implementors.
	return oInstFactory(v1.OrchestratorNameLbl, name)
}
<|endoftext|>


<commit_before>package main

import (
	"sort"
)

type Model struct {
	weight    map[string]float64
	cumWeight map[string]float64
	count     int
}

func NewModel() *Model {
	return &Model{make(map[string]float64), make(map[string]float64), 1}
}

func GetAccuracy(gold []LabelType, predict []LabelType) float64 {
	if len(gold) != len(predict) {
		return 0.0
	}
	sum := 0.0
	for i, v := range gold {
		if v == predict[i] {
			sum += 1.0
		}
	}
	return sum / float64(len(gold))
}

func (model *Model) Learn(example Example) {
	predict := model.predictForTraining(example.Fv)
	if example.Label != predict {
		for _, f := range example.Fv {
			w, _ := model.weight[f]
			cumW, _ := model.cumWeight[f]
			model.weight[f] = w + float64(example.Label)*1.0
			model.cumWeight[f] = cumW + float64(model.count)*float64(example.Label)*1.0
		}
		model.count += 1
	}
}

func (model *Model) predictForTraining(features FeatureVector) LabelType {
	result := 0.0
	for _, f := range features {
		w, ok := model.weight[f]
		if ok {
			result = result + w*1.0
		}
	}
	if result > 0 {
		return POSITIVE
	}
	return NEGATIVE
}

func (model Model) PredictScore(features FeatureVector) float64 {
	result := 0.0
	for _, f := range features {
		w, ok := model.weight[f]
		if ok {
			result = result + w*1.0
		}

		w, ok = model.cumWeight[f]
		if ok {
			result = result - w*1.0/float64(model.count)
		}

	}
	return result
}

func (model Model) Predict(features FeatureVector) LabelType {
	if model.PredictScore(features) > 0 {
		return POSITIVE
	}
	return NEGATIVE
}

func ExtractGoldLabels(examples Examples) []LabelType {
	golds := make([]LabelType, 0, 0)
	for _, e := range examples {
		golds = append(golds, e.Label)
	}
	return golds
}

func (model Model) SortByScore(examples Examples) Examples {
	var unlabeledExamples Examples
	for _, e := range examples {
		e.Score = model.PredictScore(e.Fv)
		if !e.IsLabeled() && e.Score != 0.0 {
			unlabeledExamples = append(unlabeledExamples, e)
		}
	}

	sort.Sort(unlabeledExamples)
	return unlabeledExamples
}

func TrainedModel(examples Examples) *Model {
	train := FilterLabeledExamples(examples)
	shuffle(train)
	model := NewModel()
	for iter := 0; iter < 10; iter++ {
		for _, example := range train {
			model.Learn(*example)
		}

		trainPredicts := make([]LabelType, len(train))
		for i, example := range train {
			trainPredicts[i] = model.Predict(example.Fv)
		}
		// fmt.Println(fmt.Sprintf("Iter:%d\tAccuracy:%0.03f", iter, GetAccuracy(ExtractGoldLabels(train), trainPredicts)))
	}
	return model
}
<commit_msg>同一URLですでにラベルが付いているものがあったらスキップ<commit_after>package main

import (
	"sort"
)

type Model struct {
	weight    map[string]float64
	cumWeight map[string]float64
	count     int
}

func NewModel() *Model {
	return &Model{make(map[string]float64), make(map[string]float64), 1}
}

func GetAccuracy(gold []LabelType, predict []LabelType) float64 {
	if len(gold) != len(predict) {
		return 0.0
	}
	sum := 0.0
	for i, v := range gold {
		if v == predict[i] {
			sum += 1.0
		}
	}
	return sum / float64(len(gold))
}

func (model *Model) Learn(example Example) {
	predict := model.predictForTraining(example.Fv)
	if example.Label != predict {
		for _, f := range example.Fv {
			w, _ := model.weight[f]
			cumW, _ := model.cumWeight[f]
			model.weight[f] = w + float64(example.Label)*1.0
			model.cumWeight[f] = cumW + float64(model.count)*float64(example.Label)*1.0
		}
		model.count += 1
	}
}

func (model *Model) predictForTraining(features FeatureVector) LabelType {
	result := 0.0
	for _, f := range features {
		w, ok := model.weight[f]
		if ok {
			result = result + w*1.0
		}
	}
	if result > 0 {
		return POSITIVE
	}
	return NEGATIVE
}

func (model Model) PredictScore(features FeatureVector) float64 {
	result := 0.0
	for _, f := range features {
		w, ok := model.weight[f]
		if ok {
			result = result + w*1.0
		}

		w, ok = model.cumWeight[f]
		if ok {
			result = result - w*1.0/float64(model.count)
		}

	}
	return result
}

func (model Model) Predict(features FeatureVector) LabelType {
	if model.PredictScore(features) > 0 {
		return POSITIVE
	}
	return NEGATIVE
}

func ExtractGoldLabels(examples Examples) []LabelType {
	golds := make([]LabelType, 0, 0)
	for _, e := range examples {
		golds = append(golds, e.Label)
	}
	return golds
}

func (model Model) SortByScore(examples Examples) Examples {
	alreadyLabeled := make(map[string]bool)

	for _, e := range FilterLabeledExamples(examples) {
		alreadyLabeled[e.Url] = true
	}

	var unlabeledExamples Examples
	for _, e := range examples {
		e.Score = model.PredictScore(e.Fv)
		if _, ok := alreadyLabeled[e.Url]; ok {
			continue
		}

		if !e.IsLabeled() && e.Score != 0.0 {
			unlabeledExamples = append(unlabeledExamples, e)
		}
	}

	sort.Sort(unlabeledExamples)
	return unlabeledExamples
}

func TrainedModel(examples Examples) *Model {
	train := FilterLabeledExamples(examples)
	shuffle(train)
	model := NewModel()
	for iter := 0; iter < 10; iter++ {
		for _, example := range train {
			model.Learn(*example)
		}

		trainPredicts := make([]LabelType, len(train))
		for i, example := range train {
			trainPredicts[i] = model.Predict(example.Fv)
		}
		// fmt.Println(fmt.Sprintf("Iter:%d\tAccuracy:%0.03f", iter, GetAccuracy(ExtractGoldLabels(train), trainPredicts)))
	}
	return model
}
<|endoftext|>


<commit_before>package gorm

import (
	"fmt"
	"reflect"
)

func Query(scope *Scope) {
	defer scope.Trace(NowFunc())

	var (
		isSlice        bool
		isPtr          bool
		anyRecordFound bool
		destType       reflect.Type
	)

	var dest = scope.IndirectValue()
	if value, ok := scope.InstanceGet("gorm:query_destination"); ok {
		dest = reflect.Indirect(reflect.ValueOf(value))
	}

	if orderBy, ok := scope.InstanceGet("gorm:order_by_primary_key"); ok {
		if primaryKey := scope.PrimaryKey(); primaryKey != "" {
			scope.Search = scope.Search.clone().order(fmt.Sprintf("%v.%v %v", scope.QuotedTableName(), primaryKey, orderBy))
		}
	}

	if dest.Kind() == reflect.Slice {
		isSlice = true
		destType = dest.Type().Elem()
		if destType.Kind() == reflect.Ptr {
			isPtr = true
			destType = destType.Elem()
		}
	}

	scope.prepareQuerySql()

	if !scope.HasError() {
		rows, err := scope.SqlDB().Query(scope.Sql, scope.SqlVars...)
		scope.db.RowsAffected = 0

		if scope.Err(err) != nil {
			return
		}
		defer rows.Close()

		columns, _ := rows.Columns()
		for rows.Next() {
			scope.db.RowsAffected++

			anyRecordFound = true
			elem := dest
			if isSlice {
				elem = reflect.New(destType).Elem()
			}

			var values = make([]interface{}, len(columns))

			fields := scope.New(elem.Addr().Interface()).Fields()
			for index, column := range columns {
				if field, ok := fields[column]; ok {
					if field.Field.Kind() == reflect.Ptr {
						values[index] = field.Field.Addr().Interface()
					} else {
						values[index] = reflect.New(reflect.PtrTo(field.Field.Type())).Interface()
					}
				} else {
					var value interface{}
					values[index] = &value
				}
			}

			scope.Err(rows.Scan(values...))

			for index, column := range columns {
				value := values[index]
				if field, ok := fields[column]; ok {
					if field.Field.Kind() == reflect.Ptr {
						field.Field.Set(reflect.ValueOf(value).Elem())
					} else if v := reflect.ValueOf(value).Elem().Elem(); v.IsValid() {
						field.Field.Set(v)
					}
				}
			}

			if isSlice {
				if isPtr {
					dest.Set(reflect.Append(dest, elem.Addr()))
				} else {
					dest.Set(reflect.Append(dest, elem))
				}
			}
		}

		if !anyRecordFound && !isSlice {
			scope.Err(RecordNotFound)
		}
	}
}

func AfterQuery(scope *Scope) {
	scope.CallMethodWithErrorCheck("AfterFind")
}

func init() {
	DefaultCallback.Query().Register("gorm:query", Query)
	DefaultCallback.Query().Register("gorm:after_query", AfterQuery)
	DefaultCallback.Query().Register("gorm:preload", Preload)
}
<commit_msg>Add error if query destination is not supported<commit_after>package gorm

import (
	"errors"
	"fmt"
	"reflect"
)

func Query(scope *Scope) {
	defer scope.Trace(NowFunc())

	var (
		isSlice        bool
		isPtr          bool
		anyRecordFound bool
		destType       reflect.Type
	)

	var dest = scope.IndirectValue()
	if value, ok := scope.InstanceGet("gorm:query_destination"); ok {
		dest = reflect.Indirect(reflect.ValueOf(value))
	}

	if orderBy, ok := scope.InstanceGet("gorm:order_by_primary_key"); ok {
		if primaryKey := scope.PrimaryKey(); primaryKey != "" {
			scope.Search = scope.Search.clone().order(fmt.Sprintf("%v.%v %v", scope.QuotedTableName(), primaryKey, orderBy))
		}
	}

	if kind := dest.Kind(); kind == reflect.Slice {
		isSlice = true
		destType = dest.Type().Elem()
		if destType.Kind() == reflect.Ptr {
			isPtr = true
			destType = destType.Elem()
		}
	} else if kind != reflect.Struct {
		scope.Err(errors.New("unsupported destination, should be slice or struct"))
		return
	}

	scope.prepareQuerySql()

	if !scope.HasError() {
		rows, err := scope.SqlDB().Query(scope.Sql, scope.SqlVars...)
		scope.db.RowsAffected = 0

		if scope.Err(err) != nil {
			return
		}
		defer rows.Close()

		columns, _ := rows.Columns()
		for rows.Next() {
			scope.db.RowsAffected++

			anyRecordFound = true
			elem := dest
			if isSlice {
				elem = reflect.New(destType).Elem()
			}

			var values = make([]interface{}, len(columns))

			fields := scope.New(elem.Addr().Interface()).Fields()

			for index, column := range columns {
				if field, ok := fields[column]; ok {
					if field.Field.Kind() == reflect.Ptr {
						values[index] = field.Field.Addr().Interface()
					} else {
						values[index] = reflect.New(reflect.PtrTo(field.Field.Type())).Interface()
					}
				} else {
					var value interface{}
					values[index] = &value
				}
			}

			scope.Err(rows.Scan(values...))

			for index, column := range columns {
				value := values[index]
				if field, ok := fields[column]; ok {
					if field.Field.Kind() == reflect.Ptr {
						field.Field.Set(reflect.ValueOf(value).Elem())
					} else if v := reflect.ValueOf(value).Elem().Elem(); v.IsValid() {
						field.Field.Set(v)
					}
				}
			}

			if isSlice {
				if isPtr {
					dest.Set(reflect.Append(dest, elem.Addr()))
				} else {
					dest.Set(reflect.Append(dest, elem))
				}
			}
		}

		if !anyRecordFound && !isSlice {
			scope.Err(RecordNotFound)
		}
	}
}

func AfterQuery(scope *Scope) {
	scope.CallMethodWithErrorCheck("AfterFind")
}

func init() {
	DefaultCallback.Query().Register("gorm:query", Query)
	DefaultCallback.Query().Register("gorm:after_query", AfterQuery)
	DefaultCallback.Query().Register("gorm:preload", Preload)
}
<|endoftext|>


<commit_before>package pex

import (
	"time"

	"github.com/tendermint/tendermint/p2p"
)

// knownAddress tracks information about a known network address
// that is used to determine how viable an address is.
type knownAddress struct {
	Addr        *p2p.NetAddress `json:"addr"`
	Src         *p2p.NetAddress `json:"src"`
	Buckets     []int           `json:"buckets"`
	Attempts    int32           `json:"attempts"`
	BucketType  byte            `json:"bucket_type"`
	LastAttempt time.Time       `json:"last_attempt"`
	LastSuccess time.Time       `json:"last_success"`
	LastBanTime time.Time       `json:"last_ban_time"`
}

func newKnownAddress(addr *p2p.NetAddress, src *p2p.NetAddress) *knownAddress {
	return &knownAddress{
		Addr:        addr,
		Src:         src,
		Attempts:    0,
		LastAttempt: time.Now(),
		BucketType:  bucketTypeNew,
		Buckets:     nil,
	}
}

func (ka *knownAddress) ID() p2p.ID {
	return ka.Addr.ID
}

func (ka *knownAddress) isOld() bool {
	return ka.BucketType == bucketTypeOld
}

func (ka *knownAddress) isNew() bool {
	return ka.BucketType == bucketTypeNew
}

func (ka *knownAddress) markAttempt() {
	now := time.Now()
	ka.LastAttempt = now
	ka.Attempts++
}

func (ka *knownAddress) markGood() {
	now := time.Now()
	ka.LastAttempt = now
	ka.Attempts = 0
	ka.LastSuccess = now
}

func (ka *knownAddress) ban() {
	ka.LastBanTime = time.Now()
}

func (ka *knownAddress) isBanned(banTime time.Duration) bool {
	if ka.LastBanTime.Add(banTime).Before(time.Now()) {
		return false
	}
	return true
}

func (ka *knownAddress) addBucketRef(bucketIdx int) int {
	for _, bucket := range ka.Buckets {
		if bucket == bucketIdx {
			// TODO refactor to return error?
			// log.Warn(Fmt("Bucket already exists in ka.Buckets: %v", ka))
			return -1
		}
	}
	ka.Buckets = append(ka.Buckets, bucketIdx)
	return len(ka.Buckets)
}

func (ka *knownAddress) removeBucketRef(bucketIdx int) int {
	buckets := []int{}
	for _, bucket := range ka.Buckets {
		if bucket != bucketIdx {
			buckets = append(buckets, bucket)
		}
	}
	if len(buckets) != len(ka.Buckets)-1 {
		// TODO refactor to return error?
		// log.Warn(Fmt("bucketIdx not found in ka.Buckets: %v", ka))
		return -1
	}
	ka.Buckets = buckets
	return len(ka.Buckets)
}

/*
   An address is bad if the address in question is a New address, has not been tried in the last
   minute, and meets one of the following criteria:

   1) It claims to be from the future
   2) It hasn't been seen in over a week
   3) It has failed at least three times and never succeeded
   4) It has failed ten times in the last week

   All addresses that meet these criteria are assumed to be worthless and not
   worth keeping hold of.

*/
func (ka *knownAddress) isBad() bool {
	// Is Old --> good
	if ka.BucketType == bucketTypeOld {
		return false
	}

	// Has been attempted in the last minute --> good
	if ka.LastAttempt.After(time.Now().Add(-1 * time.Minute)) {
		return false
	}

	// TODO: From the future?

	// Too old?
	// TODO: should be a timestamp of last seen, not just last attempt
	if ka.LastAttempt.Before(time.Now().Add(-1 * numMissingDays * time.Hour * 24)) {
		return true
	}

	// Never succeeded?
	if ka.LastSuccess.IsZero() && ka.Attempts >= numRetries {
		return true
	}

	// Hasn't succeeded in too long?
	if ka.LastSuccess.Before(time.Now().Add(-1*minBadDays*time.Hour*24)) &&
		ka.Attempts >= maxFailures {
		return true
	}

	return false
}
<commit_msg>lint fix<commit_after>package pex

import (
	"time"

	"github.com/tendermint/tendermint/p2p"
)

// knownAddress tracks information about a known network address
// that is used to determine how viable an address is.
type knownAddress struct {
	Addr        *p2p.NetAddress `json:"addr"`
	Src         *p2p.NetAddress `json:"src"`
	Buckets     []int           `json:"buckets"`
	Attempts    int32           `json:"attempts"`
	BucketType  byte            `json:"bucket_type"`
	LastAttempt time.Time       `json:"last_attempt"`
	LastSuccess time.Time       `json:"last_success"`
	LastBanTime time.Time       `json:"last_ban_time"`
}

func newKnownAddress(addr *p2p.NetAddress, src *p2p.NetAddress) *knownAddress {
	return &knownAddress{
		Addr:        addr,
		Src:         src,
		Attempts:    0,
		LastAttempt: time.Now(),
		BucketType:  bucketTypeNew,
		Buckets:     nil,
	}
}

func (ka *knownAddress) ID() p2p.ID {
	return ka.Addr.ID
}

func (ka *knownAddress) isOld() bool {
	return ka.BucketType == bucketTypeOld
}

func (ka *knownAddress) isNew() bool {
	return ka.BucketType == bucketTypeNew
}

func (ka *knownAddress) markAttempt() {
	now := time.Now()
	ka.LastAttempt = now
	ka.Attempts++
}

func (ka *knownAddress) markGood() {
	now := time.Now()
	ka.LastAttempt = now
	ka.Attempts = 0
	ka.LastSuccess = now
}

func (ka *knownAddress) ban() {
	ka.LastBanTime = time.Now()
}

func (ka *knownAddress) isBanned(banTime time.Duration) bool {
	return ka.LastBanTime.Add(banTime).Before(time.Now())
}

func (ka *knownAddress) addBucketRef(bucketIdx int) int {
	for _, bucket := range ka.Buckets {
		if bucket == bucketIdx {
			// TODO refactor to return error?
			// log.Warn(Fmt("Bucket already exists in ka.Buckets: %v", ka))
			return -1
		}
	}
	ka.Buckets = append(ka.Buckets, bucketIdx)
	return len(ka.Buckets)
}

func (ka *knownAddress) removeBucketRef(bucketIdx int) int {
	buckets := []int{}
	for _, bucket := range ka.Buckets {
		if bucket != bucketIdx {
			buckets = append(buckets, bucket)
		}
	}
	if len(buckets) != len(ka.Buckets)-1 {
		// TODO refactor to return error?
		// log.Warn(Fmt("bucketIdx not found in ka.Buckets: %v", ka))
		return -1
	}
	ka.Buckets = buckets
	return len(ka.Buckets)
}

/*
   An address is bad if the address in question is a New address, has not been tried in the last
   minute, and meets one of the following criteria:

   1) It claims to be from the future
   2) It hasn't been seen in over a week
   3) It has failed at least three times and never succeeded
   4) It has failed ten times in the last week

   All addresses that meet these criteria are assumed to be worthless and not
   worth keeping hold of.

*/
func (ka *knownAddress) isBad() bool {
	// Is Old --> good
	if ka.BucketType == bucketTypeOld {
		return false
	}

	// Has been attempted in the last minute --> good
	if ka.LastAttempt.After(time.Now().Add(-1 * time.Minute)) {
		return false
	}

	// TODO: From the future?

	// Too old?
	// TODO: should be a timestamp of last seen, not just last attempt
	if ka.LastAttempt.Before(time.Now().Add(-1 * numMissingDays * time.Hour * 24)) {
		return true
	}

	// Never succeeded?
	if ka.LastSuccess.IsZero() && ka.Attempts >= numRetries {
		return true
	}

	// Hasn't succeeded in too long?
	if ka.LastSuccess.Before(time.Now().Add(-1*minBadDays*time.Hour*24)) &&
		ka.Attempts >= maxFailures {
		return true
	}

	return false
}
<|endoftext|>