<commit_before>package conf

import (
	"strings"

	"github.com/stephane-martin/skewer/encoders/baseenc"
	"github.com/stephane-martin/skewer/utils/eerrors"
)

// DestinationType lists the possible kind of destinations where skewer can forward messages.
type DestinationType uint64

func (dests DestinationType) Iterate() (res []DestinationType) {
	if dests == 0 {
		return []DestinationType{Stderr}
	}
	res = make([]DestinationType, 0, len(Destinations))
	for _, dtype := range Destinations {
		if dests.Has(dtype) {
			res = append(res, dtype)
		}
	}
	return res
}

func (dests DestinationType) Has(one DestinationType) bool {
	return uint64(dests)&uint64(one) != 0
}

const (
	Kafka           DestinationType = 1
	UDP                             = 2
	TCP                             = 4
	RELP                            = 8
	File                            = 16
	Stderr                          = 32
	Graylog                         = 64
	HTTP                            = 128
	NATS                            = 256
	HTTPServer                      = 512
	WebsocketServer                 = 1024
	Elasticsearch                   = 2048
	Redis                           = 4096
)

var Destinations = map[string]DestinationType{
	"kafka":           Kafka,
	"udp":             UDP,
	"tcp":             TCP,
	"relp":            RELP,
	"file":            File,
	"stderr":          Stderr,
	"graylog":         Graylog,
	"http":            HTTP,
	"httpserver":      HTTPServer,
	"nats":            NATS,
	"websocketserver": WebsocketServer,
	"elasticsearch":   Elasticsearch,
	"redis":           Redis,
}

var DestinationNames = map[DestinationType]string{
	Kafka:           "kafka",
	UDP:             "udp",
	TCP:             "tcp",
	RELP:            "relp",
	File:            "file",
	Stderr:          "stderr",
	Graylog:         "graylog",
	HTTP:            "http",
	HTTPServer:      "httpserver",
	NATS:            "nats",
	WebsocketServer: "websocketserver",
	Elasticsearch:   "elasticsearch",
	Redis:           "redis",
}

var RDestinations = map[DestinationType]string{
	Kafka:           "k",
	UDP:             "u",
	TCP:             "t",
	RELP:            "r",
	File:            "f",
	Stderr:          "s",
	Graylog:         "g",
	HTTP:            "h",
	HTTPServer:      "e",
	NATS:            "n",
	WebsocketServer: "w",
	Elasticsearch:   "l",
	Redis:           "d",
}

func (m *MainConfig) GetDestinations() (dests DestinationType, err error) {
	destr := strings.TrimSpace(strings.ToLower(m.Destination))
	for _, dest := range strings.Split(destr, ",") {
		d, ok := Destinations[strings.TrimSpace(dest)]
		if !ok {
			return 0, confCheckError(
				eerrors.WithTags(
					eerrors.New("Unknown destination type"),
					"destination", dest,
				),
			)
		}
		dests = dests | d
	}
	if dests == 0 {
		return Stderr, nil
	}
	return
}

func (c *BaseConfig) CheckDestinations() error {
	// note that Graylog destination does not have a Format option
	c.UDPDest.Format = strings.TrimSpace(strings.ToLower(c.UDPDest.Format))
	c.TCPDest.Format = strings.TrimSpace(strings.ToLower(c.TCPDest.Format))
	c.HTTPDest.Format = strings.TrimSpace(strings.ToLower(c.HTTPDest.Format))
	c.HTTPServerDest.Format = strings.TrimSpace(strings.ToLower(c.HTTPServerDest.Format))
	c.WebsocketServerDest.Format = strings.TrimSpace(strings.ToLower(c.WebsocketServerDest.Format))
	c.RELPDest.Format = strings.TrimSpace(strings.ToLower(c.RELPDest.Format))
	c.KafkaDest.Format = strings.TrimSpace(strings.ToLower(c.KafkaDest.Format))
	c.FileDest.Format = strings.TrimSpace(strings.ToLower(c.FileDest.Format))
	c.StderrDest.Format = strings.TrimSpace(strings.ToLower(c.StderrDest.Format))
	c.ElasticDest.Format = strings.TrimSpace(strings.ToLower(c.ElasticDest.Format))
	c.RedisDest.Format = strings.TrimSpace(strings.ToLower(c.RedisDest.Format))

	for _, frmt := range []string{
		c.UDPDest.Format,
		c.TCPDest.Format,
		c.HTTPDest.Format,
		c.HTTPServerDest.Format,
		c.WebsocketServerDest.Format,
		c.RELPDest.Format,
		c.KafkaDest.Format,
		c.FileDest.Format,
		c.StderrDest.Format,
		c.ElasticDest.Format,
		c.RedisDest.Format,
	} {
		if baseenc.ParseFormat(frmt) == -1 {
			return confCheckError(
				eerrors.WithTags(
					eerrors.New("Unknown destination format"),
					"format", frmt,
				),
			)
		}
	}
	return nil
}
<commit_msg>fix lint error<commit_after>package conf

import (
	"strings"

	"github.com/stephane-martin/skewer/encoders/baseenc"
	"github.com/stephane-martin/skewer/utils/eerrors"
)

// DestinationType lists the possible kind of destinations where skewer can forward messages.
type DestinationType uint64

func (dests DestinationType) Iterate() (res []DestinationType) {
	if dests == 0 {
		return []DestinationType{Stderr}
	}
	res = make([]DestinationType, 0, len(Destinations))
	for _, dtype := range Destinations {
		if dests.Has(dtype) {
			res = append(res, dtype)
		}
	}
	return res
}

func (dests DestinationType) Has(one DestinationType) bool {
	return uint64(dests)&uint64(one) != 0
}

const (
	Kafka           DestinationType = 1
	UDP             DestinationType = 2
	TCP             DestinationType = 4
	RELP            DestinationType = 8
	File            DestinationType = 16
	Stderr          DestinationType = 32
	Graylog         DestinationType = 64
	HTTP            DestinationType = 128
	NATS            DestinationType = 256
	HTTPServer      DestinationType = 512
	WebsocketServer DestinationType = 1024
	Elasticsearch   DestinationType = 2048
	Redis           DestinationType = 4096
)

var Destinations = map[string]DestinationType{
	"kafka":           Kafka,
	"udp":             UDP,
	"tcp":             TCP,
	"relp":            RELP,
	"file":            File,
	"stderr":          Stderr,
	"graylog":         Graylog,
	"http":            HTTP,
	"httpserver":      HTTPServer,
	"nats":            NATS,
	"websocketserver": WebsocketServer,
	"elasticsearch":   Elasticsearch,
	"redis":           Redis,
}

var DestinationNames = map[DestinationType]string{
	Kafka:           "kafka",
	UDP:             "udp",
	TCP:             "tcp",
	RELP:            "relp",
	File:            "file",
	Stderr:          "stderr",
	Graylog:         "graylog",
	HTTP:            "http",
	HTTPServer:      "httpserver",
	NATS:            "nats",
	WebsocketServer: "websocketserver",
	Elasticsearch:   "elasticsearch",
	Redis:           "redis",
}

var RDestinations = map[DestinationType]string{
	Kafka:           "k",
	UDP:             "u",
	TCP:             "t",
	RELP:            "r",
	File:            "f",
	Stderr:          "s",
	Graylog:         "g",
	HTTP:            "h",
	HTTPServer:      "e",
	NATS:            "n",
	WebsocketServer: "w",
	Elasticsearch:   "l",
	Redis:           "d",
}

func (m *MainConfig) GetDestinations() (dests DestinationType, err error) {
	destr := strings.TrimSpace(strings.ToLower(m.Destination))
	for _, dest := range strings.Split(destr, ",") {
		d, ok := Destinations[strings.TrimSpace(dest)]
		if !ok {
			return 0, confCheckError(
				eerrors.WithTags(
					eerrors.New("Unknown destination type"),
					"destination", dest,
				),
			)
		}
		dests = dests | d
	}
	if dests == 0 {
		return Stderr, nil
	}
	return
}

func (c *BaseConfig) CheckDestinations() error {
	// note that Graylog destination does not have a Format option
	c.UDPDest.Format = strings.TrimSpace(strings.ToLower(c.UDPDest.Format))
	c.TCPDest.Format = strings.TrimSpace(strings.ToLower(c.TCPDest.Format))
	c.HTTPDest.Format = strings.TrimSpace(strings.ToLower(c.HTTPDest.Format))
	c.HTTPServerDest.Format = strings.TrimSpace(strings.ToLower(c.HTTPServerDest.Format))
	c.WebsocketServerDest.Format = strings.TrimSpace(strings.ToLower(c.WebsocketServerDest.Format))
	c.RELPDest.Format = strings.TrimSpace(strings.ToLower(c.RELPDest.Format))
	c.KafkaDest.Format = strings.TrimSpace(strings.ToLower(c.KafkaDest.Format))
	c.FileDest.Format = strings.TrimSpace(strings.ToLower(c.FileDest.Format))
	c.StderrDest.Format = strings.TrimSpace(strings.ToLower(c.StderrDest.Format))
	c.ElasticDest.Format = strings.TrimSpace(strings.ToLower(c.ElasticDest.Format))
	c.RedisDest.Format = strings.TrimSpace(strings.ToLower(c.RedisDest.Format))

	for _, frmt := range []string{
		c.UDPDest.Format,
		c.TCPDest.Format,
		c.HTTPDest.Format,
		c.HTTPServerDest.Format,
		c.WebsocketServerDest.Format,
		c.RELPDest.Format,
		c.KafkaDest.Format,
		c.FileDest.Format,
		c.StderrDest.Format,
		c.ElasticDest.Format,
		c.RedisDest.Format,
	} {
		if baseenc.ParseFormat(frmt) == -1 {
			return confCheckError(
				eerrors.WithTags(
					eerrors.New("Unknown destination format"),
					"format", frmt,
				),
			)
		}
	}
	return nil
}
<|endoftext|>


<commit_before>package main

import (
	"crypto/md5"
	"fmt"
	"strconv"
	"time"
)

const (
	input = "cxdnnyjw"
)

func checkPass(pass []byte) bool {
	for _, i := range pass {
		if i == 0 {
			return true
		}
	}
	return false
}

func checkHash(hash string) bool {
	for j := 0; j < 5; j++ {
		if hash[j] != '0' {
			return false
		}
	}
	return true
}

func main() {
	start := time.Now()

	password := ""
	i := 0

	for i = 0; len(password) < 8; i++ {
		hash := fmt.Sprintf("%x", md5.Sum([]byte(input+strconv.Itoa(i))))
		if checkHash(hash) {
			password += string(hash[5])
			fmt.Println(hash)
		}
	}

	password2 := [8]byte{0, 0, 0, 0, 0, 0, 0, 0}
	j := 0

	for j = 0; checkPass(password2[:]); j++ {
		hash := fmt.Sprintf("%x", md5.Sum([]byte(input+strconv.Itoa(j))))
		if checkHash(hash) {
			k := hash[5] - '0'
			if k < 8 && password2[k] == 0 {
				password2[k] = hash[6]
				fmt.Println(hash)
			}
		}
	}

	fmt.Println(fmt.Sprintf("\npassword: %s in %d iterations", password, i))
	fmt.Println(fmt.Sprintf("\npassword2: %c in %d iterations", password2, j))

	fmt.Println(fmt.Sprintf("\ntime elapsed: %s", time.Since(start)))
}
<commit_msg>goroutined day05<commit_after>package main

import (
	"crypto/md5"
	"fmt"
	"strconv"
	"time"
)

const (
	input = "cxdnnyjw"
)

func checkPass(pass []byte) bool {
	for _, i := range pass {
		if i == 0 {
			return true
		}
	}
	return false
}

func checkHash(hash string) bool {
	for j := 0; j < 5; j++ {
		if hash[j] != '0' {
			return false
		}
	}
	return true
}

