<commit_before>package conn

import (
	"net"
	"net/rpc"

	"github.com/dgraph-io/dgraph/x"
)

var glog = x.Log("conn")

type Pool struct {
	clients chan *rpc.Client
	addr    string
}

func NewPool(addr string, maxCap int) *Pool {
	p := new(Pool)
	p.addr = addr
	p.clients = make(chan *rpc.Client, maxCap)
	client, err := p.dialNew()
	if err != nil {
		glog.Fatal(err)
		return nil
	}
	p.clients <- client
	return p
}

func (p *Pool) dialNew() (*rpc.Client, error) {
	nconn, err := net.Dial("tcp", p.addr)
	if err != nil {
		return nil, err
	}
	cc := &ClientCodec{
		Rwc: nconn,
	}
	return rpc.NewClientWithCodec(cc), nil
}

func (p *Pool) Call(serviceMethod string, args interface{},
	reply interface{}) error {

	client, err := p.get()
	if err != nil {
		return err
	}
	if err = client.Call(serviceMethod, args, reply); err != nil {
		return err
	}

	select {
	case p.clients <- client:
		return nil
	default:
		return client.Close()
	}
}

func (p *Pool) get() (*rpc.Client, error) {
	select {
	case client := <-p.clients:
		return client, nil
	default:
		return p.dialNew()
	}
}

func (p *Pool) Close() error {
	// We're not doing a clean exit here. A clean exit here would require
	// synchronization, which seems unnecessary for now. But, we should
	// add one if required later.
	return nil
}
<commit_msg>Retry on connection refused<commit_after>package conn

import (
	"net"
	"net/rpc"
	"strings"
	"time"

	"github.com/dgraph-io/dgraph/x"
)

var glog = x.Log("conn")

type Pool struct {
	clients chan *rpc.Client
	addr    string
}

func NewPool(addr string, maxCap int) *Pool {
	p := new(Pool)
	p.addr = addr
	p.clients = make(chan *rpc.Client, maxCap)
	client, err := p.dialNew()
	if err != nil {
		glog.Fatal(err)
		return nil
	}
	p.clients <- client
	return p
}

func (p *Pool) dialNew() (*rpc.Client, error) {
	d := &net.Dialer{
		Timeout: 3 * time.Minute,
	}
	var nconn net.Conn
	var err error
	for i := 0; i < 10; i++ {
		nconn, err = d.Dial("tcp", p.addr)
		if err == nil {
			break
		}
		if !strings.Contains(err.Error(), "refused") {
			break
		}

		glog.WithField("error", err).WithField("addr", p.addr).
			Info("Retrying connection...")
		time.Sleep(10 * time.Second)
	}
	if err != nil {
		return nil, err
	}
	cc := &ClientCodec{
		Rwc: nconn,
	}
	return rpc.NewClientWithCodec(cc), nil
}

func (p *Pool) Call(serviceMethod string, args interface{},
	reply interface{}) error {

	client, err := p.get()
	if err != nil {
		return err
	}
	if err = client.Call(serviceMethod, args, reply); err != nil {
		return err
	}

	select {
	case p.clients <- client:
		return nil
	default:
		return client.Close()
	}
}

func (p *Pool) get() (*rpc.Client, error) {
	select {
	case client := <-p.clients:
		return client, nil
	default:
		return p.dialNew()
	}
}

func (p *Pool) Close() error {
	// We're not doing a clean exit here. A clean exit here would require
	// synchronization, which seems unnecessary for now. But, we should
	// add one if required later.
	return nil
}
<|endoftext|>


<commit_before>package raft

import (
	"errors"
	"fmt"
	"sync/atomic"
	"time"
)

const (
	RPC_CHANNEL_BUFFER_SIZE = 100
)

type passiveConsensusModule struct {
	// ===== the following fields meant to be immutable

	// -- External components
	persistentState PersistentState
	log             Log
	rpcSender       rpcSender

	// -- Config
	clusterInfo *ClusterInfo

	// ===== the following fields may be accessed concurrently

	// -- State - for all servers
	_unsafe_serverState ServerState

	// ===== the following fields meant for single-threaded access

	// -- State - for all servers
	// commitIndex is the index of highest log entry known to be committed
	// (initialized to 0, increases monotonically)
	_commitIndex           LogIndex
	electionTimeoutTracker *electionTimeoutTracker

	// -- State - for candidates only
	candidateVolatileState *candidateVolatileState

	// -- State - for leaders only
	leaderVolatileState *leaderVolatileState
}

func newPassiveConsensusModule(
	persistentState PersistentState,
	log Log,
	rpcSender rpcSender,
	clusterInfo *ClusterInfo,
	electionTimeoutLow time.Duration,
	now time.Time,
) (*passiveConsensusModule, error) {
	// Param checks
	if persistentState == nil {
		return nil, errors.New("'persistentState' cannot be nil")
	}
	if log == nil {
		return nil, errors.New("'log' cannot be nil")
	}
	if rpcSender == nil {
		return nil, errors.New("'rpcSender' cannot be nil")
	}
	if clusterInfo == nil {
		return nil, errors.New("clusterInfo cannot be nil")
	}
	if electionTimeoutLow.Nanoseconds() <= 0 {
		return nil, errors.New("electionTimeoutLow must be greater than zero")
	}

	pcm := &passiveConsensusModule{
		// -- External components
		persistentState,
		log,
		rpcSender,

		// -- Config
		clusterInfo,

		// -- State - for all servers
		// #5.2-p1s2: When servers start up, they begin as followers
		FOLLOWER,

		// -- State - for all servers
		// commitIndex is the index of highest log entry known to be committed
		// (initialized to 0, increases monotonically)
		0,
		newElectionTimeoutTracker(electionTimeoutLow, now),

		// -- State - for candidates only
		nil,

		// -- State - for leaders only
		nil,
	}

	return pcm, nil
}

// Get the current server state.
// Validates the server state before returning.
func (cm *passiveConsensusModule) getServerState() ServerState {
	serverState := ServerState(atomic.LoadUint32((*uint32)(&cm._unsafe_serverState)))
	err := validateServerState(serverState)
	if err != nil {
		panic(err.Error())
	}
	return serverState
}

// Set the current server state.
// Validates the server state before setting.
func (cm *passiveConsensusModule) setServerState(serverState ServerState) {
	err := validateServerState(serverState)
	if err != nil {
		panic(err.Error())
	}
	atomic.StoreUint32((*uint32)(&cm._unsafe_serverState), (uint32)(serverState))
}

// Get the current commitIndex value.
func (cm *passiveConsensusModule) getCommitIndex() LogIndex {
	return cm._commitIndex
}

// Set the current commitIndex value.
// Checks that it is does not reduce.
func (cm *passiveConsensusModule) setCommitIndex(commitIndex LogIndex) {
	if commitIndex < cm._commitIndex {
		panic(fmt.Sprintf(
			"setCommitIndex to %v < current commitIndex %v",
			commitIndex,
			cm._commitIndex,
		))
	}
	cm._commitIndex = commitIndex
	err := cm.log.CommitIndexChanged(commitIndex)
	if err != nil {
		panic(err)
	}
}

// Append the given command as an entry in the log.
// #RFS-L2a: If command received from client: append entry to local log
func (cm *passiveConsensusModule) appendCommand(
	command Command,
) (LogIndex, error) {
	serverState := cm.getServerState()
	if serverState == LEADER {
		iole, err := cm.log.GetIndexOfLastEntry()
		if err != nil {
			panic(err)
		}
		logEntries := []LogEntry{
			{cm.persistentState.GetCurrentTerm(), command},
		}
		err = cm.log.SetEntriesAfterIndex(iole, logEntries)
		if err != nil {
			panic(err)
		}
		var newIole LogIndex
		newIole, err = cm.log.GetIndexOfLastEntry()
		if err != nil {
			panic(err)
		}
		if newIole != iole+1 {
			panic(fmt.Sprintf("newIole=%v != %v + 1", newIole, iole))
		}
		return newIole, nil
	} else {
		return 0, errors.New("raft: state != LEADER - cannot append command to log")
	}
}

// Iterate
func (cm *passiveConsensusModule) tick(now time.Time) {
	serverState := cm.getServerState()
	switch serverState {
	case FOLLOWER:
		// #RFS-F2: If election timeout elapses without receiving
		// AppendEntries RPC from current leader or granting vote
		// to candidate: convert to candidate
		// #5.2-p1s5: If a follower receives no communication over a period
		// of time called the election timeout, then it assumes there is no
		// viable leader and begins an election to choose a new leader.
		fallthrough
	case CANDIDATE:
		// #RFS-C4: If election timeout elapses: start new election
		// #5.2-p5s1: The third possible outcome is that a candidate neither
		// wins nor loses the election; ... votes could be split so that no
		// candidate obtains a majority.
		// #5.2-p5s2: When this happens, each candidate will time out and
		// start a new election by incrementing its term and initiating
		// another round of RequestVote RPCs.
		if cm.electionTimeoutTracker.electionTimeoutHasOccurred(now) {
			err := cm.becomeCandidateAndBeginElection(now)
			if err != nil {
				panic(err)
			}
		}
	case LEADER:
		// #RFS-L4: If there exists an N such that N > commitIndex, a majority
		// of matchIndex[i] >= N, and log[N].term == currentTerm:
		// set commitIndex = N (#5.3, #5.4)
		err := cm.advanceCommitIndexIfPossible()
		if err != nil {
			panic(err)
		}
		// #RFS-L3.0: If last log index >= nextIndex for a follower: send
		// AppendEntries RPC with log entries starting at nextIndex
		err = cm.sendAppendEntriesToAllPeers(false)
		if err != nil {
			panic(err)
		}
	}
}

func (cm *passiveConsensusModule) becomeCandidateAndBeginElection(now time.Time) error {
	// #RFS-C1: On conversion to candidate, start election:
	// Increment currentTerm; Vote for self; Send RequestVote RPCs
	// to all other servers; Reset election timer
	// #5.2-p2s1: To begin an election, a follower increments its
	// current term and transitions to candidate state.
	newTerm := cm.persistentState.GetCurrentTerm() + 1
	err := cm.persistentState.SetCurrentTerm(newTerm)
	if err != nil {
		return err
	}
	cm.candidateVolatileState, err = newCandidateVolatileState(cm.clusterInfo)
	if err != nil {
		return err
	}
	cm.setServerState(CANDIDATE)
	// #5.2-p2s2: It then votes for itself and issues RequestVote RPCs
	// in parallel to each of the other servers in the cluster.
	err = cm.persistentState.SetVotedFor(cm.clusterInfo.GetThisServerId())
	if err != nil {
		return err
	}
	lastLogIndex, lastLogTerm, err := GetIndexAndTermOfLastEntry(cm.log)
	if err != nil {
		return err
	}
	err = cm.clusterInfo.ForEachPeer(
		func(serverId ServerId) error {
			rpcRequestVote := &RpcRequestVote{newTerm, lastLogIndex, lastLogTerm}
			cm.rpcSender.sendRpcRequestVoteAsync(serverId, rpcRequestVote)
			return nil
		},
	)
	if err != nil {
		return err
	}
	// Reset election timeout!
	cm.electionTimeoutTracker.chooseNewRandomElectionTimeoutAndTouch(now)
	return nil
}

func (cm *passiveConsensusModule) becomeLeader() error {
	iole, err := cm.log.GetIndexOfLastEntry()
	if err != nil {
		return err
	}
	cm.leaderVolatileState, err = newLeaderVolatileState(cm.clusterInfo, iole)
	if err != nil {
		return err
	}
	cm.setServerState(LEADER)
	// #RFS-L1a: Upon election: send initial empty AppendEntries RPCs (heartbeat)
	// to each server;
	err = cm.sendAppendEntriesToAllPeers(true)
	if err != nil {
		return err
	}
	return nil
}

func (cm *passiveConsensusModule) becomeFollowerWithTerm(newTerm TermNo) error {
	cm.setServerState(FOLLOWER)
	err := cm.persistentState.SetCurrentTerm(newTerm)
	if err != nil {
		return err
	}
	return nil
}

// -- leader code

func (cm *passiveConsensusModule) sendAppendEntriesToAllPeers(empty bool) error {
	return cm.clusterInfo.ForEachPeer(
		func(serverId ServerId) error {
			err := cm.sendAppendEntriesToPeer(serverId, empty)
			if err != nil {
				return err
			}
			return nil
		},
	)
}

