<commit_before>package main

import (
	"bytes"
	"database/sql"
	"encoding/json"
	"fmt"
	"io"
	"mime/multipart"
	"net/http"
	"os"
	"time"

	dqlite "github.com/CanonicalLtd/go-dqlite"
	"github.com/mattn/go-sqlite3"
	"github.com/pkg/errors"

	lxd "github.com/lxc/lxd/client"
	"github.com/lxc/lxd/lxd/cluster"
	"github.com/lxc/lxd/lxd/db"
	"github.com/lxc/lxd/lxd/util"
	"github.com/lxc/lxd/shared"
	"github.com/lxc/lxd/shared/api"
	"github.com/lxc/lxd/shared/version"
)

type Response interface {
	Render(w http.ResponseWriter) error
	String() string
}

// Sync response
type syncResponse struct {
	success  bool
	etag     interface{}
	metadata interface{}
	location string
	code     int
	headers  map[string]string
}

func (r *syncResponse) Render(w http.ResponseWriter) error {
	// Set an appropriate ETag header
	if r.etag != nil {
		etag, err := util.EtagHash(r.etag)
		if err == nil {
			w.Header().Set("ETag", etag)
		}
	}

	// Prepare the JSON response
	status := api.Success
	if !r.success {
		status = api.Failure
	}

	if r.headers != nil {
		for h, v := range r.headers {
			w.Header().Set(h, v)
		}
	}

	if r.location != "" {
		w.Header().Set("Location", r.location)
		code := r.code
		if code == 0 {
			code = 201
		}
		w.WriteHeader(code)
	}

	resp := api.ResponseRaw{
		Type:       api.SyncResponse,
		Status:     status.String(),
		StatusCode: int(status),
		Metadata:   r.metadata,
	}

	return util.WriteJSON(w, resp, debug)
}

func (r *syncResponse) String() string {
	if r.success {
		return "success"
	}

	return "failure"
}

func SyncResponse(success bool, metadata interface{}) Response {
	return &syncResponse{success: success, metadata: metadata}
}

func SyncResponseETag(success bool, metadata interface{}, etag interface{}) Response {
	return &syncResponse{success: success, metadata: metadata, etag: etag}
}

func SyncResponseLocation(success bool, metadata interface{}, location string) Response {
	return &syncResponse{success: success, metadata: metadata, location: location}
}

func SyncResponseRedirect(address string) Response {
	return &syncResponse{success: true, location: address, code: http.StatusPermanentRedirect}
}

func SyncResponseHeaders(success bool, metadata interface{}, headers map[string]string) Response {
	return &syncResponse{success: success, metadata: metadata, headers: headers}
}

var EmptySyncResponse = &syncResponse{success: true, metadata: make(map[string]interface{})}

type forwardedResponse struct {
	client  lxd.ContainerServer
	request *http.Request
}

func (r *forwardedResponse) Render(w http.ResponseWriter) error {
	info, err := r.client.GetConnectionInfo()
	if err != nil {
		return err
	}

	url := fmt.Sprintf("%s%s", info.Addresses[0], r.request.URL.RequestURI())
	forwarded, err := http.NewRequest(r.request.Method, url, r.request.Body)
	if err != nil {
		return err
	}
	for key := range r.request.Header {
		forwarded.Header.Set(key, r.request.Header.Get(key))
	}

	httpClient, err := r.client.GetHTTPClient()
	if err != nil {
		return err
	}
	response, err := httpClient.Do(forwarded)
	if err != nil {
		return err
	}

	for key := range response.Header {
		w.Header().Set(key, response.Header.Get(key))
	}

	w.WriteHeader(response.StatusCode)
	_, err = io.Copy(w, response.Body)
	return err
}

func (r *forwardedResponse) String() string {
	return fmt.Sprintf("request to %s", r.request.URL)
}

// ForwardedResponse takes a request directed to a node and forwards it to
// another node, writing back the response it gegs.
func ForwardedResponse(client lxd.ContainerServer, request *http.Request) Response {
	return &forwardedResponse{
		client:  client,
		request: request,
	}
}

// ForwardedResponseIfTargetIsRemote redirects a request to the request has a
// targetNode parameter pointing to a node which is not the local one.
func ForwardedResponseIfTargetIsRemote(d *Daemon, request *http.Request) Response {
	targetNode := queryParam(request, "target")
	if targetNode == "" {
		return nil
	}

	// Figure out the address of the target node (which is possibly
	// this very same node).
	address, err := cluster.ResolveTarget(d.cluster, targetNode)
	if err != nil {
		return SmartError(err)
	}

	if address != "" {
		// Forward the response.
		cert := d.endpoints.NetworkCert()
		client, err := cluster.Connect(address, cert, false)
		if err != nil {
			return SmartError(err)
		}
		return ForwardedResponse(client, request)
	}

	return nil
}

// ForwardedResponseIfContainerIsRemote redirects a request to the node running
// the container with the given name. If the container is local, nothing gets
// done and nil is returned.
func ForwardedResponseIfContainerIsRemote(d *Daemon, r *http.Request, project, name string) (Response, error) {
	cert := d.endpoints.NetworkCert()
	client, err := cluster.ConnectIfContainerIsRemote(d.cluster, project, name, cert)
	if err != nil {
		return nil, err
	}
	if client == nil {
		return nil, nil
	}
	return ForwardedResponse(client, r), nil
}

// ForwardedResponseIfVolumeIsRemote redirects a request to the node hosting
// the volume with the given pool ID, name and type. If the container is local,
// nothing gets done and nil is returned. If more than one node has a matching
// volume, an error is returned.
//
// This is used when no targetNode is specified, and saves users some typing
// when the volume name/type is unique to a node.
func ForwardedResponseIfVolumeIsRemote(d *Daemon, r *http.Request, poolID int64, volumeName string, volumeType int) Response {
	if queryParam(r, "target") != "" {
		return nil
	}

	cert := d.endpoints.NetworkCert()
	client, err := cluster.ConnectIfVolumeIsRemote(d.cluster, poolID, volumeName, volumeType, cert)
	if err != nil && err != db.ErrNoSuchObject {
		return SmartError(err)
	}
	if client == nil {
		return nil
	}
	return ForwardedResponse(client, r)
}

// File transfer response
type fileResponseEntry struct {
	identifier string
	path       string
	filename   string
	buffer     []byte /* either a path or a buffer must be provided */
}

type fileResponse struct {
	req              *http.Request
	files            []fileResponseEntry
	headers          map[string]string
	removeAfterServe bool
}

func (r *fileResponse) Render(w http.ResponseWriter) error {
	if r.headers != nil {
		for k, v := range r.headers {
			w.Header().Set(k, v)
		}
	}

	// No file, well, it's easy then
	if len(r.files) == 0 {
		return nil
	}

	// For a single file, return it inline
	if len(r.files) == 1 {
		var rs io.ReadSeeker
		var mt time.Time
		var sz int64

		if r.files[0].path == "" {
			rs = bytes.NewReader(r.files[0].buffer)
			mt = time.Now()
			sz = int64(len(r.files[0].buffer))
		} else {
			f, err := os.Open(r.files[0].path)
			if err != nil {
				return err
			}
			defer f.Close()

			fi, err := f.Stat()
			if err != nil {
				return err
			}

			mt = fi.ModTime()
			sz = fi.Size()
			rs = f
		}

		w.Header().Set("Content-Type", "application/octet-stream")
		w.Header().Set("Content-Length", fmt.Sprintf("%d", sz))
		w.Header().Set("Content-Disposition", fmt.Sprintf("inline;filename=%s", r.files[0].filename))

		http.ServeContent(w, r.req, r.files[0].filename, mt, rs)
		if r.files[0].path != "" && r.removeAfterServe {
			err := os.Remove(r.files[0].path)
			if err != nil {
				return err
			}
		}

		return nil
	}

	// Now the complex multipart answer
	body := &bytes.Buffer{}
	mw := multipart.NewWriter(body)

	for _, entry := range r.files {
		var rd io.Reader
		if entry.path != "" {
			fd, err := os.Open(entry.path)
			if err != nil {
				return err
			}
			defer fd.Close()
			rd = fd
		} else {
			rd = bytes.NewReader(entry.buffer)
		}

		fw, err := mw.CreateFormFile(entry.identifier, entry.filename)
		if err != nil {
			return err
		}

		_, err = io.Copy(fw, rd)
		if err != nil {
			return err
		}
	}
	mw.Close()

	w.Header().Set("Content-Type", mw.FormDataContentType())
	w.Header().Set("Content-Length", fmt.Sprintf("%d", body.Len()))

	_, err := io.Copy(w, body)
	return err
}

func (r *fileResponse) String() string {
	return fmt.Sprintf("%d files", len(r.files))
}

func FileResponse(r *http.Request, files []fileResponseEntry, headers map[string]string, removeAfterServe bool) Response {
	return &fileResponse{r, files, headers, removeAfterServe}
}

// Operation response
type operationResponse struct {
	op *operation
}

func (r *operationResponse) Render(w http.ResponseWriter) error {
	_, err := r.op.Run()
	if err != nil {
		return err
	}

	url, md, err := r.op.Render()
	if err != nil {
		return err
	}

	body := api.ResponseRaw{
		Type:       api.AsyncResponse,
		Status:     api.OperationCreated.String(),
		StatusCode: int(api.OperationCreated),
		Operation:  url,
		Metadata:   md,
	}

	w.Header().Set("Location", url)
	w.WriteHeader(202)

	return util.WriteJSON(w, body, debug)
}

func (r *operationResponse) String() string {
	_, md, err := r.op.Render()
	if err != nil {
		return fmt.Sprintf("error: %s", err)
	}

	return md.ID
}

func OperationResponse(op *operation) Response {
	return &operationResponse{op}
}

// Forwarded operation response.
//
// Returned when the operation has been created on another node
type forwardedOperationResponse struct {
	op      *api.Operation
	project string
}

func (r *forwardedOperationResponse) Render(w http.ResponseWriter) error {
	url := fmt.Sprintf("/%s/operations/%s", version.APIVersion, r.op.ID)
	if r.project != "" {
		url += fmt.Sprintf("?project=%s", r.project)
	}

	body := api.ResponseRaw{
		Type:       api.AsyncResponse,
		Status:     api.OperationCreated.String(),
		StatusCode: int(api.OperationCreated),
		Operation:  url,
		Metadata:   r.op,
	}

	w.Header().Set("Location", url)
	w.WriteHeader(202)

	return util.WriteJSON(w, body, debug)
}

func (r *forwardedOperationResponse) String() string {
	return r.op.ID
}

// ForwardedOperationResponse creates a response that forwards the metadata of
// an operation created on another node.
func ForwardedOperationResponse(project string, op *api.Operation) Response {
	return &forwardedOperationResponse{
		op:      op,
		project: project,
	}
}

// Error response
type errorResponse struct {
	code int
	msg  string
}

func (r *errorResponse) String() string {
	return r.msg
}

func (r *errorResponse) Render(w http.ResponseWriter) error {
	var output io.Writer

	buf := &bytes.Buffer{}
	output = buf
	var captured *bytes.Buffer
	if debug {
		captured = &bytes.Buffer{}
		output = io.MultiWriter(buf, captured)
	}

	err := json.NewEncoder(output).Encode(shared.Jmap{"type": api.ErrorResponse, "error": r.msg, "error_code": r.code})

	if err != nil {
		return err
	}

	if debug {
		shared.DebugJson(captured)
	}

	w.Header().Set("Content-Type", "application/json")
	w.Header().Set("X-Content-Type-Options", "nosniff")
	w.WriteHeader(r.code)
	fmt.Fprintln(w, buf.String())

	return nil
}

func NotImplemented(err error) Response {
	message := "not implemented"
	if err != nil {
		message = err.Error()
	}
	return &errorResponse{http.StatusNotImplemented, message}
}

func NotFound(err error) Response {
	message := "not found"
	if err != nil {
		message = err.Error()
	}
	return &errorResponse{http.StatusNotFound, message}
}

func Forbidden(err error) Response {
	message := "not authorized"
	if err != nil {
		message = err.Error()
	}
	return &errorResponse{http.StatusForbidden, message}
}

func Conflict(err error) Response {
	message := "already exists"
	if err != nil {
		message = err.Error()
	}
	return &errorResponse{http.StatusConflict, message}
}

func Unavailable(err error) Response {
	message := "unavailable"
	if err != nil {
		message = err.Error()
	}
	return &errorResponse{http.StatusServiceUnavailable, message}
}

func BadRequest(err error) Response {
	return &errorResponse{http.StatusBadRequest, err.Error()}
}

func InternalError(err error) Response {
	return &errorResponse{http.StatusInternalServerError, err.Error()}
}

func PreconditionFailed(err error) Response {
	return &errorResponse{http.StatusPreconditionFailed, err.Error()}
}

/*
 * SmartError returns the right error message based on err.
 */
func SmartError(err error) Response {
	switch errors.Cause(err) {
	case nil:
		return EmptySyncResponse
	case os.ErrNotExist:
		return NotFound(nil)
	case sql.ErrNoRows:
		return NotFound(nil)
	case db.ErrNoSuchObject:
		return NotFound(nil)
	case os.ErrPermission:
		return Forbidden(nil)
	case db.ErrAlreadyDefined:
		return Conflict(nil)
	case sqlite3.ErrConstraintUnique:
		return Conflict(nil)
	case dqlite.ErrNoAvailableLeader:
		return Unavailable(err)
	default:
		return InternalError(err)
	}
}
<commit_msg>lxd/response: Simplify SmartError<commit_after>package main

import (
	"bytes"
	"database/sql"
	"encoding/json"
	"fmt"
	"io"
	"mime/multipart"
	"net/http"
	"os"
	"time"

	dqlite "github.com/CanonicalLtd/go-dqlite"
	"github.com/mattn/go-sqlite3"
	"github.com/pkg/errors"

	lxd "github.com/lxc/lxd/client"
	"github.com/lxc/lxd/lxd/cluster"
	"github.com/lxc/lxd/lxd/db"
	"github.com/lxc/lxd/lxd/util"
	"github.com/lxc/lxd/shared"
	"github.com/lxc/lxd/shared/api"
	"github.com/lxc/lxd/shared/version"
)