func main() {
	start := time.Now()

	password := ""
	passChan := make(chan string, 8)
	passDone := make(chan bool)
	iterations := 0

	go func() {
		j := 0
		i := 0
		for i = 0; j < 8; i++ {
			hash := fmt.Sprintf("%x", md5.Sum([]byte(input+strconv.Itoa(i))))
			if checkHash(hash) {
				passChan <- string(hash[5])
				j++
			}
		}
		iterations = i
		close(passChan)
	}()

	go func() {
		for i := range passChan {
			password += i
			fmt.Println(password)
		}
		passDone <- true
	}()

	password2 := [8]byte{0, 0, 0, 0, 0, 0, 0, 0}
	pass2Done := make(chan bool)
	iterations2 := 0
	go func() {
		i := 0
		for i = 0; checkPass(password2[:]); i++ {
			hash := fmt.Sprintf("%x", md5.Sum([]byte(input+strconv.Itoa(i))))
			if checkHash(hash) {
				k := hash[5] - '0'
				if k < 8 && password2[k] == 0 {
					password2[k] = hash[6]
					fmt.Println(fmt.Sprintf("%c", password2))
				}
			}
		}
		iterations2 = i
		pass2Done <- true
	}()

	<-passDone
	<-pass2Done

	fmt.Println(fmt.Sprintf("\npassword: %s in %d iterations", password, iterations))
	fmt.Println(fmt.Sprintf("\npassword2: %c in %d iterations", password2, iterations2))

	fmt.Println(fmt.Sprintf("\ntime elapsed: %s", time.Since(start)))
}
<|endoftext|>


<commit_before>// Copyright 2012 Aaron Jacobs. All Rights Reserved.
// Author: aaronjjacobs@gmail.com (Aaron Jacobs)
//
// 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 oglematchers_test

import (
	. "github.com/jacobsa/ogletest"
)

////////////////////////////////////////////////////////////
// Helpers
////////////////////////////////////////////////////////////

type IdenticalToTest struct {
}

func init() { RegisterTestSuite(&IdenticalToTest{}) }

////////////////////////////////////////////////////////////
// Tests
////////////////////////////////////////////////////////////

func (t *IdenticalToTest) TypesNotIdentical() {
}

func (t *IdenticalToTest) Slices() {
}

func (t *IdenticalToTest) Maps() {
}

func (t *IdenticalToTest) Functions() {
}

func (t *IdenticalToTest) Channels() {
}

func (t *IdenticalToTest) Bools() {
}

func (t *IdenticalToTest) Ints() {
}

func (t *IdenticalToTest) Int8s() {
}

func (t *IdenticalToTest) Int16s() {
}

func (t *IdenticalToTest) Int32s() {
}

func (t *IdenticalToTest) Int64s() {
}

func (t *IdenticalToTest) Uints() {
}

func (t *IdenticalToTest) Uint8s() {
}

func (t *IdenticalToTest) Uint16s() {
}

func (t *IdenticalToTest) Uint32s() {
}

func (t *IdenticalToTest) Uint64s() {
}

func (t *IdenticalToTest) Float32s() {
}

func (t *IdenticalToTest) Float64s() {
}

func (t *IdenticalToTest) Complex64s() {
}

func (t *IdenticalToTest) Complex128s() {
}

func (t *IdenticalToTest) ComparableArrays() {
}

func (t *IdenticalToTest) NonComparableArrays() {
}

func (t *IdenticalToTest) ComparableInterfaces() {
}

func (t *IdenticalToTest) NonComparableInterfaces() {
}

func (t *IdenticalToTest) Pointers() {
}

func (t *IdenticalToTest) Strings() {
}

func (t *IdenticalToTest) ComparableStructs() {
}

func (t *IdenticalToTest) NonComparableStructs() {
}

func (t *IdenticalToTest) UnsafePointers() {
}

func (t *IdenticalToTest) IntAlias() {
}
<commit_msg>IdenticalToTest.TypesNotIdentical<commit_after>// Copyright 2012 Aaron Jacobs. All Rights Reserved.
// Author: aaronjjacobs@gmail.com (Aaron Jacobs)
//
// 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 oglematchers_test

import (
	. "github.com/jacobsa/oglematchers"
	. "github.com/jacobsa/ogletest"
)

////////////////////////////////////////////////////////////
// Helpers
////////////////////////////////////////////////////////////

type IdenticalToTest struct {
}

func init() { RegisterTestSuite(&IdenticalToTest{}) }

////////////////////////////////////////////////////////////
// Tests
////////////////////////////////////////////////////////////

func (t *IdenticalToTest) TypesNotIdentical() {
	var m Matcher
	var res bool
	var err error

	type intAlias int

	// Type alias expected value
	m = IdenticalTo(intAlias(17))
	res, err = m.Matches(int(17))

	ExpectFalse(res)
	ExpectThat(err, Error(Equals("which is of type int")))

	// Type alias candidate
	m = IdenticalTo(int(17))
	res, err = m.Matches(intAlias(17))

	ExpectFalse(res)
	ExpectThat(err, Error(Equals("which is of type intAlias")))

	// int and uint
	m = IdenticalTo(int(17))
	res, err = m.Matches(uint(17))

	ExpectFalse(res)
	ExpectThat(err, Error(Equals("which is of type uint")))
}

func (t *IdenticalToTest) NilExpectedValue() {
}

func (t *IdenticalToTest) NilCandidate() {
}

func (t *IdenticalToTest) Slices() {
}

func (t *IdenticalToTest) Maps() {
}

func (t *IdenticalToTest) Functions() {
}

func (t *IdenticalToTest) Channels() {
}

func (t *IdenticalToTest) Bools() {
}

func (t *IdenticalToTest) Ints() {
}

func (t *IdenticalToTest) Int8s() {
}

func (t *IdenticalToTest) Int16s() {
}

func (t *IdenticalToTest) Int32s() {
}

func (t *IdenticalToTest) Int64s() {
}

func (t *IdenticalToTest) Uints() {
}

func (t *IdenticalToTest) Uint8s() {
}

func (t *IdenticalToTest) Uint16s() {
}

func (t *IdenticalToTest) Uint32s() {
}

func (t *IdenticalToTest) Uint64s() {
}

func (t *IdenticalToTest) Float32s() {
}

func (t *IdenticalToTest) Float64s() {
}

func (t *IdenticalToTest) Complex64s() {
}

func (t *IdenticalToTest) Complex128s() {
}

func (t *IdenticalToTest) ComparableArrays() {
}

func (t *IdenticalToTest) NonComparableArrays() {
}

func (t *IdenticalToTest) ComparableInterfaces() {
}

func (t *IdenticalToTest) NonComparableInterfaces() {
}

func (t *IdenticalToTest) Pointers() {
}

func (t *IdenticalToTest) Strings() {
}

func (t *IdenticalToTest) ComparableStructs() {
}

func (t *IdenticalToTest) NonComparableStructs() {
}

func (t *IdenticalToTest) UnsafePointers() {
}

func (t *IdenticalToTest) IntAlias() {
}
<|endoftext|>


<commit_before>package backoff

import (
	"math/rand"
	"time"
)

/*
ExponentialBackOff is a backoff implementation that increases the backoff
period for each retry attempt using a randomization function that grows exponentially.

NextBackOff() is calculated using the following formula:

 randomized interval =
     RetryInterval * (random value in range [1 - RandomizationFactor, 1 + RandomizationFactor])

In other words NextBackOff() will range between the randomization factor
percentage below and above the retry interval.

For example, given the following parameters:

 RetryInterval = 2
 RandomizationFactor = 0.5
 Multiplier = 2

the actual backoff period used in the next retry attempt will range between 1 and 3 seconds,
multiplied by the exponential, that is, between 2 and 6 seconds.

Note: MaxInterval caps the RetryInterval and not the randomized interval.

If the time elapsed since an ExponentialBackOff instance is created goes past the
MaxElapsedTime, then the method NextBackOff() starts returning backoff.Stop.

The elapsed time can be reset by calling Reset().

Example: Given the following default arguments, for 10 tries the sequence will be,
and assuming we go over the MaxElapsedTime on the 10th try:

 Request #  RetryInterval (seconds)  Randomized Interval (seconds)

  1          0.5                     [0.25,   0.75]
  2          0.75                    [0.375,  1.125]
  3          1.125                   [0.562,  1.687]
  4          1.687                   [0.8435, 2.53]
  5          2.53                    [1.265,  3.795]
  6          3.795                   [1.897,  5.692]
  7          5.692                   [2.846,  8.538]
  8          8.538                   [4.269, 12.807]
  9         12.807                   [6.403, 19.210]
 10         19.210                   backoff.Stop

Note: Implementation is not thread-safe.
*/
type ExponentialBackOff struct {
	InitialInterval     time.Duration
	RandomizationFactor float64
	Multiplier          float64
	MaxInterval         time.Duration
	// After MaxElapsedTime the ExponentialBackOff stops.
	// It never stops if MaxElapsedTime == 0.
	MaxElapsedTime time.Duration
	Clock          Clock

	currentInterval time.Duration
	startTime       time.Time
}

// Clock is an interface that returns current time for BackOff.
type Clock interface {
	Now() time.Time
}

// Default values for ExponentialBackOff.
const (
	DefaultInitialInterval     = 500 * time.Millisecond
	DefaultRandomizationFactor = 0.5
	DefaultMultiplier          = 1.5
	DefaultMaxInterval         = 60 * time.Second
	DefaultMaxElapsedTime      = 15 * time.Minute
)

// withCanonicalRandomizationFactor is a utility function used by all
// NewXYZBackoff functions to clamp b.RandomizationFactor to either 0 or 1
func (b *ExponentialBackOff) withCanonicalRandomizationFactor() *ExponentialBackOff {
	if b.RandomizationFactor < 0 {
		b.RandomizationFactor = 0
	} else if b.RandomizationFactor > 1 {
		b.RandomizationFactor = 1
	}
	return b
}

// withReset is a utility function that calls 'b.Reset()' and then returns it,
// so that all NewXYZBackoff functions can reset their result and return it
// inline
func (b *ExponentialBackOff) withReset() *ExponentialBackOff {
	b.Reset()
	return b
}

// NewExponentialBackOff creates an instance of ExponentialBackOff using default values.
func NewExponentialBackOff() *ExponentialBackOff {
	b := &ExponentialBackOff{
		InitialInterval:     DefaultInitialInterval,
		RandomizationFactor: DefaultRandomizationFactor,
		Multiplier:          DefaultMultiplier,
		MaxInterval:         DefaultMaxInterval,
		MaxElapsedTime:      DefaultMaxElapsedTime,
		Clock:               SystemClock,
	}
	return b.withCanonicalRandomizationFactor().withReset()
}

// NewInfiniteBackOff creates an instance of ExponentialBackOff that never
// ends.
func NewInfiniteBackOff() *ExponentialBackOff {
	b := &ExponentialBackOff{
		InitialInterval:     DefaultInitialInterval,
		RandomizationFactor: DefaultRandomizationFactor,
		Multiplier:          DefaultMultiplier,
		MaxInterval:         15 * time.Second,
		MaxElapsedTime:      0,
		Clock:               SystemClock,
	}
	return b.withCanonicalRandomizationFactor().withReset()
}

// NewTestingBackOff returns a backoff tuned towards waiting for a Pachyderm
// state change in a test
func NewTestingBackOff() *ExponentialBackOff {
	b := &ExponentialBackOff{
		InitialInterval:     DefaultInitialInterval,
		RandomizationFactor: DefaultRandomizationFactor,
		Multiplier:          DefaultMultiplier,
		MaxInterval:         5 * time.Second,
		MaxElapsedTime:      60 * time.Second,
		Clock:               SystemClock,
	}
	return b.withCanonicalRandomizationFactor().withReset()
}

// New10sBackOff returns a backoff that's slightly more aggressive than
// NewExponentialBackOff. The Max Elapsed time for this backoff is 10s, and the
// initial backoff is 100ms (instead of 500). Therefore this will retry at most
// 10 times and then fail (depending on RPC timeout), and may be more useful
// for interactive RPCs than the default timeout of 60s.
func New10sBackOff() *ExponentialBackOff {
	b := &ExponentialBackOff{
		InitialInterval:     100 * time.Millisecond,
		RandomizationFactor: DefaultRandomizationFactor,
		Multiplier:          DefaultMultiplier,
		MaxInterval:         2 * time.Second,
		MaxElapsedTime:      10 * time.Second,
		Clock:               SystemClock,
	}
	return b.withCanonicalRandomizationFactor().withReset()
}

type systemClock struct{}

