<commit_before>package common

import (
	"errors"
	"fmt"
	"net/url"
	"os"
	"path"
	"strconv"
	"strings"
	"time"

	"github.com/Sirupsen/logrus"
	"gitlab.com/gitlab-org/gitlab-ci-multi-runner/helpers"
)

type GitStrategy int

const (
	GitClone GitStrategy = iota
	GitFetch
	GitNone
)

type BuildRuntimeState string

const (
	BuildRunStatePending      BuildRuntimeState = "pending"
	BuildRunRuntimeRunning                      = "running"
	BuildRunRuntimeFinished                     = "finished"
	BuildRunRuntimeCanceled                     = "canceled"
	BuildRunRuntimeTerminated                   = "terminated"
	BuildRunRuntimeTimedout                     = "timedout"
)

type BuildStage string

const (
	BuildStagePrepare           BuildStage = "prepare_script"
	BuildStageGetSources                   = "get_sources"
	BuildStageRestoreCache                 = "restore_cache"
	BuildStageDownloadArtifacts            = "download_artifacts"
	BuildStageUserScript                   = "build_script"
	BuildStageAfterScript                  = "after_script"
	BuildStageArchiveCache                 = "archive_cache"
	BuildStageUploadArtifacts              = "upload_artifacts"
)

type Build struct {
	GetBuildResponse `yaml:",inline"`

	Trace           BuildTrace
	SystemInterrupt chan os.Signal `json:"-" yaml:"-"`
	RootDir         string         `json:"-" yaml:"-"`
	BuildDir        string         `json:"-" yaml:"-"`
	CacheDir        string         `json:"-" yaml:"-"`
	Hostname        string         `json:"-" yaml:"-"`
	Runner          *RunnerConfig  `json:"runner"`
	ExecutorData    ExecutorData

	// Unique ID for all running builds on this runner
	RunnerID int `json:"runner_id"`

	// Unique ID for all running builds on this runner and this project
	ProjectRunnerID int `json:"project_runner_id"`

	CurrentStage BuildStage
	CurrentState BuildRuntimeState
}

func (b *Build) Log() *logrus.Entry {
	return b.Runner.Log().WithField("build", b.ID).WithField("project", b.ProjectID)
}

func (b *Build) ProjectUniqueName() string {
	return fmt.Sprintf("runner-%s-project-%d-concurrent-%d",
		b.Runner.ShortDescription(), b.ProjectID, b.ProjectRunnerID)
}

func (b *Build) ProjectSlug() (string, error) {
	url, err := url.Parse(b.RepoURL)
	if err != nil {
		return "", err
	}
	if url.Host == "" {
		return "", errors.New("only URI reference supported")
	}

	slug := url.Path
	slug = strings.TrimSuffix(slug, ".git")
	slug = path.Clean(slug)
	if slug == "." {
		return "", errors.New("invalid path")
	}
	if strings.Contains(slug, "..") {
		return "", errors.New("it doesn't look like a valid path")
	}
	return slug, nil
}

func (b *Build) ProjectUniqueDir(sharedDir bool) string {
	dir, err := b.ProjectSlug()
	if err != nil {
		dir = fmt.Sprintf("project-%d", b.ProjectID)
	}

	// for shared dirs path is constructed like this:
	// <some-path>/runner-short-id/concurrent-id/group-name/project-name/
	// ex.<some-path>/01234567/0/group/repo/
	if sharedDir {
		dir = path.Join(
			fmt.Sprintf("%s", b.Runner.ShortDescription()),
			fmt.Sprintf("%d", b.ProjectRunnerID),
			dir,
		)
	}
	return dir
}

func (b *Build) FullProjectDir() string {
	return helpers.ToSlash(b.BuildDir)
}

func (b *Build) StartBuild(rootDir, cacheDir string, sharedDir bool) {
	b.RootDir = rootDir
	b.BuildDir = path.Join(rootDir, b.ProjectUniqueDir(sharedDir))
	b.CacheDir = path.Join(cacheDir, b.ProjectUniqueDir(false))
}

func (b *Build) executeStage(buildStage BuildStage, executor Executor, abort chan interface{}) error {
	b.CurrentStage = buildStage

	shell := executor.Shell()
	if shell == nil {
		return errors.New("No shell defined")
	}

	script, err := GenerateShellScript(buildStage, *shell)
	if err != nil {
		return err
	}

	// Nothing to execute
	if script == "" {
		return nil
	}

	cmd := ExecutorCommand{
		Script: script,
		Abort:  abort,
	}

	switch buildStage {
	case BuildStageUserScript, BuildStageAfterScript: // use custom build environment
		cmd.Predefined = false
	default: // all other stages use a predefined build environment
		cmd.Predefined = true
	}

	return executor.Run(cmd)
}

func (b *Build) executeUploadArtifacts(state error, executor Executor, abort chan interface{}) (err error) {
	when, _ := b.Options.GetString("artifacts", "when")

	if state == nil {
		// Previous stages were successful
		if when == "" || when == "on_success" || when == "always" {
			err = b.executeStage(BuildStageUploadArtifacts, executor, abort)
		}
	} else {
		// Previous stage did fail
		if when == "on_failure" || when == "always" {
			err = b.executeStage(BuildStageUploadArtifacts, executor, abort)
		}
	}

	// Use previous error if set
	if state != nil {
		err = state
	}
	return
}

func (b *Build) executeScript(executor Executor, abort chan interface{}) error {
	// Prepare stage
	err := b.executeStage(BuildStagePrepare, executor, abort)

	if err == nil {
		err = b.executeStage(BuildStageGetSources, executor, abort)
	}
	if err == nil {
		err = b.executeStage(BuildStageDownloadArtifacts, executor, abort)
	}
	if err == nil {
		err = b.executeStage(BuildStageRestoreCache, executor, abort)
	}

	if err == nil {
		// Execute user build script (before_script + script)
		err = b.executeStage(BuildStageUserScript, executor, abort)

		// Execute after script (after_script)
		timeoutCh := make(chan interface{}, 1)
		timeout := time.AfterFunc(time.Minute*5, func() {
			close(timeoutCh)
		})
		b.executeStage(BuildStageAfterScript, executor, timeoutCh)
		timeout.Stop()
	}

	// Execute post script (cache store, artifacts upload)
	if err == nil {
		err = b.executeStage(BuildStageArchiveCache, executor, abort)
	}
	err = b.executeUploadArtifacts(err, executor, abort)
	return err
}

func (b *Build) run(executor Executor) (err error) {
	b.CurrentState = BuildRunRuntimeRunning

	buildTimeout := b.Timeout
	if buildTimeout <= 0 {
		buildTimeout = DefaultTimeout
	}

	buildFinish := make(chan error, 1)
	buildAbort := make(chan interface{})

	// Run build script
	go func() {
		buildFinish <- b.retryExecuteScript(executor, buildAbort)
	}()

	// Wait for signals: cancel, timeout, abort or finish
	b.Log().Debugln("Waiting for signals...")
	select {
	case <-b.Trace.Aborted():
		err = &BuildError{Inner: errors.New("canceled")}
		b.CurrentStage = BuildRunRuntimeCanceled

	case <-time.After(time.Duration(buildTimeout) * time.Second):
		err = &BuildError{Inner: fmt.Errorf("execution took longer than %v seconds", buildTimeout)}
		b.CurrentStage = BuildRunRuntimeTimedout

	case signal := <-b.SystemInterrupt:
		err = fmt.Errorf("aborted: %v", signal)
		b.CurrentStage = BuildRunRuntimeTerminated

	case err = <-buildFinish:
		b.CurrentState = BuildRunRuntimeFinished
		return err
	}

	b.Log().WithError(err).Debugln("Waiting for build to finish...")

	// Wait till we receive that build did finish
	for {
		select {
		case buildAbort <- true:
		case <-buildFinish:
			return err
		}
	}
}

func (b *Build) retryCreateExecutor(globalConfig *Config, provider ExecutorProvider, logger BuildLogger) (executor Executor, err error) {
	for tries := 0; tries < PreparationRetries; tries++ {
		executor = provider.Create()
		if executor == nil {
			err = errors.New("failed to create executor")
			return
		}

		err = executor.Prepare(globalConfig, b.Runner, b)
		if err == nil {
			break
		}
		if executor != nil {
			executor.Cleanup()
			executor = nil
		}
		if _, ok := err.(*BuildError); ok {
			break
		}

		logger.SoftErrorln("Preparation failed:", err)
		logger.Infoln("Will be retried in", PreparationRetryInterval, "...")
		time.Sleep(PreparationRetryInterval)
	}
	return
}

func (b *Build) Run(globalConfig *Config, trace BuildTrace) (err error) {
	var executor Executor

	logger := NewBuildLogger(trace, b.Log())
	logger.Println("Running with " + AppVersion.Line() + helpers.ANSI_RESET)

	b.CurrentState = BuildRunStatePending

	defer func() {
		if _, ok := err.(*BuildError); ok {
			logger.SoftErrorln("Build failed:", err)
			trace.Fail(err)
		} else if err != nil {
			logger.Errorln("Build failed (system failure):", err)
			trace.Fail(err)
		} else {
			logger.Infoln("Build succeeded")
			trace.Success()
		}
		if executor != nil {
			executor.Cleanup()
		}
	}()

	b.Trace = trace

	provider := GetExecutor(b.Runner.Executor)
	if provider == nil {
		return errors.New("executor not found")
	}

	executor, err = b.retryCreateExecutor(globalConfig, provider, logger)
	if err == nil {
		err = b.run(executor)
	}
	if executor != nil {
		executor.Finish(err)
	}
	return err
}

func (b *Build) String() string {
	return helpers.ToYAML(b)
}

func (b *Build) GetDefaultVariables() BuildVariables {
	return BuildVariables{
		{"CI", "true", true, true, false},
		{"CI_DEBUG_TRACE", "false", true, true, false},
		{"CI_BUILD_REF", b.Sha, true, true, false},
		{"CI_BUILD_BEFORE_SHA", b.BeforeSha, true, true, false},
		{"CI_BUILD_REF_NAME", b.RefName, true, true, false},
		{"CI_BUILD_ID", strconv.Itoa(b.ID), true, true, false},
		{"CI_BUILD_REPO", b.RepoURL, true, true, false},
		{"CI_BUILD_TOKEN", b.Token, true, true, false},
		{"CI_PROJECT_ID", strconv.Itoa(b.ProjectID), true, true, false},
		{"CI_PROJECT_DIR", b.FullProjectDir(), true, true, false},
		{"CI_SERVER", "yes", true, true, false},
		{"CI_SERVER_NAME", "GitLab CI", true, true, false},
		{"CI_SERVER_VERSION", "", true, true, false},
		{"CI_SERVER_REVISION", "", true, true, false},
		{"GITLAB_CI", "true", true, true, false},
	}
}

func (b *Build) GetAllVariables() (variables BuildVariables) {
	if b.Runner != nil {
		variables = append(variables, b.Runner.GetVariables()...)
	}
	variables = append(variables, b.GetDefaultVariables()...)
	variables = append(variables, b.Variables...)
	return variables.Expand()
}

func (b *Build) GetGitDepth() string {
	return b.GetAllVariables().Get("GIT_DEPTH")
}

func (b *Build) GetGitStrategy() GitStrategy {
	switch b.GetAllVariables().Get("GIT_STRATEGY") {
	case "clone":
		return GitClone

	case "fetch":
		return GitFetch

	case "none":
		return GitNone

	default:
		if b.AllowGitFetch {
			return GitFetch
		}

		return GitClone
	}
}

