<commit_before>package commands

import (
	"bufio"
	"bytes"
	"encoding/json"
	"fmt"
	"net/http"
	"os"
	"os/exec"
	"os/signal"
	"path/filepath"
	"strconv"
	"syscall"
	"time"

	"github.com/concourse/atc"
	"github.com/concourse/fly/config"
	"github.com/concourse/fly/eventstream"
	"github.com/tedsuo/rata"
	"github.com/vito/go-sse/sse"
)

type ExecuteCommand struct {
	TaskConfig     PathFlag        `short:"c" long:"config" required:"true" description:"The task config to execute"`
	Privileged     bool            `short:"p" long:"privileged"             description:"Run the task with full privileges"`
	ExcludeIgnored bool            `short:"x" long:"exclude-ignored"        description:"Skip uploading .gitignored paths"`
	Inputs         []InputPairFlag `short:"i" long:"input"                  description:"An input to provide to the task (can be specified multiple times)"`
	InputsFrom     JobFlag         `short:"j" long:"inputs-from"            description:"A job to base the inputs on"`
}

var executeCommand ExecuteCommand

func init() {
	execute, err := Parser.AddCommand(
		"execute",
		"Execute a one-off build using local bits",
		"",
		&executeCommand,
	)
	if err != nil {
		panic(err)
	}

	execute.Aliases = []string{"e"}
}

func (command *ExecuteCommand) Execute(args []string) error {
	target := returnTarget(globalOptions.Target)
	insecure := globalOptions.Insecure
	taskConfigFile := command.TaskConfig
	excludeIgnored := command.ExcludeIgnored

	atcRequester := newAtcRequester(target, insecure)

	taskConfig := config.LoadTaskConfig(string(taskConfigFile), args)

	inputs, err := determineInputs(
		atcRequester,
		taskConfig.Inputs,
		command.Inputs,
		command.InputsFrom,
	)
	if err != nil {
		return err
	}

	build, err := createBuild(
		atcRequester,
		command.Privileged,
		inputs,
		taskConfig,
	)
	if err != nil {
		return err
	}

	fmt.Println("executing build", build.ID)

	terminate := make(chan os.Signal, 1)

	go abortOnSignal(atcRequester, terminate, build)

	signal.Notify(terminate, syscall.SIGINT, syscall.SIGTERM)

	eventSource, err := sse.Connect(atcRequester.httpClient, time.Second, func() *http.Request {
		logOutput, _ := atcRequester.CreateRequest(
			atc.BuildEvents,
			rata.Params{"build_id": strconv.Itoa(build.ID)},
			nil,
		)

		return logOutput
	})
	if err != nil {
		return fmt.Errorf("failed to connect to event stream: %s", err)
	}

	go func() {
		for _, i := range inputs {
			if i.Path != "" {
				upload(i, excludeIgnored, atcRequester)
			}
		}
	}()

	exitCode, err := eventstream.RenderStream(eventSource)
	if err != nil {
		return fmt.Errorf("failed to render stream: %s", err)
	}

	eventSource.Close()

	os.Exit(exitCode)

	return nil
}

type Input struct {
	Name string

	Path string
	Pipe atc.Pipe

	BuildInput atc.BuildInput
}

func createPipe(atcRequester *atcRequester) (atc.Pipe, error) {
	cPipe, err := atcRequester.CreateRequest(atc.CreatePipe, nil, nil)
	if err != nil {
		return atc.Pipe{}, err
	}

	response, err := atcRequester.httpClient.Do(cPipe)
	if err != nil {
		return atc.Pipe{}, fmt.Errorf("failed to create pipe: %s", err)
	}

	defer response.Body.Close()

	if response.StatusCode != http.StatusCreated {
		return atc.Pipe{}, badResponseError("creating pipe", response)
	}

	var pipe atc.Pipe
	err = json.NewDecoder(response.Body).Decode(&pipe)
	if err != nil {
		return atc.Pipe{}, fmt.Errorf("malformed pipe response: %s", err)
	}

	return pipe, nil
}

func determineInputs(
	atcRequester *atcRequester,
	taskInputs []atc.TaskInputConfig,
	inputMappings []InputPairFlag,
	inputsFrom JobFlag,
) ([]Input, error) {
	if len(inputMappings) == 0 && inputsFrom.PipelineName == "" && inputsFrom.JobName == "" {
		wd, err := os.Getwd()
		if err != nil {
			return nil, err
		}

		inputMappings = append(inputMappings, InputPairFlag{
			Name: filepath.Base(wd),
			Path: wd,
		})
	}

	inputsFromLocal, err := generateLocalInputs(atcRequester, inputMappings)
	if err != nil {
		return nil, err
	}

	inputsFromJob, err := fetchInputsFromJob(atcRequester, inputsFrom)
	if err != nil {
		return nil, err
	}

	inputs := []Input{}
	for _, taskInput := range taskInputs {
		input, found := inputsFromLocal[taskInput.Name]
		if !found {
			input, found = inputsFromJob[taskInput.Name]
			if !found {
				continue
			}
		}

		inputs = append(inputs, input)
	}

	return inputs, nil
}

func generateLocalInputs(
	atcRequester *atcRequester,
	inputMappings []InputPairFlag,
) (map[string]Input, error) {
	kvMap := map[string]Input{}

	for _, i := range inputMappings {
		inputName := i.Name
		absPath := i.Path

		pipe, err := createPipe(atcRequester)
		if err != nil {
			return nil, err
		}

		kvMap[inputName] = Input{
			Name: inputName,
			Path: absPath,
			Pipe: pipe,
		}
	}

	return kvMap, nil
}

func fetchInputsFromJob(
	atcRequester *atcRequester,
	inputsFrom JobFlag,
) (map[string]Input, error) {
	kvMap := map[string]Input{}
	if inputsFrom.PipelineName == "" && inputsFrom.JobName == "" {
		return kvMap, nil
	}

	listJobInputsRequest, err := atcRequester.CreateRequest(
		atc.ListJobInputs,
		rata.Params{
			"pipeline_name": inputsFrom.PipelineName,
			"job_name":      inputsFrom.JobName,
		},
		nil,
	)
	if err != nil {
		return nil, err
	}

	response, err := atcRequester.httpClient.Do(listJobInputsRequest)
	if err != nil {
		return nil, fmt.Errorf("failed to fetch job inputs: %s", err)
	}

	defer response.Body.Close()

	if response.StatusCode != http.StatusOK {
		return nil, badResponseError("getting job inputs", response)
	}

	var buildInputs []atc.BuildInput
	err = json.NewDecoder(response.Body).Decode(&buildInputs)
	if err != nil {
		return nil, fmt.Errorf("malformed job inputs response: %s", err)
	}

	for _, buildInput := range buildInputs {
		kvMap[buildInput.Name] = Input{
			Name:       buildInput.Name,
			BuildInput: buildInput,
		}
	}

	return kvMap, nil
}

func createBuild(
	atcRequester *atcRequester,
	privileged bool,
	inputs []Input,
	config atc.TaskConfig,
) (atc.Build, error) {
	if err := config.Validate(); err != nil {
		return atc.Build{}, err
	}

	buffer := &bytes.Buffer{}

	buildInputs := atc.AggregatePlan{}
	for i, input := range inputs {
		var getPlan atc.GetPlan
		if input.Path != "" {
			readPipe, err := atcRequester.CreateRequest(
				atc.ReadPipe,
				rata.Params{"pipe_id": input.Pipe.ID},
				nil,
			)
			if err != nil {
				return atc.Build{}, err
			}

			getPlan = atc.GetPlan{
				Name: input.Name,
				Type: "archive",
				Source: atc.Source{
					"uri": readPipe.URL.String(),
				},
			}
		} else {
			getPlan = atc.GetPlan{
				Name:    input.Name,
				Type:    input.BuildInput.Type,
				Source:  input.BuildInput.Source,
				Version: input.BuildInput.Version,
				Params:  input.BuildInput.Params,
				Tags:    input.BuildInput.Tags,
			}
		}

		buildInputs = append(buildInputs, atc.Plan{
			Location: &atc.Location{
				// offset by 2 because aggregate gets parallelgroup ID 1
				ID:            uint(i) + 2,
				ParentID:      0,
				ParallelGroup: 1,
			},
			Get: &getPlan,
		})
	}

	plan := atc.Plan{
		OnSuccess: &atc.OnSuccessPlan{
			Step: atc.Plan{
				Aggregate: &buildInputs,
			},
			Next: atc.Plan{
				Location: &atc.Location{
					// offset by 1 because aggregate gets parallelgroup ID 1
					ID:       uint(len(inputs)) + 2,
					ParentID: 0,
				},
				Task: &atc.TaskPlan{
					Name:       "one-off",
					Privileged: privileged,
					Config:     &config,
				},
			},
		},
	}

	err := json.NewEncoder(buffer).Encode(plan)
	if err != nil {
		return atc.Build{}, err
	}

	createBuild, err := atcRequester.CreateRequest(atc.CreateBuild, nil, buffer)
	if err != nil {
		return atc.Build{}, err
	}

	createBuild.Header.Set("Content-Type", "application/json")

	response, err := atcRequester.httpClient.Do(createBuild)
	if err != nil {
		return atc.Build{}, fmt.Errorf("failed to create build: %s", err)
	}

	defer response.Body.Close()

	if response.StatusCode != http.StatusCreated {
		return atc.Build{}, badResponseError("creating build", response)
	}

	var build atc.Build
	err = json.NewDecoder(response.Body).Decode(&build)
	if err != nil {
		return atc.Build{}, fmt.Errorf("malformed build response: %s", err)
	}

	return build, nil
}

func abortOnSignal(
	atcRequester *atcRequester,
	terminate <-chan os.Signal,
	build atc.Build,
) {
	<-terminate

	fmt.Fprintf(os.Stderr, "\naborting...\n")

	abortReq, err := atcRequester.CreateRequest(
		atc.AbortBuild,
		rata.Params{"build_id": strconv.Itoa(build.ID)},
		nil,
	)
	if err != nil {
		panic(err)
	}

	resp, err := atcRequester.httpClient.Do(abortReq)
	if err != nil {
		fmt.Fprintln(os.Stderr, "failed to abort:", err)
		return
	}

	resp.Body.Close()

	// if told to terminate again, exit immediately
	<-terminate
	fmt.Fprintln(os.Stderr, "exiting immediately")
	os.Exit(2)
}

func upload(input Input, excludeIgnored bool, atcRequester *atcRequester) {
	path := input.Path
	pipe := input.Pipe

	var files []string
	var err error

	if excludeIgnored {
		files, err = getGitFiles(path)
		if err != nil {
			fmt.Fprintln(os.Stderr, "could not determine ignored files:", err)
			return
		}
	} else {
		files = []string{"."}
	}

	archive, err := tarStreamFrom(path, files)
	if err != nil {
		fmt.Fprintln(os.Stderr, "could create tar stream:", err)
		return
	}

	defer archive.Close()

	uploadBits, err := atcRequester.CreateRequest(
		atc.WritePipe,
		rata.Params{"pipe_id": pipe.ID},
		archive,
	)
	if err != nil {
		panic(err)
	}

	response, err := atcRequester.httpClient.Do(uploadBits)
	if err != nil {
		fmt.Fprintln(os.Stderr, "upload request failed:", err)
	}

	defer response.Body.Close()

	if response.StatusCode != http.StatusOK {
		fmt.Fprintln(os.Stderr, badResponseError("uploading bits", response))
	}
}

func getGitFiles(dir string) ([]string, error) {
	tracked, err := gitLS(dir)
	if err != nil {
		return nil, err
	}

	untracked, err := gitLS(dir, "--others", "--exclude-standard")
	if err != nil {
		return nil, err
	}

	return append(tracked, untracked...), nil
}

func gitLS(dir string, flags ...string) ([]string, error) {
	files := []string{}

	gitLS := exec.Command("git", append([]string{"ls-files", "-z"}, flags...)...)
	gitLS.Dir = dir

	gitOut, err := gitLS.StdoutPipe()
	if err != nil {
		return nil, err
	}

	outScan := bufio.NewScanner(gitOut)
	outScan.Split(scanNull)

	err = gitLS.Start()
	if err != nil {
		return nil, err
	}

	for outScan.Scan() {
		files = append(files, outScan.Text())
	}

	err = gitLS.Wait()
	if err != nil {
		return nil, err
	}

	return files, nil
}

func scanNull(data []byte, atEOF bool) (int, []byte, error) {
	// eof, no more data; terminate
	if atEOF && len(data) == 0 {
		return 0, nil, nil
	}

	// look for terminating null byte
	if i := bytes.IndexByte(data, 0); i >= 0 {
		return i + 1, data[0:i], nil
	}

	// no final terminator; return what's left
	if atEOF {
		return len(data), data, nil
	}

	// request more data
	return 0, nil, nil
}
<commit_msg>add help text for --inputs-from<commit_after>package commands

import (
	"bufio"
	"bytes"
	"encoding/json"
	"fmt"
	"net/http"
	"os"
	"os/exec"
	"os/signal"
	"path/filepath"
	"strconv"
	"syscall"
	"time"

	"github.com/concourse/atc"
	"github.com/concourse/fly/config"
	"github.com/concourse/fly/eventstream"
	"github.com/tedsuo/rata"
	"github.com/vito/go-sse/sse"
)

type ExecuteCommand struct {
	TaskConfig     PathFlag        `short:"c" long:"config" required:"true"                  description:"The task config to execute"`
	Privileged     bool            `short:"p" long:"privileged"                              description:"Run the task with full privileges"`
	ExcludeIgnored bool            `short:"x" long:"exclude-ignored"                         description:"Skip uploading .gitignored paths"`
	Inputs         []InputPairFlag `short:"i" long:"input"                                   description:"An input to provide to the task (can be specified multiple times)"`
	InputsFrom     JobFlag         `short:"j" long:"inputs-from" value-name:"[PIPELINE/]JOB" description:"A job to base the inputs on"`
}

var executeCommand ExecuteCommand