func (t systemClock) Now() time.Time {
	return time.Now()
}

// SystemClock implements Clock interface that uses time.Now().
var SystemClock = systemClock{}

// Reset the interval back to the initial retry interval and restarts the timer.
func (b *ExponentialBackOff) Reset() {
	b.currentInterval = b.InitialInterval
	b.startTime = b.Clock.Now()
}

// NextBackOff calculates the next backoff interval using the formula:
// 	Randomized interval = RetryInterval +/- (RandomizationFactor * RetryInterval)
func (b *ExponentialBackOff) NextBackOff() time.Duration {
	// Make sure we have not gone over the maximum elapsed time.
	if b.MaxElapsedTime != 0 && b.GetElapsedTime() > b.MaxElapsedTime {
		return Stop
	}
	defer b.incrementCurrentInterval()
	return getRandomValueFromInterval(b.RandomizationFactor, rand.Float64(), b.currentInterval)
}

// GetElapsedTime returns the elapsed time since an ExponentialBackOff instance
// is created and is reset when Reset() is called.
//
// The elapsed time is computed using time.Now().UnixNano().
func (b *ExponentialBackOff) GetElapsedTime() time.Duration {
	return b.Clock.Now().Sub(b.startTime)
}

// Increments the current interval by multiplying it with the multiplier.
func (b *ExponentialBackOff) incrementCurrentInterval() {
	// Check for overflow, if overflow is detected set the current interval to the max interval.
	if float64(b.currentInterval) >= float64(b.MaxInterval)/b.Multiplier {
		b.currentInterval = b.MaxInterval
	} else {
		b.currentInterval = time.Duration(float64(b.currentInterval) * b.Multiplier)
	}
}

// Returns a random value from the following interval:
// 	[randomizationFactor * currentInterval, randomizationFactor * currentInterval].
func getRandomValueFromInterval(randomizationFactor, random float64, currentInterval time.Duration) time.Duration {
	var delta = randomizationFactor * float64(currentInterval)
	var minInterval = float64(currentInterval) - delta
	var maxInterval = float64(currentInterval) + delta

	// Get a random value from the range [minInterval, maxInterval].
	// The formula used below has a +1 because if the minInterval is 1 and the maxInterval is 3 then
	// we want a 33% chance for selecting either 1, 2 or 3.
	return time.Duration(minInterval + (random * (maxInterval - minInterval + 1)))
}
<commit_msg>Add New60sBackOff to backoff/exponential.go<commit_after>package backoff

import (
	"math/rand"
	"time"
)

/*
ExponentialBackOff is a backoff implementation that increases the backoff
period for each retry attempt using a randomization function that grows exponentially.

NextBackOff() is calculated using the following formula:

 randomized interval =
     RetryInterval * (random value in range [1 - RandomizationFactor, 1 + RandomizationFactor])

In other words NextBackOff() will range between the randomization factor
percentage below and above the retry interval.

For example, given the following parameters:

 RetryInterval = 2
 RandomizationFactor = 0.5
 Multiplier = 2

the actual backoff period used in the next retry attempt will range between 1 and 3 seconds,
multiplied by the exponential, that is, between 2 and 6 seconds.

Note: MaxInterval caps the RetryInterval and not the randomized interval.

If the time elapsed since an ExponentialBackOff instance is created goes past the
MaxElapsedTime, then the method NextBackOff() starts returning backoff.Stop.

The elapsed time can be reset by calling Reset().

Example: Given the following default arguments, for 10 tries the sequence will be,
and assuming we go over the MaxElapsedTime on the 10th try:

 Request #  RetryInterval (seconds)  Randomized Interval (seconds)

  1          0.5                     [0.25,   0.75]
  2          0.75                    [0.375,  1.125]
  3          1.125                   [0.562,  1.687]
  4          1.687                   [0.8435, 2.53]
  5          2.53                    [1.265,  3.795]
  6          3.795                   [1.897,  5.692]
  7          5.692                   [2.846,  8.538]
  8          8.538                   [4.269, 12.807]
  9         12.807                   [6.403, 19.210]
 10         19.210                   backoff.Stop

Note: Implementation is not thread-safe.
*/
type ExponentialBackOff struct {
	InitialInterval     time.Duration
	RandomizationFactor float64
	Multiplier          float64
	MaxInterval         time.Duration
	// After MaxElapsedTime the ExponentialBackOff stops.
	// It never stops if MaxElapsedTime == 0.
	MaxElapsedTime time.Duration
	Clock          Clock

	currentInterval time.Duration
	startTime       time.Time
}

// Clock is an interface that returns current time for BackOff.
type Clock interface {
	Now() time.Time
}

// Default values for ExponentialBackOff.
const (
	DefaultInitialInterval     = 500 * time.Millisecond
	DefaultRandomizationFactor = 0.5
	DefaultMultiplier          = 1.5
	DefaultMaxInterval         = 60 * time.Second
	DefaultMaxElapsedTime      = 15 * time.Minute
)

// withCanonicalRandomizationFactor is a utility function used by all
// NewXYZBackoff functions to clamp b.RandomizationFactor to either 0 or 1
func (b *ExponentialBackOff) withCanonicalRandomizationFactor() *ExponentialBackOff {
	if b.RandomizationFactor < 0 {
		b.RandomizationFactor = 0
	} else if b.RandomizationFactor > 1 {
		b.RandomizationFactor = 1
	}
	return b
}

// withReset is a utility function that calls 'b.Reset()' and then returns it,
// so that all NewXYZBackoff functions can reset their result and return it
// inline
func (b *ExponentialBackOff) withReset() *ExponentialBackOff {
	b.Reset()
	return b
}

// NewExponentialBackOff creates an instance of ExponentialBackOff using default values.
func NewExponentialBackOff() *ExponentialBackOff {
	b := &ExponentialBackOff{
		InitialInterval:     DefaultInitialInterval,
		RandomizationFactor: DefaultRandomizationFactor,
		Multiplier:          DefaultMultiplier,
		MaxInterval:         DefaultMaxInterval,
		MaxElapsedTime:      DefaultMaxElapsedTime,
		Clock:               SystemClock,
	}
	return b.withCanonicalRandomizationFactor().withReset()
}

// NewInfiniteBackOff creates an instance of ExponentialBackOff that never
// ends.
func NewInfiniteBackOff() *ExponentialBackOff {
	b := &ExponentialBackOff{
		InitialInterval:     DefaultInitialInterval,
		RandomizationFactor: DefaultRandomizationFactor,
		Multiplier:          DefaultMultiplier,
		MaxInterval:         15 * time.Second,
		MaxElapsedTime:      0,
		Clock:               SystemClock,
	}
	return b.withCanonicalRandomizationFactor().withReset()
}

// NewTestingBackOff returns a backoff tuned towards waiting for a Pachyderm
// state change in a test
func NewTestingBackOff() *ExponentialBackOff {
	b := &ExponentialBackOff{
		InitialInterval:     DefaultInitialInterval,
		RandomizationFactor: DefaultRandomizationFactor,
		Multiplier:          DefaultMultiplier,
		MaxInterval:         5 * time.Second,
		MaxElapsedTime:      60 * time.Second,
		Clock:               SystemClock,
	}
	return b.withCanonicalRandomizationFactor().withReset()
}

// New10sBackOff returns a backoff that's slightly more aggressive than
// NewExponentialBackOff. The Max Elapsed time for this backoff is 10s, and the
// initial backoff is 100ms (instead of 500). Therefore this will retry at most
// 10 times and then fail (depending on RPC timeout), and may be more useful
// for interactive RPCs than NewExponentialBackOff.
func New10sBackOff() *ExponentialBackOff {
	b := &ExponentialBackOff{
		InitialInterval:     100 * time.Millisecond,
		RandomizationFactor: DefaultRandomizationFactor,
		Multiplier:          DefaultMultiplier,
		MaxInterval:         2 * time.Second,
		MaxElapsedTime:      10 * time.Second,
		Clock:               SystemClock,
	}
	return b.withCanonicalRandomizationFactor().withReset()
}

// New60sBackOff returns a backoff that's slightly more aggressive than
// NewExponentialBackOff. The Max Elapsed time for this backoff is 60s, and the
// initial backoff is 100ms (instead of 500). This may be more useful for
// watcher and controllers (e.g. the PPS master or the worker) than
// NewExponentialBackOff
func New60sBackOff() *ExponentialBackOff {
	b := &ExponentialBackOff{
		InitialInterval:     100 * time.Millisecond,
		RandomizationFactor: DefaultRandomizationFactor,
		Multiplier:          DefaultMultiplier,
		MaxInterval:         2 * time.Second,
		MaxElapsedTime:      60 * time.Second,
		Clock:               SystemClock,
	}
	return b.withCanonicalRandomizationFactor().withReset()
}

type systemClock struct{}

func (t systemClock) Now() time.Time {
	return time.Now()
}

// SystemClock implements Clock interface that uses time.Now().
var SystemClock = systemClock{}

// Reset the interval back to the initial retry interval and restarts the timer.
func (b *ExponentialBackOff) Reset() {
	b.currentInterval = b.InitialInterval
	b.startTime = b.Clock.Now()
}

// NextBackOff calculates the next backoff interval using the formula:
// 	Randomized interval = RetryInterval +/- (RandomizationFactor * RetryInterval)
func (b *ExponentialBackOff) NextBackOff() time.Duration {
	// Make sure we have not gone over the maximum elapsed time.
	if b.MaxElapsedTime != 0 && b.GetElapsedTime() > b.MaxElapsedTime {
		return Stop
	}
	defer b.incrementCurrentInterval()
	return getRandomValueFromInterval(b.RandomizationFactor, rand.Float64(), b.currentInterval)
}

// GetElapsedTime returns the elapsed time since an ExponentialBackOff instance
// is created and is reset when Reset() is called.
//
// The elapsed time is computed using time.Now().UnixNano().
func (b *ExponentialBackOff) GetElapsedTime() time.Duration {
	return b.Clock.Now().Sub(b.startTime)
}

// Increments the current interval by multiplying it with the multiplier.
func (b *ExponentialBackOff) incrementCurrentInterval() {
	// Check for overflow, if overflow is detected set the current interval to the max interval.
	if float64(b.currentInterval) >= float64(b.MaxInterval)/b.Multiplier {
		b.currentInterval = b.MaxInterval
	} else {
		b.currentInterval = time.Duration(float64(b.currentInterval) * b.Multiplier)
	}
}

// Returns a random value from the following interval:
// 	[randomizationFactor * currentInterval, randomizationFactor * currentInterval].
func getRandomValueFromInterval(randomizationFactor, random float64, currentInterval time.Duration) time.Duration {
	var delta = randomizationFactor * float64(currentInterval)
	var minInterval = float64(currentInterval) - delta
	var maxInterval = float64(currentInterval) + delta

	// Get a random value from the range [minInterval, maxInterval].
	// The formula used below has a +1 because if the minInterval is 1 and the maxInterval is 3 then
	// we want a 33% chance for selecting either 1, 2 or 3.
	return time.Duration(minInterval + (random * (maxInterval - minInterval + 1)))
}
<|endoftext|>


<commit_before>package v1payload

//WorkloadSummary is a smaller representation of a workload
type WorkloadSummary struct {
	ProjectID      string `json:"project_id"`
	WorkloadID     string `json:"workload_id"`
	Image          string `json:"image"`
	Instances      int    `json:"instances"`
	InputDatasetID string `json:"input_dataset_id"`
}

//ListWorkloadsInput is input for workload listing
type ListWorkloadsInput struct {
	ProjectID string `json:"project_id" valid:"required"`
}

//ListWorkloadsOutput is output for workload listing
type ListWorkloadsOutput struct {
	Workloads []*WorkloadSummary
}

//DescribeWorkloadInput is input for getting workload information
type DescribeWorkloadInput struct {
	ProjectID  string `json:"project_id" valid:"required"`
	WorkloadID string `json:"workload_id"`
}

//TaskStatus represents the status of a task
type TaskStatus string

//DescribeWorkloadOutput is output for getting workload information
type DescribeWorkloadOutput struct {
	WorkloadSummary
	TaskCount map[TaskStatus]int `json:"task_count"`
	Env       map[string]string  `json:"env"`
	QueueURL  string             `json:"queue_url"`
}