func (b *Build) IsDebugTraceEnabled() bool {
	trace, err := strconv.ParseBool(b.GetAllVariables().Get("CI_DEBUG_TRACE"))
	if err != nil {
		return false
	}

	return trace
}

func (b *Build) GetDockerAuthConfig() string {
	return b.GetAllVariables().Get("DOCKER_AUTH_CONFIG")
}
<commit_msg>refactored retries into retryExecuteShellScript method<commit_after>package common

import (
	"errors"
	"fmt"
	"net/url"
	"os"
	"path"
	"strconv"
	"strings"
	"time"

	"github.com/Sirupsen/logrus"
	"gitlab.com/gitlab-org/gitlab-ci-multi-runner/helpers"
)

type GitStrategy int

const (
	GitClone GitStrategy = iota
	GitFetch
	GitNone
)

type BuildRuntimeState string

const (
	BuildRunStatePending      BuildRuntimeState = "pending"
	BuildRunRuntimeRunning                      = "running"
	BuildRunRuntimeFinished                     = "finished"
	BuildRunRuntimeCanceled                     = "canceled"
	BuildRunRuntimeTerminated                   = "terminated"
	BuildRunRuntimeTimedout                     = "timedout"
)

type BuildStage string

const (
	BuildStagePrepare           BuildStage = "prepare_script"
	BuildStageGetSources                   = "get_sources"
	BuildStageRestoreCache                 = "restore_cache"
	BuildStageDownloadArtifacts            = "download_artifacts"
	BuildStageUserScript                   = "build_script"
	BuildStageAfterScript                  = "after_script"
	BuildStageArchiveCache                 = "archive_cache"
	BuildStageUploadArtifacts              = "upload_artifacts"
)

type Build struct {
	GetBuildResponse `yaml:",inline"`

	Trace           BuildTrace
	SystemInterrupt chan os.Signal `json:"-" yaml:"-"`
	RootDir         string         `json:"-" yaml:"-"`
	BuildDir        string         `json:"-" yaml:"-"`
	CacheDir        string         `json:"-" yaml:"-"`
	Hostname        string         `json:"-" yaml:"-"`
	Runner          *RunnerConfig  `json:"runner"`
	ExecutorData    ExecutorData

	// Unique ID for all running builds on this runner
	RunnerID int `json:"runner_id"`

	// Unique ID for all running builds on this runner and this project
	ProjectRunnerID int `json:"project_runner_id"`

	CurrentStage BuildStage
	CurrentState BuildRuntimeState
}

func (b *Build) Log() *logrus.Entry {
	return b.Runner.Log().WithField("build", b.ID).WithField("project", b.ProjectID)
}

func (b *Build) ProjectUniqueName() string {
	return fmt.Sprintf("runner-%s-project-%d-concurrent-%d",
		b.Runner.ShortDescription(), b.ProjectID, b.ProjectRunnerID)
}

func (b *Build) ProjectSlug() (string, error) {
	url, err := url.Parse(b.RepoURL)
	if err != nil {
		return "", err
	}
	if url.Host == "" {
		return "", errors.New("only URI reference supported")
	}

	slug := url.Path
	slug = strings.TrimSuffix(slug, ".git")
	slug = path.Clean(slug)
	if slug == "." {
		return "", errors.New("invalid path")
	}
	if strings.Contains(slug, "..") {
		return "", errors.New("it doesn't look like a valid path")
	}
	return slug, nil
}

func (b *Build) ProjectUniqueDir(sharedDir bool) string {
	dir, err := b.ProjectSlug()
	if err != nil {
		dir = fmt.Sprintf("project-%d", b.ProjectID)
	}

	// for shared dirs path is constructed like this:
	// <some-path>/runner-short-id/concurrent-id/group-name/project-name/
	// ex.<some-path>/01234567/0/group/repo/
	if sharedDir {
		dir = path.Join(
			fmt.Sprintf("%s", b.Runner.ShortDescription()),
			fmt.Sprintf("%d", b.ProjectRunnerID),
			dir,
		)
	}
	return dir
}

func (b *Build) FullProjectDir() string {
	return helpers.ToSlash(b.BuildDir)
}

func (b *Build) StartBuild(rootDir, cacheDir string, sharedDir bool) {
	b.RootDir = rootDir
	b.BuildDir = path.Join(rootDir, b.ProjectUniqueDir(sharedDir))
	b.CacheDir = path.Join(cacheDir, b.ProjectUniqueDir(false))
}

func (b *Build) executeStage(buildStage BuildStage, executor Executor, abort chan interface{}) error {
	b.CurrentStage = buildStage

	shell := executor.Shell()
	if shell == nil {
		return errors.New("No shell defined")
	}

	script, err := GenerateShellScript(buildStage, *shell)
	if err != nil {
		return err
	}

	// Nothing to execute
	if script == "" {
		return nil
	}

	cmd := ExecutorCommand{
		Script: script,
		Abort:  abort,
	}

	switch buildStage {
	case BuildStageUserScript, BuildStageAfterScript: // use custom build environment
		cmd.Predefined = false
	default: // all other stages use a predefined build environment
		cmd.Predefined = true
	}

	return executor.Run(cmd)
}

func (b *Build) executeUploadArtifacts(state error, executor Executor, abort chan interface{}) (err error) {
	when, _ := b.Options.GetString("artifacts", "when")

	if state == nil {
		// Previous stages were successful
		if when == "" || when == "on_success" || when == "always" {
			err = b.executeStage(BuildStageUploadArtifacts, executor, abort)
		}
	} else {
		// Previous stage did fail
		if when == "on_failure" || when == "always" {
			err = b.executeStage(BuildStageUploadArtifacts, executor, abort)
		}
	}

	// Use previous error if set
	if state != nil {
		err = state
	}
	return
}

func (b *Build) executeScript(executor Executor, abort chan interface{}) error {
	// Prepare stage
	err := b.executeStage(BuildStagePrepare, executor, abort)

	if err == nil {
		err = b.executeStage(BuildStageGetSources, executor, abort)
	}
	if err == nil {
		err = b.executeStage(BuildStageDownloadArtifacts, executor, abort)
	}
	if err == nil {
		err = b.executeStage(BuildStageRestoreCache, executor, abort)
	}

	if err == nil {
		// Execute user build script (before_script + script)
		err = b.executeStage(BuildStageUserScript, executor, abort)

		// Execute after script (after_script)
		timeoutCh := make(chan interface{}, 1)
		timeout := time.AfterFunc(time.Minute*5, func() {
			close(timeoutCh)
		})
		b.executeStage(BuildStageAfterScript, executor, timeoutCh)
		timeout.Stop()
	}

	// Execute post script (cache store, artifacts upload)
	if err == nil {
		err = b.executeStage(BuildStageArchiveCache, executor, abort)
	}
	err = b.executeUploadArtifacts(err, executor, abort)
	return err
}

func (b *Build) run(executor Executor) (err error) {
	b.CurrentState = BuildRunRuntimeRunning

	buildTimeout := b.Timeout
	if buildTimeout <= 0 {
		buildTimeout = DefaultTimeout
	}

	buildFinish := make(chan error, 1)
	buildAbort := make(chan interface{})

	// Run build script
	go func() {
		buildFinish <- b.executeScript(executor, buildAbort)
	}()

	// Wait for signals: cancel, timeout, abort or finish
	b.Log().Debugln("Waiting for signals...")
	select {
	case <-b.Trace.Aborted():
		err = &BuildError{Inner: errors.New("canceled")}
		b.CurrentStage = BuildRunRuntimeCanceled

	case <-time.After(time.Duration(buildTimeout) * time.Second):
		err = &BuildError{Inner: fmt.Errorf("execution took longer than %v seconds", buildTimeout)}
		b.CurrentStage = BuildRunRuntimeTimedout

	case signal := <-b.SystemInterrupt:
		err = fmt.Errorf("aborted: %v", signal)
		b.CurrentStage = BuildRunRuntimeTerminated

	case err = <-buildFinish:
		b.CurrentState = BuildRunRuntimeFinished
		return err
	}

	b.Log().WithError(err).Debugln("Waiting for build to finish...")

	// Wait till we receive that build did finish
	for {
		select {
		case buildAbort <- true:
		case <-buildFinish:
			return err
		}
	}
}

func (b *Build) retryCreateExecutor(globalConfig *Config, provider ExecutorProvider, logger BuildLogger) (executor Executor, err error) {
	for tries := 0; tries < PreparationRetries; tries++ {
		executor = provider.Create()
		if executor == nil {
			err = errors.New("failed to create executor")
			return
		}

		err = executor.Prepare(globalConfig, b.Runner, b)
		if err == nil {
			break
		}
		if executor != nil {
			executor.Cleanup()
			executor = nil
		}
		if _, ok := err.(*BuildError); ok {
			break
		}

		logger.SoftErrorln("Preparation failed:", err)
		logger.Infoln("Will be retried in", PreparationRetryInterval, "...")
		time.Sleep(PreparationRetryInterval)
	}
	return
}

func (b *Build) Run(globalConfig *Config, trace BuildTrace) (err error) {
	var executor Executor

	logger := NewBuildLogger(trace, b.Log())
	logger.Println("Running with " + AppVersion.Line() + helpers.ANSI_RESET)

	b.CurrentState = BuildRunStatePending

	defer func() {
		if _, ok := err.(*BuildError); ok {
			logger.SoftErrorln("Build failed:", err)
			trace.Fail(err)
		} else if err != nil {
			logger.Errorln("Build failed (system failure):", err)
			trace.Fail(err)
		} else {
			logger.Infoln("Build succeeded")
			trace.Success()
		}
		if executor != nil {
			executor.Cleanup()
		}
	}()

	b.Trace = trace

	provider := GetExecutor(b.Runner.Executor)
	if provider == nil {
		return errors.New("executor not found")
	}

	executor, err = b.retryCreateExecutor(globalConfig, provider, logger)
	if err == nil {
		err = b.run(executor)
	}
	if executor != nil {
		executor.Finish(err)
	}
	return err
}

func (b *Build) String() string {
	return helpers.ToYAML(b)
}

func (b *Build) GetDefaultVariables() BuildVariables {
	return BuildVariables{
		{"CI", "true", true, true, false},
		{"CI_DEBUG_TRACE", "false", true, true, false},
		{"CI_BUILD_REF", b.Sha, true, true, false},
		{"CI_BUILD_BEFORE_SHA", b.BeforeSha, true, true, false},
		{"CI_BUILD_REF_NAME", b.RefName, true, true, false},
		{"CI_BUILD_ID", strconv.Itoa(b.ID), true, true, false},
		{"CI_BUILD_REPO", b.RepoURL, true, true, false},
		{"CI_BUILD_TOKEN", b.Token, true, true, false},
		{"CI_PROJECT_ID", strconv.Itoa(b.ProjectID), true, true, false},
		{"CI_PROJECT_DIR", b.FullProjectDir(), true, true, false},
		{"CI_SERVER", "yes", true, true, false},
		{"CI_SERVER_NAME", "GitLab CI", true, true, false},
		{"CI_SERVER_VERSION", "", true, true, false},
		{"CI_SERVER_REVISION", "", true, true, false},
		{"GITLAB_CI", "true", true, true, false},
	}
}

func (b *Build) GetAllVariables() (variables BuildVariables) {
	if b.Runner != nil {
		variables = append(variables, b.Runner.GetVariables()...)
	}
	variables = append(variables, b.GetDefaultVariables()...)
	variables = append(variables, b.Variables...)
	return variables.Expand()
}

