<commit_before>package gorums

import (
	"fmt"
	"log"
	"sync"

	"google.golang.org/grpc"
	"google.golang.org/grpc/backoff"
)

// Manager manages a pool of node configurations on which quorum remote
// procedure calls can be made.
type Manager struct {
	mu        sync.Mutex
	nodes     []*Node
	lookup    map[uint32]*Node
	closeOnce sync.Once
	logger    *log.Logger
	opts      managerOptions

	*receiveQueue
}

// NewManager attempts to connect to the given set of node addresses and if
// successful returns a new Manager containing connections to those nodes.
// This function is meant for internal Gorums use. You should use the `NewManager`
// function in the generated code instead.
func NewManager(opts ...ManagerOption) (*Manager, error) {
	m := &Manager{
		lookup:       make(map[uint32]*Node),
		receiveQueue: newReceiveQueue(),
		opts:         newManagerOptions(),
	}

	for _, opt := range opts {
		opt(&m.opts)
	}
	if m.opts.logger != nil {
		m.logger = m.opts.logger
	}
	m.opts.grpcDialOpts = append(m.opts.grpcDialOpts, grpc.WithDefaultCallOptions(
		grpc.CallContentSubtype(ContentSubtype),
	))
	if m.opts.backoff != backoff.DefaultConfig {
		m.opts.grpcDialOpts = append(m.opts.grpcDialOpts, grpc.WithConnectParams(
			grpc.ConnectParams{Backoff: m.opts.backoff},
		))
	}

	switch {
	case len(m.opts.addrsList) == 0 && len(m.opts.idMapping) == 0:
		return nil, ManagerCreationError(fmt.Errorf("no nodes provided; need WithNodeMap or WithNodeList"))

	case len(m.opts.addrsList) > 0 && len(m.opts.idMapping) > 0:
		return nil, ManagerCreationError(fmt.Errorf("multiple node lists provided; use only one of WithNodeMap or WithNodeList"))

	case len(m.opts.idMapping) > 0:
		for naddr, id := range m.opts.idMapping {
			node, err := NewNodeWithID(naddr, id)
			if err != nil {
				return nil, ManagerCreationError(err)
			}
			err = m.AddNode(node)
			if err != nil {
				return nil, ManagerCreationError(err)
			}
		}
		// Sort nodes since map iteration is non-deterministic.
		OrderedBy(ID).Sort(m.nodes)

	case len(m.opts.addrsList) > 0:
		for _, naddr := range m.opts.addrsList {
			node, err := NewNode(naddr)
			if err != nil {
				return nil, ManagerCreationError(err)
			}
			err = m.AddNode(node)
			if err != nil {
				return nil, ManagerCreationError(err)
			}
		}
	}

	if m.logger != nil {
		m.logger.Printf("ready")
	}
	return m, nil
}

func (m *Manager) closeNodeConns() {
	for _, node := range m.nodes {
		err := node.close()
		if err != nil && m.logger != nil {
			m.logger.Printf("node %d: error closing: %v", node.id, err)
		}
	}
}

// Close closes all node connections and any client streams.
func (m *Manager) Close() {
	m.closeOnce.Do(func() {
		if m.logger != nil {
			m.logger.Printf("closing")
		}
		m.closeNodeConns()
	})
}

// NodeIDs returns the identifier of each available node. IDs are returned in
// the same order as they were provided in the creation of the Manager.
func (m *Manager) NodeIDs() []uint32 {
	m.mu.Lock()
	defer m.mu.Unlock()
	ids := make([]uint32, 0, len(m.nodes))
	for _, node := range m.nodes {
		ids = append(ids, node.ID())
	}
	return ids
}

// Node returns the node with the given identifier if present.
func (m *Manager) Node(id uint32) (node *Node, found bool) {
	m.mu.Lock()
	defer m.mu.Unlock()
	node, found = m.lookup[id]
	return node, found
}

// Nodes returns a slice of each available node. IDs are returned in the same
// order as they were provided in the creation of the Manager.
func (m *Manager) Nodes() []*Node {
	m.mu.Lock()
	defer m.mu.Unlock()
	return m.nodes
}

// Size returns the number of nodes in the Manager.
func (m *Manager) Size() (nodes int) {
	m.mu.Lock()
	defer m.mu.Unlock()
	return len(m.nodes)
}

// AddNode adds the node to the manager's node pool
// and establishes a connection to the node.
func (m *Manager) AddNode(node *Node) error {
	if _, found := m.Node(node.ID()); found {
		// Node IDs must be unique
		return fmt.Errorf("node ID %d already exists (%s)", node.ID(), node.Address())
	}
	if m.logger != nil {
		m.logger.Printf("connecting to %s with id %d\n", node, node.id)
	}
	if err := node.connect(m.receiveQueue, m.opts); err != nil {
		return fmt.Errorf("connection failed for %s: %w", node, err)
	}

	m.mu.Lock()
	defer m.mu.Unlock()
	m.lookup[node.id] = node
	m.nodes = append(m.nodes, node)
	return nil
}
<commit_msg>Sort nodes by ID also for WithNodeList option<commit_after>package gorums

import (
	"fmt"
	"log"
	"sync"

	"google.golang.org/grpc"
	"google.golang.org/grpc/backoff"
)

// Manager manages a pool of node configurations on which quorum remote
// procedure calls can be made.
type Manager struct {
	mu        sync.Mutex
	nodes     []*Node
	lookup    map[uint32]*Node
	closeOnce sync.Once
	logger    *log.Logger
	opts      managerOptions

	*receiveQueue
}

// NewManager attempts to connect to the given set of node addresses and if
// successful returns a new Manager containing connections to those nodes.
// This function is meant for internal Gorums use. You should use the `NewManager`
// function in the generated code instead.
func NewManager(opts ...ManagerOption) (*Manager, error) {
	m := &Manager{
		lookup:       make(map[uint32]*Node),
		receiveQueue: newReceiveQueue(),
		opts:         newManagerOptions(),
	}

	for _, opt := range opts {
		opt(&m.opts)
	}
	if m.opts.logger != nil {
		m.logger = m.opts.logger
	}
	m.opts.grpcDialOpts = append(m.opts.grpcDialOpts, grpc.WithDefaultCallOptions(
		grpc.CallContentSubtype(ContentSubtype),
	))
	if m.opts.backoff != backoff.DefaultConfig {
		m.opts.grpcDialOpts = append(m.opts.grpcDialOpts, grpc.WithConnectParams(
			grpc.ConnectParams{Backoff: m.opts.backoff},
		))
	}

	switch {
	case len(m.opts.addrsList) == 0 && len(m.opts.idMapping) == 0:
		return nil, ManagerCreationError(fmt.Errorf("no nodes provided; need WithNodeMap or WithNodeList"))

	case len(m.opts.addrsList) > 0 && len(m.opts.idMapping) > 0:
		return nil, ManagerCreationError(fmt.Errorf("multiple node lists provided; use only one of WithNodeMap or WithNodeList"))

	case len(m.opts.idMapping) > 0:
		for naddr, id := range m.opts.idMapping {
			node, err := NewNodeWithID(naddr, id)
			if err != nil {
				return nil, ManagerCreationError(err)
			}
			err = m.AddNode(node)
			if err != nil {
				return nil, ManagerCreationError(err)
			}
		}

	case len(m.opts.addrsList) > 0:
		for _, naddr := range m.opts.addrsList {
			node, err := NewNode(naddr)
			if err != nil {
				return nil, ManagerCreationError(err)
			}
			err = m.AddNode(node)
			if err != nil {
				return nil, ManagerCreationError(err)
			}
		}
	}
	// Sort nodes to ensure deterministic iteration.
	OrderedBy(ID).Sort(m.nodes)

	if m.logger != nil {
		m.logger.Printf("ready")
	}
	return m, nil
}

func (m *Manager) closeNodeConns() {
	for _, node := range m.nodes {
		err := node.close()
		if err != nil && m.logger != nil {
			m.logger.Printf("node %d: error closing: %v", node.id, err)
		}
	}
}

// Close closes all node connections and any client streams.
func (m *Manager) Close() {
	m.closeOnce.Do(func() {
		if m.logger != nil {
			m.logger.Printf("closing")
		}
		m.closeNodeConns()
	})
}

// NodeIDs returns the identifier of each available node. IDs are returned in
// the same order as they were provided in the creation of the Manager.
func (m *Manager) NodeIDs() []uint32 {
	m.mu.Lock()
	defer m.mu.Unlock()
	ids := make([]uint32, 0, len(m.nodes))
	for _, node := range m.nodes {
		ids = append(ids, node.ID())
	}
	return ids
}

// Node returns the node with the given identifier if present.
func (m *Manager) Node(id uint32) (node *Node, found bool) {
	m.mu.Lock()
	defer m.mu.Unlock()
	node, found = m.lookup[id]
	return node, found
}

// Nodes returns a slice of each available node. IDs are returned in the same
// order as they were provided in the creation of the Manager.
func (m *Manager) Nodes() []*Node {
	m.mu.Lock()
	defer m.mu.Unlock()
	return m.nodes
}

// Size returns the number of nodes in the Manager.
func (m *Manager) Size() (nodes int) {
	m.mu.Lock()
	defer m.mu.Unlock()
	return len(m.nodes)
}

// AddNode adds the node to the manager's node pool
// and establishes a connection to the node.
func (m *Manager) AddNode(node *Node) error {
	if _, found := m.Node(node.ID()); found {
		// Node IDs must be unique
		return fmt.Errorf("node ID %d already exists (%s)", node.ID(), node.Address())
	}
	if m.logger != nil {
		m.logger.Printf("connecting to %s with id %d\n", node, node.id)
	}
	if err := node.connect(m.receiveQueue, m.opts); err != nil {
		return fmt.Errorf("connection failed for %s: %w", node, err)
	}

	m.mu.Lock()
	defer m.mu.Unlock()
	m.lookup[node.id] = node
	m.nodes = append(m.nodes, node)
	return nil
}
<|endoftext|>


<commit_before>// common.go
//
// This file implements the configuration part for when you need the API
// key to modify things in the Atlas configuration and manage measurements.

package atlas

import (
	"encoding/json"
	"errors"
	"fmt"
	"github.com/sendgrid/rest"
	"log"
	"regexp"
)

const (
	apiEndpoint = "https://atlas.ripe.net/api/v2"

	ourVersion = "0.11"
)

// APIKey is the API key
var APIKey string

// ErrInvalidMeasurementType is a new error
var ErrInvalidMeasurementType = errors.New("invalid measurement type")

// ErrInvalidAPIKey is returned when the key is invalid
var ErrInvalidAPIKey = errors.New("invalid API key")

// SetAuth stores the credentials for later use
func SetAuth(key string) {
	APIKey = key
}

// HasAPIKey returns whether an API key is stored
func HasAPIKey() (string, bool) {
	if APIKey == "" {
		return "", false
	}
	return APIKey, true
}

// GetVersion returns the API wrapper version
func GetVersion() string {
	return ourVersion
}

// getPageNum returns the value of the page= parameter
func getPageNum(url string) (page string) {
	re := regexp.MustCompile(`page=(\d+)`)
	if m := re.FindStringSubmatch(url); len(m) >= 1 {
		return m[1]
	}
	return ""
}

// prepareRequest insert all pre-defined stuff
func prepareRequest(what string) (req rest.Request) {
	endPoint := apiEndpoint + fmt.Sprintf("/%s/", what)
	key, ok := HasAPIKey()

	// Add at least one option, the APIkey if present
	hdrs := make(map[string]string)
	opts := make(map[string]string)

	// Insert our sig
	hdrs["User-Agent"] = fmt.Sprintf("ripe-atlas/%s", ourVersion)

	// Insert key
	if ok {
		opts["key"] = key
	}

	req = rest.Request{
		BaseURL:     endPoint,
		Headers:     hdrs,
		QueryParams: opts,
	}
	return
}

// handleAPIResponse check status code & errors from the API
func handleAPIResponse(r *rest.Response) (err error) {
	// Everything is fine
	if r.StatusCode == 0 {
		return nil
	}

	// Everything is fine too
	if r.StatusCode >= 200 && r.StatusCode <= 299 {
		return nil
	}

	// Check this condition
	if r.StatusCode >= 300 && r.StatusCode <= 399 {
		var aerr APIError

		err = json.Unmarshal([]byte(r.Body), &aerr)
		log.Printf("Info 3XX status: %d code: %d - r:%v\n",
			aerr.Error.Status,
			aerr.Error.Code,
			aerr.Error.Detail)
		return nil
	}

	// EVerything else is an error
	var aerr APIError

	err = json.Unmarshal([]byte(r.Body), &aerr)
	err = fmt.Errorf("status: %d code: %d - r:%v",
		aerr.Error.Status,
		aerr.Error.Code,
		aerr.Error.Detail)
	return
}
<commit_msg>Add a nil check, should not happen (except when it does).<commit_after>// common.go
//
// This file implements the configuration part for when you need the API
// key to modify things in the Atlas configuration and manage measurements.

package atlas

import (
	"encoding/json"
	"errors"
	"fmt"
	"github.com/sendgrid/rest"
	"log"
	"regexp"
)

const (
	apiEndpoint = "https://atlas.ripe.net/api/v2"

	ourVersion = "0.11"
)

// APIKey is the API key
var APIKey string

// ErrInvalidMeasurementType is a new error
var ErrInvalidMeasurementType = errors.New("invalid measurement type")

// ErrInvalidAPIKey is returned when the key is invalid
var ErrInvalidAPIKey = errors.New("invalid API key")

// SetAuth stores the credentials for later use
func SetAuth(key string) {
	APIKey = key
}

// HasAPIKey returns whether an API key is stored
func HasAPIKey() (string, bool) {
	if APIKey == "" {
		return "", false
	}
	return APIKey, true
}

// GetVersion returns the API wrapper version
func GetVersion() string {
	return ourVersion
}

// getPageNum returns the value of the page= parameter
func getPageNum(url string) (page string) {
	re := regexp.MustCompile(`page=(\d+)`)
	if m := re.FindStringSubmatch(url); len(m) >= 1 {
		return m[1]
	}
	return ""
}