type Response interface {
	Render(w http.ResponseWriter) error
	String() string
}

// Sync response
type syncResponse struct {
	success  bool
	etag     interface{}
	metadata interface{}
	location string
	code     int
	headers  map[string]string
}

func (r *syncResponse) Render(w http.ResponseWriter) error {
	// Set an appropriate ETag header
	if r.etag != nil {
		etag, err := util.EtagHash(r.etag)
		if err == nil {
			w.Header().Set("ETag", etag)
		}
	}

	// Prepare the JSON response
	status := api.Success
	if !r.success {
		status = api.Failure
	}

	if r.headers != nil {
		for h, v := range r.headers {
			w.Header().Set(h, v)
		}
	}

	if r.location != "" {
		w.Header().Set("Location", r.location)
		code := r.code
		if code == 0 {
			code = 201
		}
		w.WriteHeader(code)
	}

	resp := api.ResponseRaw{
		Type:       api.SyncResponse,
		Status:     status.String(),
		StatusCode: int(status),
		Metadata:   r.metadata,
	}

	return util.WriteJSON(w, resp, debug)
}

func (r *syncResponse) String() string {
	if r.success {
		return "success"
	}

	return "failure"
}

func SyncResponse(success bool, metadata interface{}) Response {
	return &syncResponse{success: success, metadata: metadata}
}

func SyncResponseETag(success bool, metadata interface{}, etag interface{}) Response {
	return &syncResponse{success: success, metadata: metadata, etag: etag}
}

func SyncResponseLocation(success bool, metadata interface{}, location string) Response {
	return &syncResponse{success: success, metadata: metadata, location: location}
}

func SyncResponseRedirect(address string) Response {
	return &syncResponse{success: true, location: address, code: http.StatusPermanentRedirect}
}

func SyncResponseHeaders(success bool, metadata interface{}, headers map[string]string) Response {
	return &syncResponse{success: success, metadata: metadata, headers: headers}
}

var EmptySyncResponse = &syncResponse{success: true, metadata: make(map[string]interface{})}

type forwardedResponse struct {
	client  lxd.ContainerServer
	request *http.Request
}

func (r *forwardedResponse) Render(w http.ResponseWriter) error {
	info, err := r.client.GetConnectionInfo()
	if err != nil {
		return err
	}

	url := fmt.Sprintf("%s%s", info.Addresses[0], r.request.URL.RequestURI())
	forwarded, err := http.NewRequest(r.request.Method, url, r.request.Body)
	if err != nil {
		return err
	}
	for key := range r.request.Header {
		forwarded.Header.Set(key, r.request.Header.Get(key))
	}

	httpClient, err := r.client.GetHTTPClient()
	if err != nil {
		return err
	}
	response, err := httpClient.Do(forwarded)
	if err != nil {
		return err
	}

	for key := range response.Header {
		w.Header().Set(key, response.Header.Get(key))
	}

	w.WriteHeader(response.StatusCode)
	_, err = io.Copy(w, response.Body)
	return err
}

func (r *forwardedResponse) String() string {
	return fmt.Sprintf("request to %s", r.request.URL)
}

// ForwardedResponse takes a request directed to a node and forwards it to
// another node, writing back the response it gegs.
func ForwardedResponse(client lxd.ContainerServer, request *http.Request) Response {
	return &forwardedResponse{
		client:  client,
		request: request,
	}
}

// ForwardedResponseIfTargetIsRemote redirects a request to the request has a
// targetNode parameter pointing to a node which is not the local one.
func ForwardedResponseIfTargetIsRemote(d *Daemon, request *http.Request) Response {
	targetNode := queryParam(request, "target")
	if targetNode == "" {
		return nil
	}

	// Figure out the address of the target node (which is possibly
	// this very same node).
	address, err := cluster.ResolveTarget(d.cluster, targetNode)
	if err != nil {
		return SmartError(err)
	}

	if address != "" {
		// Forward the response.
		cert := d.endpoints.NetworkCert()
		client, err := cluster.Connect(address, cert, false)
		if err != nil {
			return SmartError(err)
		}
		return ForwardedResponse(client, request)
	}

	return nil
}

// ForwardedResponseIfContainerIsRemote redirects a request to the node running
// the container with the given name. If the container is local, nothing gets
// done and nil is returned.
func ForwardedResponseIfContainerIsRemote(d *Daemon, r *http.Request, project, name string) (Response, error) {
	cert := d.endpoints.NetworkCert()
	client, err := cluster.ConnectIfContainerIsRemote(d.cluster, project, name, cert)
	if err != nil {
		return nil, err
	}
	if client == nil {
		return nil, nil
	}
	return ForwardedResponse(client, r), nil
}

// ForwardedResponseIfVolumeIsRemote redirects a request to the node hosting
// the volume with the given pool ID, name and type. If the container is local,
// nothing gets done and nil is returned. If more than one node has a matching
// volume, an error is returned.
//
// This is used when no targetNode is specified, and saves users some typing
// when the volume name/type is unique to a node.
func ForwardedResponseIfVolumeIsRemote(d *Daemon, r *http.Request, poolID int64, volumeName string, volumeType int) Response {
	if queryParam(r, "target") != "" {
		return nil
	}

	cert := d.endpoints.NetworkCert()
	client, err := cluster.ConnectIfVolumeIsRemote(d.cluster, poolID, volumeName, volumeType, cert)
	if err != nil && err != db.ErrNoSuchObject {
		return SmartError(err)
	}
	if client == nil {
		return nil
	}
	return ForwardedResponse(client, r)
}

// File transfer response
type fileResponseEntry struct {
	identifier string
	path       string
	filename   string
	buffer     []byte /* either a path or a buffer must be provided */
}

type fileResponse struct {
	req              *http.Request
	files            []fileResponseEntry
	headers          map[string]string
	removeAfterServe bool
}

func (r *fileResponse) Render(w http.ResponseWriter) error {
	if r.headers != nil {
		for k, v := range r.headers {
			w.Header().Set(k, v)
		}
	}

	// No file, well, it's easy then
	if len(r.files) == 0 {
		return nil
	}

	// For a single file, return it inline
	if len(r.files) == 1 {
		var rs io.ReadSeeker
		var mt time.Time
		var sz int64

		if r.files[0].path == "" {
			rs = bytes.NewReader(r.files[0].buffer)
			mt = time.Now()
			sz = int64(len(r.files[0].buffer))
		} else {
			f, err := os.Open(r.files[0].path)
			if err != nil {
				return err
			}
			defer f.Close()

			fi, err := f.Stat()
			if err != nil {
				return err
			}

			mt = fi.ModTime()
			sz = fi.Size()
			rs = f
		}

		w.Header().Set("Content-Type", "application/octet-stream")
		w.Header().Set("Content-Length", fmt.Sprintf("%d", sz))
		w.Header().Set("Content-Disposition", fmt.Sprintf("inline;filename=%s", r.files[0].filename))

		http.ServeContent(w, r.req, r.files[0].filename, mt, rs)
		if r.files[0].path != "" && r.removeAfterServe {
			err := os.Remove(r.files[0].path)
			if err != nil {
				return err
			}
		}

		return nil
	}

	// Now the complex multipart answer
	body := &bytes.Buffer{}
	mw := multipart.NewWriter(body)

	for _, entry := range r.files {
		var rd io.Reader
		if entry.path != "" {
			fd, err := os.Open(entry.path)
			if err != nil {
				return err
			}
			defer fd.Close()
			rd = fd
		} else {
			rd = bytes.NewReader(entry.buffer)
		}

		fw, err := mw.CreateFormFile(entry.identifier, entry.filename)
		if err != nil {
			return err
		}

		_, err = io.Copy(fw, rd)
		if err != nil {
			return err
		}
	}
	mw.Close()

	w.Header().Set("Content-Type", mw.FormDataContentType())
	w.Header().Set("Content-Length", fmt.Sprintf("%d", body.Len()))

	_, err := io.Copy(w, body)
	return err
}

func (r *fileResponse) String() string {
	return fmt.Sprintf("%d files", len(r.files))
}

func FileResponse(r *http.Request, files []fileResponseEntry, headers map[string]string, removeAfterServe bool) Response {
	return &fileResponse{r, files, headers, removeAfterServe}
}

// Operation response
type operationResponse struct {
	op *operation
}

func (r *operationResponse) Render(w http.ResponseWriter) error {
	_, err := r.op.Run()
	if err != nil {
		return err
	}

	url, md, err := r.op.Render()
	if err != nil {
		return err
	}

	body := api.ResponseRaw{
		Type:       api.AsyncResponse,
		Status:     api.OperationCreated.String(),
		StatusCode: int(api.OperationCreated),
		Operation:  url,
		Metadata:   md,
	}

	w.Header().Set("Location", url)
	w.WriteHeader(202)

	return util.WriteJSON(w, body, debug)
}

func (r *operationResponse) String() string {
	_, md, err := r.op.Render()
	if err != nil {
		return fmt.Sprintf("error: %s", err)
	}

	return md.ID
}

func OperationResponse(op *operation) Response {
	return &operationResponse{op}
}

// Forwarded operation response.
//
// Returned when the operation has been created on another node
type forwardedOperationResponse struct {
	op      *api.Operation
	project string
}

func (r *forwardedOperationResponse) Render(w http.ResponseWriter) error {
	url := fmt.Sprintf("/%s/operations/%s", version.APIVersion, r.op.ID)
	if r.project != "" {
		url += fmt.Sprintf("?project=%s", r.project)
	}

	body := api.ResponseRaw{
		Type:       api.AsyncResponse,
		Status:     api.OperationCreated.String(),
		StatusCode: int(api.OperationCreated),
		Operation:  url,
		Metadata:   r.op,
	}

	w.Header().Set("Location", url)
	w.WriteHeader(202)

	return util.WriteJSON(w, body, debug)
}

func (r *forwardedOperationResponse) String() string {
	return r.op.ID
}

// ForwardedOperationResponse creates a response that forwards the metadata of
// an operation created on another node.
func ForwardedOperationResponse(project string, op *api.Operation) Response {
	return &forwardedOperationResponse{
		op:      op,
		project: project,
	}
}

// Error response
type errorResponse struct {
	code int
	msg  string
}

func (r *errorResponse) String() string {
	return r.msg
}

func (r *errorResponse) Render(w http.ResponseWriter) error {
	var output io.Writer

	buf := &bytes.Buffer{}
	output = buf
	var captured *bytes.Buffer
	if debug {
		captured = &bytes.Buffer{}
		output = io.MultiWriter(buf, captured)
	}

	err := json.NewEncoder(output).Encode(shared.Jmap{"type": api.ErrorResponse, "error": r.msg, "error_code": r.code})

	if err != nil {
		return err
	}

	if debug {
		shared.DebugJson(captured)
	}

	w.Header().Set("Content-Type", "application/json")
	w.Header().Set("X-Content-Type-Options", "nosniff")
	w.WriteHeader(r.code)
	fmt.Fprintln(w, buf.String())

	return nil
}

func NotImplemented(err error) Response {
	message := "not implemented"
	if err != nil {
		message = err.Error()
	}
	return &errorResponse{http.StatusNotImplemented, message}
}

func NotFound(err error) Response {
	message := "not found"
	if err != nil {
		message = err.Error()
	}
	return &errorResponse{http.StatusNotFound, message}
}

func Forbidden(err error) Response {
	message := "not authorized"
	if err != nil {
		message = err.Error()
	}
	return &errorResponse{http.StatusForbidden, message}
}

func Conflict(err error) Response {
	message := "already exists"
	if err != nil {
		message = err.Error()
	}
	return &errorResponse{http.StatusConflict, message}
}

func Unavailable(err error) Response {
	message := "unavailable"
	if err != nil {
		message = err.Error()
	}
	return &errorResponse{http.StatusServiceUnavailable, message}
}

func BadRequest(err error) Response {
	return &errorResponse{http.StatusBadRequest, err.Error()}
}

func InternalError(err error) Response {
	return &errorResponse{http.StatusInternalServerError, err.Error()}
}

func PreconditionFailed(err error) Response {
	return &errorResponse{http.StatusPreconditionFailed, err.Error()}
}

/*
 * SmartError returns the right error message based on err.
 */
func SmartError(err error) Response {
	switch errors.Cause(err) {
	case nil:
		return EmptySyncResponse
	case os.ErrNotExist, sql.ErrNoRows, db.ErrNoSuchObject:
		return NotFound(nil)
	case os.ErrPermission:
		return Forbidden(nil)
	case db.ErrAlreadyDefined, sqlite3.ErrConstraintUnique:
		return Conflict(nil)
	case dqlite.ErrNoAvailableLeader:
		return Unavailable(err)
	default:
		return InternalError(err)
	}
}
<|endoftext|>


<commit_before>package lzma

import (
	"bufio"
	"errors"
	"io"
)

// states defines the overall state count
const states = 12

// bufferLen is the value used for the bufferLen used by the decoder.
var bufferLen = 64 * (1 << 10)

// Decoder is able to read a LZMA byte stream and to read the plain text.
type Decoder struct {
	properties         Properties
	packedLen          uint64
	unpackedLen        uint64
	unpackedLenDefined bool
	dict               *decoderDict
	state              uint32
	posBitMask         uint32
	rd                 *rangeDecoder
	isMatch            [states << maxPosBits]prob
	isRep              [states]prob
	isRepG0            [states]prob
	isRepG1            [states]prob
	isRepG2            [states]prob
	isRepG0Long        [states << maxPosBits]prob
	rep                [4]uint32
	litDecoder         *literalCodec
	lengthDecoder      *lengthCodec
	distDecoder        *distCodec
}