//StartWorkloadInput is input for workload creation
type StartWorkloadInput struct {
	ProjectID      string            `json:"project_id" valid:"required"`
	Image          string            `json:"image" valid:"required"`
	Instances      int               `json:"instances" valid:"required"`
	InputDatasetID string            `json:"input_dataset_id"`
	Env            map[string]string `json:"env"`
}

//StartWorkloadOutput is output for workload creation
type StartWorkloadOutput struct {
	WorkloadSummary
}

//StopWorkloadInput is input for workload deletion
type StopWorkloadInput struct {
	ProjectID  string `json:"project_id" valid:"required"`
	WorkloadID string `json:"workload_id" valid:"required"`
}

//StopWorkloadOutput is output for workload deletion
type StopWorkloadOutput struct{}
<commit_msg>Add queue url<commit_after>package v1payload

//WorkloadSummary is a smaller representation of a workload
type WorkloadSummary struct {
	ProjectID      string `json:"project_id"`
	WorkloadID     string `json:"workload_id"`
	QueueURL       string `json:"queue_url"`
	Image          string `json:"image"`
	Instances      int    `json:"instances"`
	InputDatasetID string `json:"input_dataset_id"`
}

//ListWorkloadsInput is input for workload listing
type ListWorkloadsInput struct {
	ProjectID string `json:"project_id" valid:"required"`
}

//ListWorkloadsOutput is output for workload listing
type ListWorkloadsOutput struct {
	Workloads []*WorkloadSummary
}

//DescribeWorkloadInput is input for getting workload information
type DescribeWorkloadInput struct {
	ProjectID  string `json:"project_id" valid:"required"`
	WorkloadID string `json:"workload_id"`
}

//TaskStatus represents the status of a task
type TaskStatus string

//DescribeWorkloadOutput is output for getting workload information
type DescribeWorkloadOutput struct {
	WorkloadSummary
	TaskCount map[TaskStatus]int `json:"task_count"`
	Env       map[string]string  `json:"env"`
	QueueURL  string             `json:"queue_url"`
}

//StartWorkloadInput is input for workload creation
type StartWorkloadInput struct {
	ProjectID      string            `json:"project_id" valid:"required"`
	Image          string            `json:"image" valid:"required"`
	Instances      int               `json:"instances" valid:"required"`
	InputDatasetID string            `json:"input_dataset_id"`
	Env            map[string]string `json:"env"`
}

//StartWorkloadOutput is output for workload creation
type StartWorkloadOutput struct {
	WorkloadSummary
}

//StopWorkloadInput is input for workload deletion
type StopWorkloadInput struct {
	ProjectID  string `json:"project_id" valid:"required"`
	WorkloadID string `json:"workload_id" valid:"required"`
}

//StopWorkloadOutput is output for workload deletion
type StopWorkloadOutput struct{}
<|endoftext|>


<commit_before>package db

import (
	"database/sql"
	"encoding/json"
	"errors"
	"strings"
	"time"
)

// Handler contains reference to the database client
type Handler struct {
	*sql.DB
}

// Search returns search results for applications
func (handler Handler) Search(query string) (RebbleCards, error) {
	query = strings.Replace(query, "!", "!!", -1)
	query = strings.Replace(query, "%", "!%", -1)
	query = strings.Replace(query, "_", "!_", -1)
	query = strings.Replace(query, "[", "![", -1)
	query = "%" + query + "%"

	var cards RebbleCards
	rows, err := handler.Query(
		"SELECT id, name, type, thumbs_up, screenshots FROM apps WHERE name LIKE ? ESCAPE '!' ORDER BY thumbs_up DESC LIMIT 12",
		query,
	)
	if err != nil {
		return cards, err
	}
	cards.Cards = make([]RebbleCard, 0)
	for rows.Next() {
		card := RebbleCard{}
		var screenshots_b []byte
		var screenshots []RebbleScreenshotsPlatform
		err = rows.Scan(&card.Id, &card.Title, &card.Type, &card.ThumbsUp, &screenshots_b)
		if err != nil {
			return RebbleCards{}, err
		}
		err = json.Unmarshal(screenshots_b, &screenshots)
		if err != nil {
			return RebbleCards{}, err
		}
		if len(screenshots) != 0 && len(screenshots[0].Screenshots) != 0 {
			card.ImageUrl = screenshots[0].Screenshots[0]
		}
		cards.Cards = append(cards.Cards, card)
	}
	return cards, nil
}

// GetAppsForCollection returns list of apps for single collection
func (handler Handler) GetAppsForCollection(collectionID string, sortByPopular bool) ([]RebbleApplication, error) {
	var order string

	if sortByPopular {
		order = "thumbs_up"
	} else {
		order = "published_date"
	}

	rows, err := handler.Query("SELECT apps FROM collections WHERE id=?", collectionID)
	if err != nil {
		return nil, err
	}
	if !rows.Next() {
		return nil, errors.New("Specified collection does not exist")
	}
	var appIdsB []byte
	var appIds []string
	err = rows.Scan(&appIdsB)
	if err != nil {
		return nil, err
	}
	json.Unmarshal(appIdsB, &appIds)

	for i, appId := range appIds {
		appIds[i] = "'" + appId + "'"
	}

	idList := strings.Join(appIds, ", ")

	apps := make([]RebbleApplication, 0)

	// It is not possible to give a list or an order via a prepared statement, so this will have to do. Unless someone managed to change their application ID to a SQL injection, this is perfectly safe.
	rows, err = handler.Query("SELECT id, name, type, thumbs_up, screenshots, published_date, supported_platforms FROM apps WHERE id IN (" + idList + ") ORDER BY " + order + " DESC")
	if err != nil {
		return nil, err
	}

	for rows.Next() {
		app := RebbleApplication{}
		var t int64
		var supported_platforms_b []byte
		var screenshots_b []byte
		err = rows.Scan(&app.Id, &app.Name, &app.Type, &app.ThumbsUp, &screenshots_b, &t, &supported_platforms_b)
		if err != nil {
			return []RebbleApplication{}, err
		}
		app.Published.Time = time.Unix(0, t)
		err = json.Unmarshal(supported_platforms_b, &app.SupportedPlatforms)
		if err != nil {
			return []RebbleApplication{}, err
		}
		err = json.Unmarshal(screenshots_b, &app.Assets.Screenshots)
		if err != nil {
			return []RebbleApplication{}, err
		}
		apps = append(apps, app)
	}
	return apps, nil
}

// GetCollectionName returns the name of a collection
func (handler Handler) GetCollectionName(collectionID string) (string, error) {
	rows, err := handler.Query("SELECT name FROM collections WHERE id=?", collectionID)
	if err != nil {
		return "", err
	}
	if !rows.Next() {
		return "", errors.New("Specified collection does not exist")
	}
	var name string
	err = rows.Scan(&name)
	if err != nil {
		return "", err
	}

	return name, nil
}

// GetAllApps returns all available apps
func (handler Handler) GetAllApps(sortby string, ascending bool, offset int, limit int) ([]RebbleApplication, error) {
	order := "DESC"
	if ascending {
		order = "ASC"
	}

	var orderCol string
	switch sortby {
	case "popular":
		orderCol = "apps.thumbs_up"
	case "recent":
		orderCol = "apps.published_date"
	default:
		return nil, errors.New("Invalid sortby parameter")
	}

	// this code looks weird, but ORDER BY does not currently work with prepared statements,
	// that is why it is written this way. it should be completely safe as it doesn't take user input
	rows, err := handler.Query(`
		SELECT apps.name, authors.name, apps.icon_url, apps.id, apps.thumbs_up, apps.published_date
		FROM apps
		JOIN authors ON apps.author_id = authors.id
		ORDER BY `+orderCol+" "+order+`
		LIMIT ?
		OFFSET ?
	`, limit, offset)
	if err != nil {
		return nil, err
	}
	apps := make([]RebbleApplication, 0)
	for rows.Next() {
		app := RebbleApplication{}
		var t_published int64
		err = rows.Scan(&app.Name, &app.Author.Name, &app.Assets.Icon, &app.Id, &app.ThumbsUp, &t_published)
		app.Published.Time = time.Unix(0, t_published)

		apps = append(apps, app)
	}
	return apps, nil
}

// GetApp returns a specific app
func (handler Handler) GetApp(id string) (RebbleApplication, error) {
	row := handler.QueryRow("SELECT apps.id, apps.name, apps.author_id, authors.name, apps.tag_ids, apps.description, apps.thumbs_up, apps.type, apps.supported_platforms, apps.published_date, apps.pbw_url, apps.rebble_ready, apps.updated, apps.version, apps.support_url, apps.author_url, apps.source_url, apps.screenshots, apps.banner_url, apps.icon_url, apps.doomsday_backup FROM apps JOIN authors ON apps.author_id = authors.id WHERE apps.id=?", id)

	app := RebbleApplication{}
	var supportedPlatforms_b []byte
	var t_published, t_updated int64
	var tagIds_b []byte
	var tagIds []string
	var screenshots_b []byte
	var screenshots *([]RebbleScreenshotsPlatform)
	err := row.Scan(&app.Id, &app.Name, &app.Author.Id, &app.Author.Name, &tagIds_b, &app.Description, &app.ThumbsUp, &app.Type, &supportedPlatforms_b, &t_published, &app.AppInfo.PbwUrl, &app.AppInfo.RebbleReady, &t_updated, &app.AppInfo.Version, &app.AppInfo.SupportUrl, &app.AppInfo.AuthorUrl, &app.AppInfo.SourceUrl, &screenshots_b, &app.Assets.Banner, &app.Assets.Icon, &app.DoomsdayBackup)
	if err == sql.ErrNoRows {
		return RebbleApplication{}, errors.New("No application with this ID")
	} else if err != nil {
		return RebbleApplication{}, err
	}

	json.Unmarshal(supportedPlatforms_b, &app.SupportedPlatforms)
	app.Published.Time = time.Unix(0, t_published)
	app.AppInfo.Updated.Time = time.Unix(0, t_updated)
	json.Unmarshal(tagIds_b, &tagIds)
	app.AppInfo.Tags = make([]RebbleCollection, len(tagIds))
	json.Unmarshal(screenshots_b, &screenshots)
	app.Assets.Screenshots = screenshots

	for i, tagID := range tagIds {
		row := handler.QueryRow("SELECT id, name, color FROM collections WHERE id=?", tagID)

		err = row.Scan(&app.AppInfo.Tags[i].Id, &app.AppInfo.Tags[i].Name, &app.AppInfo.Tags[i].Color)
		if err != nil {
			return RebbleApplication{}, err
		}
	}

	return app, nil
}

// GetAppTags returns the the list of tags of the application with the id `id`
func (handler Handler) GetAppTags(id string) ([]RebbleCollection, error) {
	rows, err := handler.Query("SELECT apps.tag_ids FROM apps WHERE id=?", id)
	if err != nil {
		return []RebbleCollection{}, err
	}
	exists := rows.Next()
	if !exists {
		return []RebbleCollection{}, err
	}

	var tagIds_b []byte
	var tagIds []string
	err = rows.Scan(&tagIds_b)
	if err != nil {
		return []RebbleCollection{}, err
	}
	json.Unmarshal(tagIds_b, &tagIds)
	collections := make([]RebbleCollection, len(tagIds))

	for i, tagId := range tagIds {
		rows, err := handler.Query("SELECT id, name, color FROM collections WHERE id=?", tagId)
		if err != nil {
			return []RebbleCollection{}, err
		}

		rows.Next()
		err = rows.Scan(&collections[i].Id, &collections[i].Name, &collections[i].Color)
		if err != nil {
			return []RebbleCollection{}, err
		}
	}

	return collections, nil
}

// GetAppVersions returns the the list of versions of the application with the id `id`
func (handler Handler) GetAppVersions(id string) ([]RebbleVersion, error) {
	rows, err := handler.Query("SELECT apps.versions FROM apps WHERE id=?", id)
	if err != nil {
		return []RebbleVersion{}, err
	}
	exists := rows.Next()
	if !exists {
		return []RebbleVersion{}, errors.New("No app with this ID")
	}

	var versions_b []byte
	var versions []RebbleVersion
	err = rows.Scan(&versions_b)
	if err != nil {
		return []RebbleVersion{}, err
	}
	json.Unmarshal(versions_b, &versions)

	return versions, nil
}
<commit_msg>Fixes to GetAppsForCollection() as requested on #27<commit_after>package db