// prepareRequest insert all pre-defined stuff
func prepareRequest(what string) (req rest.Request) {
	endPoint := apiEndpoint + fmt.Sprintf("/%s/", what)
	key, ok := HasAPIKey()

	// Add at least one option, the APIkey if present
	hdrs := make(map[string]string)
	opts := make(map[string]string)

	// Insert our sig
	hdrs["User-Agent"] = fmt.Sprintf("ripe-atlas/%s", ourVersion)

	// Insert key
	if ok {
		opts["key"] = key
	}

	req = rest.Request{
		BaseURL:     endPoint,
		Headers:     hdrs,
		QueryParams: opts,
	}
	return
}

// handleAPIResponse check status code & errors from the API
func handleAPIResponse(r *rest.Response) (err error) {
	if r == nil {
		return fmt.Errorf("Error: r is nil!")
	}

	// Everything is fine
	if r.StatusCode == 0 {
		return nil
	}

	// Everything is fine too
	if r.StatusCode >= 200 && r.StatusCode <= 299 {
		return nil
	}

	// Check this condition
	if r.StatusCode >= 300 && r.StatusCode <= 399 {
		var aerr APIError

		err = json.Unmarshal([]byte(r.Body), &aerr)
		log.Printf("Info 3XX status: %d code: %d - r:%v\n",
			aerr.Error.Status,
			aerr.Error.Code,
			aerr.Error.Detail)
		return nil
	}

	// EVerything else is an error
	var aerr APIError

	err = json.Unmarshal([]byte(r.Body), &aerr)
	err = fmt.Errorf("status: %d code: %d - r:%v",
		aerr.Error.Status,
		aerr.Error.Code,
		aerr.Error.Detail)
	return
}
<|endoftext|>


<commit_before>// common.go
//
// This file implements the configuration part for when you need the API
// key to modify things in the Atlas configuration and manage measurements.

package atlas

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"net/http"
	"net/url"
	"regexp"
)

const (
	apiEndpoint = "https://atlas.ripe.net/api/v2"
)

// GetVersion returns the API wrapper version
func GetVersion() string {
	return ourVersion
}

// getPageNum returns the value of the page= parameter
func getPageNum(url string) (page string) {
	re := regexp.MustCompile(`page=(\d+)`)
	if m := re.FindStringSubmatch(url); len(m) >= 1 {
		return m[1]
	}
	return ""
}

// AddQueryParameters adds query parameters to the URL.
func AddQueryParameters(baseURL string, queryParams map[string]string) string {
	if len(queryParams) == 0 {
		return baseURL
	}
	baseURL += "?"
	params := url.Values{}
	for key, value := range queryParams {
		params.Add(key, value)
	}
	return baseURL + params.Encode()
}

// addAPIKey insert the key into options if needed
func (c *Client) addAPIKey(opts map[string]string) map[string]string {
	key, ok := c.HasAPIKey()
	// Insert key
	if ok {
		opts["key"] = key
	}
	return opts
}

// prepareRequest insert all pre-defined stuff
func (c *Client) prepareRequest(method, what string, opts map[string]string) (req *http.Request) {
	var endPoint string

	// This is a hack to fetch direct urls for results
	if method == "FETCH" {
		endPoint = what
		method = "GET"
	} else {
		if c.config.endpoint != "" {
			endPoint = fmt.Sprintf("%s/%s/", c.config.endpoint, what)
		} else {
			endPoint = fmt.Sprintf("%s/%s/", apiEndpoint, what)
		}
	}

	c.mergeGlobalOptions(opts)
	c.verbose("Options:\n%v", opts)
	baseURL := AddQueryParameters(endPoint, opts)

	req, err := http.NewRequest(method, baseURL, nil)
	if err != nil {
		c.log.Printf("error parsing %s: %v", baseURL, err)
		return &http.Request{}
	}

	// We need these when we POST
	if method == "POST" {
		req.Header.Set("Content-Type", "application/json")
		req.Header.Set("Accept", "application/json")
	}

	return
}

// client.handleAPIResponsese check status code & errors from the API
func (c *Client) handleAPIResponsese(r *http.Response) (err error) {
	if r == nil {
		return fmt.Errorf("error: r is nil")
	}

	// Everything is fine
	if r.StatusCode == 0 {
		return nil
	}

	// Everything is fine too
	if r.StatusCode >= 200 && r.StatusCode <= 299 {
		return nil
	}

	// Check this condition
	if r.StatusCode >= 300 && r.StatusCode <= 399 {
		var aerr APIError

		body, _ := ioutil.ReadAll(r.Body)
		defer r.Body.Close()

		err = json.Unmarshal(body, &aerr)
		if err != nil {
			c.log.Printf("Error handling error: %s - %v", r.Body, err)
		}

		c.log.Printf("Info 3XX status: %d code: %d - r:%v\n",
			aerr.Error.Status,
			aerr.Error.Code,
			aerr.Error.Detail)
		return nil
	}

	// EVerything else is an error
	var aerr APIError

	body, _ := ioutil.ReadAll(r.Body)
	defer r.Body.Close()

	err = json.Unmarshal(body, &aerr)
	if err != nil {
		c.log.Printf("Error handling error: %s - %v", r.Body, err)
	}

	err = fmt.Errorf("status: %d code: %d - r:%s\nerrors: %v",
		aerr.Error.Status,
		aerr.Error.Code,
		aerr.Error.Detail,
		aerr.Error.Errors)
	return
}
<commit_msg>Trailing "/" is not required.<commit_after>// common.go
//
// This file implements the configuration part for when you need the API
// key to modify things in the Atlas configuration and manage measurements.

package atlas

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"net/http"
	"net/url"
	"regexp"
)

const (
	apiEndpoint = "https://atlas.ripe.net/api/v2"
)

// GetVersion returns the API wrapper version
func GetVersion() string {
	return ourVersion
}

// getPageNum returns the value of the page= parameter
func getPageNum(url string) (page string) {
	re := regexp.MustCompile(`page=(\d+)`)
	if m := re.FindStringSubmatch(url); len(m) >= 1 {
		return m[1]
	}
	return ""
}

// AddQueryParameters adds query parameters to the URL.
func AddQueryParameters(baseURL string, queryParams map[string]string) string {
	if len(queryParams) == 0 {
		return baseURL
	}
	baseURL += "?"
	params := url.Values{}
	for key, value := range queryParams {
		params.Add(key, value)
	}
	return baseURL + params.Encode()
}

// addAPIKey insert the key into options if needed
func (c *Client) addAPIKey(opts map[string]string) map[string]string {
	key, ok := c.HasAPIKey()
	// Insert key
	if ok {
		opts["key"] = key
	}
	return opts
}

// prepareRequest insert all pre-defined stuff
func (c *Client) prepareRequest(method, what string, opts map[string]string) (req *http.Request) {
	var endPoint string

	// This is a hack to fetch direct urls for results
	if method == "FETCH" {
		endPoint = what
		method = "GET"
	} else {
		if c.config.endpoint != "" {
			endPoint = fmt.Sprintf("%s/%s", c.config.endpoint, what)
		} else {
			endPoint = fmt.Sprintf("%s/%s", apiEndpoint, what)
		}
	}

	c.mergeGlobalOptions(opts)
	c.verbose("Options:\n%v", opts)
	baseURL := AddQueryParameters(endPoint, opts)

	req, err := http.NewRequest(method, baseURL, nil)
	if err != nil {
		c.log.Printf("error parsing %s: %v", baseURL, err)
		return &http.Request{}
	}

	// We need these when we POST
	if method == "POST" {
		req.Header.Set("Content-Type", "application/json")
		req.Header.Set("Accept", "application/json")
	}

	return
}

// client.handleAPIResponsese check status code & errors from the API
func (c *Client) handleAPIResponsese(r *http.Response) (err error) {
	if r == nil {
		return fmt.Errorf("error: r is nil")
	}

	// Everything is fine
	if r.StatusCode == 0 {
		return nil
	}

	// Everything is fine too
	if r.StatusCode >= 200 && r.StatusCode <= 299 {
		return nil
	}

	// Check this condition
	if r.StatusCode >= 300 && r.StatusCode <= 399 {
		var aerr APIError

		body, _ := ioutil.ReadAll(r.Body)
		defer r.Body.Close()

		err = json.Unmarshal(body, &aerr)
		if err != nil {
			c.log.Printf("Error handling error: %s - %v", r.Body, err)
		}

		c.log.Printf("Info 3XX status: %d code: %d - r:%v\n",
			aerr.Error.Status,
			aerr.Error.Code,
			aerr.Error.Detail)
		return nil
	}

	// EVerything else is an error
	var aerr APIError

	body, _ := ioutil.ReadAll(r.Body)
	defer r.Body.Close()

	err = json.Unmarshal(body, &aerr)
	if err != nil {
		c.log.Printf("Error handling error: %s - %v", r.Body, err)
	}

	err = fmt.Errorf("status: %d code: %d - r:%s\nerrors: %v",
		aerr.Error.Status,
		aerr.Error.Code,
		aerr.Error.Detail,
		aerr.Error.Errors)
	return
}
<|endoftext|>


<commit_before>package slinguist

const OtherLanguage = "Other"

var (
	ExtensionsByLanguage map[string][]string
	ignoredExtensions    = map[string]bool{
		".asc": true, ".cgi": true, ".fcgi": true, ".gml": true, ".fx": true,
		".vhost": true,
	}
	auxiliaryLanguages = map[string]bool{
		"Other": true, "XML": true, "YAML": true, "TOML": true, "INI": true,
		"JSON": true, "TeX": true, "Public Key": true, "AsciiDoc": true,
		"AGS Script": true, "VimL": true, "Diff": true, "CMake": true, "fish": true,
		"Awk": true, "Graphviz (DOT)": true, "Markdown": true, "desktop": true,
		"XSLT": true, "SQL": true, "RMarkdown": true, "IRC log": true,
		"reStructuredText": true, "Twig": true, "CSS": true, "Batchfile": true,
		"Text": true, "HTML+ERB": true, "HTML": true, "Gettext Catalog": true,
		"Smarty": true, "Raw token data": true,
	}
)

func init() {
	for l, _ := range ignoredExtensions {
		languagesByExtension[l] = []string{OtherLanguage}
	}

	ExtensionsByLanguage = reverseStringListMap(languagesByExtension)
}

// GetLanguageExtensions returns the different extensions being used by the
// language.
func GetLanguageExtensions(language string) []string {
	return ExtensionsByLanguage[language]
}

// GetLanguage return the Language for a given filename and file content.
func GetLanguage(filename string, content []byte) string {
	if lang, safe := GetLanguageByExtension(filename); safe {
		return lang
	}

	lang, _ := GetLanguageByContent(filename, content)
	return lang
}

func reverseStringListMap(i map[string][]string) (o map[string][]string) {
	o = map[string][]string{}
	for key, set := range i {
		for _, value := range set {
			o[value] = append(o[value], key)
		}
	}

	return
}
<commit_msg>GetLanguage follows strategies shebang, extension, content<commit_after>package slinguist

const OtherLanguage = "Other"

var (
	ExtensionsByLanguage map[string][]string
	ignoredExtensions    = map[string]bool{
		".asc": true, ".cgi": true, ".fcgi": true, ".gml": true, ".fx": true,
		".vhost": true,
	}
	auxiliaryLanguages = map[string]bool{
		"Other": true, "XML": true, "YAML": true, "TOML": true, "INI": true,
		"JSON": true, "TeX": true, "Public Key": true, "AsciiDoc": true,
		"AGS Script": true, "VimL": true, "Diff": true, "CMake": true, "fish": true,
		"Awk": true, "Graphviz (DOT)": true, "Markdown": true, "desktop": true,
		"XSLT": true, "SQL": true, "RMarkdown": true, "IRC log": true,
		"reStructuredText": true, "Twig": true, "CSS": true, "Batchfile": true,
		"Text": true, "HTML+ERB": true, "HTML": true, "Gettext Catalog": true,
		"Smarty": true, "Raw token data": true,
	}
)

func init() {
	for l, _ := range ignoredExtensions {
		languagesByExtension[l] = []string{OtherLanguage}
	}

	ExtensionsByLanguage = reverseStringListMap(languagesByExtension)
}

// GetLanguageExtensions returns the different extensions being used by the
// language.
func GetLanguageExtensions(language string) []string {
	return ExtensionsByLanguage[language]
}

// GetLanguage return the Language for a given filename and file content.
func GetLanguage(filename string, content []byte) string {
	if lang, safe := GetLanguageByShebang(content); safe {
		return lang
	}

	if lang, safe := GetLanguageByExtension(filename); safe {
		return lang
	}

	lang, _ := GetLanguageByContent(filename, content)
	return lang
}

func reverseStringListMap(i map[string][]string) (o map[string][]string) {
	o = map[string][]string{}
	for key, set := range i {
		for _, value := range set {
			o[value] = append(o[value], key)
		}
	}

	return
}
<|endoftext|>


<commit_before>package bon

import (
	"net/http"
	"sync"
)

const (
	nodeKindStatic nodeKind = iota
	nodeKindParam
	nodeKindAny
)

type (
	Mux struct {
		tree        *node
		middlewares []Middleware
		pool        sync.Pool
		maxParam    int
		NotFound    http.HandlerFunc
	}

	nodeKind uint8

	node struct {
		kind     nodeKind
		parent   *node
		children map[string]*node
		endpoint *endpoint
	}

	endpoint struct {
		handler     http.Handler
		middlewares []Middleware
		paramKeys   []string
		pattern     string
	}

	Middleware func(http.Handler) http.Handler
)

func newMux() *Mux {
	m := &Mux{
		NotFound: http.NotFound,
	}

	m.pool = sync.Pool{
		New: func() interface{} {
			return m.NewContext()
		},
	}

	m.tree = newNode()
	return m
}

func newNode() *node {
	return &node{
		children: make(map[string]*node),
	}
}