// NewDecoder creates an LZMA decoder. It reads the classic, original LZMA
// format. Note that LZMA2 uses a different header format.
func NewDecoder(r io.Reader) (d *Decoder, err error) {
	f := bufio.NewReader(r)
	properties, err := readProperties(f)
	if err != nil {
		return nil, err
	}
	historyLen := int(properties.DictLen)
	if historyLen < 0 {
		return nil, errors.New(
			"LZMA property DictLen exceeds maximum int value")
	}
	d = &Decoder{
		properties: *properties,
	}
	if d.packedLen, err = readUint64LE(f); err != nil {
		return nil, err
	}
	if d.dict, err = newDecoderDict(bufferLen, historyLen); err != nil {
		return nil, err
	}
	d.posBitMask = (uint32(1) << uint(d.properties.PB)) - 1
	if d.rd, err = newRangeDecoder(f); err != nil {
		return nil, err
	}
	initProbSlice(d.isMatch[:])
	initProbSlice(d.isRep[:])
	initProbSlice(d.isRepG0[:])
	initProbSlice(d.isRepG1[:])
	initProbSlice(d.isRepG2[:])
	initProbSlice(d.isRepG0Long[:])
	d.litDecoder = newLiteralCodec(d.properties.LC, d.properties.LP)
	d.lengthDecoder = newLengthCodec()
	d.distDecoder = newDistCodec()
	return d, nil
}

// Properties returns a set of properties.
func (d *Decoder) Properties() Properties {
	return d.properties
}

// getUint64LE converts the uint64 value stored as little endian to an uint64
// value.
func getUint64LE(b []byte) uint64 {
	x := uint64(b[7]) << 56
	x |= uint64(b[6]) << 48
	x |= uint64(b[5]) << 40
	x |= uint64(b[4]) << 32
	x |= uint64(b[3]) << 24
	x |= uint64(b[2]) << 16
	x |= uint64(b[1]) << 8
	x |= uint64(b[0])
	return x
}

// readUint64LE reads a uint64 little-endian integer from reader.
func readUint64LE(r io.Reader) (x uint64, err error) {
	b := make([]byte, 8)
	if _, err = io.ReadFull(r, b); err != nil {
		return 0, err
	}
	x = getUint64LE(b)
	return x, nil
}

// initProbSlice initializes a slice of probabilities.
func initProbSlice(p []prob) {
	for i := range p {
		p[i] = probInit
	}
}

// Reads reads data from the decoder stream.
//
// The function fill put as much data in the buffer as it is available. The
// function might block and is not reentrant.
//
// The end of the LZMA stream is indicated by EOF. There might be other errors
// returned. The decoder will not be able to recover from an error returned.
func (d *Decoder) Read(p []byte) (n int, err error) {
	for n < len(p) {
		var k int
		k, err = d.dict.Read(p)
		if err != nil {
			return
		}
		n += k
		if n == len(p) {
			return
		}
		if err = d.fill(len(p) - n); err != nil {
			return
		}
	}
	return
}

// fill puts at lest the requested number of bytes into the decoder dictionary.
func (d *Decoder) fill(n int) error {
	panic("TODO")
}

// updateStateLiteral updates the state for a literal.
func (d *Decoder) updateStateLiteral() {
	switch {
	case d.state < 4:
		d.state = 0
		return
	case d.state < 10:
		d.state -= 3
		return
	}
	d.state -= 6
	return
}

// updateStateMatch updates the state for a match.
func (d *Decoder) updateStateMatch() {
	if d.state < 7 {
		d.state = 7
		return
	}
	d.state = 10
	return
}

// updateStateRep updates the state for a repetition.
func (d *Decoder) updateStateRep() {
	if d.state < 7 {
		d.state = 8
	}
	d.state = 11
}

// updateStateShortRep updates the state for a short repetition.
func (d *Decoder) updateStateShortRep() {
	if d.state < 7 {
		d.state = 9
	}
	d.state = 11
}

// decodeLiteral decodes a literal.
func (d *Decoder) decodeLiteral() (op operation, err error) {
	prevByte := d.dict.getByte(1)
	lp, lc := uint(d.properties.LP), uint(d.properties.LC)
	litState := ((uint32(d.dict.total) & ((1 << lp) - 1)) << lc) |
		(uint32(prevByte) >> (8 - lc))
	match := d.dict.getByte(int(d.rep[0]) + 1)
	s, err := d.litDecoder.Decode(d.rd, d.state, match, litState)
	if err != nil {
		return nil, err
	}
	return lit{s}, nil
}

// errWrongTermination indicates that a termination symbol has been received,
// but the range decoder could still produces more data
var errWrongTermination = errors.New(
	"range decoder doesn't support termination")

// decodeOp decodes an operation. The function returns io.EOF if the stream is
// terminated.
func (d *Decoder) decodeOp() (op operation, err error) {
	posState := uint32(d.dict.total) & d.posBitMask
	state2 := (d.state << maxPosBits) | posState

	b, err := d.isMatch[state2].Decode(d.rd)
	if err != nil {
		return nil, err
	}
	if b == 0 {
		// literal
		op, err := d.decodeLiteral()
		if err != nil {
			return nil, err
		}
		d.updateStateLiteral()
		return op, nil
	}
	b, err = d.isRep[d.state].Decode(d.rd)
	if err != nil {
		return nil, err
	}
	if b == 0 {
		// simple match
		d.rep[3], d.rep[2], d.rep[1] = d.rep[2], d.rep[1], d.rep[0]
		d.updateStateMatch()
		// The length decoder returns the length offset.
		l, err := d.lengthDecoder.Decode(d.rd, posState)
		if err != nil {
			return nil, err
		}
		// The dist decoder returns the distance offset. The actual
		// distance is 1 higher.
		d.rep[0], err = d.distDecoder.Decode(l, d.rd)
		if err != nil {
			return nil, err
		}
		if d.rep[0] == 0xffffffff {
			if !d.rd.possiblyAtEnd() {
				return nil, errWrongTermination
			}
			return nil, io.EOF
		}
		op := rep{length: int(l) + minLength,
			distance: int(d.rep[0]) + minDistance}
		return op, nil
	}
	b, err = d.isRepG0[d.state].Decode(d.rd)
	if b == 0 {
		// rep0
		panic("TODO")
	}
	b, err = d.isRepG1[d.state].Decode(d.rd)
	if b == 0 {
		// rep match 1
		panic("TODO")
	}
	b, err = d.isRepG2[d.state].Decode(d.rd)
	if b == 0 {
		// rep match 2
		panic("TODO")
	}
	// rep match 3
	panic("TODO")
}
<commit_msg>lzma: implemented decoder method decodeOp<commit_after>package lzma

import (
	"bufio"
	"errors"
	"io"
)

// states defines the overall state count
const states = 12

// bufferLen is the value used for the bufferLen used by the decoder.
var bufferLen = 64 * (1 << 10)

// Decoder is able to read a LZMA byte stream and to read the plain text.
type Decoder struct {
	properties         Properties
	packedLen          uint64
	unpackedLen        uint64
	unpackedLenDefined bool
	dict               *decoderDict
	state              uint32
	posBitMask         uint32
	rd                 *rangeDecoder
	isMatch            [states << maxPosBits]prob
	isRep              [states]prob
	isRepG0            [states]prob
	isRepG1            [states]prob
	isRepG2            [states]prob
	isRepG0Long        [states << maxPosBits]prob
	rep                [4]uint32
	litDecoder         *literalCodec
	lengthDecoder      *lengthCodec
	repLengthDecoder   *lengthCodec
	distDecoder        *distCodec
}

// NewDecoder creates an LZMA decoder. It reads the classic, original LZMA
// format. Note that LZMA2 uses a different header format.
func NewDecoder(r io.Reader) (d *Decoder, err error) {
	f := bufio.NewReader(r)
	properties, err := readProperties(f)
	if err != nil {
		return nil, err
	}
	historyLen := int(properties.DictLen)
	if historyLen < 0 {
		return nil, errors.New(
			"LZMA property DictLen exceeds maximum int value")
	}
	d = &Decoder{
		properties: *properties,
	}
	if d.packedLen, err = readUint64LE(f); err != nil {
		return nil, err
	}
	if d.dict, err = newDecoderDict(bufferLen, historyLen); err != nil {
		return nil, err
	}
	d.posBitMask = (uint32(1) << uint(d.properties.PB)) - 1
	if d.rd, err = newRangeDecoder(f); err != nil {
		return nil, err
	}
	initProbSlice(d.isMatch[:])
	initProbSlice(d.isRep[:])
	initProbSlice(d.isRepG0[:])
	initProbSlice(d.isRepG1[:])
	initProbSlice(d.isRepG2[:])
	initProbSlice(d.isRepG0Long[:])
	d.litDecoder = newLiteralCodec(d.properties.LC, d.properties.LP)
	d.lengthDecoder = newLengthCodec()
	d.repLengthDecoder = newLengthCodec()
	d.distDecoder = newDistCodec()
	return d, nil
}

// Properties returns a set of properties.
func (d *Decoder) Properties() Properties {
	return d.properties
}

// getUint64LE converts the uint64 value stored as little endian to an uint64
// value.
func getUint64LE(b []byte) uint64 {
	x := uint64(b[7]) << 56
	x |= uint64(b[6]) << 48
	x |= uint64(b[5]) << 40
	x |= uint64(b[4]) << 32
	x |= uint64(b[3]) << 24
	x |= uint64(b[2]) << 16
	x |= uint64(b[1]) << 8
	x |= uint64(b[0])
	return x
}

// readUint64LE reads a uint64 little-endian integer from reader.
func readUint64LE(r io.Reader) (x uint64, err error) {
	b := make([]byte, 8)
	if _, err = io.ReadFull(r, b); err != nil {
		return 0, err
	}
	x = getUint64LE(b)
	return x, nil
}

// initProbSlice initializes a slice of probabilities.
func initProbSlice(p []prob) {
	for i := range p {
		p[i] = probInit
	}
}

// Reads reads data from the decoder stream.
//
// The function fill put as much data in the buffer as it is available. The
// function might block and is not reentrant.
//
// The end of the LZMA stream is indicated by EOF. There might be other errors
// returned. The decoder will not be able to recover from an error returned.
func (d *Decoder) Read(p []byte) (n int, err error) {
	for n < len(p) {
		var k int
		k, err = d.dict.Read(p)
		if err != nil {
			return
		}
		n += k
		if n == len(p) {
			return
		}
		if err = d.fill(len(p) - n); err != nil {
			return
		}
	}
	return
}

// fill puts at lest the requested number of bytes into the decoder dictionary.
func (d *Decoder) fill(n int) error {
	panic("TODO")
}

// updateStateLiteral updates the state for a literal.
func (d *Decoder) updateStateLiteral() {
	switch {
	case d.state < 4:
		d.state = 0
		return
	case d.state < 10:
		d.state -= 3
		return
	}
	d.state -= 6
	return
}

// updateStateMatch updates the state for a match.
func (d *Decoder) updateStateMatch() {
	if d.state < 7 {
		d.state = 7
		return
	}
	d.state = 10
	return
}

// updateStateRep updates the state for a repetition.
func (d *Decoder) updateStateRep() {
	if d.state < 7 {
		d.state = 8
	}
	d.state = 11
}

// updateStateShortRep updates the state for a short repetition.
func (d *Decoder) updateStateShortRep() {
	if d.state < 7 {
		d.state = 9
	}
	d.state = 11
}

// decodeLiteral decodes a literal.
func (d *Decoder) decodeLiteral() (op operation, err error) {
	prevByte := d.dict.getByte(1)
	lp, lc := uint(d.properties.LP), uint(d.properties.LC)
	litState := ((uint32(d.dict.total) & ((1 << lp) - 1)) << lc) |
		(uint32(prevByte) >> (8 - lc))
	match := d.dict.getByte(int(d.rep[0]) + 1)
	s, err := d.litDecoder.Decode(d.rd, d.state, match, litState)
	if err != nil {
		return nil, err
	}
	return lit{s}, nil
}

// errWrongTermination indicates that a termination symbol has been received,
// but the range decoder could still produces more data
var errWrongTermination = errors.New(
	"range decoder doesn't support termination")

// decodeOp decodes an operation. The function returns io.EOF if the stream is
// terminated.
func (d *Decoder) decodeOp() (op operation, err error) {
	posState := uint32(d.dict.total) & d.posBitMask
	state2 := (d.state << maxPosBits) | posState

	b, err := d.isMatch[state2].Decode(d.rd)
	if err != nil {
		return nil, err
	}
	if b == 0 {
		// literal
		op, err := d.decodeLiteral()
		if err != nil {
			return nil, err
		}
		d.updateStateLiteral()
		return op, nil
	}
	b, err = d.isRep[d.state].Decode(d.rd)
	if err != nil {
		return nil, err
	}
	if b == 0 {
		// simple match
		d.rep[3], d.rep[2], d.rep[1] = d.rep[2], d.rep[1], d.rep[0]
		d.updateStateMatch()
		// The length decoder returns the length offset.
		l, err := d.lengthDecoder.Decode(d.rd, posState)
		if err != nil {
			return nil, err
		}
		// The dist decoder returns the distance offset. The actual
		// distance is 1 higher.
		d.rep[0], err = d.distDecoder.Decode(l, d.rd)
		if err != nil {
			return nil, err
		}
		if d.rep[0] == 0xffffffff {
			if !d.rd.possiblyAtEnd() {
				return nil, errWrongTermination
			}
			return nil, io.EOF
		}
		op = rep{length: int(l) + minLength,
			distance: int(d.rep[0]) + minDistance}
		return op, nil
	}
	b, err = d.isRepG0[d.state].Decode(d.rd)
	if err != nil {
		return nil, err
	}
	dist := d.rep[0]
	if b == 0 {
		// rep match 0
		b, err = d.isRepG0Long[state2].Decode(d.rd)
		if err != nil {
			return nil, err
		}
		if b == 0 {
			d.updateStateShortRep()
			op = rep{length: 1,
				distance: int(d.rep[0]) + minDistance}
			return op, nil
		}
	} else {
		b, err = d.isRepG1[d.state].Decode(d.rd)
		if err != nil {
			return nil, err
		}
		if b == 0 {
			dist = d.rep[1]
		} else {
			b, err = d.isRepG2[d.state].Decode(d.rd)
			if err != nil {
				return nil, err
			}
			if b == 0 {
				dist = d.rep[2]
			} else {
				dist = d.rep[3]
				d.rep[3] = d.rep[2]
			}
			d.rep[2] = d.rep[1]
		}
		d.rep[1] = d.rep[0]
		d.rep[0] = dist
	}
	l, err := d.repLengthDecoder.Decode(d.rd, posState)
	if err != nil {
		return nil, err
	}
	d.updateStateRep()
	op = rep{length: int(l) + minLength, distance: int(dist) + minDistance}
	return op, nil
}
<|endoftext|>