func init() {
	execute, err := Parser.AddCommand(
		"execute",
		"Execute a one-off build using local bits",
		"",
		&executeCommand,
	)
	if err != nil {
		panic(err)
	}

	execute.Aliases = []string{"e"}
}

func (command *ExecuteCommand) Execute(args []string) error {
	target := returnTarget(globalOptions.Target)
	insecure := globalOptions.Insecure
	taskConfigFile := command.TaskConfig
	excludeIgnored := command.ExcludeIgnored

	atcRequester := newAtcRequester(target, insecure)

	taskConfig := config.LoadTaskConfig(string(taskConfigFile), args)

	inputs, err := determineInputs(
		atcRequester,
		taskConfig.Inputs,
		command.Inputs,
		command.InputsFrom,
	)
	if err != nil {
		return err
	}

	build, err := createBuild(
		atcRequester,
		command.Privileged,
		inputs,
		taskConfig,
	)
	if err != nil {
		return err
	}

	fmt.Println("executing build", build.ID)

	terminate := make(chan os.Signal, 1)

	go abortOnSignal(atcRequester, terminate, build)

	signal.Notify(terminate, syscall.SIGINT, syscall.SIGTERM)

	eventSource, err := sse.Connect(atcRequester.httpClient, time.Second, func() *http.Request {
		logOutput, _ := atcRequester.CreateRequest(
			atc.BuildEvents,
			rata.Params{"build_id": strconv.Itoa(build.ID)},
			nil,
		)

		return logOutput
	})
	if err != nil {
		return fmt.Errorf("failed to connect to event stream: %s", err)
	}

	go func() {
		for _, i := range inputs {
			if i.Path != "" {
				upload(i, excludeIgnored, atcRequester)
			}
		}
	}()

	exitCode, err := eventstream.RenderStream(eventSource)
	if err != nil {
		return fmt.Errorf("failed to render stream: %s", err)
	}

	eventSource.Close()

	os.Exit(exitCode)

	return nil
}

type Input struct {
	Name string

	Path string
	Pipe atc.Pipe

	BuildInput atc.BuildInput
}

func createPipe(atcRequester *atcRequester) (atc.Pipe, error) {
	cPipe, err := atcRequester.CreateRequest(atc.CreatePipe, nil, nil)
	if err != nil {
		return atc.Pipe{}, err
	}

	response, err := atcRequester.httpClient.Do(cPipe)
	if err != nil {
		return atc.Pipe{}, fmt.Errorf("failed to create pipe: %s", err)
	}

	defer response.Body.Close()

	if response.StatusCode != http.StatusCreated {
		return atc.Pipe{}, badResponseError("creating pipe", response)
	}

	var pipe atc.Pipe
	err = json.NewDecoder(response.Body).Decode(&pipe)
	if err != nil {
		return atc.Pipe{}, fmt.Errorf("malformed pipe response: %s", err)
	}

	return pipe, nil
}

func determineInputs(
	atcRequester *atcRequester,
	taskInputs []atc.TaskInputConfig,
	inputMappings []InputPairFlag,
	inputsFrom JobFlag,
) ([]Input, error) {
	if len(inputMappings) == 0 && inputsFrom.PipelineName == "" && inputsFrom.JobName == "" {
		wd, err := os.Getwd()
		if err != nil {
			return nil, err
		}

		inputMappings = append(inputMappings, InputPairFlag{
			Name: filepath.Base(wd),
			Path: wd,
		})
	}

	inputsFromLocal, err := generateLocalInputs(atcRequester, inputMappings)
	if err != nil {
		return nil, err
	}

	inputsFromJob, err := fetchInputsFromJob(atcRequester, inputsFrom)
	if err != nil {
		return nil, err
	}

	inputs := []Input{}
	for _, taskInput := range taskInputs {
		input, found := inputsFromLocal[taskInput.Name]
		if !found {
			input, found = inputsFromJob[taskInput.Name]
			if !found {
				continue
			}
		}

		inputs = append(inputs, input)
	}

	return inputs, nil
}

func generateLocalInputs(
	atcRequester *atcRequester,
	inputMappings []InputPairFlag,
) (map[string]Input, error) {
	kvMap := map[string]Input{}

	for _, i := range inputMappings {
		inputName := i.Name
		absPath := i.Path

		pipe, err := createPipe(atcRequester)
		if err != nil {
			return nil, err
		}

		kvMap[inputName] = Input{
			Name: inputName,
			Path: absPath,
			Pipe: pipe,
		}
	}

	return kvMap, nil
}

func fetchInputsFromJob(
	atcRequester *atcRequester,
	inputsFrom JobFlag,
) (map[string]Input, error) {
	kvMap := map[string]Input{}
	if inputsFrom.PipelineName == "" && inputsFrom.JobName == "" {
		return kvMap, nil
	}

	listJobInputsRequest, err := atcRequester.CreateRequest(
		atc.ListJobInputs,
		rata.Params{
			"pipeline_name": inputsFrom.PipelineName,
			"job_name":      inputsFrom.JobName,
		},
		nil,
	)
	if err != nil {
		return nil, err
	}

	response, err := atcRequester.httpClient.Do(listJobInputsRequest)
	if err != nil {
		return nil, fmt.Errorf("failed to fetch job inputs: %s", err)
	}

	defer response.Body.Close()

	if response.StatusCode != http.StatusOK {
		return nil, badResponseError("getting job inputs", response)
	}

	var buildInputs []atc.BuildInput
	err = json.NewDecoder(response.Body).Decode(&buildInputs)
	if err != nil {
		return nil, fmt.Errorf("malformed job inputs response: %s", err)
	}

	for _, buildInput := range buildInputs {
		kvMap[buildInput.Name] = Input{
			Name:       buildInput.Name,
			BuildInput: buildInput,
		}
	}

	return kvMap, nil
}

func createBuild(
	atcRequester *atcRequester,
	privileged bool,
	inputs []Input,
	config atc.TaskConfig,
) (atc.Build, error) {
	if err := config.Validate(); err != nil {
		return atc.Build{}, err
	}

	buffer := &bytes.Buffer{}

	buildInputs := atc.AggregatePlan{}
	for i, input := range inputs {
		var getPlan atc.GetPlan
		if input.Path != "" {
			readPipe, err := atcRequester.CreateRequest(
				atc.ReadPipe,
				rata.Params{"pipe_id": input.Pipe.ID},
				nil,
			)
			if err != nil {
				return atc.Build{}, err
			}

			getPlan = atc.GetPlan{
				Name: input.Name,
				Type: "archive",
				Source: atc.Source{
					"uri": readPipe.URL.String(),
				},
			}
		} else {
			getPlan = atc.GetPlan{
				Name:    input.Name,
				Type:    input.BuildInput.Type,
				Source:  input.BuildInput.Source,
				Version: input.BuildInput.Version,
				Params:  input.BuildInput.Params,
				Tags:    input.BuildInput.Tags,
			}
		}

		buildInputs = append(buildInputs, atc.Plan{
			Location: &atc.Location{
				// offset by 2 because aggregate gets parallelgroup ID 1
				ID:            uint(i) + 2,
				ParentID:      0,
				ParallelGroup: 1,
			},
			Get: &getPlan,
		})
	}

	plan := atc.Plan{
		OnSuccess: &atc.OnSuccessPlan{
			Step: atc.Plan{
				Aggregate: &buildInputs,
			},
			Next: atc.Plan{
				Location: &atc.Location{
					// offset by 1 because aggregate gets parallelgroup ID 1
					ID:       uint(len(inputs)) + 2,
					ParentID: 0,
				},
				Task: &atc.TaskPlan{
					Name:       "one-off",
					Privileged: privileged,
					Config:     &config,
				},
			},
		},
	}

	err := json.NewEncoder(buffer).Encode(plan)
	if err != nil {
		return atc.Build{}, err
	}

	createBuild, err := atcRequester.CreateRequest(atc.CreateBuild, nil, buffer)
	if err != nil {
		return atc.Build{}, err
	}

	createBuild.Header.Set("Content-Type", "application/json")

	response, err := atcRequester.httpClient.Do(createBuild)
	if err != nil {
		return atc.Build{}, fmt.Errorf("failed to create build: %s", err)
	}

	defer response.Body.Close()

	if response.StatusCode != http.StatusCreated {
		return atc.Build{}, badResponseError("creating build", response)
	}

	var build atc.Build
	err = json.NewDecoder(response.Body).Decode(&build)
	if err != nil {
		return atc.Build{}, fmt.Errorf("malformed build response: %s", err)
	}

	return build, nil
}

func abortOnSignal(
	atcRequester *atcRequester,
	terminate <-chan os.Signal,
	build atc.Build,
) {
	<-terminate

	fmt.Fprintf(os.Stderr, "\naborting...\n")

	abortReq, err := atcRequester.CreateRequest(
		atc.AbortBuild,
		rata.Params{"build_id": strconv.Itoa(build.ID)},
		nil,
	)
	if err != nil {
		panic(err)
	}

	resp, err := atcRequester.httpClient.Do(abortReq)
	if err != nil {
		fmt.Fprintln(os.Stderr, "failed to abort:", err)
		return
	}

	resp.Body.Close()

	// if told to terminate again, exit immediately
	<-terminate
	fmt.Fprintln(os.Stderr, "exiting immediately")
	os.Exit(2)
}

func upload(input Input, excludeIgnored bool, atcRequester *atcRequester) {
	path := input.Path
	pipe := input.Pipe

	var files []string
	var err error

	if excludeIgnored {
		files, err = getGitFiles(path)
		if err != nil {
			fmt.Fprintln(os.Stderr, "could not determine ignored files:", err)
			return
		}
	} else {
		files = []string{"."}
	}

	archive, err := tarStreamFrom(path, files)
	if err != nil {
		fmt.Fprintln(os.Stderr, "could create tar stream:", err)
		return
	}

	defer archive.Close()

	uploadBits, err := atcRequester.CreateRequest(
		atc.WritePipe,
		rata.Params{"pipe_id": pipe.ID},
		archive,
	)
	if err != nil {
		panic(err)
	}

	response, err := atcRequester.httpClient.Do(uploadBits)
	if err != nil {
		fmt.Fprintln(os.Stderr, "upload request failed:", err)
	}

	defer response.Body.Close()

	if response.StatusCode != http.StatusOK {
		fmt.Fprintln(os.Stderr, badResponseError("uploading bits", response))
	}
}

func getGitFiles(dir string) ([]string, error) {
	tracked, err := gitLS(dir)
	if err != nil {
		return nil, err
	}

	untracked, err := gitLS(dir, "--others", "--exclude-standard")
	if err != nil {
		return nil, err
	}

	return append(tracked, untracked...), nil
}

func gitLS(dir string, flags ...string) ([]string, error) {
	files := []string{}

	gitLS := exec.Command("git", append([]string{"ls-files", "-z"}, flags...)...)
	gitLS.Dir = dir

	gitOut, err := gitLS.StdoutPipe()
	if err != nil {
		return nil, err
	}

	outScan := bufio.NewScanner(gitOut)
	outScan.Split(scanNull)

	err = gitLS.Start()
	if err != nil {
		return nil, err
	}

	for outScan.Scan() {
		files = append(files, outScan.Text())
	}

	err = gitLS.Wait()
	if err != nil {
		return nil, err
	}

	return files, nil
}

func scanNull(data []byte, atEOF bool) (int, []byte, error) {
	// eof, no more data; terminate
	if atEOF && len(data) == 0 {
		return 0, nil, nil
	}

	// look for terminating null byte
	if i := bytes.IndexByte(data, 0); i >= 0 {
		return i + 1, data[0:i], nil
	}

	// no final terminator; return what's left
	if atEOF {
		return len(data), data, nil
	}

	// request more data
	return 0, nil, nil
}
<|endoftext|>


<commit_before>package commands

// Version
const version = "v0.81.2-beta"
<commit_msg>add version bump<commit_after>package commands

// Version
const version = "v0.81.3-beta"
<|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 http

import (
	"bufio"
	"io"
	"net"
	"net/textproto"
	"os"
	"sync"
)

var (
	ErrPersistEOF = &ProtocolError{"persistent connection closed"}
	ErrPipeline   = &ProtocolError{"pipeline error"}
)

// A ServerConn reads requests and sends responses over an underlying
// connection, until the HTTP keepalive logic commands an end. ServerConn
// does not close the underlying connection. Instead, the user calls Close
// and regains control over the connection. ServerConn supports pipe-lining,
// i.e. requests can be read out of sync (but in the same order) while the
// respective responses are sent.
type ServerConn struct {
	lk              sync.Mutex // read-write protects the following fields
	c               net.Conn
	r               *bufio.Reader
	re, we          os.Error // read/write errors
	lastbody        io.ReadCloser
	nread, nwritten int
	pipereq         map[*Request]uint

	pipe textproto.Pipeline
}

// NewServerConn returns a new ServerConn reading and writing c.  If r is not
// nil, it is the buffer to use when reading c.
func NewServerConn(c net.Conn, r *bufio.Reader) *ServerConn {
	if r == nil {
		r = bufio.NewReader(c)
	}
	return &ServerConn{c: c, r: r, pipereq: make(map[*Request]uint)}
}

// Close detaches the ServerConn and returns the underlying connection as well
// as the read-side bufio which may have some left over data. Close may be
// called before Read has signaled the end of the keep-alive logic. The user
// should not call Close while Read or Write is in progress.
func (sc *ServerConn) Close() (c net.Conn, r *bufio.Reader) {
	sc.lk.Lock()
	defer sc.lk.Unlock()
	c = sc.c
	r = sc.r
	sc.c = nil
	sc.r = nil
	return
}

