<commit_before>/*
Copyright 2020 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 main

import (
	"context"
	"encoding/json"
	"fmt"
	"io"

	"k8s.io/kubectl/pkg/util/i18n"
	"k8s.io/kubectl/pkg/util/templates"
	"sigs.k8s.io/yaml"

	"k8s.io/kops/util/pkg/tables"

	"github.com/spf13/cobra"
	"k8s.io/kops/cmd/kops/util"
	"k8s.io/kops/upup/pkg/fi/cloudup"
)

type Image struct {
	Image  string `json:"image"`
	Mirror string `json:"mirror"`
}

type File struct {
	File   string `json:"file"`
	Mirror string `json:"mirror"`
	SHA    string `json:"sha"`
}

type AssetResult struct {
	// Images are the image assets we use (output).
	Images []*Image `json:"images,omitempty"`
	// FileAssets are the file assets we use (output).
	Files []*File `json:"files,omitempty"`
}

func NewCmdGetAssets(f *util.Factory, out io.Writer, options *GetOptions) *cobra.Command {
	getAssetsShort := i18n.T(`Display assets for cluster.`)

	getAssetsLong := templates.LongDesc(i18n.T(`
	Display assets for cluster.`))

	getAssetsExample := templates.Examples(i18n.T(`
	# Display all assets.
	kops get assets
	`))

	cmd := &cobra.Command{
		Use:     "assets",
		Short:   getAssetsShort,
		Long:    getAssetsLong,
		Example: getAssetsExample,
		Run: func(cmd *cobra.Command, args []string) {
			ctx := context.TODO()

			if err := rootCommand.ProcessArgs(args); err != nil {
				exitWithError(err)
			}

			err := RunGetAssets(ctx, f, out, options)
			if err != nil {
				exitWithError(err)
			}
		},
	}

	return cmd
}

func RunGetAssets(ctx context.Context, f *util.Factory, out io.Writer, options *GetOptions) error {

	clusterName := rootCommand.ClusterName()
	options.clusterName = clusterName
	if clusterName == "" {
		return fmt.Errorf("--name is required")
	}

	updateClusterResults, err := RunUpdateCluster(ctx, f, clusterName, out, &UpdateClusterOptions{
		Target: cloudup.TargetDryRun,
		Phase:  string(cloudup.PhaseStageAssets),
		Quiet:  true,
	})
	if err != nil {
		return err
	}

	result := AssetResult{
		Images: make([]*Image, 0, len(updateClusterResults.ImageAssets)),
		Files:  make([]*File, 0, len(updateClusterResults.FileAssets)),
	}

	seen := map[string]bool{}
	for _, containerAsset := range updateClusterResults.ImageAssets {
		image := Image{
			Image:  containerAsset.CanonicalLocation,
			Mirror: containerAsset.DownloadLocation,
		}
		if !seen[image.Image] {
			result.Images = append(result.Images, &image)
			seen[image.Image] = true
		}
	}
	seen = map[string]bool{}
	for _, fileAsset := range updateClusterResults.FileAssets {
		file := File{
			File:   fileAsset.CanonicalURL.String(),
			Mirror: fileAsset.DownloadURL.String(),
			SHA:    fileAsset.SHAValue,
		}
		if !seen[file.File] {
			result.Files = append(result.Files, &file)
			seen[file.File] = true
		}
	}

	switch options.output {
	case OutputTable:
		if err = containerOutputTable(result.Images, out); err != nil {
			return err
		}
		return fileOutputTable(result.Files, out)
	case OutputYaml:
		y, err := yaml.Marshal(result)
		if err != nil {
			return fmt.Errorf("unable to marshal YAML: %v", err)
		}
		if _, err := out.Write(y); err != nil {
			return fmt.Errorf("error writing to output: %v", err)
		}
	case OutputJSON:
		j, err := json.Marshal(result)
		if err != nil {
			return fmt.Errorf("unable to marshal JSON: %v", err)
		}
		if _, err := out.Write(j); err != nil {
			return fmt.Errorf("error writing to output: %v", err)
		}
	default:
		return fmt.Errorf("unsupported output format: %q", options.output)
	}

	return nil
}

func containerOutputTable(images []*Image, out io.Writer) error {
	fmt.Println("")
	t := &tables.Table{}
	t.AddColumn("IMAGE", func(i *Image) string {
		return i.Image
	})
	t.AddColumn("MIRROR", func(i *Image) string {
		return i.Mirror
	})

	columns := []string{"IMAGE", "MIRROR"}
	return t.Render(images, out, columns...)
}

func fileOutputTable(files []*File, out io.Writer) error {
	fmt.Println("")
	t := &tables.Table{}
	t.AddColumn("FILE", func(f *File) string {
		return f.File
	})
	t.AddColumn("MIRROR", func(f *File) string {
		return f.Mirror
	})
	t.AddColumn("SHA", func(f *File) string {
		return f.SHA
	})

	columns := []string{"FILE", "MIRROR", "SHA"}
	return t.Render(files, out, columns...)
}
<commit_msg>More "container" to "image" renaming<commit_after>/*
Copyright 2020 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 main

import (
	"context"
	"encoding/json"
	"fmt"
	"io"

	"k8s.io/kubectl/pkg/util/i18n"
	"k8s.io/kubectl/pkg/util/templates"
	"sigs.k8s.io/yaml"

	"k8s.io/kops/util/pkg/tables"

	"github.com/spf13/cobra"
	"k8s.io/kops/cmd/kops/util"
	"k8s.io/kops/upup/pkg/fi/cloudup"
)

type Image struct {
	Image  string `json:"image"`
	Mirror string `json:"mirror"`
}

type File struct {
	File   string `json:"file"`
	Mirror string `json:"mirror"`
	SHA    string `json:"sha"`
}

type AssetResult struct {
	// Images are the image assets we use (output).
	Images []*Image `json:"images,omitempty"`
	// FileAssets are the file assets we use (output).
	Files []*File `json:"files,omitempty"`
}

func NewCmdGetAssets(f *util.Factory, out io.Writer, options *GetOptions) *cobra.Command {
	getAssetsShort := i18n.T(`Display assets for cluster.`)

	getAssetsLong := templates.LongDesc(i18n.T(`
	Display assets for cluster.`))

	getAssetsExample := templates.Examples(i18n.T(`
	# Display all assets.
	kops get assets
	`))

	cmd := &cobra.Command{
		Use:     "assets",
		Short:   getAssetsShort,
		Long:    getAssetsLong,
		Example: getAssetsExample,
		Run: func(cmd *cobra.Command, args []string) {
			ctx := context.TODO()

			if err := rootCommand.ProcessArgs(args); err != nil {
				exitWithError(err)
			}

			err := RunGetAssets(ctx, f, out, options)
			if err != nil {
				exitWithError(err)
			}
		},
	}

	return cmd
}

func RunGetAssets(ctx context.Context, f *util.Factory, out io.Writer, options *GetOptions) error {

	clusterName := rootCommand.ClusterName()
	options.clusterName = clusterName
	if clusterName == "" {
		return fmt.Errorf("--name is required")
	}

	updateClusterResults, err := RunUpdateCluster(ctx, f, clusterName, out, &UpdateClusterOptions{
		Target: cloudup.TargetDryRun,
		Phase:  string(cloudup.PhaseStageAssets),
		Quiet:  true,
	})
	if err != nil {
		return err
	}

	result := AssetResult{
		Images: make([]*Image, 0, len(updateClusterResults.ImageAssets)),
		Files:  make([]*File, 0, len(updateClusterResults.FileAssets)),
	}

	seen := map[string]bool{}
	for _, imageAsset := range updateClusterResults.ImageAssets {
		image := Image{
			Image:  imageAsset.CanonicalLocation,
			Mirror: imageAsset.DownloadLocation,
		}
		if !seen[image.Image] {
			result.Images = append(result.Images, &image)
			seen[image.Image] = true
		}
	}
	seen = map[string]bool{}
	for _, fileAsset := range updateClusterResults.FileAssets {
		file := File{
			File:   fileAsset.CanonicalURL.String(),
			Mirror: fileAsset.DownloadURL.String(),
			SHA:    fileAsset.SHAValue,
		}
		if !seen[file.File] {
			result.Files = append(result.Files, &file)
			seen[file.File] = true
		}
	}

	switch options.output {
	case OutputTable:
		if err = imageOutputTable(result.Images, out); err != nil {
			return err
		}
		return fileOutputTable(result.Files, out)
	case OutputYaml:
		y, err := yaml.Marshal(result)
		if err != nil {
			return fmt.Errorf("unable to marshal YAML: %v", err)
		}
		if _, err := out.Write(y); err != nil {
			return fmt.Errorf("error writing to output: %v", err)
		}
	case OutputJSON:
		j, err := json.Marshal(result)
		if err != nil {
			return fmt.Errorf("unable to marshal JSON: %v", err)
		}
		if _, err := out.Write(j); err != nil {
			return fmt.Errorf("error writing to output: %v", err)
		}
	default:
		return fmt.Errorf("unsupported output format: %q", options.output)
	}

	return nil
}

func imageOutputTable(images []*Image, out io.Writer) error {
	fmt.Println("")
	t := &tables.Table{}
	t.AddColumn("IMAGE", func(i *Image) string {
		return i.Image
	})
	t.AddColumn("MIRROR", func(i *Image) string {
		return i.Mirror
	})

	columns := []string{"IMAGE", "MIRROR"}
	return t.Render(images, out, columns...)
}

func fileOutputTable(files []*File, out io.Writer) error {
	fmt.Println("")
	t := &tables.Table{}
	t.AddColumn("FILE", func(f *File) string {
		return f.File
	})
	t.AddColumn("MIRROR", func(f *File) string {
		return f.Mirror
	})
	t.AddColumn("SHA", func(f *File) string {
		return f.SHA
	})

	columns := []string{"FILE", "MIRROR", "SHA"}
	return t.Render(files, out, columns...)
}
<|endoftext|>


<commit_before>package filepathfilter

import (
	"fmt"
	"path/filepath"
	"regexp"
	"strings"
)

type Pattern interface {
	// HasPrefix returns whether the receiving Pattern will match a fullpath
	// that contains the prefix "prefix".
	//
	// For instance, if the receiving pattern were to match 'a/b/c.txt',
	// HasPrefix() will return true for:
	//
	//   - 'a', and 'a/'
	//   - 'a/b', and 'a/b/'
	HasPrefix(prefix string) bool

	Match(filename string) bool
	// String returns a string representation (see: regular expressions) of
	// the underlying pattern used to match filenames against this Pattern.
	String() string
}

type Filter struct {
	include []Pattern
	exclude []Pattern
}

func NewFromPatterns(include, exclude []Pattern) *Filter {
	return &Filter{include: include, exclude: exclude}
}

func New(include, exclude []string) *Filter {
	return NewFromPatterns(convertToPatterns(include), convertToPatterns(exclude))
}

// Include returns the result of calling String() on each Pattern in the
// include set of this *Filter.
func (f *Filter) Include() []string { return patternsToStrings(f.include...) }

// Exclude returns the result of calling String() on each Pattern in the
// exclude set of this *Filter.
func (f *Filter) Exclude() []string { return patternsToStrings(f.exclude...) }

// patternsToStrings maps the given set of Pattern's to a string slice by
// calling String() on each pattern.
func patternsToStrings(ps ...Pattern) []string {
	s := make([]string, 0, len(ps))
	for _, p := range ps {
		s = append(s, p.String())
	}

	return s
}

func (f *Filter) Allows(filename string) bool {
	_, allowed := f.AllowsPattern(filename)
	return allowed
}

// AllowsPattern returns whether the given filename is permitted by the
// inclusion/exclusion rules of this filter, as well as the pattern that either
// allowed or disallowed that filename.
//
// In special cases, such as a nil `*Filter` receiver, the absence of any
// patterns, or the given filename not being matched by any pattern, the empty
// string "" will be returned in place of the pattern.
func (f *Filter) AllowsPattern(filename string) (pattern string, allowed bool) {
	if f == nil {
		return "", true
	}

	if len(f.include)+len(f.exclude) == 0 {
		return "", true
	}

	cleanedName := filepath.Clean(filename)

	if len(f.include) > 0 {
		matched := false
		for _, inc := range f.include {
			matched = inc.Match(cleanedName)
			if matched {
				pattern = inc.String()
				break
			}
		}
		if !matched {
			return "", false
		}
	}

	if len(f.exclude) > 0 {
		for _, ex := range f.exclude {
			if ex.Match(cleanedName) {
				return ex.String(), false
			}
		}
	}

	return pattern, true
}

const (
	sep = string(filepath.Separator)
)

func NewPattern(rawpattern string) Pattern {
	cleanpattern := filepath.Clean(rawpattern)

	// Special case local dir, matches all (inc subpaths)
	if _, local := localDirSet[cleanpattern]; local {
		return noOpMatcher{}
	}

	hasPathSep := strings.Contains(cleanpattern, sep)
	ext := filepath.Ext(cleanpattern)
	plen := len(cleanpattern)
	if plen > 1 && !hasPathSep && strings.HasPrefix(cleanpattern, "*") && cleanpattern[1:plen] == ext {
		return &simpleExtPattern{ext: ext}
	}

	// special case * when there are no path separators
	// filepath.Match never allows * to match a path separator, which is correct
	// for gitignore IF the pattern includes a path separator, but not otherwise
	// So *.txt should match in any subdir, as should test*, but sub/*.txt would
	// only match directly in the sub dir
	// Don't need to test cross-platform separators as both cleaned above
	if !hasPathSep && strings.Contains(cleanpattern, "*") {
		pattern := regexp.QuoteMeta(cleanpattern)
		regpattern := fmt.Sprintf("^%s$", strings.Replace(pattern, "\\*", ".*", -1))
		return &pathlessWildcardPattern{
			rawPattern: cleanpattern,
			wildcardRE: regexp.MustCompile(regpattern),
		}
	}

	// Also support ** with path separators
	if hasPathSep && strings.Contains(cleanpattern, "**") {
		pattern := regexp.QuoteMeta(cleanpattern)
		regpattern := fmt.Sprintf("^%s$", strings.Replace(pattern, "\\*\\*", ".*", -1))
		return &doubleWildcardPattern{
			rawPattern: cleanpattern,
			wildcardRE: regexp.MustCompile(regpattern),
		}
	}

	if hasPathSep && strings.HasPrefix(cleanpattern, sep) {
		rel := cleanpattern[1:len(cleanpattern)]
		prefix := rel
		if strings.HasSuffix(rel, sep) {
			rel = rel[0 : len(rel)-1]
		} else {
			prefix += sep
		}

		return &pathPrefixPattern{
			rawPattern: cleanpattern,
			relative:   rel,
			prefix:     prefix,
		}
	}

	return &pathPattern{
		rawPattern: cleanpattern,
		prefix:     cleanpattern + sep,
		suffix:     sep + cleanpattern,
		inner:      sep + cleanpattern + sep,
	}
}

func convertToPatterns(rawpatterns []string) []Pattern {
	patterns := make([]Pattern, len(rawpatterns))
	for i, raw := range rawpatterns {
		patterns[i] = NewPattern(raw)
	}
	return patterns
}

type pathPrefixPattern struct {
	rawPattern string
	relative   string
	prefix     string
}

// Match is a revised version of filepath.Match which makes it behave more
// like gitignore
func (p *pathPrefixPattern) Match(name string) bool {
	if name == p.relative || strings.HasPrefix(name, p.prefix) {
		return true
	}
	matched, _ := filepath.Match(p.rawPattern, name)
	return matched
}

func (p *pathPrefixPattern) HasPrefix(name string) bool {
	return strings.HasPrefix(p.relative, name)
}

// String returns a string representation of the underlying pattern for which
// this *pathPrefixPattern is matching.
func (p *pathPrefixPattern) String() string {
	return p.rawPattern
}

type pathPattern struct {
	rawPattern string
	prefix     string
	suffix     string
	inner      string
}

// Match is a revised version of filepath.Match which makes it behave more
// like gitignore
func (p *pathPattern) Match(name string) bool {
	if strings.HasPrefix(name, p.prefix) || strings.HasSuffix(name, p.suffix) || strings.Contains(name, p.inner) {
		return true
	}
	matched, _ := filepath.Match(p.rawPattern, name)
	return matched
}

func (p *pathPattern) HasPrefix(name string) bool {
	return strings.HasPrefix(p.prefix, name)
}

// String returns a string representation of the underlying pattern for which
// this *pathPattern is matching.
func (p *pathPattern) String() string {
	return p.rawPattern
}

type simpleExtPattern struct {
	ext string
}

func (p *simpleExtPattern) Match(name string) bool {
	return strings.HasSuffix(name, p.ext)
}

func (p *simpleExtPattern) HasPrefix(name string) bool {
	return true
}

// String returns a string representation of the underlying pattern for which
// this *simpleExtPattern is matching.
func (p *simpleExtPattern) String() string {
	return fmt.Sprintf("*%s", p.ext)
}

type pathlessWildcardPattern struct {
	rawPattern string
	wildcardRE *regexp.Regexp
}

// Match is a revised version of filepath.Match which makes it behave more
// like gitignore
func (p *pathlessWildcardPattern) Match(name string) bool {
	matched, _ := filepath.Match(p.rawPattern, name)
	// Match the whole of the base name but allow matching in folders if no path
	return matched || p.wildcardRE.MatchString(filepath.Base(name))
}

func (p *pathlessWildcardPattern) HasPrefix(name string) bool {
	lit, ok := p.wildcardRE.LiteralPrefix()
	if !ok {
		return true
	}

	return strings.HasPrefix(name, lit)
}

// String returns a string representation of the underlying pattern for which
// this *pathlessWildcardPattern is matching.
func (p *pathlessWildcardPattern) String() string {
	return p.rawPattern
}

type doubleWildcardPattern struct {
	rawPattern string
	wildcardRE *regexp.Regexp
}

// Match is a revised version of filepath.Match which makes it behave more
// like gitignore
func (p *doubleWildcardPattern) Match(name string) bool {
	matched, _ := filepath.Match(p.rawPattern, name)
	// Match the whole of the base name but allow matching in folders if no path
	return matched || p.wildcardRE.MatchString(name)
}

func (p *doubleWildcardPattern) HasPrefix(name string) bool {
	lit, ok := p.wildcardRE.LiteralPrefix()
	if !ok {
		return true
	}

	return strings.HasPrefix(name, lit)
}

// String returns a string representation of the underlying pattern for which
// this *doubleWildcardPattern is matching.
func (p *doubleWildcardPattern) String() string {
	return p.rawPattern
}

type noOpMatcher struct {
}

func (n noOpMatcher) Match(name string) bool {
	return true
}

func (n noOpMatcher) HasPrefix(name string) bool {
	return true
}

func (n noOpMatcher) String() string {
	return ""
}

var localDirSet = map[string]struct{}{
	".":   struct{}{},
	"./":  struct{}{},
	".\\": struct{}{},
}
<commit_msg>filepathfilter: teach 'HasPrefix' to *Filter type<commit_after>package filepathfilter

import (
	"fmt"
	"path/filepath"
	"regexp"
	"strings"
)

type Pattern interface {
	// HasPrefix returns whether the receiving Pattern will match a fullpath
	// that contains the prefix "prefix".
	//
	// For instance, if the receiving pattern were to match 'a/b/c.txt',
	// HasPrefix() will return true for:
	//
	//   - 'a', and 'a/'
	//   - 'a/b', and 'a/b/'
	HasPrefix(prefix string) bool

	Match(filename string) bool
	// String returns a string representation (see: regular expressions) of
	// the underlying pattern used to match filenames against this Pattern.
	String() string
}

type Filter struct {
	include []Pattern
	exclude []Pattern
}

func NewFromPatterns(include, exclude []Pattern) *Filter {
	return &Filter{include: include, exclude: exclude}
}

func New(include, exclude []string) *Filter {
	return NewFromPatterns(convertToPatterns(include), convertToPatterns(exclude))
}

// Include returns the result of calling String() on each Pattern in the
// include set of this *Filter.
func (f *Filter) Include() []string { return patternsToStrings(f.include...) }

// Exclude returns the result of calling String() on each Pattern in the
// exclude set of this *Filter.
func (f *Filter) Exclude() []string { return patternsToStrings(f.exclude...) }

// patternsToStrings maps the given set of Pattern's to a string slice by
// calling String() on each pattern.
func patternsToStrings(ps ...Pattern) []string {
	s := make([]string, 0, len(ps))
	for _, p := range ps {
		s = append(s, p.String())
	}

	return s
}

func (f *Filter) Allows(filename string) bool {
	_, allowed := f.AllowsPattern(filename)
	return allowed
}

// HasPrefix returns whether the given prefix "prefix" is a prefix for all
// included Patterns, and not a prefix for any excluded Patterns.
func (f *Filter) HasPrefix(prefix string) bool {
	if f == nil {
		return true
	}

	parts := strings.Split(prefix, sep)

L:
	for i := len(parts); i > 0; i-- {
		prefix := strings.Join(parts[:i], sep)

		for _, p := range f.exclude {
			if p.Match(prefix) {
				break L
			}
		}

		for _, p := range f.include {
			if p.HasPrefix(prefix) {
				return true
			}
		}
	}
	return false
}

// AllowsPattern returns whether the given filename is permitted by the
// inclusion/exclusion rules of this filter, as well as the pattern that either
// allowed or disallowed that filename.
//
// In special cases, such as a nil `*Filter` receiver, the absence of any
// patterns, or the given filename not being matched by any pattern, the empty
// string "" will be returned in place of the pattern.
func (f *Filter) AllowsPattern(filename string) (pattern string, allowed bool) {
	if f == nil {
		return "", true
	}

	if len(f.include)+len(f.exclude) == 0 {
		return "", true
	}

	cleanedName := filepath.Clean(filename)

	if len(f.include) > 0 {
		matched := false
		for _, inc := range f.include {
			matched = inc.Match(cleanedName)
			if matched {
				pattern = inc.String()
				break
			}
		}
		if !matched {
			return "", false
		}
	}

	if len(f.exclude) > 0 {
		for _, ex := range f.exclude {
			if ex.Match(cleanedName) {
				return ex.String(), false
			}
		}
	}

	return pattern, true
}

const (
	sep = string(filepath.Separator)
)

func NewPattern(rawpattern string) Pattern {
	cleanpattern := filepath.Clean(rawpattern)

	// Special case local dir, matches all (inc subpaths)
	if _, local := localDirSet[cleanpattern]; local {
		return noOpMatcher{}
	}

	hasPathSep := strings.Contains(cleanpattern, sep)
	ext := filepath.Ext(cleanpattern)
	plen := len(cleanpattern)
	if plen > 1 && !hasPathSep && strings.HasPrefix(cleanpattern, "*") && cleanpattern[1:plen] == ext {
		return &simpleExtPattern{ext: ext}
	}

	// special case * when there are no path separators
	// filepath.Match never allows * to match a path separator, which is correct
	// for gitignore IF the pattern includes a path separator, but not otherwise
	// So *.txt should match in any subdir, as should test*, but sub/*.txt would
	// only match directly in the sub dir
	// Don't need to test cross-platform separators as both cleaned above
	if !hasPathSep && strings.Contains(cleanpattern, "*") {
		pattern := regexp.QuoteMeta(cleanpattern)
		regpattern := fmt.Sprintf("^%s$", strings.Replace(pattern, "\\*", ".*", -1))
		return &pathlessWildcardPattern{
			rawPattern: cleanpattern,
			wildcardRE: regexp.MustCompile(regpattern),
		}
	}

	// Also support ** with path separators
	if hasPathSep && strings.Contains(cleanpattern, "**") {
		pattern := regexp.QuoteMeta(cleanpattern)
		regpattern := fmt.Sprintf("^%s$", strings.Replace(pattern, "\\*\\*", ".*", -1))
		return &doubleWildcardPattern{
			rawPattern: cleanpattern,
			wildcardRE: regexp.MustCompile(regpattern),
		}
	}

	if hasPathSep && strings.HasPrefix(cleanpattern, sep) {
		rel := cleanpattern[1:len(cleanpattern)]
		prefix := rel
		if strings.HasSuffix(rel, sep) {
			rel = rel[0 : len(rel)-1]
		} else {
			prefix += sep
		}

		return &pathPrefixPattern{
			rawPattern: cleanpattern,
			relative:   rel,
			prefix:     prefix,
		}
	}

	return &pathPattern{
		rawPattern: cleanpattern,
		prefix:     cleanpattern + sep,
		suffix:     sep + cleanpattern,
		inner:      sep + cleanpattern + sep,
	}
}

func convertToPatterns(rawpatterns []string) []Pattern {
	patterns := make([]Pattern, len(rawpatterns))
	for i, raw := range rawpatterns {
		patterns[i] = NewPattern(raw)
	}
	return patterns
}

type pathPrefixPattern struct {
	rawPattern string
	relative   string
	prefix     string
}

// Match is a revised version of filepath.Match which makes it behave more
// like gitignore
func (p *pathPrefixPattern) Match(name string) bool {
	if name == p.relative || strings.HasPrefix(name, p.prefix) {
		return true
	}
	matched, _ := filepath.Match(p.rawPattern, name)
	return matched
}

func (p *pathPrefixPattern) HasPrefix(name string) bool {
	return strings.HasPrefix(p.relative, name)
}

// String returns a string representation of the underlying pattern for which
// this *pathPrefixPattern is matching.
func (p *pathPrefixPattern) String() string {
	return p.rawPattern
}

type pathPattern struct {
	rawPattern string
	prefix     string
	suffix     string
	inner      string
}

// Match is a revised version of filepath.Match which makes it behave more
// like gitignore
func (p *pathPattern) Match(name string) bool {
	if strings.HasPrefix(name, p.prefix) || strings.HasSuffix(name, p.suffix) || strings.Contains(name, p.inner) {
		return true
	}
	matched, _ := filepath.Match(p.rawPattern, name)
	return matched
}

func (p *pathPattern) HasPrefix(name string) bool {
	return strings.HasPrefix(p.prefix, name)
}

// String returns a string representation of the underlying pattern for which
// this *pathPattern is matching.
func (p *pathPattern) String() string {
	return p.rawPattern
}

type simpleExtPattern struct {
	ext string
}

func (p *simpleExtPattern) Match(name string) bool {
	return strings.HasSuffix(name, p.ext)
}

func (p *simpleExtPattern) HasPrefix(name string) bool {
	return true
}

// String returns a string representation of the underlying pattern for which
// this *simpleExtPattern is matching.
func (p *simpleExtPattern) String() string {
	return fmt.Sprintf("*%s", p.ext)
}

type pathlessWildcardPattern struct {
	rawPattern string
	wildcardRE *regexp.Regexp
}

// Match is a revised version of filepath.Match which makes it behave more
// like gitignore
func (p *pathlessWildcardPattern) Match(name string) bool {
	matched, _ := filepath.Match(p.rawPattern, name)
	// Match the whole of the base name but allow matching in folders if no path
	return matched || p.wildcardRE.MatchString(filepath.Base(name))
}

func (p *pathlessWildcardPattern) HasPrefix(name string) bool {
	lit, ok := p.wildcardRE.LiteralPrefix()
	if !ok {
		return true
	}

	return strings.HasPrefix(name, lit)
}

// String returns a string representation of the underlying pattern for which
// this *pathlessWildcardPattern is matching.
func (p *pathlessWildcardPattern) String() string {
	return p.rawPattern
}

type doubleWildcardPattern struct {
	rawPattern string
	wildcardRE *regexp.Regexp
}

// Match is a revised version of filepath.Match which makes it behave more
// like gitignore
func (p *doubleWildcardPattern) Match(name string) bool {
	matched, _ := filepath.Match(p.rawPattern, name)
	// Match the whole of the base name but allow matching in folders if no path
	return matched || p.wildcardRE.MatchString(name)
}

func (p *doubleWildcardPattern) HasPrefix(name string) bool {
	lit, ok := p.wildcardRE.LiteralPrefix()
	if !ok {
		return true
	}

	return strings.HasPrefix(name, lit)
}

// String returns a string representation of the underlying pattern for which
// this *doubleWildcardPattern is matching.
func (p *doubleWildcardPattern) String() string {
	return p.rawPattern
}

type noOpMatcher struct {
}

func (n noOpMatcher) Match(name string) bool {
	return true
}

func (n noOpMatcher) HasPrefix(name string) bool {
	return true
}

func (n noOpMatcher) String() string {
	return ""
}

var localDirSet = map[string]struct{}{
	".":   struct{}{},
	"./":  struct{}{},
	".\\": struct{}{},
}
<|endoftext|>


<commit_before>package commands

import (
	"strconv"

	"github.com/epicagency/pdns-manager/pdns"
)

func add_record(args ...string) (string, error) {
	shell.ShowPrompt(false)
	defer shell.ShowPrompt(true)

	zone, errs := pdns.GetZone(args[0])
	if errs != nil {
		for err := range errs {
			shell.Println(err)
		}
		return "", nil
	}

	record := new(pdns.Record)

	shell.Print("Name: ")
	name := shell.ReadLine()
	if name == "" {
		return "name can't be empty", nil
	}
	record.Name = name

	shell.Print("Type: ")
	typ := shell.ReadLine()
	if typ == "" {
		return "type can't be empty", nil
	}
	record.Type = typ

	shell.Print("Content: ")
	content := shell.ReadLine()
	if content == "" {
		return "content can't be empty", nil
	}
	record.Content = content

	shell.Print("TTL [300]: ")
	ttl := shell.ReadLine()
	if ttl != "" {
		record.TTL, _ = strconv.Atoi(ttl)
	} else {
		record.TTL = 300
	}

	shell.Print("Priority [0]: ")
	prio := shell.ReadLine()
	if prio != "" {
		record.Priority, _ = strconv.Atoi(prio)
	} else {
		record.Priority = 0
	}

	shell.Print("Disabled [false]?: ")
	dis := shell.ReadLine()
	record.Disabled = (dis == "y")

	shell.Print("Do you really want to add this record?? [y/n] ")
	confirm := shell.ReadLine()
	if confirm != "y" && confirm != "Y" {
		return "", nil
	}

	records := make([]*pdns.Record, 0, 5)
	for _, rec := range zone.Records {
		if rec.Name == record.Name && rec.Type == record.Type {
			records = append(records, rec)
		}
	}
	records = append(records, record)

	errs = zone.UpdateRecords(records)
	if errs != nil {
		for err := range errs {
			shell.Println(err)
		}
	}
	return "", nil
}
<commit_msg>Allow inline record add<commit_after>package commands

import (
	"strconv"

	"github.com/epicagency/pdns-manager/pdns"
)

func add_record(args ...string) (string, error) {
	shell.ShowPrompt(false)
	defer shell.ShowPrompt(true)

	zone, errs := pdns.GetZone(args[0])
	if errs != nil {
		for err := range errs {
			shell.Println(err)
		}
		return "", nil
	}

	record := new(pdns.Record)

	if len(args) < 7 {
		shell.Print("Name: ")
		name := shell.ReadLine()
		if name == "" {
			return "name can't be empty", nil
		}
		record.Name = name

		shell.Print("Type: ")
		typ := shell.ReadLine()
		if typ == "" {
			return "type can't be empty", nil
		}
		record.Type = typ

		shell.Print("Content: ")
		content := shell.ReadLine()
		if content == "" {
			return "content can't be empty", nil
		}
		record.Content = content

		shell.Print("TTL [300]: ")
		ttl := shell.ReadLine()
		if ttl != "" {
			record.TTL, _ = strconv.Atoi(ttl)
		} else {
			record.TTL = 300
		}

		shell.Print("Priority [0]: ")
		prio := shell.ReadLine()
		if prio != "" {
			record.Priority, _ = strconv.Atoi(prio)
		} else {
			record.Priority = 0
		}

		shell.Print("Disabled [false]?: ")
		dis := shell.ReadLine()
		record.Disabled = (dis == "y")
	} else {
		record.Name = args[1]
		record.Type = args[2]
		record.Content = args[3]
		record.TTL, _ = strconv.Atoi(args[4])
		record.Priority, _ = strconv.Atoi(args[5])
		record.Disabled = (args[6] == "y")
	}

	shell.Print("Do you really want to add this record?? [y/n] ")
	confirm := shell.ReadLine()
	if confirm != "y" && confirm != "Y" {
		return "", nil
	}

	records := make([]*pdns.Record, 0, 5)
	for _, rec := range zone.Records {
		if rec.Name == record.Name && rec.Type == record.Type {
			records = append(records, rec)
		}
	}
	records = append(records, record)

	errs = zone.UpdateRecords(records)
	if errs != nil {
		for err := range errs {
			shell.Println(err)
		}
	}
	return "", nil
}
<|endoftext|>


<commit_before>// Package alloc provides a light-weight memory allocation mechanism.
package alloc

import (
	"io"

	"github.com/v2ray/v2ray-core/common/serial"
)

const (
	defaultOffset = 16
)

// Buffer is a recyclable allocation of a byte array. Buffer.Release() recycles
// the buffer into an internal buffer pool, in order to recreate a buffer more
// quickly.
type Buffer struct {
	head   []byte
	pool   *BufferPool
	Value  []byte
	offset int
}

func CreateBuffer(container []byte, parent *BufferPool) *Buffer {
	b := new(Buffer)
	b.head = container
	b.pool = parent
	b.Value = b.head[defaultOffset:]
	b.offset = defaultOffset
	return b
}

// Release recycles the buffer into an internal buffer pool.
func (b *Buffer) Release() {
	if b == nil || b.head == nil {
		return
	}
	b.pool.Free(b)
	b.head = nil
	b.Value = nil
	b.pool = nil
}

// Clear clears the content of the buffer, results an empty buffer with
// Len() = 0.
func (b *Buffer) Clear() *Buffer {
	b.offset = defaultOffset
	b.Value = b.head[b.offset:b.offset]
	return b
}

func (b *Buffer) Reset() *Buffer {
	b.offset = defaultOffset
	b.Value = b.head
	return b
}

// AppendBytes appends one or more bytes to the end of the buffer.
func (b *Buffer) AppendBytes(bytes ...byte) *Buffer {
	b.Value = append(b.Value, bytes...)
	return b
}

// Append appends a byte array to the end of the buffer.
func (b *Buffer) Append(data []byte) *Buffer {
	b.Value = append(b.Value, data...)
	return b
}

// AppendString appends a given string to the end of the buffer.
func (b *Buffer) AppendString(s string) *Buffer {
	b.Value = append(b.Value, s...)
	return b
}

func (b *Buffer) AppendUint16(v uint16) *Buffer {
	b.Value = serial.Uint16ToBytes(v, b.Value)
	return b
}

func (b *Buffer) AppendUint32(v uint32) *Buffer {
	b.Value = serial.Uint32ToBytes(v, b.Value)
	return b
}

// Prepend prepends bytes in front of the buffer. Caller must ensure total bytes prepended is
// no more than 16 bytes.
func (b *Buffer) Prepend(data []byte) *Buffer {
	b.SliceBack(len(data))
	copy(b.Value, data)
	return b
}

func (b *Buffer) PrependBytes(data ...byte) *Buffer {
	return b.Prepend(data)
}

func (b *Buffer) PrependUint16(v uint16) *Buffer {
	b.SliceBack(2)
	serial.Uint16ToBytes(v, b.Value[:0])
	return b
}

func (b *Buffer) PrependUint32(v uint32) *Buffer {
	b.SliceBack(4)
	serial.Uint32ToBytes(v, b.Value[:0])
	return b
}

// Bytes returns the content bytes of this Buffer.
func (b *Buffer) Bytes() []byte {
	return b.Value
}

// Slice cuts the buffer at the given position.
func (b *Buffer) Slice(from, to int) *Buffer {
	b.offset += from
	b.Value = b.Value[from:to]
	return b
}

// SliceFrom cuts the buffer at the given position.
func (b *Buffer) SliceFrom(from int) *Buffer {
	b.offset += from
	b.Value = b.Value[from:]
	return b
}

// SliceBack extends the Buffer to its front by offset bytes.
// Caller must ensure cumulated offset is no more than 16.
func (b *Buffer) SliceBack(offset int) *Buffer {
	newoffset := b.offset - offset
	if newoffset < 0 {
		panic("Negative buffer offset.")
	}
	b.Value = b.head[newoffset : b.offset+len(b.Value)]
	b.offset = newoffset
	return b
}

// Len returns the length of the buffer content.
func (b *Buffer) Len() int {
	if b == nil {
		return 0
	}
	return len(b.Value)
}

func (b *Buffer) IsEmpty() bool {
	return b.Len() == 0
}

// IsFull returns true if the buffer has no more room to grow.
func (b *Buffer) IsFull() bool {
	return len(b.Value) == cap(b.Value)
}

// Write implements Write method in io.Writer.
func (b *Buffer) Write(data []byte) (int, error) {
	b.Append(data)
	return len(data), nil
}

// Read implements io.Reader.Read().
func (b *Buffer) Read(data []byte) (int, error) {
	if b.Len() == 0 {
		return 0, io.EOF
	}
	nBytes := copy(data, b.Value)
	if nBytes == b.Len() {
		b.Clear()
	} else {
		b.Value = b.Value[nBytes:]
		b.offset += nBytes
	}
	return nBytes, nil
}

func (b *Buffer) FillFrom(reader io.Reader) (int, error) {
	begin := b.Len()
	b.Value = b.Value[:cap(b.Value)]
	nBytes, err := reader.Read(b.Value[begin:])
	if err == nil {
		b.Value = b.Value[:begin+nBytes]
	}
	return nBytes, err
}

func (b *Buffer) String() string {
	return string(b.Value)
}

// NewSmallBuffer creates a Buffer with 1K bytes of arbitrary content.
func NewSmallBuffer() *Buffer {
	return smallPool.Allocate()
}

// NewBuffer creates a Buffer with 8K bytes of arbitrary content.
func NewBuffer() *Buffer {
	return mediumPool.Allocate()
}

// NewLargeBuffer creates a Buffer with 64K bytes of arbitrary content.
func NewLargeBuffer() *Buffer {
	return largePool.Allocate()
}

func NewBufferWithSize(size int) *Buffer {
	if size <= SmallBufferSize {
		return NewSmallBuffer()
	}

	if size <= BufferSize {
		return NewBuffer()
	}

	return NewLargeBuffer()
}
<commit_msg>allow buffer on local stack<commit_after>// Package alloc provides a light-weight memory allocation mechanism.
package alloc

import (
	"io"

	"github.com/v2ray/v2ray-core/common/serial"
)

const (
	defaultOffset = 16
)

// Buffer is a recyclable allocation of a byte array. Buffer.Release() recycles
// the buffer into an internal buffer pool, in order to recreate a buffer more
// quickly.
type Buffer struct {
	head   []byte
	pool   *BufferPool
	Value  []byte
	offset int
}

func CreateBuffer(container []byte, parent *BufferPool) *Buffer {
	b := new(Buffer)
	b.head = container
	b.pool = parent
	b.Value = b.head[defaultOffset:]
	b.offset = defaultOffset
	return b
}

// Release recycles the buffer into an internal buffer pool.
func (b *Buffer) Release() {
	if b == nil || b.head == nil {
		return
	}
	if b.pool != nil {
		b.pool.Free(b)
	}
	b.head = nil
	b.Value = nil
	b.pool = nil
}

// Clear clears the content of the buffer, results an empty buffer with
// Len() = 0.
func (b *Buffer) Clear() *Buffer {
	b.offset = defaultOffset
	b.Value = b.head[b.offset:b.offset]
	return b
}

func (b *Buffer) Reset() *Buffer {
	b.offset = defaultOffset
	b.Value = b.head
	return b
}

// AppendBytes appends one or more bytes to the end of the buffer.
func (b *Buffer) AppendBytes(bytes ...byte) *Buffer {
	b.Value = append(b.Value, bytes...)
	return b
}

// Append appends a byte array to the end of the buffer.
func (b *Buffer) Append(data []byte) *Buffer {
	b.Value = append(b.Value, data...)
	return b
}

// AppendString appends a given string to the end of the buffer.
func (b *Buffer) AppendString(s string) *Buffer {
	b.Value = append(b.Value, s...)
	return b
}

func (b *Buffer) AppendUint16(v uint16) *Buffer {
	b.Value = serial.Uint16ToBytes(v, b.Value)
	return b
}

func (b *Buffer) AppendUint32(v uint32) *Buffer {
	b.Value = serial.Uint32ToBytes(v, b.Value)
	return b
}

// Prepend prepends bytes in front of the buffer. Caller must ensure total bytes prepended is
// no more than 16 bytes.
func (b *Buffer) Prepend(data []byte) *Buffer {
	b.SliceBack(len(data))
	copy(b.Value, data)
	return b
}

func (b *Buffer) PrependBytes(data ...byte) *Buffer {
	return b.Prepend(data)
}

func (b *Buffer) PrependUint16(v uint16) *Buffer {
	b.SliceBack(2)
	serial.Uint16ToBytes(v, b.Value[:0])
	return b
}

func (b *Buffer) PrependUint32(v uint32) *Buffer {
	b.SliceBack(4)
	serial.Uint32ToBytes(v, b.Value[:0])
	return b
}

// Bytes returns the content bytes of this Buffer.
func (b *Buffer) Bytes() []byte {
	return b.Value
}

// Slice cuts the buffer at the given position.
func (b *Buffer) Slice(from, to int) *Buffer {
	b.offset += from
	b.Value = b.Value[from:to]
	return b
}

// SliceFrom cuts the buffer at the given position.
func (b *Buffer) SliceFrom(from int) *Buffer {
	b.offset += from
	b.Value = b.Value[from:]
	return b
}

// SliceBack extends the Buffer to its front by offset bytes.
// Caller must ensure cumulated offset is no more than 16.
func (b *Buffer) SliceBack(offset int) *Buffer {
	newoffset := b.offset - offset
	if newoffset < 0 {
		panic("Negative buffer offset.")
	}
	b.Value = b.head[newoffset : b.offset+len(b.Value)]
	b.offset = newoffset
	return b
}

// Len returns the length of the buffer content.
func (b *Buffer) Len() int {
	if b == nil {
		return 0
	}
	return len(b.Value)
}

func (b *Buffer) IsEmpty() bool {
	return b.Len() == 0
}

// IsFull returns true if the buffer has no more room to grow.
func (b *Buffer) IsFull() bool {
	return len(b.Value) == cap(b.Value)
}

// Write implements Write method in io.Writer.
func (b *Buffer) Write(data []byte) (int, error) {
	b.Append(data)
	return len(data), nil
}

// Read implements io.Reader.Read().
func (b *Buffer) Read(data []byte) (int, error) {
	if b.Len() == 0 {
		return 0, io.EOF
	}
	nBytes := copy(data, b.Value)
	if nBytes == b.Len() {
		b.Clear()
	} else {
		b.Value = b.Value[nBytes:]
		b.offset += nBytes
	}
	return nBytes, nil
}

func (b *Buffer) FillFrom(reader io.Reader) (int, error) {
	begin := b.Len()
	b.Value = b.Value[:cap(b.Value)]
	nBytes, err := reader.Read(b.Value[begin:])
	if err == nil {
		b.Value = b.Value[:begin+nBytes]
	}
	return nBytes, err
}

func (b *Buffer) String() string {
	return string(b.Value)
}

// NewSmallBuffer creates a Buffer with 1K bytes of arbitrary content.
func NewSmallBuffer() *Buffer {
	return smallPool.Allocate()
}

// NewBuffer creates a Buffer with 8K bytes of arbitrary content.
func NewBuffer() *Buffer {
	return mediumPool.Allocate()
}

// NewLargeBuffer creates a Buffer with 64K bytes of arbitrary content.
func NewLargeBuffer() *Buffer {
	return largePool.Allocate()
}

func NewBufferWithSize(size int) *Buffer {
	if size <= SmallBufferSize {
		return NewSmallBuffer()
	}

	if size <= BufferSize {
		return NewBuffer()
	}

	return NewLargeBuffer()
}

func NewLocalBuffer(size int) *Buffer {
	return CreateBuffer(make([]byte, size), nil)
}
<|endoftext|>


<commit_before>package boxrunner

import (
	"fmt"
	"github.com/armon/consul-api"
	"github.com/christianberg/boxrunner/statemachine"
	"github.com/fsouza/go-dockerclient"
	"io"
	"log"
	"net/http"
	"os"
	"time"
)

type BoxRunner struct {
	Service string
	ID      string
	port    string
	consul  *consulapi.Client
	logger  *log.Logger
	dock    *docker.Client
	lock    *consulapi.KVPair
}

type BoxRunnerOptions struct {
	ConsulAddress string
	ConsulClient  *consulapi.Client
	Logger        *log.Logger
}

var DefaultOptions = &BoxRunnerOptions{
	ConsulAddress: "localhost:8500",
}

func NewBoxRunner(service_name string, options *BoxRunnerOptions) (runner *BoxRunner, err error) {
	if options == nil {
		options = DefaultOptions
	}
	completeOptions(options)

	logger := options.Logger
	dock, err := docker.NewClient("tcp://0.0.0.0:2375")
	if err != nil {
		logger.Printf("Could not initialize Docker client: %s", err)
		return
	}

	hostname, err := os.Hostname()
	if err != nil {
		logger.Printf("Could not determine hostname: %s", err)
		return
	}

	port := os.Getenv("PORT")
	runner_id := fmt.Sprintf("boxrunner-%v-%v", hostname, port)
	logger.Printf("This is boxrunner: %v", runner_id)

	runner = &BoxRunner{
		Service: service_name,
		ID:      runner_id,
		consul:  options.ConsulClient,
		logger:  options.Logger,
		dock:    dock,
		port:    port,
		lock: &consulapi.KVPair{
			Key:   service_name,
			Value: []byte(runner_id),
		},
	}
	return
}

func (b *BoxRunner) findOrCreateSession() (string, error) {
	sessions, _, err := b.consul.Session().List(nil)
	if err != nil {
		b.logger.Printf("Could not list existing sessions: %v", err)
		return "", err
	}
	for _, session := range sessions {
		if session.Name == b.ID {
			b.logger.Printf("Found existing session: %v\n", session.ID)
			return session.ID, nil
		}
	}

	err = b.consul.Agent().CheckRegister(&consulapi.AgentCheckRegistration{
		Name: b.ID,
		AgentServiceCheck: consulapi.AgentServiceCheck{
			Script:   fmt.Sprintf("curl -sf http://localhost:%v/health", b.port),
			Interval: "5s",
		},
	})
	if err != nil {
		b.logger.Printf("ERROR: Could not register boxrunner healthcheck: %v", err)
		return "", err
	}

	session_entry := &consulapi.SessionEntry{
		Name:      b.ID,
		LockDelay: 5 * time.Second,
		Checks:    []string{"serfHealth", b.ID},
	}
	session_id, _, err := b.consul.Session().Create(session_entry, nil)
	if err != nil {
		b.logger.Printf("ERROR: Could not create session: %v", err)
		return "", err
	}
	b.logger.Printf("INFO: Session created (ID: %v)\n", session_id)
	return session_id, nil
}

func (b *BoxRunner) waitForLockChange(predicate func(string) bool) (err error) {
	query_options := &consulapi.QueryOptions{
		WaitIndex: 0,
	}
	for {
		lock_status, meta, err := b.consul.KV().Get(b.lock.Key, query_options)
		if err != nil {
			b.logger.Printf("ERROR: Cannot check lock status: %s", err)
			return err
		}
		if lock_status == nil || predicate(lock_status.Session) {
			b.logger.Println("INFO: Lock was released")
			return nil
		}
		query_options.WaitIndex = meta.LastIndex
	}
}

func (b *BoxRunner) Run() (success bool, error error) {
	http.HandleFunc("/health", func(w http.ResponseWriter, _ *http.Request) {
		io.WriteString(w, "OK")
	})

	go http.ListenAndServe("127.0.0.1:"+b.port, nil)

	machine := &statemachine.Machine{
		Handlers: map[string]statemachine.Handler{},
		Logger:   b.logger,
	}

	machine.AddState("INIT", func() string {
		return "DISCOVER"
	})

	machine.AddState("DISCOVER", func() string {
		session_id, err := b.findOrCreateSession()
		if err != nil {
			return "FAILED"
		}
		b.lock.Session = session_id

		if err := b.dock.Ping(); err != nil {
			b.logger.Printf("ERROR: Cannot ping docker server: %v", err)
			return "FAILED"
		}
		return "COMPETE"
	})

	machine.AddState("COMPETE", func() string {
		b.logger.Printf("INFO: Trying to acquire lock for %s\n", b.Service)
		success, _, err := b.consul.KV().Acquire(b.lock, nil)
		if err != nil {
			b.logger.Printf("ERROR: Could not acquire lock: %s", err)
			return "FAILED"
		}
		if success {
			b.logger.Println("INFO: Lock acquired!")
			return "START"
		} else {
			lock_status, _, _ := b.consul.KV().Get(b.lock.Key, nil)
			if lock_status != nil {
				b.logger.Printf("INFO: Lock is already taken by: %s", lock_status.Value)
			}
			return "SLEEP"
		}
	})

	machine.AddState("START", func() string {
		if err := b.dock.PullImage(
			docker.PullImageOptions{
				Repository: "busybox",
			},
			docker.AuthConfiguration{},
		); err != nil {
			b.logger.Printf("ERROR: Failed to pull image: %v", err)
			return "FAILED"
		}
		b.logger.Println("INFO: Image pulled")

		container, err := b.dock.CreateContainer(
			docker.CreateContainerOptions{
				Name: b.ID,
				Config: &docker.Config{
					Image: "busybox",
					Cmd:   []string{"/bin/sleep", "10"},
				},
			},
		)
		if err != nil {
			b.logger.Printf("ERROR: Failed to create docker container: %v", err)
			return "FAILED"
		}
		b.logger.Printf("INFO: Container created: %v", container.ID)

		if err := b.dock.StartContainer(container.ID, &docker.HostConfig{}); err != nil {
			b.logger.Printf("ERROR: Failed to start docker container: %v", err)
			return "FAILED"
		}
		b.logger.Printf("INFO: Container started: %v", container.ID)
		return "RUNNING"
	})

	machine.AddState("RUNNING", func() string {
		lock_watch := make(chan string)
		cancel_lock_watch := make(chan bool, 1)
		go func() {
			err := b.waitForLockChange(func(s string) bool { return s != b.lock.Session })
			select {
			case <-cancel_lock_watch:
				return
			default:
				if err != nil {
					lock_watch <- "FAILED"
					return
				}
				lock_watch <- "STOP"
				return
			}
		}()

		container_watch := make(chan string)
		cancel_container_watch := make(chan bool, 1)
		go func() {
			exit_code, err := b.dock.WaitContainer(b.ID)
			select {
			case <-cancel_container_watch:
				return
			default:
				if err != nil {
					b.logger.Printf("ERROR: Waiting for Docker container exit failed: %v", err)
					container_watch <- "FAILED"
					return
				}
				level := "INFO"
				if exit_code > 0 {
					level = "WARN"
				}
				b.logger.Printf("%v: Docker container exited with code %v\n", level, exit_code)
				container_watch <- "RELEASE"
				return
			}
		}()

		select {
		case s := <-lock_watch:
			cancel_container_watch <- true
			return s
		case s := <-container_watch:
			cancel_lock_watch <- true
			return s
		}
	})

	machine.AddState("SLEEP", func() string {
		time.Sleep(3 * time.Second)
		err := b.waitForLockChange(func(s string) bool { return s == "" })
		if err != nil {
			return "FAILED"
		}
		return "COMPETE"
	})

	machine.AddState("STOP", func() string {
		return "RELEASE"
	})

	machine.AddState("RELEASE", func() string {
		b.logger.Printf("INFO: Releasing lock for %s\n", b.Service)
		_, _, err := b.consul.KV().Release(b.lock, nil)
		if err != nil {
			b.logger.Printf("ERROR: Could not release lock: %v", err)
			return "FAILED"
		}
		return "REMOVE"
	})

	machine.AddState("REMOVE", func() string {
		err := b.dock.RemoveContainer(docker.RemoveContainerOptions{ID: b.ID})
		if err != nil {
			b.logger.Printf("ERROR: Could not remove container: %v", err)
			return "FAILED"
		}
		return "COMPETE"
	})

	return machine.Run()
}

func completeOptions(options *BoxRunnerOptions) {
	if options.ConsulClient == nil {
		if options.ConsulAddress == "" {
			options.ConsulAddress = DefaultOptions.ConsulAddress
		}
		var err error
		// options.ConsulClient, err = consulapi.NewClient(&consulapi.Config{
		// 	Address: options.ConsulAddress,
		// })
		options.ConsulClient, err = consulapi.NewClient(consulapi.DefaultConfig())
		if err != nil {
			panic("Failed to create consul-api Client")
		}
	}

	if options.Logger == nil {
		options.Logger = log.New(os.Stdout, "", 0)
	}
}
<commit_msg>Retry with exponential back-off in case of failures<commit_after>package boxrunner

import (
	"fmt"
	"github.com/armon/consul-api"
	"github.com/christianberg/boxrunner/statemachine"
	"github.com/fsouza/go-dockerclient"
	"io"
	"log"
	"net/http"
	"os"
	"time"
)

type BoxRunner struct {
	Service  string
	ID       string
	port     string
	consul   *consulapi.Client
	logger   *log.Logger
	dock     *docker.Client
	lock     *consulapi.KVPair
	failwait time.Duration
	lastfail time.Time
}

type BoxRunnerOptions struct {
	ConsulAddress string
	ConsulClient  *consulapi.Client
	Logger        *log.Logger
}

var DefaultOptions = &BoxRunnerOptions{
	ConsulAddress: "localhost:8500",
}

func NewBoxRunner(service_name string, options *BoxRunnerOptions) (runner *BoxRunner, err error) {
	if options == nil {
		options = DefaultOptions
	}
	completeOptions(options)

	logger := options.Logger
	dock, err := docker.NewClient("tcp://0.0.0.0:2375")
	if err != nil {
		logger.Printf("Could not initialize Docker client: %s", err)
		return
	}

	hostname, err := os.Hostname()
	if err != nil {
		logger.Printf("Could not determine hostname: %s", err)
		return
	}

	port := os.Getenv("PORT")
	runner_id := fmt.Sprintf("boxrunner-%v-%v", hostname, port)
	logger.Printf("This is boxrunner: %v", runner_id)

	runner = &BoxRunner{
		Service: service_name,
		ID:      runner_id,
		consul:  options.ConsulClient,
		logger:  options.Logger,
		dock:    dock,
		port:    port,
		lock: &consulapi.KVPair{
			Key:   service_name,
			Value: []byte(runner_id),
		},
		failwait: 1 * time.Second,
	}
	return
}

func (b *BoxRunner) findOrCreateSession() (string, error) {
	sessions, _, err := b.consul.Session().List(nil)
	if err != nil {
		b.logger.Printf("Could not list existing sessions: %v", err)
		return "", err
	}
	for _, session := range sessions {
		if session.Name == b.ID {
			b.logger.Printf("Found existing session: %v\n", session.ID)
			return session.ID, nil
		}
	}

	err = b.consul.Agent().CheckRegister(&consulapi.AgentCheckRegistration{
		Name: b.ID,
		AgentServiceCheck: consulapi.AgentServiceCheck{
			Script:   fmt.Sprintf("curl -sf http://localhost:%v/health", b.port),
			Interval: "5s",
		},
	})
	if err != nil {
		b.logger.Printf("ERROR: Could not register boxrunner healthcheck: %v", err)
		return "", err
	}

	session_entry := &consulapi.SessionEntry{
		Name:      b.ID,
		LockDelay: 5 * time.Second,
		Checks:    []string{"serfHealth", b.ID},
	}
	session_id, _, err := b.consul.Session().Create(session_entry, nil)
	if err != nil {
		b.logger.Printf("ERROR: Could not create session: %v", err)
		return "", err
	}
	b.logger.Printf("INFO: Session created (ID: %v)\n", session_id)
	return session_id, nil
}

func (b *BoxRunner) waitForLockChange(predicate func(string) bool) (err error) {
	query_options := &consulapi.QueryOptions{
		WaitIndex: 0,
	}
	for {
		lock_status, meta, err := b.consul.KV().Get(b.lock.Key, query_options)
		if err != nil {
			b.logger.Printf("ERROR: Cannot check lock status: %s", err)
			return err
		}
		if lock_status == nil || predicate(lock_status.Session) {
			b.logger.Println("INFO: Lock was released")
			return nil
		}
		query_options.WaitIndex = meta.LastIndex
	}
}

func (b *BoxRunner) Run() (success bool, error error) {
	http.HandleFunc("/health", func(w http.ResponseWriter, _ *http.Request) {
		io.WriteString(w, "OK")
	})

	go http.ListenAndServe("127.0.0.1:"+b.port, nil)

	machine := &statemachine.Machine{
		Handlers: map[string]statemachine.Handler{},
		Logger:   b.logger,
	}

	machine.AddState("INIT", func() string {
		return "DISCOVER"
	})

	machine.AddState("DISCOVER", func() string {
		session_id, err := b.findOrCreateSession()
		if err != nil {
			return "FAILED"
		}
		b.lock.Session = session_id

		if err := b.dock.Ping(); err != nil {
			b.logger.Printf("ERROR: Cannot ping docker server: %v", err)
			return "FAILED"
		}
		return "COMPETE"
	})

	machine.AddState("COMPETE", func() string {
		b.logger.Printf("INFO: Trying to acquire lock for %s\n", b.Service)
		success, _, err := b.consul.KV().Acquire(b.lock, nil)
		if err != nil {
			b.logger.Printf("ERROR: Could not acquire lock: %s", err)
			return "FAILED"
		}
		if success {
			b.logger.Println("INFO: Lock acquired!")
			return "START"
		} else {
			lock_status, _, _ := b.consul.KV().Get(b.lock.Key, nil)
			if lock_status != nil {
				b.logger.Printf("INFO: Lock is already taken by: %s", lock_status.Value)
			}
			return "SLEEP"
		}
	})

	machine.AddState("START", func() string {
		if err := b.dock.PullImage(
			docker.PullImageOptions{
				Repository: "busybox",
			},
			docker.AuthConfiguration{},
		); err != nil {
			b.logger.Printf("ERROR: Failed to pull image: %v", err)
			return "FAILED"
		}
		b.logger.Println("INFO: Image pulled")

		container, err := b.dock.CreateContainer(
			docker.CreateContainerOptions{
				Name: b.ID,
				Config: &docker.Config{
					Image: "busybox",
					Cmd:   []string{"/bin/sleep", "10"},
				},
			},
		)
		if err != nil {
			b.logger.Printf("ERROR: Failed to create docker container: %v", err)
			return "FAILED"
		}
		b.logger.Printf("INFO: Container created: %v", container.ID)

		if err := b.dock.StartContainer(container.ID, &docker.HostConfig{}); err != nil {
			b.logger.Printf("ERROR: Failed to start docker container: %v", err)
			return "FAILED"
		}
		b.logger.Printf("INFO: Container started: %v", container.ID)
		return "RUNNING"
	})

	machine.AddState("RUNNING", func() string {
		lock_watch := make(chan string)
		cancel_lock_watch := make(chan bool, 1)
		go func() {
			err := b.waitForLockChange(func(s string) bool { return s != b.lock.Session })
			select {
			case <-cancel_lock_watch:
				return
			default:
				if err != nil {
					lock_watch <- "FAILED"
					return
				}
				lock_watch <- "STOP"
				return
			}
		}()

		container_watch := make(chan string)
		cancel_container_watch := make(chan bool, 1)
		go func() {
			exit_code, err := b.dock.WaitContainer(b.ID)
			select {
			case <-cancel_container_watch:
				return
			default:
				if err != nil {
					b.logger.Printf("ERROR: Waiting for Docker container exit failed: %v", err)
					container_watch <- "FAILED"
					return
				}
				level := "INFO"
				if exit_code > 0 {
					level = "WARN"
				}
				b.logger.Printf("%v: Docker container exited with code %v\n", level, exit_code)
				container_watch <- "RELEASE"
				return
			}
		}()

		select {
		case s := <-lock_watch:
			cancel_container_watch <- true
			return s
		case s := <-container_watch:
			cancel_lock_watch <- true
			return s
		}
	})

	machine.AddState("SLEEP", func() string {
		time.Sleep(3 * time.Second)
		err := b.waitForLockChange(func(s string) bool { return s == "" })
		if err != nil {
			return "FAILED"
		}
		return "COMPETE"
	})

	machine.AddState("STOP", func() string {
		return "RELEASE"
	})

	machine.AddState("RELEASE", func() string {
		b.logger.Printf("INFO: Releasing lock for %s\n", b.Service)
		_, _, err := b.consul.KV().Release(b.lock, nil)
		if err != nil {
			b.logger.Printf("ERROR: Could not release lock: %v", err)
			return "FAILED"
		}
		return "REMOVE"
	})

	machine.AddState("REMOVE", func() string {
		err := b.dock.RemoveContainer(docker.RemoveContainerOptions{ID: b.ID})
		if err != nil {
			b.logger.Printf("ERROR: Could not remove container: %v", err)
			return "FAILED"
		}
		return "COMPETE"
	})

	machine.AddState("FAILED", func() string {
		if b.lastfail.Add(2 * b.failwait).Before(time.Now()) {
			b.failwait = 1 * time.Second
		}
		b.lastfail = time.Now()
		b.logger.Printf("WARN: Waiting for %v", b.failwait)
		time.Sleep(b.failwait)
		b.failwait = 2 * b.failwait
		if b.failwait > 5*time.Minute {
			b.failwait = 5 * time.Minute
		}
		return "DISCOVER"
	})

	return machine.Run()
}

func completeOptions(options *BoxRunnerOptions) {
	if options.ConsulClient == nil {
		if options.ConsulAddress == "" {
			options.ConsulAddress = DefaultOptions.ConsulAddress
		}
		var err error
		// options.ConsulClient, err = consulapi.NewClient(&consulapi.Config{
		// 	Address: options.ConsulAddress,
		// })
		options.ConsulClient, err = consulapi.NewClient(consulapi.DefaultConfig())
		if err != nil {
			panic("Failed to create consul-api Client")
		}
	}

	if options.Logger == nil {
		options.Logger = log.New(os.Stdout, "", 0)
	}
}
<|endoftext|>


<commit_before>package main

import (
	"encoding/csv"
	"flag"
	"fmt"
	. "github.com/abhiyerra/workmachine/app"
	"os"
)

type ImageTagging struct {
	ImageUrl             InputField  `work_desc:"Use this image to fill the information below." work_id:"image_url" work_type:"image"`
	Tags                 OutputField `work_desc:"List all the relevent tags separated by a comma for the image. Ex. trees, castle, person" work_id:"tags"`
	TextInImage          OutputField `work_desc:"Put any text that appears on the image here. Put one item per line." work_id:"text_in_image" work_type:"long_text"`
	IsCorrectOrientation OutputField `work_desc:"Is the image in the correct orientation?" work_id:"is_correct_orientation" work_type:"checkbox"`
	IsLandscape          OutputField `work_desc:"Is the image of a landscape?" work_id:"is_landscape" work_type:"checkbox"`
	IsPattern            OutputField `work_desc:"Is the image of a pattern?" work_id:"is_pattern" work_type:"checkbox"`
	IsPerson             OutputField `work_desc:"Is the image of a person?" work_id:"is_person" work_type:"checkbox"`
	TraditionalClothing  OutputField `work_desc:"If it's a person are they wearing a traditional costume?" work_id:"traditional_clothing" work_type:"checkbox"`
	IsMap                OutputField `work_desc:"Is the image a map?" work_id:"is_map" work_type:"checkbox"`
	IsDiagram            OutputField `work_desc:"Is the image a diagram?" work_id:"is_diagram" work_type:"checkbox"`
}

func imageUrls(in_file string) (images []ImageTagging) {
	file, err := os.Open(in_file)
	if err != nil {
		panic(err)
	}

	reader := csv.NewReader(file)
	records, err := reader.ReadAll()

	for _, i := range records {
		//		fmt.Printf("%s\n", i[1])
		images = append(images, ImageTagging{ImageUrl: InputField(i[1])})
	}

	if err != nil {
		panic(err)
	}

	return
}

func main() {
	var in_file string
	flag.StringVar(&in_file, "in_file", "", "input file")
	flag.Parse()

	if in_file == "" {
		fmt.Println("No in file")
		os.Exit(1)
	}

	results_filename := fmt.Sprintf("%s_out.csv", in_file)
	results_file, err := os.OpenFile(results_filename, os.O_CREATE|os.O_RDWR|os.O_APPEND, 0660)
	if err != nil {
		panic(err)
	}
	defer results_file.Close()

	image_urls := imageUrls(in_file)

	description := `
Look at the image and fill out the appropriate fields. We want to be able to tag all the images correctly. Fill out any appropriate tag that you see.
 Here are further Instructions and FAQ`

	image_tasks := Task{
		Title:       "Tag the appropriate images",
		Description: description,
		Write:       CsvJobWriter(results_file),
		Tasks:       image_urls,
	}

	fmt.Printf("Loaded %d images and starting\n", len(image_urls))
	serve := HtmlServe{}
	go HtmlServer()

	fmt.Println("Serving")
	var backend Assigner = serve
	NewBatch(image_tasks).Run(backend)

}
<commit_msg>Updated location of app<commit_after>package main

import (
	"encoding/csv"
	"flag"
	"fmt"
	. "github.com/abhiyerra/workmachine/crowdflow"
	"os"
)

type ImageTagging struct {
	ImageUrl             InputField  `work_desc:"Use this image to fill the information below." work_id:"image_url" work_type:"image"`
	Tags                 OutputField `work_desc:"List all the relevent tags separated by a comma for the image. Ex. trees, castle, person" work_id:"tags"`
	TextInImage          OutputField `work_desc:"Put any text that appears on the image here. Put one item per line." work_id:"text_in_image" work_type:"long_text"`
	IsCorrectOrientation OutputField `work_desc:"Is the image in the correct orientation?" work_id:"is_correct_orientation" work_type:"checkbox"`
	IsLandscape          OutputField `work_desc:"Is the image of a landscape?" work_id:"is_landscape" work_type:"checkbox"`
	IsPattern            OutputField `work_desc:"Is the image of a pattern?" work_id:"is_pattern" work_type:"checkbox"`
	IsPerson             OutputField `work_desc:"Is the image of a person?" work_id:"is_person" work_type:"checkbox"`
	TraditionalClothing  OutputField `work_desc:"If it's a person are they wearing a traditional costume?" work_id:"traditional_clothing" work_type:"checkbox"`
	IsMap                OutputField `work_desc:"Is the image a map?" work_id:"is_map" work_type:"checkbox"`
	IsDiagram            OutputField `work_desc:"Is the image a diagram?" work_id:"is_diagram" work_type:"checkbox"`
}

func imageUrls(in_file string) (images []ImageTagging) {
	file, err := os.Open(in_file)
	if err != nil {
		panic(err)
	}

	reader := csv.NewReader(file)
	records, err := reader.ReadAll()

	for _, i := range records {
		//		fmt.Printf("%s\n", i[1])
		images = append(images, ImageTagging{ImageUrl: InputField(i[1])})
	}

	if err != nil {
		panic(err)
	}

	return
}

func main() {
	var in_file string
	flag.StringVar(&in_file, "in_file", "", "input file")
	flag.Parse()

	if in_file == "" {
		fmt.Println("No in file")
		os.Exit(1)
	}

	results_filename := fmt.Sprintf("%s_out.csv", in_file)
	results_file, err := os.OpenFile(results_filename, os.O_CREATE|os.O_RDWR|os.O_APPEND, 0660)
	if err != nil {
		panic(err)
	}
	defer results_file.Close()

	image_urls := imageUrls(in_file)

	description := `
Look at the image and fill out the appropriate fields. We want to be able to tag all the images correctly. Fill out any appropriate tag that you see.
 Here are further Instructions and FAQ`

	image_tasks := Task{
		Title:       "Tag the appropriate images",
		Description: description,
		Write:       CsvJobWriter(results_file),
		Tasks:       image_urls,
	}

	fmt.Printf("Loaded %d images and starting\n", len(image_urls))
	serve := HtmlServe{}
	go HtmlServer()

	fmt.Println("Serving")
	var backend Assigner = serve
	NewBatch(image_tasks).Run(backend)

}
<|endoftext|>


<commit_before>// Copyright 2015 Matthew Holt and The Caddy 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 requestbody

import (
	"net/http"

	"github.com/caddyserver/caddy/v2"
	"github.com/caddyserver/caddy/v2/modules/caddyhttp"
)

func init() {
	caddy.RegisterModule(RequestBody{})
}

// RequestBody is a middleware for manipulating the request body.
type RequestBody struct {
	// The maximum number of bytes to allow reading from the body by a later handler.
	MaxSize int64 `json:"max_size,omitempty"`

	// Overwrites the remote address from which the request came. This is destructive;
	// handlers later in the chain will not be able to recover the true originating
	// address of the request. EXPERIMENTAL: May get changed or removed later.
	RemoteAddress string `json:"remote_address,omitempty"`
}

// CaddyModule returns the Caddy module information.
func (RequestBody) CaddyModule() caddy.ModuleInfo {
	return caddy.ModuleInfo{
		ID:  "http.handlers.request_body",
		New: func() caddy.Module { return new(RequestBody) },
	}
}

func (rb RequestBody) ServeHTTP(w http.ResponseWriter, r *http.Request, next caddyhttp.Handler) error {
	if rb.RemoteAddress != "" {
		repl := r.Context().Value(caddy.ReplacerCtxKey).(*caddy.Replacer)
		r.RemoteAddr = repl.ReplaceAll(rb.RemoteAddress, "")
	}
	if r.Body == nil {
		return next.ServeHTTP(w, r)
	}
	if rb.MaxSize > 0 {
		r.Body = http.MaxBytesReader(w, r.Body, rb.MaxSize)
	}
	return next.ServeHTTP(w, r)
}

// Interface guard
var _ caddyhttp.MiddlewareHandler = (*RequestBody)(nil)
<commit_msg>Revert "requestbody: Allow overwriting remote address"<commit_after>// Copyright 2015 Matthew Holt and The Caddy 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 requestbody

import (
	"net/http"

	"github.com/caddyserver/caddy/v2"
	"github.com/caddyserver/caddy/v2/modules/caddyhttp"
)

func init() {
	caddy.RegisterModule(RequestBody{})
}

// RequestBody is a middleware for manipulating the request body.
type RequestBody struct {
	// The maximum number of bytes to allow reading from the body by a later handler.
	MaxSize int64 `json:"max_size,omitempty"`
}

// CaddyModule returns the Caddy module information.
func (RequestBody) CaddyModule() caddy.ModuleInfo {
	return caddy.ModuleInfo{
		ID:  "http.handlers.request_body",
		New: func() caddy.Module { return new(RequestBody) },
	}
}

func (rb RequestBody) ServeHTTP(w http.ResponseWriter, r *http.Request, next caddyhttp.Handler) error {
	if r.Body == nil {
		return next.ServeHTTP(w, r)
	}
	if rb.MaxSize > 0 {
		r.Body = http.MaxBytesReader(w, r.Body, rb.MaxSize)
	}
	return next.ServeHTTP(w, r)
}

// Interface guard
var _ caddyhttp.MiddlewareHandler = (*RequestBody)(nil)
<|endoftext|>


<commit_before>package cmap

import (
	"sort"
	"strconv"
	"testing"
)

type Animal struct {
	name string
}

func TestMapCreation(t *testing.T) {
	m := NewConcurrentMap()
	if m == nil {
		t.Error("map is null.")
	}

	if m.Count() != 0 {
		t.Error("new map should be empty.")
	}
}

func TestInsert(t *testing.T) {
	m := NewConcurrentMap()
	elephant := Animal{"elephant"}
	monkey := Animal{"monkey"}

	m.Add("elephant", elephant)
	m.Add("monkey", monkey)

	if m.Count() != 2 {
		t.Error("map should contain exactly two elements.")
	}
}

func TestGet(t *testing.T) {
	m := NewConcurrentMap()

	// Get a missing element.
	val, ok := m.Get("Money")

	if ok == true {
		t.Error("ok should be false when item is missing from map.")
	}

	if val != nil {
		t.Error("Missing values should return as null.")
	}

	elephant := Animal{"elephant"}
	m.Add("elephant", elephant)

	// Retrieve inserted element.

	tmp, ok := m.Get("elephant")
	elephant = tmp.(Animal) // Type assertion.

	if ok == false {
		t.Error("ok should be true for item stored within the map.")
	}

	if &elephant == nil {
		t.Error("expecting an element, not null.")
	}

	if elephant.name != "elephant" {
		t.Error("item was modified.")
	}
}

func TestHas(t *testing.T) {
	m := NewConcurrentMap()

	// Get a missing element.
	if m.Has("Money") == true {
		t.Error("element shouldn't exists")
	}

	elephant := Animal{"elephant"}
	m.Add("elephant", elephant)

	if m.Has("elephant") == false {
		t.Error("element exists, expecting Has to return True.")
	}
}

func TestRemove(t *testing.T) {
	m := NewConcurrentMap()

	monkey := Animal{"monkey"}
	m.Add("monkey", monkey)

	m.Remove("monkey")

	if m.Count() != 0 {
		t.Error("Expecting count to be zero once item was removed.")
	}

	temp, ok := m.Get("monkey")

	if ok != false {
		t.Error("Expecting ok to be false for missing items.")
	}

	if temp != nil {
		t.Error("Expecting item to be nil after its removal.")
	}

	// Remove a none existing element.
	m.Remove("noone")
}

func TestCount(t *testing.T) {
	m := NewConcurrentMap()
	for i := 0; i < 100; i++ {
		m.Add(strconv.Itoa(i), Animal{strconv.Itoa(i)})
	}

	if m.Count() != 100 {
		t.Error("Expecting 100 element within map.")
	}
}

func TestClear(t *testing.T) {
	m := NewConcurrentMap()

	m.Clear()
	if m.Count() != 0 {
		t.Error("Expecting an empty map")
	}

	monkey := Animal{"monkey"}

	m.Add("monkey", monkey)

	m.Clear()
	if m.Count() != 0 {
		t.Error("Expecting an empty map")
	}

	if &monkey == nil {
		t.Error("Element should still exits")
	}
}

func TestIsEmpty(t *testing.T) {
	m := NewConcurrentMap()

	if m.IsEmpty() == false {
		t.Error("new map should be empty")
	}

	m.Add("elephant", Animal{"elephant"})

	if m.IsEmpty() != false {
		t.Error("map shouldn't be empty.")
	}
}

func TestRange(t *testing.T) {
	m := NewConcurrentMap()

	// Insert 100 elements.
	for i := 0; i < 100; i++ {
		m.Add(strconv.Itoa(i), Animal{strconv.Itoa(i)})
	}

	counter := 0
	// Iterate over elements.
	for item := range m.Iter() {
		val := item.Val

		if val == nil {
			t.Error("Expecting an object.")
		}
		counter++
	}

	if counter != 100 {
		t.Error("We should have counted 100 elements.")
	}
}

func TestConcurrent(t *testing.T) {
	m := NewConcurrentMap()
	ch := make(chan int)
	var a [1000]int

	// Using go routines insert 1000 ints into our map.
	for i := 0; i < 1000; i++ {
		go func(j int) {
			// Add item to map.
			m.Add(strconv.Itoa(j), j)

			// Retrieve item from map.
			val, _ := m.Get(strconv.Itoa(j))

			// Write to channel inserted value.
			ch <- val.(int)
		}(i) // Call go routine with current index.
	}

	// Wait for all go routines to finish.
	counter := 0
	for elem := range ch {
		a[counter] = elem
		counter++
		if counter == 1000 {
			break
		}
	}

	// Sorts array, will make is simpler to verify all inserted values we're returned.
	sort.Ints(a[0:1000])

	// Make sure map contains 1000 elements.
	if m.Count() != 1000 {
		t.Error("Expecting 1000 elements.")
	}

	// Make sure all inserted values we're fetched from map.
	for i := 0; i < 1000; i++ {
		if i != a[i] {
			t.Error("missing value", i)
		}
	}
}
<commit_msg>modified concurrent test<commit_after>package cmap

import (
	"sort"
	"strconv"
	"testing"
)

type Animal struct {
	name string
}

func TestMapCreation(t *testing.T) {
	m := NewConcurrentMap()
	if m == nil {
		t.Error("map is null.")
	}

	if m.Count() != 0 {
		t.Error("new map should be empty.")
	}
}

func TestInsert(t *testing.T) {
	m := NewConcurrentMap()
	elephant := Animal{"elephant"}
	monkey := Animal{"monkey"}

	m.Add("elephant", elephant)
	m.Add("monkey", monkey)

	if m.Count() != 2 {
		t.Error("map should contain exactly two elements.")
	}
}

func TestGet(t *testing.T) {
	m := NewConcurrentMap()

	// Get a missing element.
	val, ok := m.Get("Money")

	if ok == true {
		t.Error("ok should be false when item is missing from map.")
	}

	if val != nil {
		t.Error("Missing values should return as null.")
	}

	elephant := Animal{"elephant"}
	m.Add("elephant", elephant)

	// Retrieve inserted element.

	tmp, ok := m.Get("elephant")
	elephant = tmp.(Animal) // Type assertion.

	if ok == false {
		t.Error("ok should be true for item stored within the map.")
	}

	if &elephant == nil {
		t.Error("expecting an element, not null.")
	}

	if elephant.name != "elephant" {
		t.Error("item was modified.")
	}
}

func TestHas(t *testing.T) {
	m := NewConcurrentMap()

	// Get a missing element.
	if m.Has("Money") == true {
		t.Error("element shouldn't exists")
	}

	elephant := Animal{"elephant"}
	m.Add("elephant", elephant)

	if m.Has("elephant") == false {
		t.Error("element exists, expecting Has to return True.")
	}
}

func TestRemove(t *testing.T) {
	m := NewConcurrentMap()

	monkey := Animal{"monkey"}
	m.Add("monkey", monkey)

	m.Remove("monkey")

	if m.Count() != 0 {
		t.Error("Expecting count to be zero once item was removed.")
	}

	temp, ok := m.Get("monkey")

	if ok != false {
		t.Error("Expecting ok to be false for missing items.")
	}

	if temp != nil {
		t.Error("Expecting item to be nil after its removal.")
	}

	// Remove a none existing element.
	m.Remove("noone")
}

func TestCount(t *testing.T) {
	m := NewConcurrentMap()
	for i := 0; i < 100; i++ {
		m.Add(strconv.Itoa(i), Animal{strconv.Itoa(i)})
	}

	if m.Count() != 100 {
		t.Error("Expecting 100 element within map.")
	}
}

func TestClear(t *testing.T) {
	m := NewConcurrentMap()

	m.Clear()
	if m.Count() != 0 {
		t.Error("Expecting an empty map")
	}

	monkey := Animal{"monkey"}

	m.Add("monkey", monkey)

	m.Clear()
	if m.Count() != 0 {
		t.Error("Expecting an empty map")
	}

	if &monkey == nil {
		t.Error("Element should still exits")
	}
}

func TestIsEmpty(t *testing.T) {
	m := NewConcurrentMap()

	if m.IsEmpty() == false {
		t.Error("new map should be empty")
	}

	m.Add("elephant", Animal{"elephant"})

	if m.IsEmpty() != false {
		t.Error("map shouldn't be empty.")
	}
}

func TestRange(t *testing.T) {
	m := NewConcurrentMap()

	// Insert 100 elements.
	for i := 0; i < 100; i++ {
		m.Add(strconv.Itoa(i), Animal{strconv.Itoa(i)})
	}

	counter := 0
	// Iterate over elements.
	for item := range m.Iter() {
		val := item.Val

		if val == nil {
			t.Error("Expecting an object.")
		}
		counter++
	}

	if counter != 100 {
		t.Error("We should have counted 100 elements.")
	}
}

func TestConcurrent(t *testing.T) {
	m := NewConcurrentMap()
	ch := make(chan int)
	const iterations = 1000
	var a [iterations]int

	// Using go routines insert 1000 ints into our map.
	go func() {
		for i := 0; i < iterations/2; i++ {
			// Add item to map.
			m.Add(strconv.Itoa(i), i)

			// Retrieve item from map.
			val, _ := m.Get(strconv.Itoa(i))

			// Write to channel inserted value.
			ch <- val.(int)
		} // Call go routine with current index.
	}()

	go func() {
		for i := iterations / 2; i < iterations; i++ {
			// Add item to map.
			m.Add(strconv.Itoa(i), i)

			// Retrieve item from map.
			val, _ := m.Get(strconv.Itoa(i))

			// Write to channel inserted value.
			ch <- val.(int)
		} // Call go routine with current index.
	}()

	// Wait for all go routines to finish.
	counter := 0
	for elem := range ch {
		a[counter] = elem
		counter++
		if counter == iterations {
			break
		}
	}

	// Sorts array, will make is simpler to verify all inserted values we're returned.
	sort.Ints(a[0:iterations])

	// Make sure map contains 1000 elements.
	if m.Count() != iterations {
		t.Error("Expecting 1000 elements.")
	}

	// Make sure all inserted values we're fetched from map.
	for i := 0; i < iterations; i++ {
		if i != a[i] {
			t.Error("missing value", i)
		}
	}
}
<|endoftext|>


<commit_before>// Copyright (c) 2012, Suryandaru Triandana <syndtr@gmail.com>
// All rights reserved.
//
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// This LevelDB Go implementation is based on LevelDB C++ implementation.
// Which contains the following header:
//   Copyright (c) 2011 The LevelDB Authors. All rights reserved.
//   Use of this source code is governed by a BSD-style license that can be
//   found in the LEVELDBCPP_LICENSE file. See the LEVELDBCPP_AUTHORS file
//   for names of contributors.

package log

import (
	"bytes"
	"encoding/binary"
	"leveldb"
	"leveldb/descriptor"
)

const (
	// Zero is reserved for preallocated files
	tZero uint = iota
	tFull
	tFirst
	tMiddle
	tLast

	// Internal use
	tCorrupt
	tEof
)

const (
	kBlockSize = 32768

	// Header is checksum (4 bytes), type (1 byte), length (2 bytes).
	kHeaderSize = 4 + 1 + 2
)

var sixZero [6]byte

type Writer struct {
	w descriptor.Writer

	boff int
}

func NewWriter(w descriptor.Writer) *Writer {
	return &Writer{w: w}
}

func (l *Writer) Append(record []byte) (err error) {
	begin := true
	for {
		leftover := kBlockSize - l.boff
		if leftover < kHeaderSize {
			// Switch to a new block
			if leftover > 0 {
				_, err = l.w.Write(sixZero[:leftover])
				if err != nil {
					return
				}
			}
			l.boff = 0
		}

		avail := kBlockSize - l.boff - kHeaderSize
		fragLen := len(record)
		end := true
		if fragLen > avail {
			fragLen = avail
			end = false
		}

		rtype := tMiddle
		if begin && end {
			rtype = tFull
		} else if begin {
			rtype = tFirst
		} else if end {
			rtype = tLast
		}

		err = l.write(rtype, record[:fragLen])
		if err != nil {
			return
		}

		record = record[fragLen:]
		begin = false

		l.boff += kHeaderSize + fragLen

		if len(record) <= 0 {
			break
		}
	}

	return
}

func (l *Writer) write(rtype uint, record []byte) (err error) {
	rlen := len(record)
	buf := new(bytes.Buffer)

	crc := leveldb.NewCRC32C()
	crc.Write([]byte{byte(rtype)})
	crc.Write(record)
	err = binary.Write(buf, binary.LittleEndian, leveldb.MaskCRC32(crc.Sum32()))
	if err != nil {
		return
	}

	buf.WriteByte(byte(rlen & 0xff))
	buf.WriteByte(byte(rlen >> 8))
	buf.WriteByte(byte(rtype))

	_, err = l.w.Write(buf.Bytes())
	if err != nil {
		return
	}
	_, err = l.w.Write(record)
	if err != nil {
		return
	}
	err = l.w.Sync()
	if err != nil {
		return
	}

	return
}
<commit_msg>log: writer: remove file.Sync() on write<commit_after>// Copyright (c) 2012, Suryandaru Triandana <syndtr@gmail.com>
// All rights reserved.
//
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// This LevelDB Go implementation is based on LevelDB C++ implementation.
// Which contains the following header:
//   Copyright (c) 2011 The LevelDB Authors. All rights reserved.
//   Use of this source code is governed by a BSD-style license that can be
//   found in the LEVELDBCPP_LICENSE file. See the LEVELDBCPP_AUTHORS file
//   for names of contributors.

package log

import (
	"bytes"
	"encoding/binary"
	"io"
	"leveldb"
)

const (
	// Zero is reserved for preallocated files
	tZero uint = iota
	tFull
	tFirst
	tMiddle
	tLast

	// Internal use
	tCorrupt
	tEof
)

const (
	kBlockSize = 32768

	// Header is checksum (4 bytes), type (1 byte), length (2 bytes).
	kHeaderSize = 4 + 1 + 2
)

var sixZero [6]byte

type Writer struct {
	w io.Writer

	boff int
}

func NewWriter(w io.Writer) *Writer {
	return &Writer{w: w}
}

func (l *Writer) Append(record []byte) (err error) {
	begin := true
	for {
		leftover := kBlockSize - l.boff
		if leftover < kHeaderSize {
			// Switch to a new block
			if leftover > 0 {
				_, err = l.w.Write(sixZero[:leftover])
				if err != nil {
					return
				}
			}
			l.boff = 0
		}

		avail := kBlockSize - l.boff - kHeaderSize
		fragLen := len(record)
		end := true
		if fragLen > avail {
			fragLen = avail
			end = false
		}

		rtype := tMiddle
		if begin && end {
			rtype = tFull
		} else if begin {
			rtype = tFirst
		} else if end {
			rtype = tLast
		}

		err = l.write(rtype, record[:fragLen])
		if err != nil {
			return
		}

		record = record[fragLen:]
		begin = false

		l.boff += kHeaderSize + fragLen

		if len(record) <= 0 {
			break
		}
	}

	return
}

func (l *Writer) write(rtype uint, record []byte) (err error) {
	rlen := len(record)
	buf := new(bytes.Buffer)

	crc := leveldb.NewCRC32C()
	crc.Write([]byte{byte(rtype)})
	crc.Write(record)
	err = binary.Write(buf, binary.LittleEndian, leveldb.MaskCRC32(crc.Sum32()))
	if err != nil {
		return
	}

	buf.WriteByte(byte(rlen & 0xff))
	buf.WriteByte(byte(rlen >> 8))
	buf.WriteByte(byte(rtype))

	_, err = l.w.Write(buf.Bytes())
	if err != nil {
		return
	}
	_, err = l.w.Write(record)
	if err != nil {
		return
	}

	return
}
<|endoftext|>


<commit_before>package objecthash

import "bufio"
import "fmt"
import "os"
import "testing"

const testFile = "../../common_json.test"

func commonJSON(j string) {
	fmt.Printf("%x\n", CommonJSONHash(j))
}

func ExampleCommonJSONHash_Common() {
	commonJSON(`["foo", "bar"]`)
	// Output: 32ae896c413cfdc79eec68be9139c86ded8b279238467c216cf2bec4d5f1e4a2
}

func ExampleCommonJSONHash_FloatAndInt() {
	commonJSON(`["foo", {"bar":["baz", null, 1.0, 1.5, 0.0001, 1000.0, 2.0, -23.1234, 2.0]}]`)
	// Integers and floats are the same in common JSON
	commonJSON(`["foo", {"bar":["baz", null, 1, 1.5, 0.0001, 1000, 2, -23.1234, 2]}]`)
	// Output:
	// 783a423b094307bcb28d005bc2f026ff44204442ef3513585e7e73b66e3c2213
	// 783a423b094307bcb28d005bc2f026ff44204442ef3513585e7e73b66e3c2213
}

func ExampleCommonJSONHash_KeyChange() {
	commonJSON(`["foo", {"b4r":["baz", null, 1, 1.5, 0.0001, 1000, 2, -23.1234, 2]}]`)
	// Output: 7e01f8b45da35386e4f9531ff1678147a215b8d2b1d047e690fd9ade6151e431
}

func ExampleCommonJSONHash_KeyOrderIndependence() {
	commonJSON(`{"k1":"v1","k2":"v2","k3":"v3"}`)
	commonJSON(`{"k2":"v2","k1":"v1","k3":"v3"}`)
	// Output:
	// ddd65f1f7568269a30df7cafc26044537dc2f02a1a0d830da61762fc3e687057
	// ddd65f1f7568269a30df7cafc26044537dc2f02a1a0d830da61762fc3e687057
}

/*
func ExampleCommonJSONHash_UnicodeNormalisation() {
	commonJSON("\"\u03d3\"")
	commonJSON("\"\u03d2\u0301\"")
	// Output:
	// f72826713a01881404f34975447bd6edcb8de40b191dc57097ebf4f5417a554d
	// f72826713a01881404f34975447bd6edcb8de40b191dc57097ebf4f5417a554d
}
*/
func objectHash(o interface{}) {
	fmt.Printf("%x\n", ObjectHash(o))
}