func (b *Build) GetGitDepth() string {
	return b.GetAllVariables().Get("GIT_DEPTH")
}

func (b *Build) GetGitStrategy() GitStrategy {
	switch b.GetAllVariables().Get("GIT_STRATEGY") {
	case "clone":
		return GitClone

	case "fetch":
		return GitFetch

	case "none":
		return GitNone

	default:
		if b.AllowGitFetch {
			return GitFetch
		}

		return GitClone
	}
}

func (b *Build) IsDebugTraceEnabled() bool {
	trace, err := strconv.ParseBool(b.GetAllVariables().Get("CI_DEBUG_TRACE"))
	if err != nil {
		return false
	}

	return trace
}

func (b *Build) GetDockerAuthConfig() string {
	return b.GetAllVariables().Get("DOCKER_AUTH_CONFIG")
}
<|endoftext|>


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

package query

import (
	"sort"

	"github.com/square/metrics/api"
)

// ExecutionContext is the context supplied when invoking a command.
type ExecutionContext struct {
	Backend    api.MultiBackend // the backend
	API        api.API          // the api
	FetchLimit int              // the maximum number of fetches
}

// Command is the final result of the parsing.
// A command contains all the information to execute the
// given query against the API.
type Command interface {
	// Execute the given command. Returns JSON-encodable result or an error.
	Execute(ExecutionContext) (interface{}, error)
	Name() string
}

// DescribeCommand describes the tag set managed by the given metric indexer.
type DescribeCommand struct {
	metricName api.MetricKey
	predicate  api.Predicate
}

// DescribeAllCommand returns all the metrics available in the system.
type DescribeAllCommand struct {
}

// DescribeMetricsCommand returns all metrics that use a particular key-value pair.
type DescribeMetricsCommand struct {
	tagKey   string
	tagValue string
}

// SelectCommand is the bread and butter of the metrics query engine.
// It actually performs the query against the underlying metrics system.
type SelectCommand struct {
	predicate   api.Predicate
	expressions []Expression
	context     *evaluationContextNode
}

// Execute returns the list of tags satisfying the provided predicate.
func (cmd *DescribeCommand) Execute(context ExecutionContext) (interface{}, error) {
	tags, _ := context.API.GetAllTags(cmd.metricName)
	output := make([]string, 0, len(tags))
	for _, tag := range tags {
		if cmd.predicate.Apply(tag) {
			output = append(output, tag.Serialize())
		}
	}
	sort.Strings(output)
	return output, nil
}
func (cmd *DescribeCommand) Name() string {
	return "describe"
}

// Execute of a DescribeAllCommand returns the list of all metrics.
func (cmd *DescribeAllCommand) Execute(context ExecutionContext) (interface{}, error) {
	result, err := context.API.GetAllMetrics()
	if err == nil {
		sort.Sort(api.MetricKeys(result))
	}
	return result, err
}

func (cmd *DescribeAllCommand) Name() string {
	return "describe all"
}

// Execute asks for all metrics with the given name.
func (cmd *DescribeMetricsCommand) Execute(b api.MultiBackend, a api.API) (interface{}, error) {
	return a.GetMetricsForTag(cmd.tagKey, cmd.tagValue)
}

func (cmd *DescribeMetricsCommand) Name() string {
	return "describe metrics"
}

// Execute performs the query represented by the given query string, and returs the result.
func (cmd *SelectCommand) Execute(context ExecutionContext) (interface{}, error) {
	timerange, err := api.NewSnappedTimerange(cmd.context.Start, cmd.context.End, cmd.context.Resolution)
	if err != nil {
		return nil, err
	}
	return evaluateExpressions(EvaluationContext{
		MultiBackend: context.Backend,
		Timerange:    timerange,
		SampleMethod: cmd.context.SampleMethod,
		Predicate:    cmd.predicate,
		API:          context.API,
		FetchLimit:   NewFetchCounter(context.FetchLimit),
	}, cmd.expressions)
}

func (cmd *SelectCommand) Name() string {
	return "select"
}
<commit_msg>update describemetricscommand to use new interface<commit_after>// Copyright 2015 Square Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package query

import (
	"sort"

	"github.com/square/metrics/api"
)

// ExecutionContext is the context supplied when invoking a command.
type ExecutionContext struct {
	Backend    api.MultiBackend // the backend
	API        api.API          // the api
	FetchLimit int              // the maximum number of fetches
}

// Command is the final result of the parsing.
// A command contains all the information to execute the
// given query against the API.
type Command interface {
	// Execute the given command. Returns JSON-encodable result or an error.
	Execute(ExecutionContext) (interface{}, error)
	Name() string
}

// DescribeCommand describes the tag set managed by the given metric indexer.
type DescribeCommand struct {
	metricName api.MetricKey
	predicate  api.Predicate
}

// DescribeAllCommand returns all the metrics available in the system.
type DescribeAllCommand struct {
}

// DescribeMetricsCommand returns all metrics that use a particular key-value pair.
type DescribeMetricsCommand struct {
	tagKey   string
	tagValue string
}

// SelectCommand is the bread and butter of the metrics query engine.
// It actually performs the query against the underlying metrics system.
type SelectCommand struct {
	predicate   api.Predicate
	expressions []Expression
	context     *evaluationContextNode
}

// Execute returns the list of tags satisfying the provided predicate.
func (cmd *DescribeCommand) Execute(context ExecutionContext) (interface{}, error) {
	tags, _ := context.API.GetAllTags(cmd.metricName)
	output := make([]string, 0, len(tags))
	for _, tag := range tags {
		if cmd.predicate.Apply(tag) {
			output = append(output, tag.Serialize())
		}
	}
	sort.Strings(output)
	return output, nil
}
func (cmd *DescribeCommand) Name() string {
	return "describe"
}

// Execute of a DescribeAllCommand returns the list of all metrics.
func (cmd *DescribeAllCommand) Execute(context ExecutionContext) (interface{}, error) {
	result, err := context.API.GetAllMetrics()
	if err == nil {
		sort.Sort(api.MetricKeys(result))
	}
	return result, err
}

func (cmd *DescribeAllCommand) Name() string {
	return "describe all"
}

// Execute asks for all metrics with the given name.
func (cmd *DescribeMetricsCommand) Execute(context ExecutionContext) (interface{}, error) {
	return context.API.GetMetricsForTag(cmd.tagKey, cmd.tagValue)
}

func (cmd *DescribeMetricsCommand) Name() string {
	return "describe metrics"
}

// Execute performs the query represented by the given query string, and returs the result.
func (cmd *SelectCommand) Execute(context ExecutionContext) (interface{}, error) {
	timerange, err := api.NewSnappedTimerange(cmd.context.Start, cmd.context.End, cmd.context.Resolution)
	if err != nil {
		return nil, err
	}
	return evaluateExpressions(EvaluationContext{
		MultiBackend: context.Backend,
		Timerange:    timerange,
		SampleMethod: cmd.context.SampleMethod,
		Predicate:    cmd.predicate,
		API:          context.API,
		FetchLimit:   NewFetchCounter(context.FetchLimit),
	}, cmd.expressions)
}

func (cmd *SelectCommand) Name() string {
	return "select"
}
<|endoftext|>


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

package queue

import (
	"errors"
	"sync"
	"time"

	"tux21b.org/v1/gocql"
)

var (
	ErrManagerShutdown = errors.New("queue manager is shutdown")
)

type ErrWrongManager struct {
	ActualManager string
}

func (err *ErrWrongManager) Error() string {
	return "queue has another manager: " + err.ActualManager
}

type QueueManagerConfig struct {
	CassandraHosts    []string
	CassandraKeyspace string
	ReservationTTL    time.Duration
}

func (cfg *QueueManagerConfig) reservationTTL() time.Duration {
	if cfg.ReservationTTL == 0 {
		return 60
	} else {
		return cfg.ReservationTTL
	}
}

// QueueManager is used to publish to and read from queues. Every QueueManager
// must supply a unique name - this is not enforced, but failure to do so will
// result in Bad Things happening.
//
// Each queue may only be published to by a single QueueManager, which becomes
// the master for that queue. Attempts to publish to a queue not owned by the
// QueueManager will result in an ErrWrongManager error, which indicates the
// name of the QueueManager responsible for that queue. For this reason, it may
// be useful to encode the information needed to reach a QueueManager in its
// name.  For example, if exposed by an HTTP API, the hostname and port of HTTP
// service could be encoded in the manager's name in order to generate an
// appropriate redirect.
//
// Any QueueManager may read from any queue.
type QueueManager struct {
	Name          string
	config        QueueManagerConfig
	mu            sync.RWMutex
	writers       map[string]*queueWriter
	db            *gocql.Session
	done          *sync.WaitGroup
	stopKeepAlive chan bool
	stopped       bool
}

// NewQueueManager constructs a new QueueManager with a given name and
// configuration. The QueueManagerConfig is copied by value, so attempts to
// mutate a configuration already passed to NewQueueManager will have no
// effect.
func NewQueueManager(name string, config QueueManagerConfig) (*QueueManager, error) {
	cassCluster := gocql.NewCluster(config.CassandraHosts...)
	cassCluster.Keyspace = config.CassandraKeyspace
	cassSession, err := cassCluster.CreateSession()

	if err != nil {
		return nil, err
	}

	mgr := &QueueManager{
		name:          name,
		config:        config,
		writers:       make(map[string]*queueWriter),
		db:            cassSession,
		done:          &sync.WaitGroup{},
		stopKeepAlive: make(chan bool),
	}

	go mgr.keepAlive()
	return mgr, nil
}

func (mgr *QueueManager) keepAlive() {
	ticker := time.NewTicker((mgr.config.reservationTTL() / 3.0) * time.Second)

	for {
		select {
		case <-mgr.stopKeepAlive:
			break

		case <-ticker.C:
			mgr.heartbeatReservations()
		}
	}

	ticker.Stop()
}

func (mgr *QueueManager) heartbeatReservations() {
	batch := gocql.NewBatch(gocql.UnloggedBatch)

	mgr.mu.RLock()
	for queueID := range mgr.writers {
		batch.Query(`UPDATE queue_managers USING TTL ? SET manager_id = ? WHERE queue_id = ?`,
			mgr.config.reservationTTL(), mgr.Name, queueID)
	}
	mgr.mu.RUnlock()

	// TODO: Panic hard if an error occurs
	mgr.db.ExecuteBatch(batch)
}

func (mgr *QueueManager) getOrCreateQueueWriter(queueID string) (*queueWriter, error) {
	// Hot path: just get the queue from the map
	mgr.mu.RLock()
	if mgr.stopped {
		return nil, ErrManagerShutdown
	}

	writer, exists := mgr.writers[queueID]
	mgr.mu.RUnlock()

	if exists {
		return writer, nil
	}

	// Before we go down the really slow path, see if someone else owns the queue
	actualManager := ""
	err := mgr.db.Query(`SELECT manager_id FROM queue_managers WHERE queue_id = ?`, queueID).Scan(&actualManager)
	if err != nil && err != gocql.ErrNotFound {
		return nil, err
	}

	if actualManager != "" && actualManager != mgr.Name {
		return nil, &ErrWrongManager{actualManager}
	}

	// Slow path: get the write lock, make sure the writer hasn't been created
	// then create it.
	mgr.mu.Lock()
	defer mgr.mu.Unlock()

	if mgr.stopped {
		return nil, ErrManagerShutdown
	}

	writer, exists = mgr.writers[queueID]

	if exists {
		return writer, nil
	}

	// Attempt to register as the manager for this queue
	var uselessID string
	applied, err := mgr.db.Query(`INSERT INTO queue_managers (queue_id, manager_id) VALUES (?, ?) IF NOT EXISTS USING TTL ?;`,
		queueID, mgr.Name, mgr.config.reservationTTL()).ScanCAS(&uselessID, &actualManager)

	if err != nil {
		return nil, err
	}

	if !applied && actualManager != mgr.Name {
		_ = uselessID
		return nil, &ErrWrongManager{actualManager}
	}

	writer, err = newQueueWriter(mgr, queueID)
	if err != nil {
		return nil, err
	}

	mgr.writers[queueID] = writer
	return writer, nil
}