// Read returns the next request on the wire. An ErrPersistEOF is returned if
// it is gracefully determined that there are no more requests (e.g. after the
// first request on an HTTP/1.0 connection, or after a Connection:close on a
// HTTP/1.1 connection).
func (sc *ServerConn) Read() (req *Request, err os.Error) {

	// Ensure ordered execution of Reads and Writes
	id := sc.pipe.Next()
	sc.pipe.StartRequest(id)
	defer func() {
		sc.pipe.EndRequest(id)
		if req == nil {
			sc.pipe.StartResponse(id)
			sc.pipe.EndResponse(id)
		} else {
			// Remember the pipeline id of this request
			sc.lk.Lock()
			sc.pipereq[req] = id
			sc.lk.Unlock()
		}
	}()

	sc.lk.Lock()
	if sc.we != nil { // no point receiving if write-side broken or closed
		defer sc.lk.Unlock()
		return nil, sc.we
	}
	if sc.re != nil {
		defer sc.lk.Unlock()
		return nil, sc.re
	}
	if sc.r == nil { // connection closed by user in the meantime
		defer sc.lk.Unlock()
		return nil, os.EBADF
	}
	r := sc.r
	lastbody := sc.lastbody
	sc.lastbody = nil
	sc.lk.Unlock()

	// Make sure body is fully consumed, even if user does not call body.Close
	if lastbody != nil {
		// body.Close is assumed to be idempotent and multiple calls to
		// it should return the error that its first invokation
		// returned.
		err = lastbody.Close()
		if err != nil {
			sc.lk.Lock()
			defer sc.lk.Unlock()
			sc.re = err
			return nil, err
		}
	}

	req, err = ReadRequest(r)
	sc.lk.Lock()
	defer sc.lk.Unlock()
	if err != nil {
		if err == io.ErrUnexpectedEOF {
			// A close from the opposing client is treated as a
			// graceful close, even if there was some unparse-able
			// data before the close.
			sc.re = ErrPersistEOF
			return nil, sc.re
		} else {
			sc.re = err
			return req, err
		}
	}
	sc.lastbody = req.Body
	sc.nread++
	if req.Close {
		sc.re = ErrPersistEOF
		return req, sc.re
	}
	return req, err
}

// Pending returns the number of unanswered requests
// that have been received on the connection.
func (sc *ServerConn) Pending() int {
	sc.lk.Lock()
	defer sc.lk.Unlock()
	return sc.nread - sc.nwritten
}

// Write writes resp in response to req. To close the connection gracefully, set the
// Response.Close field to true. Write should be considered operational until
// it returns an error, regardless of any errors returned on the Read side.
func (sc *ServerConn) Write(req *Request, resp *Response) os.Error {

	// Retrieve the pipeline ID of this request/response pair
	sc.lk.Lock()
	id, ok := sc.pipereq[req]
	sc.pipereq[req] = 0, false
	if !ok {
		sc.lk.Unlock()
		return ErrPipeline
	}
	sc.lk.Unlock()

	// Ensure pipeline order
	sc.pipe.StartResponse(id)
	defer sc.pipe.EndResponse(id)

	sc.lk.Lock()
	if sc.we != nil {
		defer sc.lk.Unlock()
		return sc.we
	}
	if sc.c == nil { // connection closed by user in the meantime
		defer sc.lk.Unlock()
		return os.EBADF
	}
	c := sc.c
	if sc.nread <= sc.nwritten {
		defer sc.lk.Unlock()
		return os.NewError("persist server pipe count")
	}
	if resp.Close {
		// After signaling a keep-alive close, any pipelined unread
		// requests will be lost. It is up to the user to drain them
		// before signaling.
		sc.re = ErrPersistEOF
	}
	sc.lk.Unlock()

	err := resp.Write(c)
	sc.lk.Lock()
	defer sc.lk.Unlock()
	if err != nil {
		sc.we = err
		return err
	}
	sc.nwritten++

	return nil
}

// A ClientConn sends request and receives headers over an underlying
// connection, while respecting the HTTP keepalive logic. ClientConn is not
// responsible for closing the underlying connection. One must call Close to
// regain control of that connection and deal with it as desired.
type ClientConn struct {
	lk              sync.Mutex // read-write protects the following fields
	c               net.Conn
	r               *bufio.Reader
	re, we          os.Error // read/write errors
	lastbody        io.ReadCloser
	nread, nwritten int
	pipereq         map[*Request]uint

	pipe     textproto.Pipeline
	writeReq func(*Request, io.Writer) os.Error
	readRes  func(buf *bufio.Reader, method string) (*Response, os.Error)
}

// NewClientConn returns a new ClientConn reading and writing c.  If r is not
// nil, it is the buffer to use when reading c.
func NewClientConn(c net.Conn, r *bufio.Reader) *ClientConn {
	if r == nil {
		r = bufio.NewReader(c)
	}
	return &ClientConn{
		c:        c,
		r:        r,
		pipereq:  make(map[*Request]uint),
		writeReq: (*Request).Write,
		readRes:  ReadResponse,
	}
}

// NewProxyClientConn works like NewClientConn but writes Requests
// using Request's WriteProxy method.
func NewProxyClientConn(c net.Conn, r *bufio.Reader) *ClientConn {
	cc := NewClientConn(c, r)
	cc.writeReq = (*Request).WriteProxy
	return cc
}

// Close detaches the ClientConn and returns the underlying connection as well
// as the read-side bufio which may have some left over data. Close may be
// called before the user or Read have signaled the end of the keep-alive
// logic. The user should not call Close while Read or Write is in progress.
func (cc *ClientConn) Close() (c net.Conn, r *bufio.Reader) {
	cc.lk.Lock()
	defer cc.lk.Unlock()
	c = cc.c
	r = cc.r
	cc.c = nil
	cc.r = nil
	return
}

// Write writes a request. An ErrPersistEOF error is returned if the connection
// has been closed in an HTTP keepalive sense. If req.Close equals true, the
// keepalive connection is logically closed after this request and the opposing
// server is informed. An ErrUnexpectedEOF indicates the remote closed the
// underlying TCP connection, which is usually considered as graceful close.
func (cc *ClientConn) Write(req *Request) (err os.Error) {

	// Ensure ordered execution of Writes
	id := cc.pipe.Next()
	cc.pipe.StartRequest(id)
	defer func() {
		cc.pipe.EndRequest(id)
		if err != nil {
			cc.pipe.StartResponse(id)
			cc.pipe.EndResponse(id)
		} else {
			// Remember the pipeline id of this request
			cc.lk.Lock()
			cc.pipereq[req] = id
			cc.lk.Unlock()
		}
	}()

	cc.lk.Lock()
	if cc.re != nil { // no point sending if read-side closed or broken
		defer cc.lk.Unlock()
		return cc.re
	}
	if cc.we != nil {
		defer cc.lk.Unlock()
		return cc.we
	}
	if cc.c == nil { // connection closed by user in the meantime
		defer cc.lk.Unlock()
		return os.EBADF
	}
	c := cc.c
	if req.Close {
		// We write the EOF to the write-side error, because there
		// still might be some pipelined reads
		cc.we = ErrPersistEOF
	}
	cc.lk.Unlock()

	err = cc.writeReq(req, c)
	cc.lk.Lock()
	defer cc.lk.Unlock()
	if err != nil {
		cc.we = err
		return err
	}
	cc.nwritten++

	return nil
}

// Pending returns the number of unanswered requests
// that have been sent on the connection.
func (cc *ClientConn) Pending() int {
	cc.lk.Lock()
	defer cc.lk.Unlock()
	return cc.nwritten - cc.nread
}

// Read reads the next response from the wire. A valid response might be
// returned together with an ErrPersistEOF, which means that the remote
// requested that this be the last request serviced. Read can be called
// concurrently with Write, but not with another Read.
func (cc *ClientConn) Read(req *Request) (resp *Response, err os.Error) {

	// Retrieve the pipeline ID of this request/response pair
	cc.lk.Lock()
	id, ok := cc.pipereq[req]
	cc.pipereq[req] = 0, false
	if !ok {
		cc.lk.Unlock()
		return nil, ErrPipeline
	}
	cc.lk.Unlock()

	// Ensure pipeline order
	cc.pipe.StartResponse(id)
	defer cc.pipe.EndResponse(id)

	cc.lk.Lock()
	if cc.re != nil {
		defer cc.lk.Unlock()
		return nil, cc.re
	}
	if cc.r == nil { // connection closed by user in the meantime
		defer cc.lk.Unlock()
		return nil, os.EBADF
	}
	r := cc.r
	lastbody := cc.lastbody
	cc.lastbody = nil
	cc.lk.Unlock()

	// Make sure body is fully consumed, even if user does not call body.Close
	if lastbody != nil {
		// body.Close is assumed to be idempotent and multiple calls to
		// it should return the error that its first invokation
		// returned.
		err = lastbody.Close()
		if err != nil {
			cc.lk.Lock()
			defer cc.lk.Unlock()
			cc.re = err
			return nil, err
		}
	}

	resp, err = cc.readRes(r, req.Method)
	cc.lk.Lock()
	defer cc.lk.Unlock()
	if err != nil {
		cc.re = err
		return resp, err
	}
	cc.lastbody = resp.Body

	cc.nread++

	if resp.Close {
		cc.re = ErrPersistEOF // don't send any more requests
		return resp, cc.re
	}
	return resp, err
}

// Do is convenience method that writes a request and reads a response.
func (cc *ClientConn) Do(req *Request) (resp *Response, err os.Error) {
	err = cc.Write(req)
	if err != nil {
		return
	}
	return cc.Read(req)
}
<commit_msg>http: in ServerConn and ClientConn, rename Close to Hijack, add Close<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 http

import (
	"bufio"
	"io"
	"net"
	"net/textproto"
	"os"
	"sync"
)

var (
	ErrPersistEOF = &ProtocolError{"persistent connection closed"}
	ErrPipeline   = &ProtocolError{"pipeline error"}
)

// A ServerConn reads requests and sends responses over an underlying
// connection, until the HTTP keepalive logic commands an end. ServerConn
// also allows hijacking the underlying connection by calling Hijack
// to regain control over the connection. ServerConn supports pipe-lining,
// i.e. requests can be read out of sync (but in the same order) while the
// respective responses are sent.
type ServerConn struct {
	lk              sync.Mutex // read-write protects the following fields
	c               net.Conn
	r               *bufio.Reader
	re, we          os.Error // read/write errors
	lastbody        io.ReadCloser
	nread, nwritten int
	pipereq         map[*Request]uint

	pipe textproto.Pipeline
}

// NewServerConn returns a new ServerConn reading and writing c.  If r is not
// nil, it is the buffer to use when reading c.
func NewServerConn(c net.Conn, r *bufio.Reader) *ServerConn {
	if r == nil {
		r = bufio.NewReader(c)
	}
	return &ServerConn{c: c, r: r, pipereq: make(map[*Request]uint)}
}

// Hijack detaches the ServerConn and returns the underlying connection as well
// as the read-side bufio which may have some left over data. Hijack may be
// called before Read has signaled the end of the keep-alive logic. The user
// should not call Hijack while Read or Write is in progress.
func (sc *ServerConn) Hijack() (c net.Conn, r *bufio.Reader) {
	sc.lk.Lock()
	defer sc.lk.Unlock()
	c = sc.c
	r = sc.r
	sc.c = nil
	sc.r = nil
	return
}

// Close calls Hijack and then also closes the underlying connection
func (sc *ServerConn) Close() os.Error {
	c, _ := sc.Hijack()
	if c != nil {
		return c.Close()
	}
	return nil
}

// Read returns the next request on the wire. An ErrPersistEOF is returned if
// it is gracefully determined that there are no more requests (e.g. after the
// first request on an HTTP/1.0 connection, or after a Connection:close on a
// HTTP/1.1 connection).
func (sc *ServerConn) Read() (req *Request, err os.Error) {

	// Ensure ordered execution of Reads and Writes
	id := sc.pipe.Next()
	sc.pipe.StartRequest(id)
	defer func() {
		sc.pipe.EndRequest(id)
		if req == nil {
			sc.pipe.StartResponse(id)
			sc.pipe.EndResponse(id)
		} else {
			// Remember the pipeline id of this request
			sc.lk.Lock()
			sc.pipereq[req] = id
			sc.lk.Unlock()
		}
	}()

	sc.lk.Lock()
	if sc.we != nil { // no point receiving if write-side broken or closed
		defer sc.lk.Unlock()
		return nil, sc.we
	}
	if sc.re != nil {
		defer sc.lk.Unlock()
		return nil, sc.re
	}
	if sc.r == nil { // connection closed by user in the meantime
		defer sc.lk.Unlock()
		return nil, os.EBADF
	}
	r := sc.r
	lastbody := sc.lastbody
	sc.lastbody = nil
	sc.lk.Unlock()

	// Make sure body is fully consumed, even if user does not call body.Close
	if lastbody != nil {
		// body.Close is assumed to be idempotent and multiple calls to
		// it should return the error that its first invokation
		// returned.
		err = lastbody.Close()
		if err != nil {
			sc.lk.Lock()
			defer sc.lk.Unlock()
			sc.re = err
			return nil, err
		}
	}

	req, err = ReadRequest(r)
	sc.lk.Lock()
	defer sc.lk.Unlock()
	if err != nil {
		if err == io.ErrUnexpectedEOF {
			// A close from the opposing client is treated as a
			// graceful close, even if there was some unparse-able
			// data before the close.
			sc.re = ErrPersistEOF
			return nil, sc.re
		} else {
			sc.re = err
			return req, err
		}
	}
	sc.lastbody = req.Body
	sc.nread++
	if req.Close {
		sc.re = ErrPersistEOF
		return req, sc.re
	}
	return req, err
}

// Pending returns the number of unanswered requests
// that have been received on the connection.
func (sc *ServerConn) Pending() int {
	sc.lk.Lock()
	defer sc.lk.Unlock()
	return sc.nread - sc.nwritten
}