func (cm *passiveConsensusModule) sendAppendEntriesToPeer(
	peerId ServerId,
	empty bool,
) error {
	serverTerm := cm.persistentState.GetCurrentTerm()
	//
	peerNextIndex, err := cm.leaderVolatileState.getNextIndex(peerId)
	if err != nil {
		return err
	}
	peerLastLogIndex := peerNextIndex - 1
	var peerLastLogTerm TermNo
	if peerLastLogIndex == 0 {
		peerLastLogTerm = 0
	} else {
		var err error
		peerLastLogTerm, err = cm.log.GetTermAtIndex(peerLastLogIndex)
		if err != nil {
			return err
		}
	}
	//
	var entriesToSend []LogEntry
	if empty {
		entriesToSend = []LogEntry{}
	} else {
		var err error
		entriesToSend, err = cm.log.GetEntriesAfterIndex(peerLastLogIndex)
		if err != nil {
			return err
		}
	}
	//
	rpcAppendEntries := &RpcAppendEntries{
		serverTerm,
		peerLastLogIndex,
		peerLastLogTerm,
		entriesToSend,
		cm.getCommitIndex(),
	}
	cm.rpcSender.sendRpcAppendEntriesAsync(peerId, rpcAppendEntries)
	return nil
}

// #RFS-L4: If there exists an N such that N > commitIndex, a majority
// of matchIndex[i] >= N, and log[N].term == currentTerm:
// set commitIndex = N (#5.3, #5.4)
func (cm *passiveConsensusModule) advanceCommitIndexIfPossible() error {
	newerCommitIndex, err := findNewerCommitIndex(
		cm.clusterInfo,
		cm.leaderVolatileState,
		cm.log,
		cm.persistentState.GetCurrentTerm(),
		cm.getCommitIndex(),
	)
	if err != nil {
		return err
	}
	if newerCommitIndex != 0 && newerCommitIndex > cm.getCommitIndex() {
		cm.setCommitIndex(newerCommitIndex)
	}
	return nil
}

// -- rpc bridging things

// This is an internal equivalent to RpcService without the reply setup.
type rpcSender interface {
	sendRpcAppendEntriesAsync(toServer ServerId, rpc *RpcAppendEntries)
	sendRpcRequestVoteAsync(toServer ServerId, rpc *RpcRequestVote)
}
<commit_msg>Change panics to errors: appendCommand<commit_after>package raft

import (
	"errors"
	"fmt"
	"sync/atomic"
	"time"
)

const (
	RPC_CHANNEL_BUFFER_SIZE = 100
)

type passiveConsensusModule struct {
	// ===== the following fields meant to be immutable

	// -- External components
	persistentState PersistentState
	log             Log
	rpcSender       rpcSender

	// -- Config
	clusterInfo *ClusterInfo

	// ===== the following fields may be accessed concurrently

	// -- State - for all servers
	_unsafe_serverState ServerState

	// ===== the following fields meant for single-threaded access

	// -- State - for all servers
	// commitIndex is the index of highest log entry known to be committed
	// (initialized to 0, increases monotonically)
	_commitIndex           LogIndex
	electionTimeoutTracker *electionTimeoutTracker

	// -- State - for candidates only
	candidateVolatileState *candidateVolatileState

	// -- State - for leaders only
	leaderVolatileState *leaderVolatileState
}

func newPassiveConsensusModule(
	persistentState PersistentState,
	log Log,
	rpcSender rpcSender,
	clusterInfo *ClusterInfo,
	electionTimeoutLow time.Duration,
	now time.Time,
) (*passiveConsensusModule, error) {
	// Param checks
	if persistentState == nil {
		return nil, errors.New("'persistentState' cannot be nil")
	}
	if log == nil {
		return nil, errors.New("'log' cannot be nil")
	}
	if rpcSender == nil {
		return nil, errors.New("'rpcSender' cannot be nil")
	}
	if clusterInfo == nil {
		return nil, errors.New("clusterInfo cannot be nil")
	}
	if electionTimeoutLow.Nanoseconds() <= 0 {
		return nil, errors.New("electionTimeoutLow must be greater than zero")
	}

	pcm := &passiveConsensusModule{
		// -- External components
		persistentState,
		log,
		rpcSender,

		// -- Config
		clusterInfo,

		// -- State - for all servers
		// #5.2-p1s2: When servers start up, they begin as followers
		FOLLOWER,

		// -- State - for all servers
		// commitIndex is the index of highest log entry known to be committed
		// (initialized to 0, increases monotonically)
		0,
		newElectionTimeoutTracker(electionTimeoutLow, now),

		// -- State - for candidates only
		nil,

		// -- State - for leaders only
		nil,
	}

	return pcm, nil
}

// Get the current server state.
// Validates the server state before returning.
func (cm *passiveConsensusModule) getServerState() ServerState {
	serverState := ServerState(atomic.LoadUint32((*uint32)(&cm._unsafe_serverState)))
	err := validateServerState(serverState)
	if err != nil {
		panic(err.Error())
	}
	return serverState
}

// Set the current server state.
// Validates the server state before setting.
func (cm *passiveConsensusModule) setServerState(serverState ServerState) {
	err := validateServerState(serverState)
	if err != nil {
		panic(err.Error())
	}
	atomic.StoreUint32((*uint32)(&cm._unsafe_serverState), (uint32)(serverState))
}

// Get the current commitIndex value.
func (cm *passiveConsensusModule) getCommitIndex() LogIndex {
	return cm._commitIndex
}

// Set the current commitIndex value.
// Checks that it is does not reduce.
func (cm *passiveConsensusModule) setCommitIndex(commitIndex LogIndex) {
	if commitIndex < cm._commitIndex {
		panic(fmt.Sprintf(
			"setCommitIndex to %v < current commitIndex %v",
			commitIndex,
			cm._commitIndex,
		))
	}
	cm._commitIndex = commitIndex
	err := cm.log.CommitIndexChanged(commitIndex)
	if err != nil {
		panic(err)
	}
}

// Append the given command as an entry in the log.
// #RFS-L2a: If command received from client: append entry to local log
func (cm *passiveConsensusModule) appendCommand(
	command Command,
) (LogIndex, error) {
	serverState := cm.getServerState()
	if serverState == LEADER {
		iole, err := cm.log.GetIndexOfLastEntry()
		if err != nil {
			return 0, err
		}
		logEntries := []LogEntry{
			{cm.persistentState.GetCurrentTerm(), command},
		}
		err = cm.log.SetEntriesAfterIndex(iole, logEntries)
		if err != nil {
			return 0, err
		}
		var newIole LogIndex
		newIole, err = cm.log.GetIndexOfLastEntry()
		if err != nil {
			return 0, err
		}
		if newIole != iole+1 {
			return 0, fmt.Errorf("newIole=%v != %v + 1", newIole, iole)
		}
		return newIole, nil
	} else {
		return 0, errors.New("raft: state != LEADER - cannot append command to log")
	}
}

// Iterate
func (cm *passiveConsensusModule) tick(now time.Time) {
	serverState := cm.getServerState()
	switch serverState {
	case FOLLOWER:
		// #RFS-F2: If election timeout elapses without receiving
		// AppendEntries RPC from current leader or granting vote
		// to candidate: convert to candidate
		// #5.2-p1s5: If a follower receives no communication over a period
		// of time called the election timeout, then it assumes there is no
		// viable leader and begins an election to choose a new leader.
		fallthrough
	case CANDIDATE:
		// #RFS-C4: If election timeout elapses: start new election
		// #5.2-p5s1: The third possible outcome is that a candidate neither
		// wins nor loses the election; ... votes could be split so that no
		// candidate obtains a majority.
		// #5.2-p5s2: When this happens, each candidate will time out and
		// start a new election by incrementing its term and initiating
		// another round of RequestVote RPCs.
		if cm.electionTimeoutTracker.electionTimeoutHasOccurred(now) {
			err := cm.becomeCandidateAndBeginElection(now)
			if err != nil {
				panic(err)
			}
		}
	case LEADER:
		// #RFS-L4: If there exists an N such that N > commitIndex, a majority
		// of matchIndex[i] >= N, and log[N].term == currentTerm:
		// set commitIndex = N (#5.3, #5.4)
		err := cm.advanceCommitIndexIfPossible()
		if err != nil {
			panic(err)
		}
		// #RFS-L3.0: If last log index >= nextIndex for a follower: send
		// AppendEntries RPC with log entries starting at nextIndex
		err = cm.sendAppendEntriesToAllPeers(false)
		if err != nil {
			panic(err)
		}
	}
}

func (cm *passiveConsensusModule) becomeCandidateAndBeginElection(now time.Time) error {
	// #RFS-C1: On conversion to candidate, start election:
	// Increment currentTerm; Vote for self; Send RequestVote RPCs
	// to all other servers; Reset election timer
	// #5.2-p2s1: To begin an election, a follower increments its
	// current term and transitions to candidate state.
	newTerm := cm.persistentState.GetCurrentTerm() + 1
	err := cm.persistentState.SetCurrentTerm(newTerm)
	if err != nil {
		return err
	}
	cm.candidateVolatileState, err = newCandidateVolatileState(cm.clusterInfo)
	if err != nil {
		return err
	}
	cm.setServerState(CANDIDATE)
	// #5.2-p2s2: It then votes for itself and issues RequestVote RPCs
	// in parallel to each of the other servers in the cluster.
	err = cm.persistentState.SetVotedFor(cm.clusterInfo.GetThisServerId())
	if err != nil {
		return err
	}
	lastLogIndex, lastLogTerm, err := GetIndexAndTermOfLastEntry(cm.log)
	if err != nil {
		return err
	}
	err = cm.clusterInfo.ForEachPeer(
		func(serverId ServerId) error {
			rpcRequestVote := &RpcRequestVote{newTerm, lastLogIndex, lastLogTerm}
			cm.rpcSender.sendRpcRequestVoteAsync(serverId, rpcRequestVote)
			return nil
		},
	)
	if err != nil {
		return err
	}
	// Reset election timeout!
	cm.electionTimeoutTracker.chooseNewRandomElectionTimeoutAndTouch(now)
	return nil
}

func (cm *passiveConsensusModule) becomeLeader() error {
	iole, err := cm.log.GetIndexOfLastEntry()
	if err != nil {
		return err
	}
	cm.leaderVolatileState, err = newLeaderVolatileState(cm.clusterInfo, iole)
	if err != nil {
		return err
	}
	cm.setServerState(LEADER)
	// #RFS-L1a: Upon election: send initial empty AppendEntries RPCs (heartbeat)
	// to each server;
	err = cm.sendAppendEntriesToAllPeers(true)
	if err != nil {
		return err
	}
	return nil
}

func (cm *passiveConsensusModule) becomeFollowerWithTerm(newTerm TermNo) error {
	cm.setServerState(FOLLOWER)
	err := cm.persistentState.SetCurrentTerm(newTerm)
	if err != nil {
		return err
	}
	return nil
}

// -- leader code

func (cm *passiveConsensusModule) sendAppendEntriesToAllPeers(empty bool) error {
	return cm.clusterInfo.ForEachPeer(
		func(serverId ServerId) error {
			err := cm.sendAppendEntriesToPeer(serverId, empty)
			if err != nil {
				return err
			}
			return nil
		},
	)
}

func (cm *passiveConsensusModule) sendAppendEntriesToPeer(
	peerId ServerId,
	empty bool,
) error {
	serverTerm := cm.persistentState.GetCurrentTerm()
	//
	peerNextIndex, err := cm.leaderVolatileState.getNextIndex(peerId)
	if err != nil {
		return err
	}
	peerLastLogIndex := peerNextIndex - 1
	var peerLastLogTerm TermNo
	if peerLastLogIndex == 0 {
		peerLastLogTerm = 0
	} else {
		var err error
		peerLastLogTerm, err = cm.log.GetTermAtIndex(peerLastLogIndex)
		if err != nil {
			return err
		}
	}
	//
	var entriesToSend []LogEntry
	if empty {
		entriesToSend = []LogEntry{}
	} else {
		var err error
		entriesToSend, err = cm.log.GetEntriesAfterIndex(peerLastLogIndex)
		if err != nil {
			return err
		}
	}
	//
	rpcAppendEntries := &RpcAppendEntries{
		serverTerm,
		peerLastLogIndex,
		peerLastLogTerm,
		entriesToSend,
		cm.getCommitIndex(),
	}
	cm.rpcSender.sendRpcAppendEntriesAsync(peerId, rpcAppendEntries)
	return nil
}