func (n *node) newChild(child *node, edge string) *node {
	if len(n.children) == 0 {
		n.children = make(map[string]*node)
	}

	child.parent = n
	n.children[edge] = child
	return child
}

func isStaticPattern(pattern string) bool {
	for i := 0; i < len(pattern); i++ {
		if pattern[i] == ':' || pattern[i] == '*' {
			return false
		}
	}

	return true
}

func compensatePattern(pattern string) string {
	if len(pattern) > 0 {
		if pattern[0] != '/' {
			return "/" + pattern
		}
	}

	return pattern
}

func (m *Mux) Group(pattern string, middlewares ...Middleware) *Group {
	return &Group{
		mux:         m,
		middlewares: append(m.middlewares, middlewares...),
		prefix:      compensatePattern(pattern),
	}
}

func (m *Mux) Route(middlewares ...Middleware) *Route {
	return &Route{
		mux:         m,
		middlewares: middlewares,
	}
}

func (m *Mux) Use(middlewares ...Middleware) {
	m.middlewares = append(m.middlewares, middlewares...)
}

func (m *Mux) Get(pattern string, handlerFunc http.HandlerFunc, middlewares ...Middleware) {
	m.Handle(http.MethodGet, pattern, handlerFunc, append(m.middlewares, middlewares...)...)
}

func (m *Mux) Post(pattern string, handlerFunc http.HandlerFunc, middlewares ...Middleware) {
	m.Handle(http.MethodPost, pattern, handlerFunc, append(m.middlewares, middlewares...)...)
}

func (m *Mux) Put(pattern string, handlerFunc http.HandlerFunc, middlewares ...Middleware) {
	m.Handle(http.MethodPut, pattern, handlerFunc, append(m.middlewares, middlewares...)...)
}

func (m *Mux) Delete(pattern string, handlerFunc http.HandlerFunc, middlewares ...Middleware) {
	m.Handle(http.MethodDelete, pattern, handlerFunc, append(m.middlewares, middlewares...)...)
}

func (m *Mux) Head(pattern string, handlerFunc http.HandlerFunc, middlewares ...Middleware) {
	m.Handle(http.MethodHead, pattern, handlerFunc, append(m.middlewares, middlewares...)...)
}

func (m *Mux) Options(pattern string, handlerFunc http.HandlerFunc, middlewares ...Middleware) {
	m.Handle(http.MethodOptions, pattern, handlerFunc, append(m.middlewares, middlewares...)...)
}

func (m *Mux) Patch(pattern string, handlerFunc http.HandlerFunc, middlewares ...Middleware) {
	m.Handle(http.MethodPatch, pattern, handlerFunc, append(m.middlewares, middlewares...)...)
}

func (m *Mux) Connect(pattern string, handlerFunc http.HandlerFunc, middlewares ...Middleware) {
	m.Handle(http.MethodConnect, pattern, handlerFunc, append(m.middlewares, middlewares...)...)
}

func (m *Mux) Trace(pattern string, handlerFunc http.HandlerFunc, middlewares ...Middleware) {
	m.Handle(http.MethodTrace, pattern, handlerFunc, append(m.middlewares, middlewares...)...)
}

func (m *Mux) FileServer(pattern, dir string) {
	if !isStaticPattern(pattern) {
		panic("It is not a static pattern")
	}

	if pattern[len(pattern)-1] != '/' {
		pattern += "/"
	}

	m.Handle(http.MethodGet, pattern+"*", http.StripPrefix(pattern, http.FileServer(http.Dir(dir))))
}

func (m *Mux) Handle(method, pattern string, handler http.Handler, middlewares ...Middleware) {
	parent := m.tree.children[method]
	if parent == nil {
		parent = m.tree.newChild(newNode(), method)
	}

	pattern = compensatePattern(pattern)

	if isStaticPattern(pattern) {
		child, ok := parent.children[pattern]
		if !ok {
			child = newNode()
		}

		child.endpoint = &endpoint{
			handler:     handler,
			middlewares: middlewares,
			pattern:     pattern,
		}

		parent.newChild(child, pattern)
		return
	}

	var si, ei int
	var pKeys []string

	// i = 0 is '/'
	for i := 1; i < len(pattern); i++ {
		si = i
		ei = i

		for ; i < len(pattern); i++ {
			if si < ei {
				if pattern[i] == ':' || pattern[i] == '*' {
					panic("Parameter are not first")
				}
			}

			if pattern[i] == '/' {
				break
			}

			ei++
		}

		edge := pattern[si:ei]
		kind := nodeKindStatic
		var pKey string

		switch edge[0] {
		case ':':
			pKey = edge[1:]
			edge = ":"
			kind = nodeKindParam
		case '*':
			edge = "*"
			kind = nodeKindAny
		}

		child, exist := parent.children[edge]
		if !exist {
			child = newNode()
		}

		child.kind = kind

		if len(pKey) > 0 {
			pKeys = append(pKeys, pKey)
		}

		if i >= len(pattern)-1 {
			child.endpoint = &endpoint{
				handler:     handler,
				middlewares: middlewares,
				pattern:     pattern,
				paramKeys:   pKeys,
			}
		}

		if exist {
			parent = child
			continue
		}

		parent = parent.newChild(child, edge)
	}

	if len(pKeys) > m.maxParam {
		m.maxParam = len(pKeys)
	}
}

func (m *Mux) lookup(r *http.Request) (*endpoint, *Context) {
	var parent, child, backtrack *node

	if parent = m.tree.children[r.Method]; parent == nil {
		return nil, nil
	}

	rPath := r.URL.Path

	//STATIC PATH
	if child = parent.children[rPath]; child != nil {
		return child.endpoint, nil
	}

	var si, ei int
	var ctx *Context

	for i := 1; i < len(rPath); i++ {
		si = i
		ei = i

		for ; i < len(rPath); i++ {
			if rPath[i] == '/' {
				break
			}

			ei++
		}

		edge := rPath[si:ei]

		if child = parent.children[edge]; child == nil {
			if child = parent.children[":"]; child != nil {
				if ctx == nil {
					ctx = m.pool.Get().(*Context)
				}

				ctx.params.values = append(ctx.params.values, edge)
			} else if child = parent.children["*"]; child != nil && child.endpoint != nil {
				backtrack = child
			}
		}

		if child != nil {
			if i >= len(rPath)-1 && child.endpoint != nil {
				return child.endpoint, ctx
			}

			if child.kind != nodeKindAny {
				if b := parent.children["*"]; b != nil && b.endpoint != nil {
					backtrack = b
				}
			}

			if len(child.children) == 0 {
				if child.kind == nodeKindAny && child.endpoint != nil {
					return child.endpoint, ctx
				}

				break
			}

			parent = child
			continue
		}

		break
	}

	if backtrack != nil {
		return backtrack.endpoint, ctx
	}

	return nil, ctx
}

func (m *Mux) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	if e, ctx := m.lookup(r); e != nil {
		if ctx != nil {
			ctx.params.keys = e.paramKeys
			r = ctx.WithContext(r)
		}

		if len(e.middlewares) == 0 {
			e.handler.ServeHTTP(w, r)

			if ctx != nil {
				m.pool.Put(ctx.reset())
			}

			return
		}

		h := e.middlewares[len(e.middlewares)-1](e.handler)
		for i := len(e.middlewares) - 2; i >= 0; i-- {
			h = e.middlewares[i](h)
		}

		h.ServeHTTP(w, r)

		if ctx != nil {
			m.pool.Put(ctx.reset())
		}

		return
	}

	m.NotFound.ServeHTTP(w, r)
}
<commit_msg>fix middlewares<commit_after>package bon

import (
	"net/http"
	"sync"
)

const (
	nodeKindStatic nodeKind = iota
	nodeKindParam
	nodeKindAny
)

type (
	Mux struct {
		tree        *node
		middlewares []Middleware
		pool        sync.Pool
		maxParam    int
		NotFound    http.HandlerFunc
	}

	nodeKind uint8

	node struct {
		kind     nodeKind
		parent   *node
		children map[string]*node
		endpoint *endpoint
	}

	endpoint struct {
		handler     http.Handler
		middlewares []Middleware
		paramKeys   []string
		pattern     string
	}

	Middleware func(http.Handler) http.Handler
)

func newMux() *Mux {
	m := &Mux{
		NotFound: http.NotFound,
	}

	m.pool = sync.Pool{
		New: func() interface{} {
			return m.NewContext()
		},
	}

	m.tree = newNode()
	return m
}

func newNode() *node {
	return &node{
		children: make(map[string]*node),
	}
}

func (n *node) newChild(child *node, edge string) *node {
	if len(n.children) == 0 {
		n.children = make(map[string]*node)
	}

	child.parent = n
	n.children[edge] = child
	return child
}

func isStaticPattern(pattern string) bool {
	for i := 0; i < len(pattern); i++ {
		if pattern[i] == ':' || pattern[i] == '*' {
			return false
		}
	}

	return true
}

func compensatePattern(pattern string) string {
	if len(pattern) > 0 {
		if pattern[0] != '/' {
			return "/" + pattern
		}
	}

	return pattern
}

func (m *Mux) Group(pattern string, middlewares ...Middleware) *Group {
	return &Group{
		mux:         m,
		middlewares: append(m.middlewares, middlewares...),
		prefix:      compensatePattern(pattern),
	}
}

func (m *Mux) Route(middlewares ...Middleware) *Route {
	return &Route{
		mux:         m,
		middlewares: middlewares,
	}
}

func (m *Mux) Use(middlewares ...Middleware) {
	m.middlewares = append(m.middlewares, middlewares...)
}

func (m *Mux) Get(pattern string, handlerFunc http.HandlerFunc, middlewares ...Middleware) {
	m.Handle(http.MethodGet, pattern, handlerFunc, append(m.middlewares, middlewares...)...)
}

func (m *Mux) Post(pattern string, handlerFunc http.HandlerFunc, middlewares ...Middleware) {
	m.Handle(http.MethodPost, pattern, handlerFunc, append(m.middlewares, middlewares...)...)
}

func (m *Mux) Put(pattern string, handlerFunc http.HandlerFunc, middlewares ...Middleware) {
	m.Handle(http.MethodPut, pattern, handlerFunc, append(m.middlewares, middlewares...)...)
}

func (m *Mux) Delete(pattern string, handlerFunc http.HandlerFunc, middlewares ...Middleware) {
	m.Handle(http.MethodDelete, pattern, handlerFunc, append(m.middlewares, middlewares...)...)
}

func (m *Mux) Head(pattern string, handlerFunc http.HandlerFunc, middlewares ...Middleware) {
	m.Handle(http.MethodHead, pattern, handlerFunc, append(m.middlewares, middlewares...)...)
}

func (m *Mux) Options(pattern string, handlerFunc http.HandlerFunc, middlewares ...Middleware) {
	m.Handle(http.MethodOptions, pattern, handlerFunc, append(m.middlewares, middlewares...)...)
}

func (m *Mux) Patch(pattern string, handlerFunc http.HandlerFunc, middlewares ...Middleware) {
	m.Handle(http.MethodPatch, pattern, handlerFunc, append(m.middlewares, middlewares...)...)
}

func (m *Mux) Connect(pattern string, handlerFunc http.HandlerFunc, middlewares ...Middleware) {
	m.Handle(http.MethodConnect, pattern, handlerFunc, append(m.middlewares, middlewares...)...)
}

func (m *Mux) Trace(pattern string, handlerFunc http.HandlerFunc, middlewares ...Middleware) {
	m.Handle(http.MethodTrace, pattern, handlerFunc, append(m.middlewares, middlewares...)...)
}

func (m *Mux) FileServer(path, dir string, middlewares ...Middleware) {
	if !isStaticPattern(path) {
		panic("It is not a static pattern")
	}

	if path[len(path)-1] != '/' {
		path += "/"
	}

	m.Handle(http.MethodGet, path+"*", http.StripPrefix(path, http.FileServer(http.Dir(dir))), append(m.middlewares, middlewares...)...)
}

func (m *Mux) Handle(method, pattern string, handler http.Handler, middlewares ...Middleware) {
	parent := m.tree.children[method]
	if parent == nil {
		parent = m.tree.newChild(newNode(), method)
	}

	pattern = compensatePattern(pattern)

	if isStaticPattern(pattern) {
		child, ok := parent.children[pattern]
		if !ok {
			child = newNode()
		}

		child.endpoint = &endpoint{
			handler:     handler,
			middlewares: middlewares,
			pattern:     pattern,
		}

		parent.newChild(child, pattern)
		return
	}

	var si, ei int
	var pKeys []string

	// i = 0 is '/'
	for i := 1; i < len(pattern); i++ {
		si = i
		ei = i

		for ; i < len(pattern); i++ {
			if si < ei {
				if pattern[i] == ':' || pattern[i] == '*' {
					panic("Parameter are not first")
				}
			}

			if pattern[i] == '/' {
				break
			}

			ei++
		}

		edge := pattern[si:ei]
		kind := nodeKindStatic
		var pKey string

		switch edge[0] {
		case ':':
			pKey = edge[1:]
			edge = ":"
			kind = nodeKindParam
		case '*':
			edge = "*"
			kind = nodeKindAny
		}

		child, exist := parent.children[edge]
		if !exist {
			child = newNode()
		}

		child.kind = kind

		if len(pKey) > 0 {
			pKeys = append(pKeys, pKey)
		}

		if i >= len(pattern)-1 {
			child.endpoint = &endpoint{
				handler:     handler,
				middlewares: middlewares,
				pattern:     pattern,
				paramKeys:   pKeys,
			}
		}

		if exist {
			parent = child
			continue
		}

		parent = parent.newChild(child, edge)
	}

	if len(pKeys) > m.maxParam {
		m.maxParam = len(pKeys)
	}
}