import (
	"database/sql"
	"encoding/json"
	"errors"
	"regexp"
	"strings"
	"time"
)

// Handler contains reference to the database client
type Handler struct {
	*sql.DB
}

// Search returns search results for applications
func (handler Handler) Search(query string) (RebbleCards, error) {
	query = strings.Replace(query, "!", "!!", -1)
	query = strings.Replace(query, "%", "!%", -1)
	query = strings.Replace(query, "_", "!_", -1)
	query = strings.Replace(query, "[", "![", -1)
	query = "%" + query + "%"

	var cards RebbleCards
	rows, err := handler.Query(
		"SELECT id, name, type, thumbs_up, screenshots FROM apps WHERE name LIKE ? ESCAPE '!' ORDER BY thumbs_up DESC LIMIT 12",
		query,
	)
	if err != nil {
		return cards, err
	}
	cards.Cards = make([]RebbleCard, 0)
	for rows.Next() {
		card := RebbleCard{}
		var screenshots_b []byte
		var screenshots []RebbleScreenshotsPlatform
		err = rows.Scan(&card.Id, &card.Title, &card.Type, &card.ThumbsUp, &screenshots_b)
		if err != nil {
			return RebbleCards{}, err
		}
		err = json.Unmarshal(screenshots_b, &screenshots)
		if err != nil {
			return RebbleCards{}, err
		}
		if len(screenshots) != 0 && len(screenshots[0].Screenshots) != 0 {
			card.ImageUrl = screenshots[0].Screenshots[0]
		}
		cards.Cards = append(cards.Cards, card)
	}
	return cards, nil
}

// GetAppsForCollection returns list of apps for single collection
func (handler Handler) GetAppsForCollection(collectionID string, sortByPopular bool) ([]RebbleApplication, error) {
	var order string

	if sortByPopular {
		order = "thumbs_up"
	} else {
		order = "published_date"
	}

	row := handler.QueryRow("SELECT apps FROM collections WHERE id=?", collectionID)
	var appIdsB []byte
	var appIds []string
	err := row.Scan(&appIdsB)
	if err != nil {
		return nil, err
	}
	json.Unmarshal(appIdsB, &appIds)

	for i, appId := range appIds {
		appIds[i] = "'" + appId + "'"
	}

	idList := strings.Join(appIds, ", ")

	// There is no feasible way for idList to contain user generated data, and therefore for it to be a SQL injection vector. But just in case, we strip any non-authorized character
	reg, err := regexp.Compile("[^a-zA-Z0-9, ']+")
	if err != nil {
		return nil, err
	}
	idList = reg.ReplaceAllString(idList, "")

	apps := make([]RebbleApplication, 0)

	// It is not possible to give a list or an order via a prepared statement, so this will have to do. We just sanitized idList, so SQL injection isn't a concern.
	rows, err := handler.Query("SELECT id, name, type, thumbs_up, screenshots, published_date, supported_platforms FROM apps WHERE id IN (" + idList + ") ORDER BY " + order + " DESC")
	if err != nil {
		return nil, err
	}

	defer rows.Close()

	for rows.Next() {
		app := RebbleApplication{}
		var t int64
		var supported_platforms_b []byte
		var screenshots_b []byte
		err = rows.Scan(&app.Id, &app.Name, &app.Type, &app.ThumbsUp, &screenshots_b, &t, &supported_platforms_b)
		if err != nil {
			return []RebbleApplication{}, err
		}
		app.Published.Time = time.Unix(0, t)
		err = json.Unmarshal(supported_platforms_b, &app.SupportedPlatforms)
		if err != nil {
			return []RebbleApplication{}, err
		}
		err = json.Unmarshal(screenshots_b, &app.Assets.Screenshots)
		if err != nil {
			return []RebbleApplication{}, err
		}
		apps = append(apps, app)
	}
	return apps, nil
}

// GetCollectionName returns the name of a collection
func (handler Handler) GetCollectionName(collectionID string) (string, error) {
	rows, err := handler.Query("SELECT name FROM collections WHERE id=?", collectionID)
	if err != nil {
		return "", err
	}
	if !rows.Next() {
		return "", errors.New("Specified collection does not exist")
	}
	var name string
	err = rows.Scan(&name)
	if err != nil {
		return "", err
	}

	return name, nil
}

// GetAllApps returns all available apps
func (handler Handler) GetAllApps(sortby string, ascending bool, offset int, limit int) ([]RebbleApplication, error) {
	order := "DESC"
	if ascending {
		order = "ASC"
	}

	var orderCol string
	switch sortby {
	case "popular":
		orderCol = "apps.thumbs_up"
	case "recent":
		orderCol = "apps.published_date"
	default:
		return nil, errors.New("Invalid sortby parameter")
	}

	// this code looks weird, but ORDER BY does not currently work with prepared statements,
	// that is why it is written this way. it should be completely safe as it doesn't take user input
	rows, err := handler.Query(`
		SELECT apps.name, authors.name, apps.icon_url, apps.id, apps.thumbs_up, apps.published_date
		FROM apps
		JOIN authors ON apps.author_id = authors.id
		ORDER BY `+orderCol+" "+order+`
		LIMIT ?
		OFFSET ?
	`, limit, offset)
	if err != nil {
		return nil, err
	}
	apps := make([]RebbleApplication, 0)
	for rows.Next() {
		app := RebbleApplication{}
		var t_published int64
		err = rows.Scan(&app.Name, &app.Author.Name, &app.Assets.Icon, &app.Id, &app.ThumbsUp, &t_published)
		app.Published.Time = time.Unix(0, t_published)

		apps = append(apps, app)
	}
	return apps, nil
}

// GetApp returns a specific app
func (handler Handler) GetApp(id string) (RebbleApplication, error) {
	row := handler.QueryRow("SELECT apps.id, apps.name, apps.author_id, authors.name, apps.tag_ids, apps.description, apps.thumbs_up, apps.type, apps.supported_platforms, apps.published_date, apps.pbw_url, apps.rebble_ready, apps.updated, apps.version, apps.support_url, apps.author_url, apps.source_url, apps.screenshots, apps.banner_url, apps.icon_url, apps.doomsday_backup FROM apps JOIN authors ON apps.author_id = authors.id WHERE apps.id=?", id)

	app := RebbleApplication{}
	var supportedPlatforms_b []byte
	var t_published, t_updated int64
	var tagIds_b []byte
	var tagIds []string
	var screenshots_b []byte
	var screenshots *([]RebbleScreenshotsPlatform)
	err := row.Scan(&app.Id, &app.Name, &app.Author.Id, &app.Author.Name, &tagIds_b, &app.Description, &app.ThumbsUp, &app.Type, &supportedPlatforms_b, &t_published, &app.AppInfo.PbwUrl, &app.AppInfo.RebbleReady, &t_updated, &app.AppInfo.Version, &app.AppInfo.SupportUrl, &app.AppInfo.AuthorUrl, &app.AppInfo.SourceUrl, &screenshots_b, &app.Assets.Banner, &app.Assets.Icon, &app.DoomsdayBackup)
	if err == sql.ErrNoRows {
		return RebbleApplication{}, errors.New("No application with this ID")
	} else if err != nil {
		return RebbleApplication{}, err
	}

	json.Unmarshal(supportedPlatforms_b, &app.SupportedPlatforms)
	app.Published.Time = time.Unix(0, t_published)
	app.AppInfo.Updated.Time = time.Unix(0, t_updated)
	json.Unmarshal(tagIds_b, &tagIds)
	app.AppInfo.Tags = make([]RebbleCollection, len(tagIds))
	json.Unmarshal(screenshots_b, &screenshots)
	app.Assets.Screenshots = screenshots

	for i, tagID := range tagIds {
		row := handler.QueryRow("SELECT id, name, color FROM collections WHERE id=?", tagID)

		err = row.Scan(&app.AppInfo.Tags[i].Id, &app.AppInfo.Tags[i].Name, &app.AppInfo.Tags[i].Color)
		if err != nil {
			return RebbleApplication{}, err
		}
	}

	return app, nil
}

// GetAppTags returns the the list of tags of the application with the id `id`
func (handler Handler) GetAppTags(id string) ([]RebbleCollection, error) {
	rows, err := handler.Query("SELECT apps.tag_ids FROM apps WHERE id=?", id)
	if err != nil {
		return []RebbleCollection{}, err
	}
	exists := rows.Next()
	if !exists {
		return []RebbleCollection{}, err
	}

	var tagIds_b []byte
	var tagIds []string
	err = rows.Scan(&tagIds_b)
	if err != nil {
		return []RebbleCollection{}, err
	}
	json.Unmarshal(tagIds_b, &tagIds)
	collections := make([]RebbleCollection, len(tagIds))

	for i, tagId := range tagIds {
		rows, err := handler.Query("SELECT id, name, color FROM collections WHERE id=?", tagId)
		if err != nil {
			return []RebbleCollection{}, err
		}

		rows.Next()
		err = rows.Scan(&collections[i].Id, &collections[i].Name, &collections[i].Color)
		if err != nil {
			return []RebbleCollection{}, err
		}
	}

	return collections, nil
}

// GetAppVersions returns the the list of versions of the application with the id `id`
func (handler Handler) GetAppVersions(id string) ([]RebbleVersion, error) {
	rows, err := handler.Query("SELECT apps.versions FROM apps WHERE id=?", id)
	if err != nil {
		return []RebbleVersion{}, err
	}
	exists := rows.Next()
	if !exists {
		return []RebbleVersion{}, errors.New("No app with this ID")
	}

	var versions_b []byte
	var versions []RebbleVersion
	err = rows.Scan(&versions_b)
	if err != nil {
		return []RebbleVersion{}, err
	}
	json.Unmarshal(versions_b, &versions)

	return versions, nil
}
<|endoftext|>


<commit_before>// Copyright 2014 The Serviced 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 cgroup

import (
	"bufio"
	"fmt"
	"io/ioutil"
	"strconv"
	"strings"
	"github.com/control-center/serviced/utils"
)

const (
    Cpuacct string = "cpuacct"
    Memory string = "memory"
)

// Helper function that takes a docker ID and parameter (to specify cpu or memory)
// and returns a path to the correct stats file
func GetCgroupDockerStatsFilePath(dockerID string, stat string) string {
    statsFile := ""
    if utils.Platform == utils.Debian {
        statsFile = "/sys/fs/cgroup/" + stat + "/docker/" + dockerID + "/" + stat + ".stat"
    } else {
        statsFile = "/sys/fs/cgroup/" + stat + "/system.slice/docker-" + dockerID + ".scope/" + stat + ".stat"
    }
    return statsFile
}

// parseSSKVint64 parses a space-separated key-value pair file and returns a
// key(string):value(int64) mapping.
func parseSSKVint64(filename string) (map[string]int64, error) {
	kv, err := parseSSKV(filename)
	if err != nil {
		return nil, err
	}
	mapping := make(map[string]int64)
	for k, v := range kv {
		n, err := strconv.ParseInt(v, 0, 64)
		if err != nil {
			uintVal, uintErr := strconv.ParseUint(v, 0, 64)
			if uintErr == nil {
				// the value is 64-bit unsigned, so we will cast it to a signed 64-bit integer.  This will result
				// in an incorrect value, but will allow us to report other metrics without breaking everything
				n = int64(uintVal)
			} else {
				return nil, err
			}
		}
		mapping[k] = n
	}
	return mapping, nil
}

// parseSSKV parses a space-separated key-value pair file and returns a
// key(string):value(string) mapping.
func parseSSKV(filename string) (map[string]string, error) {
	stats, err := ioutil.ReadFile(filename)
	if err != nil {
		return nil, err
	}
	mapping := make(map[string]string)
	scanner := bufio.NewScanner(strings.NewReader(string(stats)))
	for scanner.Scan() {
		line := scanner.Text()
		parts := strings.Fields(line)
		if len(parts) != 2 {
			return nil, fmt.Errorf("expected 2 parts, got %d: %s", len(parts), line)
		}
		mapping[parts[0]] = parts[1]
	}
	return mapping, nil
}
<commit_msg>CC-1432: Location for docker container cgroup data changed. Update container stat collection to reflect.<commit_after>// Copyright 2014 The Serviced 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 cgroup