// #RFS-L4: If there exists an N such that N > commitIndex, a majority
// of matchIndex[i] >= N, and log[N].term == currentTerm:
// set commitIndex = N (#5.3, #5.4)
func (cm *passiveConsensusModule) advanceCommitIndexIfPossible() error {
	newerCommitIndex, err := findNewerCommitIndex(
		cm.clusterInfo,
		cm.leaderVolatileState,
		cm.log,
		cm.persistentState.GetCurrentTerm(),
		cm.getCommitIndex(),
	)
	if err != nil {
		return err
	}
	if newerCommitIndex != 0 && newerCommitIndex > cm.getCommitIndex() {
		cm.setCommitIndex(newerCommitIndex)
	}
	return nil
}

// -- rpc bridging things

// This is an internal equivalent to RpcService without the reply setup.
type rpcSender interface {
	sendRpcAppendEntriesAsync(toServer ServerId, rpc *RpcAppendEntries)
	sendRpcRequestVoteAsync(toServer ServerId, rpc *RpcRequestVote)
}
<|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.

// TODO(rsc): All the prints in this file should go to standard error.

package net

import (
	"net";
	"once";
	"os";
	"sync";
	"syscall";
)

// Network file descriptor.
type netFD struct {
	// immutable until Close
	fd int64;
	file *os.File;
	cr chan *netFD;
	cw chan *netFD;
	net string;
	laddr string;
	raddr string;

	// owned by client
	rdeadline_delta int64;
	rdeadline int64;
	rio sync.Mutex;
	wdeadline_delta int64;
	wdeadline int64;
	wio sync.Mutex;

	// owned by fd wait server
	ncr, ncw int;
}

// Make reads and writes on fd return EAGAIN instead of blocking.
func setNonblock(fd int64) *os.Error {
	flags, e := syscall.Fcntl(fd, syscall.F_GETFL, 0);
	if e != 0 {
		return os.ErrnoToError(e)
	}
	flags, e = syscall.Fcntl(fd, syscall.F_SETFL, flags | syscall.O_NONBLOCK);
	if e != 0 {
		return os.ErrnoToError(e)
	}
	return nil
}

// Make reads/writes blocking; last gasp, so no error checking.
func setBlock(fd int64) {
	flags, e := syscall.Fcntl(fd, syscall.F_GETFL, 0);
	if e != 0 {
		return;
	}
	syscall.Fcntl(fd, syscall.F_SETFL, flags & ^syscall.O_NONBLOCK);
}

// A pollServer helps FDs determine when to retry a non-blocking
// read or write after they get EAGAIN.  When an FD needs to wait,
// send the fd on s.cr (for a read) or s.cw (for a write) to pass the
// request to the poll server.  Then receive on fd.cr/fd.cw.
// When the pollServer finds that i/o on FD should be possible
// again, it will send fd on fd.cr/fd.cw to wake any waiting processes.
// This protocol is implemented as s.WaitRead() and s.WaitWrite().
//
// There is one subtlety: when sending on s.cr/s.cw, the
// poll server is probably in a system call, waiting for an fd
// to become ready.  It's not looking at the request channels.
// To resolve this, the poll server waits not just on the FDs it has
// been given but also its own pipe.  After sending on the
// buffered channel s.cr/s.cw, WaitRead/WaitWrite writes a
// byte to the pipe, causing the pollServer's poll system call to
// return.  In response to the pipe being readable, the pollServer
// re-polls its request channels.
//
// Note that the ordering is "send request" and then "wake up server".
// If the operations were reversed, there would be a race: the poll
// server might wake up and look at the request channel, see that it
// was empty, and go back to sleep, all before the requester managed
// to send the request.  Because the send must complete before the wakeup,
// the request channel must be buffered.  A buffer of size 1 is sufficient
// for any request load.  If many processes are trying to submit requests,
// one will succeed, the pollServer will read the request, and then the
// channel will be empty for the next process's request.  A larger buffer
// might help batch requests.

type pollServer struct {
	cr, cw chan *netFD;	// buffered >= 1
	pr, pw *os.File;
	pending map[int64] *netFD;
	poll *pollster;	// low-level OS hooks
	deadline int64;	// next deadline (nsec since 1970)
}
func (s *pollServer) Run();

func newPollServer() (s *pollServer, err *os.Error) {
	s = new(pollServer);
	s.cr = make(chan *netFD, 1);
	s.cw = make(chan *netFD, 1);
	if s.pr, s.pw, err = os.Pipe(); err != nil {
		return nil, err
	}
	if err = setNonblock(s.pr.Fd()); err != nil {
	Error:
		s.pr.Close();
		s.pw.Close();
		return nil, err
	}
	if err = setNonblock(s.pw.Fd()); err != nil {
		goto Error
	}
	if s.poll, err = newpollster(); err != nil {
		goto Error
	}
	if err = s.poll.AddFD(s.pr.Fd(), 'r', true); err != nil {
		s.poll.Close();
		goto Error
	}
	s.pending = make(map[int64] *netFD);
	go s.Run();
	return s, nil
}

func (s *pollServer) AddFD(fd *netFD, mode int) {
	if err := s.poll.AddFD(fd.fd, mode, false); err != nil {
		panicln("pollServer AddFD ", fd.fd, ": ", err.String(), "\n");
		return
	}

	var t int64;
	key := fd.fd << 1;
	if mode == 'r' {
		fd.ncr++;
		t = fd.rdeadline;
	} else {
		fd.ncw++;
		key++;
		t = fd.wdeadline;
	}
	s.pending[key] = fd;
	if t > 0 && (s.deadline == 0 || t < s.deadline) {
		s.deadline = t;
	}
}

func (s *pollServer) LookupFD(fd int64, mode int) *netFD {
	key := fd << 1;
	if mode == 'w' {
		key++;
	}
	netfd, ok := s.pending[key];
	if !ok {
		return nil
	}
	s.pending[key] = nil, false;
	return netfd
}

func (s *pollServer) WakeFD(fd *netFD, mode int) {
	if mode == 'r' {
		for fd.ncr > 0 {
			fd.ncr--;
			fd.cr <- fd
		}
	} else {
		for fd.ncw > 0 {
			fd.ncw--;
			fd.cw <- fd
		}
	}
}

func (s *pollServer) Now() int64 {
	sec, nsec, err := os.Time();
	if err != nil {
		panic("net: os.Time: ", err.String());
	}
	nsec += sec * 1e9;
	return nsec;
}

func (s *pollServer) CheckDeadlines() {
	now := s.Now();
	// TODO(rsc): This will need to be handled more efficiently,
	// probably with a heap indexed by wakeup time.

	var next_deadline int64;
	for key, fd := range s.pending {
		var t int64;
		var mode int;
		if key&1 == 0 {
			mode = 'r';
		} else {
			mode = 'w';
		}
		if mode == 'r' {
			t = fd.rdeadline;
		} else {
			t = fd.wdeadline;
		}
		if t > 0 {
			if t <= now {
				s.pending[key] = nil, false;
				if mode == 'r' {
					s.poll.DelFD(fd.fd, mode);
					fd.rdeadline = -1;
				} else {
					s.poll.DelFD(fd.fd, mode);
					fd.wdeadline = -1;
				}
				s.WakeFD(fd, mode);
			} else if next_deadline == 0 || t < next_deadline {
				next_deadline = t;
			}
		}
	}
	s.deadline = next_deadline;
}

func (s *pollServer) Run() {
	var scratch [100]byte;
	for {
		var t = s.deadline;
		if t > 0 {
			t = t - s.Now();
			if t < 0 {
				s.CheckDeadlines();
				continue;
			}
		}
		fd, mode, err := s.poll.WaitFD(t);
		if err != nil {
			print("pollServer WaitFD: ", err.String(), "\n");
			return
		}
		if fd < 0 {
			// Timeout happened.
			s.CheckDeadlines();
			continue;
		}
		if fd == s.pr.Fd() {
			// Drain our wakeup pipe.
			for nn, e := s.pr.Read(scratch); nn > 0; {
				nn, e = s.pr.Read(scratch)
			}

			// Read from channels
			for fd, ok := <-s.cr; ok; fd, ok = <-s.cr {
				s.AddFD(fd, 'r')
			}
			for fd, ok := <-s.cw; ok; fd, ok = <-s.cw {
				s.AddFD(fd, 'w')
			}
		} else {
			netfd := s.LookupFD(fd, mode);
			if netfd == nil {
				print("pollServer: unexpected wakeup for fd=", netfd, " mode=", string(mode), "\n");
				continue
			}
			s.WakeFD(netfd, mode);
		}
	}
}

func (s *pollServer) Wakeup() {
	var b [1]byte;
	s.pw.Write(b)
}

func (s *pollServer) WaitRead(fd *netFD) {
	s.cr <- fd;
	s.Wakeup();
	<-fd.cr
}

func (s *pollServer) WaitWrite(fd *netFD) {
	s.cr <- fd;
	s.Wakeup();
	<-fd.cr
}

// Network FD methods.
// All the network FDs use a single pollServer.

var pollserver *pollServer

func _StartServer() {
	p, err := newPollServer();
	if err != nil {
		print("Start pollServer: ", err.String(), "\n")
	}
	pollserver = p
}

func newFD(fd int64, net, laddr, raddr string) (f *netFD, err *os.Error) {
	if pollserver == nil {
		once.Do(_StartServer);
	}
	if err = setNonblock(fd); err != nil {
		return nil, err
	}
	f = new(netFD);
	f.fd = fd;
	f.net = net;
	f.laddr = laddr;
	f.raddr = raddr;
	f.file = os.NewFile(fd, "net: " + net + " " + laddr + " " + raddr);
	f.cr = make(chan *netFD, 1);
	f.cw = make(chan *netFD, 1);
	return f, nil
}

func (fd *netFD) Close() *os.Error {
	if fd == nil || fd.file == nil {
		return os.EINVAL
	}

	// In case the user has set linger,
	// switch to blocking mode so the close blocks.
	// As long as this doesn't happen often,
	// we can handle the extra OS processes.
	// Otherwise we'll need to use the pollserver
	// for Close too.  Sigh.
	setBlock(fd.file.Fd());

	e := fd.file.Close();
	fd.file = nil;
	fd.fd = -1;
	return e
}

func (fd *netFD) Read(p []byte) (n int, err *os.Error) {
	if fd == nil || fd.file == nil {
		return -1, os.EINVAL
	}
	fd.rio.Lock();
	defer fd.rio.Unlock();
	if fd.rdeadline_delta > 0 {
		fd.rdeadline = pollserver.Now() + fd.rdeadline_delta;
	} else {
		fd.rdeadline = 0;
	}
	n, err = fd.file.Read(p);
	for err == os.EAGAIN && fd.rdeadline >= 0 {
		pollserver.WaitRead(fd);
		n, err = fd.file.Read(p)
	}
	return n, err
}

func (fd *netFD) Write(p []byte) (n int, err *os.Error) {
	if fd == nil || fd.file == nil {
		return -1, os.EINVAL
	}
	fd.wio.Lock();
	defer fd.wio.Unlock();
	if fd.wdeadline_delta > 0 {
		fd.wdeadline = pollserver.Now() + fd.wdeadline_delta;
	} else {
		fd.wdeadline = 0;
	}
	err = nil;
	nn := 0;
	for nn < len(p) {
		n, err = fd.file.Write(p[nn:len(p)]);
		if n > 0 {
			nn += n
		}
		if nn == len(p) {
			break;
		}
		if err == os.EAGAIN && fd.wdeadline >= 0 {
			pollserver.WaitWrite(fd);
			continue;
		}
		if n == 0 || err != nil {
			break;
		}
	}
	return nn, err
}

func sockaddrToHostPort(sa *syscall.Sockaddr) (hostport string, err *os.Error)

func (fd *netFD) Accept(sa *syscall.Sockaddr) (nfd *netFD, err *os.Error) {
	if fd == nil || fd.file == nil {
		return nil, os.EINVAL
	}

	// See ../syscall/exec.go for description of ForkLock.
	// It is okay to hold the lock across syscall.Accept
	// because we have put fd.fd into non-blocking mode.
	syscall.ForkLock.RLock();
	var s, e int64;
	for {
		s, e = syscall.Accept(fd.fd, sa);
		if e != syscall.EAGAIN {
			break;
		}
		syscall.ForkLock.RUnlock();
		pollserver.WaitRead(fd);
		syscall.ForkLock.RLock();
	}
	if e != 0 {
		syscall.ForkLock.RUnlock();
		return nil, os.ErrnoToError(e)
	}
	syscall.CloseOnExec(s);
	syscall.ForkLock.RUnlock();

	raddr, err1 := sockaddrToHostPort(sa);
	if err1 != nil {
		raddr = "invalid-address";
	}
	if nfd, err = newFD(s, fd.net, fd.laddr, raddr); err != nil {
		syscall.Close(s);
		return nil, err
	}
	return nfd, nil
}