func (m *Mux) lookup(r *http.Request) (*endpoint, *Context) {
	var parent, child, backtrack *node

	if parent = m.tree.children[r.Method]; parent == nil {
		return nil, nil
	}

	rPath := r.URL.Path

	//STATIC PATH
	if child = parent.children[rPath]; child != nil {
		return child.endpoint, nil
	}

	var si, ei int
	var ctx *Context

	for i := 1; i < len(rPath); i++ {
		si = i
		ei = i

		for ; i < len(rPath); i++ {
			if rPath[i] == '/' {
				break
			}

			ei++
		}

		edge := rPath[si:ei]

		if child = parent.children[edge]; child == nil {
			if child = parent.children[":"]; child != nil {
				if ctx == nil {
					ctx = m.pool.Get().(*Context)
				}

				ctx.params.values = append(ctx.params.values, edge)
			} else if child = parent.children["*"]; child != nil && child.endpoint != nil {
				backtrack = child
			}
		}

		if child != nil {
			if i >= len(rPath)-1 && child.endpoint != nil {
				return child.endpoint, ctx
			}

			if child.kind != nodeKindAny {
				if b := parent.children["*"]; b != nil && b.endpoint != nil {
					backtrack = b
				}
			}

			if len(child.children) == 0 {
				if child.kind == nodeKindAny && child.endpoint != nil {
					return child.endpoint, ctx
				}

				break
			}

			parent = child
			continue
		}

		break
	}

	if backtrack != nil {
		return backtrack.endpoint, ctx
	}

	return nil, ctx
}

func (m *Mux) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	if e, ctx := m.lookup(r); e != nil {
		if ctx != nil {
			ctx.params.keys = e.paramKeys
			r = ctx.WithContext(r)
		}

		if len(e.middlewares) == 0 {
			e.handler.ServeHTTP(w, r)

			if ctx != nil {
				m.pool.Put(ctx.reset())
			}

			return
		}

		h := e.middlewares[len(e.middlewares)-1](e.handler)
		for i := len(e.middlewares) - 2; i >= 0; i-- {
			h = e.middlewares[i](h)
		}

		h.ServeHTTP(w, r)

		if ctx != nil {
			m.pool.Put(ctx.reset())
		}

		return
	}

	m.NotFound.ServeHTTP(w, r)
}
<|endoftext|>


<commit_before>// Copyright (c) 2011 Mikkel Krautz
// The use of this source code is goverened by a BSD-style
// license that can be found in the LICENSE-file.

// Package pdfdraw implements a library for rendering and reading PDFs (Currently implemented on top of poppler-glib)
package pdfdraw

/*
#cgo pkg-config: poppler-glib cairo
#include <stdlib.h>
#include <poppler.h>
#include <cairo.h>

static unsigned char getbyte(unsigned char *buf, int idx) {
	return buf[idx];
}

static char *path_to_uri(char *path) {
	GError *err = NULL;
	gchar *absfn = NULL;

	if (g_path_is_absolute(path))
		absfn = g_strdup(path);
	else {
		gchar *tmp = g_get_current_dir();
		absfn = g_build_filename(tmp, path, NULL);
		free(tmp);
	}

	return (char *) g_filename_to_uri(absfn, NULL, &err);
}
*/
import "C"

import (
	"image"
	"os"
	"unsafe"
)

func init() {
	C.g_type_init()
}

// A Document represents a PDF document
type Document struct {
	doc *C.PopplerDocument
}

// A Page represents a page in a Document
type Page struct {
	page *C.PopplerPage
}

// Open a PDF file at path and return a Document
func Open(path string) (doc *Document, err os.Error) {
	uri := C.path_to_uri(C.CString(path))
	if uri == nil {
		return nil, os.NewError("unable to convert path to uri")
	}
	defer C.free(unsafe.Pointer(uri))

	doc = new(Document)
	doc.doc = C.poppler_document_new_from_file(uri, nil, nil)
	if doc.doc == nil {
		return nil, os.NewError("unable to open file")
	}

	return doc, nil
}

// Get the total number of pages in the Document
func (doc *Document) NumPages() int {
	return int(C.poppler_document_get_n_pages(doc.doc))
}

// Get a Page
func (doc *Document) Page(idx int) (page *Page) {
	page = new(Page)
	page.page = C.poppler_document_get_page(doc.doc, C.int(idx))
	return
}

// RenderOptions specifies a set of options for rendering a page.
type RenderOptions struct {
	// The color to fill the image with before it is drawn.
	FillColor image.RGBAColor
	// Disable anti-aliasing
	NoAA bool
}

// Get the internal size of the Page
func (page *Page) Size() (width, height float64) {
	var (
		dw, dh C.double
	)
	C.poppler_page_get_size(page.page, &dw, &dh);
	return float64(dw), float64(dh)
}

// Render the page to an image.Image
func (page *Page) Render(width int, height int, opts *RenderOptions) image.Image {
	surface := C.cairo_image_surface_create(C.CAIRO_FORMAT_ARGB32, C.int(width), C.int(height))
	ctx := C.cairo_create(surface)

	ow, oh := page.Size()
	fw := float64(width)
	fh := float64(height)
	sw, sh := float64(fw/ow), float64(fh/oh)
	C.cairo_scale(ctx, C.double(sw), C.double(sh))

	fillColor := image.RGBAColor{255, 255, 255, 255}
	if opts != nil {
		fillColor = opts.FillColor
	}
	C.cairo_set_source_rgba(ctx, C.double(float64(fillColor.R)/float64(255)),
	                             C.double(float64(fillColor.G)/float64(255)),
	                             C.double(float64(fillColor.B)/float64(255)),
	                             C.double(float64(fillColor.A)/float64(255)))
	C.cairo_rectangle(ctx, 0, 0, C.double(width), C.double(height));
	C.cairo_fill(ctx);

	if opts != nil && opts.NoAA {
		C.cairo_set_antialias(ctx, C.CAIRO_ANTIALIAS_NONE)
	}

	C.poppler_page_render_for_printing(page.page, ctx)
	data := C.cairo_image_surface_get_data(surface)
	nrgba := image.NewNRGBA(width, height)
	for x := 0; x < width; x++ {
		for y := 0; y < height; y++ {
			nrgba.SetNRGBA(x, y, image.NRGBAColor{
				R: uint8(C.getbyte(data, C.int(x*4 + 4*y*width + 2))),
				G: uint8(C.getbyte(data, C.int(x*4 + 4*y*width + 1))),
				B: uint8(C.getbyte(data, C.int(x*4 + 4*y*width + 0))),
				A: uint8(C.getbyte(data, C.int(x*4 + 4*y*width + 3))),
			})
		}
	}
	return nrgba
}<commit_msg>Cairo memory management.<commit_after>// Copyright (c) 2011 Mikkel Krautz
// The use of this source code is goverened by a BSD-style
// license that can be found in the LICENSE-file.

// Package pdfdraw implements a library for rendering and reading PDFs (Currently implemented on top of poppler-glib)
package pdfdraw

/*
#cgo pkg-config: poppler-glib cairo
#include <stdlib.h>
#include <poppler.h>
#include <cairo.h>

static unsigned char getbyte(unsigned char *buf, int idx) {
	return buf[idx];
}

static char *path_to_uri(char *path) {
	GError *err = NULL;
	gchar *absfn = NULL;

	if (g_path_is_absolute(path))
		absfn = g_strdup(path);
	else {
		gchar *tmp = g_get_current_dir();
		absfn = g_build_filename(tmp, path, NULL);
		free(tmp);
	}

	return (char *) g_filename_to_uri(absfn, NULL, &err);
}
*/
import "C"

import (
	"image"
	"os"
	"unsafe"
)

func init() {
	C.g_type_init()
}

// A Document represents a PDF document
type Document struct {
	doc *C.PopplerDocument
}

// A Page represents a page in a Document
type Page struct {
	page *C.PopplerPage
}

// Open a PDF file at path and return a Document
func Open(path string) (doc *Document, err os.Error) {
	uri := C.path_to_uri(C.CString(path))
	if uri == nil {
		return nil, os.NewError("unable to convert path to uri")
	}
	defer C.free(unsafe.Pointer(uri))

	doc = new(Document)
	doc.doc = C.poppler_document_new_from_file(uri, nil, nil)
	if doc.doc == nil {
		return nil, os.NewError("unable to open file")
	}

	return doc, nil
}

// Get the total number of pages in the Document
func (doc *Document) NumPages() int {
	return int(C.poppler_document_get_n_pages(doc.doc))
}

// Get a Page
func (doc *Document) Page(idx int) (page *Page) {
	page = new(Page)
	page.page = C.poppler_document_get_page(doc.doc, C.int(idx))
	return
}

// RenderOptions specifies a set of options for rendering a page.
type RenderOptions struct {
	// The color to fill the image with before it is drawn.
	FillColor image.RGBAColor
	// Disable anti-aliasing
	NoAA bool
}

// Get the internal size of the Page
func (page *Page) Size() (width, height float64) {
	var (
		dw, dh C.double
	)
	C.poppler_page_get_size(page.page, &dw, &dh);
	return float64(dw), float64(dh)
}

// Render the page to an image.Image
func (page *Page) Render(width int, height int, opts *RenderOptions) image.Image {
	surface := C.cairo_image_surface_create(C.CAIRO_FORMAT_ARGB32, C.int(width), C.int(height))
	defer C.cairo_surface_destroy(surface)

	ctx := C.cairo_create(surface)
	defer C.cairo_destroy(ctx)

	ow, oh := page.Size()
	fw := float64(width)
	fh := float64(height)
	sw, sh := float64(fw/ow), float64(fh/oh)
	C.cairo_scale(ctx, C.double(sw), C.double(sh))

	fillColor := image.RGBAColor{255, 255, 255, 255}
	if opts != nil {
		fillColor = opts.FillColor
	}
	C.cairo_set_source_rgba(ctx, C.double(float64(fillColor.R)/float64(255)),
	                             C.double(float64(fillColor.G)/float64(255)),
	                             C.double(float64(fillColor.B)/float64(255)),
	                             C.double(float64(fillColor.A)/float64(255)))
	C.cairo_rectangle(ctx, 0, 0, C.double(width), C.double(height));
	C.cairo_fill(ctx);

	if opts != nil && opts.NoAA {
		C.cairo_set_antialias(ctx, C.CAIRO_ANTIALIAS_NONE)
	}

	C.poppler_page_render_for_printing(page.page, ctx)
	data := C.cairo_image_surface_get_data(surface)
	nrgba := image.NewNRGBA(width, height)
	for x := 0; x < width; x++ {
		for y := 0; y < height; y++ {
			nrgba.SetNRGBA(x, y, image.NRGBAColor{
				R: uint8(C.getbyte(data, C.int(x*4 + 4*y*width + 2))),
				G: uint8(C.getbyte(data, C.int(x*4 + 4*y*width + 1))),
				B: uint8(C.getbyte(data, C.int(x*4 + 4*y*width + 0))),
				A: uint8(C.getbyte(data, C.int(x*4 + 4*y*width + 3))),
			})
		}
	}

	return nrgba
}<|endoftext|>


<commit_before>package pgn

import (
	"fmt"
	"io"
	"strings"
	"text/scanner"
)

type PGNScanner struct {
	s scanner.Scanner
}

type Game struct {
	Moves []Move
	Tags  map[string]string
}

type Move struct {
	From    Position
	To      Position
	Promote Piece
}

func (m Move) String() string {
	if m.Promote == NoPiece {
		return fmt.Sprintf("%v%v", m.From, m.To)
	}
	return fmt.Sprintf("%v%v%v", m.From, m.To, m.Promote)
}

var (
	NilMove Move = Move{From: NoPosition, To: NoPosition}
)

func ParseGame(s *scanner.Scanner) (*Game, error) {
	g := Game{Tags: map[string]string{}, Moves: []Move{}}
	err := ParseTags(s, &g)
	if err != nil {
		return nil, err
	}
	err = ParseMoves(s, &g)
	if err != nil {
		return nil, err
	}
	return &g, nil
}

func ParseTags(s *scanner.Scanner, g *Game) error {
	//fmt.Println("starting tags parse")
	run := s.Peek()
	for run != scanner.EOF {
		switch run {
		case '[', ']', '\n', '\r':
			run = s.Next()
		case '1':
			return nil
		default:
			s.Scan()
			tag := s.TokenText()
			s.Scan()
			val := s.TokenText()
			//fmt.Println("tag:", tag, "; val:", val)
			g.Tags[tag] = strings.Trim(val, "\"")
		}
		run = s.Peek()
	}
	return nil
}

func isEnd(str string) bool {
	if str == "1/2-1/2" {
		return true
	}
	if str == "0-1" {
		return true
	}
	if str == "1-0" {
		return true
	}
	return false
}