// Write writes resp in response to req. To close the connection gracefully, set the
// Response.Close field to true. Write should be considered operational until
// it returns an error, regardless of any errors returned on the Read side.
func (sc *ServerConn) Write(req *Request, resp *Response) os.Error {

	// Retrieve the pipeline ID of this request/response pair
	sc.lk.Lock()
	id, ok := sc.pipereq[req]
	sc.pipereq[req] = 0, false
	if !ok {
		sc.lk.Unlock()
		return ErrPipeline
	}
	sc.lk.Unlock()

	// Ensure pipeline order
	sc.pipe.StartResponse(id)
	defer sc.pipe.EndResponse(id)

	sc.lk.Lock()
	if sc.we != nil {
		defer sc.lk.Unlock()
		return sc.we
	}
	if sc.c == nil { // connection closed by user in the meantime
		defer sc.lk.Unlock()
		return os.EBADF
	}
	c := sc.c
	if sc.nread <= sc.nwritten {
		defer sc.lk.Unlock()
		return os.NewError("persist server pipe count")
	}
	if resp.Close {
		// After signaling a keep-alive close, any pipelined unread
		// requests will be lost. It is up to the user to drain them
		// before signaling.
		sc.re = ErrPersistEOF
	}
	sc.lk.Unlock()

	err := resp.Write(c)
	sc.lk.Lock()
	defer sc.lk.Unlock()
	if err != nil {
		sc.we = err
		return err
	}
	sc.nwritten++

	return nil
}

// A ClientConn sends request and receives headers over an underlying
// connection, while respecting the HTTP keepalive logic. ClientConn
// supports hijacking the connection calling Hijack to
// regain control of the underlying net.Conn and deal with it as desired.
type ClientConn struct {
	lk              sync.Mutex // read-write protects the following fields
	c               net.Conn
	r               *bufio.Reader
	re, we          os.Error // read/write errors
	lastbody        io.ReadCloser
	nread, nwritten int
	pipereq         map[*Request]uint

	pipe     textproto.Pipeline
	writeReq func(*Request, io.Writer) os.Error
	readRes  func(buf *bufio.Reader, method string) (*Response, os.Error)
}

// NewClientConn returns a new ClientConn reading and writing c.  If r is not
// nil, it is the buffer to use when reading c.
func NewClientConn(c net.Conn, r *bufio.Reader) *ClientConn {
	if r == nil {
		r = bufio.NewReader(c)
	}
	return &ClientConn{
		c:        c,
		r:        r,
		pipereq:  make(map[*Request]uint),
		writeReq: (*Request).Write,
		readRes:  ReadResponse,
	}
}

// NewProxyClientConn works like NewClientConn but writes Requests
// using Request's WriteProxy method.
func NewProxyClientConn(c net.Conn, r *bufio.Reader) *ClientConn {
	cc := NewClientConn(c, r)
	cc.writeReq = (*Request).WriteProxy
	return cc
}

// Hijack detaches the ClientConn and returns the underlying connection as well
// as the read-side bufio which may have some left over data. Hijack may be
// called before the user or Read have signaled the end of the keep-alive
// logic. The user should not call Hijack while Read or Write is in progress.
func (cc *ClientConn) Hijack() (c net.Conn, r *bufio.Reader) {
	cc.lk.Lock()
	defer cc.lk.Unlock()
	c = cc.c
	r = cc.r
	cc.c = nil
	cc.r = nil
	return
}

// Close calls Hijack and then also closes the underlying connection
func (cc *ClientConn) Close() os.Error {
	c, _ := cc.Hijack()
	if c != nil {
		return c.Close()
	}
	return nil
}

// Write writes a request. An ErrPersistEOF error is returned if the connection
// has been closed in an HTTP keepalive sense. If req.Close equals true, the
// keepalive connection is logically closed after this request and the opposing
// server is informed. An ErrUnexpectedEOF indicates the remote closed the
// underlying TCP connection, which is usually considered as graceful close.
func (cc *ClientConn) Write(req *Request) (err os.Error) {

	// Ensure ordered execution of Writes
	id := cc.pipe.Next()
	cc.pipe.StartRequest(id)
	defer func() {
		cc.pipe.EndRequest(id)
		if err != nil {
			cc.pipe.StartResponse(id)
			cc.pipe.EndResponse(id)
		} else {
			// Remember the pipeline id of this request
			cc.lk.Lock()
			cc.pipereq[req] = id
			cc.lk.Unlock()
		}
	}()

	cc.lk.Lock()
	if cc.re != nil { // no point sending if read-side closed or broken
		defer cc.lk.Unlock()
		return cc.re
	}
	if cc.we != nil {
		defer cc.lk.Unlock()
		return cc.we
	}
	if cc.c == nil { // connection closed by user in the meantime
		defer cc.lk.Unlock()
		return os.EBADF
	}
	c := cc.c
	if req.Close {
		// We write the EOF to the write-side error, because there
		// still might be some pipelined reads
		cc.we = ErrPersistEOF
	}
	cc.lk.Unlock()

	err = cc.writeReq(req, c)
	cc.lk.Lock()
	defer cc.lk.Unlock()
	if err != nil {
		cc.we = err
		return err
	}
	cc.nwritten++

	return nil
}

// Pending returns the number of unanswered requests
// that have been sent on the connection.
func (cc *ClientConn) Pending() int {
	cc.lk.Lock()
	defer cc.lk.Unlock()
	return cc.nwritten - cc.nread
}

// Read reads the next response from the wire. A valid response might be
// returned together with an ErrPersistEOF, which means that the remote
// requested that this be the last request serviced. Read can be called
// concurrently with Write, but not with another Read.
func (cc *ClientConn) Read(req *Request) (resp *Response, err os.Error) {

	// Retrieve the pipeline ID of this request/response pair
	cc.lk.Lock()
	id, ok := cc.pipereq[req]
	cc.pipereq[req] = 0, false
	if !ok {
		cc.lk.Unlock()
		return nil, ErrPipeline
	}
	cc.lk.Unlock()

	// Ensure pipeline order
	cc.pipe.StartResponse(id)
	defer cc.pipe.EndResponse(id)

	cc.lk.Lock()
	if cc.re != nil {
		defer cc.lk.Unlock()
		return nil, cc.re
	}
	if cc.r == nil { // connection closed by user in the meantime
		defer cc.lk.Unlock()
		return nil, os.EBADF
	}
	r := cc.r
	lastbody := cc.lastbody
	cc.lastbody = nil
	cc.lk.Unlock()

	// Make sure body is fully consumed, even if user does not call body.Close
	if lastbody != nil {
		// body.Close is assumed to be idempotent and multiple calls to
		// it should return the error that its first invokation
		// returned.
		err = lastbody.Close()
		if err != nil {
			cc.lk.Lock()
			defer cc.lk.Unlock()
			cc.re = err
			return nil, err
		}
	}

	resp, err = cc.readRes(r, req.Method)
	cc.lk.Lock()
	defer cc.lk.Unlock()
	if err != nil {
		cc.re = err
		return resp, err
	}
	cc.lastbody = resp.Body

	cc.nread++

	if resp.Close {
		cc.re = ErrPersistEOF // don't send any more requests
		return resp, cc.re
	}
	return resp, err
}

// Do is convenience method that writes a request and reads a response.
func (cc *ClientConn) Do(req *Request) (resp *Response, err os.Error) {
	err = cc.Write(req)
	if err != nil {
		return
	}
	return cc.Read(req)
}
<|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.

// This file implements runtime support for signal handling.
//
// Most synchronization primitives are not available from
// the signal handler (it cannot block, allocate memory, or use locks)
// so the handler communicates with a processing goroutine
// via struct sig, below.
//
// sigsend is called by the signal handler to queue a new signal.
// signal_recv is called by the Go program to receive a newly queued signal.
// Synchronization between sigsend and signal_recv is based on the sig.state
// variable. It can be in 4 states: sigIdle, sigReceiving, sigSending and sigFixup.
// sigReceiving means that signal_recv is blocked on sig.Note and there are no
// new pending signals.
// sigSending means that sig.mask *may* contain new pending signals,
// signal_recv can't be blocked in this state.
// sigIdle means that there are no new pending signals and signal_recv is not blocked.
// sigFixup is a transient state that can only exist as a short
// transition from sigReceiving and then on to sigIdle: it is
// used to ensure the AllThreadsSyscall()'s mDoFixup() operation
// occurs on the sleeping m, waiting to receive a signal.
// Transitions between states are done atomically with CAS.
// When signal_recv is unblocked, it resets sig.Note and rechecks sig.mask.
// If several sigsends and signal_recv execute concurrently, it can lead to
// unnecessary rechecks of sig.mask, but it cannot lead to missed signals
// nor deadlocks.

//go:build !plan9
// +build !plan9

package runtime

import (
	"runtime/internal/atomic"
	_ "unsafe" // for go:linkname
)

// sig handles communication between the signal handler and os/signal.
// Other than the inuse and recv fields, the fields are accessed atomically.
//
// The wanted and ignored fields are only written by one goroutine at
// a time; access is controlled by the handlers Mutex in os/signal.
// The fields are only read by that one goroutine and by the signal handler.
// We access them atomically to minimize the race between setting them
// in the goroutine calling os/signal and the signal handler,
// which may be running in a different thread. That race is unavoidable,
// as there is no connection between handling a signal and receiving one,
// but atomic instructions should minimize it.
var sig struct {
	note       note
	mask       [(_NSIG + 31) / 32]uint32
	wanted     [(_NSIG + 31) / 32]uint32
	ignored    [(_NSIG + 31) / 32]uint32
	recv       [(_NSIG + 31) / 32]uint32
	state      uint32
	delivering uint32
	inuse      bool
}

const (
	sigIdle = iota
	sigReceiving
	sigSending
	sigFixup
)

// sigsend delivers a signal from sighandler to the internal signal delivery queue.
// It reports whether the signal was sent. If not, the caller typically crashes the program.
// It runs from the signal handler, so it's limited in what it can do.
func sigsend(s uint32) bool {
	bit := uint32(1) << uint(s&31)
	if !sig.inuse || s >= uint32(32*len(sig.wanted)) {
		return false
	}

	atomic.Xadd(&sig.delivering, 1)
	// We are running in the signal handler; defer is not available.

	if w := atomic.Load(&sig.wanted[s/32]); w&bit == 0 {
		atomic.Xadd(&sig.delivering, -1)
		return false
	}

	// Add signal to outgoing queue.
	for {
		mask := sig.mask[s/32]
		if mask&bit != 0 {
			atomic.Xadd(&sig.delivering, -1)
			return true // signal already in queue
		}
		if atomic.Cas(&sig.mask[s/32], mask, mask|bit) {
			break
		}
	}

	// Notify receiver that queue has new bit.
Send:
	for {
		switch atomic.Load(&sig.state) {
		default:
			throw("sigsend: inconsistent state")
		case sigIdle:
			if atomic.Cas(&sig.state, sigIdle, sigSending) {
				break Send
			}
		case sigSending:
			// notification already pending
			break Send
		case sigReceiving:
			if atomic.Cas(&sig.state, sigReceiving, sigIdle) {
				if GOOS == "darwin" || GOOS == "ios" {
					sigNoteWakeup(&sig.note)
					break Send
				}
				notewakeup(&sig.note)
				break Send
			}
		case sigFixup:
			// nothing to do - we need to wait for sigIdle.
			osyield()
		}
	}

	atomic.Xadd(&sig.delivering, -1)
	return true
}

// sigRecvPrepareForFixup is used to temporarily wake up the
// signal_recv() running thread while it is blocked waiting for the
// arrival of a signal. If it causes the thread to wake up, the
// sig.state travels through this sequence: sigReceiving -> sigFixup
// -> sigIdle -> sigReceiving and resumes. (This is only called while
// GC is disabled.)
//go:nosplit
func sigRecvPrepareForFixup() {
	if atomic.Cas(&sig.state, sigReceiving, sigFixup) {
		notewakeup(&sig.note)
	}
}

// Called to receive the next queued signal.
// Must only be called from a single goroutine at a time.
//go:linkname signal_recv os/signal.signal_recv
func signal_recv() uint32 {
	for {
		// Serve any signals from local copy.
		for i := uint32(0); i < _NSIG; i++ {
			if sig.recv[i/32]&(1<<(i&31)) != 0 {
				sig.recv[i/32] &^= 1 << (i & 31)
				return i
			}
		}

		// Wait for updates to be available from signal sender.
	Receive:
		for {
			switch atomic.Load(&sig.state) {
			default:
				throw("signal_recv: inconsistent state")
			case sigIdle:
				if atomic.Cas(&sig.state, sigIdle, sigReceiving) {
					if GOOS == "darwin" || GOOS == "ios" {
						sigNoteSleep(&sig.note)
						break Receive
					}
					notetsleepg(&sig.note, -1)
					noteclear(&sig.note)
					if !atomic.Cas(&sig.state, sigFixup, sigIdle) {
						break Receive
					}
					// Getting here, the code will
					// loop around again to sleep
					// in state sigReceiving. This
					// path is taken when
					// sigRecvPrepareForFixup()
					// has been called by another
					// thread.
				}
			case sigSending:
				if atomic.Cas(&sig.state, sigSending, sigIdle) {
					break Receive
				}
			}
		}

		// Incorporate updates from sender into local copy.
		for i := range sig.mask {
			sig.recv[i] = atomic.Xchg(&sig.mask[i], 0)
		}
	}
}

// signalWaitUntilIdle waits until the signal delivery mechanism is idle.
// This is used to ensure that we do not drop a signal notification due
// to a race between disabling a signal and receiving a signal.
// This assumes that signal delivery has already been disabled for
// the signal(s) in question, and here we are just waiting to make sure
// that all the signals have been delivered to the user channels
// by the os/signal package.
//go:linkname signalWaitUntilIdle os/signal.signalWaitUntilIdle
func signalWaitUntilIdle() {
	// Although the signals we care about have been removed from
	// sig.wanted, it is possible that another thread has received
	// a signal, has read from sig.wanted, is now updating sig.mask,
	// and has not yet woken up the processor thread. We need to wait
	// until all current signal deliveries have completed.
	for atomic.Load(&sig.delivering) != 0 {
		Gosched()
	}

	// Although WaitUntilIdle seems like the right name for this
	// function, the state we are looking for is sigReceiving, not
	// sigIdle.  The sigIdle state is really more like sigProcessing.
	for atomic.Load(&sig.state) != sigReceiving {
		Gosched()
	}
}