<commit_msg>document and partially fix a race<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.

// TODO(rsc): All the prints in this file should go to standard error.

package net

import (
	"net";
	"once";
	"os";
	"sync";
	"syscall";
)

// Network file descriptor.
type netFD struct {
	// immutable until Close
	fd int64;
	file *os.File;
	cr chan *netFD;
	cw chan *netFD;
	net string;
	laddr string;
	raddr string;

	// owned by client
	rdeadline_delta int64;
	rdeadline int64;
	rio sync.Mutex;
	wdeadline_delta int64;
	wdeadline int64;
	wio sync.Mutex;

	// owned by fd wait server
	ncr, ncw int;
}

// Make reads and writes on fd return EAGAIN instead of blocking.
func setNonblock(fd int64) *os.Error {
	flags, e := syscall.Fcntl(fd, syscall.F_GETFL, 0);
	if e != 0 {
		return os.ErrnoToError(e)
	}
	flags, e = syscall.Fcntl(fd, syscall.F_SETFL, flags | syscall.O_NONBLOCK);
	if e != 0 {
		return os.ErrnoToError(e)
	}
	return nil
}

// Make reads/writes blocking; last gasp, so no error checking.
func setBlock(fd int64) {
	flags, e := syscall.Fcntl(fd, syscall.F_GETFL, 0);
	if e != 0 {
		return;
	}
	syscall.Fcntl(fd, syscall.F_SETFL, flags & ^syscall.O_NONBLOCK);
}

// A pollServer helps FDs determine when to retry a non-blocking
// read or write after they get EAGAIN.  When an FD needs to wait,
// send the fd on s.cr (for a read) or s.cw (for a write) to pass the
// request to the poll server.  Then receive on fd.cr/fd.cw.
// When the pollServer finds that i/o on FD should be possible
// again, it will send fd on fd.cr/fd.cw to wake any waiting processes.
// This protocol is implemented as s.WaitRead() and s.WaitWrite().
//
// There is one subtlety: when sending on s.cr/s.cw, the
// poll server is probably in a system call, waiting for an fd
// to become ready.  It's not looking at the request channels.
// To resolve this, the poll server waits not just on the FDs it has
// been given but also its own pipe.  After sending on the
// buffered channel s.cr/s.cw, WaitRead/WaitWrite writes a
// byte to the pipe, causing the pollServer's poll system call to
// return.  In response to the pipe being readable, the pollServer
// re-polls its request channels.
//
// Note that the ordering is "send request" and then "wake up server".
// If the operations were reversed, there would be a race: the poll
// server might wake up and look at the request channel, see that it
// was empty, and go back to sleep, all before the requester managed
// to send the request.  Because the send must complete before the wakeup,
// the request channel must be buffered.  A buffer of size 1 is sufficient
// for any request load.  If many processes are trying to submit requests,
// one will succeed, the pollServer will read the request, and then the
// channel will be empty for the next process's request.  A larger buffer
// might help batch requests.

type pollServer struct {
	cr, cw chan *netFD;	// buffered >= 1
	pr, pw *os.File;
	pending map[int64] *netFD;
	poll *pollster;	// low-level OS hooks
	deadline int64;	// next deadline (nsec since 1970)
}
func (s *pollServer) Run();

func newPollServer() (s *pollServer, err *os.Error) {
	s = new(pollServer);
	s.cr = make(chan *netFD, 1);
	s.cw = make(chan *netFD, 1);
	if s.pr, s.pw, err = os.Pipe(); err != nil {
		return nil, err
	}
	if err = setNonblock(s.pr.Fd()); err != nil {
	Error:
		s.pr.Close();
		s.pw.Close();
		return nil, err
	}
	if err = setNonblock(s.pw.Fd()); err != nil {
		goto Error
	}
	if s.poll, err = newpollster(); err != nil {
		goto Error
	}
	if err = s.poll.AddFD(s.pr.Fd(), 'r', true); err != nil {
		s.poll.Close();
		goto Error
	}
	s.pending = make(map[int64] *netFD);
	go s.Run();
	return s, nil
}

func (s *pollServer) AddFD(fd *netFD, mode int) {
	// TODO(rsc): This check handles a race between
	// one goroutine reading and another one closing,
	// but it doesn't solve the race completely:
	// it still could happen that one goroutine closes
	// but we read fd.fd before it does, and then
	// another goroutine creates a new open file with
	// that fd, which we'd now be referring to.
	// The fix is probably to send the Close call
	// through the poll server too, except that
	// not all Reads and Writes go through the poll
	// server even now.
	intfd := fd.fd;
	if intfd < 0 {
		// fd closed underfoot
		if mode == 'r' {
			fd.cr <- fd
		} else {
			fd.cw <- fd
		}
		return
	}
	if err := s.poll.AddFD(intfd, mode, false); err != nil {
		panicln("pollServer AddFD ", intfd, ": ", err.String(), "\n");
		return
	}

	var t int64;
	key := intfd << 1;
	if mode == 'r' {
		fd.ncr++;
		t = fd.rdeadline;
	} else {
		fd.ncw++;
		key++;
		t = fd.wdeadline;
	}
	s.pending[key] = fd;
	if t > 0 && (s.deadline == 0 || t < s.deadline) {
		s.deadline = t;
	}
}

func (s *pollServer) LookupFD(fd int64, mode int) *netFD {
	key := fd << 1;
	if mode == 'w' {
		key++;
	}
	netfd, ok := s.pending[key];
	if !ok {
		return nil
	}
	s.pending[key] = nil, false;
	return netfd
}

func (s *pollServer) WakeFD(fd *netFD, mode int) {
	if mode == 'r' {
		for fd.ncr > 0 {
			fd.ncr--;
			fd.cr <- fd
		}
	} else {
		for fd.ncw > 0 {
			fd.ncw--;
			fd.cw <- fd
		}
	}
}

func (s *pollServer) Now() int64 {
	sec, nsec, err := os.Time();
	if err != nil {
		panic("net: os.Time: ", err.String());
	}
	nsec += sec * 1e9;
	return nsec;
}

func (s *pollServer) CheckDeadlines() {
	now := s.Now();
	// TODO(rsc): This will need to be handled more efficiently,
	// probably with a heap indexed by wakeup time.

	var next_deadline int64;
	for key, fd := range s.pending {
		var t int64;
		var mode int;
		if key&1 == 0 {
			mode = 'r';
		} else {
			mode = 'w';
		}
		if mode == 'r' {
			t = fd.rdeadline;
		} else {
			t = fd.wdeadline;
		}
		if t > 0 {
			if t <= now {
				s.pending[key] = nil, false;
				if mode == 'r' {
					s.poll.DelFD(fd.fd, mode);
					fd.rdeadline = -1;
				} else {
					s.poll.DelFD(fd.fd, mode);
					fd.wdeadline = -1;
				}
				s.WakeFD(fd, mode);
			} else if next_deadline == 0 || t < next_deadline {
				next_deadline = t;
			}
		}
	}
	s.deadline = next_deadline;
}

func (s *pollServer) Run() {
	var scratch [100]byte;
	for {
		var t = s.deadline;
		if t > 0 {
			t = t - s.Now();
			if t < 0 {
				s.CheckDeadlines();
				continue;
			}
		}
		fd, mode, err := s.poll.WaitFD(t);
		if err != nil {
			print("pollServer WaitFD: ", err.String(), "\n");
			return
		}
		if fd < 0 {
			// Timeout happened.
			s.CheckDeadlines();
			continue;
		}
		if fd == s.pr.Fd() {
			// Drain our wakeup pipe.
			for nn, e := s.pr.Read(scratch); nn > 0; {
				nn, e = s.pr.Read(scratch)
			}

			// Read from channels
			for fd, ok := <-s.cr; ok; fd, ok = <-s.cr {
				s.AddFD(fd, 'r')
			}
			for fd, ok := <-s.cw; ok; fd, ok = <-s.cw {
				s.AddFD(fd, 'w')
			}
		} else {
			netfd := s.LookupFD(fd, mode);
			if netfd == nil {
				print("pollServer: unexpected wakeup for fd=", netfd, " mode=", string(mode), "\n");
				continue
			}
			s.WakeFD(netfd, mode);
		}
	}
}

func (s *pollServer) Wakeup() {
	var b [1]byte;
	s.pw.Write(b)
}

func (s *pollServer) WaitRead(fd *netFD) {
	s.cr <- fd;
	s.Wakeup();
	<-fd.cr
}

func (s *pollServer) WaitWrite(fd *netFD) {
	s.cr <- fd;
	s.Wakeup();
	<-fd.cr
}

// Network FD methods.
// All the network FDs use a single pollServer.

var pollserver *pollServer

func _StartServer() {
	p, err := newPollServer();
	if err != nil {
		print("Start pollServer: ", err.String(), "\n")
	}
	pollserver = p
}

func newFD(fd int64, net, laddr, raddr string) (f *netFD, err *os.Error) {
	if pollserver == nil {
		once.Do(_StartServer);
	}
	if err = setNonblock(fd); err != nil {
		return nil, err
	}
	f = new(netFD);
	f.fd = fd;
	f.net = net;
	f.laddr = laddr;
	f.raddr = raddr;
	f.file = os.NewFile(fd, "net: " + net + " " + laddr + " " + raddr);
	f.cr = make(chan *netFD, 1);
	f.cw = make(chan *netFD, 1);
	return f, nil
}

func (fd *netFD) Close() *os.Error {
	if fd == nil || fd.file == nil {
		return os.EINVAL
	}

	// In case the user has set linger,
	// switch to blocking mode so the close blocks.
	// As long as this doesn't happen often,
	// we can handle the extra OS processes.
	// Otherwise we'll need to use the pollserver
	// for Close too.  Sigh.
	setBlock(fd.file.Fd());

	e := fd.file.Close();
	fd.file = nil;
	fd.fd = -1;
	return e
}

func (fd *netFD) Read(p []byte) (n int, err *os.Error) {
	if fd == nil || fd.file == nil {
		return -1, os.EINVAL
	}
	fd.rio.Lock();
	defer fd.rio.Unlock();
	if fd.rdeadline_delta > 0 {
		fd.rdeadline = pollserver.Now() + fd.rdeadline_delta;
	} else {
		fd.rdeadline = 0;
	}
	n, err = fd.file.Read(p);
	for err == os.EAGAIN && fd.rdeadline >= 0 {
		pollserver.WaitRead(fd);
		n, err = fd.file.Read(p)
	}
	return n, err
}

func (fd *netFD) Write(p []byte) (n int, err *os.Error) {
	if fd == nil || fd.file == nil {
		return -1, os.EINVAL
	}
	fd.wio.Lock();
	defer fd.wio.Unlock();
	if fd.wdeadline_delta > 0 {
		fd.wdeadline = pollserver.Now() + fd.wdeadline_delta;
	} else {
		fd.wdeadline = 0;
	}
	err = nil;
	nn := 0;
	for nn < len(p) {
		n, err = fd.file.Write(p[nn:len(p)]);
		if n > 0 {
			nn += n
		}
		if nn == len(p) {
			break;
		}
		if err == os.EAGAIN && fd.wdeadline >= 0 {
			pollserver.WaitWrite(fd);
			continue;
		}
		if n == 0 || err != nil {
			break;
		}
	}
	return nn, err
}

func sockaddrToHostPort(sa *syscall.Sockaddr) (hostport string, err *os.Error)