import (
	"bufio"
	"fmt"
	"io/ioutil"
	"strconv"
	"strings"
	"os"
)

const (
    Cpuacct string = "cpuacct"
    Memory string = "memory"
)

// Helper function that takes a docker ID and parameter (to specify cpu or memory)
// and returns a path to the correct stats file
func GetCgroupDockerStatsFilePath(dockerID string, stat string) string {
	debFile := "/sys/fs/cgroup/" + stat + "/docker/" + dockerID + "/" + stat + ".stat"
	linFile := "/sys/fs/cgroup/" + stat + "/system.slice/docker-" + dockerID + ".scope/" + stat + ".stat"
	if _, err := os.Stat(debFile); err == nil {
		return debFile
	}
	if _, err := os.Stat(linFile); err == nil {
		return linFile
	}
    return ""
}

// parseSSKVint64 parses a space-separated key-value pair file and returns a
// key(string):value(int64) mapping.
func parseSSKVint64(filename string) (map[string]int64, error) {
	kv, err := parseSSKV(filename)
	if err != nil {
		return nil, err
	}
	mapping := make(map[string]int64)
	for k, v := range kv {
		n, err := strconv.ParseInt(v, 0, 64)
		if err != nil {
			uintVal, uintErr := strconv.ParseUint(v, 0, 64)
			if uintErr == nil {
				// the value is 64-bit unsigned, so we will cast it to a signed 64-bit integer.  This will result
				// in an incorrect value, but will allow us to report other metrics without breaking everything
				n = int64(uintVal)
			} else {
				return nil, err
			}
		}
		mapping[k] = n
	}
	return mapping, nil
}

// parseSSKV parses a space-separated key-value pair file and returns a
// key(string):value(string) mapping.
func parseSSKV(filename string) (map[string]string, error) {
	stats, err := ioutil.ReadFile(filename)
	if err != nil {
		return nil, err
	}
	mapping := make(map[string]string)
	scanner := bufio.NewScanner(strings.NewReader(string(stats)))
	for scanner.Scan() {
		line := scanner.Text()
		parts := strings.Fields(line)
		if len(parts) != 2 {
			return nil, fmt.Errorf("expected 2 parts, got %d: %s", len(parts), line)
		}
		mapping[parts[0]] = parts[1]
	}
	return mapping, nil
}
<|endoftext|>


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

package orchestrator

import (
	"fmt"
	"github.com/andreaskoch/allmark2/common/index"
	"github.com/andreaskoch/allmark2/common/paths"
	"github.com/andreaskoch/allmark2/common/route"
	"github.com/andreaskoch/allmark2/ui/web/view/viewmodel"
)

func NewSitemapOrchestrator(itemIndex *index.ItemIndex) SitemapOrchestrator {
	return SitemapOrchestrator{
		itemIndex: itemIndex,
	}
}

type SitemapOrchestrator struct {
	itemIndex *index.ItemIndex
}

func (orchestrator *SitemapOrchestrator) GetSitemap(pathProvider paths.Pather) viewmodel.Sitemap {

	rootItem := orchestrator.itemIndex.Root()
	if rootItem == nil {
		panic("J")
	}

	rootModel := viewmodel.Sitemap{
		Title:       rootItem.Title,
		Description: rootItem.Description,
		Childs:      getSitemapEntries(orchestrator.itemIndex, *rootItem.Route()),
	}

	return rootModel
}

func getSitemapEntries(index *index.ItemIndex, startRoute route.Route) []viewmodel.Sitemap {

	childs := make([]viewmodel.Sitemap, 0)
	for _, child := range index.GetChilds(&startRoute) {

		fmt.Println(child)

		childRoute := child.Route()

		childModel := viewmodel.Sitemap{
			Title:       child.Title,
			Description: child.Description,
			Childs:      getSitemapEntries(index, *childRoute),
		}

		childs = append(childs, childModel)
	}

	return childs
}
<commit_msg>Removed debug code<commit_after>// Copyright 2013 Andreas Koch. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package orchestrator

import (
	"github.com/andreaskoch/allmark2/common/index"
	"github.com/andreaskoch/allmark2/common/paths"
	"github.com/andreaskoch/allmark2/common/route"
	"github.com/andreaskoch/allmark2/ui/web/view/viewmodel"
)

func NewSitemapOrchestrator(itemIndex *index.ItemIndex) SitemapOrchestrator {
	return SitemapOrchestrator{
		itemIndex: itemIndex,
	}
}

type SitemapOrchestrator struct {
	itemIndex *index.ItemIndex
}

func (orchestrator *SitemapOrchestrator) GetSitemap(pathProvider paths.Pather) viewmodel.Sitemap {

	rootItem := orchestrator.itemIndex.Root()
	if rootItem == nil {
		panic("No root item found")
	}

	rootModel := viewmodel.Sitemap{
		Title:       rootItem.Title,
		Description: rootItem.Description,
		Childs:      getSitemapEntries(orchestrator.itemIndex, *rootItem.Route()),
	}

	return rootModel
}

func getSitemapEntries(index *index.ItemIndex, startRoute route.Route) []viewmodel.Sitemap {

	childs := make([]viewmodel.Sitemap, 0)
	for _, child := range index.GetChilds(&startRoute) {

		childRoute := child.Route()

		childModel := viewmodel.Sitemap{
			Title:       child.Title,
			Description: child.Description,
			Childs:      getSitemapEntries(index, *childRoute),
		}

		childs = append(childs, childModel)
	}

	return childs
}
<|endoftext|>


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

// Package db encapsulates tsuru connection with MongoDB.
//
// The function Open dials to MongoDB and returns a connection (represented by
// the Storage type). It manages an internal pool of connections, and
// reconnects in case of failures. That means that you should not store
// references to the connection, but always call Open.
package db

import (
	"fmt"
	"github.com/globocom/config"
	"labix.org/v2/mgo"
	"sync"
	"time"
)

var (
	conn        = make(map[string]*session) // pool of connections
	mut         sync.RWMutex                // for pool thread safety
	ticker      *time.Ticker                // for garbage collection
	maxIdleTime = 5 * time.Minute           // max idle time for connections
)

const period time.Duration = 7 * 24 * time.Hour

type session struct {
	s    *mgo.Session
	used time.Time
}

// Storage holds the connection with the database.
type Storage struct {
	session *mgo.Session
	dbname  string
}

func open(addr, dbname string) (*Storage, error) {
	sess, err := mgo.DialWithTimeout(addr, 1e9)
	if err != nil {
		return nil, err
	}
	copy := sess.Copy()
	go func(t time.Duration) {
		time.Sleep(t)
		copy.Close()
	}(maxIdleTime)
	storage := &Storage{session: copy, dbname: dbname}
	mut.Lock()
	conn[addr] = &session{s: sess, used: time.Now()}
	mut.Unlock()
	return storage, nil
}

// Open dials to the MongoDB database, and return the connection (represented
// by the type Storage).
//
// addr is a MongoDB connection URI, and dbname is the name of the database.
//
// This function returns a pointer to a Storage, or a non-nil error in case of
// any failure.
func Open(addr, dbname string) (storage *Storage, err error) {
	defer func() {
		if r := recover(); r != nil {
			storage, err = open(addr, dbname)
		}
	}()
	mut.RLock()
	if session, ok := conn[addr]; ok {
		mut.RUnlock()
		if err = session.s.Ping(); err == nil {
			mut.Lock()
			session.used = time.Now()
			conn[addr] = session
			mut.Unlock()
			copy := session.s.Copy()
			go func() {
				time.Sleep(maxIdleTime)
				copy.Close()
			}()
			return &Storage{copy, dbname}, nil
		}
		return open(addr, dbname)
	}
	mut.RUnlock()
	return open(addr, dbname)
}

// Conn reads the tsuru config and calls Open to get a database connection.
//
// Most tsuru packages should probably use this function. Open is intended for
// use when supporting more than one database.
func Conn() (*Storage, error) {
	url, err := config.GetString("database:url")
	if err != nil {
		return nil, fmt.Errorf("configuration error: %s", err)
	}
	dbname, err := config.GetString("database:name")
	if err != nil {
		return nil, fmt.Errorf("configuration error: %s", err)
	}
	return Open(url, dbname)
}

// Close closes the storage, releasing the connection.
func (s *Storage) Close() {
	s.session.Close()
}

// Collection returns a collection by its name.
//
// If the collection does not exist, MongoDB will create it.
func (s *Storage) Collection(name string) *mgo.Collection {
	return s.session.DB(s.dbname).C(name)
}

// Apps returns the apps collection from MongoDB.
func (s *Storage) Apps() *mgo.Collection {
	nameIndex := mgo.Index{Key: []string{"name"}, Unique: true}
	c := s.Collection("apps")
	c.EnsureIndex(nameIndex)
	return c
}

// Platforms returns the platforms collection from MongoDB.
func (s *Storage) Platforms() *mgo.Collection {
	return s.Collection("platforms")
}

// Logs returns the logs collection from MongoDB.
func (s *Storage) Logs() *mgo.Collection {
	return s.Collection("logs")
}

// Services returns the services collection from MongoDB.
func (s *Storage) Services() *mgo.Collection {
	c := s.Collection("services")
	return c
}

// ServiceInstances returns the services_instances collection from MongoDB.
func (s *Storage) ServiceInstances() *mgo.Collection {
	return s.Collection("service_instances")
}

// Users returns the users collection from MongoDB.
func (s *Storage) Users() *mgo.Collection {
	emailIndex := mgo.Index{Key: []string{"email"}, Unique: true}
	c := s.Collection("users")
	c.EnsureIndex(emailIndex)
	return c
}

func (s *Storage) Tokens() *mgo.Collection {
	return s.Collection("tokens")
}

func (s *Storage) PasswordTokens() *mgo.Collection {
	return s.Collection("password_tokens")
}

func (s *Storage) UserActions() *mgo.Collection {
	return s.Collection("user_actions")
}

// Teams returns the teams collection from MongoDB.
func (s *Storage) Teams() *mgo.Collection {
	return s.Collection("teams")
}

// Quota returns the quota collection from MongoDB.
func (s *Storage) Quota() *mgo.Collection {
	userIndex := mgo.Index{Key: []string{"user"}, Unique: true}
	c := s.Collection("quota")
	c.EnsureIndex(userIndex)
	return c
}

func init() {
	ticker = time.NewTicker(time.Hour)
	go retire(ticker)
}

// retire retires old connections :-)
func retire(t *time.Ticker) {
	for _ = range t.C {
		now := time.Now()
		var old []string
		mut.RLock()
		for k, v := range conn {
			if now.Sub(v.used) >= period {
				old = append(old, k)
			}
		}
		mut.RUnlock()
		mut.Lock()
		for _, c := range old {
			conn[c].s.Close()
			delete(conn, c)
		}
		mut.Unlock()
	}
}
<commit_msg>db: remove emoticon from retire documentation<commit_after>// Copyright 2013 tsuru authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// Package db encapsulates tsuru connection with MongoDB.
//
// The function Open dials to MongoDB and returns a connection (represented by
// the Storage type). It manages an internal pool of connections, and
// reconnects in case of failures. That means that you should not store
// references to the connection, but always call Open.
package db

import (
	"fmt"
	"github.com/globocom/config"
	"labix.org/v2/mgo"
	"sync"
	"time"
)

var (
	conn        = make(map[string]*session) // pool of connections
	mut         sync.RWMutex                // for pool thread safety
	ticker      *time.Ticker                // for garbage collection
	maxIdleTime = 5 * time.Minute           // max idle time for connections
)

const period time.Duration = 7 * 24 * time.Hour

type session struct {
	s    *mgo.Session
	used time.Time
}

// Storage holds the connection with the database.
type Storage struct {
	session *mgo.Session
	dbname  string
}