func ExampleObjectHash_JSON() {
	// Same as equivalent JSON object
	o := []interface{}{`foo`, `bar`}
	objectHash(o)
	// Output: 32ae896c413cfdc79eec68be9139c86ded8b279238467c216cf2bec4d5f1e4a2
}

func ExampleObjectHash_JSON2() {
	// Same as equivalent _Python_ JSON object
	o := []interface{}{`foo`, map[string]interface{}{`bar`: []interface{}{`baz`, nil, 1, 1.5, 0.0001, 1000, 2, -23.1234, 2}}}
	objectHash(o)
	// Same as equivalent Common JSON object
	o = []interface{}{`foo`, map[string]interface{}{`bar`: []interface{}{`baz`, nil, 1.0, 1.5, 0.0001, 1000.0, 2.0, -23.1234, 2.0}}}
	objectHash(o)
	// Output:
	// 726e7ae9e3fadf8a2228bf33e505a63df8db1638fa4f21429673d387dbd1c52a
	// 783a423b094307bcb28d005bc2f026ff44204442ef3513585e7e73b66e3c2213
}

func ExampleObjectHash_Set() {
	o := map[string]interface{}{`thing1`: map[string]interface{}{`thing2`: Set{1, 2, `s`}}, `thing3`: 1234.567}
	objectHash(o)
	// Output: 618cf0582d2e716a70e99c2f3079d74892fec335e3982eb926835967cb0c246c
}