func (fd *netFD) Accept(sa *syscall.Sockaddr) (nfd *netFD, err *os.Error) {
	if fd == nil || fd.file == nil {
		return nil, os.EINVAL
	}

	// See ../syscall/exec.go for description of ForkLock.
	// It is okay to hold the lock across syscall.Accept
	// because we have put fd.fd into non-blocking mode.
	syscall.ForkLock.RLock();
	var s, e int64;
	for {
		s, e = syscall.Accept(fd.fd, sa);
		if e != syscall.EAGAIN {
			break;
		}
		syscall.ForkLock.RUnlock();
		pollserver.WaitRead(fd);
		syscall.ForkLock.RLock();
	}
	if e != 0 {
		syscall.ForkLock.RUnlock();
		return nil, os.ErrnoToError(e)
	}
	syscall.CloseOnExec(s);
	syscall.ForkLock.RUnlock();

	raddr, err1 := sockaddrToHostPort(sa);
	if err1 != nil {
		raddr = "invalid-address";
	}
	if nfd, err = newFD(s, fd.net, fd.laddr, raddr); err != nil {
		syscall.Close(s);
		return nil, err
	}
	return nfd, nil
}

<|endoftext|>


<commit_before>// Copyright 2013 Google Inc.  All rights reserved.
// Copyright 2016 the gousb Authors.  All rights reserved.
//
// 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 gousb

// #include <libusb.h>
import "C"
import "strconv"

// Class represents a USB-IF (Implementers Forum) class or subclass code.
type Class uint8

// Standard classes defined by USB spec.
const (
	ClassPerInterface Class = C.LIBUSB_CLASS_PER_INTERFACE
	ClassAudio        Class = C.LIBUSB_CLASS_AUDIO
	ClassComm         Class = C.LIBUSB_CLASS_COMM
	ClassHID          Class = C.LIBUSB_CLASS_HID
	ClassPrinter      Class = C.LIBUSB_CLASS_PRINTER
	ClassPTP          Class = C.LIBUSB_CLASS_PTP
	ClassMassStorage  Class = C.LIBUSB_CLASS_MASS_STORAGE
	ClassHub          Class = C.LIBUSB_CLASS_HUB
	ClassData         Class = C.LIBUSB_CLASS_DATA
	ClassWireless     Class = C.LIBUSB_CLASS_WIRELESS
	ClassApplication  Class = C.LIBUSB_CLASS_APPLICATION
	ClassVendorSpec   Class = C.LIBUSB_CLASS_VENDOR_SPEC
)

var classDescription = map[Class]string{
	ClassPerInterface: "per-interface",
	ClassAudio:        "audio",
	ClassComm:         "communications",
	ClassHID:          "human interface device",
	ClassPrinter:      "printer dclass",
	ClassPTP:          "picture transfer protocol",
	ClassMassStorage:  "mass storage",
	ClassHub:          "hub",
	ClassData:         "data",
	ClassWireless:     "wireless",
	ClassApplication:  "application",
	ClassVendorSpec:   "vendor-specific",
}

func (c Class) String() string {
	if d, ok := classDescription[c]; ok {
		return d
	}
	return strconv.Itoa(int(c))
}

// Protocol is the interface class protocol, qualified by the values
// of interface class and subclass.
type Protocol uint8

func (p Protocol) String() string {
	return strconv.Itoa(int(p))
}

// DescriptorType identifies the type of a USB descriptor.
type DescriptorType uint8

// Descriptor types defined by the USB spec.
const (
	DescriptorTypeDevice    DescriptorType = C.LIBUSB_DT_DEVICE
	DescriptorTypeConfig    DescriptorType = C.LIBUSB_DT_CONFIG
	DescriptorTypeString    DescriptorType = C.LIBUSB_DT_STRING
	DescriptorTypeInterface DescriptorType = C.LIBUSB_DT_INTERFACE
	DescriptorTypeEndpoint  DescriptorType = C.LIBUSB_DT_ENDPOINT
	DescriptorTypeHID       DescriptorType = C.LIBUSB_DT_HID
	DescriptorTypeReport    DescriptorType = C.LIBUSB_DT_REPORT
	DescriptorTypePhysical  DescriptorType = C.LIBUSB_DT_PHYSICAL
	DescriptorTypeHub       DescriptorType = C.LIBUSB_DT_HUB
)

var descriptorTypeDescription = map[DescriptorType]string{
	DescriptorTypeDevice:    "device",
	DescriptorTypeConfig:    "configuration",
	DescriptorTypeString:    "string",
	DescriptorTypeInterface: "interface",
	DescriptorTypeEndpoint:  "endpoint",
	DescriptorTypeHID:       "HID",
	DescriptorTypeReport:    "HID report",
	DescriptorTypePhysical:  "physical",
	DescriptorTypeHub:       "hub",
}

func (dt DescriptorType) String() string {
	return descriptorTypeDescription[dt]
}

// EndpointDirection defines the direction of data flow - IN (device to host)
// or OUT (host to device).
type EndpointDirection bool

const (
	endpointNumMask       = 0x0f
	endpointDirectionMask = 0x80
	// EndpointDirectionIn marks data flowing from device to host.
	EndpointDirectionIn EndpointDirection = true
	// EndpointDirectionOut marks data flowing from host to device.
	EndpointDirectionOut EndpointDirection = false
)

var endpointDirectionDescription = map[EndpointDirection]string{
	EndpointDirectionIn:  "IN",
	EndpointDirectionOut: "OUT",
}

func (ed EndpointDirection) String() string {
	return endpointDirectionDescription[ed]
}

// TransferType defines the endpoint transfer type.
type TransferType uint8

// Transfer types defined by the USB spec.
const (
	TransferTypeControl     TransferType = C.LIBUSB_TRANSFER_TYPE_CONTROL
	TransferTypeIsochronous TransferType = C.LIBUSB_TRANSFER_TYPE_ISOCHRONOUS
	TransferTypeBulk        TransferType = C.LIBUSB_TRANSFER_TYPE_BULK
	TransferTypeInterrupt   TransferType = C.LIBUSB_TRANSFER_TYPE_INTERRUPT
	transferTypeMask                     = 0x03
)

var transferTypeDescription = map[TransferType]string{
	TransferTypeControl:     "control",
	TransferTypeIsochronous: "isochronous",
	TransferTypeBulk:        "bulk",
	TransferTypeInterrupt:   "interrupt",
}

// String returns a human-readable name of the endpoint transfer type.
func (tt TransferType) String() string {
	return transferTypeDescription[tt]
}

// IsoSyncType defines the isochronous transfer synchronization type.
type IsoSyncType uint8

// Synchronization types defined by the USB spec.
const (
	IsoSyncTypeNone     IsoSyncType = C.LIBUSB_ISO_SYNC_TYPE_NONE << 2
	IsoSyncTypeAsync    IsoSyncType = C.LIBUSB_ISO_SYNC_TYPE_ASYNC << 2
	IsoSyncTypeAdaptive IsoSyncType = C.LIBUSB_ISO_SYNC_TYPE_ADAPTIVE << 2
	IsoSyncTypeSync     IsoSyncType = C.LIBUSB_ISO_SYNC_TYPE_SYNC << 2
	isoSyncTypeMask                 = 0x0C
)

var isoSyncTypeDescription = map[IsoSyncType]string{
	IsoSyncTypeNone:     "unsynchronized",
	IsoSyncTypeAsync:    "asynchronous",
	IsoSyncTypeAdaptive: "adaptive",
	IsoSyncTypeSync:     "synchronous",
}

// String returns a human-readable description of the synchronization type.
func (ist IsoSyncType) String() string {
	return isoSyncTypeDescription[ist]
}

// UsageType defines the transfer usage type for isochronous and interrupt
// transfers.
type UsageType uint8

// Usage types for iso and interrupt transfers, defined by the USB spec.
const (
	// Note: USB3.0 defines usage type for both isochronous and interrupt
	// endpoints, with the same constants representing different usage types.
	// UsageType constants do not correspond to bmAttribute values.
	UsageTypeUndefined UsageType = iota
	IsoUsageTypeData
	IsoUsageTypeFeedback
	IsoUsageTypeImplicit
	InterruptUsageTypePeriodic
	InterruptUsageTypeNotification
	usageTypeMask = 0x30
)

var usageTypeDescription = map[UsageType]string{
	UsageTypeUndefined:             "undefined usage",
	IsoUsageTypeData:               "data",
	IsoUsageTypeFeedback:           "feedback",
	IsoUsageTypeImplicit:           "implicit data",
	InterruptUsageTypePeriodic:     "periodic",
	InterruptUsageTypeNotification: "notification",
}

func (ut UsageType) String() string {
	return usageTypeDescription[ut]
}

// RequestType identifies a control transfer request type.
type RequestType uint8

// Control request types defined in the USB spec.
const (
	RequestTypeStandard = C.LIBUSB_REQUEST_TYPE_STANDARD
	RequestTypeClass    = C.LIBUSB_REQUEST_TYPE_CLASS
	RequestTypeVendor   = C.LIBUSB_REQUEST_TYPE_VENDOR
	RequestTypeReserved = C.LIBUSB_REQUEST_TYPE_RESERVED
)

var requestTypeDescription = map[RequestType]string{
	RequestTypeStandard: "standard",
	RequestTypeClass:    "class",
	RequestTypeVendor:   "vendor",
	RequestTypeReserved: "reserved",
}

// String returns a human-readable name of the control transfer request type.
func (rt RequestType) String() string {
	return requestTypeDescription[rt]
}

// Speed identifies the speed of the device.
type Speed int

// Device speeds as defined in the USB spec.
const (
	SpeedUnknown Speed = C.LIBUSB_SPEED_UNKNOWN
	SpeedLow     Speed = C.LIBUSB_SPEED_LOW
	SpeedFull    Speed = C.LIBUSB_SPEED_FULL
	SpeedHigh    Speed = C.LIBUSB_SPEED_HIGH
	SpeedSuper   Speed = C.LIBUSB_SPEED_SUPER
)

var deviceSpeedDescription = map[Speed]string{
	SpeedUnknown: "unknown",
	SpeedLow:     "low",
	SpeedFull:    "full",
	SpeedHigh:    "high",
	SpeedSuper:   "super",
}

// String returns a human-readable name of the device speed.
func (s Speed) String() string {
	return deviceSpeedDescription[s]
}

const (
	selfPoweredMask  = 0x40
	remoteWakeupMask = 0x20
)