func ParseMoves(s *scanner.Scanner, g *Game) error {
	//fmt.Println("starting moves parse")
	s.Mode = scanner.ScanIdents | scanner.ScanChars | scanner.ScanInts | scanner.ScanStrings
	run := s.Peek()
	board := NewBoard()
	var err error
	if len(g.Tags["FEN"]) > 0 {
		board, err = NewBoardFEN(g.Tags["FEN"])
		if err != nil {
			return err
		}
	}
	num := ""
	white := ""
	black := ""
	for run != scanner.EOF {
		switch run {
		case '(':
			for run != ')' && run != scanner.EOF {
				run = s.Next()
			}
		case '{':
			for run != '}' && run != scanner.EOF {
				run = s.Next()
			}
		case '#', '.', '+', '!', '?', '\n', '\r':
			run = s.Next()
			run = s.Peek()
		default:
			s.Scan()
			if s.TokenText() == "{" {
				run = '{'
				continue
			}
			if num == "" {
				num = s.TokenText()
				for s.Peek() == '-' {
					s.Scan()
					num += s.TokenText()
					s.Scan()
					num += s.TokenText()
				}
				for s.Peek() == '/' {
					s.Scan()
					num += s.TokenText()
					s.Scan()
					num += s.TokenText()
					s.Scan()
					num += s.TokenText()
					s.Scan()
					num += s.TokenText()
					s.Scan()
					num += s.TokenText()
					s.Scan()
					num += s.TokenText()
				}
				if isEnd(num) {
					return nil
				}
			} else if white == "" {
				white = s.TokenText()
				for s.Peek() == '-' {
					s.Scan()
					white += s.TokenText()
					s.Scan()
					white += s.TokenText()
				}
				for s.Peek() == '/' {
					s.Scan()
					white += s.TokenText()
					s.Scan()
					white += s.TokenText()
					s.Scan()
					white += s.TokenText()
					s.Scan()
					white += s.TokenText()
					s.Scan()
					white += s.TokenText()
					s.Scan()
					white += s.TokenText()
				}
				if isEnd(white) {
					return nil
				}
				if s.Peek() == '=' {
					s.Scan()
					white += s.TokenText()
					s.Scan()
					white += s.TokenText()
				}
				move, err := board.MoveFromAlgebraic(white, White)
				if err != nil {
					fmt.Println(board)
					return err
				}
				g.Moves = append(g.Moves, move)
				board.MakeMove(move)
			} else if black == "" {
				black = s.TokenText()
				for s.Peek() == '-' {
					s.Scan()
					black += s.TokenText()
					s.Scan()
					black += s.TokenText()
				}
				for s.Peek() == '/' {
					s.Scan()
					black += s.TokenText()
					s.Scan()
					black += s.TokenText()
					s.Scan()
					black += s.TokenText()
					s.Scan()
					black += s.TokenText()
					s.Scan()
					black += s.TokenText()
					s.Scan()
					black += s.TokenText()
				}
				if isEnd(black) {
					return nil
				}
				if s.Peek() == '=' {
					s.Scan()
					black += s.TokenText()
					s.Scan()
					black += s.TokenText()
				}
				move, err := board.MoveFromAlgebraic(black, Black)
				if err != nil {
					fmt.Println(board)
					return err
				}
				g.Moves = append(g.Moves, move)
				board.MakeMove(move)
				num = ""
				white = ""
				black = ""
			}
			run = s.Peek()
		}
	}
	return nil
}

func NewPGNScanner(r io.Reader) *PGNScanner {
	s := scanner.Scanner{}
	s.Init(r)
	return &PGNScanner{s: s}
}

func (ps *PGNScanner) Next() bool {
	if ps.s.Peek() == scanner.EOF {
		return false
	}
	return true
}

func (ps *PGNScanner) Scan() (*Game, error) {
	game, err := ParseGame(&ps.s)
	//fmt.Println(game)
	return game, err
}
<commit_msg>remove board print statements on error<commit_after>package pgn

import (
	"fmt"
	"io"
	"strings"
	"text/scanner"
)

type PGNScanner struct {
	s scanner.Scanner
}

type Game struct {
	Moves []Move
	Tags  map[string]string
}

type Move struct {
	From    Position
	To      Position
	Promote Piece
}

func (m Move) String() string {
	if m.Promote == NoPiece {
		return fmt.Sprintf("%v%v", m.From, m.To)
	}
	return fmt.Sprintf("%v%v%v", m.From, m.To, m.Promote)
}

var (
	NilMove Move = Move{From: NoPosition, To: NoPosition}
)

func ParseGame(s *scanner.Scanner) (*Game, error) {
	g := Game{Tags: map[string]string{}, Moves: []Move{}}
	err := ParseTags(s, &g)
	if err != nil {
		return nil, err
	}
	err = ParseMoves(s, &g)
	if err != nil {
		return nil, err
	}
	return &g, nil
}

func ParseTags(s *scanner.Scanner, g *Game) error {
	//fmt.Println("starting tags parse")
	run := s.Peek()
	for run != scanner.EOF {
		switch run {
		case '[', ']', '\n', '\r':
			run = s.Next()
		case '1':
			return nil
		default:
			s.Scan()
			tag := s.TokenText()
			s.Scan()
			val := s.TokenText()
			//fmt.Println("tag:", tag, "; val:", val)
			g.Tags[tag] = strings.Trim(val, "\"")
		}
		run = s.Peek()
	}
	return nil
}

func isEnd(str string) bool {
	if str == "1/2-1/2" {
		return true
	}
	if str == "0-1" {
		return true
	}
	if str == "1-0" {
		return true
	}
	return false
}

func ParseMoves(s *scanner.Scanner, g *Game) error {
	//fmt.Println("starting moves parse")
	s.Mode = scanner.ScanIdents | scanner.ScanChars | scanner.ScanInts | scanner.ScanStrings
	run := s.Peek()
	board := NewBoard()
	var err error
	if len(g.Tags["FEN"]) > 0 {
		board, err = NewBoardFEN(g.Tags["FEN"])
		if err != nil {
			return err
		}
	}
	num := ""
	white := ""
	black := ""
	for run != scanner.EOF {
		switch run {
		case '(':
			for run != ')' && run != scanner.EOF {
				run = s.Next()
			}
		case '{':
			for run != '}' && run != scanner.EOF {
				run = s.Next()
			}
		case '#', '.', '+', '!', '?', '\n', '\r':
			run = s.Next()
			run = s.Peek()
		default:
			s.Scan()
			if s.TokenText() == "{" {
				run = '{'
				continue
			}
			if num == "" {
				num = s.TokenText()
				for s.Peek() == '-' {
					s.Scan()
					num += s.TokenText()
					s.Scan()
					num += s.TokenText()
				}
				for s.Peek() == '/' {
					s.Scan()
					num += s.TokenText()
					s.Scan()
					num += s.TokenText()
					s.Scan()
					num += s.TokenText()
					s.Scan()
					num += s.TokenText()
					s.Scan()
					num += s.TokenText()
					s.Scan()
					num += s.TokenText()
				}
				if isEnd(num) {
					return nil
				}
			} else if white == "" {
				white = s.TokenText()
				for s.Peek() == '-' {
					s.Scan()
					white += s.TokenText()
					s.Scan()
					white += s.TokenText()
				}
				for s.Peek() == '/' {
					s.Scan()
					white += s.TokenText()
					s.Scan()
					white += s.TokenText()
					s.Scan()
					white += s.TokenText()
					s.Scan()
					white += s.TokenText()
					s.Scan()
					white += s.TokenText()
					s.Scan()
					white += s.TokenText()
				}
				if isEnd(white) {
					return nil
				}
				if s.Peek() == '=' {
					s.Scan()
					white += s.TokenText()
					s.Scan()
					white += s.TokenText()
				}
				move, err := board.MoveFromAlgebraic(white, White)
				if err != nil {
					return err
				}
				g.Moves = append(g.Moves, move)
				board.MakeMove(move)
			} else if black == "" {
				black = s.TokenText()
				for s.Peek() == '-' {
					s.Scan()
					black += s.TokenText()
					s.Scan()
					black += s.TokenText()
				}
				for s.Peek() == '/' {
					s.Scan()
					black += s.TokenText()
					s.Scan()
					black += s.TokenText()
					s.Scan()
					black += s.TokenText()
					s.Scan()
					black += s.TokenText()
					s.Scan()
					black += s.TokenText()
					s.Scan()
					black += s.TokenText()
				}
				if isEnd(black) {
					return nil
				}
				if s.Peek() == '=' {
					s.Scan()
					black += s.TokenText()
					s.Scan()
					black += s.TokenText()
				}
				move, err := board.MoveFromAlgebraic(black, Black)
				if err != nil {
					return err
				}
				g.Moves = append(g.Moves, move)
				board.MakeMove(move)
				num = ""
				white = ""
				black = ""
			}
			run = s.Peek()
		}
	}
	return nil
}

func NewPGNScanner(r io.Reader) *PGNScanner {
	s := scanner.Scanner{}
	s.Init(r)
	return &PGNScanner{s: s}
}

func (ps *PGNScanner) Next() bool {
	if ps.s.Peek() == scanner.EOF {
		return false
	}
	return true
}

func (ps *PGNScanner) Scan() (*Game, error) {
	game, err := ParseGame(&ps.s)
	//fmt.Println(game)
	return game, err
}
<|endoftext|>


<commit_before>// Package red implements server speaking redis serialization protocol.
package red

import (
	"bufio"
	"errors"
	"io"
	"net"
	"strings"
	"time"

	"github.com/artyom/resp"
)

// HandlerFunc is a type of command processing function. It should return value
// that's passed to resp.Encode function, so it's expected such function would
// return values of resp package types.
type HandlerFunc func(req Request) (interface{}, error)

// Request holds information about single redis command.
type Request struct {
	Name string   // lowercase command itself (first word)
	Args []string // command arguments
}

// NewServer returns initialized server.
func NewServer() *Server {
	return &Server{log: noopLogger{}}
}

// WithLogger configures server to use provided Logger.
func (s *Server) WithLogger(l Logger) {
	if l != nil {
		s.log = l
	}
}

// Handle registers handler for command with given name
func (s *Server) Handle(name string, h HandlerFunc) {
	if s.handlers == nil {
		s.handlers = make(map[string]HandlerFunc)
	}
	s.handlers[name] = h
}

// Server implements server speaking RESP (REdis Serialization Protocol). Server
// automatically handles MULTI & EXEC commands for transactions, QUIT for
// client-initiated disconnect, other commands are expected to be implemented
// separately and registered with Handle method.
type Server struct {
	log      Logger
	handlers map[string]HandlerFunc
}

// HandleConn processes single client connection, automatically handling
// following commands MULTI/EXEC (transactions), QUIT (client disconnect). It
// calls user-provided handlers for registered commands.
func (s *Server) HandleConn(conn io.ReadWriteCloser) error {
	defer conn.Close()
	rd := bufio.NewReader(conn)
	var tx []Request
	var inTx bool  // if we're inside transaction
	var errTx bool // true if transaction seen error and should be discarded
	var err error
	for {
		if err != nil {
			return err
		}
		req, err := resp.DecodeRequest(rd)
		switch err {
		case nil:
		case resp.ErrInvalidRequest:
			err = resp.Encode(conn, resp.Error("ERR unknown command"))
			continue
		default:
			return err
		}
		cmd := strings.ToLower(req[0])
		s.log.Println("REQ:", req)
		switch cmd {
		case "quit":
			return nil
		case "multi":
			if len(req) != 1 {
				if inTx {
					errTx = true
				}
				err = resp.Encode(conn, errWrongArgs(cmd))
				continue
			}
			if inTx {
				errTx = true
				err = resp.Encode(conn, resp.Error("ERR MULTI calls can not be nested"))
				continue
			}
			inTx, errTx = true, false
			err = resp.Encode(conn, resp.OK{})
			continue
		case "exec":
			if len(req) != 1 {
				if inTx {
					errTx = true
				}
				err = resp.Encode(conn, errWrongArgs(cmd))
				continue
			}
			if !inTx {
				err = resp.Encode(conn, resp.Error("ERR EXEC without MULTI"))
				continue
			}
			if errTx {
				inTx, errTx = false, false
				tx = tx[:0]
				err = resp.Encode(conn, resp.Error("EXECABORT Transaction discarded because of previous errors."))
				continue
			}
		default:
			h, ok := s.handlers[cmd]
			if !ok {
				if inTx {
					errTx = true
				}
				err = resp.Encode(conn, errNoCmd(cmd))
				continue
			}
			if inTx {
				if !errTx {
					tx = append(tx, Request{Name: cmd, Args: req[1:]})
				}
				err = resp.Encode(conn, resp.SimpleString("QUEUED"))
				continue
			}
			err = resp.Encode(conn, singleVal(h, Request{Name: cmd, Args: req[1:]}))
			continue
		}

		txReplies := make(resp.Array, 0, len(tx))
		for _, r := range tx {
			h, ok := s.handlers[r.Name]
			if !ok {
				txReplies = append(txReplies, errNoCmd(r.Name))
				continue
			}
			txReplies = append(txReplies, singleVal(h, r))
		}
		inTx, errTx = false, false
		tx = tx[:0]
		err = resp.Encode(conn, txReplies)
	}
}

// ListenAndServe listens on TCP network address addr and then calls Serve to
// handle requests on incoming connections.
func (s *Server) ListenAndServe(addr string) error {
	ln, err := net.Listen("tcp", addr)
	if err != nil {
		return err
	}
	return s.Serve(tcpKeepAliveListener{ln.(*net.TCPListener)})
}

// Serve accepts incoming connections on the Listener l, creating a new service
// goroutine for each.
func (s *Server) Serve(l net.Listener) error {
	defer l.Close()
	for {
		conn, err := l.Accept()
		if err != nil {
			return err
		}
		go func(c net.Conn) {
			switch err := s.HandleConn(c); err {
			case nil, io.EOF:
			default:
				if s.log != nil {
					s.log.Println(err)
				}
			}
		}(conn)
	}
}

// Logger is a set of methods used to log information. *log.Logger implements
// this interface.
type Logger interface {
	Print(v ...interface{})
	Printf(format string, v ...interface{})
	Println(v ...interface{})
}

type noopLogger struct{}

func (noopLogger) Print(v ...interface{})                 {}
func (noopLogger) Printf(format string, v ...interface{}) {}
func (noopLogger) Println(v ...interface{})               {}

func errNoCmd(name string) resp.Error { return resp.Error("ERR unknown command '" + name + "'") }

// ErrWrongArgs are expected to be returned by HandlerFunc implementations when
// number of arguments are wrong. This error automatically to client with
// command name annotated.
var ErrWrongArgs = errors.New("wrong number of arguments")

func errWrongArgs(name string) resp.Error {
	return resp.Error("ERR wrong number of arguments for '" + name + "' command")
}

// silgleVal calls HandlerFunc h with given Request r and returns single value
// that is expected to be passed to resp.Encode.
//
// If h returns a non-nil error, then singleVal returns resp.Error type,
// otherwise it's an interface{} returned by h.
func singleVal(h HandlerFunc, r Request) interface{} {
	v, err := h(r)
	if err != nil {
		if err == ErrWrongArgs {
			return errWrongArgs(r.Name)
		}
		text := err.Error()
		if strings.ContainsAny(text, "\r\n") {
			text = strings.Replace(text, "\r", " ", -1)
			text = strings.Replace(text, "\n", " ", -1)
		}
		return resp.Error("ERR " + text)
	}
	return v
}

// tcpKeepAliveListener sets TCP keep-alive timeouts on accepted
// connections. It's used by ListenAndServe and ListenAndServeTLS so
// dead TCP connections (e.g. closing laptop mid-download) eventually
// go away.
type tcpKeepAliveListener struct {
	*net.TCPListener
}