// Publish a batch of values to a queue. Each each value will be assigned an
// integer ID.  Upon success, Publish will return the ID of the first value.
// For example, if 4 values are published and an ID of 17 is returned, then the
// four values have been assigned IDs 17, 18, 19 and 20 respectively.
//
// If the specified queue does not exist, it will be created.
func (mgr *QueueManager) Publish(queueID string, items []QueueItemValue) (int64, error) {
	writer, err := mgr.getOrCreateQueueWriter(queueID)

	if err != nil {
		return 0, err
	}

	return writer.publish(items)
}

// Read values from a queue, starting at the specified index.
func (mgr *QueueManager) Read(queueID string, startIndex int64, count int) ([]QueueItem, error) {
	query := mgr.db.Query(`SELECT item_id, item_value FROM queue_items WHERE queue_id = ? AND item_id >= ? LIMIT ?;`,
		queueID, startIndex, count)

	// Disable result paging, we know exactly how much we want
	query.PageSize(0)

	iter := query.Iter()

	items := []QueueItem{}

	var itemID int64
	var itemValue QueueItemValue

	for iter.Scan(&itemID, &itemValue) {
		// We could do better than the built-in append here if it mattered. Common cases are:
		// - no items
		// - a few items
		// - `count` items
		items = append(items, QueueItem{ID: itemID, Value: itemValue})
	}

	err := iter.Close()

	if err != nil {
		return nil, err
	}

	return items, nil
}