// Must only be called from a single goroutine at a time.
//go:linkname signal_enable os/signal.signal_enable
func signal_enable(s uint32) {
	if !sig.inuse {
		// This is the first call to signal_enable. Initialize.
		sig.inuse = true // enable reception of signals; cannot disable
		if GOOS == "darwin" || GOOS == "ios" {
			sigNoteSetup(&sig.note)
		} else {
			noteclear(&sig.note)
		}
	}

	if s >= uint32(len(sig.wanted)*32) {
		return
	}

	w := sig.wanted[s/32]
	w |= 1 << (s & 31)
	atomic.Store(&sig.wanted[s/32], w)

	i := sig.ignored[s/32]
	i &^= 1 << (s & 31)
	atomic.Store(&sig.ignored[s/32], i)

	sigenable(s)
}

// Must only be called from a single goroutine at a time.
//go:linkname signal_disable os/signal.signal_disable
func signal_disable(s uint32) {
	if s >= uint32(len(sig.wanted)*32) {
		return
	}
	sigdisable(s)

	w := sig.wanted[s/32]
	w &^= 1 << (s & 31)
	atomic.Store(&sig.wanted[s/32], w)
}

// Must only be called from a single goroutine at a time.
//go:linkname signal_ignore os/signal.signal_ignore
func signal_ignore(s uint32) {
	if s >= uint32(len(sig.wanted)*32) {
		return
	}
	sigignore(s)

	w := sig.wanted[s/32]
	w &^= 1 << (s & 31)
	atomic.Store(&sig.wanted[s/32], w)

	i := sig.ignored[s/32]
	i |= 1 << (s & 31)
	atomic.Store(&sig.ignored[s/32], i)
}

// sigInitIgnored marks the signal as already ignored. This is called at
// program start by initsig. In a shared library initsig is called by
// libpreinit, so the runtime may not be initialized yet.
//go:nosplit
func sigInitIgnored(s uint32) {
	i := sig.ignored[s/32]
	i |= 1 << (s & 31)
	atomic.Store(&sig.ignored[s/32], i)
}

// Checked by signal handlers.
//go:linkname signal_ignored os/signal.signal_ignored
func signal_ignored(s uint32) bool {
	i := atomic.Load(&sig.ignored[s/32])
	return i&(1<<(s&31)) != 0
}
<commit_msg>runtime: don't test sig.inuse in sigsend<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.

// This file implements runtime support for signal handling.
//
// Most synchronization primitives are not available from
// the signal handler (it cannot block, allocate memory, or use locks)
// so the handler communicates with a processing goroutine
// via struct sig, below.
//
// sigsend is called by the signal handler to queue a new signal.
// signal_recv is called by the Go program to receive a newly queued signal.
// Synchronization between sigsend and signal_recv is based on the sig.state
// variable. It can be in 4 states: sigIdle, sigReceiving, sigSending and sigFixup.
// sigReceiving means that signal_recv is blocked on sig.Note and there are no
// new pending signals.
// sigSending means that sig.mask *may* contain new pending signals,
// signal_recv can't be blocked in this state.
// sigIdle means that there are no new pending signals and signal_recv is not blocked.
// sigFixup is a transient state that can only exist as a short
// transition from sigReceiving and then on to sigIdle: it is
// used to ensure the AllThreadsSyscall()'s mDoFixup() operation
// occurs on the sleeping m, waiting to receive a signal.
// Transitions between states are done atomically with CAS.
// When signal_recv is unblocked, it resets sig.Note and rechecks sig.mask.
// If several sigsends and signal_recv execute concurrently, it can lead to
// unnecessary rechecks of sig.mask, but it cannot lead to missed signals
// nor deadlocks.

//go:build !plan9
// +build !plan9

package runtime

import (
	"runtime/internal/atomic"
	_ "unsafe" // for go:linkname
)

// sig handles communication between the signal handler and os/signal.
// Other than the inuse and recv fields, the fields are accessed atomically.
//
// The wanted and ignored fields are only written by one goroutine at
// a time; access is controlled by the handlers Mutex in os/signal.
// The fields are only read by that one goroutine and by the signal handler.
// We access them atomically to minimize the race between setting them
// in the goroutine calling os/signal and the signal handler,
// which may be running in a different thread. That race is unavoidable,
// as there is no connection between handling a signal and receiving one,
// but atomic instructions should minimize it.
var sig struct {
	note       note
	mask       [(_NSIG + 31) / 32]uint32
	wanted     [(_NSIG + 31) / 32]uint32
	ignored    [(_NSIG + 31) / 32]uint32
	recv       [(_NSIG + 31) / 32]uint32
	state      uint32
	delivering uint32
	inuse      bool
}

const (
	sigIdle = iota
	sigReceiving
	sigSending
	sigFixup
)

// sigsend delivers a signal from sighandler to the internal signal delivery queue.
// It reports whether the signal was sent. If not, the caller typically crashes the program.
// It runs from the signal handler, so it's limited in what it can do.
func sigsend(s uint32) bool {
	bit := uint32(1) << uint(s&31)
	if s >= uint32(32*len(sig.wanted)) {
		return false
	}

	atomic.Xadd(&sig.delivering, 1)
	// We are running in the signal handler; defer is not available.

	if w := atomic.Load(&sig.wanted[s/32]); w&bit == 0 {
		atomic.Xadd(&sig.delivering, -1)
		return false
	}

	// Add signal to outgoing queue.
	for {
		mask := sig.mask[s/32]
		if mask&bit != 0 {
			atomic.Xadd(&sig.delivering, -1)
			return true // signal already in queue
		}
		if atomic.Cas(&sig.mask[s/32], mask, mask|bit) {
			break
		}
	}

	// Notify receiver that queue has new bit.
Send:
	for {
		switch atomic.Load(&sig.state) {
		default:
			throw("sigsend: inconsistent state")
		case sigIdle:
			if atomic.Cas(&sig.state, sigIdle, sigSending) {
				break Send
			}
		case sigSending:
			// notification already pending
			break Send
		case sigReceiving:
			if atomic.Cas(&sig.state, sigReceiving, sigIdle) {
				if GOOS == "darwin" || GOOS == "ios" {
					sigNoteWakeup(&sig.note)
					break Send
				}
				notewakeup(&sig.note)
				break Send
			}
		case sigFixup:
			// nothing to do - we need to wait for sigIdle.
			osyield()
		}
	}

	atomic.Xadd(&sig.delivering, -1)
	return true
}

// sigRecvPrepareForFixup is used to temporarily wake up the
// signal_recv() running thread while it is blocked waiting for the
// arrival of a signal. If it causes the thread to wake up, the
// sig.state travels through this sequence: sigReceiving -> sigFixup
// -> sigIdle -> sigReceiving and resumes. (This is only called while
// GC is disabled.)
//go:nosplit
func sigRecvPrepareForFixup() {
	if atomic.Cas(&sig.state, sigReceiving, sigFixup) {
		notewakeup(&sig.note)
	}
}

// Called to receive the next queued signal.
// Must only be called from a single goroutine at a time.
//go:linkname signal_recv os/signal.signal_recv
func signal_recv() uint32 {
	for {
		// Serve any signals from local copy.
		for i := uint32(0); i < _NSIG; i++ {
			if sig.recv[i/32]&(1<<(i&31)) != 0 {
				sig.recv[i/32] &^= 1 << (i & 31)
				return i
			}
		}

		// Wait for updates to be available from signal sender.
	Receive:
		for {
			switch atomic.Load(&sig.state) {
			default:
				throw("signal_recv: inconsistent state")
			case sigIdle:
				if atomic.Cas(&sig.state, sigIdle, sigReceiving) {
					if GOOS == "darwin" || GOOS == "ios" {
						sigNoteSleep(&sig.note)
						break Receive
					}
					notetsleepg(&sig.note, -1)
					noteclear(&sig.note)
					if !atomic.Cas(&sig.state, sigFixup, sigIdle) {
						break Receive
					}
					// Getting here, the code will
					// loop around again to sleep
					// in state sigReceiving. This
					// path is taken when
					// sigRecvPrepareForFixup()
					// has been called by another
					// thread.
				}
			case sigSending:
				if atomic.Cas(&sig.state, sigSending, sigIdle) {
					break Receive
				}
			}
		}

		// Incorporate updates from sender into local copy.
		for i := range sig.mask {
			sig.recv[i] = atomic.Xchg(&sig.mask[i], 0)
		}
	}
}

// signalWaitUntilIdle waits until the signal delivery mechanism is idle.
// This is used to ensure that we do not drop a signal notification due
// to a race between disabling a signal and receiving a signal.
// This assumes that signal delivery has already been disabled for
// the signal(s) in question, and here we are just waiting to make sure
// that all the signals have been delivered to the user channels
// by the os/signal package.
//go:linkname signalWaitUntilIdle os/signal.signalWaitUntilIdle
func signalWaitUntilIdle() {
	// Although the signals we care about have been removed from
	// sig.wanted, it is possible that another thread has received
	// a signal, has read from sig.wanted, is now updating sig.mask,
	// and has not yet woken up the processor thread. We need to wait
	// until all current signal deliveries have completed.
	for atomic.Load(&sig.delivering) != 0 {
		Gosched()
	}

	// Although WaitUntilIdle seems like the right name for this
	// function, the state we are looking for is sigReceiving, not
	// sigIdle.  The sigIdle state is really more like sigProcessing.
	for atomic.Load(&sig.state) != sigReceiving {
		Gosched()
	}
}

// Must only be called from a single goroutine at a time.
//go:linkname signal_enable os/signal.signal_enable
func signal_enable(s uint32) {
	if !sig.inuse {
		// This is the first call to signal_enable. Initialize.
		sig.inuse = true // enable reception of signals; cannot disable
		if GOOS == "darwin" || GOOS == "ios" {
			sigNoteSetup(&sig.note)
		} else {
			noteclear(&sig.note)
		}
	}

	if s >= uint32(len(sig.wanted)*32) {
		return
	}

	w := sig.wanted[s/32]
	w |= 1 << (s & 31)
	atomic.Store(&sig.wanted[s/32], w)

	i := sig.ignored[s/32]
	i &^= 1 << (s & 31)
	atomic.Store(&sig.ignored[s/32], i)

	sigenable(s)
}

// Must only be called from a single goroutine at a time.
//go:linkname signal_disable os/signal.signal_disable
func signal_disable(s uint32) {
	if s >= uint32(len(sig.wanted)*32) {
		return
	}
	sigdisable(s)

	w := sig.wanted[s/32]
	w &^= 1 << (s & 31)
	atomic.Store(&sig.wanted[s/32], w)
}

// Must only be called from a single goroutine at a time.
//go:linkname signal_ignore os/signal.signal_ignore
func signal_ignore(s uint32) {
	if s >= uint32(len(sig.wanted)*32) {
		return
	}
	sigignore(s)

	w := sig.wanted[s/32]
	w &^= 1 << (s & 31)
	atomic.Store(&sig.wanted[s/32], w)

	i := sig.ignored[s/32]
	i |= 1 << (s & 31)
	atomic.Store(&sig.ignored[s/32], i)
}

// sigInitIgnored marks the signal as already ignored. This is called at
// program start by initsig. In a shared library initsig is called by
// libpreinit, so the runtime may not be initialized yet.
//go:nosplit
func sigInitIgnored(s uint32) {
	i := sig.ignored[s/32]
	i |= 1 << (s & 31)
	atomic.Store(&sig.ignored[s/32], i)
}

// Checked by signal handlers.
//go:linkname signal_ignored os/signal.signal_ignored
func signal_ignored(s uint32) bool {
	i := atomic.Load(&sig.ignored[s/32])
	return i&(1<<(s&31)) != 0
}
<|endoftext|>


<commit_before>// Copyright ©2018 The Gonum 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 hyperdual_test

import (
	"fmt"

	"gonum.org/v1/gonum/num/hyperdual"
)

func Example_Number_fike() {
	// Calculate the value and first and second derivatives
	// of the function e^x/(sqrt(sin(x)^3 + cos(x)^3)).
	fn := func(x hyperdual.Number) hyperdual.Number {
		return hyperdual.Mul(
			hyperdual.Exp(x),
			hyperdual.Inv(hyperdual.Sqrt(
				hyperdual.Add(
					hyperdual.PowReal(hyperdual.Sin(x), 3),
					hyperdual.PowReal(hyperdual.Cos(x), 3)))))
	}

	v := fn(hyperdual.Number{Real: 1.5, E1mag: 1, E2mag: 1})
	fmt.Printf("v=%.4f\n", v)
	fmt.Printf("fn(1.5)=%.4f\nfn'(1.5)=%.4f\nfn''(1.5)=%.4f\n", v.Real, v.E1mag, v.E1E2mag)

	// Output:
	//
	// v=(4.4978+4.0534ϵ₁+4.0534ϵ₂+9.4631ϵ₁ϵ₂)
	// fn(1.5)=4.4978
	// fn'(1.5)=4.0534
	// fn''(1.5)=9.4631
}
<commit_msg>num/hyperdual: fix Number example<commit_after>// Copyright ©2018 The Gonum 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 hyperdual_test

import (
	"fmt"

	"gonum.org/v1/gonum/num/hyperdual"
)

func ExampleNumber_fike() {
	// Calculate the value and first and second derivatives
	// of the function e^x/(sqrt(sin(x)^3 + cos(x)^3)).
	fn := func(x hyperdual.Number) hyperdual.Number {
		return hyperdual.Mul(
			hyperdual.Exp(x),
			hyperdual.Inv(hyperdual.Sqrt(
				hyperdual.Add(
					hyperdual.PowReal(hyperdual.Sin(x), 3),
					hyperdual.PowReal(hyperdual.Cos(x), 3)))))
	}

	v := fn(hyperdual.Number{Real: 1.5, E1mag: 1, E2mag: 1})
	fmt.Printf("v=%.4f\n", v)
	fmt.Printf("fn(1.5)=%.4f\nfn'(1.5)=%.4f\nfn''(1.5)=%.4f\n", v.Real, v.E1mag, v.E1E2mag)

	// Output:
	//
	// v=(4.4978+4.0534ϵ₁+4.0534ϵ₂+9.4631ϵ₁ϵ₂)
	// fn(1.5)=4.4978
	// fn'(1.5)=4.0534
	// fn''(1.5)=9.4631
}
<|endoftext|>


<commit_before>package train

import "github.com/galeone/tfgo/core/example"