func ExampleObjectHash_ComplexSet() {
	o := Set{`foo`, 23.6, Set{Set{}}, Set{Set{1}}}
	objectHash(o)
	// Output: 3773b0a5283f91243a304d2bb0adb653564573bc5301aa8bb63156266ea5d398
}

func ExampleObjectHash_ComplexSetRepeated() {
	o := Set{`foo`, 23.6, Set{Set{}}, Set{Set{1}}, Set{Set{}}}
	objectHash(o)
	// Output: 3773b0a5283f91243a304d2bb0adb653564573bc5301aa8bb63156266ea5d398
}

func TestGolden(t *testing.T) {
	f, err := os.Open(testFile)
	if err != nil {
		t.Error(err)
		return
	}
	defer f.Close()
	s := bufio.NewScanner(f)
	for {
		var j string
		for {
			if !s.Scan() {
				return
			}
			j = s.Text()
			if len(j) != 0 && j[0] != '#' {
				break
			}
		}
		if !s.Scan() {
			t.Error("Premature EOF")
			return
		}
		h := s.Text()
		hh := fmt.Sprintf("%x", CommonJSONHash(j))
		if h != hh {
			t.Errorf("Got %s expected %s", hh, h)
		}
	}
}
<commit_msg>Don't overload objectHash.<commit_after>package objecthash