func (ln tcpKeepAliveListener) Accept() (c net.Conn, err error) {
	tc, err := ln.AcceptTCP()
	if err != nil {
		return
	}
	tc.SetKeepAlive(true)
	tc.SetKeepAlivePeriod(3 * time.Minute)
	return tc, nil
}
<commit_msg>Make sure Handle is non case-sensitive<commit_after>// Package red implements server speaking redis serialization protocol.
package red

import (
	"bufio"
	"errors"
	"io"
	"net"
	"strings"
	"time"

	"github.com/artyom/resp"
)

// HandlerFunc is a type of command processing function. It should return value
// that's passed to resp.Encode function, so it's expected such function would
// return values of resp package types.
type HandlerFunc func(req Request) (interface{}, error)

// Request holds information about single redis command.
type Request struct {
	Name string   // lowercase command itself (first word)
	Args []string // command arguments
}

// NewServer returns initialized server.
func NewServer() *Server {
	return &Server{log: noopLogger{}}
}

// WithLogger configures server to use provided Logger.
func (s *Server) WithLogger(l Logger) {
	if l != nil {
		s.log = l
	}
}

// Handle registers handler for command with given name (case-insensitive)
func (s *Server) Handle(name string, h HandlerFunc) {
	if name == "" {
		panic("Handle called with empty name")
	}
	if h == nil {
		panic("Handle called with nil HandlerFunc")
	}
	if s.handlers == nil {
		s.handlers = make(map[string]HandlerFunc)
	}
	s.handlers[strings.ToLower(name)] = h
}

// Server implements server speaking RESP (REdis Serialization Protocol). Server
// automatically handles MULTI & EXEC commands for transactions, QUIT for
// client-initiated disconnect, other commands are expected to be implemented
// separately and registered with Handle method.
type Server struct {
	log      Logger
	handlers map[string]HandlerFunc
}

// HandleConn processes single client connection, automatically handling
// following commands MULTI/EXEC (transactions), QUIT (client disconnect). It
// calls user-provided handlers for registered commands.
func (s *Server) HandleConn(conn io.ReadWriteCloser) error {
	defer conn.Close()
	rd := bufio.NewReader(conn)
	var tx []Request
	var inTx bool  // if we're inside transaction
	var errTx bool // true if transaction seen error and should be discarded
	var err error
	for {
		if err != nil {
			return err
		}
		req, err := resp.DecodeRequest(rd)
		switch err {
		case nil:
		case resp.ErrInvalidRequest:
			err = resp.Encode(conn, resp.Error("ERR unknown command"))
			continue
		default:
			return err
		}
		cmd := strings.ToLower(req[0])
		s.log.Println("REQ:", req)
		switch cmd {
		case "quit":
			return nil
		case "multi":
			if len(req) != 1 {
				if inTx {
					errTx = true
				}
				err = resp.Encode(conn, errWrongArgs(cmd))
				continue
			}
			if inTx {
				errTx = true
				err = resp.Encode(conn, resp.Error("ERR MULTI calls can not be nested"))
				continue
			}
			inTx, errTx = true, false
			err = resp.Encode(conn, resp.OK{})
			continue
		case "exec":
			if len(req) != 1 {
				if inTx {
					errTx = true
				}
				err = resp.Encode(conn, errWrongArgs(cmd))
				continue
			}
			if !inTx {
				err = resp.Encode(conn, resp.Error("ERR EXEC without MULTI"))
				continue
			}
			if errTx {
				inTx, errTx = false, false
				tx = tx[:0]
				err = resp.Encode(conn, resp.Error("EXECABORT Transaction discarded because of previous errors."))
				continue
			}
		default:
			h, ok := s.handlers[cmd]
			if !ok {
				if inTx {
					errTx = true
				}
				err = resp.Encode(conn, errNoCmd(cmd))
				continue
			}
			if inTx {
				if !errTx {
					tx = append(tx, Request{Name: cmd, Args: req[1:]})
				}
				err = resp.Encode(conn, resp.SimpleString("QUEUED"))
				continue
			}
			err = resp.Encode(conn, singleVal(h, Request{Name: cmd, Args: req[1:]}))
			continue
		}

		txReplies := make(resp.Array, 0, len(tx))
		for _, r := range tx {
			h, ok := s.handlers[r.Name]
			if !ok {
				txReplies = append(txReplies, errNoCmd(r.Name))
				continue
			}
			txReplies = append(txReplies, singleVal(h, r))
		}
		inTx, errTx = false, false
		tx = tx[:0]
		err = resp.Encode(conn, txReplies)
	}
}

// ListenAndServe listens on TCP network address addr and then calls Serve to
// handle requests on incoming connections.
func (s *Server) ListenAndServe(addr string) error {
	ln, err := net.Listen("tcp", addr)
	if err != nil {
		return err
	}
	return s.Serve(tcpKeepAliveListener{ln.(*net.TCPListener)})
}

// Serve accepts incoming connections on the Listener l, creating a new service
// goroutine for each.
func (s *Server) Serve(l net.Listener) error {
	defer l.Close()
	for {
		conn, err := l.Accept()
		if err != nil {
			return err
		}
		go func(c net.Conn) {
			switch err := s.HandleConn(c); err {
			case nil, io.EOF:
			default:
				if s.log != nil {
					s.log.Println(err)
				}
			}
		}(conn)
	}
}

// Logger is a set of methods used to log information. *log.Logger implements
// this interface.
type Logger interface {
	Print(v ...interface{})
	Printf(format string, v ...interface{})
	Println(v ...interface{})
}

type noopLogger struct{}

func (noopLogger) Print(v ...interface{})                 {}
func (noopLogger) Printf(format string, v ...interface{}) {}
func (noopLogger) Println(v ...interface{})               {}

func errNoCmd(name string) resp.Error { return resp.Error("ERR unknown command '" + name + "'") }

// ErrWrongArgs are expected to be returned by HandlerFunc implementations when
// number of arguments are wrong. This error automatically to client with
// command name annotated.
var ErrWrongArgs = errors.New("wrong number of arguments")

func errWrongArgs(name string) resp.Error {
	return resp.Error("ERR wrong number of arguments for '" + name + "' command")
}

// silgleVal calls HandlerFunc h with given Request r and returns single value
// that is expected to be passed to resp.Encode.
//
// If h returns a non-nil error, then singleVal returns resp.Error type,
// otherwise it's an interface{} returned by h.
func singleVal(h HandlerFunc, r Request) interface{} {
	v, err := h(r)
	if err != nil {
		if err == ErrWrongArgs {
			return errWrongArgs(r.Name)
		}
		text := err.Error()
		if strings.ContainsAny(text, "\r\n") {
			text = strings.Replace(text, "\r", " ", -1)
			text = strings.Replace(text, "\n", " ", -1)
		}
		return resp.Error("ERR " + text)
	}
	return v
}

// tcpKeepAliveListener sets TCP keep-alive timeouts on accepted
// connections. It's used by ListenAndServe and ListenAndServeTLS so
// dead TCP connections (e.g. closing laptop mid-download) eventually
// go away.
type tcpKeepAliveListener struct {
	*net.TCPListener
}

func (ln tcpKeepAliveListener) Accept() (c net.Conn, err error) {
	tc, err := ln.AcceptTCP()
	if err != nil {
		return
	}
	tc.SetKeepAlive(true)
	tc.SetKeepAlivePeriod(3 * time.Minute)
	return tc, nil
}
<|endoftext|>


<commit_before>/*
  Go Language Raspberry Pi Interface
  (c) Copyright David Thorpe 2016-2020
  All Rights Reserved
  For Licensing and Usage information, please see LICENSE.md
*/

package gopi

import (
	"context"
	"fmt"
	"net"
	"strconv"
	"strings"
	"time"
)

////////////////////////////////////////////////////////////////////////////////
// TYPES

// RPCServiceRecord defines a service which can be registered or discovered
// on the network
type RPCServiceRecord struct {
	Name    string
	Service string
	Host    string
	Port    uint16
	Addrs   []net.IP
	Txt     []string
}

type (
	RPCFlag      uint // RPCFlag is a set of flags modifying behavior
	RPCEventType uint // RPCEventType is an enumeration of event types
)

////////////////////////////////////////////////////////////////////////////////
// INTERFACES

// RPCServiceDiscovery will lookup services and classes of service
type RPCServiceDiscovery interface {
	// Lookup service instances by name
	Lookup(ctx context.Context, service string) ([]RPCServiceRecord, error)

	// Return list of service names
	EnumerateServices(ctx context.Context) ([]string, error)

	// Implements gopi.Unit
	Unit
}

// RPCServiceRegister will register services
type RPCServiceRegister interface {
	// Register service record, and de-register when deadline is exceeded
	Register(ctx context.Context, record RPCServiceRecord) error

	// Implements gopi.Unit
	Unit
}

// RPCServer serves requests for one or more services
type RPCServer interface {
	// Start an RPC server in currently running thread.
	// The method will not return until Stop is called
	// which needs to be done in a different thread
	Start() error

	// Stop RPC server. If halt is true then it immediately
	// ends the server without waiting for current requests to
	// be served
	Stop(halt bool) error

	// Return address the server is bound to, or nil if
	// the server is not running
	Addr() net.Addr

	// Implements gopi.Unit
	Unit
}

// RPCService is a driver which implements all the necessary
// methods to handle remote calls
type RPCService interface {
	// CancelRequests is called by the server to gracefully end any
	// on-going streaming requests, but before the service is shutdown
	CancelRequests() error

	// Implements gopi.Unit
	Unit
}

// RPCEvent is emitted on service discovery and server events
type RPCEvent interface {
	// Type of event
	Type() RPCEventType

	// Service record associated with event
	Service() RPCServiceRecord

	// Time-to-live value for event
	TTL() time.Duration

	// Implements gopi.Event
	Event
}

////////////////////////////////////////////////////////////////////////////////
// CONSTANTS

const (
	RPC_FLAG_NONE          RPCFlag = 0
	RPC_FLAG_INET_UDP      RPCFlag = (1 << iota) >> 1 // Use UDP protocol (TCP assumed otherwise)
	RPC_FLAG_INET_V4                                  // Use V4 addressing
	RPC_FLAG_INET_V6                                  // Use V6 addressing
	RPC_FLAG_SERVICE_FIRST                            // Use first service
	RPC_FLAG_SERVICE_ANY                              // Use any service
	RPC_FLAG_MIN           = RPC_FLAG_INET_UDP
	RPC_FLAG_MAX           = RPC_FLAG_SERVICE_ANY
)

const (
	RPC_EVENT_NONE            RPCEventType = iota
	RPC_EVENT_SERVER_STARTED               // RPC Server started
	RPC_EVENT_SERVER_STOPPED               // RPC Server stopped
	RPC_EVENT_SERVICE_ADDED                // Service instance lookup (new)
	RPC_EVENT_SERVICE_UPDATED              // Service instance lookup (updated)
	RPC_EVENT_SERVICE_REMOVED              // Service instance lookup (removed)
	RPC_EVENT_SERVICE_EXPIRED              // Service instance lookup (expired)
	RPC_EVENT_SERVICE_NAME                 // Service name discovered
	RPC_EVENT_SERVICE_RECORD               // Service record lookup
	RPC_EVENT_CLIENT_CONNECTED
	RPC_EVENT_CLIENT_DISCONNECTED
	RPC_EVENT_MAX = RPC_EVENT_CLIENT_DISCONNECTED
)

////////////////////////////////////////////////////////////////////////////////
// STRINGIFY

func (f RPCFlag) String() string {
	str := ""
	if f == 0 {
		return f.FlagString()
	}
	for v := RPC_FLAG_MIN; v <= RPC_FLAG_MAX; v <<= 1 {
		if f&v == v {
			str += "|" + v.FlagString()
		}
	}
	return strings.TrimPrefix(str, "|")
}

func (v RPCFlag) FlagString() string {
	switch v {
	case RPC_FLAG_NONE:
		return "RPC_FLAG_NONE"
	case RPC_FLAG_INET_UDP:
		return "RPC_FLAG_INET_UDP"
	case RPC_FLAG_INET_V4:
		return "RPC_FLAG_INET_V4"
	case RPC_FLAG_INET_V6:
		return "RPC_FLAG_INET_V6"
	case RPC_FLAG_SERVICE_FIRST:
		return "RPC_FLAG_SERVICE_FIRST"
	case RPC_FLAG_SERVICE_ANY:
		return "RPC_FLAG_SERVICE_ANY"
	default:
		return "[?? Invalid PlatformType value]"
	}
}

func (t RPCEventType) String() string {
	switch t {
	case RPC_EVENT_NONE:
		return "RPC_EVENT_NONE"
	case RPC_EVENT_SERVER_STARTED:
		return "RPC_EVENT_SERVER_STARTED"
	case RPC_EVENT_SERVER_STOPPED:
		return "RPC_EVENT_SERVER_STOPPED"
	case RPC_EVENT_SERVICE_ADDED:
		return "RPC_EVENT_SERVICE_ADDED"
	case RPC_EVENT_SERVICE_UPDATED:
		return "RPC_EVENT_SERVICE_UPDATED"
	case RPC_EVENT_SERVICE_REMOVED:
		return "RPC_EVENT_SERVICE_REMOVED"
	case RPC_EVENT_SERVICE_EXPIRED:
		return "RPC_EVENT_SERVICE_EXPIRED"
	case RPC_EVENT_SERVICE_NAME:
		return "RPC_EVENT_SERVICE_NAME"
	case RPC_EVENT_SERVICE_RECORD:
		return "RPC_EVENT_SERVICE_RECORD"
	case RPC_EVENT_CLIENT_CONNECTED:
		return "RPC_EVENT_CLIENT_CONNECTED"
	case RPC_EVENT_CLIENT_DISCONNECTED:
		return "RPC_EVENT_CLIENT_DISCONNECTED"
	default:
		return "[?? Invalid RPCEventType value]"
	}
}