// Milliamperes is a unit of electric current consumption.
type Milliamperes uint
<commit_msg>Redefine constants around control request types. (#34)<commit_after>// Copyright 2013 Google Inc.  All rights reserved.
// Copyright 2016 the gousb Authors.  All rights reserved.
//
// 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 gousb

// #include <libusb.h>
import "C"
import "strconv"

// Class represents a USB-IF (Implementers Forum) class or subclass code.
type Class uint8

// Standard classes defined by USB spec.
const (
	ClassPerInterface Class = C.LIBUSB_CLASS_PER_INTERFACE
	ClassAudio        Class = C.LIBUSB_CLASS_AUDIO
	ClassComm         Class = C.LIBUSB_CLASS_COMM
	ClassHID          Class = C.LIBUSB_CLASS_HID
	ClassPrinter      Class = C.LIBUSB_CLASS_PRINTER
	ClassPTP          Class = C.LIBUSB_CLASS_PTP
	ClassMassStorage  Class = C.LIBUSB_CLASS_MASS_STORAGE
	ClassHub          Class = C.LIBUSB_CLASS_HUB
	ClassData         Class = C.LIBUSB_CLASS_DATA
	ClassWireless     Class = C.LIBUSB_CLASS_WIRELESS
	ClassApplication  Class = C.LIBUSB_CLASS_APPLICATION
	ClassVendorSpec   Class = C.LIBUSB_CLASS_VENDOR_SPEC
)

var classDescription = map[Class]string{
	ClassPerInterface: "per-interface",
	ClassAudio:        "audio",
	ClassComm:         "communications",
	ClassHID:          "human interface device",
	ClassPrinter:      "printer dclass",
	ClassPTP:          "picture transfer protocol",
	ClassMassStorage:  "mass storage",
	ClassHub:          "hub",
	ClassData:         "data",
	ClassWireless:     "wireless",
	ClassApplication:  "application",
	ClassVendorSpec:   "vendor-specific",
}

func (c Class) String() string {
	if d, ok := classDescription[c]; ok {
		return d
	}
	return strconv.Itoa(int(c))
}

// Protocol is the interface class protocol, qualified by the values
// of interface class and subclass.
type Protocol uint8

func (p Protocol) String() string {
	return strconv.Itoa(int(p))
}

// DescriptorType identifies the type of a USB descriptor.
type DescriptorType uint8

// Descriptor types defined by the USB spec.
const (
	DescriptorTypeDevice    DescriptorType = C.LIBUSB_DT_DEVICE
	DescriptorTypeConfig    DescriptorType = C.LIBUSB_DT_CONFIG
	DescriptorTypeString    DescriptorType = C.LIBUSB_DT_STRING
	DescriptorTypeInterface DescriptorType = C.LIBUSB_DT_INTERFACE
	DescriptorTypeEndpoint  DescriptorType = C.LIBUSB_DT_ENDPOINT
	DescriptorTypeHID       DescriptorType = C.LIBUSB_DT_HID
	DescriptorTypeReport    DescriptorType = C.LIBUSB_DT_REPORT
	DescriptorTypePhysical  DescriptorType = C.LIBUSB_DT_PHYSICAL
	DescriptorTypeHub       DescriptorType = C.LIBUSB_DT_HUB
)

var descriptorTypeDescription = map[DescriptorType]string{
	DescriptorTypeDevice:    "device",
	DescriptorTypeConfig:    "configuration",
	DescriptorTypeString:    "string",
	DescriptorTypeInterface: "interface",
	DescriptorTypeEndpoint:  "endpoint",
	DescriptorTypeHID:       "HID",
	DescriptorTypeReport:    "HID report",
	DescriptorTypePhysical:  "physical",
	DescriptorTypeHub:       "hub",
}

func (dt DescriptorType) String() string {
	return descriptorTypeDescription[dt]
}

// EndpointDirection defines the direction of data flow - IN (device to host)
// or OUT (host to device).
type EndpointDirection bool

const (
	endpointNumMask       = 0x0f
	endpointDirectionMask = 0x80
	// EndpointDirectionIn marks data flowing from device to host.
	EndpointDirectionIn EndpointDirection = true
	// EndpointDirectionOut marks data flowing from host to device.
	EndpointDirectionOut EndpointDirection = false
)

var endpointDirectionDescription = map[EndpointDirection]string{
	EndpointDirectionIn:  "IN",
	EndpointDirectionOut: "OUT",
}

func (ed EndpointDirection) String() string {
	return endpointDirectionDescription[ed]
}

// TransferType defines the endpoint transfer type.
type TransferType uint8

// Transfer types defined by the USB spec.
const (
	TransferTypeControl     TransferType = C.LIBUSB_TRANSFER_TYPE_CONTROL
	TransferTypeIsochronous TransferType = C.LIBUSB_TRANSFER_TYPE_ISOCHRONOUS
	TransferTypeBulk        TransferType = C.LIBUSB_TRANSFER_TYPE_BULK
	TransferTypeInterrupt   TransferType = C.LIBUSB_TRANSFER_TYPE_INTERRUPT
	transferTypeMask                     = 0x03
)

var transferTypeDescription = map[TransferType]string{
	TransferTypeControl:     "control",
	TransferTypeIsochronous: "isochronous",
	TransferTypeBulk:        "bulk",
	TransferTypeInterrupt:   "interrupt",
}

// String returns a human-readable name of the endpoint transfer type.
func (tt TransferType) String() string {
	return transferTypeDescription[tt]
}

// IsoSyncType defines the isochronous transfer synchronization type.
type IsoSyncType uint8

// Synchronization types defined by the USB spec.
const (
	IsoSyncTypeNone     IsoSyncType = C.LIBUSB_ISO_SYNC_TYPE_NONE << 2
	IsoSyncTypeAsync    IsoSyncType = C.LIBUSB_ISO_SYNC_TYPE_ASYNC << 2
	IsoSyncTypeAdaptive IsoSyncType = C.LIBUSB_ISO_SYNC_TYPE_ADAPTIVE << 2
	IsoSyncTypeSync     IsoSyncType = C.LIBUSB_ISO_SYNC_TYPE_SYNC << 2
	isoSyncTypeMask                 = 0x0C
)

var isoSyncTypeDescription = map[IsoSyncType]string{
	IsoSyncTypeNone:     "unsynchronized",
	IsoSyncTypeAsync:    "asynchronous",
	IsoSyncTypeAdaptive: "adaptive",
	IsoSyncTypeSync:     "synchronous",
}

// String returns a human-readable description of the synchronization type.
func (ist IsoSyncType) String() string {
	return isoSyncTypeDescription[ist]
}

// UsageType defines the transfer usage type for isochronous and interrupt
// transfers.
type UsageType uint8

// Usage types for iso and interrupt transfers, defined by the USB spec.
const (
	// Note: USB3.0 defines usage type for both isochronous and interrupt
	// endpoints, with the same constants representing different usage types.
	// UsageType constants do not correspond to bmAttribute values.
	UsageTypeUndefined UsageType = iota
	IsoUsageTypeData
	IsoUsageTypeFeedback
	IsoUsageTypeImplicit
	InterruptUsageTypePeriodic
	InterruptUsageTypeNotification
	usageTypeMask = 0x30
)

var usageTypeDescription = map[UsageType]string{
	UsageTypeUndefined:             "undefined usage",
	IsoUsageTypeData:               "data",
	IsoUsageTypeFeedback:           "feedback",
	IsoUsageTypeImplicit:           "implicit data",
	InterruptUsageTypePeriodic:     "periodic",
	InterruptUsageTypeNotification: "notification",
}

func (ut UsageType) String() string {
	return usageTypeDescription[ut]
}

// Control request type bit fields as defined in the USB spec. All values are
// of uint8 type.  These constants can be used with Device.Control() method to
// specify the type and destination of the control request, e.g.
// `dev.Control(ControlOut|ControlVendor|ControlDevice, ...)`.
const (
	ControlIn  = C.LIBUSB_ENDPOINT_IN
	ControlOut = C.LIBUSB_ENDPOINT_OUT

	// "Standard" is explicitly omitted, as functionality of standard requests
	// is exposed through higher level operations of gousb.
	ControlClass  = C.LIBUSB_REQUEST_TYPE_CLASS
	ControlVendor = C.LIBUSB_REQUEST_TYPE_VENDOR
	// "Reserved" is explicitly omitted, should not be used.

	ControlDevice    = C.LIBUSB_RECIPIENT_DEVICE
	ControlInterface = C.LIBUSB_RECIPIENT_INTERFACE
	ControlEndpoint  = C.LIBUSB_RECIPIENT_ENDPOINT
	ControlOther     = C.LIBUSB_RECIPIENT_OTHER
)

// Speed identifies the speed of the device.
type Speed int

// Device speeds as defined in the USB spec.
const (
	SpeedUnknown Speed = C.LIBUSB_SPEED_UNKNOWN
	SpeedLow     Speed = C.LIBUSB_SPEED_LOW
	SpeedFull    Speed = C.LIBUSB_SPEED_FULL
	SpeedHigh    Speed = C.LIBUSB_SPEED_HIGH
	SpeedSuper   Speed = C.LIBUSB_SPEED_SUPER
)

var deviceSpeedDescription = map[Speed]string{
	SpeedUnknown: "unknown",
	SpeedLow:     "low",
	SpeedFull:    "full",
	SpeedHigh:    "high",
	SpeedSuper:   "super",
}

// String returns a human-readable name of the device speed.
func (s Speed) String() string {
	return deviceSpeedDescription[s]
}

const (
	selfPoweredMask  = 0x40
	remoteWakeupMask = 0x20
)

// Milliamperes is a unit of electric current consumption.
type Milliamperes uint
<|endoftext|>


<commit_before>package wca

const (
	DEVICE_STATE_ACTIVE     = 0x00000001
	DEVICE_STATE_DISABLED   = 0x00000002
	DEVICE_STATE_NOTPRESENT = 0x00000004
	DEVICE_STATE_UNPLUGGED  = 0x00000008
	DEVICE_STATEMASK_ALL    = 0x0000000F
)

const (
	ERender              = 0x0
	ECapture             = 0x1
	EAll                 = 0x2
	EDataFlow_enum_count = 0x3
)

const (
	STGM_READ       = 0x0
	STGM_WRITE      = 0x1
	STGM_READ_WRITE = 0x2
)

const (
	CLSCTX_INPROC_SERVER          = 0x1
	CLSCTX_INPROC_HANDLER         = 0x2
	CLSCTX_LOCAL_SERVER           = 0x4
	CLSCTX_INPROC_SERVER16        = 0x8
	CLSCTX_REMOTE_SERVER          = 0x10
	CLSCTX_INPROC_HANDLER16       = 0x20
	CLSCTX_RESERVED1              = 0x40
	CLSCTX_RESERVED2              = 0x80
	CLSCTX_RESERVED3              = 0x100
	CLSCTX_RESERVED4              = 0x200
	CLSCTX_NO_CODE_DOWNLOAD       = 0x400
	CLSCTX_RESERVED5              = 0x800
	CLSCTX_NO_CUSTOM_MARSHAL      = 0x1000
	CLSCTX_ENABLE_CODE_DOWNLOAD   = 0x2000
	CLSCTX_NO_FAILURE_LOG         = 0x4000
	CLSCTX_DISABLE_AAA            = 0x8000
	CLSCTX_ENABLE_AAA             = 0x10000
	CLSCTX_FROM_DEFAULT_CONTEXT   = 0x20000
	CLSCTX_ACTIVATE_32_BIT_SERVER = 0x40000
	CLSCTX_ACTIVATE_64_BIT_SERVER = 0x80000
	CLSCTX_ENABLE_CLOAKING        = 0x100000
	CLSCTX_APPCONTAINER           = 0x400000
	CLSCTX_ACTIVATE_AAA_AS_IU     = 0x800000
	CLSCTX_PS_DLL                 = 0x80000000
)
<commit_msg>Add constants<commit_after>package wca

const (
	ENDPOINT_SYSFX_ENABLED  = 0x00000000
	ENDPOINT_SYSFX_DISABLED = 0x00000001
)

const (
	DEVICE_STATE_ACTIVE     = 0x00000001
	DEVICE_STATE_DISABLED   = 0x00000002
	DEVICE_STATE_NOTPRESENT = 0x00000004
	DEVICE_STATE_UNPLUGGED  = 0x00000008
	DEVICE_STATEMASK_ALL    = 0x0000000F
)

const (
	ERender              = 0x0
	ECapture             = 0x1
	EAll                 = 0x2
	EDataFlow_enum_count = 0x3
)

const (
	STGM_READ       = 0x0
	STGM_WRITE      = 0x1
	STGM_READ_WRITE = 0x2
)

const (
	CLSCTX_INPROC_SERVER          = 0x1
	CLSCTX_INPROC_HANDLER         = 0x2
	CLSCTX_LOCAL_SERVER           = 0x4
	CLSCTX_INPROC_SERVER16        = 0x8
	CLSCTX_REMOTE_SERVER          = 0x10
	CLSCTX_INPROC_HANDLER16       = 0x20
	CLSCTX_RESERVED1              = 0x40
	CLSCTX_RESERVED2              = 0x80
	CLSCTX_RESERVED3              = 0x100
	CLSCTX_RESERVED4              = 0x200
	CLSCTX_NO_CODE_DOWNLOAD       = 0x400
	CLSCTX_RESERVED5              = 0x800
	CLSCTX_NO_CUSTOM_MARSHAL      = 0x1000
	CLSCTX_ENABLE_CODE_DOWNLOAD   = 0x2000
	CLSCTX_NO_FAILURE_LOG         = 0x4000
	CLSCTX_DISABLE_AAA            = 0x8000
	CLSCTX_ENABLE_AAA             = 0x10000
	CLSCTX_FROM_DEFAULT_CONTEXT   = 0x20000
	CLSCTX_ACTIVATE_32_BIT_SERVER = 0x40000
	CLSCTX_ACTIVATE_64_BIT_SERVER = 0x80000
	CLSCTX_ENABLE_CLOAKING        = 0x100000
	CLSCTX_APPCONTAINER           = 0x400000
	CLSCTX_ACTIVATE_AAA_AS_IU     = 0x800000
	CLSCTX_PS_DLL                 = 0x80000000
)
<|endoftext|>


<commit_before>// Copyright 2013 Google Inc.  All rights reserved.
// Copyright 2016 the gousb Authors.  All rights reserved.
//
// 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 gousb

// #include <libusb.h>
import "C"
import "strconv"

// Class represents a USB-IF (Implementers Forum) class or subclass code.
type Class uint8

// Standard classes defined by USB spec.
const (
	ClassPerInterface Class = C.LIBUSB_CLASS_PER_INTERFACE
	ClassAudio        Class = C.LIBUSB_CLASS_AUDIO
	ClassComm         Class = C.LIBUSB_CLASS_COMM
	ClassHID          Class = C.LIBUSB_CLASS_HID
	ClassPrinter      Class = C.LIBUSB_CLASS_PRINTER
	ClassPTP          Class = C.LIBUSB_CLASS_PTP
	ClassMassStorage  Class = C.LIBUSB_CLASS_MASS_STORAGE
	ClassHub          Class = C.LIBUSB_CLASS_HUB
	ClassData         Class = C.LIBUSB_CLASS_DATA
	ClassWireless     Class = C.LIBUSB_CLASS_WIRELESS
	ClassApplication  Class = C.LIBUSB_CLASS_APPLICATION
	ClassVendorSpec   Class = C.LIBUSB_CLASS_VENDOR_SPEC
)

var classDescription = map[Class]string{
	ClassPerInterface: "per-interface",
	ClassAudio:        "audio",
	ClassComm:         "communications",
	ClassHID:          "human interface device",
	ClassPrinter:      "printer dclass",
	ClassPTP:          "picture transfer protocol",
	ClassMassStorage:  "mass storage",
	ClassHub:          "hub",
	ClassData:         "data",
	ClassWireless:     "wireless",
	ClassApplication:  "application",
	ClassVendorSpec:   "vendor-specific",
}

func (c Class) String() string {
	if d, ok := classDescription[c]; ok {
		return d
	}
	return strconv.Itoa(int(c))
}

// Protocol is the interface class protocol, qualified by the values
// of interface class and subclass.
type Protocol uint8

func (p Protocol) String() string {
	return strconv.Itoa(int(p))
}

// DescriptorType identifies the type of a USB descriptor.
type DescriptorType uint8

// Descriptor types defined by the USB spec.
const (
	DescriptorTypeDevice    DescriptorType = C.LIBUSB_DT_DEVICE
	DescriptorTypeConfig    DescriptorType = C.LIBUSB_DT_CONFIG
	DescriptorTypeString    DescriptorType = C.LIBUSB_DT_STRING
	DescriptorTypeInterface DescriptorType = C.LIBUSB_DT_INTERFACE
	DescriptorTypeEndpoint  DescriptorType = C.LIBUSB_DT_ENDPOINT
	DescriptorTypeHID       DescriptorType = C.LIBUSB_DT_HID
	DescriptorTypeReport    DescriptorType = C.LIBUSB_DT_REPORT
	DescriptorTypePhysical  DescriptorType = C.LIBUSB_DT_PHYSICAL
	DescriptorTypeHub       DescriptorType = C.LIBUSB_DT_HUB
)

var descriptorTypeDescription = map[DescriptorType]string{
	DescriptorTypeDevice:    "device",
	DescriptorTypeConfig:    "configuration",
	DescriptorTypeString:    "string",
	DescriptorTypeInterface: "interface",
	DescriptorTypeEndpoint:  "endpoint",
	DescriptorTypeHID:       "HID",
	DescriptorTypeReport:    "HID report",
	DescriptorTypePhysical:  "physical",
	DescriptorTypeHub:       "hub",
}

func (dt DescriptorType) String() string {
	return descriptorTypeDescription[dt]
}

// EndpointDirection defines the direction of data flow - IN (device to host)
// or OUT (host to device).
type EndpointDirection bool

const (
	endpointNumMask       = 0x0f
	endpointDirectionMask = 0x80
	// EndpointDirectionIn marks data flowing from device to host.
	EndpointDirectionIn EndpointDirection = true
	// EndpointDirectionOut marks data flowing from host to device.
	EndpointDirectionOut EndpointDirection = false
)

var endpointDirectionDescription = map[EndpointDirection]string{
	EndpointDirectionIn:  "IN",
	EndpointDirectionOut: "OUT",
}

func (ed EndpointDirection) String() string {
	return endpointDirectionDescription[ed]
}

// TransferType defines the endpoint transfer type.
type TransferType uint8

// Transfer types defined by the USB spec.
const (
	TransferTypeControl     TransferType = C.LIBUSB_TRANSFER_TYPE_CONTROL
	TransferTypeIsochronous TransferType = C.LIBUSB_TRANSFER_TYPE_ISOCHRONOUS
	TransferTypeBulk        TransferType = C.LIBUSB_TRANSFER_TYPE_BULK
	TransferTypeInterrupt   TransferType = C.LIBUSB_TRANSFER_TYPE_INTERRUPT
	transferTypeMask                     = 0x03
)

var transferTypeDescription = map[TransferType]string{
	TransferTypeControl:     "control",
	TransferTypeIsochronous: "isochronous",
	TransferTypeBulk:        "bulk",
	TransferTypeInterrupt:   "interrupt",
}

// String returns a human-readable name of the endpoint transfer type.
func (tt TransferType) String() string {
	return transferTypeDescription[tt]
}

// IsoSyncType defines the isochronous transfer synchronization type.
type IsoSyncType uint8

// Synchronization types defined by the USB spec.
const (
	IsoSyncTypeNone     IsoSyncType = C.LIBUSB_ISO_SYNC_TYPE_NONE << 2
	IsoSyncTypeAsync    IsoSyncType = C.LIBUSB_ISO_SYNC_TYPE_ASYNC << 2
	IsoSyncTypeAdaptive IsoSyncType = C.LIBUSB_ISO_SYNC_TYPE_ADAPTIVE << 2
	IsoSyncTypeSync     IsoSyncType = C.LIBUSB_ISO_SYNC_TYPE_SYNC << 2
	isoSyncTypeMask                 = 0x0C
)

var isoSyncTypeDescription = map[IsoSyncType]string{
	IsoSyncTypeNone:     "unsynchronized",
	IsoSyncTypeAsync:    "asynchronous",
	IsoSyncTypeAdaptive: "adaptive",
	IsoSyncTypeSync:     "synchronous",
}

// String returns a human-readable description of the synchronization type.
func (ist IsoSyncType) String() string {
	return isoSyncTypeDescription[ist]
}

// UsageType defines the transfer usage type for isochronous and interrupt
// transfers.
type UsageType uint8

// Usage types for iso and interrupt transfers, defined by the USB spec.
const (
	// Note: USB3.0 defines usage type for both isochronous and interrupt
	// endpoints, with the same constants representing different usage types.
	// UsageType constants do not correspond to bmAttribute values.
	UsageTypeUndefined UsageType = iota
	IsoUsageTypeData
	IsoUsageTypeFeedback
	IsoUsageTypeImplicit
	InterruptUsageTypePeriodic
	InterruptUsageTypeNotification
	usageTypeMask = 0x30
)

var usageTypeDescription = map[UsageType]string{
	UsageTypeUndefined:             "undefined usage",
	IsoUsageTypeData:               "data",
	IsoUsageTypeFeedback:           "feedback",
	IsoUsageTypeImplicit:           "implicit data",
	InterruptUsageTypePeriodic:     "periodic",
	InterruptUsageTypeNotification: "notification",
}

func (ut UsageType) String() string {
	return usageTypeDescription[ut]
}

// Control request type bit fields as defined in the USB spec. All values are
// of uint8 type.  These constants can be used with Device.Control() method to
// specify the type and destination of the control request, e.g.
// `dev.Control(ControlOut|ControlVendor|ControlDevice, ...)`.
const (
	ControlIn  = C.LIBUSB_ENDPOINT_IN
	ControlOut = C.LIBUSB_ENDPOINT_OUT

	// "Standard" is explicitly omitted, as functionality of standard requests
	// is exposed through higher level operations of gousb.
	ControlClass  = C.LIBUSB_REQUEST_TYPE_CLASS
	ControlVendor = C.LIBUSB_REQUEST_TYPE_VENDOR
	// "Reserved" is explicitly omitted, should not be used.

	ControlDevice    = C.LIBUSB_RECIPIENT_DEVICE
	ControlInterface = C.LIBUSB_RECIPIENT_INTERFACE
	ControlEndpoint  = C.LIBUSB_RECIPIENT_ENDPOINT
	ControlOther     = C.LIBUSB_RECIPIENT_OTHER
)

// Speed identifies the speed of the device.
type Speed int

// Device speeds as defined in the USB spec.
const (
	SpeedUnknown Speed = C.LIBUSB_SPEED_UNKNOWN
	SpeedLow     Speed = C.LIBUSB_SPEED_LOW
	SpeedFull    Speed = C.LIBUSB_SPEED_FULL
	SpeedHigh    Speed = C.LIBUSB_SPEED_HIGH
	SpeedSuper   Speed = C.LIBUSB_SPEED_SUPER
)

var deviceSpeedDescription = map[Speed]string{
	SpeedUnknown: "unknown",
	SpeedLow:     "low",
	SpeedFull:    "full",
	SpeedHigh:    "high",
	SpeedSuper:   "super",
}

// String returns a human-readable name of the device speed.
func (s Speed) String() string {
	return deviceSpeedDescription[s]
}

const (
	selfPoweredMask  = 0x40
	remoteWakeupMask = 0x20
)

// Milliamperes is a unit of electric current consumption.
type Milliamperes uint
<commit_msg>Add more device classes, based on libusb.h enumeration. (#51)<commit_after>// Copyright 2013 Google Inc.  All rights reserved.
// Copyright 2016 the gousb Authors.  All rights reserved.
//
// 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 gousb

// #include <libusb.h>
import "C"
import "strconv"

// Class represents a USB-IF (Implementers Forum) class or subclass code.
type Class uint8

// Standard classes defined by USB spec.
const (
	ClassPerInterface       Class = C.LIBUSB_CLASS_PER_INTERFACE
	ClassAudio              Class = C.LIBUSB_CLASS_AUDIO
	ClassComm               Class = C.LIBUSB_CLASS_COMM
	ClassHID                Class = C.LIBUSB_CLASS_HID
	ClassPhysical           Class = C.LIBUSB_CLASS_PHYSICAL
	ClassPrinter            Class = C.LIBUSB_CLASS_PRINTER
	ClassPTP                Class = C.LIBUSB_CLASS_PTP
	ClassMassStorage        Class = C.LIBUSB_CLASS_MASS_STORAGE
	ClassHub                Class = C.LIBUSB_CLASS_HUB
	ClassData               Class = C.LIBUSB_CLASS_DATA
	ClassSmartCard          Class = C.LIBUSB_CLASS_SMART_CARD
	ClassContentSecurity    Class = C.LIBUSB_CLASS_CONTENT_SECURITY
	ClassVideo              Class = C.LIBUSB_CLASS_VIDEO
	ClassPersonalHealthcare Class = C.LIBUSB_CLASS_PERSONAL_HEALTHCARE
	ClassDiagnosticDevice   Class = C.LIBUSB_CLASS_DIAGNOSTIC_DEVICE
	ClassWireless           Class = C.LIBUSB_CLASS_WIRELESS
	ClassApplication        Class = C.LIBUSB_CLASS_APPLICATION
	ClassVendorSpec         Class = C.LIBUSB_CLASS_VENDOR_SPEC
)

var classDescription = map[Class]string{
	ClassPerInterface:       "per-interface",
	ClassAudio:              "audio",
	ClassComm:               "communications",
	ClassHID:                "human interface device",
	ClassPhysical:           "physical",
	ClassPrinter:            "printer",
	ClassPTP:                "picture transfer protocol",
	ClassMassStorage:        "mass storage",
	ClassHub:                "hub",
	ClassData:               "data",
	ClassSmartCard:          "smart card",
	ClassContentSecurity:    "content security",
	ClassVideo:              "video",
	ClassPersonalHealthcare: "personal healthcare",
	ClassDiagnosticDevice:   "diagnostic device",
	ClassWireless:           "wireless",
	ClassApplication:        "application",
	ClassVendorSpec:         "vendor-specific",
}

func (c Class) String() string {
	if d, ok := classDescription[c]; ok {
		return d
	}
	return strconv.Itoa(int(c))
}

// Protocol is the interface class protocol, qualified by the values
// of interface class and subclass.
type Protocol uint8

func (p Protocol) String() string {
	return strconv.Itoa(int(p))
}

// DescriptorType identifies the type of a USB descriptor.
type DescriptorType uint8

// Descriptor types defined by the USB spec.
const (
	DescriptorTypeDevice    DescriptorType = C.LIBUSB_DT_DEVICE
	DescriptorTypeConfig    DescriptorType = C.LIBUSB_DT_CONFIG
	DescriptorTypeString    DescriptorType = C.LIBUSB_DT_STRING
	DescriptorTypeInterface DescriptorType = C.LIBUSB_DT_INTERFACE
	DescriptorTypeEndpoint  DescriptorType = C.LIBUSB_DT_ENDPOINT
	DescriptorTypeHID       DescriptorType = C.LIBUSB_DT_HID
	DescriptorTypeReport    DescriptorType = C.LIBUSB_DT_REPORT
	DescriptorTypePhysical  DescriptorType = C.LIBUSB_DT_PHYSICAL
	DescriptorTypeHub       DescriptorType = C.LIBUSB_DT_HUB
)

var descriptorTypeDescription = map[DescriptorType]string{
	DescriptorTypeDevice:    "device",
	DescriptorTypeConfig:    "configuration",
	DescriptorTypeString:    "string",
	DescriptorTypeInterface: "interface",
	DescriptorTypeEndpoint:  "endpoint",
	DescriptorTypeHID:       "HID",
	DescriptorTypeReport:    "HID report",
	DescriptorTypePhysical:  "physical",
	DescriptorTypeHub:       "hub",
}

func (dt DescriptorType) String() string {
	return descriptorTypeDescription[dt]
}

// EndpointDirection defines the direction of data flow - IN (device to host)
// or OUT (host to device).
type EndpointDirection bool

const (
	endpointNumMask       = 0x0f
	endpointDirectionMask = 0x80
	// EndpointDirectionIn marks data flowing from device to host.
	EndpointDirectionIn EndpointDirection = true
	// EndpointDirectionOut marks data flowing from host to device.
	EndpointDirectionOut EndpointDirection = false
)

var endpointDirectionDescription = map[EndpointDirection]string{
	EndpointDirectionIn:  "IN",
	EndpointDirectionOut: "OUT",
}

func (ed EndpointDirection) String() string {
	return endpointDirectionDescription[ed]
}

// TransferType defines the endpoint transfer type.
type TransferType uint8

// Transfer types defined by the USB spec.
const (
	TransferTypeControl     TransferType = C.LIBUSB_TRANSFER_TYPE_CONTROL
	TransferTypeIsochronous TransferType = C.LIBUSB_TRANSFER_TYPE_ISOCHRONOUS
	TransferTypeBulk        TransferType = C.LIBUSB_TRANSFER_TYPE_BULK
	TransferTypeInterrupt   TransferType = C.LIBUSB_TRANSFER_TYPE_INTERRUPT
	transferTypeMask                     = 0x03
)

var transferTypeDescription = map[TransferType]string{
	TransferTypeControl:     "control",
	TransferTypeIsochronous: "isochronous",
	TransferTypeBulk:        "bulk",
	TransferTypeInterrupt:   "interrupt",
}

// String returns a human-readable name of the endpoint transfer type.
func (tt TransferType) String() string {
	return transferTypeDescription[tt]
}

// IsoSyncType defines the isochronous transfer synchronization type.
type IsoSyncType uint8

// Synchronization types defined by the USB spec.
const (
	IsoSyncTypeNone     IsoSyncType = C.LIBUSB_ISO_SYNC_TYPE_NONE << 2
	IsoSyncTypeAsync    IsoSyncType = C.LIBUSB_ISO_SYNC_TYPE_ASYNC << 2
	IsoSyncTypeAdaptive IsoSyncType = C.LIBUSB_ISO_SYNC_TYPE_ADAPTIVE << 2
	IsoSyncTypeSync     IsoSyncType = C.LIBUSB_ISO_SYNC_TYPE_SYNC << 2
	isoSyncTypeMask                 = 0x0C
)

var isoSyncTypeDescription = map[IsoSyncType]string{
	IsoSyncTypeNone:     "unsynchronized",
	IsoSyncTypeAsync:    "asynchronous",
	IsoSyncTypeAdaptive: "adaptive",
	IsoSyncTypeSync:     "synchronous",
}

// String returns a human-readable description of the synchronization type.
func (ist IsoSyncType) String() string {
	return isoSyncTypeDescription[ist]
}

// UsageType defines the transfer usage type for isochronous and interrupt
// transfers.
type UsageType uint8

// Usage types for iso and interrupt transfers, defined by the USB spec.
const (
	// Note: USB3.0 defines usage type for both isochronous and interrupt
	// endpoints, with the same constants representing different usage types.
	// UsageType constants do not correspond to bmAttribute values.
	UsageTypeUndefined UsageType = iota
	IsoUsageTypeData
	IsoUsageTypeFeedback
	IsoUsageTypeImplicit
	InterruptUsageTypePeriodic
	InterruptUsageTypeNotification
	usageTypeMask = 0x30
)

var usageTypeDescription = map[UsageType]string{
	UsageTypeUndefined:             "undefined usage",
	IsoUsageTypeData:               "data",
	IsoUsageTypeFeedback:           "feedback",
	IsoUsageTypeImplicit:           "implicit data",
	InterruptUsageTypePeriodic:     "periodic",
	InterruptUsageTypeNotification: "notification",
}

func (ut UsageType) String() string {
	return usageTypeDescription[ut]
}

// Control request type bit fields as defined in the USB spec. All values are
// of uint8 type.  These constants can be used with Device.Control() method to
// specify the type and destination of the control request, e.g.
// `dev.Control(ControlOut|ControlVendor|ControlDevice, ...)`.
const (
	ControlIn  = C.LIBUSB_ENDPOINT_IN
	ControlOut = C.LIBUSB_ENDPOINT_OUT

	// "Standard" is explicitly omitted, as functionality of standard requests
	// is exposed through higher level operations of gousb.
	ControlClass  = C.LIBUSB_REQUEST_TYPE_CLASS
	ControlVendor = C.LIBUSB_REQUEST_TYPE_VENDOR
	// "Reserved" is explicitly omitted, should not be used.

	ControlDevice    = C.LIBUSB_RECIPIENT_DEVICE
	ControlInterface = C.LIBUSB_RECIPIENT_INTERFACE
	ControlEndpoint  = C.LIBUSB_RECIPIENT_ENDPOINT
	ControlOther     = C.LIBUSB_RECIPIENT_OTHER
)

// Speed identifies the speed of the device.
type Speed int

// Device speeds as defined in the USB spec.
const (
	SpeedUnknown Speed = C.LIBUSB_SPEED_UNKNOWN
	SpeedLow     Speed = C.LIBUSB_SPEED_LOW
	SpeedFull    Speed = C.LIBUSB_SPEED_FULL
	SpeedHigh    Speed = C.LIBUSB_SPEED_HIGH
	SpeedSuper   Speed = C.LIBUSB_SPEED_SUPER
)

var deviceSpeedDescription = map[Speed]string{
	SpeedUnknown: "unknown",
	SpeedLow:     "low",
	SpeedFull:    "full",
	SpeedHigh:    "high",
	SpeedSuper:   "super",
}

// String returns a human-readable name of the device speed.
func (s Speed) String() string {
	return deviceSpeedDescription[s]
}

const (
	selfPoweredMask  = 0x40
	remoteWakeupMask = 0x20
)

// Milliamperes is a unit of electric current consumption.
type Milliamperes uint
<|endoftext|>


<commit_before>/*
NOTE: The API is in flux and mainly not implemented. Proceed with caution until further notice.
*/
package libcontainer

type ContainerInfo interface {
	// Returns the ID of the container
	ID() string

	// Returns the current run state of the container.
	//
	// Errors:
	// ContainerDestroyed - Container no longer exists,
	// SystemError - System error.
	RunState() (*RunState, Error)

	// Returns the current config of the container.
	Config() *Config

	// Returns the PIDs inside this container. The PIDs are in the namespace of the calling process.
	//
	// Errors:
	// ContainerDestroyed - Container no longer exists,
	// SystemError - System error.
	//
	// Some of the returned PIDs may no longer refer to processes in the Container, unless
	// the Container state is PAUSED in which case every PID in the slice is valid.
	Processes() ([]int, Error)

	// Returns statistics for the container.
	//
	// Errors:
	// ContainerDestroyed - Container no longer exists,
	// SystemError - System error.
	Stats() (*ContainerStats, Error)
}

// A libcontainer container object.
//
// Each container is thread-safe within the same process. Since a container can
// be destroyed by a separate process, any function may return that the container
// was not found.
type Container interface {
	ContainerInfo

	// Start a process inside the container. Returns the PID of the new process (in the caller process's namespace) and a channel that will return the exit status of the process whenever it dies.
	//
	// Errors:
	// ContainerDestroyed - Container no longer exists,
	// ConfigInvalid - config is invalid,
	// ContainerPaused - Container is paused,
	// SystemError - System error.
	Start(config *ProcessConfig) (pid int, exitChan chan int, err Error)

	// Destroys the container after killing all running processes.
	//
	// Any event registrations are removed before the container is destroyed.
	// No error is returned if the container is already destroyed.
	//
	// Errors:
	// SystemError - System error.
	Destroy() Error

	// If the Container state is RUNNING or PAUSING, sets the Container state to PAUSING and pauses
	// the execution of any user processes. Asynchronously, when the container finished being paused the
	// state is changed to PAUSED.
	// If the Container state is PAUSED, do nothing.
	//
	// Errors:
	// ContainerDestroyed - Container no longer exists,
	// SystemError - System error.
	Pause() Error

	// If the Container state is PAUSED, resumes the execution of any user processes in the
	// Container before setting the Container state to RUNNING.
	// If the Container state is RUNNING, do nothing.
	//
	// Errors:
	// ContainerDestroyed - Container no longer exists,
	// SystemError - System error.
	Resume() Error
}
<commit_msg>Update container interface with process operations<commit_after>/*
NOTE: The API is in flux and mainly not implemented. Proceed with caution until further notice.
*/
package libcontainer

type ContainerInfo interface {
	// Returns the ID of the container
	ID() string

	// Returns the current run state of the container.
	//
	// Errors:
	// ContainerDestroyed - Container no longer exists,
	// SystemError - System error.
	RunState() (*RunState, Error)

	// Returns the current config of the container.
	Config() *Config

	// Returns the PIDs inside this container. The PIDs are in the namespace of the calling process.
	//
	// Errors:
	// ContainerDestroyed - Container no longer exists,
	// SystemError - System error.
	//
	// Some of the returned PIDs may no longer refer to processes in the Container, unless
	// the Container state is PAUSED in which case every PID in the slice is valid.
	Processes() ([]int, Error)

	// Returns statistics for the container.
	//
	// Errors:
	// ContainerDestroyed - Container no longer exists,
	// SystemError - System error.
	Stats() (*ContainerStats, Error)
}

// A libcontainer container object.
//
// Each container is thread-safe within the same process. Since a container can
// be destroyed by a separate process, any function may return that the container
// was not found.
type Container interface {
	ContainerInfo

	// Start a process inside the container. Returns the PID of the new process (in the caller process's namespace) and a channel that will return the exit status of the process whenever it dies.
	//
	// Errors:
	// ContainerDestroyed - Container no longer exists,
	// ConfigInvalid - config is invalid,
	// ContainerPaused - Container is paused,
	// SystemError - System error.
	StartProcess(config *ProcessConfig) (pid int, err Error)

	// Destroys the container after killing all running processes.
	//
	// Any event registrations are removed before the container is destroyed.
	// No error is returned if the container is already destroyed.
	//
	// Errors:
	// SystemError - System error.
	Destroy() Error

	// If the Container state is RUNNING or PAUSING, sets the Container state to PAUSING and pauses
	// the execution of any user processes. Asynchronously, when the container finished being paused the
	// state is changed to PAUSED.
	// If the Container state is PAUSED, do nothing.
	//
	// Errors:
	// ContainerDestroyed - Container no longer exists,
	// SystemError - System error.
	Pause() Error

	// If the Container state is PAUSED, resumes the execution of any user processes in the
	// Container before setting the Container state to RUNNING.
	// If the Container state is RUNNING, do nothing.
	//
	// Errors:
	// ContainerDestroyed - Container no longer exists,
	// SystemError - System error.
	Resume() Error

	// Signal sends the specified signal to a process owned by the container.
	//
	// Errors:
	// ContainerDestroyed - Container no longer exists,
	// ContainerPaused - Container is paused,
	// SystemError - System error.
	Signal(pid, signal int) Error

	// Wait waits for the init process of the conatiner to die and returns it's exit status.
	//
	// Errors:
	// ContainerDestroyed - Container no longer exists,
	// SystemError - System error.
	Wait() (exitStatus int, err Error)

	// WaitProcess waits on a process owned by the container.
	//
	// Errors:
	// ContainerDestroyed - Container no longer exists,
	// SystemError - System error.
	WaitProcess(pid int) (exitStatus int, err Error)
}
<|endoftext|>