// this arr support [][]byte []float32 []int32
// it likes this method in python
// tf.train.BytesList tf.train.Int64List tf.train.FloatList

func StringToFeature(value []string) (exampleFeature *example.Feature) {
	bytesArr :=make([][]byte,0)
	for _,s:=range value{
		bytesArr = append(bytesArr,[]byte(s))
	}
	bytesList := example.BytesList{Value: bytesArr}
	featureBytesList := example.Feature_BytesList{BytesList: &bytesList}
	exampleFeature = &example.Feature{Kind: &featureBytesList}
	return
}

func Float32ToFeature(value []float32) (exampleFeature *example.Feature) {
	floatList := example.FloatList{Value: value}
	featureFloatList := example.Feature_FloatList{FloatList: &floatList}
	exampleFeature = &example.Feature{Kind: &featureFloatList}
	return
}

func Int32ToFeature(value []int64) (exampleFeature *example.Feature) {
	intList := example.Int64List{Value: value}
	featureFloatList := example.Feature_Int64List{Int64List: &intList}
	exampleFeature = &example.Feature{Kind: &featureFloatList}
	return
}<commit_msg>modify int32 to int64<commit_after>package train

import "github.com/galeone/tfgo/core/example"

// this arr support [][]byte []float32 []int32
// it likes this method in python
// tf.train.BytesList tf.train.Int64List tf.train.FloatList

func StringToFeature(value []string) (exampleFeature *example.Feature) {
	bytesArr :=make([][]byte,0)
	for _,s:=range value{
		bytesArr = append(bytesArr,[]byte(s))
	}
	bytesList := example.BytesList{Value: bytesArr}
	featureBytesList := example.Feature_BytesList{BytesList: &bytesList}
	exampleFeature = &example.Feature{Kind: &featureBytesList}
	return
}

func Float32ToFeature(value []float32) (exampleFeature *example.Feature) {
	floatList := example.FloatList{Value: value}
	featureFloatList := example.Feature_FloatList{FloatList: &floatList}
	exampleFeature = &example.Feature{Kind: &featureFloatList}
	return
}

func Int64ToFeature(value []int64) (exampleFeature *example.Feature) {
	intList := example.Int64List{Value: value}
	featureFloatList := example.Feature_Int64List{Int64List: &intList}
	exampleFeature = &example.Feature{Kind: &featureFloatList}
	return
}<|endoftext|>


<commit_before>package smpp34

import (
	"crypto/tls"
	"time"
)

type Transceiver struct {
	Smpp
	eLTicker     *time.Ticker // Enquire Link ticker
	eLCheckTimer *time.Timer  // Enquire Link Check timer
	eLDuration   int          // Enquire Link Duration
	Err          error        // Errors generated in go routines that lead to conn close
}

// NewTransceiver creates and initializes a new Transceiver.
// The eli parameter is for EnquireLink interval, in seconds.
func NewTransceiver(host string, port int, eli int, bindParams Params) (*Transceiver, error) {
	return newTransceiver(host, port, eli, bindParams, nil)
}

// NewTransceiver creates and initializes a new Transceiver using TLS.
// The eli parameter is for EnquireLink interval, in seconds.
func NewTransceiverTLS(host string, port int, eli int, bindParams Params, config *tls.Config) (*Transceiver, error) {
	if config == nil {
		config = &tls.Config{}
	}
	return newTransceiver(host, port, eli, bindParams, config)
}

// eli = EnquireLink Interval in Seconds
func newTransceiver(host string, port int, eli int, bindParams Params, config *tls.Config) (*Transceiver, error) {
	trx := &Transceiver{}
	var err error
	if config == nil {
		err = trx.Connect(host, port)
	} else {
		err = trx.ConnectTLS(host, port, config)
	}
	if err != nil {
		return nil, err
	}

	sysId := bindParams[SYSTEM_ID].(string)
	pass := bindParams[PASSWORD].(string)

	if err := trx.Bind(sysId, pass, &bindParams); err != nil {
		return nil, err
	}

	// EnquireLinks should not be less 10seconds
	if eli < 10 {
		eli = 10
	}

	trx.eLDuration = eli

	go trx.startEnquireLink(eli)

	return trx, nil
}

func (t *Transceiver) Bind(system_id string, password string, params *Params) error {
	pdu, err := t.Smpp.Bind(BIND_TRANSCEIVER, system_id, password, params)
	if err := t.Write(pdu); err != nil {
		return err
	}

	// If BindResp NOT received in 5secs close connection
	go t.bindCheck()

	// Read (blocking)
	pdu, err = t.Smpp.Read()

	if err != nil {
		return err
	}

	if pdu.GetHeader().Id != BIND_TRANSCEIVER_RESP {
		return SmppBindRespErr
	}

	if !pdu.Ok() {
		return SmppBindAuthErr("Bind auth failed. " + pdu.GetHeader().Status.Error())
	}

	t.Bound = true

	return nil
}

func (t *Transceiver) SubmitSm(source_addr, destination_addr, short_message string, params *Params) (seq uint32, err error) {
	p, err := t.Smpp.SubmitSm(source_addr, destination_addr, short_message, params)

	if err != nil {
		return 0, err
	}

	if err := t.Write(p); err != nil {
		return 0, err
	}

	return p.GetHeader().Sequence, nil
}

func (t *Transceiver) DeliverSmResp(seq uint32, status CMDStatus) error {
	p, err := t.Smpp.DeliverSmResp(seq, status)

	if err != nil {
		return err
	}

	if err := t.Write(p); err != nil {
		return err
	}

	return nil
}

func (t *Transceiver) Unbind() error {
	p, _ := t.Smpp.Unbind()

	if err := t.Write(p); err != nil {
		return err
	}

	return nil
}

func (t *Transceiver) UnbindResp(seq uint32) error {
	p, _ := t.Smpp.UnbindResp(seq)

	if err := t.Write(p); err != nil {
		return err
	}

	t.Bound = false

	return nil
}

func (t *Transceiver) GenericNack(seq uint32, status CMDStatus) error {
	p, _ := t.Smpp.GenericNack(seq, status)

	if err := t.Write(p); err != nil {
		return err
	}

	return nil
}

func (t *Transceiver) bindCheck() {
	// Block
	<-time.After(time.Duration(5 * time.Second))
	if !t.Bound {
		// send error to t.err? So it can be read before closing.
		t.Err = SmppBindRespErr
		t.Close()
	}
}

func (t *Transceiver) startEnquireLink(eli int) {
	t.eLTicker = time.NewTicker(time.Duration(eli) * time.Second)
	// check delay is half the time of enquire link intervel
	d := time.Duration(eli/2) * time.Second
	t.eLCheckTimer = time.NewTimer(d)
	t.eLCheckTimer.Stop()

	for {
		select {
		case <-t.eLTicker.C:

			p, _ := t.EnquireLink()
			if err := t.Write(p); err != nil {
				t.Err = SmppELWriteErr
				t.Close()
				return
			}

			t.eLCheckTimer.Reset(d)
		case <-t.eLCheckTimer.C:
			t.Err = SmppELRespErr
			t.Close()
			return
		}
	}
}

func (t *Transceiver) Read() (Pdu, error) {
	pdu, err := t.Smpp.Read()
	if err != nil {
		if _, ok := err.(PduCmdIdErr); ok {
			// Invalid PDU Command ID, should send back GenericNack
			t.GenericNack(uint32(0), ESME_RINVCMDID)
		} else if SmppPduLenErr == err {
			// Invalid PDU, PDU read or Len error
			t.GenericNack(uint32(0), ESME_RINVCMDLEN)
		}

		return nil, err
	}

	switch pdu.GetHeader().Id {
	case SUBMIT_SM_RESP, DELIVER_SM:
		return pdu, nil
	case ENQUIRE_LINK:
		p, _ := t.Smpp.EnquireLinkResp(pdu.GetHeader().Sequence)

		if err := t.Write(p); err != nil {
			return nil, err
		}
	case ENQUIRE_LINK_RESP:
		// Reset EnquireLink Check
		t.eLCheckTimer.Reset(time.Duration(t.eLDuration) * time.Second)
	case UNBIND:
		t.UnbindResp(pdu.GetHeader().Sequence)
		t.Close()
	default:
		// Should not have received these PDUs on a TRx bind
		return nil, SmppPduErr
	}

	return pdu, nil
}

func (t *Transceiver) Close() {
	// Check timers exists incase we Close() before timers are created
	if t.eLCheckTimer != nil {
		t.eLCheckTimer.Stop()
	}

	if t.eLTicker != nil {
		t.eLTicker.Stop()
	}

	t.Smpp.Close()
}

func (t *Transceiver) Write(p Pdu) error {
	err := t.Smpp.Write(p)

	return err
}
<commit_msg>add public access to eLDuration and startEnquireLink in transceiver;<commit_after>package smpp34

import (
	"crypto/tls"
	"time"
)

type Transceiver struct {
	Smpp
	eLTicker     *time.Ticker // Enquire Link ticker
	eLCheckTimer *time.Timer  // Enquire Link Check timer
	eLDuration   int          // Enquire Link Duration
	Err          error        // Errors generated in go routines that lead to conn close
}

func (t *Transceiver) ELDuration(v int) { t.eLDuration = v }

// NewTransceiver creates and initializes a new Transceiver.
// The eli parameter is for EnquireLink interval, in seconds.
func NewTransceiver(host string, port int, eli int, bindParams Params) (*Transceiver, error) {
	return newTransceiver(host, port, eli, bindParams, nil)
}

// NewTransceiver creates and initializes a new Transceiver using TLS.
// The eli parameter is for EnquireLink interval, in seconds.
func NewTransceiverTLS(host string, port int, eli int, bindParams Params, config *tls.Config) (*Transceiver, error) {
	if config == nil {
		config = &tls.Config{}
	}
	return newTransceiver(host, port, eli, bindParams, config)
}

// eli = EnquireLink Interval in Seconds
func newTransceiver(host string, port int, eli int, bindParams Params, config *tls.Config) (*Transceiver, error) {
	trx := &Transceiver{}
	var err error
	if config == nil {
		err = trx.Connect(host, port)
	} else {
		err = trx.ConnectTLS(host, port, config)
	}
	if err != nil {
		return nil, err
	}

	sysId := bindParams[SYSTEM_ID].(string)
	pass := bindParams[PASSWORD].(string)

	if err := trx.Bind(sysId, pass, &bindParams); err != nil {
		return nil, err
	}

	// EnquireLinks should not be less 10seconds
	if eli < 10 {
		eli = 10
	}

	trx.eLDuration = eli

	go trx.startEnquireLink(eli)

	return trx, nil
}

func (t *Transceiver) Bind(system_id string, password string, params *Params) error {
	pdu, err := t.Smpp.Bind(BIND_TRANSCEIVER, system_id, password, params)
	if err := t.Write(pdu); err != nil {
		return err
	}

	// If BindResp NOT received in 5secs close connection
	go t.bindCheck()

	// Read (blocking)
	pdu, err = t.Smpp.Read()

	if err != nil {
		return err
	}

	if pdu.GetHeader().Id != BIND_TRANSCEIVER_RESP {
		return SmppBindRespErr
	}

	if !pdu.Ok() {
		return SmppBindAuthErr("Bind auth failed. " + pdu.GetHeader().Status.Error())
	}

	t.Bound = true

	return nil
}

func (t *Transceiver) SubmitSm(source_addr, destination_addr, short_message string, params *Params) (seq uint32, err error) {
	p, err := t.Smpp.SubmitSm(source_addr, destination_addr, short_message, params)

	if err != nil {
		return 0, err
	}

	if err := t.Write(p); err != nil {
		return 0, err
	}

	return p.GetHeader().Sequence, nil
}

func (t *Transceiver) DeliverSmResp(seq uint32, status CMDStatus) error {
	p, err := t.Smpp.DeliverSmResp(seq, status)

	if err != nil {
		return err
	}

	if err := t.Write(p); err != nil {
		return err
	}

	return nil
}

func (t *Transceiver) Unbind() error {
	p, _ := t.Smpp.Unbind()

	if err := t.Write(p); err != nil {
		return err
	}

	return nil
}

func (t *Transceiver) UnbindResp(seq uint32) error {
	p, _ := t.Smpp.UnbindResp(seq)

	if err := t.Write(p); err != nil {
		return err
	}

	t.Bound = false

	return nil
}

func (t *Transceiver) GenericNack(seq uint32, status CMDStatus) error {
	p, _ := t.Smpp.GenericNack(seq, status)

	if err := t.Write(p); err != nil {
		return err
	}

	return nil
}

func (t *Transceiver) bindCheck() {
	// Block
	<-time.After(time.Duration(5 * time.Second))
	if !t.Bound {
		// send error to t.err? So it can be read before closing.
		t.Err = SmppBindRespErr
		t.Close()
	}
}

func (t *Transceiver) StartEnquireLink(eli int) { t.startEnquireLink(eli) }
func (t *Transceiver) startEnquireLink(eli int) {
	t.eLTicker = time.NewTicker(time.Duration(eli) * time.Second)
	// check delay is half the time of enquire link intervel
	d := time.Duration(eli/2) * time.Second
	t.eLCheckTimer = time.NewTimer(d)
	t.eLCheckTimer.Stop()

	for {
		select {
		case <-t.eLTicker.C:

			p, _ := t.EnquireLink()
			if err := t.Write(p); err != nil {
				t.Err = SmppELWriteErr
				t.Close()
				return
			}

			t.eLCheckTimer.Reset(d)
		case <-t.eLCheckTimer.C:
			t.Err = SmppELRespErr
			t.Close()
			return
		}
	}
}