func open(addr, dbname string) (*Storage, error) {
	sess, err := mgo.DialWithTimeout(addr, 1e9)
	if err != nil {
		return nil, err
	}
	copy := sess.Copy()
	go func(t time.Duration) {
		time.Sleep(t)
		copy.Close()
	}(maxIdleTime)
	storage := &Storage{session: copy, dbname: dbname}
	mut.Lock()
	conn[addr] = &session{s: sess, used: time.Now()}
	mut.Unlock()
	return storage, nil
}

// Open dials to the MongoDB database, and return the connection (represented
// by the type Storage).
//
// addr is a MongoDB connection URI, and dbname is the name of the database.
//
// This function returns a pointer to a Storage, or a non-nil error in case of
// any failure.
func Open(addr, dbname string) (storage *Storage, err error) {
	defer func() {
		if r := recover(); r != nil {
			storage, err = open(addr, dbname)
		}
	}()
	mut.RLock()
	if session, ok := conn[addr]; ok {
		mut.RUnlock()
		if err = session.s.Ping(); err == nil {
			mut.Lock()
			session.used = time.Now()
			conn[addr] = session
			mut.Unlock()
			copy := session.s.Copy()
			go func() {
				time.Sleep(maxIdleTime)
				copy.Close()
			}()
			return &Storage{copy, dbname}, nil
		}
		return open(addr, dbname)
	}
	mut.RUnlock()
	return open(addr, dbname)
}

// Conn reads the tsuru config and calls Open to get a database connection.
//
// Most tsuru packages should probably use this function. Open is intended for
// use when supporting more than one database.
func Conn() (*Storage, error) {
	url, err := config.GetString("database:url")
	if err != nil {
		return nil, fmt.Errorf("configuration error: %s", err)
	}
	dbname, err := config.GetString("database:name")
	if err != nil {
		return nil, fmt.Errorf("configuration error: %s", err)
	}
	return Open(url, dbname)
}

// Close closes the storage, releasing the connection.
func (s *Storage) Close() {
	s.session.Close()
}

// Collection returns a collection by its name.
//
// If the collection does not exist, MongoDB will create it.
func (s *Storage) Collection(name string) *mgo.Collection {
	return s.session.DB(s.dbname).C(name)
}

// Apps returns the apps collection from MongoDB.
func (s *Storage) Apps() *mgo.Collection {
	nameIndex := mgo.Index{Key: []string{"name"}, Unique: true}
	c := s.Collection("apps")
	c.EnsureIndex(nameIndex)
	return c
}

// Platforms returns the platforms collection from MongoDB.
func (s *Storage) Platforms() *mgo.Collection {
	return s.Collection("platforms")
}

// Logs returns the logs collection from MongoDB.
func (s *Storage) Logs() *mgo.Collection {
	return s.Collection("logs")
}

// Services returns the services collection from MongoDB.
func (s *Storage) Services() *mgo.Collection {
	c := s.Collection("services")
	return c
}

// ServiceInstances returns the services_instances collection from MongoDB.
func (s *Storage) ServiceInstances() *mgo.Collection {
	return s.Collection("service_instances")
}

// Users returns the users collection from MongoDB.
func (s *Storage) Users() *mgo.Collection {
	emailIndex := mgo.Index{Key: []string{"email"}, Unique: true}
	c := s.Collection("users")
	c.EnsureIndex(emailIndex)
	return c
}

func (s *Storage) Tokens() *mgo.Collection {
	return s.Collection("tokens")
}

func (s *Storage) PasswordTokens() *mgo.Collection {
	return s.Collection("password_tokens")
}

func (s *Storage) UserActions() *mgo.Collection {
	return s.Collection("user_actions")
}

// Teams returns the teams collection from MongoDB.
func (s *Storage) Teams() *mgo.Collection {
	return s.Collection("teams")
}

// Quota returns the quota collection from MongoDB.
func (s *Storage) Quota() *mgo.Collection {
	userIndex := mgo.Index{Key: []string{"user"}, Unique: true}
	c := s.Collection("quota")
	c.EnsureIndex(userIndex)
	return c
}

func init() {
	ticker = time.NewTicker(time.Hour)
	go retire(ticker)
}

// retire retires old connections
func retire(t *time.Ticker) {
	for _ = range t.C {
		now := time.Now()
		var old []string
		mut.RLock()
		for k, v := range conn {
			if now.Sub(v.used) >= period {
				old = append(old, k)
			}
		}
		mut.RUnlock()
		mut.Lock()
		for _, c := range old {
			conn[c].s.Close()
			delete(conn, c)
		}
		mut.Unlock()
	}
}
<|endoftext|>


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

package assert

import "reflect"

// OnSlice is the result of calling ThatSlice on an Assertion.
// It provides assertion tests that are specific to slice types.
type OnSlice struct {
	Assertion
	slice interface{}
}

// ThatSlice returns an OnSlice for assertions on slice type objects.
// Calling this with a non slice type will result in panics.
func (a Assertion) ThatSlice(slice interface{}) OnSlice {
	return OnSlice{Assertion: a, slice: slice}
}

// IsEmpty asserts that the slice was of length 0
func (o OnSlice) IsEmpty() bool {
	value := reflect.ValueOf(o.slice)
	return o.CompareRaw(value.Len(), "is", "empty").Test(value.Len() == 0)
}

// IsNotEmpty asserts that the slice has elements
func (o OnSlice) IsNotEmpty() bool {
	value := reflect.ValueOf(o.slice)
	return o.Compare(value.Len(), "length >", 0).Test(value.Len() > 0)
}

// IsLength asserts that the slice has exactly the specified number of elements
func (o OnSlice) IsLength(length int) bool {
	value := reflect.ValueOf(o.slice)
	return o.Compare(value.Len(), "length ==", length).Test(value.Len() == length)
}

// Equals asserts the array or slice matches expected.
func (o OnSlice) Equals(expected interface{}) bool {
	return o.slicesEqual(expected, func(a, b interface{}) bool { return a == b })
}

// EqualsWithComparator asserts the array or slice matches expected using a comparator function
func (o OnSlice) EqualsWithComparator(expected interface{}, same func(a, b interface{}) bool) bool {
	return o.slicesEqual(expected, same)
}

// DeepEquals asserts the array or slice matches expected using a deep-equal comparison.
func (o OnSlice) DeepEquals(expected interface{}) bool {
	return o.slicesEqual(expected, reflect.DeepEqual)
}

func (o OnSlice) slicesEqual(expected interface{}, same func(a, b interface{}) bool) bool {
	return o.Test(func() bool {
		gs := reflect.ValueOf(o.slice)
		glen := gs.Len()
		es := reflect.ValueOf(expected)
		elen := es.Len()
		max := glen
		if max < elen {
			max = elen
		}
		equal := true
		for i := 0; i < max; i++ {
			switch {
			case i >= glen:
				// expected but not present
				ev := es.Index(i)
				o.Printf("-\t%d\t\t", i)
				o.Printf("\t==>\t%T\t", ev.Interface())
				o.Println(ev.Interface())
				equal = false
			case i >= elen:
				// present but not expected
				gv := gs.Index(i)
				o.Printf("+\t%d\t%T\t", i, gv.Interface())
				o.Print(gv.Interface())
				o.Rawln("\t;")
				equal = false
			default:
				// in both
				ev := es.Index(i)
				gv := gs.Index(i)
				if same(gv.Interface(), ev.Interface()) {
					o.Printf("\t%d\t%T\t", i, gv.Interface())
					o.Print(gv.Interface())
					o.Rawln("\t;")
				} else {
					ev := es.Index(i)
					o.Printf("*\t%d\t%T\t", i, gv.Interface())
					o.Print(gv.Interface())
					o.Printf("\t==>\t%T\t", ev.Interface())
					o.Println(ev.Interface())
					equal = false
				}
			}
		}
		return equal
	}())
}
<commit_msg>Use compare.DeepEqual for slices, instead of reflect.DeepEqual.<commit_after>// Copyright (C) 2017 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package assert

import (
	"reflect"

	"github.com/google/gapid/core/data/compare"
)

// OnSlice is the result of calling ThatSlice on an Assertion.
// It provides assertion tests that are specific to slice types.
type OnSlice struct {
	Assertion
	slice interface{}
}

// ThatSlice returns an OnSlice for assertions on slice type objects.
// Calling this with a non slice type will result in panics.
func (a Assertion) ThatSlice(slice interface{}) OnSlice {
	return OnSlice{Assertion: a, slice: slice}
}

// IsEmpty asserts that the slice was of length 0
func (o OnSlice) IsEmpty() bool {
	value := reflect.ValueOf(o.slice)
	return o.CompareRaw(value.Len(), "is", "empty").Test(value.Len() == 0)
}

// IsNotEmpty asserts that the slice has elements
func (o OnSlice) IsNotEmpty() bool {
	value := reflect.ValueOf(o.slice)
	return o.Compare(value.Len(), "length >", 0).Test(value.Len() > 0)
}

// IsLength asserts that the slice has exactly the specified number of elements
func (o OnSlice) IsLength(length int) bool {
	value := reflect.ValueOf(o.slice)
	return o.Compare(value.Len(), "length ==", length).Test(value.Len() == length)
}

// Equals asserts the array or slice matches expected.
func (o OnSlice) Equals(expected interface{}) bool {
	return o.slicesEqual(expected, func(a, b interface{}) bool { return a == b })
}

// EqualsWithComparator asserts the array or slice matches expected using a comparator function
func (o OnSlice) EqualsWithComparator(expected interface{}, same func(a, b interface{}) bool) bool {
	return o.slicesEqual(expected, same)
}

// DeepEquals asserts the array or slice matches expected using a deep-equal comparison.
func (o OnSlice) DeepEquals(expected interface{}) bool {
	return o.slicesEqual(expected, compare.DeepEqual)
}

func (o OnSlice) slicesEqual(expected interface{}, same func(a, b interface{}) bool) bool {
	return o.Test(func() bool {
		gs := reflect.ValueOf(o.slice)
		glen := gs.Len()
		es := reflect.ValueOf(expected)
		elen := es.Len()
		max := glen
		if max < elen {
			max = elen
		}
		equal := true
		for i := 0; i < max; i++ {
			switch {
			case i >= glen:
				// expected but not present
				ev := es.Index(i)
				o.Printf("-\t%d\t\t", i)
				o.Printf("\t==>\t%T\t", ev.Interface())
				o.Println(ev.Interface())
				equal = false
			case i >= elen:
				// present but not expected
				gv := gs.Index(i)
				o.Printf("+\t%d\t%T\t", i, gv.Interface())
				o.Print(gv.Interface())
				o.Rawln("\t;")
				equal = false
			default:
				// in both
				ev := es.Index(i)
				gv := gs.Index(i)
				if same(gv.Interface(), ev.Interface()) {
					o.Printf("\t%d\t%T\t", i, gv.Interface())
					o.Print(gv.Interface())
					o.Rawln("\t;")
				} else {
					ev := es.Index(i)
					o.Printf("*\t%d\t%T\t", i, gv.Interface())
					o.Print(gv.Interface())
					o.Printf("\t==>\t%T\t", ev.Interface())
					o.Println(ev.Interface())
					equal = false
				}
			}
		}
		return equal
	}())
}
<|endoftext|>