import "bufio"
import "fmt"
import "os"
import "testing"

const testFile = "../../common_json.test"

func commonJSON(j string) {
	fmt.Printf("%x\n", CommonJSONHash(j))
}

func ExampleCommonJSONHash_Common() {
	commonJSON(`["foo", "bar"]`)
	// Output: 32ae896c413cfdc79eec68be9139c86ded8b279238467c216cf2bec4d5f1e4a2
}

func ExampleCommonJSONHash_FloatAndInt() {
	commonJSON(`["foo", {"bar":["baz", null, 1.0, 1.5, 0.0001, 1000.0, 2.0, -23.1234, 2.0]}]`)
	// Integers and floats are the same in common JSON
	commonJSON(`["foo", {"bar":["baz", null, 1, 1.5, 0.0001, 1000, 2, -23.1234, 2]}]`)
	// Output:
	// 783a423b094307bcb28d005bc2f026ff44204442ef3513585e7e73b66e3c2213
	// 783a423b094307bcb28d005bc2f026ff44204442ef3513585e7e73b66e3c2213
}

func ExampleCommonJSONHash_KeyChange() {
	commonJSON(`["foo", {"b4r":["baz", null, 1, 1.5, 0.0001, 1000, 2, -23.1234, 2]}]`)
	// Output: 7e01f8b45da35386e4f9531ff1678147a215b8d2b1d047e690fd9ade6151e431
}