// Shutdown the queue manager. Subsequent writes will fail with
// ErrManagerShutdown.
func (mgr *QueueManager) Shutdown() {
	mgr.mu.Lock()
	mgr.stopped = true
	for _, writer := range mgr.writers {
		writer.shutdown()
	}
	mgr.mu.Unlock()

	// Wait for all writers to drain
	mgr.done.Wait()

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

package queue

import (
	"errors"
	"sync"
	"time"

	"tux21b.org/v1/gocql"
)

var (
	ErrManagerShutdown = errors.New("queue manager is shutdown")
)

type ErrWrongManager struct {
	ActualManager string
}

func (err *ErrWrongManager) Error() string {
	return "queue has another manager: " + err.ActualManager
}

type QueueManagerConfig struct {
	CassandraHosts    []string
	CassandraKeyspace string
	ReservationTTL    time.Duration
}

func (cfg *QueueManagerConfig) reservationTTL() time.Duration {
	if cfg.ReservationTTL == 0 {
		return 60
	} else {
		return cfg.ReservationTTL
	}
}

// QueueManager is used to publish to and read from queues. Every QueueManager
// must supply a unique name - this is not enforced, but failure to do so will
// result in Bad Things happening.
//
// Each queue may only be published to by a single QueueManager, which becomes
// the master for that queue. Attempts to publish to a queue not owned by the
// QueueManager will result in an ErrWrongManager error, which indicates the
// name of the QueueManager responsible for that queue. For this reason, it may
// be useful to encode the information needed to reach a QueueManager in its
// name.  For example, if exposed by an HTTP API, the hostname and port of HTTP
// service could be encoded in the manager's name in order to generate an
// appropriate redirect.
//
// Any QueueManager may read from any queue.
type QueueManager struct {
	Name          string
	config        QueueManagerConfig
	mu            sync.RWMutex
	writers       map[string]*queueWriter
	db            *gocql.Session
	done          *sync.WaitGroup
	stopKeepAlive chan bool
	stopped       bool
}

// NewQueueManager constructs a new QueueManager with a given name and
// configuration. The QueueManagerConfig is copied by value, so attempts to
// mutate a configuration already passed to NewQueueManager will have no
// effect.
func NewQueueManager(name string, config QueueManagerConfig) (*QueueManager, error) {
	cassCluster := gocql.NewCluster(config.CassandraHosts...)
	cassCluster.Keyspace = config.CassandraKeyspace
	cassSession, err := cassCluster.CreateSession()

	if err != nil {
		return nil, err
	}

	mgr := &QueueManager{
		Name:          name,
		config:        config,
		writers:       make(map[string]*queueWriter),
		db:            cassSession,
		done:          &sync.WaitGroup{},
		stopKeepAlive: make(chan bool),
	}

	go mgr.keepAlive()
	return mgr, nil
}

func (mgr *QueueManager) keepAlive() {
	ticker := time.NewTicker((mgr.config.reservationTTL() / 3.0) * time.Second)

	for {
		select {
		case <-mgr.stopKeepAlive:
			break

		case <-ticker.C:
			mgr.heartbeatReservations()
		}
	}

	ticker.Stop()
}

func (mgr *QueueManager) heartbeatReservations() {
	batch := gocql.NewBatch(gocql.UnloggedBatch)

	mgr.mu.RLock()
	for queueID := range mgr.writers {
		batch.Query(`UPDATE queue_managers USING TTL ? SET manager_id = ? WHERE queue_id = ?`,
			mgr.config.reservationTTL(), mgr.Name, queueID)
	}
	mgr.mu.RUnlock()

	// TODO: Panic hard if an error occurs
	mgr.db.ExecuteBatch(batch)
}

func (mgr *QueueManager) getOrCreateQueueWriter(queueID string) (*queueWriter, error) {
	// Hot path: just get the queue from the map
	mgr.mu.RLock()
	if mgr.stopped {
		return nil, ErrManagerShutdown
	}

	writer, exists := mgr.writers[queueID]
	mgr.mu.RUnlock()

	if exists {
		return writer, nil
	}

	// Before we go down the really slow path, see if someone else owns the queue
	actualManager := ""
	err := mgr.db.Query(`SELECT manager_id FROM queue_managers WHERE queue_id = ?`, queueID).Scan(&actualManager)
	if err != nil && err != gocql.ErrNotFound {
		return nil, err
	}

	if actualManager != "" && actualManager != mgr.Name {
		return nil, &ErrWrongManager{actualManager}
	}

	// Slow path: get the write lock, make sure the writer hasn't been created
	// then create it.
	mgr.mu.Lock()
	defer mgr.mu.Unlock()

	if mgr.stopped {
		return nil, ErrManagerShutdown
	}

	writer, exists = mgr.writers[queueID]

	if exists {
		return writer, nil
	}

	// Attempt to register as the manager for this queue
	var uselessID string
	applied, err := mgr.db.Query(`INSERT INTO queue_managers (queue_id, manager_id) VALUES (?, ?) IF NOT EXISTS USING TTL ?;`,
		queueID, mgr.Name, mgr.config.reservationTTL()).ScanCAS(&uselessID, &actualManager)

	if err != nil {
		return nil, err
	}

	if !applied && actualManager != mgr.Name {
		_ = uselessID
		return nil, &ErrWrongManager{actualManager}
	}

	writer, err = newQueueWriter(mgr, queueID)
	if err != nil {
		return nil, err
	}

	mgr.writers[queueID] = writer
	return writer, nil
}

// Publish a batch of values to a queue. Each each value will be assigned an
// integer ID.  Upon success, Publish will return the ID of the first value.
// For example, if 4 values are published and an ID of 17 is returned, then the
// four values have been assigned IDs 17, 18, 19 and 20 respectively.
//
// If the specified queue does not exist, it will be created.
func (mgr *QueueManager) Publish(queueID string, items []QueueItemValue) (int64, error) {
	writer, err := mgr.getOrCreateQueueWriter(queueID)

	if err != nil {
		return 0, err
	}

	return writer.publish(items)
}

// Read values from a queue, starting at the specified index.
func (mgr *QueueManager) Read(queueID string, startIndex int64, count int) ([]QueueItem, error) {
	query := mgr.db.Query(`SELECT item_id, item_value FROM queue_items WHERE queue_id = ? AND item_id >= ? LIMIT ?;`,
		queueID, startIndex, count)

	// Disable result paging, we know exactly how much we want
	query.PageSize(0)

	iter := query.Iter()

	items := []QueueItem{}

	var itemID int64
	var itemValue QueueItemValue

	for iter.Scan(&itemID, &itemValue) {
		// We could do better than the built-in append here if it mattered. Common cases are:
		// - no items
		// - a few items
		// - `count` items
		items = append(items, QueueItem{ID: itemID, Value: itemValue})
	}

	err := iter.Close()

	if err != nil {
		return nil, err
	}

	return items, nil
}

// Shutdown the queue manager. Subsequent writes will fail with
// ErrManagerShutdown.
func (mgr *QueueManager) Shutdown() {
	mgr.mu.Lock()
	mgr.stopped = true
	for _, writer := range mgr.writers {
		writer.shutdown()
	}
	mgr.mu.Unlock()

	// Wait for all writers to drain
	mgr.done.Wait()

	// Kill the heartbeat
	mgr.stopKeepAlive <- true
}
<|endoftext|>


<commit_before>package rational

import (
	"math/big"

	"github.com/alex-ant/gomath/misc"
)

// Simplify simplifies the rational number by dividing it's numerator and
// denominator by the GCD.
func (ev *Rational) Simplify() {
	currentNumerator := ev.numerator
	currentDenominator := ev.denominator

	if currentNumerator < 0 && currentDenominator > 0 {
		currentNumerator *= -1
	} else if currentDenominator < 0 && currentNumerator >= 0 {
		currentDenominator *= -1
	}

	n := big.NewInt(currentNumerator)
	d := big.NewInt(currentDenominator)

	gcd := new(big.Int).GCD(nil, nil, n, d).Int64()

	if gcd > 1 {
		ev.numerator /= gcd
		ev.denominator /= gcd
	}
}

// SimplifyLine miltiplies all the rationals in the line by the
// Greatest Common Delimiter if one is greater than 1.
func SimplifyLine(line []Rational) []Rational {
	var denominators []int64
	for _, v := range line {
		denominators = append(denominators, v.GetDenominator())
	}

	gcd := misc.MultiGCD(denominators)

	if gcd > 1 {
		for i, v := range line {
			line[i] = v.MultiplyByNum(gcd)
		}
	}

	return line
}

// Float64 returns the float64 representation of a rational number.
func (ev Rational) Float64() float64 {
	return float64(ev.numerator) / float64(ev.denominator)
}

// Get returns a value.
func (ev Rational) Get() (numerator, denominator int64) {
	return ev.numerator, ev.denominator
}

// GetNumerator returns a numerator.
func (ev Rational) GetNumerator() int64 {
	return ev.numerator
}

// GetDenominator returns a denominator.
func (ev Rational) GetDenominator() int64 {
	return ev.denominator
}

// GetModule returns rational number's module.
func (ev Rational) GetModule() Rational {
	if ev.LessThanNum(0) {
		ev = ev.MultiplyByNum(-1)
	}
	return ev
}

// IsNull determines whether the value is zero.
func (ev Rational) IsNull() (n bool) {
	if ev.numerator == 0 {
		n = true
	}
	return
}

// RationalsAreNull determines whether the slice of Rationals contains only zero values.
func RationalsAreNull(l []Rational) (isNull bool) {
	isNull = true
	for _, v := range l {
		if !v.IsNull() {
			isNull = false
		}
	}
	return
}

func solveNegatives(n, d *int64) {
	if *n < 0 && *d < 0 {
		*n *= -1
		*d *= -1
	}
}
<commit_msg>fixed comment<commit_after>package rational

import (
	"math/big"

	"github.com/alex-ant/gomath/misc"
)

// Simplify simplifies the rational number by dividing it's numerator and
// denominator by the GCD.
func (ev *Rational) Simplify() {
	currentNumerator := ev.numerator
	currentDenominator := ev.denominator

	if currentNumerator < 0 && currentDenominator > 0 {
		currentNumerator *= -1
	} else if currentDenominator < 0 && currentNumerator >= 0 {
		currentDenominator *= -1
	}

	n := big.NewInt(currentNumerator)
	d := big.NewInt(currentDenominator)

	gcd := new(big.Int).GCD(nil, nil, n, d).Int64()

	if gcd > 1 {
		ev.numerator /= gcd
		ev.denominator /= gcd
	}
}

// SimplifyLine miltiplies all the rationals in the line by the
// Greatest Common Delimiter of denominators if one is greater than 1.
func SimplifyLine(line []Rational) []Rational {
	var denominators []int64
	for _, v := range line {
		denominators = append(denominators, v.GetDenominator())
	}

	gcd := misc.MultiGCD(denominators)

	if gcd > 1 {
		for i, v := range line {
			line[i] = v.MultiplyByNum(gcd)
		}
	}

	return line
}

// Float64 returns the float64 representation of a rational number.
func (ev Rational) Float64() float64 {
	return float64(ev.numerator) / float64(ev.denominator)
}

// Get returns a value.
func (ev Rational) Get() (numerator, denominator int64) {
	return ev.numerator, ev.denominator
}

// GetNumerator returns a numerator.
func (ev Rational) GetNumerator() int64 {
	return ev.numerator
}

// GetDenominator returns a denominator.
func (ev Rational) GetDenominator() int64 {
	return ev.denominator
}

// GetModule returns rational number's module.
func (ev Rational) GetModule() Rational {
	if ev.LessThanNum(0) {
		ev = ev.MultiplyByNum(-1)
	}
	return ev
}

// IsNull determines whether the value is zero.
func (ev Rational) IsNull() (n bool) {
	if ev.numerator == 0 {
		n = true
	}
	return
}

// RationalsAreNull determines whether the slice of Rationals contains only zero values.
func RationalsAreNull(l []Rational) (isNull bool) {
	isNull = true
	for _, v := range l {
		if !v.IsNull() {
			isNull = false
		}
	}
	return
}

func solveNegatives(n, d *int64) {
	if *n < 0 && *d < 0 {
		*n *= -1
		*d *= -1
	}
}
<|endoftext|>


<commit_before>package raven

import (
	"net/http"
	"os"
	"regexp"
	"strings"

	"github.com/yext/glog"
)

var (
	projectName string
	hostname    string
	re          *regexp.Regexp
)

func init() {
	hostname, _ = os.Hostname()
	if short := strings.Index(hostname, "."); short != -1 {
		hostname = hostname[:short]
	}
	re = regexp.MustCompile("[0-9]{2,}")
}

// CaptureErrors sets the name of the project so that when events are
// sent to sentry they are tagged as coming from the given
// project. It then sets up the connection to sentry and begins
// to send any errors recieved over comm to sentry.
// It panics if a client could be initialized.
func CaptureErrors(project, dsn string, comm <-chan glog.Event) {
	projectName = project
	client, err := NewClient(dsn)
	if err != nil {
		panic(err)
	}

	for e := range comm {
		if e.Severity == "ERROR" {
			client.Capture(fromGlogEvent(e))
		}
	}
}

func separateMessageAndIds(message string) (string, string) {
	msg := re.ReplaceAllString(message, "[ID]")
	numbers := re.FindAllString(message, -1)
	ids := strings.Join(numbers, " ")
	return msg, ids
}

// fromGlogEvent converts a glog.Event to the format expected by Sentry.
func fromGlogEvent(e glog.Event) *Event {
	message := string(e.Message)
	if square := strings.Index(message, "]"); square != -1 {
		message = message[square+1:]
	}

	fullMessage := message
	if line := strings.Index(message, "\n"); line != -1 {
		message = message[:line]
	}

	msg, ids := separateMessageAndIds(message)

	eve := &Event{
		Project:    projectName,
		Level:      e.Severity,
		Message:    msg,
		ServerName: hostname,
		Extra:      map[string]interface{}{"FullMessage": fullMessage},
		StackTrace: BuildStackTrace(e.StackTrace),
		Logger:     os.Args[0],
	}

	for _, d := range e.Data {
		switch t := d.(type) {
		case *http.Request:
			eve.Http = NewHttp(t)
			break
		default:
			//TODO(ltacon): ignore for now...
		}
	}

	eve.Extra["Source"] = sourceFromStack(eve.StackTrace)
	if ids != "" {
		eve.Extra["IDs"] = ids
	}

	return eve
}

// sourceFromStack retrieves the function and line where the
// event was logged from in the format "file.Function:118".
func sourceFromStack(s StackTrace) string {
	if len(s.Frames) == 0 {
		return ""
	}

	f := s.Frames[0]
	return f.Function + ":" + f.LineNo
}
<commit_msg>Allow arbitrary key-value pairs to be passed through to Sentry as extra data.<commit_after>package raven

import (
	"net/http"
	"os"
	"regexp"
	"strings"

	"github.com/yext/glog"
)

var (
	projectName string
	hostname    string
	re          *regexp.Regexp
)

func init() {
	hostname, _ = os.Hostname()
	if short := strings.Index(hostname, "."); short != -1 {
		hostname = hostname[:short]
	}
	re = regexp.MustCompile("[0-9]{2,}")
}

// CaptureErrors sets the name of the project so that when events are
// sent to sentry they are tagged as coming from the given
// project. It then sets up the connection to sentry and begins
// to send any errors recieved over comm to sentry.
// It panics if a client could be initialized.
func CaptureErrors(project, dsn string, comm <-chan glog.Event) {
	projectName = project
	client, err := NewClient(dsn)
	if err != nil {
		panic(err)
	}

	for e := range comm {
		if e.Severity == "ERROR" {
			client.Capture(fromGlogEvent(e))
		}
	}
}

func separateMessageAndIds(message string) (string, string) {
	msg := re.ReplaceAllString(message, "[ID]")
	numbers := re.FindAllString(message, -1)
	ids := strings.Join(numbers, " ")
	return msg, ids
}

// fromGlogEvent converts a glog.Event to the format expected by Sentry.
func fromGlogEvent(e glog.Event) *Event {
	message := string(e.Message)
	if square := strings.Index(message, "]"); square != -1 {
		message = message[square+1:]
	}

	fullMessage := message
	if line := strings.Index(message, "\n"); line != -1 {
		message = message[:line]
	}

	msg, ids := separateMessageAndIds(message)

	eve := &Event{
		Project:    projectName,
		Level:      e.Severity,
		Message:    msg,
		ServerName: hostname,
		Extra:      map[string]interface{}{"FullMessage": fullMessage},
		StackTrace: BuildStackTrace(e.StackTrace),
		Logger:     os.Args[0],
	}

	for _, d := range e.Data {
		switch t := d.(type) {
		case *http.Request:
			if eve.Http == nil {
				eve.Http = NewHttp(t)
			}
		case map[string]interface{}:
			for k, v := range t {
				data[k] = v
			}
		default:
			//TODO(ltacon): ignore for now...
		}
	}

	eve.Extra["Source"] = sourceFromStack(eve.StackTrace)
	if ids != "" {
		eve.Extra["IDs"] = ids
	}

	return eve
}

// sourceFromStack retrieves the function and line where the
// event was logged from in the format "file.Function:118".
func sourceFromStack(s StackTrace) string {
	if len(s.Frames) == 0 {
		return ""
	}

	f := s.Frames[0]
	return f.Function + ":" + f.LineNo
}
<|endoftext|>


<commit_before>package exifcamera

import(
	"fmt"
	"github.com/antonholmquist/jason"
	"cgt.name/pkg/go-mwclient/params"
	mwclient "cgt.name/pkg/go-mwclient"
	"github.com/garyhouston/takenwith/mwlib"
	"strings"
)

func requestExif(pages []string, client *mwclient.Client) (*jason.Object) {
	params := params.Values {
		"action": "query",
		"titles": mwlib.MakeTitleString(pages),
		"prop": "imageinfo",
		"iiprop": "metadata",
		"redirects" : "",  // follow redirects
		"continue": "",
	}
	json, err := client.Get(params)
	if err != nil {
		panic(err)
	}
	return json
}

// Return device make/model from json imageinfo object.
func ExtractCamera(imageinfo *jason.Object) (string, string) {
	metadata, err := imageinfo.GetObjectArray("metadata")
	if err != nil {
		// metadata is null in some cases
		return "", ""
	}
	make := ""
	model := ""
	for i := 0; i < len(metadata); i++ {
		name, err := metadata[i].GetString("name")
		if err != nil {
			panic(err)
		}
		if name == "Make" {
			value, err := metadata[i].GetString("value")
			if err != nil {
				panic(err)
			}
			make = strings.Trim(value, " ")
		} else if name == "Model" {
			value, err := metadata[i].GetString("value")
			if err != nil {
				panic(err)
			}
			model = strings.Trim(value, " ")
		}
	}
	return make, model
}

type FileCamera struct {
	Title string
	Make string
	Model string
}

// Return the camera manufacturer and model from Exif. Also follow any
// redirects and return the final page name.
func GetCameraInfo(pageReq []string, client *mwclient.Client) []FileCamera {
	exif := requestExif(pageReq, client)
	pages, err := exif.GetObject("query", "pages")
	if err != nil {
		panic(err)
	}
	pageMap := pages.Map()
	pageArray := make([]FileCamera, 0, len(pageMap))
	idx := 0
	for pageId, page := range pageMap {
		pageObj, err := page.Object()
		if err != nil {
			panic(err)
		}
		title, err := pageObj.GetString("title")
		if err != nil {
			panic(err)
		}
		if pageId == "-1" {
			fmt.Println(title)
			fmt.Println("File does not exist, possibly deleted.")
			continue
		}
		make := ""
		model := ""
		imageinfo, err := pageObj.GetObjectArray("imageinfo")
		if err == nil {
			make, model = ExtractCamera(imageinfo[0])
		}
		pageArray = pageArray[0:idx + 1]
		pageArray[idx] = FileCamera{title, make, model}
		idx++
	}
	return pageArray
}
<commit_msg>Trim leading/trailing newlines from make/model in Exif.<commit_after>package exifcamera

import(
	"fmt"
	"github.com/antonholmquist/jason"
	"cgt.name/pkg/go-mwclient/params"
	mwclient "cgt.name/pkg/go-mwclient"
	"github.com/garyhouston/takenwith/mwlib"
	"strings"
)

func requestExif(pages []string, client *mwclient.Client) (*jason.Object) {
	params := params.Values {
		"action": "query",
		"titles": mwlib.MakeTitleString(pages),
		"prop": "imageinfo",
		"iiprop": "metadata",
		"redirects" : "",  // follow redirects
		"continue": "",
	}
	json, err := client.Get(params)
	if err != nil {
		panic(err)
	}
	return json
}

// Return device make/model from json imageinfo object.
func ExtractCamera(imageinfo *jason.Object) (string, string) {
	metadata, err := imageinfo.GetObjectArray("metadata")
	if err != nil {
		// metadata is null in some cases
		return "", ""
	}
	make := ""
	model := ""
	for i := 0; i < len(metadata); i++ {
		name, err := metadata[i].GetString("name")
		if err != nil {
			panic(err)
		}
		if name == "Make" {
			value, err := metadata[i].GetString("value")
			if err != nil {
				panic(err)
			}
			make = strings.Trim(value, " \n")
		} else if name == "Model" {
			value, err := metadata[i].GetString("value")
			if err != nil {
				panic(err)
			}
			model = strings.Trim(value, " \n")
		}
	}
	return make, model
}

type FileCamera struct {
	Title string
	Make string
	Model string
}

// Return the camera manufacturer and model from Exif. Also follow any
// redirects and return the final page name.
func GetCameraInfo(pageReq []string, client *mwclient.Client) []FileCamera {
	exif := requestExif(pageReq, client)
	pages, err := exif.GetObject("query", "pages")
	if err != nil {
		panic(err)
	}
	pageMap := pages.Map()
	pageArray := make([]FileCamera, 0, len(pageMap))
	idx := 0
	for pageId, page := range pageMap {
		pageObj, err := page.Object()
		if err != nil {
			panic(err)
		}
		title, err := pageObj.GetString("title")
		if err != nil {
			panic(err)
		}
		if pageId == "-1" {
			fmt.Println(title)
			fmt.Println("File does not exist, possibly deleted.")
			continue
		}
		make := ""
		model := ""
		imageinfo, err := pageObj.GetObjectArray("imageinfo")
		if err == nil {
			make, model = ExtractCamera(imageinfo[0])
		}
		pageArray = pageArray[0:idx + 1]
		pageArray[idx] = FileCamera{title, make, model}
		idx++
	}
	return pageArray
}
<|endoftext|>


<commit_before>package refctx

import (
	"context"
	"sync/atomic"

	"github.com/SentimensRG/ctx"
)

// RefCtr cancels a context when no references are held
type RefCtr struct {
	cancel func()
	refcnt uint32
}

// Incr increments the refcount
func (r *RefCtr) Incr() { r.Add(1) }

// Add i refcounts
func (r *RefCtr) Add(i uint32) {
	if v := atomic.AddUint32(&r.refcnt, i); v == 0 {
		r.cancel()
	}
}

// Decr decrements the refcount
func (r *RefCtr) Decr() { atomic.AddUint32(&r.refcnt, ^uint32(0)) }

// WithRefCount derives a ctx.C that will be cancelled when all references are
// freed
func WithRefCount(d ctx.Doner) (ctx.C, *RefCtr) {
	ch, cancel := ctx.WithCancel(d)
	return ch, &RefCtr{cancel: cancel}
}

// ContextWithRefCount derives a context that will be cancelled when all
// references are freed.
func ContextWithRefCount(c context.Context) (context.Context, *RefCtr) {
	c, cancel := context.WithCancel(c)
	return c, &RefCtr{cancel: cancel}
}
<commit_msg>Pass Decr call to Add<commit_after>package refctx

import (
	"context"
	"sync/atomic"

	"github.com/SentimensRG/ctx"
)

// RefCtr cancels a context when no references are held
type RefCtr struct {
	cancel func()
	refcnt uint32
}

// Incr increments the refcount
func (r *RefCtr) Incr() { r.Add(1) }

// Add i refcounts
func (r *RefCtr) Add(i uint32) {
	if v := atomic.AddUint32(&r.refcnt, i); v == 0 {
		r.cancel()
	}
}

// Decr decrements the refcount
func (r *RefCtr) Decr() { r.Add(^uint32(0)) }

// WithRefCount derives a ctx.C that will be cancelled when all references are
// freed
func WithRefCount(d ctx.Doner) (ctx.C, *RefCtr) {
	ch, cancel := ctx.WithCancel(d)
	return ch, &RefCtr{cancel: cancel}
}

// ContextWithRefCount derives a context that will be cancelled when all
// references are freed.
func ContextWithRefCount(c context.Context) (context.Context, *RefCtr) {
	c, cancel := context.WithCancel(c)
	return c, &RefCtr{cancel: cancel}
}
<|endoftext|>


<commit_before>// An implementation of Conway's Game of Life.
package main

import (
	"bytes"
	"fmt"
	"math/rand"
//	"os"
//	"strconv"
	"time"
	"flag"
)

// Field represents a two-dimensional field of cells.
type Field struct {
	s    [][]bool
	w, h int
}

// NewField returns an empty field of the specified width and height.
func NewField(w, h int) *Field {
	s := make([][]bool, h)
	for i := range s {
		s[i] = make([]bool, w)
	}
	return &Field{s: s, w: w, h: h}
}

// Set sets the state of the specified cell to the given value.
func (f *Field) Set(x, y int, b bool) {
	f.s[y][x] = b
}

// Alive reports whether the specified cell is alive.
// If the x or y coordinates are outside the field boundaries they are wrapped
// toroidally. For instance, an x value of -1 is treated as width-1.
func (f *Field) Alive(x, y int) bool {
	x += f.w
	x %= f.w
	y += f.h
	y %= f.h
	return f.s[y][x]
}

// Next returns the state of the specified cell at the next time step.
func (f *Field) Next(x, y int) bool {
	// Count the adjacent cells that are alive.
	alive := 0
	for i := -1; i <= 1; i++ {
		for j := -1; j <= 1; j++ {
			if (j != 0 || i != 0) && f.Alive(x+i, y+j) {
				alive++
			}
		}
	}
	// Return next state according to the game rules:
	//   exactly 3 neighbors: on,
	//   exactly 2 neighbors: maintain current state,
	//   otherwise: off.
	return alive == 3 || alive == 2 && f.Alive(x, y)
}

// Life stores the state of a round of Conway's Game of Life.
type Life struct {
	a, b *Field
	w, h, g int

}

// NewLife returns a new Life game state with a random initial state.
func NewLife(w, h int) *Life {
	a := NewField(w, h)
	for i := 0; i < (w * h / 4); i++ {
		a.Set(rand.Intn(w), rand.Intn(h), true)
	}
	return &Life{
		a: a, b: NewField(w, h),
		w: w, h: h,
	}
}

// Step advances the game by one instant, recomputing and updating all cells.
func (l *Life) step() {
	// Update the state of the next field (b) from the current field (a).
	for y := 0; y < l.h; y++ {
		for x := 0; x < l.w; x++ {
			l.b.Set(x, y, l.a.Next(x, y))
		}
	}
	// Swap fields a and b.
	l.a, l.b = l.b, l.a

	// increment generation count
    l.g++
}

// String returns the game board as a string.
func (l *Life) String() string {
	var buf bytes.Buffer
	for y := 0; y < l.h; y++ {
		for x := 0; x < l.w; x++ {
			b := byte(' ')
			if l.a.Alive(x, y) {
				b = '*'
			}
			buf.WriteByte(' ')
			buf.WriteByte(b)
		}
		buf.WriteByte('\n')
	}
	return buf.String()
}

func (l *Life) show() {
    fmt.Printf("\n\n\n\nGeneration %d of %d:\n\n%s", l.g, gens, l)
}

func (l *Life) simulate(gens int, delay time.Duration) {
    for i := 0; i < gens; i++ {
       l.step()
       l.show()
       time.Sleep(delay)
    }
    fmt.Printf("%v generations, %v x %v grid, seed=%v\n", l.g, l.h, l.w, seed)
}

var (
   seed int64
   gens int
)

func initSeed() {
    if seed == 0 {
        seed = time.Now().UnixNano()
    }
	rand.Seed(seed)
}

func parseCommandLineFlags() (width, height, perSec int) {

    flag.Int64Var(&seed, "seed", 0,
       "seed for initial population; default will use random N")

	flag.IntVar(&height, "h", 30, "height of simulation field")
	flag.IntVar(&width, "w", 30, "width of simulation field")
	flag.IntVar(&gens, "n", 20, "simulate N generations")
    flag.IntVar(&perSec, "d",  5, "delay 1/N seconds between generations")

    flag.Parse()

    initSeed()

    return

//    gens, _ := strconv.Atoi(os.Args[1])
//    perSec, _ := strconv.Atoi(os.Args[2])

//	hPtr := flag.Int("h", 30, "height of simulation field")
//	wPtr := flag.Int("w", 30, "width of simulation field")
//	gPtr := flag.Int("n", 20, "simulate n generations")
//   pPtr := flag.Int("d",  5, "delay 1/d seconds between generations")

//    width = *wPtr
//    height = *hPtr
//    gens = *gPtr
//    perSec = *pPtr
}

func main() {

    width, height, perSec := parseCommandLineFlags()

	NewLife(width, height).simulate(
	   gens,
	   time.Second / time.Duration(perSec),
	)
}
<commit_msg>Modified default fmt.Usage<commit_after>// My mods to the Go implementation of Conway's Game of Life.
//
// based on https://golang.org/doc/play/life.go
//
package main

import (
	"bytes"
	"flag"
	"fmt"
	"math/rand"
	"os"
	"time"
)

const (
	deadcell = "  "
	// \u263A smile-white
	// \u263B smile-black
	// \u26AA dot-white
	// \u26B1 little-man
	// \u26F9 man-dribble

	liveAster1   = " \u2731"
	liveAster2   = " \u2749"
	liveBug      = " \u2603"
	liveCircleX  = " \u2A02"
	liveDotStar  = " \u272A"
	liveFatX     = " \u2716"
	liveGreenX   = " \u274E"
	liveLilman   = " \u26B1"
	liveNoEntry  = " \u26D4"
	liveRedHat   = " \u26D1"
	liveSkullX   = " \u2620"
	liveSnowman  = " \u26C4"
	liveStar     = " \u2606"
	liveWhiteDot = " \u26AA"
)

var (
	seed     int64
	gens     int
	skipto   int
	livename string
	livecell []byte
)

// Field represents a two-dimensional field of cells.
type Field struct {
	s    [][]bool
	w, h int
}

// NewField returns an empty field of the specified width and height.
func NewField(w, h int) *Field {
	s := make([][]bool, h)
	for i := range s {
		s[i] = make([]bool, w)
	}
	return &Field{s: s, w: w, h: h}
}

// Set sets the state of the specified cell to the given value.
func (f *Field) Set(x, y int, b bool) {
	f.s[y][x] = b
}

// Alive reports whether the specified cell is alive.
// If the x or y coordinates are outside the field boundaries they are wrapped
// toroidally. For instance, an x value of -1 is treated as width-1.
func (f *Field) Alive(x, y int) bool {
	x += f.w
	x %= f.w
	y += f.h
	y %= f.h
	return f.s[y][x]
}

// Next returns the state of the specified cell at the next time step.
func (f *Field) Next(x, y int) bool {
	// Count the adjacent cells that are alive.
	alive := 0
	for i := -1; i <= 1; i++ {
		for j := -1; j <= 1; j++ {
			if (j != 0 || i != 0) && f.Alive(x+i, y+j) {
				alive++
			}
		}
	}
	// Return next state according to the game rules:
	//   exactly 3 neighbors: on,
	//   exactly 2 neighbors: maintain current state,
	//   otherwise: off.
	return alive == 3 || alive == 2 && f.Alive(x, y)
}

// Life stores the state of a round of Conway's Game of Life.
type Life struct {
	a, b    *Field
	w, h, g int
}

// NewLife returns a new Life game state with a random initial state.
func NewLife(w, h int) *Life {
	a := NewField(w, h)
	for i := 0; i < (w * h / 4); i++ {
		a.Set(rand.Intn(w), rand.Intn(h), true)
	}
	return &Life{
		a: a, b: NewField(w, h),
		w: w, h: h,
	}
}

// Step advances the game by one instant, recomputing and updating all cells.
func (l *Life) step() {
	// Update the state of the next field (b) from the current field (a).
	for y := 0; y < l.h; y++ {
		for x := 0; x < l.w; x++ {
			l.b.Set(x, y, l.a.Next(x, y))
		}
	}
	// Swap fields a and b.
	l.a, l.b = l.b, l.a

	// increment generation count
	l.g++
}

// String returns the game board as a string.
func (l *Life) String() string {
	var buf bytes.Buffer
	for y := 0; y < l.h; y++ {
		for x := 0; x < l.w; x++ {
			cell := []byte(deadcell)
			if l.a.Alive(x, y) {
				cell = livecell
			}
			buf.Write(cell)
		}
		buf.WriteByte('\n')
	}
	return buf.String()
}

func (l *Life) showGeneration(nth int) {
	fmt.Printf("\n\nGeneration %v (%v of %v):\n\n%v", l.g, nth-skipto, gens, l)
}

func (l *Life) simulate(gens int, delay time.Duration) {

	fmt.Printf("\nConway's Game of Life\n")

	if skipto != 0 {
		fmt.Printf("\nStarting from generation %v...", skipto)
	}

	maxgen := gens + skipto
	skipto--
	for i := 0; i < maxgen; i++ {
		l.step()
		if skipto <= i {
			l.showGeneration(i)
			time.Sleep(delay)
		}
	}

	fmt.Printf("%v generations, %v x %v grid, seed=%v\n\n", l.g, l.h, l.w, seed)
}

func initSeed() {
	if seed == 0 {
		seed = time.Now().UnixNano()
	}
	rand.Seed(seed)
}

func initLiveCell() {
	switch livename {
	case "aster-1":
		livecell = []byte(liveAster1)
	case "aster-2":
		livecell = []byte(liveAster2)
	case "bug":
		livecell = []byte(liveBug)
	case "circle-x":
		livecell = []byte(liveCircleX)
	case "dot-star":
		livecell = []byte(liveDotStar)
	case "fat-x":
		livecell = []byte(liveFatX)
	case "green-x":
		livecell = []byte(liveGreenX)
	case "little-man":
		livecell = []byte(liveLilman)
	case "redhat":
		livecell = []byte(liveRedHat)
	case "skull-x":
		livecell = []byte(liveSkullX)
	case "snowman":
		livecell = []byte(liveSnowman)
	case "star":
		livecell = []byte(liveStar)
	default:
		livecell = []byte(liveWhiteDot)
	}
}

func checkSkipping() {
	if skipto < 0 {
		skipto = 0
	}
}

func parseflags() (width, height, perSec int) {

	flag.Int64Var(&seed, "seed", 0,
		"seed for initial population (default random)")

	flag.IntVar(&perSec, "d", 5, "delay 1/`N` seconds between generations")
	flag.IntVar(&height, "h", 30, "height of simulation field")
	flag.IntVar(&width, "w", 30, "width of simulation field")
	flag.IntVar(&gens, "n", 20, "display up to `N` generations")
	flag.IntVar(&skipto, "from", 0, "display from generation `N`")
	flag.StringVar(&livename, "live", "", "`name` of dingbat used to depict a live cell (default whitedot)")

	flag.Parse()

	initSeed()
	initLiveCell()
	checkSkipping()

	return
}

func addUsageInfo() {
	defaultUsage := flag.Usage
	flag.Usage = func() {
		defaultUsage()
		fmt.Fprintf(os.Stderr,
			"\nAvailable dingbats for live cells:\n\n"+
				"Name    \tDescription\n"+
				"--------\t-----------\n"+
				"aster-1 \tAsterisk 1\n"+
				"aster-2 \tAsterisk 2\n"+
				"bug     \tBug\n"+
				"circle-x\tWhite circle with an X\n"+
				"dot-star\tDot with star\n"+
				"fat-x   \tFat white X\n"+
				"green-x \tGreen square with white X\n"+
				"little-man\tLittle yellow man\n"+
				"no-entry\tRed no entry sign\n"+
				"redhat  \tRed hardhat with white cross\n"+
				"skull-x \tSkull and crossbones\n"+
				"snowman \tSnowman\n"+
				"star    \tWhite star\n"+
				"whitedot\tWhite dot (default)\n",
		)
	}
}

func main() {

	addUsageInfo()

	width, height, perSec := parseflags()

	NewLife(width, height).simulate(
		gens,
		time.Second/time.Duration(perSec),
	)
}
<|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 clnt

import (
	"net"
	"syscall"
	"go9p.googlecode.com/hg/p"
)

// Creates an authentication fid for the specified user. Returns the fid, if
// successful, or an Error.
func (clnt *Clnt) Auth(user p.User, aname string) (*Fid, *p.Error) {
	fid := clnt.FidAlloc()
	tc := clnt.NewFcall()
	err := p.PackTauth(tc, fid.Fid, user.Name(), aname, uint32(user.Id()), clnt.Dotu)
	if err != nil {
		return nil, err
	}

	_, err = clnt.Rpc(tc)
	if err != nil {
		return nil, err
	}

	fid.User = user
	return fid, nil
}

// Creates a fid for the specified user that points to the root
// of the file server's file tree. Returns a Fid pointing to the root,
// if successful, or an Error.
func (clnt *Clnt) Attach(afid *Fid, user p.User, aname string) (*Fid, *p.Error) {
	var afno uint32

	if afid != nil {
		afno = afid.Fid
	} else {
		afno = p.NOFID
	}

	fid := clnt.FidAlloc()
	tc := clnt.NewFcall()
	err := p.PackTattach(tc, fid.Fid, afno, user.Name(), aname, uint32(user.Id()), clnt.Dotu)
	if err != nil {
		return nil, err
	}

	rc, err := clnt.Rpc(tc)
	if err != nil {
		return nil, err
	}
	if rc.Type == p.Rerror {
		return nil, &p.Error{rc.Error, int(rc.Errornum)}
	}

	fid.Qid = rc.Qid
	fid.User = user
	return fid, nil
}

// Connects to a file server and attaches to it as the specified user.
func Mount(ntype, addr, aname string, user p.User) (*Clnt, *p.Error) {
	c, e := net.Dial(ntype, "", addr)
	if e != nil {
		return nil, &p.Error{e.String(), syscall.EIO}
	}

	return MountConn(c, aname, user)
}

func MountConn(c net.Conn, aname string, user p.User) (*Clnt, *p.Error) {
	clnt, err := Connect(c, 8192+p.IOHDRSZ, true)
	if err != nil {
		return nil, err
	}

	fid, err := clnt.Attach(nil, user, aname)
	if err != nil {
		clnt.Unmount()
		return nil, err
	}

	clnt.Root = fid
	return clnt, nil
}

// Closes the connection to the file sever.
func (clnt *Clnt) Unmount() {
	clnt.Lock()
	clnt.err = &p.Error{"connection closed", syscall.ECONNRESET}
	clnt.conn.Close()
	clnt.Unlock()
}
<commit_msg>Mark the auth and attached fid as walked so they are clunked when no longer referenced.<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 clnt

import (
	"net"
	"syscall"
	"go9p.googlecode.com/hg/p"
)

// Creates an authentication fid for the specified user. Returns the fid, if
// successful, or an Error.
func (clnt *Clnt) Auth(user p.User, aname string) (*Fid, *p.Error) {
	fid := clnt.FidAlloc()
	tc := clnt.NewFcall()
	err := p.PackTauth(tc, fid.Fid, user.Name(), aname, uint32(user.Id()), clnt.Dotu)
	if err != nil {
		return nil, err
	}

	_, err = clnt.Rpc(tc)
	if err != nil {
		return nil, err
	}

	fid.User = user
	fid.walked = true
	return fid, nil
}

// Creates a fid for the specified user that points to the root
// of the file server's file tree. Returns a Fid pointing to the root,
// if successful, or an Error.
func (clnt *Clnt) Attach(afid *Fid, user p.User, aname string) (*Fid, *p.Error) {
	var afno uint32

	if afid != nil {
		afno = afid.Fid
	} else {
		afno = p.NOFID
	}

	fid := clnt.FidAlloc()
	tc := clnt.NewFcall()
	err := p.PackTattach(tc, fid.Fid, afno, user.Name(), aname, uint32(user.Id()), clnt.Dotu)
	if err != nil {
		return nil, err
	}

	rc, err := clnt.Rpc(tc)
	if err != nil {
		return nil, err
	}
	if rc.Type == p.Rerror {
		return nil, &p.Error{rc.Error, int(rc.Errornum)}
	}

	fid.Qid = rc.Qid
	fid.User = user
	fid.walked = true
	return fid, nil
}

// Connects to a file server and attaches to it as the specified user.
func Mount(ntype, addr, aname string, user p.User) (*Clnt, *p.Error) {
	c, e := net.Dial(ntype, "", addr)
	if e != nil {
		return nil, &p.Error{e.String(), syscall.EIO}
	}

	return MountConn(c, aname, user)
}

func MountConn(c net.Conn, aname string, user p.User) (*Clnt, *p.Error) {
	clnt, err := Connect(c, 8192+p.IOHDRSZ, true)
	if err != nil {
		return nil, err
	}

	fid, err := clnt.Attach(nil, user, aname)
	if err != nil {
		clnt.Unmount()
		return nil, err
	}

	clnt.Root = fid
	return clnt, nil
}

// Closes the connection to the file sever.
func (clnt *Clnt) Unmount() {
	clnt.Lock()
	clnt.err = &p.Error{"connection closed", syscall.ECONNRESET}
	clnt.conn.Close()
	clnt.Unlock()
}
<|endoftext|>


<commit_before>package parser

import (
	"io"
	"io/ioutil"
	"os"
	"strings"
)

// Lexer is a token scanner
type Lexer struct {
	c    *cursor
	last *Tok
	hold *Tok
}

// NewLexer creates a lexer for an io stream.
// It will close the stream automatically when the lexing ends.
func NewLexer(file string, r io.ReadCloser) *Lexer {
	ret := new(Lexer)
	ret.c = newCursor(file, r)

	return ret
}

func (lex *Lexer) emitTok(t *Tok) {
	lex.hold = t
	if lex.hold.Type != TypeComment {
		lex.last = t
	}
}

func (lex *Lexer) emitType(t Type) {
	tok := lex.c.Token(t)
	lex.emitTok(tok)
}

func (lex *Lexer) skipEndl() bool {
	if lex.last == nil {
		return true
	}
	t := lex.last.Type

	switch t {
	case TypeIdent, TypeInt, TypeFloat, TypeString:
		return false
	case TypeOperator:
		lit := lex.last.Lit
		return !(lit == "}" || lit == "]" || lit == ")")
	}

	return true
}

func (lex *Lexer) scanInt() {
	for lex.c.Scan() {
		r := lex.c.Next()
		if !isDigit(r) {
			break
		}
	}

	lex.emitType(TypeInt)
}

func (lex *Lexer) scanIdent() {
	for lex.c.Scan() {
		r := lex.c.Next()
		if !isDigit(r) && !isLetter(r) {
			break
		}
	}

	lex.emitType(TypeIdent)
}

func (lex *Lexer) scanLineComment() {
	for lex.c.Scan() {
		r := lex.c.Next()
		if r == '\n' {
			break
		}
	}

	lex.emitType(TypeComment)
}

func (lex *Lexer) scanBlockComment() {
	var star bool
	var complete bool

	for lex.c.Scan() {
		r := lex.c.Next()
		if star && r == '/' {
			lex.c.Accept()
			complete = true
			break
		}

		star = r == '*'
	}

	lex.emitType(TypeComment)
	if !complete {
		// TODO: report imcomplete block comment parsing error
	}
}

func (lex *Lexer) isWhite(r rune) bool {
	if isWhite(r) {
		return true
	}

	if r == '\n' {
		return lex.skipEndl()
	}

	return false
}

func (lex *Lexer) skipWhite() {
	if lex.c.EOF() || !lex.isWhite(lex.c.Next()) {
		return // no white to skip
	}

	for lex.c.Scan() {
		r := lex.c.Next()
		if !lex.isWhite(r) {
			break
		}
	}

	lex.c.Discard()
}

func (lex *Lexer) scanOperator() {
	r := lex.c.Next()

	if lex.c.Scan() && r == '/' {
		r2 := lex.c.Next()

		if r2 == '/' {
			lex.scanLineComment()
			return
		} else if r2 == '*' {
			lex.scanBlockComment()
			return
		}
	}

	if r == '\n' && lex.skipEndl() {
		panic("bug")
	}

	lex.emitType(TypeOperator)
}

func (lex *Lexer) scanInvalid() {
	lex.c.Accept()
	lex.emitType(TypeInvalid)
}

// Scan returns true where there is a new token
func (lex *Lexer) Scan() bool {
	lex.skipWhite()

	if lex.c.EOF() {
		return false
	}
	r := lex.c.Next()

	if isDigit(r) {
		lex.scanInt()
	} else if isLetter(r) {
		lex.scanIdent()
	} else if isOperator(r) {
		lex.scanOperator()
	} else {
		lex.scanInvalid()
	}

	return true
}

// IOErr returns the IO error on scanning.
func (lex *Lexer) IOErr() error {
	return lex.c.Err()
}

// LexFile creates a lexer over a file.
func LexFile(path string) (*Lexer, error) {
	f, e := os.Open(path)
	if e != nil {
		return nil, e
	}

	return NewLexer(path, f), nil
}

// LexString creates a lexer over a string.
func LexString(file, s string) *Lexer {
	r := ioutil.NopCloser(strings.NewReader(s))
	return NewLexer(file, r)
}
<commit_msg>token<commit_after>package parser

import (
	"io"
	"io/ioutil"
	"os"
	"strings"
)

// Lexer is a token scanner
type Lexer struct {
	c    *cursor
	last *Tok
	hold *Tok
}

// NewLexer creates a lexer for an io stream.
// It will close the stream automatically when the lexing ends.
func NewLexer(file string, r io.ReadCloser) *Lexer {
	ret := new(Lexer)
	ret.c = newCursor(file, r)

	return ret
}

func (lex *Lexer) emitTok(t *Tok) {
	lex.hold = t
	if lex.hold.Type != TypeComment {
		lex.last = t
	}
}

func (lex *Lexer) emitType(t Type) {
	tok := lex.c.Token(t)
	lex.emitTok(tok)
}

func (lex *Lexer) skipEndl() bool {
	if lex.last == nil {
		return true
	}
	t := lex.last.Type

	switch t {
	case TypeIdent, TypeInt, TypeFloat, TypeString:
		return false
	case TypeOperator:
		lit := lex.last.Lit
		return !(lit == "}" || lit == "]" || lit == ")")
	}

	return true
}

func (lex *Lexer) scanInt() {
	for lex.c.Scan() {
		r := lex.c.Next()
		if !isDigit(r) {
			break
		}
	}

	lex.emitType(TypeInt)
}

func (lex *Lexer) scanIdent() {
	for lex.c.Scan() {
		r := lex.c.Next()
		if !isDigit(r) && !isLetter(r) {
			break
		}
	}

	lex.emitType(TypeIdent)
}

func (lex *Lexer) scanLineComment() {
	for lex.c.Scan() {
		r := lex.c.Next()
		if r == '\n' {
			break
		}
	}

	lex.emitType(TypeComment)
}

func (lex *Lexer) scanBlockComment() {
	var star bool
	var complete bool

	for lex.c.Scan() {
		r := lex.c.Next()
		if star && r == '/' {
			lex.c.Accept()
			complete = true
			break
		}

		star = r == '*'
	}

	lex.emitType(TypeComment)
	if !complete {
		// TODO: report imcomplete block comment parsing error
	}
}

func (lex *Lexer) isWhite(r rune) bool {
	if isWhite(r) {
		return true
	}

	if r == '\n' {
		return lex.skipEndl()
	}

	return false
}

func (lex *Lexer) skipWhite() {
	if lex.c.EOF() || !lex.isWhite(lex.c.Next()) {
		return // no white to skip
	}

	for lex.c.Scan() {
		r := lex.c.Next()
		if !lex.isWhite(r) {
			break
		}
	}

	lex.c.Discard()
}

func (lex *Lexer) scanOperator() {
	r := lex.c.Next()

	if lex.c.Scan() && r == '/' {
		r2 := lex.c.Next()

		if r2 == '/' {
			lex.scanLineComment()
			return
		} else if r2 == '*' {
			lex.scanBlockComment()
			return
		}
	}

	if r == '\n' && lex.skipEndl() {
		panic("bug")
	}

	lex.emitType(TypeOperator)
}

func (lex *Lexer) scanInvalid() {
	lex.c.Accept()
	lex.emitType(TypeInvalid)
}

// Scan returns true where there is a new token
func (lex *Lexer) Scan() bool {
	lex.skipWhite()

	if lex.c.EOF() {
		return false
	}
	r := lex.c.Next()

	if isDigit(r) {
		lex.scanInt()
	} else if isLetter(r) {
		lex.scanIdent()
	} else if isOperator(r) {
		lex.scanOperator()
	} else {
		lex.scanInvalid()
	}

	return true
}

// Token returns the current token.
func (lex *Lexer) Token() *Tok {
	return lex.hold
}

// IOErr returns the IO error on scanning.
func (lex *Lexer) IOErr() error {
	return lex.c.Err()
}

// LexFile creates a lexer over a file.
func LexFile(path string) (*Lexer, error) {
	f, e := os.Open(path)
	if e != nil {
		return nil, e
	}

	return NewLexer(path, f), nil
}

// LexString creates a lexer over a string.
func LexString(file, s string) *Lexer {
	r := ioutil.NopCloser(strings.NewReader(s))
	return NewLexer(file, r)
}
<|endoftext|>


<commit_before>/*
Copyright 2016 The Kubernetes Authors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package bootstrappolicy

import (
	"k8s.io/kubernetes/pkg/api"
	rbac "k8s.io/kubernetes/pkg/apis/rbac"
)

var (
	readWrite = []string{"get", "list", "watch", "create", "update", "patch", "delete", "deletecollection"}
	read      = []string{"get", "list", "watch"}

	legacyGroup = ""
)

// ClusterRoles returns the cluster roles to bootstrap an API server with
func ClusterRoles() []rbac.ClusterRole {
	return []rbac.ClusterRole{
		{
			ObjectMeta: api.ObjectMeta{Name: "cluster-admin"},
			Rules: []rbac.PolicyRule{
				rbac.NewRule("*").Groups("*").Resources("*").RuleOrDie(),
				rbac.NewRule("*").URLs("*").RuleOrDie(),
			},
		},
	}
}
<commit_msg>add system:discovery role<commit_after>/*
Copyright 2016 The Kubernetes Authors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package bootstrappolicy

import (
	"k8s.io/kubernetes/pkg/api"
	rbac "k8s.io/kubernetes/pkg/apis/rbac"
)

var (
	readWrite = []string{"get", "list", "watch", "create", "update", "patch", "delete", "deletecollection"}
	read      = []string{"get", "list", "watch"}

	legacyGroup = ""
)

// ClusterRoles returns the cluster roles to bootstrap an API server with
func ClusterRoles() []rbac.ClusterRole {
	return []rbac.ClusterRole{
		{
			// a "root" role which can do absolutely anything
			ObjectMeta: api.ObjectMeta{Name: "cluster-admin"},
			Rules: []rbac.PolicyRule{
				rbac.NewRule("*").Groups("*").Resources("*").RuleOrDie(),
				rbac.NewRule("*").URLs("*").RuleOrDie(),
			},
		},
		{
			// a role which provides just enough power to discovery API versions for negotiation
			ObjectMeta: api.ObjectMeta{Name: "system:discovery"},
			Rules: []rbac.PolicyRule{
				rbac.NewRule("get").URLs("/version", "/api", "/api/*", "/apis", "/apis/*").RuleOrDie(),
			},
		},
	}
}
<|endoftext|>


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

package strfmt

import (
	"database/sql"
	"database/sql/driver"
	"testing"
	"time"

	"github.com/stretchr/testify/assert"
)

var _ sql.Scanner = &Date{}
var _ driver.Valuer = Date{}

func TestDate(t *testing.T) {
	pp := Date{}
	err := pp.UnmarshalText([]byte{})
	assert.NoError(t, err)
	err = pp.UnmarshalText([]byte("yada"))
	assert.Error(t, err)
	orig := "2014-12-15"
	err = pp.UnmarshalText([]byte(orig))
	assert.NoError(t, err)
	txt, err := pp.MarshalText()
	assert.NoError(t, err)
	assert.Equal(t, orig, string(txt))
}

func TestDate_Scan(t *testing.T) {
	ref := time.Now().Truncate(24 * time.Hour).UTC()
	date, str := Date{ref}, ref.Format(RFC3339FullDate)

	values := []interface{}{str, []byte(str), ref}
	for _, value := range values {
		result := Date{}
		(&result).Scan(value)
		assert.Equal(t, date, result, "value: %#v", value)
	}
}

func TestDate_Value(t *testing.T) {
	ref := time.Now().Truncate(24 * time.Hour).UTC()
	date := Date{ref}
	dbv, err := date.Value()
	assert.NoError(t, err)
	assert.Equal(t, dbv, ref)
}
<commit_msg>fixes #92 structs can't have more than one swagger function<commit_after>// Copyright 2015 go-swagger maintainers
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//    http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package strfmt

import (
	"database/sql"
	"database/sql/driver"
	"testing"
	"time"

	"github.com/stretchr/testify/assert"
)

var _ sql.Scanner = &Date{}
var _ driver.Valuer = Date{}

func TestDate(t *testing.T) {
	pp := Date{}
	err := pp.UnmarshalText([]byte{})
	assert.NoError(t, err)
	err = pp.UnmarshalText([]byte("yada"))
	assert.Error(t, err)
	orig := "2014-12-15"
	err = pp.UnmarshalText([]byte(orig))
	assert.NoError(t, err)
	txt, err := pp.MarshalText()
	assert.NoError(t, err)
	assert.Equal(t, orig, string(txt))
}

func TestDate_Scan(t *testing.T) {
	ref := time.Now().Truncate(24 * time.Hour).UTC()
	date, str := Date{ref}, ref.Format(RFC3339FullDate)

	values := []interface{}{str, []byte(str), ref}
	for _, value := range values {
		result := Date{}
		(&result).Scan(value)
		assert.Equal(t, date, result, "value: %#v", value)
	}
}

func TestDate_Value(t *testing.T) {
	ref := time.Now().Truncate(24 * time.Hour).UTC()
	date := Date{ref}
	dbv, err := date.Value()
	assert.NoError(t, err)
	assert.Equal(t, dbv, ref)
}
<|endoftext|>