func (this RPCServiceRecord) String() string {
	str := "<RPCServiceRecord name=" + strconv.Quote(this.Name)
	if this.Service != "" {
		str += " service=" + strconv.Quote(this.Service)
	}
	if this.Host != "" {
		str += " host=" + strconv.Quote(this.Host)
	}
	if this.Port != 0 {
		str += " port=" + fmt.Sprint(this.Port)
	}
	if len(this.Addrs) > 0 {
		str += " addrs="
		for _, addr := range this.Addrs {
			str += addr.String() + ","
		}
		str = strings.TrimSuffix(str, ",")
	}
	if len(this.Txt) > 0 {
		str += " txt=" + fmt.Sprint(this.Txt)
	}
	str += ">"
	return str
}
<commit_msg>Added client pool<commit_after>/*
  Go Language Raspberry Pi Interface
  (c) Copyright David Thorpe 2016-2020
  All Rights Reserved
  For Licensing and Usage information, please see LICENSE.md
*/

package gopi

import (
	"context"
	"fmt"
	"net"
	"strconv"
	"strings"
	"time"
)

////////////////////////////////////////////////////////////////////////////////
// TYPES

// RPCServiceRecord defines a service which can be registered or discovered
// on the network
type RPCServiceRecord struct {
	Name    string
	Service string
	Host    string
	Port    uint16
	Addrs   []net.IP
	Txt     []string
}

type (
	RPCFlag      uint // RPCFlag is a set of flags modifying behavior
	RPCEventType uint // RPCEventType is an enumeration of event types
)

////////////////////////////////////////////////////////////////////////////////
// INTERFACES

// RPCServiceDiscovery will lookup services and classes of service
type RPCServiceDiscovery interface {
	// Lookup service instances by name
	Lookup(ctx context.Context, service string) ([]RPCServiceRecord, error)

	// Return list of service names
	EnumerateServices(ctx context.Context) ([]string, error)

	// Implements gopi.Unit
	Unit
}

// RPCServiceRegister will register services
type RPCServiceRegister interface {
	// Register service record, and de-register when deadline is exceeded
	Register(ctx context.Context, record RPCServiceRecord) error

	// Implements gopi.Unit
	Unit
}

// RPCServer serves requests for one or more services
type RPCServer interface {
	// Start an RPC server in currently running thread.
	// The method will not return until Stop is called
	// which needs to be done in a different thread
	Start() error

	// Stop RPC server. If halt is true then it immediately
	// ends the server without waiting for current requests to
	// be served
	Stop(halt bool) error

	// Return address the server is bound to, or nil if
	// the server is not running
	Addr() net.Addr

	// Implements gopi.Unit
	Unit
}

// RPCService is a driver which implements all the necessary
// methods to handle remote calls
type RPCService interface {
	// CancelRequests is called by the server to gracefully end any
	// on-going streaming requests, but before the service is shutdown
	CancelRequests() error

	// Implements gopi.Unit
	Unit
}

// RPCClientPool represents a pool of clients and connections to
// remove services
type RPCClientPool interface {
	// Lookup service records by parameter - returns records
	// which match either a service name up to max number of
	// records (or zero for unlimited). Will wait for new records
	// and block until cancelled
	Lookup(ctx context.Context, addr string, max uint) ([]RPCServiceRecord, error)

	// Implements gopi.Unit
	Unit
}

// RPCEvent is emitted on service discovery and server events
type RPCEvent interface {
	// Type of event
	Type() RPCEventType

	// Service record associated with event
	Service() RPCServiceRecord

	// Time-to-live value for event
	TTL() time.Duration

	// Implements gopi.Event
	Event
}

////////////////////////////////////////////////////////////////////////////////
// CONSTANTS

const (
	RPC_FLAG_NONE          RPCFlag = 0
	RPC_FLAG_INET_UDP      RPCFlag = (1 << iota) >> 1 // Use UDP protocol (TCP assumed otherwise)
	RPC_FLAG_INET_V4                                  // Use V4 addressing
	RPC_FLAG_INET_V6                                  // Use V6 addressing
	RPC_FLAG_SERVICE_FIRST                            // Use first service
	RPC_FLAG_SERVICE_ANY                              // Use any service
	RPC_FLAG_MIN           = RPC_FLAG_INET_UDP
	RPC_FLAG_MAX           = RPC_FLAG_SERVICE_ANY
)

const (
	RPC_EVENT_NONE            RPCEventType = iota
	RPC_EVENT_SERVER_STARTED               // RPC Server started
	RPC_EVENT_SERVER_STOPPED               // RPC Server stopped
	RPC_EVENT_SERVICE_ADDED                // Service instance lookup (new)
	RPC_EVENT_SERVICE_UPDATED              // Service instance lookup (updated)
	RPC_EVENT_SERVICE_REMOVED              // Service instance lookup (removed)
	RPC_EVENT_SERVICE_EXPIRED              // Service instance lookup (expired)
	RPC_EVENT_SERVICE_NAME                 // Service name discovered
	RPC_EVENT_SERVICE_RECORD               // Service record lookup
	RPC_EVENT_CLIENT_CONNECTED
	RPC_EVENT_CLIENT_DISCONNECTED
	RPC_EVENT_MAX = RPC_EVENT_CLIENT_DISCONNECTED
)

////////////////////////////////////////////////////////////////////////////////
// STRINGIFY

func (f RPCFlag) String() string {
	str := ""
	if f == 0 {
		return f.FlagString()
	}
	for v := RPC_FLAG_MIN; v <= RPC_FLAG_MAX; v <<= 1 {
		if f&v == v {
			str += "|" + v.FlagString()
		}
	}
	return strings.TrimPrefix(str, "|")
}

func (v RPCFlag) FlagString() string {
	switch v {
	case RPC_FLAG_NONE:
		return "RPC_FLAG_NONE"
	case RPC_FLAG_INET_UDP:
		return "RPC_FLAG_INET_UDP"
	case RPC_FLAG_INET_V4:
		return "RPC_FLAG_INET_V4"
	case RPC_FLAG_INET_V6:
		return "RPC_FLAG_INET_V6"
	case RPC_FLAG_SERVICE_FIRST:
		return "RPC_FLAG_SERVICE_FIRST"
	case RPC_FLAG_SERVICE_ANY:
		return "RPC_FLAG_SERVICE_ANY"
	default:
		return "[?? Invalid PlatformType value]"
	}
}

func (t RPCEventType) String() string {
	switch t {
	case RPC_EVENT_NONE:
		return "RPC_EVENT_NONE"
	case RPC_EVENT_SERVER_STARTED:
		return "RPC_EVENT_SERVER_STARTED"
	case RPC_EVENT_SERVER_STOPPED:
		return "RPC_EVENT_SERVER_STOPPED"
	case RPC_EVENT_SERVICE_ADDED:
		return "RPC_EVENT_SERVICE_ADDED"
	case RPC_EVENT_SERVICE_UPDATED:
		return "RPC_EVENT_SERVICE_UPDATED"
	case RPC_EVENT_SERVICE_REMOVED:
		return "RPC_EVENT_SERVICE_REMOVED"
	case RPC_EVENT_SERVICE_EXPIRED:
		return "RPC_EVENT_SERVICE_EXPIRED"
	case RPC_EVENT_SERVICE_NAME:
		return "RPC_EVENT_SERVICE_NAME"
	case RPC_EVENT_SERVICE_RECORD:
		return "RPC_EVENT_SERVICE_RECORD"
	case RPC_EVENT_CLIENT_CONNECTED:
		return "RPC_EVENT_CLIENT_CONNECTED"
	case RPC_EVENT_CLIENT_DISCONNECTED:
		return "RPC_EVENT_CLIENT_DISCONNECTED"
	default:
		return "[?? Invalid RPCEventType value]"
	}
}

func (this RPCServiceRecord) String() string {
	str := "<RPCServiceRecord name=" + strconv.Quote(this.Name)
	if this.Service != "" {
		str += " service=" + strconv.Quote(this.Service)
	}
	if this.Host != "" {
		str += " host=" + strconv.Quote(this.Host)
	}
	if this.Port != 0 {
		str += " port=" + fmt.Sprint(this.Port)
	}
	if len(this.Addrs) > 0 {
		str += " addrs="
		for _, addr := range this.Addrs {
			str += addr.String() + ","
		}
		str = strings.TrimSuffix(str, ",")
	}
	if len(this.Txt) > 0 {
		str += " txt=" + fmt.Sprint(this.Txt)
	}
	str += ">"
	return str
}
<|endoftext|>


<commit_before>package main

import (
	"crypto/tls"
	"io"
	"net"
	"net/http/httputil"
	"net/url"
	"os"
	"strconv"
	"strings"

	"github.com/remind101/emp/Godeps/_workspace/src/github.com/bgentry/heroku-go"
	"github.com/remind101/emp/term"
)

var (
	detachedRun bool
	dynoSize    string
)

var cmdRun = &Command{
	Run:      runRun,
	Usage:    "run [-s <size>] [-d] <command> [<argument>...]",
	NeedsApp: true,
	Category: "dyno",
	Short:    "run a process in a dyno",
	Long: `
Run a process on Heroku. Flags such as` + " `-a` " + `may be parsed out of
the command unless the command is quoted or provided after a
double-dash (--).

Options:

    -s <size>  set the size for this dyno (e.g. 2X)
    -d         run in detached mode instead of attached to terminal

Examples:

    $ emp run echo "hello"
    Running ` + "`echo \"hello\"`" + ` on myapp as run.1234:
    "hello"

    $ emp run console
    Running ` + "`console`" + ` on myapp as run.5678:
    Loading production environment (Rails 3.2.14)
    irb(main):001:0> ...

    $ emp run -d -s 2X bin/my_worker
    Ran ` + "`bin/my_worker`" + ` on myapp as run.4321, detached.

    $ emp run -a myapp -- ls -a /
    Running ` + "`ls -a bin /`" + ` on myapp as run.8650:
    /:
    .  ..  app  bin  dev  etc  home  lib  lib64  lost+found  proc  sbin  tmp  usr  var
`,
}

func init() {
	cmdRun.Flag.BoolVarP(&detachedRun, "detached", "d", false, "detached")
	cmdRun.Flag.StringVarP(&dynoSize, "size", "s", "", "dyno size")
}

func runRun(cmd *Command, args []string) {
	if len(args) == 0 {
		cmd.PrintUsage()
		os.Exit(2)
	}
	appname := mustApp()

	cols, err := term.Cols()
	if err != nil {
		printFatal(err.Error())
	}
	lines, err := term.Lines()
	if err != nil {
		printFatal(err.Error())
	}

	attached := !detachedRun
	opts := heroku.DynoCreateOpts{Attach: &attached}
	if attached {
		env := map[string]string{
			"COLUMNS": strconv.Itoa(cols),
			"LINES":   strconv.Itoa(lines),
			"TERM":    os.Getenv("TERM"),
		}
		opts.Env = &env
	}
	if dynoSize != "" {
		if !strings.HasSuffix(dynoSize, "X") {
			cmd.PrintUsage()
			os.Exit(2)
		}
		opts.Size = &dynoSize
	}

	command := strings.Join(args, " ")
	params := struct {
		Command string             `json:"command"`
		Attach  *bool              `json:"attach,omitempty"`
		Env     *map[string]string `json:"env,omitempty"`
		Size    *string            `json:"size,omitempty"`
	}{
		Command: command,
		Attach:  opts.Attach,
		Env:     opts.Env,
		Size:    opts.Size,
	}
	req, err := client.NewRequest("POST", "/apps/"+appname+"/dynos", params)
	must(err)

	u, err := url.Parse(apiURL)
	must(err)

	protocol := u.Scheme
	address := u.Path
	if protocol != "unix" {
		protocol = "tcp"
		address = u.Host
	}

	dial, err := net.Dial(protocol, address)
	must(err)

	if u.Scheme == "https" {
		dial = tls.Client(dial, nil)
		must(err)
	}

	clientconn := httputil.NewClientConn(dial, nil)
	defer clientconn.Close()
	clientconn.Do(req)
	rwc, br := clientconn.Hijack()
	defer rwc.Close()

	if term.IsTerminal(os.Stdin) && term.IsTerminal(os.Stdout) {
		err = term.MakeRaw(os.Stdin)
		if err != nil {
			printFatal(err.Error())
		}
		defer term.Restore(os.Stdin)
	}

	errChanOut := make(chan error, 1)
	errChanIn := make(chan error, 1)
	exit := make(chan bool)
	go func() {
		defer close(exit)
		defer close(errChanOut)
		var err error
		_, err = io.Copy(os.Stdout, br)
		errChanOut <- err
	}()
	go func() {
		_, err := io.Copy(rwc, os.Stdin)
		errChanIn <- err
		rwc.(interface {
			CloseWrite() error
		}).CloseWrite()
	}()
	<-exit
	select {
	case err = <-errChanIn:
		must(err)
	case err = <-errChanOut:
		must(err)
	}
}
<commit_msg>Handle detached runs.<commit_after>package main

import (
	"crypto/tls"
	"io"
	"log"
	"net"
	"net/http/httputil"
	"net/url"
	"os"
	"strconv"
	"strings"

	"github.com/remind101/emp/Godeps/_workspace/src/github.com/bgentry/heroku-go"
	"github.com/remind101/emp/term"
)

var (
	detachedRun bool
	dynoSize    string
)

var cmdRun = &Command{
	Run:      runRun,
	Usage:    "run [-s <size>] [-d] <command> [<argument>...]",
	NeedsApp: true,
	Category: "dyno",
	Short:    "run a process in a dyno",
	Long: `
Run a process on Heroku. Flags such as` + " `-a` " + `may be parsed out of
the command unless the command is quoted or provided after a
double-dash (--).

Options:

    -s <size>  set the size for this dyno (e.g. 2X)
    -d         run in detached mode instead of attached to terminal

Examples:

    $ emp run echo "hello"
    Running ` + "`echo \"hello\"`" + ` on myapp as run.1234:
    "hello"

    $ emp run console
    Running ` + "`console`" + ` on myapp as run.5678:
    Loading production environment (Rails 3.2.14)
    irb(main):001:0> ...

    $ emp run -d -s 2X bin/my_worker
    Ran ` + "`bin/my_worker`" + ` on myapp as run.4321, detached.

    $ emp run -a myapp -- ls -a /
    Running ` + "`ls -a bin /`" + ` on myapp as run.8650:
    /:
    .  ..  app  bin  dev  etc  home  lib  lib64  lost+found  proc  sbin  tmp  usr  var
`,
}