<commit_before>package lzma

import "io"

// opLenMargin provides the upper limit of the number of bytes required
// to encode a single operation.
const opLenMargin = 10

// compressFlags control the compression process.
type compressFlags uint32

// Values for compressFlags.
const (
	// all data should be compresed, even if compression is not
	// optimal.
	all compressFlags = 1 << iota
)

// opFinder enables the support of multiple different OpFinder
// algorithms.
type opFinder interface {
	findOps(e *EncoderDict, r reps, flags compressFlags) []operation
	name() string
}

// EncoderFlags provide the flags for an encoder.
type EncoderFlags uint32

// Flags for the encoder.
const (
	// Requests that an EOSMarker is written.
	EOSMarker EncoderFlags = 1 << iota
)

// Encoder compresses data buffered in the encoder dictionary and writes
// it into a byte writer.
type Encoder struct {
	Dict       *EncoderDict
	State      *State
	writerDict writerDict
	re         *rangeEncoder
	start      int64
	// generate eos marker
	marker   bool
	limit    bool
	opFinder opFinder
	margin   int
}

// NewEncoder creates a new encoder. If the byte writer must be
// limited use LimitedByteWriter provided by this package. The flags
// argument supports the EOSMarker flag, controlling whether a
// termnating end-of-stream marker must be written.
func NewEncoder(bw io.ByteWriter, state *State, dict *EncoderDict,
	flags EncoderFlags) (e *Encoder, err error) {

	re, err := newRangeEncoder(bw)
	if err != nil {
		return nil, err
	}
	e = &Encoder{
		opFinder: greedyFinder{},
		Dict:     dict,
		State:    state,
		re:       re,
		marker:   flags&EOSMarker != 0,
		start:    dict.pos(),
		margin:   opLenMargin,
	}
	if e.marker {
		e.margin += 5
	}
	return e, nil
}

// Write writes the bytes from p into the dictionary. If not enough
// space is available the data in the dictionary buffer will be
// compressed to make additional space available.
func (e *Encoder) Write(p []byte) (n int, err error) {
	for {
		k, err := e.Dict.write(p[n:])
		n += k
		if err == ErrNoSpace {
			if err = e.compress(0); err != nil {
				return n, err
			}
			continue
		}
		return n, err
	}
}

// Reopen reopens the encoder with a new byte writer.
func (e *Encoder) Reopen(bw io.ByteWriter) error {
	var err error
	if e.re, err = newRangeEncoder(bw); err != nil {
		return err
	}
	e.start = e.Dict.pos()
	return nil
}

// writeLiteral writes a literal into the LZMA stream
func (e *Encoder) writeLiteral(l lit) error {
	var err error
	state, state2, _ := e.State.states(e.writerDict.pos())
	if err = e.State.isMatch[state2].Encode(e.re, 0); err != nil {
		return err
	}
	litState := e.State.litState(e.writerDict.byteAt(1), e.writerDict.pos())
	match := e.writerDict.byteAt(int(e.State.rep[0]) + 1)
	err = e.State.litCodec.Encode(e.re, l.b, state, match, litState)
	if err != nil {
		return err
	}
	e.State.updateStateLiteral()
	return nil
}

// iverson implements the Iverson operator as proposed by Donald Knuth in his
// book Concrete Mathematics.
func iverson(ok bool) uint32 {
	if ok {
		return 1
	}
	return 0
}

// writeMatch writes a repetition operation into the operation stream
func (e *Encoder) writeMatch(m match) error {
	var err error
	if !(minDistance <= m.distance && m.distance <= maxDistance) {
		panic("match distance out of range")
	}
	dist := uint32(m.distance - minDistance)
	if !(minMatchLen <= m.n && m.n <= maxMatchLen) &&
		!(dist == e.State.rep[0] && m.n == 1) {
		panic("match length out of range")
	}
	state, state2, posState := e.State.states(e.writerDict.pos())
	if err = e.State.isMatch[state2].Encode(e.re, 1); err != nil {
		return err
	}
	g := 0
	for ; g < 4; g++ {
		if e.State.rep[g] == dist {
			break
		}
	}
	b := iverson(g < 4)
	if err = e.State.isRep[state].Encode(e.re, b); err != nil {
		return err
	}
	n := uint32(m.n - minMatchLen)
	if b == 0 {
		// simple match
		e.State.rep[3], e.State.rep[2], e.State.rep[1], e.State.rep[0] =
			e.State.rep[2], e.State.rep[1], e.State.rep[0], dist
		e.State.updateStateMatch()
		if err = e.State.lenCodec.Encode(e.re, n, posState); err != nil {
			return err
		}
		return e.State.distCodec.Encode(e.re, dist, n)
	}
	b = iverson(g != 0)
	if err = e.State.isRepG0[state].Encode(e.re, b); err != nil {
		return err
	}
	if b == 0 {
		// g == 0
		b = iverson(m.n != 1)
		if err = e.State.isRepG0Long[state2].Encode(e.re, b); err != nil {
			return err
		}
		if b == 0 {
			e.State.updateStateShortRep()
			return nil
		}
	} else {
		// g in {1,2,3}
		b = iverson(g != 1)
		if err = e.State.isRepG1[state].Encode(e.re, b); err != nil {
			return err
		}
		if b == 1 {
			// g in {2,3}
			b = iverson(g != 2)
			err = e.State.isRepG2[state].Encode(e.re, b)
			if err != nil {
				return err
			}
			if b == 1 {
				e.State.rep[3] = e.State.rep[2]
			}
			e.State.rep[2] = e.State.rep[1]
		}
		e.State.rep[1] = e.State.rep[0]
		e.State.rep[0] = dist
	}
	e.State.updateStateRep()
	return e.State.repLenCodec.Encode(e.re, n, posState)
}

// writeOp writes an operation value into the stream. It checks whether there
// is still enough space available using an upper limit for the size required.
func (e *Encoder) writeOp(op operation) error {
	if e.re.Available() < int64(e.margin) {
		return ErrLimit
	}
	var err error
	switch x := op.(type) {
	case match:
		err = e.writeMatch(x)
	case lit:
		err = e.writeLiteral(x)
	}
	if err != nil {
		return err
	}
	_, err = e.writerDict.advance(op.Len())
	return err
}

// compress compressed data from the dictionary buffer. If the flag all
// is set, all data in the dictionay buffer will be compressed.
func (e *Encoder) compress(flags compressFlags) error {
	if e.limit {
		return ErrLimit
	}
	e.writerDict = e.Dict.writerDict
	ops := e.opFinder.findOps(e.Dict, reps(e.State.rep), flags)
	for _, op := range ops {
		if err := e.writeOp(op); err != nil {
			if err == ErrLimit {
				e.limit = true
			}
			return err
		}
	}
	return nil
}

// eosMatch is a pseudo operation that indicates the end of the stream.
var eosMatch = match{distance: maxDistance, n: minMatchLen}

// Close terminates the LZMA stream. If requested the end-of-stream
// marker will be written. ErrLimit is returned if the limit in the
// underlying write stream has been encountered.
func (e *Encoder) Close() error {
	cerr := e.compress(all)
	if cerr != nil && cerr != ErrLimit {
		return cerr
	}
	if e.marker {
		if err := e.writeMatch(eosMatch); err != nil {
			return err
		}
	}
	if err := e.re.Close(); err != nil {
		return err
	}
	return cerr
}

// Compressed returns the number bytes of the input data that been
// compressed.
func (e *Encoder) Compressed() int64 {
	return e.Dict.pos() - e.start
}
<commit_msg>lzma: changed behaviour of encoder<commit_after>package lzma

import "io"

// opLenMargin provides the upper limit of the number of bytes required
// to encode a single operation.
const opLenMargin = 10

// compressFlags control the compression process.
type compressFlags uint32

// Values for compressFlags.
const (
	// all data should be compresed, even if compression is not
	// optimal.
	all compressFlags = 1 << iota
)

// opFinder enables the support of multiple different OpFinder
// algorithms.
type opFinder interface {
	findOps(e *EncoderDict, r reps, flags compressFlags) []operation
	name() string
}

// EncoderFlags provide the flags for an encoder.
type EncoderFlags uint32

// Flags for the encoder.
const (
	// Requests that an EOSMarker is written.
	EOSMarker EncoderFlags = 1 << iota
)

// Encoder compresses data buffered in the encoder dictionary and writes
// it into a byte writer.
type Encoder struct {
	Dict       *EncoderDict
	State      *State
	writerDict writerDict
	re         *rangeEncoder
	start      int64
	// generate eos marker
	marker   bool
	limit    bool
	opFinder opFinder
	margin   int
}

// NewEncoder creates a new encoder. If the byte writer must be
// limited use LimitedByteWriter provided by this package. The flags
// argument supports the EOSMarker flag, controlling whether a
// termnating end-of-stream marker must be written.
func NewEncoder(bw io.ByteWriter, state *State, dict *EncoderDict,
	flags EncoderFlags) (e *Encoder, err error) {

	re, err := newRangeEncoder(bw)
	if err != nil {
		return nil, err
	}
	e = &Encoder{
		opFinder: greedyFinder{},
		Dict:     dict,
		State:    state,
		re:       re,
		marker:   flags&EOSMarker != 0,
		start:    dict.pos(),
		margin:   opLenMargin,
	}
	if e.marker {
		e.margin += 5
	}
	return e, nil
}

// Write writes the bytes from p into the dictionary. If not enough
// space is available the data in the dictionary buffer will be
// compressed to make additional space available. If the limit of the
// underlying writer has been reached ErrLimit will be returned.
func (e *Encoder) Write(p []byte) (n int, err error) {
	for {
		k, err := e.Dict.write(p[n:])
		n += k
		if err == ErrNoSpace {
			if err = e.compress(0); err != nil {
				return n, err
			}
			continue
		}
		return n, err
	}
}

// Reopen reopens the encoder with a new byte writer.
func (e *Encoder) Reopen(bw io.ByteWriter) error {
	var err error
	if e.re, err = newRangeEncoder(bw); err != nil {
		return err
	}
	e.start = e.Dict.pos()
	return nil
}

// writeLiteral writes a literal into the LZMA stream
func (e *Encoder) writeLiteral(l lit) error {
	var err error
	state, state2, _ := e.State.states(e.writerDict.pos())
	if err = e.State.isMatch[state2].Encode(e.re, 0); err != nil {
		return err
	}
	litState := e.State.litState(e.writerDict.byteAt(1), e.writerDict.pos())
	match := e.writerDict.byteAt(int(e.State.rep[0]) + 1)
	err = e.State.litCodec.Encode(e.re, l.b, state, match, litState)
	if err != nil {
		return err
	}
	e.State.updateStateLiteral()
	return nil
}

// iverson implements the Iverson operator as proposed by Donald Knuth in his
// book Concrete Mathematics.
func iverson(ok bool) uint32 {
	if ok {
		return 1
	}
	return 0
}

// writeMatch writes a repetition operation into the operation stream
func (e *Encoder) writeMatch(m match) error {
	var err error
	if !(minDistance <= m.distance && m.distance <= maxDistance) {
		panic("match distance out of range")
	}
	dist := uint32(m.distance - minDistance)
	if !(minMatchLen <= m.n && m.n <= maxMatchLen) &&
		!(dist == e.State.rep[0] && m.n == 1) {
		panic("match length out of range")
	}
	state, state2, posState := e.State.states(e.writerDict.pos())
	if err = e.State.isMatch[state2].Encode(e.re, 1); err != nil {
		return err
	}
	g := 0
	for ; g < 4; g++ {
		if e.State.rep[g] == dist {
			break
		}
	}
	b := iverson(g < 4)
	if err = e.State.isRep[state].Encode(e.re, b); err != nil {
		return err
	}
	n := uint32(m.n - minMatchLen)
	if b == 0 {
		// simple match
		e.State.rep[3], e.State.rep[2], e.State.rep[1], e.State.rep[0] =
			e.State.rep[2], e.State.rep[1], e.State.rep[0], dist
		e.State.updateStateMatch()
		if err = e.State.lenCodec.Encode(e.re, n, posState); err != nil {
			return err
		}
		return e.State.distCodec.Encode(e.re, dist, n)
	}
	b = iverson(g != 0)
	if err = e.State.isRepG0[state].Encode(e.re, b); err != nil {
		return err
	}
	if b == 0 {
		// g == 0
		b = iverson(m.n != 1)
		if err = e.State.isRepG0Long[state2].Encode(e.re, b); err != nil {
			return err
		}
		if b == 0 {
			e.State.updateStateShortRep()
			return nil
		}
	} else {
		// g in {1,2,3}
		b = iverson(g != 1)
		if err = e.State.isRepG1[state].Encode(e.re, b); err != nil {
			return err
		}
		if b == 1 {
			// g in {2,3}
			b = iverson(g != 2)
			err = e.State.isRepG2[state].Encode(e.re, b)
			if err != nil {
				return err
			}
			if b == 1 {
				e.State.rep[3] = e.State.rep[2]
			}
			e.State.rep[2] = e.State.rep[1]
		}
		e.State.rep[1] = e.State.rep[0]
		e.State.rep[0] = dist
	}
	e.State.updateStateRep()
	return e.State.repLenCodec.Encode(e.re, n, posState)
}

// writeOp writes an operation value into the stream. It checks whether there
// is still enough space available using an upper limit for the size required.
func (e *Encoder) writeOp(op operation) error {
	if e.re.Available() < int64(e.margin) {
		return ErrLimit
	}
	var err error
	switch x := op.(type) {
	case match:
		err = e.writeMatch(x)
	case lit:
		err = e.writeLiteral(x)
	}
	if err != nil {
		return err
	}
	_, err = e.writerDict.advance(op.Len())
	return err
}