func ExampleCommonJSONHash_KeyOrderIndependence() {
	commonJSON(`{"k1":"v1","k2":"v2","k3":"v3"}`)
	commonJSON(`{"k2":"v2","k1":"v1","k3":"v3"}`)
	// Output:
	// ddd65f1f7568269a30df7cafc26044537dc2f02a1a0d830da61762fc3e687057
	// ddd65f1f7568269a30df7cafc26044537dc2f02a1a0d830da61762fc3e687057
}

/*
func ExampleCommonJSONHash_UnicodeNormalisation() {
	commonJSON("\"\u03d3\"")
	commonJSON("\"\u03d2\u0301\"")
	// Output:
	// f72826713a01881404f34975447bd6edcb8de40b191dc57097ebf4f5417a554d
	// f72826713a01881404f34975447bd6edcb8de40b191dc57097ebf4f5417a554d
}
*/
func printObjectHash(o interface{}) {
	fmt.Printf("%x\n", ObjectHash(o))
}

func ExampleObjectHash_JSON() {
	// Same as equivalent JSON object
	o := []interface{}{`foo`, `bar`}
	printObjectHash(o)
	// Output: 32ae896c413cfdc79eec68be9139c86ded8b279238467c216cf2bec4d5f1e4a2
}

func ExampleObjectHash_JSON2() {
	// Same as equivalent _Python_ JSON object
	o := []interface{}{`foo`, map[string]interface{}{`bar`: []interface{}{`baz`, nil, 1, 1.5, 0.0001, 1000, 2, -23.1234, 2}}}
	printObjectHash(o)
	// Same as equivalent Common JSON object
	o = []interface{}{`foo`, map[string]interface{}{`bar`: []interface{}{`baz`, nil, 1.0, 1.5, 0.0001, 1000.0, 2.0, -23.1234, 2.0}}}
	printObjectHash(o)
	// Output:
	// 726e7ae9e3fadf8a2228bf33e505a63df8db1638fa4f21429673d387dbd1c52a
	// 783a423b094307bcb28d005bc2f026ff44204442ef3513585e7e73b66e3c2213
}