<commit_before>/**
 *  Copyright 2014 Paul Querna
 *
 *  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 ffjsoninception

import (
	"bytes"
	"encoding/json"
	fflib "github.com/pquerna/ffjson/fflib/v1"
	"github.com/pquerna/ffjson/scanner"
	"reflect"
	"sort"
)

type StructField struct {
	Name             string
	JsonName         string
	Typ              reflect.Type
	OmitEmpty        bool
	ForceString      bool
	HasMarshalJSON   bool
	HasUnmarshalJSON bool
	Pointer          bool
}

type FieldByJsonName []*StructField

func (a FieldByJsonName) Len() int           { return len(a) }
func (a FieldByJsonName) Swap(i, j int)      { a[i], a[j] = a[j], a[i] }
func (a FieldByJsonName) Less(i, j int) bool { return a[i].JsonName < a[j].JsonName }

type StructInfo struct {
	Name   string
	Obj    interface{}
	Typ    reflect.Type
	Fields []*StructField
}

func NewStructInfo(obj interface{}) *StructInfo {
	t := reflect.TypeOf(obj)
	return &StructInfo{
		Obj:    obj,
		Name:   t.Name(),
		Typ:    t,
		Fields: extractFields(obj),
	}
}

type MarshalerBuf interface {
	MarshalJSONBuf(buf *bytes.Buffer) error
}

type UnmarshalFaster interface {
	UnmarshalJSONFFLexer(l *scanner.FFLexer, state scanner.FFParseState) error
}

var marshalerType = reflect.TypeOf(new(json.Marshaler)).Elem()
var marshalerBufType = reflect.TypeOf(new(MarshalerBuf)).Elem()
var unmarshalerType = reflect.TypeOf(new(json.Unmarshaler)).Elem()
var unmarshalFasterType = reflect.TypeOf(new(UnmarshalFaster)).Elem()

/*
func extractFields(obj interface{}) []*StructField {
	rv := make([]*StructField, 0)
	typ := reflect.TypeOf(obj)
	for i := 0; i < typ.NumField(); i++ {
		sf := typ.Field(i)
		ft := sf.Type

		// based on checks in encoding/json/encode.go, we don't export everything.
		if sf.PkgPath != "" { // unexported
			continue
		}

		jsonName := f.Name
		omitEmpty := false
		forceString := false

		tag := sf.Tag.Get("json")

		if tag != "" {
			tagName, opts := parseTag(tag)
			if tagName != "" {
				jsonName = tagName
			}
			omitEmpty = opts.Contains("omitempty")
			forceString = opts.Contains("string")
		}

		if jsonName == "-" {
			continue
		}

		if ft.Name() == "" && ft.Kind() == reflect.Ptr {
			ft = ft.Elem()
		}

		if jsonName != "" || !sf.Anonymous || ft.Kind() != reflect.Struct {
			var buf bytes.Buffer
			fflib.WriteJsonString(&buf, jsonName)

			sf := &StructField{
				Name:             sf.Name,
				JsonName:         string(buf.Bytes()),
				Typ:              ft,
				HasMarshalJSON:   ft.Implements(marshalerType),
				HasUnmarshalJSON: ft.Implements(unmarshalerType),
				OmitEmpty:        omitEmpty,
				ForceString:      forceString,
			}
		}

		rv = append(rv, sf)
	}

	sort.Sort(FieldByJsonName(rv))

	return rv
}

*/

// typeFields returns a list of fields that JSON should recognize for the given type.
// The algorithm is breadth-first search over the set of structs to include - the top struct
// and then any reachable anonymous structs.
func extractFields(obj interface{}) []*StructField {
	t := reflect.TypeOf(obj)
	// Anonymous fields to explore at the current level and the next.
	current := []StructField{}
	next := []StructField{{Typ: t}}

	// Count of queued names for current level and the next.
	count := map[reflect.Type]int{}
	nextCount := map[reflect.Type]int{}

	// Types already visited at an earlier level.
	visited := map[reflect.Type]bool{}

	// Fields found.
	var fields []*StructField

	for len(next) > 0 {
		current, next = next, current[:0]
		count, nextCount = nextCount, map[reflect.Type]int{}

		for _, f := range current {
			if visited[f.Typ] {
				continue
			}
			visited[f.Typ] = true

			// Scan f.typ for fields to include.
			for i := 0; i < f.Typ.NumField(); i++ {
				sf := f.Typ.Field(i)
				if sf.PkgPath != "" { // unexported
					continue
				}
				tag := sf.Tag.Get("json")
				if tag == "-" {
					continue
				}
				name, opts := parseTag(tag)
				if !isValidTag(name) {
					name = ""
				}

				ft := sf.Type
				ptr := false
				if ft.Kind() == reflect.Ptr {
					ptr = true
				}

				if ft.Name() == "" && ft.Kind() == reflect.Ptr {
					// Follow pointer.
					ft = ft.Elem()
				}

				// Record found field and index sequence.
				if name != "" || !sf.Anonymous || ft.Kind() != reflect.Struct {
					if name == "" {
						name = sf.Name
					}

					var buf bytes.Buffer
					fflib.WriteJsonString(&buf, name)

					field := &StructField{
						Name:             sf.Name,
						JsonName:         string(buf.Bytes()),
						Typ:              ft,
						HasMarshalJSON:   ft.Implements(marshalerType),
						HasUnmarshalJSON: ft.Implements(unmarshalerType),
						OmitEmpty:        opts.Contains("omitempty"),
						ForceString:      opts.Contains("string"),
						Pointer:          ptr,
					}

					fields = append(fields, field)

					if count[f.Typ] > 1 {
						// If there were multiple instances, add a second,
						// so that the annihilation code will see a duplicate.
						// It only cares about the distinction between 1 or 2,
						// so don't bother generating any more copies.
						fields = append(fields, fields[len(fields)-1])
					}
					continue
				}

				// Record new anonymous struct to explore in next round.
				nextCount[ft]++
				if nextCount[ft] == 1 {
					next = append(next, StructField{
						Name: ft.Name(),
						Typ:  ft,
					})
				}
			}
		}
	}

	sort.Sort(FieldByJsonName(fields))
	/*
		// Delete all fields that are hidden by the Go rules for embedded fields,
		// except that fields with JSON tags are promoted.

		// The fields are sorted in primary order of name, secondary order
		// of field index length. Loop over names; for each name, delete
		// hidden fields by choosing the one dominant field that survives.
		out := fields[:0]
		for advance, i := 0, 0; i < len(fields); i += advance {
			// One iteration per name.
			// Find the sequence of fields with the name of this first field.
			fi := fields[i]
			name := fi.name
			for advance = 1; i+advance < len(fields); advance++ {
				fj := fields[i+advance]
				if fj.name != name {
					break
				}
			}
			if advance == 1 { // Only one field with this name
				out = append(out, fi)
				continue
			}
			dominant, ok := dominantField(fields[i : i+advance])
			if ok {
				out = append(out, dominant)
			}
		}

		fields = out
		sort.Sort(byIndex(fields))

		return fields
	*/
	return fields
}
<commit_msg>cleanup extractfields<commit_after>/**
 *  Copyright 2014 Paul Querna
 *
 *  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 ffjsoninception

import (
	"bytes"
	"encoding/json"
	fflib "github.com/pquerna/ffjson/fflib/v1"
	"github.com/pquerna/ffjson/scanner"
	"reflect"
	"sort"
)

type StructField struct {
	Name             string
	JsonName         string
	Typ              reflect.Type
	OmitEmpty        bool
	ForceString      bool
	HasMarshalJSON   bool
	HasUnmarshalJSON bool
	Pointer          bool
	Tagged           bool
}

type FieldByJsonName []*StructField

func (a FieldByJsonName) Len() int           { return len(a) }
func (a FieldByJsonName) Swap(i, j int)      { a[i], a[j] = a[j], a[i] }
func (a FieldByJsonName) Less(i, j int) bool { return a[i].JsonName < a[j].JsonName }

type StructInfo struct {
	Name   string
	Obj    interface{}
	Typ    reflect.Type
	Fields []*StructField
}

func NewStructInfo(obj interface{}) *StructInfo {
	t := reflect.TypeOf(obj)
	return &StructInfo{
		Obj:    obj,
		Name:   t.Name(),
		Typ:    t,
		Fields: extractFields(obj),
	}
}

type MarshalerBuf interface {
	MarshalJSONBuf(buf *bytes.Buffer) error
}

type UnmarshalFaster interface {
	UnmarshalJSONFFLexer(l *scanner.FFLexer, state scanner.FFParseState) error
}

var marshalerType = reflect.TypeOf(new(json.Marshaler)).Elem()
var marshalerBufType = reflect.TypeOf(new(MarshalerBuf)).Elem()
var unmarshalerType = reflect.TypeOf(new(json.Unmarshaler)).Elem()
var unmarshalFasterType = reflect.TypeOf(new(UnmarshalFaster)).Elem()

// extractFields returns a list of fields that JSON should recognize for the given type.
// The algorithm is breadth-first search over the set of structs to include - the top struct
// and then any reachable anonymous structs.
func extractFields(obj interface{}) []*StructField {
	t := reflect.TypeOf(obj)
	// Anonymous fields to explore at the current level and the next.
	current := []StructField{}
	next := []StructField{{Typ: t}}

	// Count of queued names for current level and the next.
	count := map[reflect.Type]int{}
	nextCount := map[reflect.Type]int{}

	// Types already visited at an earlier level.
	visited := map[reflect.Type]bool{}

	// Fields found.
	var fields []*StructField

	for len(next) > 0 {
		current, next = next, current[:0]
		count, nextCount = nextCount, map[reflect.Type]int{}

		for _, f := range current {
			if visited[f.Typ] {
				continue
			}
			visited[f.Typ] = true

			// Scan f.typ for fields to include.
			for i := 0; i < f.Typ.NumField(); i++ {
				sf := f.Typ.Field(i)
				if sf.PkgPath != "" { // unexported
					continue
				}
				tag := sf.Tag.Get("json")
				if tag == "-" {
					continue
				}
				name, opts := parseTag(tag)
				if !isValidTag(name) {
					name = ""
				}

				ft := sf.Type
				ptr := false
				if ft.Kind() == reflect.Ptr {
					ptr = true
				}

				if ft.Name() == "" && ft.Kind() == reflect.Ptr {
					// Follow pointer.
					ft = ft.Elem()
				}

				// Record found field and index sequence.
				if name != "" || !sf.Anonymous || ft.Kind() != reflect.Struct {
					tagged := name != ""
					if name == "" {
						name = sf.Name
					}

					var buf bytes.Buffer
					fflib.WriteJsonString(&buf, name)

					field := &StructField{
						Name:             sf.Name,
						JsonName:         string(buf.Bytes()),
						Typ:              ft,
						HasMarshalJSON:   ft.Implements(marshalerType),
						HasUnmarshalJSON: ft.Implements(unmarshalerType),
						OmitEmpty:        opts.Contains("omitempty"),
						ForceString:      opts.Contains("string"),
						Pointer:          ptr,
						Tagged:           tagged,
					}

					fields = append(fields, field)

					if count[f.Typ] > 1 {
						// If there were multiple instances, add a second,
						// so that the annihilation code will see a duplicate.
						// It only cares about the distinction between 1 or 2,
						// so don't bother generating any more copies.
						fields = append(fields, fields[len(fields)-1])
					}
					continue
				}

				// Record new anonymous struct to explore in next round.
				nextCount[ft]++
				if nextCount[ft] == 1 {
					next = append(next, StructField{
						Name: ft.Name(),
						Typ:  ft,
					})
				}
			}
		}
	}

	sort.Sort(FieldByJsonName(fields))

	// Delete all fields that are hidden by the Go rules for embedded fields,
	// except that fields with JSON tags are promoted.

	// The fields are sorted in primary order of name, secondary order
	// of field index length. Loop over names; for each name, delete
	// hidden fields by choosing the one dominant field that survives.
	out := fields[:0]
	for advance, i := 0, 0; i < len(fields); i += advance {
		// One iteration per name.
		// Find the sequence of fields with the name of this first field.
		fi := fields[i]
		name := fi.JsonName
		for advance = 1; i+advance < len(fields); advance++ {
			fj := fields[i+advance]
			if fj.JsonName != name {
				break
			}
		}
		if advance == 1 { // Only one field with this name
			out = append(out, fi)
			continue
		}
		dominant, ok := dominantField(fields[i : i+advance])
		if ok {
			out = append(out, dominant)
		}
	}

	fields = out

	return fields
}

// dominantField looks through the fields, all of which are known to
// have the same name, to find the single field that dominates the
// others using Go's embedding rules, modified by the presence of
// JSON tags. If there are multiple top-level fields, the boolean
// will be false: This condition is an error in Go and we skip all
// the fields.
func dominantField(fields []*StructField) (*StructField, bool) {
	tagged := -1 // Index of first tagged field.
	for i, f := range fields {
		if f.Tagged {
			if tagged >= 0 {
				// Multiple tagged fields at the same level: conflict.
				// Return no field.
				return nil, false
			}
			tagged = i
		}
	}
	if tagged >= 0 {
		return fields[tagged], true
	}
	// All remaining fields have the same length. If there's more than one,
	// we have a conflict (two fields named "X" at the same level) and we
	// return no field.
	if len(fields) > 1 {
		return nil, false
	}
	return fields[0], true
}
<|endoftext|>