// compress compressed data from the dictionary buffer. If the flag all
// is set, all data in the dictionay buffer will be compressed. The
// function returns ErrLimit if the underlying writer has reached its
// limit.
func (e *Encoder) compress(flags compressFlags) error {
	if e.limit {
		return ErrLimit
	}
	e.writerDict = e.Dict.writerDict
	ops := e.opFinder.findOps(e.Dict, reps(e.State.rep), flags)
	for _, op := range ops {
		if err := e.writeOp(op); err != nil {
			if err == ErrLimit {
				e.limit = true
			}
			return err
		}
	}
	return nil
}

// eosMatch is a pseudo operation that indicates the end of the stream.
var eosMatch = match{distance: maxDistance, n: minMatchLen}

// Close terminates the LZMA stream. If requested the end-of-stream
// marker will be written. Reaching the writer limit is ignored.
func (e *Encoder) Close() error {
	err := e.compress(all)
	if err != nil && err != ErrLimit {
		return err
	}
	if e.marker {
		if err := e.writeMatch(eosMatch); err != nil {
			return err
		}
	}
	err = e.re.Close()
	return err
}

// Compressed returns the number bytes of the input data that been
// compressed.
func (e *Encoder) Compressed() int64 {
	return e.Dict.pos() - e.start
}
<|endoftext|>


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

package bytes

// Simple byte buffer for marshaling data.

import (
	"io";
	"os";
)

// Copy from string to byte array at offset doff.  Assume there's room.
func copyString(dst []byte, doff int, str string) {
	for soff := 0; soff < len(str); soff++ {
		dst[doff] = str[soff];
		doff++;
	}
}

// Copy from bytes to byte array at offset doff.  Assume there's room.
func copyBytes(dst []byte, doff int, src []byte) {
	if len(src) == 1 {
		dst[doff] = src[0];
		return;
	}
	copy(dst[doff:], src);
}

// A Buffer is a variable-sized buffer of bytes
// with Read and Write methods.
// The zero value for Buffer is an empty buffer ready to use.
type Buffer struct {
	buf	[]byte;	// contents are the bytes buf[off : len(buf)]
	off	int;	// read at &buf[off], write at &buf[len(buf)]
	oneByte	[]byte;	// avoid allocation of slice on each WriteByte
}

// Bytes returns the contents of the unread portion of the buffer;
// len(b.Bytes()) == b.Len().
func (b *Buffer) Bytes() []byte	{ return b.buf[b.off:] }

// String returns the contents of the unread portion of the buffer
// as a string.  If the Buffer is a nil pointer, it returns "<nil>".
func (b *Buffer) String() string {
	if b == nil {
		// Special case, useful in debugging.
		return "<nil>"
	}
	return string(b.buf[b.off:]);
}

// Len returns the number of bytes of the unread portion of the buffer;
// b.Len() == len(b.Bytes()).
func (b *Buffer) Len() int	{ return len(b.buf) - b.off }

// Truncate discards all but the first n unread bytes from the buffer.
// It is an error to call b.Truncate(n) with n > b.Len().
func (b *Buffer) Truncate(n int) {
	if n == 0 {
		// Reuse buffer space.
		b.off = 0
	}
	b.buf = b.buf[0 : b.off+n];
}

// Reset resets the buffer so it has no content.
// b.Reset() is the same as b.Truncate(0).
func (b *Buffer) Reset()	{ b.Truncate(0) }

// Write appends the contents of p to the buffer.  The return
// value n is the length of p; err is always nil.
func (b *Buffer) Write(p []byte) (n int, err os.Error) {
	m := b.Len();
	n = len(p);

	if len(b.buf)+n > cap(b.buf) {
		// not enough space at end
		buf := b.buf;
		if m+n > cap(b.buf) {
			// not enough space anywhere
			buf = make([]byte, 2*cap(b.buf)+n)
		}
		copyBytes(buf, 0, b.buf[b.off:b.off+m]);
		b.buf = buf;
		b.off = 0;
	}

	b.buf = b.buf[0 : b.off+m+n];
	copyBytes(b.buf, b.off+m, p);
	return n, nil;
}

// MinRead is the minimum slice size passed to a Read call by
// Buffer.ReadFrom.  As long as the Buffer has at least MinRead bytes beyond
// what is required to hold the contents of r, ReadFrom will not grow the
// underlying buffer.
const MinRead = 512

// ReadFrom reads data from r until EOF and appends it to the buffer.
// The return value n is the number of bytes read.
// Any error except os.EOF encountered during the read
// is also returned.
func (b *Buffer) ReadFrom(r io.Reader) (n int64, err os.Error) {
	for {
		if cap(b.buf)-len(b.buf) < MinRead {
			var newBuf []byte;
			// can we get space without allocation?
			if b.off+cap(b.buf)-len(b.buf) >= MinRead {
				// reuse beginning of buffer
				newBuf = b.buf[0 : len(b.buf)-b.off]
			} else {
				// not enough space at end; put space on end
				newBuf = make([]byte, len(b.buf)-b.off, 2*(cap(b.buf)-b.off)+MinRead)
			}
			copy(newBuf, b.buf[b.off:]);
			b.buf = newBuf;
			b.off = 0;
		}
		m, e := r.Read(b.buf[len(b.buf):cap(b.buf)]);
		b.buf = b.buf[b.off : len(b.buf)+m];
		n += int64(m);
		if e == os.EOF {
			break
		}
		if e != nil {
			return n, e
		}
	}
	return n, nil;	// err is EOF, so return nil explicitly
}

// WriteTo writes data to w until the buffer is drained or an error
// occurs. The return value n is the number of bytes written.
// Any error encountered during the write is also returned.
func (b *Buffer) WriteTo(w io.Writer) (n int64, err os.Error) {
	for b.off < len(b.buf) {
		m, e := w.Write(b.buf[b.off:]);
		n += int64(m);
		b.off += m;
		if e != nil {
			return n, e
		}
	}
	return;
}

// WriteString appends the contents of s to the buffer.  The return
// value n is the length of s; err is always nil.
func (b *Buffer) WriteString(s string) (n int, err os.Error) {
	m := b.Len();
	n = len(s);

	if len(b.buf)+n > cap(b.buf) {
		// not enough space at end
		buf := b.buf;
		if m+n > cap(b.buf) {
			// not enough space anywhere
			buf = make([]byte, 2*cap(b.buf)+n)
		}
		copyBytes(buf, 0, b.buf[b.off:b.off+m]);
		b.buf = buf;
		b.off = 0;
	}

	b.buf = b.buf[0 : b.off+m+n];
	copyString(b.buf, b.off+m, s);
	return n, nil;
}

// WriteByte appends the byte c to the buffer.
// The returned error is always nil, but is included
// to match bufio.Writer's WriteByte.
func (b *Buffer) WriteByte(c byte) os.Error {
	if b.oneByte == nil {
		// Only happens once per Buffer, and then we have a slice.
		b.oneByte = make([]byte, 1)
	}
	b.oneByte[0] = c;
	b.Write(b.oneByte);
	return nil;
}

// Read reads the next len(p) bytes from the buffer or until the buffer
// is drained.  The return value n is the number of bytes read.  If the
// buffer has no data to return, err is os.EOF even if len(p) is zero;
// otherwise it is nil.
func (b *Buffer) Read(p []byte) (n int, err os.Error) {
	if b.off >= len(b.buf) {
		return 0, os.EOF
	}
	m := b.Len();
	n = len(p);

	if n > m {
		// more bytes requested than available
		n = m
	}

	copyBytes(p, 0, b.buf[b.off:b.off+n]);
	b.off += n;
	return n, err;
}

// ReadByte reads and returns the next byte from the buffer.
// If no byte is available, it returns error os.EOF.
func (b *Buffer) ReadByte() (c byte, err os.Error) {
	if b.off >= len(b.buf) {
		return 0, os.EOF
	}
	c = b.buf[b.off];
	b.off++;
	return c, nil;
}

// NewBuffer creates and initializes a new Buffer
// using buf as its initial contents.
func NewBuffer(buf []byte) *Buffer	{ return &Buffer{buf: buf} }

// NewBufferString creates and initializes a new Buffer
// using string s as its initial contents.
func NewBufferString(s string) *Buffer {
	buf := make([]byte, len(s));
	copyString(buf, 0, s);
	return &Buffer{buf: buf};
}
<commit_msg>avoid an allocation inside bytes.Buffer by providing a static array.<commit_after>// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package bytes

// Simple byte buffer for marshaling data.

import (
	"io";
	"os";
)

// Copy from string to byte array at offset doff.  Assume there's room.
func copyString(dst []byte, doff int, str string) {
	for soff := 0; soff < len(str); soff++ {
		dst[doff] = str[soff];
		doff++;
	}
}

// Copy from bytes to byte array at offset doff.  Assume there's room.
func copyBytes(dst []byte, doff int, src []byte) {
	if len(src) == 1 {
		dst[doff] = src[0];
		return;
	}
	copy(dst[doff:], src);
}

// A Buffer is a variable-sized buffer of bytes
// with Read and Write methods.
// The zero value for Buffer is an empty buffer ready to use.
type Buffer struct {
	buf	[]byte;		// contents are the bytes buf[off : len(buf)]
	off	int;		// read at &buf[off], write at &buf[len(buf)]
	oneByte	[1]byte;	// avoid allocation of slice on each WriteByte
}

// Bytes returns the contents of the unread portion of the buffer;
// len(b.Bytes()) == b.Len().
func (b *Buffer) Bytes() []byte	{ return b.buf[b.off:] }

// String returns the contents of the unread portion of the buffer
// as a string.  If the Buffer is a nil pointer, it returns "<nil>".
func (b *Buffer) String() string {
	if b == nil {
		// Special case, useful in debugging.
		return "<nil>"
	}
	return string(b.buf[b.off:]);
}

// Len returns the number of bytes of the unread portion of the buffer;
// b.Len() == len(b.Bytes()).
func (b *Buffer) Len() int	{ return len(b.buf) - b.off }

// Truncate discards all but the first n unread bytes from the buffer.
// It is an error to call b.Truncate(n) with n > b.Len().
func (b *Buffer) Truncate(n int) {
	if n == 0 {
		// Reuse buffer space.
		b.off = 0
	}
	b.buf = b.buf[0 : b.off+n];
}

// Reset resets the buffer so it has no content.
// b.Reset() is the same as b.Truncate(0).
func (b *Buffer) Reset()	{ b.Truncate(0) }

// Write appends the contents of p to the buffer.  The return
// value n is the length of p; err is always nil.
func (b *Buffer) Write(p []byte) (n int, err os.Error) {
	m := b.Len();
	n = len(p);

	if len(b.buf)+n > cap(b.buf) {
		// not enough space at end
		buf := b.buf;
		if m+n > cap(b.buf) {
			// not enough space anywhere
			buf = make([]byte, 2*cap(b.buf)+n)
		}
		copyBytes(buf, 0, b.buf[b.off:b.off+m]);
		b.buf = buf;
		b.off = 0;
	}

	b.buf = b.buf[0 : b.off+m+n];
	copyBytes(b.buf, b.off+m, p);
	return n, nil;
}

// MinRead is the minimum slice size passed to a Read call by
// Buffer.ReadFrom.  As long as the Buffer has at least MinRead bytes beyond
// what is required to hold the contents of r, ReadFrom will not grow the
// underlying buffer.
const MinRead = 512

// ReadFrom reads data from r until EOF and appends it to the buffer.
// The return value n is the number of bytes read.
// Any error except os.EOF encountered during the read
// is also returned.
func (b *Buffer) ReadFrom(r io.Reader) (n int64, err os.Error) {
	for {
		if cap(b.buf)-len(b.buf) < MinRead {
			var newBuf []byte;
			// can we get space without allocation?
			if b.off+cap(b.buf)-len(b.buf) >= MinRead {
				// reuse beginning of buffer
				newBuf = b.buf[0 : len(b.buf)-b.off]
			} else {
				// not enough space at end; put space on end
				newBuf = make([]byte, len(b.buf)-b.off, 2*(cap(b.buf)-b.off)+MinRead)
			}
			copy(newBuf, b.buf[b.off:]);
			b.buf = newBuf;
			b.off = 0;
		}
		m, e := r.Read(b.buf[len(b.buf):cap(b.buf)]);
		b.buf = b.buf[b.off : len(b.buf)+m];
		n += int64(m);
		if e == os.EOF {
			break
		}
		if e != nil {
			return n, e
		}
	}
	return n, nil;	// err is EOF, so return nil explicitly
}

// WriteTo writes data to w until the buffer is drained or an error
// occurs. The return value n is the number of bytes written.
// Any error encountered during the write is also returned.
func (b *Buffer) WriteTo(w io.Writer) (n int64, err os.Error) {
	for b.off < len(b.buf) {
		m, e := w.Write(b.buf[b.off:]);
		n += int64(m);
		b.off += m;
		if e != nil {
			return n, e
		}
	}
	return;
}

// WriteString appends the contents of s to the buffer.  The return
// value n is the length of s; err is always nil.
func (b *Buffer) WriteString(s string) (n int, err os.Error) {
	m := b.Len();
	n = len(s);

	if len(b.buf)+n > cap(b.buf) {
		// not enough space at end
		buf := b.buf;
		if m+n > cap(b.buf) {
			// not enough space anywhere
			buf = make([]byte, 2*cap(b.buf)+n)
		}
		copyBytes(buf, 0, b.buf[b.off:b.off+m]);
		b.buf = buf;
		b.off = 0;
	}

	b.buf = b.buf[0 : b.off+m+n];
	copyString(b.buf, b.off+m, s);
	return n, nil;
}

// WriteByte appends the byte c to the buffer.
// The returned error is always nil, but is included
// to match bufio.Writer's WriteByte.
func (b *Buffer) WriteByte(c byte) os.Error {
	b.oneByte[0] = c;
	b.Write(&b.oneByte);
	return nil;
}

// Read reads the next len(p) bytes from the buffer or until the buffer
// is drained.  The return value n is the number of bytes read.  If the
// buffer has no data to return, err is os.EOF even if len(p) is zero;
// otherwise it is nil.
func (b *Buffer) Read(p []byte) (n int, err os.Error) {
	if b.off >= len(b.buf) {
		return 0, os.EOF
	}
	m := b.Len();
	n = len(p);

	if n > m {
		// more bytes requested than available
		n = m
	}

	copyBytes(p, 0, b.buf[b.off:b.off+n]);
	b.off += n;
	return n, err;
}