func ExampleObjectHash_Set() {
	o := map[string]interface{}{`thing1`: map[string]interface{}{`thing2`: Set{1, 2, `s`}}, `thing3`: 1234.567}
	printObjectHash(o)
	// Output: 618cf0582d2e716a70e99c2f3079d74892fec335e3982eb926835967cb0c246c
}

func ExampleObjectHash_ComplexSet() {
	o := Set{`foo`, 23.6, Set{Set{}}, Set{Set{1}}}
	printObjectHash(o)
	// Output: 3773b0a5283f91243a304d2bb0adb653564573bc5301aa8bb63156266ea5d398
}

func ExampleObjectHash_ComplexSetRepeated() {
	o := Set{`foo`, 23.6, Set{Set{}}, Set{Set{1}}, Set{Set{}}}
	printObjectHash(o)
	// Output: 3773b0a5283f91243a304d2bb0adb653564573bc5301aa8bb63156266ea5d398
}

func TestGolden(t *testing.T) {
	f, err := os.Open(testFile)
	if err != nil {
		t.Error(err)
		return
	}
	defer f.Close()
	s := bufio.NewScanner(f)
	for {
		var j string
		for {
			if !s.Scan() {
				return
			}
			j = s.Text()
			if len(j) != 0 && j[0] != '#' {
				break
			}
		}
		if !s.Scan() {
			t.Error("Premature EOF")
			return
		}
		h := s.Text()
		hh := fmt.Sprintf("%x", CommonJSONHash(j))
		if h != hh {
			t.Errorf("Got %s expected %s", hh, h)
		}
	}
}
<|endoftext|>