func init() {
	cmdRun.Flag.BoolVarP(&detachedRun, "detached", "d", false, "detached")
	cmdRun.Flag.StringVarP(&dynoSize, "size", "s", "", "dyno size")
}

func runRun(cmd *Command, args []string) {
	if len(args) == 0 {
		cmd.PrintUsage()
		os.Exit(2)
	}
	appname := mustApp()

	cols, err := term.Cols()
	if err != nil {
		printFatal(err.Error())
	}
	lines, err := term.Lines()
	if err != nil {
		printFatal(err.Error())
	}

	attached := !detachedRun
	opts := heroku.DynoCreateOpts{Attach: &attached}
	if attached {
		env := map[string]string{
			"COLUMNS": strconv.Itoa(cols),
			"LINES":   strconv.Itoa(lines),
			"TERM":    os.Getenv("TERM"),
		}
		opts.Env = &env
	}
	if dynoSize != "" {
		if !strings.HasSuffix(dynoSize, "X") {
			cmd.PrintUsage()
			os.Exit(2)
		}
		opts.Size = &dynoSize
	}

	command := strings.Join(args, " ")
	if detachedRun {
		dyno, err := client.DynoCreate(appname, command, &opts)
		must(err)

		log.Printf("Ran `%s` on %s as %s, detached.", dyno.Command, appname, dyno.Name)
		return
	}

	params := struct {
		Command string             `json:"command"`
		Attach  *bool              `json:"attach,omitempty"`
		Env     *map[string]string `json:"env,omitempty"`
		Size    *string            `json:"size,omitempty"`
	}{
		Command: command,
		Attach:  opts.Attach,
		Env:     opts.Env,
		Size:    opts.Size,
	}
	req, err := client.NewRequest("POST", "/apps/"+appname+"/dynos", params)
	must(err)

	u, err := url.Parse(apiURL)
	must(err)

	protocol := u.Scheme
	address := u.Path
	if protocol != "unix" {
		protocol = "tcp"
		address = u.Host
	}

	dial, err := net.Dial(protocol, address)
	must(err)

	if u.Scheme == "https" {
		dial = tls.Client(dial, nil)
		must(err)
	}

	clientconn := httputil.NewClientConn(dial, nil)
	defer clientconn.Close()
	clientconn.Do(req)
	rwc, br := clientconn.Hijack()
	defer rwc.Close()

	if term.IsTerminal(os.Stdin) && term.IsTerminal(os.Stdout) {
		err = term.MakeRaw(os.Stdin)
		if err != nil {
			printFatal(err.Error())
		}
		defer term.Restore(os.Stdin)
	}

	errChanOut := make(chan error, 1)
	errChanIn := make(chan error, 1)
	exit := make(chan bool)
	go func() {
		defer close(exit)
		defer close(errChanOut)
		var err error
		_, err = io.Copy(os.Stdout, br)
		errChanOut <- err
	}()
	go func() {
		_, err := io.Copy(rwc, os.Stdin)
		errChanIn <- err
		rwc.(interface {
			CloseWrite() error
		}).CloseWrite()
	}()
	<-exit
	select {
	case err = <-errChanIn:
		must(err)
	case err = <-errChanOut:
		must(err)
	}
}
<|endoftext|>


<commit_before>package simplehstore

import (
	"context"
	"database/sql"
	"errors"
	"fmt"
	"log"
	"strings"

	"github.com/lib/pq"
)

// Set is a set of strings, stored in PostgreSQL
type Set dbDatastructure

// NewSet creates a new set
func NewSet(host *Host, name string) (*Set, error) {
	s := &Set{host, pq.QuoteIdentifier(name)} // name is the name of the table
	// list is the name of the column
	if _, err := s.host.db.Exec(fmt.Sprintf("CREATE TABLE IF NOT EXISTS %s (%s %s)", s.table, setCol, defaultStringType)); err != nil {
		if !strings.HasSuffix(err.Error(), "already exists") {
			return nil, err
		}
	}
	if Verbose {
		log.Println("Created table " + s.table + " in database " + host.dbname)
	}
	return s, nil
}

// Add an element to the set
func (s *Set) Add(value string) error {
	originalValue := value
	if !s.host.rawUTF8 {
		Encode(&value)
	}
	// Check that the value is not already there before adding
	has, err := s.Has(originalValue)
	if !has && (err == nil) {
		_, err = s.host.db.Exec(fmt.Sprintf("INSERT INTO %s (%s) VALUES ($1)", s.table, setCol), value)
	}
	return err
}

// add an element to the set, as part of a transaction
func (s *Set) addWithTransaction(ctx context.Context, transaction *sql.Tx, value string) error {
	originalValue := value
	if !s.host.rawUTF8 {
		Encode(&value)
	}
	// Check that the value is not already there before adding
	has, err := s.Has(originalValue)
	if !has && (err == nil) {
		_, err = transaction.ExecContext(ctx, fmt.Sprintf("INSERT INTO %s (%s) VALUES ($1)", s.table, setCol), value)
	}
	return err
}

// Has checks if the given value is in the set
func (s *Set) Has(value string) (bool, error) {
	if !s.host.rawUTF8 {
		Encode(&value)
	}
	rows, err := s.host.db.Query(fmt.Sprintf("SELECT %s FROM %s WHERE %s = $1", setCol, s.table, setCol), value)
	if err != nil {
		return false, err
	}
	if rows == nil {
		return false, errors.New("Set Has returned no rows for value " + value)
	}
	defer rows.Close()
	var scanValue sql.NullString
	// Get the value. Should not loop more than once.
	counter := 0
	for rows.Next() {
		err = rows.Scan(&scanValue)
		if err != nil {
			// No rows
			return false, err
		}
		counter++
	}
	if err := rows.Err(); err != nil {
		return false, err
	}
	if counter > 1 {
		// Should never happen
		return false, errors.New("Duplicate keys in set for value " + value + "!")
	}
	return counter > 0, nil
}

// All returns all elements in the set
func (s *Set) All() ([]string, error) {
	var (
		values []string
		value  string
	)
	rows, err := s.host.db.Query(fmt.Sprintf("SELECT DISTINCT %s FROM %s", setCol, s.table))
	if err != nil {
		return values, err
	}
	defer rows.Close()
	for rows.Next() {
		err = rows.Scan(&value)
		if !s.host.rawUTF8 {
			Decode(&value)
		}
		values = append(values, value)
		if err != nil {
			return values, err
		}
	}
	err = rows.Err()
	return values, err
}

// GetAll is deprecated in favor of All
func (s *Set) GetAll() ([]string, error) {
	return s.All()
}

// Del removes an element from the set
func (s *Set) Del(value string) error {
	if !s.host.rawUTF8 {
		Encode(&value)
	}
	// Remove a value from the table
	_, err := s.host.db.Exec(fmt.Sprintf("DELETE FROM %s WHERE %s = '%s'", s.table, setCol, value))
	return err
}

// Remove this set
func (s *Set) Remove() error {
	// Remove the table
	_, err := s.host.db.Exec(fmt.Sprintf("DROP TABLE %s", s.table))
	return err
}

// Clear the list contents
func (s *Set) Clear() error {
	// Clear the table
	_, err := s.host.db.Exec(fmt.Sprintf("TRUNCATE TABLE %s", s.table))
	return err
}

// Count counts the number of elements in this list
func (s *Set) Count() (int, error) {
	var value sql.NullInt32
	rows, err := s.host.db.Query(fmt.Sprintf("SELECT COUNT(*) FROM (SELECT DISTINCT %s FROM %s) as temp", setCol, s.table))
	if err != nil {
		return 0, err
	}
	if rows == nil {
		return 0, ErrNoAvailableValues
	}
	defer rows.Close()
	if rows.Next() {
		err = rows.Scan(&value)
		if err != nil {
			return 0, err
		}
	}
	return int(value.Int32), nil
}

// CountInt64 counts the number of elements in this list (int64)
func (s *Set) CountInt64() (int64, error) {
	var value sql.NullInt64
	rows, err := s.host.db.Query(fmt.Sprintf("SELECT COUNT(*) FROM (SELECT DISTINCT %s FROM %s) as temp", setCol, s.table))
	if err != nil {
		return 0, err
	}
	if rows == nil {
		return 0, ErrNoAvailableValues
	}
	defer rows.Close()
	if rows.Next() {
		err = rows.Scan(&value)
		if err != nil {
			return 0, err
		}
	}
	return value.Int64, nil
}
<commit_msg>Fix an issue in Has<commit_after>package simplehstore

import (
	"context"
	"database/sql"
	"errors"
	"fmt"
	"log"
	"strings"

	"github.com/lib/pq"
)

// Set is a set of strings, stored in PostgreSQL
type Set dbDatastructure

// NewSet creates a new set
func NewSet(host *Host, name string) (*Set, error) {
	s := &Set{host, pq.QuoteIdentifier(name)} // name is the name of the table
	// list is the name of the column
	if _, err := s.host.db.Exec(fmt.Sprintf("CREATE TABLE IF NOT EXISTS %s (%s %s)", s.table, setCol, defaultStringType)); err != nil {
		if !strings.HasSuffix(err.Error(), "already exists") {
			return nil, err
		}
	}
	if Verbose {
		log.Println("Created table " + s.table + " in database " + host.dbname)
	}
	return s, nil
}

// Add an element to the set
func (s *Set) Add(value string) error {
	originalValue := value
	if !s.host.rawUTF8 {
		Encode(&value)
	}
	// Check that the value is not already there before adding
	has, err := s.Has(originalValue)
	if !has && (err == nil) {
		_, err = s.host.db.Exec(fmt.Sprintf("INSERT INTO %s (%s) VALUES ($1)", s.table, setCol), value)
	}
	return err
}

// add an element to the set, as part of a transaction
func (s *Set) addWithTransaction(ctx context.Context, transaction *sql.Tx, value string) error {
	originalValue := value
	if !s.host.rawUTF8 {
		Encode(&value)
	}
	// Check that the value is not already there before adding
	has, err := s.Has(originalValue)
	if !has && (err == nil) {
		_, err = transaction.ExecContext(ctx, fmt.Sprintf("INSERT INTO %s (%s) VALUES ($1)", s.table, setCol), value)
	}
	return err
}

// Has checks if the given value is in the set
func (s *Set) Has(value string) (bool, error) {
	if !s.host.rawUTF8 {
		Encode(&value)
	}
	rows, err := s.host.db.Query(fmt.Sprintf("SELECT %s FROM %s WHERE %s = $1", setCol, s.table, setCol), value)
	if err != nil {
		return false, err
	}
	if rows == nil {
		return false, errors.New("Set Has returned no rows for value " + value)
	}
	defer rows.Close()
	var scanValue sql.NullString
	// Get the value. Should not loop more than once.
	counter := 0
	for rows.Next() {
		err = rows.Scan(&scanValue)
		if err != nil {
			// No rows
			return false, err
		}
		counter++
	}
	if err := rows.Err(); err != nil {
		return false, err
	}
	//if counter > 1 {
	// more than one element that has the same *value* is fine!
	//}
	return counter > 0, nil
}

// All returns all elements in the set
func (s *Set) All() ([]string, error) {
	var (
		values []string
		value  string
	)
	rows, err := s.host.db.Query(fmt.Sprintf("SELECT DISTINCT %s FROM %s", setCol, s.table))
	if err != nil {
		return values, err
	}
	defer rows.Close()
	for rows.Next() {
		err = rows.Scan(&value)
		if !s.host.rawUTF8 {
			Decode(&value)
		}
		values = append(values, value)
		if err != nil {
			return values, err
		}
	}
	err = rows.Err()
	return values, err
}

// GetAll is deprecated in favor of All
func (s *Set) GetAll() ([]string, error) {
	return s.All()
}

// Del removes an element from the set
func (s *Set) Del(value string) error {
	if !s.host.rawUTF8 {
		Encode(&value)
	}
	// Remove a value from the table
	_, err := s.host.db.Exec(fmt.Sprintf("DELETE FROM %s WHERE %s = '%s'", s.table, setCol, value))
	return err
}

// Remove this set
func (s *Set) Remove() error {
	// Remove the table
	_, err := s.host.db.Exec(fmt.Sprintf("DROP TABLE %s", s.table))
	return err
}

// Clear the list contents
func (s *Set) Clear() error {
	// Clear the table
	_, err := s.host.db.Exec(fmt.Sprintf("TRUNCATE TABLE %s", s.table))
	return err
}

// Count counts the number of elements in this list
func (s *Set) Count() (int, error) {
	var value sql.NullInt32
	rows, err := s.host.db.Query(fmt.Sprintf("SELECT COUNT(*) FROM (SELECT DISTINCT %s FROM %s) as temp", setCol, s.table))
	if err != nil {
		return 0, err
	}
	if rows == nil {
		return 0, ErrNoAvailableValues
	}
	defer rows.Close()
	if rows.Next() {
		err = rows.Scan(&value)
		if err != nil {
			return 0, err
		}
	}
	return int(value.Int32), nil
}

// CountInt64 counts the number of elements in this list (int64)
func (s *Set) CountInt64() (int64, error) {
	var value sql.NullInt64
	rows, err := s.host.db.Query(fmt.Sprintf("SELECT COUNT(*) FROM (SELECT DISTINCT %s FROM %s) as temp", setCol, s.table))
	if err != nil {
		return 0, err
	}
	if rows == nil {
		return 0, ErrNoAvailableValues
	}
	defer rows.Close()
	if rows.Next() {
		err = rows.Scan(&value)
		if err != nil {
			return 0, err
		}
	}
	return value.Int64, nil
}
<|endoftext|>