// ReadByte reads and returns the next byte from the buffer.
// If no byte is available, it returns error os.EOF.
func (b *Buffer) ReadByte() (c byte, err os.Error) {
	if b.off >= len(b.buf) {
		return 0, os.EOF
	}
	c = b.buf[b.off];
	b.off++;
	return c, nil;
}

// NewBuffer creates and initializes a new Buffer
// using buf as its initial contents.
func NewBuffer(buf []byte) *Buffer	{ return &Buffer{buf: buf} }

// NewBufferString creates and initializes a new Buffer
// using string s as its initial contents.
func NewBufferString(s string) *Buffer {
	buf := make([]byte, len(s));
	copyString(buf, 0, s);
	return &Buffer{buf: buf};
}
<|endoftext|>


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

package bytes

import "os"

// Efficient construction of large strings and byte arrays.
// Implements io.Reader and io.Writer.

// A Buffer provides efficient construction of large strings
// and slices of bytes.  It implements io.Reader and io.Writer.
// Appends (writes) are efficient.
// The zero value for Buffer is an empty buffer ready to use.
type Buffer struct {
	blk	[]block;
	len	int;
	oneByte	[1]byte;
}

// There are two kinds of block: a string or a []byte.
// When the user writes big strings, we add string blocks;
// when the user writes big byte slices, we add []byte blocks.
// Small writes are coalesced onto the end of the last block,
// whatever it is.
// This strategy is intended to reduce unnecessary allocation.
type block interface {
	Len()	int;
	String()	string;
	appendBytes(s []byte);
	appendString(s string);
	setSlice(m, n int);
}

// stringBlocks represent strings. We use pointer receivers
// so append and setSlice can overwrite the receiver.
type stringBlock string

func (b *stringBlock) Len() int {
	return len(*b)
}

func (b *stringBlock) String() string {
	return string(*b)
}

func (b *stringBlock) appendBytes(s []byte) {
	*b += stringBlock(s)
}

func (b *stringBlock) appendString(s string) {
	*b = stringBlock(s)
}

func (b *stringBlock) setSlice(m, n int) {
	*b = (*b)[m:n]
}

// byteBlock represent slices of bytes.  We use pointer receivers
// so append and setSlice can overwrite the receiver.
type byteBlock []byte

func (b *byteBlock) Len() int {
	return len(*b)
}

func (b *byteBlock) String() string {
	return string(*b)
}

func (b *byteBlock) resize(max int) {
	by := []byte(*b);
	if cap(by) >= max {
		by = by[0:max];
	} else {
		nby := make([]byte, max, 3*(max+10)/2);
		copyBytes(nby, 0, by);
		by = nby;
	}
	*b = by;
}

func (b *byteBlock) appendBytes(s []byte) {
	curLen := b.Len();
	b.resize(curLen + len(s));
	copyBytes([]byte(*b), curLen, s);
}

func (b *byteBlock) appendString(s string) {
	curLen := b.Len();
	b.resize(curLen + len(s));
	copyString([]byte(*b), curLen, s);
}

func (b *byteBlock) setSlice(m, n int) {
	*b = (*b)[m:n]
}

// Because the user may overwrite the contents of byte slices, we need
// to make a copy.  Allocation strategy: leave some space on the end so
// small subsequent writes can avoid another allocation.  The input
// is known to be non-empty.
func newByteBlock(s []byte) *byteBlock {
	l := len(s);
	// Capacity with room to grow.  If small, allocate a mininum.  If medium,
	// double the size.  If huge, use the size plus epsilon (room for a newline,
	// at least).
	c := l;
	switch {
	case l < 32:
		c = 64
	case l < 1<<18:
		c *= 2;
	default:
		c += 8
	}
	b := make([]byte, l, c);
	copyBytes(b, 0, s);
	return &b;
}

// Copy from block to byte array at offset doff.  Assume there's room.
func copy(dst []byte, doff int, src block) {
	switch s := src.(type) {
	case *stringBlock:
		copyString(dst, doff, string(*s));
	case *byteBlock:
		copyBytes(dst, doff, []byte(*s));
	}
}

// Copy from string to byte array at offset doff.  Assume there's room.
func copyString(dst []byte, doff int, str string) {
	for soff := 0; soff < len(str); soff++ {
		dst[doff] = str[soff];
		doff++;
	}
}

// Copy from bytes to byte array at offset doff.  Assume there's room.
func copyBytes(dst []byte, doff int, src []byte) {
	for soff := 0; soff < len(src); soff++ {
		dst[doff] = src[soff];
		doff++;
	}
}

// Bytes returns the contents of the unread portion of the buffer
// as a byte array.
func (b *Buffer) Bytes() []byte {
	n := b.len;
	bytes := make([]byte, n);
	nbytes := 0;
	for _, s := range b.blk {
		copy(bytes, nbytes, s);
		nbytes += s.Len();
	}
	return bytes;
}

// String returns the contents of the unread portion of the buffer
// as a string.
func (b *Buffer) String() string {
	if len(b.blk) == 1 {	// important special case
		return b.blk[0].String()
	}
	return string(b.Bytes())
}

// Len returns the number of bytes in the unread portion of the buffer;
// b.Len() == len(b.Bytes()) == len(b.String()).
func (b *Buffer) Len() int {
	return b.len
}

// Truncate discards all but the first n unread bytes from the buffer.
func (b *Buffer) Truncate(n int) {
	b.len = 0;	// recompute during scan.
	for i, s := range b.blk {
		if n <= 0 {
			b.blk = b.blk[0:i];
			break;
		}
		if l := s.Len(); n < l {
			b.blk[i].setSlice(0, n);
			b.len += n;
			n = 0;
		} else {
			b.len += l;
			n -= l;
		}
	}
}

// Reset resets the buffer so it has no content.
// b.Reset() is the same as b.Truncate(0).
func (b *Buffer) Reset() {
	b.blk = b.blk[0:0];
	b.len = 0;
}

// Can n bytes be appended efficiently to the end of the final string?
func (b *Buffer) canCombine(n int) bool {
	return len(b.blk) > 0 && n+b.blk[len(b.blk)-1].Len() <= 64
}

// WriteString appends string s to the buffer.  The return
// value n is the length of s; err is always nil.
func (b *Buffer) WriteString(s string) (n int, err os.Error) {
	n = len(s);
	if n == 0 {
		return
	}
	b.len += n;
	numStr := len(b.blk);
	// Special case: If the last piece is short and this one is short,
	// combine them and avoid growing the list.
	if b.canCombine(n) {
		b.blk[numStr-1].appendString(s);
		return
	}
	if cap(b.blk) == numStr {
		nstr := make([]block, numStr, 3*(numStr+10)/2);
		for i, s := range b.blk {
			nstr[i] = s;
		}
		b.blk = nstr;
	}
	b.blk = b.blk[0:numStr+1];
	// The string is immutable; no need to make a copy.
	b.blk[numStr] = (*stringBlock)(&s);
	return
}

// Write appends the contents of p to the buffer.  The return
// value n is the length of p; err is always nil.
func (b *Buffer) Write(p []byte) (n int, err os.Error) {
	n = len(p);
	if n == 0 {
		return
	}
	b.len += n;
	numStr := len(b.blk);
	// Special case: If the last piece is short and this one is short,
	// combine them and avoid growing the list.
	if b.canCombine(n) {
		b.blk[numStr-1].appendBytes(p);
		return
	}
	if cap(b.blk) == numStr {
		nstr := make([]block, numStr, 3*(numStr+10)/2);
		for i, s := range b.blk {
			nstr[i] = s;
		}
		b.blk = nstr;
	}
	b.blk = b.blk[0:numStr+1];
	// Need to copy the data - user might overwrite the data.
	b.blk[numStr] = newByteBlock(p);
	return
}

// WriteByte appends the byte c to the buffer.
// The returned error is always nil, but is included
// to match bufio.Writer's WriteByte.
func (b *Buffer) WriteByte(c byte) os.Error {
	b.oneByte[0] = c;
	// For WriteByte, canCombine is almost always true so it's worth
	// doing here.
	if b.canCombine(1) {
		b.blk[len(b.blk)-1].appendBytes(&b.oneByte);
		b.len++;
		return nil
	}
	b.Write(&b.oneByte);
	return nil;
}

// Read reads the next len(p) bytes from the buffer or until the buffer
// is drained.  The return value n is the number of bytes read.  If the
// buffer has no data to return, err is os.EOF even if len(p) is zero;
// otherwise it is nil.
func (b *Buffer) Read(p []byte) (n int, err os.Error) {
	if len(b.blk) == 0 {
		return 0, os.EOF
	}
	for len(b.blk) > 0 {
		blk := b.blk[0];
		m := len(p) - n;
		if l := blk.Len(); m >= l {
			// consume all of this string.
			copy(p, n, blk);
			n += l;
			b.blk = b.blk[1:len(b.blk)];
		} else {
			// consume some of this block; it's the last piece.
			switch b := blk.(type) {
			case *stringBlock:
				copyString(p, n, string(*b)[0:m]);
			case *byteBlock:
				copyBytes(p, n, []byte(*b)[0:m]);
			}
			n += m;
			b.blk[0].setSlice(m, l);
			break;
		}
	}
	b.len -= n;
	return
}

// ReadByte reads and returns the next byte from the buffer.
// If no byte is available, it returns error os.EOF.
func (b *Buffer) ReadByte() (c byte, err os.Error) {
	if _, err := b.Read(&b.oneByte); err != nil {
		return 0, err
	}
	return b.oneByte[0], nil
}

// NewBufferString creates and initializes a new Buffer
// using a string as its initial contents.
func NewBufferString(str string) *Buffer {
	b := new(Buffer);
	if len(str) > 0 {
		b.blk = make([]block, 1, 10);	// room to grow
		b.blk[0] = (*stringBlock)(&str);
	}
	b.len = len(str);
	return b;
}

// NewBuffer creates and initializes a new Buffer
// using a byte slice as its initial contents.
func NewBuffer(by []byte) *Buffer {
	b := new(Buffer);
	if len(by) > 0 {
		b.blk = make([]block, 1, 10);	// room to grow
		b.blk[0] = (*byteBlock)(&by);
	}
	b.len = len(by);
	return b;
}
<commit_msg>restore the old algorithm. the new one is more memory efficient in large cases but too slow across the board.<commit_after>// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package bytes

// Simple byte buffer for marshaling data.

import (
	"os";
)

// Copy from string to byte array at offset doff.  Assume there's room.
func copyString(dst []byte, doff int, str string) {
	for soff := 0; soff < len(str); soff++ {
		dst[doff] = str[soff];
		doff++;
	}
}

// Copy from bytes to byte array at offset doff.  Assume there's room.
func copyBytes(dst []byte, doff int, src []byte) {
	for soff := 0; soff < len(src); soff++ {
		dst[doff] = src[soff];
		doff++;
	}
}

// A Buffer is a variable-sized buffer of bytes
// with Read and Write methods.
// The zero value for Buffer is an empty buffer ready to use.
type Buffer struct {
	buf	[]byte;	// contents are the bytes buf[off : len(buf)]
	off	int;	// read at &buf[off], write at &buf[len(buf)]
	oneByte	[]byte;	// avoid allocation of slice on each WriteByte
}

// Bytes returns the contents of the unread portion of the buffer;
// len(b.Bytes()) == b.Len().
func (b *Buffer) Bytes() []byte {
	return b.buf[b.off : len(b.buf)]
}

// String returns the contents of the unread portion of the buffer
// as a string.
func (b *Buffer) String() string {
	return string(b.buf[b.off : len(b.buf)])
}

// Len returns the number of bytes of the unread portion of the buffer;
// b.Len() == len(b.Bytes()).
func (b *Buffer) Len() int {
	return len(b.buf) - b.off
}

// Truncate discards all but the first n unread bytes from the buffer.
// It is an error to call b.Truncate(n) with n > b.Len().
func (b *Buffer) Truncate(n int) {
	if n == 0 {
		// Reuse buffer space.
		b.off = 0;
	}
	b.buf = b.buf[0 : b.off + n];
}

// Reset resets the buffer so it has no content.
// b.Reset() is the same as b.Truncate(0).
func (b *Buffer) Reset() {
	b.Truncate(0);
}

// Write appends the contents of p to the buffer.  The return
// value n is the length of p; err is always nil.
func (b *Buffer) Write(p []byte) (n int, err os.Error) {
	m := b.Len();
	n = len(p);

	if len(b.buf) + n > cap(b.buf) {
		// not enough space at end
		buf := b.buf;
		if m + n > cap(b.buf) {
			// not enough space anywhere
			buf = make([]byte, 2*cap(b.buf) + n)
		}
		copyBytes(buf, 0, b.buf[b.off:b.off+m]);
		b.buf = buf;
		b.off = 0
	}

	b.buf = b.buf[0 : b.off + m + n];
	copyBytes(b.buf, b.off + m, p);
	return n, nil
}

// WriteString appends the contents of s to the buffer.  The return
// value n is the length of s; err is always nil.
func (b *Buffer) WriteString(s string) (n int, err os.Error) {
	m := b.Len();
	n = len(s);

	if len(b.buf) + n > cap(b.buf) {
		// not enough space at end
		buf := b.buf;
		if m + n > cap(b.buf) {
			// not enough space anywhere
			buf = make([]byte, 2*cap(b.buf) + n)
		}
		copyBytes(buf, 0, b.buf[b.off:b.off+m]);
		b.buf = buf;
		b.off = 0
	}

	b.buf = b.buf[0 : b.off + m + n];
	copyString(b.buf, b.off+m, s);
	return n, nil
}

// WriteByte appends the byte c to the buffer.
// The returned error is always nil, but is included
// to match bufio.Writer's WriteByte.
func (b *Buffer) WriteByte(c byte) os.Error {
	if b.oneByte == nil {
		// Only happens once per Buffer, and then we have a slice.
		b.oneByte = make([]byte, 1);
	}
	b.oneByte[0] = c;
	b.Write(b.oneByte);
	return nil;
}