<commit_before>package model

import (
	"app/app"
	"app/util"
	"context"
	"fmt"
	"strconv"
	"time"

	sq "github.com/Masterminds/squirrel"
	"github.com/goadesign/goa"
	"github.com/jmoiron/sqlx"
)

// UserAnswers DBカラム
type UserAnswers struct {
	ID         int       `db:"id"`
	Question   string    `db:"question"`
	Answer     string    `db:"answer"`
	Score      float64   `db:"score"`
	Emotion    int       `db:"emotion"`
	QuestionID int       `db:"question_id"`
	CreatedAt  time.Time `db:"created_at"`
}

// UserAnswersDB DB
type UserAnswersDB struct {
	DB *sqlx.DB
}

// NewUserAnswersDB イニシャライザ
func NewUserAnswersDB(db *sqlx.DB) *UserAnswersDB {
	return &UserAnswersDB{DB: db}
}

// GetList ユーザー回答の取得
func (db *UserAnswersDB) GetList(ctx context.Context) ([]UserAnswers, error) {
	sql, prepare, err := sq.Select("*").
		From("user_answers").
		OrderBy("created_at DESC").
		ToSql()
	if err != nil {
		goa.LogError(ctx, "UserAnswersDB GetList Error 1: err", "err", err)
		return []UserAnswers{}, err
	}
	ua := []UserAnswers{}
	err = db.DB.Select(&ua, sql, prepare...)
	if err != nil {
		goa.LogError(ctx, "UserAnswersDB GetList Error 2: err", "err", err)
		return []UserAnswers{}, err
	}
	return ua, nil
}

type UserAnswersGroupByEmotion struct {
	// Formatが違う
	CreatedAt string `db:"created_at"`
	Emotion   int    `db:"emotion"`
	Count     int    `db:"count"`
}

func (db *UserAnswersDB) GetListGroupByEmotion(ctx context.Context) ([]UserAnswersGroupByEmotion, error) {
	q, prepare, err := sq.Select(
		"DATE_FORMAT(created_at, '%Y-%m-%d') as created_at",
		"emotion",
		"COUNT(*) as count",
	).
		From("user_answers").
		GroupBy("DATE_FORMAT(created_at, '%Y%m%d')", "emotion").
		OrderBy("created_at DESC").
		ToSql()
	goa.LogInfo(ctx, "a", "a", q)
	if err != nil {
		goa.LogError(ctx, "UserAnswersDB GetGroupByEmotion Error 1: err", "err", err)
		return []UserAnswersGroupByEmotion{}, err
	}
	ua := []UserAnswersGroupByEmotion{}
	err = db.DB.Select(&ua, q, prepare...)
	if err != nil {
		goa.LogError(ctx, "UserAnswersDB GetGroupByEmotion Error 2: err", "err", err)
		return []UserAnswersGroupByEmotion{}, err
	}
	return ua, nil
}