func (t *Transceiver) Read() (Pdu, error) {
	pdu, err := t.Smpp.Read()
	if err != nil {
		if _, ok := err.(PduCmdIdErr); ok {
			// Invalid PDU Command ID, should send back GenericNack
			t.GenericNack(uint32(0), ESME_RINVCMDID)
		} else if SmppPduLenErr == err {
			// Invalid PDU, PDU read or Len error
			t.GenericNack(uint32(0), ESME_RINVCMDLEN)
		}

		return nil, err
	}

	switch pdu.GetHeader().Id {
	case SUBMIT_SM_RESP, DELIVER_SM:
		return pdu, nil
	case ENQUIRE_LINK:
		p, _ := t.Smpp.EnquireLinkResp(pdu.GetHeader().Sequence)

		if err := t.Write(p); err != nil {
			return nil, err
		}
	case ENQUIRE_LINK_RESP:
		// Reset EnquireLink Check
		t.eLCheckTimer.Reset(time.Duration(t.eLDuration) * time.Second)
	case UNBIND:
		t.UnbindResp(pdu.GetHeader().Sequence)
		t.Close()
	default:
		// Should not have received these PDUs on a TRx bind
		return nil, SmppPduErr
	}

	return pdu, nil
}

func (t *Transceiver) Close() {
	// Check timers exists incase we Close() before timers are created
	if t.eLCheckTimer != nil {
		t.eLCheckTimer.Stop()
	}

	if t.eLTicker != nil {
		t.eLTicker.Stop()
	}

	t.Smpp.Close()
}

func (t *Transceiver) Write(p Pdu) error {
	err := t.Smpp.Write(p)

	return err
}
<|endoftext|>


<commit_before>package triego

import (
	"testing"
	/*"fmt"*/
	"os"
	"bufio"
	"io"
)

func Test_trieFindsWords(t *testing.T) {
	rootTrie := NewTrie()

	// manually appending two short
	// words to make sure test is
	// exclusively run against
	// the find function
	//
	// words added: cat, dog

	// dog
	tr := NewTrie()
	tr.isRoot = false
	tr.Parent = rootTrie
	tr.C = 'd'

	rootTrie.Children['d'] = tr

	tr1 := NewTrie()
	tr1.isRoot = false
	tr1.Parent = tr
	tr1.C = 'o'
	tr.Children['o'] = tr1

	tr2 := NewTrie()
	tr2.isRoot = false
	tr2.Parent = tr1
	tr2.C = 'g'
	tr2.IsWord = true
	tr1.Children['g'] = tr2

	// cat
	tr3 := NewTrie()
	tr3.isRoot = false
	tr3.Parent = rootTrie
	tr3.C = 'c'

	rootTrie.Children['c'] = tr3

	tr4 := NewTrie()
	tr4.isRoot = false
	tr4.Parent = tr3
	tr4.C = 'a'
	tr3.Children['a'] = tr4

	tr5 := NewTrie()
	tr5.isRoot = false
	tr5.Parent = tr4
	tr5.C = 't'
	tr5.IsWord = true
	tr4.Children['t'] = tr5

	if rootTrie.HasWord("dog") == false {
		t.Errorf("Finding word 'dog' in trie fails")
	}

	if rootTrie.HasWord("cat") == false {
		t.Errorf("Finding word 'cat' in trie fails")
	}

	if rootTrie.HasWord("foo") == true {
		t.Errorf("Finding word 'foo' in trie unexpectedly succeeds")
	}

	var i int = 0
	countTries(rootTrie, &i)
	if i != 7 {
		t.Fatalf("Expected 7 nodes, got %d", i)
	}
}

/*
 * A utility function to make sure
 * node append workd properly for our trie
 */
func countTries(trie *Trie, i *int) {
	if len(trie.Children) == 0 {
		*i = *i + 1
		return
	}
	for _, v := range trie.Children {
		countTries(v, i)
	}

	*i = *i + 1
}

type word_test struct {
	w string
	out bool
}

var testWords = []word_test{
	{"testWord1", true},
	{"testWord2", true},
	{"nonExisting", false},
}

func Test_trieAppendsWords(t *testing.T) {
	rootTrie := NewTrie()

	for _, v := range testWords {
		if v.out == true {
			rootTrie.AppendWord(v.w)
		}
	}

	for _, v := range testWords {
		if rootTrie.HasWord(v.w) != v.out {
			t.Errorf("Finding word '%s' in trie fails", v.w)
		}
	}

	var i int = 0
	countTries(rootTrie, &i)
	if i != 11 {
		t.Fatalf("Expected 11 nodes, got %d", i)
	}

	words := rootTrie.Words()
	for _, word := range words {
		found := false
		for _, v := range testWords {
			if word == v.w && v.out == true {
				found = true
				break
			}
		}

		if !found {
			t.Fatalf("Cannot find expected words in the list of words in the trie: '%s'", word)
		}
	}
}

func Test_heavyHasWords(t *testing.T) {
	rootTrie := NewTrie()

	for _, v := range country_names {
		rootTrie.AppendWord(v)
		if !rootTrie.HasWord(v) {
			t.Errorf("Cannot find appended word %s", v)
		}
	}

	words := rootTrie.Words()
	for _, w := range country_names {
		found := false
		for _, word := range words {
			if w == word {
				found = true
				break
			}
		}
		if !found {
			t.Logf("Cannot find word %s in trie", w)
			t.Log("Trie is:")
			t.Log(words)
			t.FailNow()
		}
	}
}

type node_count_test struct {
	words          []string
    expected_count int
}

var node_count_tests = []node_count_test{
    { []string{ "a", "aaa", "bb", "bbb"}, 7},
    { []string{ "trie", "triego", "git"}, 10},
}

func Test_iteratesEachNode(t *testing.T) {

	for _, v := range node_count_tests {
		rootTrie := NewTrie()
		for _, word := range v.words {
			rootTrie.AppendWord(word)
		}

		buffer := make([]rune, 0, 21)
		rootTrie.EachNode(func(node *TrieNode, halt *bool) {
			buffer = append(buffer, node.Character())
		})

		if c := len(buffer); c != v.expected_count {
			t.Fatalf("Unexpected number of nodes: expected %d, got %d", v.expected_count, c)
		}
	}
}

func Benchmark_nodesAllocation(b *testing.B) {
	b.StopTimer()

	// building country name
	// source from file
	file, err := os.Open("/usr/share/dict/words")
	words := make([]string, 0)
	if err != nil {
		b.Log("Cannot open expected file /usr/share/dict/words. Skipping this benchmark.")
		b.SkipNow()
		return
	}
	reader := bufio.NewReader(file)
	for  {
		line, err := reader.ReadString('\n');
		if err == io.EOF {
			break
		}
		words = append(words, line[:len(line)-1])
	}

	b.Logf("Inserting %d words in the trie", b.N)

	rootTrie := NewTrie()

	b.ResetTimer()
	b.StartTimer()
	b.ReportAllocs()

	for i := 0; i < b.N; i++ {
		rootTrie.AppendWord(words[i % len(words)])
	}
}

/*
 * A few helper functions
 */
/*func printTrie(trie *Trie) {
	for _, v := range trie.Children {
		runes := make([]rune, 0)
		printTrie_(v, append(runes, v.C))
	}
}

func printTrie_(trie *Trie, runes []rune) {
	for _,v := range trie.Children {
		if v.IsWord {
			fmt.Println(string(append(runes, v.C)))
		}
		printTrie_(v, append(runes, v.C))
	}
}*/
<commit_msg>add word find benchmark as well<commit_after>package triego

import (
	"testing"
	/*"fmt"*/
	"os"
	"bufio"
	"io"
)

func Test_trieFindsWords(t *testing.T) {
	rootTrie := NewTrie()

	// manually appending two short
	// words to make sure test is
	// exclusively run against
	// the find function
	//
	// words added: cat, dog

	// dog
	tr := NewTrie()
	tr.isRoot = false
	tr.Parent = rootTrie
	tr.C = 'd'

	rootTrie.Children['d'] = tr

	tr1 := NewTrie()
	tr1.isRoot = false
	tr1.Parent = tr
	tr1.C = 'o'
	tr.Children['o'] = tr1

	tr2 := NewTrie()
	tr2.isRoot = false
	tr2.Parent = tr1
	tr2.C = 'g'
	tr2.IsWord = true
	tr1.Children['g'] = tr2

	// cat
	tr3 := NewTrie()
	tr3.isRoot = false
	tr3.Parent = rootTrie
	tr3.C = 'c'

	rootTrie.Children['c'] = tr3

	tr4 := NewTrie()
	tr4.isRoot = false
	tr4.Parent = tr3
	tr4.C = 'a'
	tr3.Children['a'] = tr4

	tr5 := NewTrie()
	tr5.isRoot = false
	tr5.Parent = tr4
	tr5.C = 't'
	tr5.IsWord = true
	tr4.Children['t'] = tr5

	if rootTrie.HasWord("dog") == false {
		t.Errorf("Finding word 'dog' in trie fails")
	}

	if rootTrie.HasWord("cat") == false {
		t.Errorf("Finding word 'cat' in trie fails")
	}

	if rootTrie.HasWord("foo") == true {
		t.Errorf("Finding word 'foo' in trie unexpectedly succeeds")
	}

	var i int = 0
	countTries(rootTrie, &i)
	if i != 7 {
		t.Fatalf("Expected 7 nodes, got %d", i)
	}
}

/*
 * A utility function to make sure
 * node append workd properly for our trie
 */
func countTries(trie *Trie, i *int) {
	if len(trie.Children) == 0 {
		*i = *i + 1
		return
	}
	for _, v := range trie.Children {
		countTries(v, i)
	}

	*i = *i + 1
}

type word_test struct {
	w string
	out bool
}

var testWords = []word_test{
	{"testWord1", true},
	{"testWord2", true},
	{"nonExisting", false},
}

func Test_trieAppendsWords(t *testing.T) {
	rootTrie := NewTrie()

	for _, v := range testWords {
		if v.out == true {
			rootTrie.AppendWord(v.w)
		}
	}

	for _, v := range testWords {
		if rootTrie.HasWord(v.w) != v.out {
			t.Errorf("Finding word '%s' in trie fails", v.w)
		}
	}

	var i int = 0
	countTries(rootTrie, &i)
	if i != 11 {
		t.Fatalf("Expected 11 nodes, got %d", i)
	}

	words := rootTrie.Words()
	for _, word := range words {
		found := false
		for _, v := range testWords {
			if word == v.w && v.out == true {
				found = true
				break
			}
		}

		if !found {
			t.Fatalf("Cannot find expected words in the list of words in the trie: '%s'", word)
		}
	}
}

func Test_heavyHasWords(t *testing.T) {
	rootTrie := NewTrie()

	for _, v := range country_names {
		rootTrie.AppendWord(v)
		if !rootTrie.HasWord(v) {
			t.Errorf("Cannot find appended word %s", v)
		}
	}

	words := rootTrie.Words()
	for _, w := range country_names {
		found := false
		for _, word := range words {
			if w == word {
				found = true
				break
			}
		}
		if !found {
			t.Logf("Cannot find word %s in trie", w)
			t.Log("Trie is:")
			t.Log(words)
			t.FailNow()
		}
	}
}

type node_count_test struct {
	words          []string
    expected_count int
}

var node_count_tests = []node_count_test{
    { []string{ "a", "aaa", "bb", "bbb"}, 7},
    { []string{ "trie", "triego", "git"}, 10},
}

func Test_iteratesEachNode(t *testing.T) {

	for _, v := range node_count_tests {
		rootTrie := NewTrie()
		for _, word := range v.words {
			rootTrie.AppendWord(word)
		}

		buffer := make([]rune, 0, 21)
		rootTrie.EachNode(func(node *TrieNode, halt *bool) {
			buffer = append(buffer, node.Character())
		})

		if c := len(buffer); c != v.expected_count {
			t.Fatalf("Unexpected number of nodes: expected %d, got %d", v.expected_count, c)
		}
	}
}

func Benchmark_nodesAllocation(b *testing.B) {
	b.StopTimer()

	// building country name
	// source from file
	file, err := os.Open("/usr/share/dict/words")
	words := make([]string, 0)
	if err != nil {
		b.Log("Cannot open expected file /usr/share/dict/words. Skipping this benchmark.")
		b.SkipNow()
		return
	}
	reader := bufio.NewReader(file)
	for  {
		line, err := reader.ReadString('\n');
		if err == io.EOF {
			break
		}
		words = append(words, line[:len(line)-1])
	}

	b.Logf("Inserting %d words in the trie", b.N)

	rootTrie := NewTrie()

	b.ResetTimer()
	b.StartTimer()
	b.ReportAllocs()

	for i := 0; i < b.N; i++ {
		rootTrie.AppendWord(words[i % len(words)])
	}
}

func Benchmark_wordFind(b *testing.B) {
	b.StopTimer()

	// building country name
	// source from file
	file, err := os.Open("/usr/share/dict/words")
	words := make([]string, 0)
	if err != nil {
		b.Log("Cannot open expected file /usr/share/dict/words. Skipping this benchmark.")
		b.SkipNow()
		return
	}
	reader := bufio.NewReader(file)
	for  {
		line, err := reader.ReadString('\n');
		if err == io.EOF {
			break
		}
		words = append(words, line[:len(line)-1])
	}

	b.Logf("Inserting %d words in the trie", b.N)

	rootTrie := NewTrie()

	for i := 0; i < b.N; i++ {
		rootTrie.AppendWord(words[i % len(words)])
	}

	b.ResetTimer()
	b.StartTimer()
	b.ReportAllocs()

	for i := 0; i < b.N; i++ {
		found := rootTrie.HasWord(words[i % len(words)])
		if found != true {
			b.Errorf("Unexpected: couldn't find word '%s'", words[i % len(words)])
		}
	}
}

/*
 * A few helper functions
 */
/*func printTrie(trie *Trie) {
	for _, v := range trie.Children {
		runes := make([]rune, 0)
		printTrie_(v, append(runes, v.C))
	}
}

func printTrie_(trie *Trie, runes []rune) {
	for _,v := range trie.Children {
		if v.IsWord {
			fmt.Println(string(append(runes, v.C)))
		}
		printTrie_(v, append(runes, v.C))
	}
}*/
<|endoftext|>


<commit_before>package melrose

import (
	"time"

	"github.com/emicklei/melrose/notify"
)

type Transformer interface {
	Transform(Sequence) Sequence
}

type Sequenceable interface {
	S() Sequence
}

type NoteConvertable interface {
	ToNote() Note
}

type Storable interface {
	Storex() string
}