// Read reads the next len(p) bytes from the buffer or until the buffer
// is drained.  The return value n is the number of bytes read.  If the
// buffer has no data to return, err is os.EOF even if len(p) is zero;
// otherwise it is nil.
func (b *Buffer) Read(p []byte) (n int, err os.Error) {
	if b.off >= len(b.buf) {
		return 0, os.EOF
	}
	m := b.Len();
	n = len(p);

	if n > m {
		// more bytes requested than available
		n = m
	}

	copyBytes(p, 0, b.buf[b.off:b.off+n]);
	b.off += n;
	return n, err
}

// ReadByte reads and returns the next byte from the buffer.
// If no byte is available, it returns error os.EOF.
func (b *Buffer) ReadByte() (c byte, err os.Error) {
	if b.off >= len(b.buf) {
		return 0, os.EOF;
	}
	c = b.buf[b.off];
	b.off++;
	return c, nil;
}

// NewBuffer creates and initializes a new Buffer
// using buf as its initial contents.
func NewBuffer(buf []byte) *Buffer {
	return &Buffer{buf: buf};
}

// NewBufferString creates and initializes a new Buffer
// using string s as its initial contents.
func NewBufferString(s string) *Buffer {
	buf := make([]byte, len(s));
	copyString(buf, 0, s);
	return &Buffer{buf: buf};
}
<|endoftext|>


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

// +build !netgo
// +build darwin freebsd linux netbsd openbsd

package net

/*
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
*/
import "C"

import (
	"syscall"
	"unsafe"
)

func cgoLookupHost(name string) (addrs []string, err error, completed bool) {
	ip, err, completed := cgoLookupIP(name)
	for _, p := range ip {
		addrs = append(addrs, p.String())
	}
	return
}

func cgoLookupPort(net, service string) (port int, err error, completed bool) {
	var res *C.struct_addrinfo
	var hints C.struct_addrinfo

	switch net {
	case "":
		// no hints
	case "tcp", "tcp4", "tcp6":
		hints.ai_socktype = C.SOCK_STREAM
		hints.ai_protocol = C.IPPROTO_TCP
	case "udp", "udp4", "udp6":
		hints.ai_socktype = C.SOCK_DGRAM
		hints.ai_protocol = C.IPPROTO_UDP
	default:
		return 0, UnknownNetworkError(net), true
	}
	if len(net) >= 4 {
		switch net[3] {
		case '4':
			hints.ai_family = C.AF_INET
		case '6':
			hints.ai_family = C.AF_INET6
		}
	}

	s := C.CString(service)
	defer C.free(unsafe.Pointer(s))
	if C.getaddrinfo(nil, s, &hints, &res) == 0 {
		defer C.freeaddrinfo(res)
		for r := res; r != nil; r = r.ai_next {
			switch r.ai_family {
			default:
				continue
			case C.AF_INET:
				sa := (*syscall.RawSockaddrInet4)(unsafe.Pointer(r.ai_addr))
				p := (*[2]byte)(unsafe.Pointer(&sa.Port))
				return int(p[0])<<8 | int(p[1]), nil, true
			case C.AF_INET6:
				sa := (*syscall.RawSockaddrInet6)(unsafe.Pointer(r.ai_addr))
				p := (*[2]byte)(unsafe.Pointer(&sa.Port))
				return int(p[0])<<8 | int(p[1]), nil, true
			}
		}
	}
	return 0, &AddrError{"unknown port", net + "/" + service}, true
}

func cgoLookupIPCNAME(name string) (addrs []IP, cname string, err error, completed bool) {
	var res *C.struct_addrinfo
	var hints C.struct_addrinfo

	hints.ai_flags = cgoAddrInfoFlags()

	h := C.CString(name)
	defer C.free(unsafe.Pointer(h))
	gerrno, err := C.getaddrinfo(h, nil, &hints, &res)
	if gerrno != 0 {
		var str string
		if gerrno == C.EAI_NONAME {
			str = noSuchHost
		} else if gerrno == C.EAI_SYSTEM {
			str = err.Error()
		} else {
			str = C.GoString(C.gai_strerror(gerrno))
		}
		return nil, "", &DNSError{Err: str, Name: name}, true
	}
	defer C.freeaddrinfo(res)
	if res != nil {
		cname = C.GoString(res.ai_canonname)
		if cname == "" {
			cname = name
		}
		if len(cname) > 0 && cname[len(cname)-1] != '.' {
			cname += "."
		}
	}
	for r := res; r != nil; r = r.ai_next {
		// Everything comes back twice, once for UDP and once for TCP.
		if r.ai_socktype != C.SOCK_STREAM {
			continue
		}
		switch r.ai_family {
		default:
			continue
		case C.AF_INET:
			sa := (*syscall.RawSockaddrInet4)(unsafe.Pointer(r.ai_addr))
			addrs = append(addrs, copyIP(sa.Addr[:]))
		case C.AF_INET6:
			sa := (*syscall.RawSockaddrInet6)(unsafe.Pointer(r.ai_addr))
			addrs = append(addrs, copyIP(sa.Addr[:]))
		}
	}
	return addrs, cname, nil, true
}

func cgoLookupIP(name string) (addrs []IP, err error, completed bool) {
	addrs, _, err, completed = cgoLookupIPCNAME(name)
	return
}

func cgoLookupCNAME(name string) (cname string, err error, completed bool) {
	_, cname, err, completed = cgoLookupIPCNAME(name)
	return
}

func copyIP(x IP) IP {
	y := make(IP, len(x))
	copy(y, x)
	return y
}
<commit_msg>net: give C.getaddrinfo a hint that we only want SOCK_STREAM answers<commit_after>// Copyright 2011 The Go Authors.  All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// +build !netgo
// +build darwin freebsd linux netbsd openbsd

package net

/*
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
*/
import "C"

import (
	"syscall"
	"unsafe"
)

func cgoLookupHost(name string) (addrs []string, err error, completed bool) {
	ip, err, completed := cgoLookupIP(name)
	for _, p := range ip {
		addrs = append(addrs, p.String())
	}
	return
}

func cgoLookupPort(net, service string) (port int, err error, completed bool) {
	var res *C.struct_addrinfo
	var hints C.struct_addrinfo

	switch net {
	case "":
		// no hints
	case "tcp", "tcp4", "tcp6":
		hints.ai_socktype = C.SOCK_STREAM
		hints.ai_protocol = C.IPPROTO_TCP
	case "udp", "udp4", "udp6":
		hints.ai_socktype = C.SOCK_DGRAM
		hints.ai_protocol = C.IPPROTO_UDP
	default:
		return 0, UnknownNetworkError(net), true
	}
	if len(net) >= 4 {
		switch net[3] {
		case '4':
			hints.ai_family = C.AF_INET
		case '6':
			hints.ai_family = C.AF_INET6
		}
	}

	s := C.CString(service)
	defer C.free(unsafe.Pointer(s))
	if C.getaddrinfo(nil, s, &hints, &res) == 0 {
		defer C.freeaddrinfo(res)
		for r := res; r != nil; r = r.ai_next {
			switch r.ai_family {
			default:
				continue
			case C.AF_INET:
				sa := (*syscall.RawSockaddrInet4)(unsafe.Pointer(r.ai_addr))
				p := (*[2]byte)(unsafe.Pointer(&sa.Port))
				return int(p[0])<<8 | int(p[1]), nil, true
			case C.AF_INET6:
				sa := (*syscall.RawSockaddrInet6)(unsafe.Pointer(r.ai_addr))
				p := (*[2]byte)(unsafe.Pointer(&sa.Port))
				return int(p[0])<<8 | int(p[1]), nil, true
			}
		}
	}
	return 0, &AddrError{"unknown port", net + "/" + service}, true
}

func cgoLookupIPCNAME(name string) (addrs []IP, cname string, err error, completed bool) {
	var res *C.struct_addrinfo
	var hints C.struct_addrinfo

	hints.ai_flags = cgoAddrInfoFlags()
	hints.ai_socktype = C.SOCK_STREAM

	h := C.CString(name)
	defer C.free(unsafe.Pointer(h))
	gerrno, err := C.getaddrinfo(h, nil, &hints, &res)
	if gerrno != 0 {
		var str string
		if gerrno == C.EAI_NONAME {
			str = noSuchHost
		} else if gerrno == C.EAI_SYSTEM {
			str = err.Error()
		} else {
			str = C.GoString(C.gai_strerror(gerrno))
		}
		return nil, "", &DNSError{Err: str, Name: name}, true
	}
	defer C.freeaddrinfo(res)
	if res != nil {
		cname = C.GoString(res.ai_canonname)
		if cname == "" {
			cname = name
		}
		if len(cname) > 0 && cname[len(cname)-1] != '.' {
			cname += "."
		}
	}
	for r := res; r != nil; r = r.ai_next {
		// We only asked for SOCK_STREAM, but check anyhow.
		if r.ai_socktype != C.SOCK_STREAM {
			continue
		}
		switch r.ai_family {
		default:
			continue
		case C.AF_INET:
			sa := (*syscall.RawSockaddrInet4)(unsafe.Pointer(r.ai_addr))
			addrs = append(addrs, copyIP(sa.Addr[:]))
		case C.AF_INET6:
			sa := (*syscall.RawSockaddrInet6)(unsafe.Pointer(r.ai_addr))
			addrs = append(addrs, copyIP(sa.Addr[:]))
		}
	}
	return addrs, cname, nil, true
}

func cgoLookupIP(name string) (addrs []IP, err error, completed bool) {
	addrs, _, err, completed = cgoLookupIPCNAME(name)
	return
}

func cgoLookupCNAME(name string) (cname string, err error, completed bool) {
	_, cname, err, completed = cgoLookupIPCNAME(name)
	return
}

func copyIP(x IP) IP {
	y := make(IP, len(x))
	copy(y, x)
	return y
}
<|endoftext|>


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

// Waiting for FDs via epoll(7).

package net

import (
	"os"
	"syscall"
)

const (
	readFlags  = syscall.EPOLLIN | syscall.EPOLLRDHUP
	writeFlags = syscall.EPOLLOUT
)

type pollster struct {
	epfd int

	// Events we're already waiting for
	// Must hold pollServer lock
	events map[int]uint32
}

func newpollster() (p *pollster, err os.Error) {
	p = new(pollster)
	var e int

	// The arg to epoll_create is a hint to the kernel
	// about the number of FDs we will care about.
	// We don't know.
	if p.epfd, e = syscall.EpollCreate(16); e != 0 {
		return nil, os.NewSyscallError("epoll_create", e)
	}
	p.events = make(map[int]uint32)
	return p, nil
}

func (p *pollster) AddFD(fd int, mode int, repeat bool) os.Error {
	// pollServer is locked.

	var ev syscall.EpollEvent
	var already bool
	ev.Fd = int32(fd)
	ev.Events, already = p.events[fd]
	if !repeat {
		ev.Events |= syscall.EPOLLONESHOT
	}
	if mode == 'r' {
		ev.Events |= readFlags
	} else {
		ev.Events |= writeFlags
	}

	var op int
	if already {
		op = syscall.EPOLL_CTL_MOD
	} else {
		op = syscall.EPOLL_CTL_ADD
	}
	if e := syscall.EpollCtl(p.epfd, op, fd, &ev); e != 0 {
		return os.NewSyscallError("epoll_ctl", e)
	}
	p.events[fd] = ev.Events
	return nil
}

func (p *pollster) StopWaiting(fd int, bits uint) {
	// pollServer is locked.

	events, already := p.events[fd]
	if !already {
		print("Epoll unexpected fd=", fd, "\n")
		return
	}

	// If syscall.EPOLLONESHOT is not set, the wait
	// is a repeating wait, so don't change it.
	if events&syscall.EPOLLONESHOT == 0 {
		return
	}

	// Disable the given bits.
	// If we're still waiting for other events, modify the fd
	// event in the kernel.  Otherwise, delete it.
	events &= ^uint32(bits)
	if int32(events)&^syscall.EPOLLONESHOT != 0 {
		var ev syscall.EpollEvent
		ev.Fd = int32(fd)
		ev.Events = events
		if e := syscall.EpollCtl(p.epfd, syscall.EPOLL_CTL_MOD, fd, &ev); e != 0 {
			print("Epoll modify fd=", fd, ": ", os.Errno(e).String(), "\n")
		}
		p.events[fd] = events
	} else {
		if e := syscall.EpollCtl(p.epfd, syscall.EPOLL_CTL_DEL, fd, nil); e != 0 {
			print("Epoll delete fd=", fd, ": ", os.Errno(e).String(), "\n")
		}
		p.events[fd] = 0, false
	}
}

func (p *pollster) DelFD(fd int, mode int) {
	// pollServer is locked.

	if mode == 'r' {
		p.StopWaiting(fd, readFlags)
	} else {
		p.StopWaiting(fd, writeFlags)
	}
}

func (p *pollster) WaitFD(s *pollServer, nsec int64) (fd int, mode int, err os.Error) {
	s.Unlock()

	// Get an event.
	var evarray [1]syscall.EpollEvent
	ev := &evarray[0]
	var msec int = -1
	if nsec > 0 {
		msec = int((nsec + 1e6 - 1) / 1e6)
	}
	n, e := syscall.EpollWait(p.epfd, evarray[0:], msec)
	for e == syscall.EAGAIN || e == syscall.EINTR {
		n, e = syscall.EpollWait(p.epfd, evarray[0:], msec)
	}

	s.Lock()

	if e != 0 {
		return -1, 0, os.NewSyscallError("epoll_wait", e)
	}
	if n == 0 {
		return -1, 0, nil
	}
	fd = int(ev.Fd)

	if ev.Events&writeFlags != 0 {
		p.StopWaiting(fd, writeFlags)
		return fd, 'w', nil
	}
	if ev.Events&readFlags != 0 {
		p.StopWaiting(fd, readFlags)
		return fd, 'r', nil
	}

	// Other events are error conditions - wake whoever is waiting.
	events, _ := p.events[fd]
	if events&writeFlags != 0 {
		p.StopWaiting(fd, writeFlags)
		return fd, 'w', nil
	}
	p.StopWaiting(fd, readFlags)
	return fd, 'r', nil
}