type UserAnswersGetListEmotionRatio struct {
	Emotion int     `db:"emotion"`
	Percent float64 `db:"percent"`
}

func (db *UserAnswersDB) GetListEmotionRatio(ctx context.Context) ([]UserAnswersGetListEmotionRatio, error) {
	q, prepare, err := sq.Select(
		"emotion",
		"round(COUNT(*) / (SELECT COUNT(*) FROM user_answers) * 100, 1) as percent",
	).
		From("user_answers").
		GroupBy("emotion").
		OrderBy("created_at DESC").
		ToSql()
	if err != nil {
		goa.LogError(ctx, "UserAnswersDB GetGroupByEmotion Error 1: err", "err", err)
		return []UserAnswersGetListEmotionRatio{}, err
	}
	ua := []UserAnswersGetListEmotionRatio{}
	err = db.DB.Select(&ua, q, prepare...)
	if err != nil {
		goa.LogError(ctx, "UserAnswersDB GetGroupByEmotion Error 2: err", "err", err)
		return []UserAnswersGetListEmotionRatio{}, err
	}
	return ua, nil
}

// Add Insert
func (db *UserAnswersDB) Add(ctx context.Context, a UserAnswers) error {
	sql, prepare, err := sq.Insert("user_answers").
		Columns(
			"question",
			"answer",
			"score",
			"emotion",
			"question_id",
		).
		Values(
			a.Question,
			a.Answer,
			a.Score,
			a.Emotion,
			a.QuestionID,
		).
		ToSql()
	if err != nil {
		goa.LogError(ctx, "UserAnswerDB Add Error 1: err", "err", err)
		return err
	}
	db.DB.MustExec(sql, prepare...)
	return nil
}

// AddAnalysis 解析結果を格納する（非同期処理用）
func (db *UserAnswersDB) AddAnalysis(ctx context.Context, a UserAnswers) {
	s, err := util.AnalyzeSentiment(ctx, a.Answer)
	if err != nil {
		goa.LogError(ctx, "UserAnswerDB AddAnalysis Error 1: err", "err", err)
		return
	}
	score := s.DocumentSentiment.GetScore()
	a.Emotion = getEmotion(ctx, score)
	a.Score, err = strconv.ParseFloat(fmt.Sprint(score), 64)
	if err != nil {
		goa.LogError(ctx, "UserAnswerDB AddAnalysis Error 2: err", "err", err)
		return
	}
	err = db.Add(ctx, a)
	if err != nil {
		goa.LogError(ctx, "UserAnswerDB AddAnalysis Error 3: err", "err", err)
		return
	}
	goa.LogInfo(ctx, "UserAnswerDB AddAnalysis OK: insert", "insert", a)
}

// UserAnswerToUserAnswertype レスポンス用の構造体へ
func (ua UserAnswers) UserAnswerToUserAnswertype() app.Useranswertype {
	u := app.Useranswertype{}
	u.ID = ua.ID
	u.Score = ua.Score
	u.Answer = ua.Answer
	u.Question = ua.Question
	u.CreatedAt = ua.CreatedAt
	u.QuestionID = ua.QuestionID
	return u
}

// UserAnswerToUserAnswertypePtr レスポンス用の構造体へ(ポインター)
func (ua UserAnswers) UserAnswerToUserAnswertypePtr() *app.Useranswertype {
	u := &app.Useranswertype{}
	u.ID = ua.ID
	u.Score = ua.Score
	u.Answer = ua.Answer
	u.Question = ua.Question
	u.CreatedAt = ua.CreatedAt
	u.QuestionID = ua.QuestionID
	return u
}

func (ua UserAnswersGetListEmotionRatio) UserAnswerToGraphpietype() app.Graphpietype {
	u := app.Graphpietype{}
	u.Emotion = ua.Emotion
	u.Percent = ua.Percent
	return u
}

func (ua UserAnswersGetListEmotionRatio) UserAnswerToGraphpietypePtr() *app.Graphpietype {
	u := &app.Graphpietype{}
	u.Emotion = ua.Emotion
	u.Percent = ua.Percent
	return u
}

// func (uae UserAnswersGroupByEmotion) UserAnswerToGraphpietype() app.Graphbartype {
// 	u := app.Graphbartype{}
// 	u.Emotion = uae.Emotion
// 	u.Count = uae.Count
// 	u.Date = fmt.Sprint(uae.CreatedAt)
// 	return u
// }

// func (uae UserAnswersGroupByEmotion) UserAnswerToGraphpietypePtr() *app.Graphbartype {
// 	u := &app.Graphbartype{}
// 	u.Emotion = uae.Emotion
// 	u.Count = uae.Count
// 	u.Date = fmt.Sprint(uae.CreatedAt)
// 	return u
// }
<commit_msg>fix: lint<commit_after>package model

import (
	"app/app"
	"app/util"
	"context"
	"fmt"
	"strconv"
	"time"

	sq "github.com/Masterminds/squirrel"
	"github.com/goadesign/goa"
	"github.com/jmoiron/sqlx"
)

// UserAnswers DBカラム
type UserAnswers struct {
	ID         int       `db:"id"`
	Question   string    `db:"question"`
	Answer     string    `db:"answer"`
	Score      float64   `db:"score"`
	Emotion    int       `db:"emotion"`
	QuestionID int       `db:"question_id"`
	CreatedAt  time.Time `db:"created_at"`
}

// UserAnswersDB DB
type UserAnswersDB struct {
	DB *sqlx.DB
}

// NewUserAnswersDB イニシャライザ
func NewUserAnswersDB(db *sqlx.DB) *UserAnswersDB {
	return &UserAnswersDB{DB: db}
}

// GetList ユーザー回答の取得
func (db *UserAnswersDB) GetList(ctx context.Context) ([]UserAnswers, error) {
	sql, prepare, err := sq.Select("*").
		From("user_answers").
		OrderBy("created_at DESC").
		ToSql()
	if err != nil {
		goa.LogError(ctx, "UserAnswersDB GetList Error 1: err", "err", err)
		return []UserAnswers{}, err
	}
	ua := []UserAnswers{}
	err = db.DB.Select(&ua, sql, prepare...)
	if err != nil {
		goa.LogError(ctx, "UserAnswersDB GetList Error 2: err", "err", err)
		return []UserAnswers{}, err
	}
	return ua, nil
}

// UserAnswersGroupByEmotion ユーザーの感情分析（棒グラフ）
type UserAnswersGroupByEmotion struct {
	// Formatが違う
	CreatedAt string `db:"created_at"`
	Emotion   int    `db:"emotion"`
	Count     int    `db:"count"`
}

// GetListGroupByEmotion ユーザーの感情分析（棒グラフ）
func (db *UserAnswersDB) GetListGroupByEmotion(ctx context.Context) ([]UserAnswersGroupByEmotion, error) {
	q, prepare, err := sq.Select(
		"DATE_FORMAT(created_at, '%Y-%m-%d') as created_at",
		"emotion",
		"COUNT(*) as count",
	).
		From("user_answers").
		GroupBy("DATE_FORMAT(created_at, '%Y%m%d')", "emotion").
		OrderBy("created_at DESC").
		ToSql()
	goa.LogInfo(ctx, "a", "a", q)
	if err != nil {
		goa.LogError(ctx, "UserAnswersDB GetGroupByEmotion Error 1: err", "err", err)
		return []UserAnswersGroupByEmotion{}, err
	}
	ua := []UserAnswersGroupByEmotion{}
	err = db.DB.Select(&ua, q, prepare...)
	if err != nil {
		goa.LogError(ctx, "UserAnswersDB GetGroupByEmotion Error 2: err", "err", err)
		return []UserAnswersGroupByEmotion{}, err
	}
	return ua, nil
}

// UserAnswersGetListEmotionRatio ユーザーの感情分析（円グラフ）
type UserAnswersGetListEmotionRatio struct {
	Emotion int     `db:"emotion"`
	Percent float64 `db:"percent"`
}

// GetListEmotionRatio ユーザーの感情分析（円グラフ）
func (db *UserAnswersDB) GetListEmotionRatio(ctx context.Context) ([]UserAnswersGetListEmotionRatio, error) {
	q, prepare, err := sq.Select(
		"emotion",
		"round(COUNT(*) / (SELECT COUNT(*) FROM user_answers) * 100, 1) as percent",
	).
		From("user_answers").
		GroupBy("emotion").
		OrderBy("created_at DESC").
		ToSql()
	if err != nil {
		goa.LogError(ctx, "UserAnswersDB GetGroupByEmotion Error 1: err", "err", err)
		return []UserAnswersGetListEmotionRatio{}, err
	}
	ua := []UserAnswersGetListEmotionRatio{}
	err = db.DB.Select(&ua, q, prepare...)
	if err != nil {
		goa.LogError(ctx, "UserAnswersDB GetGroupByEmotion Error 2: err", "err", err)
		return []UserAnswersGetListEmotionRatio{}, err
	}
	return ua, nil
}

// Add Insert
func (db *UserAnswersDB) Add(ctx context.Context, a UserAnswers) error {
	sql, prepare, err := sq.Insert("user_answers").
		Columns(
			"question",
			"answer",
			"score",
			"emotion",
			"question_id",
		).
		Values(
			a.Question,
			a.Answer,
			a.Score,
			a.Emotion,
			a.QuestionID,
		).
		ToSql()
	if err != nil {
		goa.LogError(ctx, "UserAnswerDB Add Error 1: err", "err", err)
		return err
	}
	db.DB.MustExec(sql, prepare...)
	return nil
}

// AddAnalysis 解析結果を格納する（非同期処理用）
func (db *UserAnswersDB) AddAnalysis(ctx context.Context, a UserAnswers) {
	s, err := util.AnalyzeSentiment(ctx, a.Answer)
	if err != nil {
		goa.LogError(ctx, "UserAnswerDB AddAnalysis Error 1: err", "err", err)
		return
	}
	score := s.DocumentSentiment.GetScore()
	a.Emotion = getEmotion(ctx, score)
	a.Score, err = strconv.ParseFloat(fmt.Sprint(score), 64)
	if err != nil {
		goa.LogError(ctx, "UserAnswerDB AddAnalysis Error 2: err", "err", err)
		return
	}
	err = db.Add(ctx, a)
	if err != nil {
		goa.LogError(ctx, "UserAnswerDB AddAnalysis Error 3: err", "err", err)
		return
	}
	goa.LogInfo(ctx, "UserAnswerDB AddAnalysis OK: insert", "insert", a)
}

// UserAnswerToUserAnswertype レスポンス用の構造体へ
func (ua UserAnswers) UserAnswerToUserAnswertype() app.Useranswertype {
	u := app.Useranswertype{}
	u.ID = ua.ID
	u.Score = ua.Score
	u.Answer = ua.Answer
	u.Question = ua.Question
	u.CreatedAt = ua.CreatedAt
	u.QuestionID = ua.QuestionID
	return u
}

// UserAnswerToUserAnswertypePtr レスポンス用の構造体へ(ポインター)
func (ua UserAnswers) UserAnswerToUserAnswertypePtr() *app.Useranswertype {
	u := &app.Useranswertype{}
	u.ID = ua.ID
	u.Score = ua.Score
	u.Answer = ua.Answer
	u.Question = ua.Question
	u.CreatedAt = ua.CreatedAt
	u.QuestionID = ua.QuestionID
	return u
}

// UserAnswerToGraphpietype レスポンス用の構造体へ
func (ua UserAnswersGetListEmotionRatio) UserAnswerToGraphpietype() app.Graphpietype {
	u := app.Graphpietype{}
	u.Emotion = ua.Emotion
	u.Percent = ua.Percent
	return u
}

// UserAnswerToGraphpietypePtr レスポンス用の構造体へ（ポインター）
func (ua UserAnswersGetListEmotionRatio) UserAnswerToGraphpietypePtr() *app.Graphpietype {
	u := &app.Graphpietype{}
	u.Emotion = ua.Emotion
	u.Percent = ua.Percent
	return u
}

// func (uae UserAnswersGroupByEmotion) UserAnswerToGraphpietype() app.Graphbartype {
// 	u := app.Graphbartype{}
// 	u.Emotion = uae.Emotion
// 	u.Count = uae.Count
// 	u.Date = fmt.Sprint(uae.CreatedAt)
// 	return u
// }

// func (uae UserAnswersGroupByEmotion) UserAnswerToGraphpietypePtr() *app.Graphbartype {
// 	u := &app.Graphbartype{}
// 	u.Emotion = uae.Emotion
// 	u.Count = uae.Count
// 	u.Date = fmt.Sprint(uae.CreatedAt)
// 	return u
// }
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"os"

	"golang.org/x/net/html"
)

func main() {
	doc, err := html.Parse(os.Stdin)
	if err != nil {
		fmt.Fprintf(os.Stderr, "findlinks: %v\n", err)
		os.Exit(1)
	}
	for _, link := range visit(nil, doc) {
		fmt.Println(link)
	}
}

func visit(links []string, n *html.Node) []string {
	if n.Type == html.ElementNode && n.Data == "a" {
		for _, a := range n.Attr {
			if a.Key == "href" {
				links = append(links, a.Val)
			}
		}
	}
	for c := n.FirstChild; c != nil; c = c.NextSibling {
		links = visit(links, c)
	}
	return links
}
<commit_msg>[5.1] Make visit w/o for loop.<commit_after>package main

import (
	"fmt"
	"os"

	"golang.org/x/net/html"
)

func main() {
	doc, err := html.Parse(os.Stdin)
	if err != nil {
		fmt.Fprintf(os.Stderr, "findlinks: %v\n", err)
		os.Exit(1)
	}
	for _, link := range visit(nil, doc) {
		fmt.Println(link)
	}
}

func visit(links []string, n *html.Node) []string {
	if n == nil {
		return links
	}

	if n.Type == html.ElementNode && n.Data == "a" {
		for _, a := range n.Attr {
			if a.Key == "href" {
				links = append(links, a.Val)
			}
		}
	}
	links = visit(links, n.FirstChild)
	return visit(links, n.NextSibling)
}
<|endoftext|>