type Indexable interface {
	At(i int) Sequenceable
}

type Nextable interface {
	Next() interface{}
}

type AudioDevice interface {
	// Per device specific commands
	Command(args []string) notify.Message

	// Play schedules all the notes on the timeline using a BPM (beats-per-minute).
	// Returns the end time of the last played Note.
	Play(seq Sequenceable, bpm float64, beginAt time.Time) (endingAt time.Time)
	Record(deviceID int, stopAfterInactivity time.Duration) (*Recording, error)
	Timeline() *Timeline
	SetEchoNotes(echo bool)
	Reset()
	Close()
}

type LoopController interface {
	Start()
	Stop()
	Reset()

	SetBPM(bpm float64)
	BPM() float64

	SetBIAB(biab int)
	BIAB() int

	Begin(l *Loop)
	End(l *Loop)

	BeatsAndBars() (int64, int64)
	Plan(bars int64, beats int64, seq Sequenceable)
}

type MapFunc func(seq Sequenceable) Sequenceable

// TODO experiment
type Mappeable interface {
	Map(m MapFunc) Mappeable
}

type Replaceable interface {
	// Returns a new value in which any occurrences of "from" are replaced by "to".
	Replaced(from, to Sequenceable) Sequenceable
}
<commit_msg>moved interface<commit_after>package melrose

import (
	"time"

	"github.com/emicklei/melrose/notify"
)

type Transformer interface {
	Transform(Sequence) Sequence
}

type Sequenceable interface {
	S() Sequence
}

type NoteConvertable interface {
	ToNote() Note
}

type Storable interface {
	Storex() string
}

type Indexable interface {
	At(i int) Sequenceable
}

type Nextable interface {
	Next() interface{}
}

type AudioDevice interface {
	// Per device specific commands
	Command(args []string) notify.Message

	// Play schedules all the notes on the timeline using a BPM (beats-per-minute).
	// Returns the end time of the last played Note.
	Play(seq Sequenceable, bpm float64, beginAt time.Time) (endingAt time.Time)
	Record(deviceID int, stopAfterInactivity time.Duration) (*Recording, error)
	Timeline() *Timeline
	SetEchoNotes(echo bool)
	Reset()
	Close()
}

type LoopController interface {
	Start()
	Stop()
	Reset()

	SetBPM(bpm float64)
	BPM() float64

	SetBIAB(biab int)
	BIAB() int

	Begin(l *Loop)
	End(l *Loop)

	BeatsAndBars() (int64, int64)
	Plan(bars int64, beats int64, seq Sequenceable)
}

type MapFunc func(seq Sequenceable) Sequenceable

// TODO experiment
type Mappeable interface {
	Map(m MapFunc) Mappeable
}

type Replaceable interface {
	// Returns a new value in which any occurrences of "from" are replaced by "to".
	Replaced(from, to Sequenceable) Sequenceable
}

type Valueable interface {
	Value() interface{}
}
<|endoftext|>


<commit_before>package gocassa

import (
	"time"
)

// The Connection interface only exists because one can not connect to a keyspace if it does not exist, thus having a Create on KeySpace is not possible.
// Use ConnectToKeySpace to acquire an instance of KeySpace.
type Connection interface {
	CreateKeySpace(name string) error
	DropKeySpace(name string) error
	KeySpace(name string) KeySpace
	Batcher
}

type KeySpace interface {
	OneToOneTable(tableName, id string, row interface{}) OneToOneTable
	OneToManyTable(tableName, fieldToIndexBy, uniqueKey string, row interface{}) OneToManyTable
	TimeSeriesTable(tableName, timeField, uniqueKey string, bucketSize time.Duration, row interface{}) TimeSeriesTable
	TimeSeriesBTable(tableName, fieldToIndexByField, timeField, uniqueKey string, bucketSize time.Duration, row interface{}) TimeSeriesBTable
	Table(tableName string, row interface{}, keys Keys) Table
	DebugMode(bool)
	Batcher
}

//
// OneToOne recipe
//

type OneToOneWriter interface {
	SetWithOptions(v interface{}, opts Options) error
	Set(v interface{}) error
	UpdateWithOptions(id interface{}, m map[string]interface{}, opts Options) error
	Update(id interface{}, m map[string]interface{}) error
	Delete(id interface{}) error
}

type OneToOneBatchWriter interface {
	SetWithOptions(v interface{}, opts Options) WriteOp
	Set(v interface{}) WriteOp
	UpdateWithOptions(id interface{}, m map[string]interface{}, opts Options) WriteOp
	Update(id interface{}, m map[string]interface{}) WriteOp
	Delete(id interface{}) WriteOp
	Batcher
}

type OneToOneReader interface {
	Read(id, pointer interface{}) error
	MultiRead(ids []interface{}, pointerToASlice interface{}) error
}

// Simple CRUD interface. You can do CRUD by Id.
type OneToOneTable interface {
	OneToOneReader
	OneToOneWriter
	Batched() OneToOneBatchWriter
	TableChanger
	Batcher
}

//
// OneToMany recipe
//

// OneToMany lets you list rows based on a field equality, eg. 'list all sales where seller id = v'.
type OneToManyTable interface {
	SetWithOptions(v interface{}, opts Options) error
	Set(v interface{}) error
	UpdateWithOptions(v, id interface{}, m map[string]interface{}, opts Options) error
	Update(v, id interface{}, m map[string]interface{}) error
	Delete(v, id interface{}) error
	DeleteAll(v interface{}) error
	List(v, startId interface{}, limit int, pointerToASlice interface{}) error
	Read(v, id, pointer interface{}) error
	MultiRead(id interface{}, ids []interface{}, pointerToASlice interface{}) error
	Batcher
	TableChanger
}

//
// TimeSeries recipe
//

// TimeSeries lets you list rows which have a field value between two date ranges.
type TimeSeriesTable interface {
	// timeField and idField must be present
	SetWithOptions(v interface{}, opts Options) error
	Set(v interface{}) error
	UpdateWithOptions(timeStamp time.Time, id interface{}, m map[string]interface{}, opts Options) error
	Update(timeStamp time.Time, id interface{}, m map[string]interface{}) error
	List(start, end time.Time, pointerToASlice interface{}) error
	Read(timeStamp time.Time, id, pointer interface{}) error
	Delete(timeStamp time.Time, id interface{}) error
	Batcher
	TableChanger
}

//
// TimeSeries B recipe
//

// TimeSeriesB is a cross between TimeSeries and OneToMany tables.
type TimeSeriesBTable interface {
	// timeField and idField must be present
	SetWithOptions(v interface{}, opts Options) error
	Set(v interface{}) error
	UpdateWithOptions(v interface{}, timeStamp time.Time, id interface{}, m map[string]interface{}, opts Options) error
	Update(v interface{}, timeStamp time.Time, id interface{}, m map[string]interface{}) error
	List(v interface{}, start, end time.Time, pointerToASlice interface{}) error
	Read(v interface{}, timeStamp time.Time, id, pointer interface{}) error
	Delete(v interface{}, timeStamp time.Time, id interface{}) error
	Batcher
	TableChanger
}

//
// Raw CQL
//

// A Query is a subset of a Table intended to be read
type Query interface {
	Read(pointerToASlice interface{}) error
	ReadOne(pointer interface{}) error
	Limit(int) Query
}

// A Filter is a subset of a Table, filtered by Relations.
// You can do writes or reads on a filter.
type Filter interface {
	// Selection modifiers
	Query() Query
	// Partial update.
	Update(m map[string]interface{}) WriteOp // Probably this is danger zone (can't be implemented efficiently) on a selection with more than 1 document
	UpdateWithOptions(m map[string]interface{}, opts Options) WriteOp
	Delete() WriteOp
}

type Keys struct {
	PartitionKeys     []string
	ClusteringColumns []string
}

type Batcher interface{
	// Send writes to Cassandra in one Go, to spare network trips
	Together(...WriteOp) error
	// Make these writes atomic - caution, might make your writes very slow!
	Atomically(...WriteOp) error
}

type WriteOp interface {
	// Run this write operation alone
	Commit() error
}

// Danger zone! Do not use this interface unless you really know what you are doing
type TableChanger interface {
	Create() WriteOp
	CreateStatement() (string, error)
	Recreate() WriteOp
	//Drop() error
	//CreateIfDoesNotExist() error
}

type Table interface {
	// Set Inserts, or Replaces your row with the supplied struct. Be aware that what is not in your struct
	// will be deleted. To only overwrite some of the fields, use Query.Update.
	Set(v interface{}) WriteOp
	SetWithOptions(v interface{}, opts Options) WriteOp
	Where(relations ...Relation) Filter // Because we provide selections
	TableChanger
}

type QueryExecutor interface {
	Query(stmt string, params ...interface{}) ([]map[string]interface{}, error)
	Execute(stmt string, params ...interface{}) error
}
<commit_msg>Save game<commit_after>package gocassa

import (
	"time"
)

// The Connection interface only exists because one can not connect to a keyspace if it does not exist, thus having a Create on KeySpace is not possible.
// Use ConnectToKeySpace to acquire an instance of KeySpace.
type Connection interface {
	CreateKeySpace(name string) error
	DropKeySpace(name string) error
	KeySpace(name string) KeySpace
	Batcher
}

type KeySpace interface {
	OneToOneTable(tableName, id string, row interface{}) OneToOneTable
	OneToManyTable(tableName, fieldToIndexBy, uniqueKey string, row interface{}) OneToManyTable
	TimeSeriesTable(tableName, timeField, uniqueKey string, bucketSize time.Duration, row interface{}) TimeSeriesTable
	TimeSeriesBTable(tableName, fieldToIndexByField, timeField, uniqueKey string, bucketSize time.Duration, row interface{}) TimeSeriesBTable
	Table(tableName string, row interface{}, keys Keys) Table
	DebugMode(bool)
	Batched
}

type KeySpaceBatched interface {

}

//
// OneToOne recipe
//

// Simple CRUD interface. You can do CRUD by Id.
type OneToOneWriter interface {
	SetWithOptions(v interface{}, opts Options) error
	Set(v interface{}) error
	UpdateWithOptions(id interface{}, m map[string]interface{}, opts Options) error
	Update(id interface{}, m map[string]interface{}) error
	Delete(id interface{}) error
}

type OneToOneReader interface {
	Read(id, pointer interface{}) error
	MultiRead(ids []interface{}, pointerToASlice interface{}) error
}

type OneToOneTable interface {
	OneToOneReader
	Batched() OneToOneTableBatched
}

type OneToOneTableBatched interface {
	OneToOneWriter
	Batcher
}

//
// OneToMany recipe
//

// OneToMany lets you list rows based on a field equality, eg. 'list all sales where seller id = v'.
type OneToManyTable interface {
	SetWithOptions(v interface{}, opts Options) error
	Set(v interface{}) error
	UpdateWithOptions(v, id interface{}, m map[string]interface{}, opts Options) error
	Update(v, id interface{}, m map[string]interface{}) error
	Delete(v, id interface{}) error
	DeleteAll(v interface{}) error
	List(v, startId interface{}, limit int, pointerToASlice interface{}) error
	Read(v, id, pointer interface{}) error
	MultiRead(id interface{}, ids []interface{}, pointerToASlice interface{}) error
	Batcher
	TableChanger
}

//
// TimeSeries recipe
//

// TimeSeries lets you list rows which have a field value between two date ranges.
type TimeSeriesTable interface {
	// timeField and idField must be present
	SetWithOptions(v interface{}, opts Options) error
	Set(v interface{}) error
	UpdateWithOptions(timeStamp time.Time, id interface{}, m map[string]interface{}, opts Options) error
	Update(timeStamp time.Time, id interface{}, m map[string]interface{}) error
	List(start, end time.Time, pointerToASlice interface{}) error
	Read(timeStamp time.Time, id, pointer interface{}) error
	Delete(timeStamp time.Time, id interface{}) error
	Batcher
	TableChanger
}

//
// TimeSeries B recipe
//

// TimeSeriesB is a cross between TimeSeries and OneToMany tables.
type TimeSeriesBTable interface {
	// timeField and idField must be present
	SetWithOptions(v interface{}, opts Options) error
	Set(v interface{}) error
	UpdateWithOptions(v interface{}, timeStamp time.Time, id interface{}, m map[string]interface{}, opts Options) error
	Update(v interface{}, timeStamp time.Time, id interface{}, m map[string]interface{}) error
	List(v interface{}, start, end time.Time, pointerToASlice interface{}) error
	Read(v interface{}, timeStamp time.Time, id, pointer interface{}) error
	Delete(v interface{}, timeStamp time.Time, id interface{}) error
	Batcher
	TableChanger
}

//
// Raw CQL
//

// A Query is a subset of a Table intended to be read
type Query interface {
	Read(pointerToASlice interface{}) error
	ReadOne(pointer interface{}) error
	Limit(int) Query
}

// A Filter is a subset of a Table, filtered by Relations.
// You can do writes or reads on a filter.
type Filter interface {
	// Selection modifiers
	Query() Query
	// Partial update.
	Update(m map[string]interface{}) error // Probably this is danger zone (can't be implemented efficiently) on a selectuinb with more than 1 document
	UpdateWithOptions(m map[string]interface{}, opts Options) error
	Delete() error
}

type Keys struct {
	PartitionKeys     []string
	ClusteringColumns []string
}

type Batcher interface{
	Start()
	Commit() error
}

// Danger zone! Do not use this interface unless you really know what you are doing
type TableChanger interface {
	Create() error
	CreateStatement() (string, error)
	Recreate() error
	//Drop() error
	//CreateIfDoesNotExist() error
}

type Table interface {
	// Set Inserts, or Replaces your row with the supplied struct. Be aware that what is not in your struct
	// will be deleted. To only overwrite some of the fields, use Query.Update.
	Set(v interface{}) error
	SetWithOptions(v interface{}, opts Options) error
	Where(relations ...Relation) Filter // Because we provide selections
	TableChanger
}

type QueryExecutor interface {
	Query(stmt string, params ...interface{}) ([]map[string]interface{}, error)
	Execute(stmt string, params ...interface{}) error
}
<|endoftext|>