func (p *pollster) Close() os.Error {
	return os.NewSyscallError("close", syscall.Close(p.epfd))
}
<commit_msg>net: Use preallocated buffer for epoll.<commit_after>// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// Waiting for FDs via epoll(7).

package net

import (
	"os"
	"syscall"
)

const (
	readFlags  = syscall.EPOLLIN | syscall.EPOLLRDHUP
	writeFlags = syscall.EPOLLOUT
)

type pollster struct {
	epfd int

	// Events we're already waiting for
	// Must hold pollServer lock
	events map[int]uint32

	// An event buffer for EpollWait.
	// Used without a lock, may only be used by WaitFD.
	waitEventBuf [10]syscall.EpollEvent
	waitEvents   []syscall.EpollEvent

	// An event buffer for EpollCtl, to avoid a malloc.
	// Must hold pollServer lock.
	ctlEvent syscall.EpollEvent
}

func newpollster() (p *pollster, err os.Error) {
	p = new(pollster)
	var e int

	// The arg to epoll_create is a hint to the kernel
	// about the number of FDs we will care about.
	// We don't know, and since 2.6.8 the kernel ignores it anyhow.
	if p.epfd, e = syscall.EpollCreate(16); e != 0 {
		return nil, os.NewSyscallError("epoll_create", e)
	}
	p.events = make(map[int]uint32)
	return p, nil
}

func (p *pollster) AddFD(fd int, mode int, repeat bool) os.Error {
	// pollServer is locked.

	var already bool
	p.ctlEvent.Fd = int32(fd)
	p.ctlEvent.Events, already = p.events[fd]
	if !repeat {
		p.ctlEvent.Events |= syscall.EPOLLONESHOT
	}
	if mode == 'r' {
		p.ctlEvent.Events |= readFlags
	} else {
		p.ctlEvent.Events |= writeFlags
	}

	var op int
	if already {
		op = syscall.EPOLL_CTL_MOD
	} else {
		op = syscall.EPOLL_CTL_ADD
	}
	if e := syscall.EpollCtl(p.epfd, op, fd, &p.ctlEvent); e != 0 {
		return os.NewSyscallError("epoll_ctl", e)
	}
	p.events[fd] = p.ctlEvent.Events
	return nil
}

func (p *pollster) StopWaiting(fd int, bits uint) {
	// pollServer is locked.

	events, already := p.events[fd]
	if !already {
		print("Epoll unexpected fd=", fd, "\n")
		return
	}

	// If syscall.EPOLLONESHOT is not set, the wait
	// is a repeating wait, so don't change it.
	if events&syscall.EPOLLONESHOT == 0 {
		return
	}

	// Disable the given bits.
	// If we're still waiting for other events, modify the fd
	// event in the kernel.  Otherwise, delete it.
	events &= ^uint32(bits)
	if int32(events)&^syscall.EPOLLONESHOT != 0 {
		p.ctlEvent.Fd = int32(fd)
		p.ctlEvent.Events = events
		if e := syscall.EpollCtl(p.epfd, syscall.EPOLL_CTL_MOD, fd, &p.ctlEvent); e != 0 {
			print("Epoll modify fd=", fd, ": ", os.Errno(e).String(), "\n")
		}
		p.events[fd] = events
	} else {
		if e := syscall.EpollCtl(p.epfd, syscall.EPOLL_CTL_DEL, fd, nil); e != 0 {
			print("Epoll delete fd=", fd, ": ", os.Errno(e).String(), "\n")
		}
		p.events[fd] = 0, false
	}
}

func (p *pollster) DelFD(fd int, mode int) {
	// pollServer is locked.

	if mode == 'r' {
		p.StopWaiting(fd, readFlags)
	} else {
		p.StopWaiting(fd, writeFlags)
	}
}

func (p *pollster) WaitFD(s *pollServer, nsec int64) (fd int, mode int, err os.Error) {
	for len(p.waitEvents) == 0 {
		var msec int = -1
		if nsec > 0 {
			msec = int((nsec + 1e6 - 1) / 1e6)
		}

		s.Unlock()
		n, e := syscall.EpollWait(p.epfd, p.waitEventBuf[0:], msec)
		s.Lock()

		if e != 0 {
			if e == syscall.EAGAIN || e == syscall.EINTR {
				continue
			}
			return -1, 0, os.NewSyscallError("epoll_wait", e)
		}
		if n == 0 {
			return -1, 0, nil
		}
		p.waitEvents = p.waitEventBuf[0:n]
	}

	ev := &p.waitEvents[0]
	p.waitEvents = p.waitEvents[1:]

	fd = int(ev.Fd)

	if ev.Events&writeFlags != 0 {
		p.StopWaiting(fd, writeFlags)
		return fd, 'w', nil
	}
	if ev.Events&readFlags != 0 {
		p.StopWaiting(fd, readFlags)
		return fd, 'r', nil
	}

	// Other events are error conditions - wake whoever is waiting.
	events, _ := p.events[fd]
	if events&writeFlags != 0 {
		p.StopWaiting(fd, writeFlags)
		return fd, 'w', nil
	}
	p.StopWaiting(fd, readFlags)
	return fd, 'r', nil
}

func (p *pollster) Close() os.Error {
	return os.NewSyscallError("close", syscall.Close(p.epfd))
}
<|endoftext|>


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

package net

import (
	"io"
	"io/ioutil"
	"os"
	"runtime"
	"testing"
	"time"
)

func TestShutdown(t *testing.T) {
	if runtime.GOOS == "plan9" {
		t.Logf("skipping test on %q", runtime.GOOS)
		return
	}
	ln, err := Listen("tcp", "127.0.0.1:0")
	if err != nil {
		if ln, err = Listen("tcp6", "[::1]:0"); err != nil {
			t.Fatalf("ListenTCP on :0: %v", err)
		}
	}

	go func() {
		c, err := ln.Accept()
		if err != nil {
			t.Fatalf("Accept: %v", err)
		}
		var buf [10]byte
		n, err := c.Read(buf[:])
		if n != 0 || err != io.EOF {
			t.Fatalf("server Read = %d, %v; want 0, io.EOF", n, err)
		}
		c.Write([]byte("response"))
		c.Close()
	}()

	c, err := Dial("tcp", ln.Addr().String())
	if err != nil {
		t.Fatalf("Dial: %v", err)
	}
	defer c.Close()

	err = c.(*TCPConn).CloseWrite()
	if err != nil {
		t.Fatalf("CloseWrite: %v", err)
	}
	var buf [10]byte
	n, err := c.Read(buf[:])
	if err != nil {
		t.Fatalf("client Read: %d, %v", n, err)
	}
	got := string(buf[:n])
	if got != "response" {
		t.Errorf("read = %q, want \"response\"", got)
	}
}

func TestShutdownUnix(t *testing.T) {
	if runtime.GOOS == "plan9" {
		t.Logf("skipping test on %q", runtime.GOOS)
		return
	}
	f, err := ioutil.TempFile("", "go_net_unixtest")
	if err != nil {
		t.Fatalf("TempFile: %s", err)
	}
	f.Close()
	tmpname := f.Name()
	os.Remove(tmpname)
	ln, err := Listen("unix", tmpname)
	if err != nil {
		t.Fatalf("ListenUnix on %s: %s", tmpname, err)
	}
	defer os.Remove(tmpname)

	go func() {
		c, err := ln.Accept()
		if err != nil {
			t.Fatalf("Accept: %v", err)
		}
		var buf [10]byte
		n, err := c.Read(buf[:])
		if n != 0 || err != io.EOF {
			t.Fatalf("server Read = %d, %v; want 0, io.EOF", n, err)
		}
		c.Write([]byte("response"))
		c.Close()
	}()

	c, err := Dial("unix", tmpname)
	if err != nil {
		t.Fatalf("Dial: %v", err)
	}
	defer c.Close()

	err = c.(*UnixConn).CloseWrite()
	if err != nil {
		t.Fatalf("CloseWrite: %v", err)
	}
	var buf [10]byte
	n, err := c.Read(buf[:])
	if err != nil {
		t.Fatalf("client Read: %d, %v", n, err)
	}
	got := string(buf[:n])
	if got != "response" {
		t.Errorf("read = %q, want \"response\"", got)
	}
}

func TestTCPListenClose(t *testing.T) {
	ln, err := Listen("tcp", "127.0.0.1:0")
	if err != nil {
		t.Fatalf("Listen failed: %v", err)
	}

	done := make(chan bool, 1)
	go func() {
		time.Sleep(100 * time.Millisecond)
		ln.Close()
	}()
	go func() {
		c, err := ln.Accept()
		if err == nil {
			c.Close()
			t.Error("Accept succeeded")
		} else {
			t.Logf("Accept timeout error: %s (any error is fine)", err)
		}
		done <- true
	}()
	select {
	case <-done:
	case <-time.After(2 * time.Second):
		t.Fatal("timeout waiting for TCP close")
	}
}

func TestUDPListenClose(t *testing.T) {
	ln, err := ListenPacket("udp", "127.0.0.1:0")
	if err != nil {
		t.Fatalf("Listen failed: %v", err)
	}

	buf := make([]byte, 1000)
	done := make(chan bool, 1)
	go func() {
		time.Sleep(100 * time.Millisecond)
		ln.Close()
	}()
	go func() {
		_, _, err = ln.ReadFrom(buf)
		if err == nil {
			t.Error("ReadFrom succeeded")
		} else {
			t.Logf("ReadFrom timeout error: %s (any error is fine)", err)
		}
		done <- true
	}()
	select {
	case <-done:
	case <-time.After(2 * time.Second):
		t.Fatal("timeout waiting for UDP close")
	}
}
<commit_msg>net: skip UnixShutdown test on windows<commit_after>// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package net

import (
	"io"
	"io/ioutil"
	"os"
	"runtime"
	"testing"
	"time"
)

func TestShutdown(t *testing.T) {
	if runtime.GOOS == "plan9" {
		t.Logf("skipping test on %q", runtime.GOOS)
		return
	}
	ln, err := Listen("tcp", "127.0.0.1:0")
	if err != nil {
		if ln, err = Listen("tcp6", "[::1]:0"); err != nil {
			t.Fatalf("ListenTCP on :0: %v", err)
		}
	}

	go func() {
		c, err := ln.Accept()
		if err != nil {
			t.Fatalf("Accept: %v", err)
		}
		var buf [10]byte
		n, err := c.Read(buf[:])
		if n != 0 || err != io.EOF {
			t.Fatalf("server Read = %d, %v; want 0, io.EOF", n, err)
		}
		c.Write([]byte("response"))
		c.Close()
	}()

	c, err := Dial("tcp", ln.Addr().String())
	if err != nil {
		t.Fatalf("Dial: %v", err)
	}
	defer c.Close()

	err = c.(*TCPConn).CloseWrite()
	if err != nil {
		t.Fatalf("CloseWrite: %v", err)
	}
	var buf [10]byte
	n, err := c.Read(buf[:])
	if err != nil {
		t.Fatalf("client Read: %d, %v", n, err)
	}
	got := string(buf[:n])
	if got != "response" {
		t.Errorf("read = %q, want \"response\"", got)
	}
}

func TestShutdownUnix(t *testing.T) {
	switch runtime.GOOS {
	case "windows", "plan9":
		t.Logf("skipping test on %q", runtime.GOOS)
		return
	}
	f, err := ioutil.TempFile("", "go_net_unixtest")
	if err != nil {
		t.Fatalf("TempFile: %s", err)
	}
	f.Close()
	tmpname := f.Name()
	os.Remove(tmpname)
	ln, err := Listen("unix", tmpname)
	if err != nil {
		t.Fatalf("ListenUnix on %s: %s", tmpname, err)
	}
	defer os.Remove(tmpname)

	go func() {
		c, err := ln.Accept()
		if err != nil {
			t.Fatalf("Accept: %v", err)
		}
		var buf [10]byte
		n, err := c.Read(buf[:])
		if n != 0 || err != io.EOF {
			t.Fatalf("server Read = %d, %v; want 0, io.EOF", n, err)
		}
		c.Write([]byte("response"))
		c.Close()
	}()

	c, err := Dial("unix", tmpname)
	if err != nil {
		t.Fatalf("Dial: %v", err)
	}
	defer c.Close()

	err = c.(*UnixConn).CloseWrite()
	if err != nil {
		t.Fatalf("CloseWrite: %v", err)
	}
	var buf [10]byte
	n, err := c.Read(buf[:])
	if err != nil {
		t.Fatalf("client Read: %d, %v", n, err)
	}
	got := string(buf[:n])
	if got != "response" {
		t.Errorf("read = %q, want \"response\"", got)
	}
}

func TestTCPListenClose(t *testing.T) {
	ln, err := Listen("tcp", "127.0.0.1:0")
	if err != nil {
		t.Fatalf("Listen failed: %v", err)
	}

	done := make(chan bool, 1)
	go func() {
		time.Sleep(100 * time.Millisecond)
		ln.Close()
	}()
	go func() {
		c, err := ln.Accept()
		if err == nil {
			c.Close()
			t.Error("Accept succeeded")
		} else {
			t.Logf("Accept timeout error: %s (any error is fine)", err)
		}
		done <- true
	}()
	select {
	case <-done:
	case <-time.After(2 * time.Second):
		t.Fatal("timeout waiting for TCP close")
	}
}

func TestUDPListenClose(t *testing.T) {
	ln, err := ListenPacket("udp", "127.0.0.1:0")
	if err != nil {
		t.Fatalf("Listen failed: %v", err)
	}

	buf := make([]byte, 1000)
	done := make(chan bool, 1)
	go func() {
		time.Sleep(100 * time.Millisecond)
		ln.Close()
	}()
	go func() {
		_, _, err = ln.ReadFrom(buf)
		if err == nil {
			t.Error("ReadFrom succeeded")
		} else {
			t.Logf("ReadFrom timeout error: %s (any error is fine)", err)
		}
		done <- true
	}()
	select {
	case <-done:
	case <-time.After(2 * time.Second):
		t.Fatal("timeout waiting for UDP close")
	}
}
<|endoftext|>