<commit_before>/*
	rulehuntersrv - A server to find rules in data based on user specified goals
	Copyright (C) 2016 vLife Systems Ltd <http://vlifesystems.com>

	This program is free software: you can redistribute it and/or modify
	it under the terms of the GNU Affero General Public License as published by
	the Free Software Foundation, either version 3 of the License, or
	(at your option) any later version.

	This program is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	GNU Affero General Public License for more details.

	You should have received a copy of the GNU Affero General Public License
	along with this program; see the file COPYING.  If not, see
	<http://www.gnu.org/licenses/>.
*/
package main

import (
	"flag"
	"fmt"
	"github.com/kardianos/service"
	"github.com/vlifesystems/rulehuntersrv/config"
	"github.com/vlifesystems/rulehuntersrv/experiment"
	"github.com/vlifesystems/rulehuntersrv/html"
	"github.com/vlifesystems/rulehuntersrv/html/cmd"
	"github.com/vlifesystems/rulehuntersrv/progress"
	"io/ioutil"
	"log"
	"os"
	"path/filepath"
	"time"
)

var logger service.Logger

type program struct {
	configDir       string
	config          *config.Config
	progressMonitor *progress.ProgressMonitor
}

func (p *program) Start(s service.Service) error {
	go p.run()
	return nil
}

func (p *program) run() {
	sleepInSeconds := time.Duration(2)
	logWaitingForExperiments := true

	for {
		if logWaitingForExperiments {
			logWaitingForExperiments = false
			logger.Infof("Waiting for experiments to process")
		}
		experimentFilenames, err := p.getExperimentFilenames()
		if err != nil {
			logger.Error(err)
		}
		for _, experimentFilename := range experimentFilenames {
			err := p.progressMonitor.AddExperiment(experimentFilename)
			if err != nil {
				logger.Error(err)
			}
		}

		for _, experimentFilename := range experimentFilenames {
			logWaitingForExperiments = true
			logger.Infof("Processing experiment: %s", experimentFilename)

			err := experiment.Process(
				experimentFilename,
				p.config,
				p.progressMonitor,
			)
			if err != nil {
				logger.Errorf("Failed processing experiment: %s - %s",
					experimentFilename, err)
				err := p.moveExperimentToFail(experimentFilename)
				if err != nil {
					fullErr := fmt.Errorf("%s (Couldn't move experiment file: %s)", err)
					logger.Error(fullErr)
				}
			} else {
				err := p.moveExperimentToSuccess(experimentFilename)
				if err != nil {
					fullErr := fmt.Errorf("Couldn't move experiment file: %s", err)
					logger.Error(fullErr)
				} else {
					logger.Infof("Successfully processed experiment: %s",
						experimentFilename)
				}
			}
		}

		// Sleeping prevents 'excessive' cpu use and disk access
		time.Sleep(sleepInSeconds * time.Second)
	}
}

func (p *program) getExperimentFilenames() ([]string, error) {
	experimentFilenames := make([]string, 0)
	files, err := ioutil.ReadDir(p.config.ExperimentsDir)
	if err != nil {
		return experimentFilenames, err
	}

	for _, file := range files {
		if !file.IsDir() {
			experimentFilenames = append(experimentFilenames, file.Name())
		}
	}
	return experimentFilenames, nil
}

func (p *program) moveExperimentToSuccess(experimentFilename string) error {
	experimentFullFilename :=
		filepath.Join(p.config.ExperimentsDir, experimentFilename)
	experimentSuccessFullFilename :=
		filepath.Join(p.config.ExperimentsDir, "success", experimentFilename)
	return os.Rename(experimentFullFilename, experimentSuccessFullFilename)
}

func (p *program) moveExperimentToFail(experimentFilename string) error {
	experimentFullFilename :=
		filepath.Join(p.config.ExperimentsDir, experimentFilename)
	experimentFailFullFilename :=
		filepath.Join(p.config.ExperimentsDir, "fail", experimentFilename)
	return os.Rename(experimentFullFilename, experimentFailFullFilename)
}

func (p *program) Stop(s service.Service) error {
	return nil
}

func main() {
	svcConfig := &service.Config{
		Name:        "GoTestService",
		DisplayName: "Go Test Service",
		Description: "A test Go service.",
	}
	prg := &program{}

	userPtr := flag.String("user", "", "The user to run the server as")
	configDirPtr := flag.String("configdir", "", "The configuration directory")
	installPtr := flag.Bool("install", false, "Install the server as a service")
	flag.Parse()

	if *userPtr != "" {
		svcConfig.UserName = *userPtr
	}

	if *configDirPtr != "" {
		svcConfig.Arguments = []string{fmt.Sprintf("-configdir=%s", *configDirPtr)}
		prg.configDir = *configDirPtr
	}

	configFilename := filepath.Join(prg.configDir, "config.json")
	config, err := config.Load(configFilename)
	if err != nil {
		log.Fatal(fmt.Sprintf("Couldn't load configuration %s: %s",
			configFilename, err))
	}
	prg.config = config

	htmlCmds := make(chan cmd.Cmd)
	prg.progressMonitor =
		progress.NewMonitor(filepath.Join(config.BuildDir, "progress"), htmlCmds)

	s, err := service.New(prg, svcConfig)
	if err != nil {
		log.Fatal(err)
	}
	logger, err = s.Logger(nil)
	if err != nil {
		log.Fatal(err)
	}

	go html.Run(config, prg.progressMonitor, logger, htmlCmds)
	htmlCmds <- cmd.All

	if *installPtr {
		if *configDirPtr == "" {
			log.Fatal("No -configdir argument")
		}
		err = s.Install()
		if err != nil {
			log.Fatal(err)
		}
	} else {
		err = s.Run()
		if err != nil {
			logger.Error(err)
		}
	}
}
<commit_msg>Amalgamate success/ and fail/ to processed/<commit_after>/*
	rulehuntersrv - A server to find rules in data based on user specified goals
	Copyright (C) 2016 vLife Systems Ltd <http://vlifesystems.com>

	This program is free software: you can redistribute it and/or modify
	it under the terms of the GNU Affero General Public License as published by
	the Free Software Foundation, either version 3 of the License, or
	(at your option) any later version.

	This program is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	GNU Affero General Public License for more details.

	You should have received a copy of the GNU Affero General Public License
	along with this program; see the file COPYING.  If not, see
	<http://www.gnu.org/licenses/>.
*/
package main

import (
	"flag"
	"fmt"
	"github.com/kardianos/service"
	"github.com/vlifesystems/rulehuntersrv/config"
	"github.com/vlifesystems/rulehuntersrv/experiment"
	"github.com/vlifesystems/rulehuntersrv/html"
	"github.com/vlifesystems/rulehuntersrv/html/cmd"
	"github.com/vlifesystems/rulehuntersrv/progress"
	"io/ioutil"
	"log"
	"os"
	"path/filepath"
	"time"
)

var logger service.Logger

type program struct {
	configDir       string
	config          *config.Config
	progressMonitor *progress.ProgressMonitor
}

func (p *program) Start(s service.Service) error {
	go p.run()
	return nil
}

func (p *program) run() {
	sleepInSeconds := time.Duration(2)
	logWaitingForExperiments := true

	for {
		if logWaitingForExperiments {
			logWaitingForExperiments = false
			logger.Infof("Waiting for experiments to process")
		}
		experimentFilenames, err := p.getExperimentFilenames()
		if err != nil {
			logger.Error(err)
		}
		for _, experimentFilename := range experimentFilenames {
			err := p.progressMonitor.AddExperiment(experimentFilename)
			if err != nil {
				logger.Error(err)
			}
		}

		for _, experimentFilename := range experimentFilenames {
			logWaitingForExperiments = true
			logger.Infof("Processing experiment: %s", experimentFilename)

			err := experiment.Process(
				experimentFilename,
				p.config,
				p.progressMonitor,
			)
			if err != nil {
				logger.Errorf("Failed processing experiment: %s - %s",
					experimentFilename, err)
			} else {
				logger.Infof("Successfully processed experiment: %s",
					experimentFilename)
			}
			if err := p.moveExperimentToProcessed(experimentFilename); err != nil {
				fullErr := fmt.Errorf("Couldn't move experiment file: %s", err)
				logger.Error(fullErr)
			}
		}

		// Sleeping prevents 'excessive' cpu use and disk access
		time.Sleep(sleepInSeconds * time.Second)
	}
}

func (p *program) getExperimentFilenames() ([]string, error) {
	experimentFilenames := make([]string, 0)
	files, err := ioutil.ReadDir(p.config.ExperimentsDir)
	if err != nil {
		return experimentFilenames, err
	}

	for _, file := range files {
		if !file.IsDir() {
			experimentFilenames = append(experimentFilenames, file.Name())
		}
	}
	return experimentFilenames, nil
}

func (p *program) moveExperimentToProcessed(experimentFilename string) error {
	experimentFullFilename :=
		filepath.Join(p.config.ExperimentsDir, experimentFilename)
	experimentProcessedFullFilename :=
		filepath.Join(p.config.ExperimentsDir, "processed", experimentFilename)
	return os.Rename(experimentFullFilename, experimentProcessedFullFilename)
}

func (p *program) Stop(s service.Service) error {
	return nil
}

func main() {
	svcConfig := &service.Config{
		Name:        "GoTestService",
		DisplayName: "Go Test Service",
		Description: "A test Go service.",
	}
	prg := &program{}

	userPtr := flag.String("user", "", "The user to run the server as")
	configDirPtr := flag.String("configdir", "", "The configuration directory")
	installPtr := flag.Bool("install", false, "Install the server as a service")
	flag.Parse()

	if *userPtr != "" {
		svcConfig.UserName = *userPtr
	}

	if *configDirPtr != "" {
		svcConfig.Arguments = []string{fmt.Sprintf("-configdir=%s", *configDirPtr)}
		prg.configDir = *configDirPtr
	}

	configFilename := filepath.Join(prg.configDir, "config.json")
	config, err := config.Load(configFilename)
	if err != nil {
		log.Fatal(fmt.Sprintf("Couldn't load configuration %s: %s",
			configFilename, err))
	}
	prg.config = config

	htmlCmds := make(chan cmd.Cmd)
	prg.progressMonitor =
		progress.NewMonitor(filepath.Join(config.BuildDir, "progress"), htmlCmds)

	s, err := service.New(prg, svcConfig)
	if err != nil {
		log.Fatal(err)
	}
	logger, err = s.Logger(nil)
	if err != nil {
		log.Fatal(err)
	}

	go html.Run(config, prg.progressMonitor, logger, htmlCmds)
	htmlCmds <- cmd.All

	if *installPtr {
		if *configDirPtr == "" {
			log.Fatal("No -configdir argument")
		}
		err = s.Install()
		if err != nil {
			log.Fatal(err)
		}
	} else {
		err = s.Run()
		if err != nil {
			logger.Error(err)
		}
	}
}
<|endoftext|>


<commit_before>package samlsp

import (
	"net/http"
	"strings"
	"time"

	"github.com/crewjam/saml"
)

// ClientState implements client side storage for state.
type ClientState interface {
	SetState(w http.ResponseWriter, r *http.Request, id string, value string)
	GetStates(r *http.Request) map[string]string
	GetState(r *http.Request, id string) string
	DeleteState(w http.ResponseWriter, r *http.Request, id string) error
}

// ClientToken implements client side storage for signed authorization tokens.
type ClientToken interface {
	GetToken(r *http.Request) string
	SetToken(w http.ResponseWriter, r *http.Request, value string, maxAge time.Duration)
}

const stateCookiePrefix = "saml_"
const defaultCookieName = "token"

// ClientCookies implements ClientState and ClientToken using cookies.
type ClientCookies struct {
	ServiceProvider *saml.ServiceProvider
	Name            string
	Domain          string
	Secure          bool
}

// SetState stores the named state value by setting a cookie.
func (c ClientCookies) SetState(w http.ResponseWriter, r *http.Request, id string, value string) {
	http.SetCookie(w, &http.Cookie{
		Name:     stateCookiePrefix + id,
		Value:    value,
		MaxAge:   int(saml.MaxIssueDelay.Seconds()),
		HttpOnly: true,
		Secure:   c.Secure || r.URL.Scheme == "https",
		Path:     c.ServiceProvider.AcsURL.Path,
	})
}

// GetStates returns the currently stored states by reading cookies.
func (c ClientCookies) GetStates(r *http.Request) map[string]string {
	rv := map[string]string{}
	for _, cookie := range r.Cookies() {
		if !strings.HasPrefix(cookie.Name, stateCookiePrefix) {
			continue
		}
		name := strings.TrimPrefix(cookie.Name, stateCookiePrefix)
		rv[name] = cookie.Value
	}
	return rv
}

// GetState returns a single stored state by reading the cookies
func (c ClientCookies) GetState(r *http.Request, id string) string {
	stateCookie, err := r.Cookie(stateCookiePrefix + id)
	if err != nil {
		return ""
	}
	return stateCookie.Value
}

// DeleteState removes the named stored state by clearing the corresponding cookie.
func (c ClientCookies) DeleteState(w http.ResponseWriter, r *http.Request, id string) error {
	cookie, err := r.Cookie(stateCookiePrefix + id)
	if err != nil {
		return err
	}
	cookie.Value = ""
	cookie.Expires = time.Unix(1, 0) // past time as close to epoch as possible, but not zero time.Time{}
	http.SetCookie(w, cookie)
	return nil
}

// SetToken assigns the specified token by setting a cookie.
func (c ClientCookies) SetToken(w http.ResponseWriter, r *http.Request, value string, maxAge time.Duration) {
	http.SetCookie(w, &http.Cookie{
		Name:     c.Name,
		Domain:   c.Domain,
		Value:    value,
		MaxAge:   int(maxAge.Seconds()),
		HttpOnly: true,
		Secure:   c.Secure || r.URL.Scheme == "https",
		Path:     "/",
	})
}

// GetToken returns the token by reading the cookie.
func (c ClientCookies) GetToken(r *http.Request) string {
	cookie, err := r.Cookie(c.Name)
	if err != nil {
		return ""
	}
	return cookie.Value
}

var _ ClientState = ClientCookies{}
var _ ClientToken = ClientCookies{}
<commit_msg>Don't include the port with the domain when setting the cookie (#202)<commit_after>package samlsp

import (
	"net"
	"net/http"
	"strings"
	"time"

	"github.com/crewjam/saml"
)

// ClientState implements client side storage for state.
type ClientState interface {
	SetState(w http.ResponseWriter, r *http.Request, id string, value string)
	GetStates(r *http.Request) map[string]string
	GetState(r *http.Request, id string) string
	DeleteState(w http.ResponseWriter, r *http.Request, id string) error
}

// ClientToken implements client side storage for signed authorization tokens.
type ClientToken interface {
	GetToken(r *http.Request) string
	SetToken(w http.ResponseWriter, r *http.Request, value string, maxAge time.Duration)
}

const stateCookiePrefix = "saml_"
const defaultCookieName = "token"

// ClientCookies implements ClientState and ClientToken using cookies.
type ClientCookies struct {
	ServiceProvider *saml.ServiceProvider
	Name            string
	Domain          string
	Secure          bool
}

// SetState stores the named state value by setting a cookie.
func (c ClientCookies) SetState(w http.ResponseWriter, r *http.Request, id string, value string) {
	http.SetCookie(w, &http.Cookie{
		Name:     stateCookiePrefix + id,
		Value:    value,
		MaxAge:   int(saml.MaxIssueDelay.Seconds()),
		HttpOnly: true,
		Secure:   c.Secure || r.URL.Scheme == "https",
		Path:     c.ServiceProvider.AcsURL.Path,
	})
}

// GetStates returns the currently stored states by reading cookies.
func (c ClientCookies) GetStates(r *http.Request) map[string]string {
	rv := map[string]string{}
	for _, cookie := range r.Cookies() {
		if !strings.HasPrefix(cookie.Name, stateCookiePrefix) {
			continue
		}
		name := strings.TrimPrefix(cookie.Name, stateCookiePrefix)
		rv[name] = cookie.Value
	}
	return rv
}

// GetState returns a single stored state by reading the cookies
func (c ClientCookies) GetState(r *http.Request, id string) string {
	stateCookie, err := r.Cookie(stateCookiePrefix + id)
	if err != nil {
		return ""
	}
	return stateCookie.Value
}

// DeleteState removes the named stored state by clearing the corresponding cookie.
func (c ClientCookies) DeleteState(w http.ResponseWriter, r *http.Request, id string) error {
	cookie, err := r.Cookie(stateCookiePrefix + id)
	if err != nil {
		return err
	}
	cookie.Value = ""
	cookie.Expires = time.Unix(1, 0) // past time as close to epoch as possible, but not zero time.Time{}
	http.SetCookie(w, cookie)
	return nil
}

// SetToken assigns the specified token by setting a cookie.
func (c ClientCookies) SetToken(w http.ResponseWriter, r *http.Request, value string, maxAge time.Duration) {
	// Cookies should not have the port attached to them so strip it off
	domain := c.Domain
	if strings.Contains(domain, ":") {
		domain, _, _ = net.SplitHostPort(domain)
	}
	http.SetCookie(w, &http.Cookie{
		Name:     c.Name,
		Domain:   domain,
		Value:    value,
		MaxAge:   int(maxAge.Seconds()),
		HttpOnly: true,
		Secure:   c.Secure || r.URL.Scheme == "https",
		Path:     "/",
	})
}

// GetToken returns the token by reading the cookie.
func (c ClientCookies) GetToken(r *http.Request) string {
	cookie, err := r.Cookie(c.Name)
	if err != nil {
		return ""
	}
	return cookie.Value
}

var _ ClientState = ClientCookies{}
var _ ClientToken = ClientCookies{}
<|endoftext|>


<commit_before>package veneur

import (
	"testing"

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

func TestCounterEmpty(t *testing.T) {

	c := NewCounter("a.b.c", []string{"a:b"})
	c.Sample(1, 1.0)

	assert.Equal(t, "a.b.c", c.name, "Name")
	if len(c.tags) != 1 && c.tags[0] != "a:b" {
		t.Errorf("Expected tags, wanted ([\"a:b\"]) got (%v)", c.tags)
	}

	metrics := c.Flush()
	if len(metrics) != 1 {
		t.Errorf("Expected 1 DDMetric, got (%d)", len(metrics))
	}

	m1 := metrics[0]
	if m1.Interval != 10 {
		t.Errorf("Expected interval, wanted (10) got (%d)", m1.Interval)
	}
	if m1.MetricType != "rate" {
		t.Errorf("Expected metric type, wanted (rate) got (%s)", m1.MetricType)
	}
	tags := m1.Tags
	if len(tags) != 1 && tags[0] != "a:b" {
		t.Errorf("Expected tags, wanted ([\"a:b\"]) got (%v)", m1.Tags)
	}
	// The counter returns an array with a single tuple of timestamp,value
	if m1.Value[0][1] != 0.1 {
		t.Errorf("Expected value, wanted (0) got (%f)", m1.Value[0][1])
	}
}

func TestCounterRate(t *testing.T) {

	c := NewCounter("a.b.c", []string{"a:b"})

	c.Sample(5, 1.0)

	// The counter returns an array with a single tuple of timestamp,value
	metrics := c.Flush()
	if metrics[0].Value[0][1] != 0.5 {
		t.Errorf("Expected value, wanted (0.5) got (%f)", metrics[0].Value[0][1])
	}
}

func TestGauge(t *testing.T) {

	g := NewGauge("a.b.c", []string{"a:b"})

	if g.name != "a.b.c" {
		t.Errorf("Expected name, wanted (a.b.c) got (%s)", g.name)
	}
	if len(g.tags) != 1 && g.tags[0] != "a:b" {
		t.Errorf("Expected tags, wanted ([\"a:b\"]) got (%v)", g.tags)
	}

	g.Sample(5, 1.0)

	metrics := g.Flush()
	if len(metrics) != 1 {
		t.Errorf("Expected 1 DDMetric, got (%d)", len(metrics))
	}

	m1 := metrics[0]
	// Interval is not meaningful for this
	if m1.Interval != 0 {
		t.Errorf("Expected interval, wanted (0) got (%d)", m1.Interval)
	}
	if m1.MetricType != "gauge" {
		t.Errorf("Expected metric type, wanted (gauge) got (%s)", m1.MetricType)
	}
	tags := m1.Tags
	if len(tags) != 1 && tags[0] != "a:b" {
		t.Errorf("Expected tags, wanted ([\"a:b\"]) got (%v)", m1.Tags)
	}
	// The counter returns an array with a single tuple of timestamp,value
	if m1.Value[0][1] != 5 {
		t.Errorf("Expected value, wanted (5) got (%f)", m1.Value[0][1])
	}
}

func TestSet(t *testing.T) {

	s := NewSet("a.b.c", []string{"a:b"}, 1000, 0.99)

	assert.Equal(t, "a.b.c", s.name, "Name")
	assert.Len(t, s.tags, 1, "Tag count")
	assert.Equal(t, "a:b", s.tags[0], "First tag")

	s.Sample(5, 1.0)

	s.Sample(5, 1.0)

	s.Sample(123, 1.0)

	metrics := s.Flush()
	assert.Len(t, metrics, 1, "Flush")

	m1 := metrics[0]
	// Interval is not meaningful for this
	assert.Equal(t, int32(0), m1.Interval, "Interval")
	assert.Equal(t, "set", m1.MetricType, "Type")
	assert.Len(t, m1.Tags, 1, "Tag count")
	assert.Equal(t, "a:b", m1.Tags[0], "First tag")
	assert.Equal(t, float64(2), m1.Value[0][1], "Value")
}

func TestHisto(t *testing.T) {

	h := NewHist("a.b.c", []string{"a:b"}, []float64{0.50})

	if h.name != "a.b.c" {
		t.Errorf("Expected name, wanted (a.b.c) got (%s)", h.name)
	}
	if len(h.tags) != 1 && h.tags[0] != "a:b" {
		t.Errorf("Expected tags, wanted ([\"a:b\"]) got (%v)", h.tags)
	}

	h.Sample(5, 1.0)
	h.Sample(10, 1.0)
	h.Sample(15, 1.0)
	h.Sample(20, 1.0)
	h.Sample(25, 1.0)

	metrics := h.Flush()
	// We get lots of metrics back for histograms!
	if len(metrics) != 4 {
		t.Errorf("Expected 4 DDMetrics, got (%d)", len(metrics))
	}

	// First the count
	m1 := metrics[0]
	if m1.Name != "a.b.c.count" {
		t.Errorf("Expected interval, wanted (a.b.c.count) got (%s)", m1.Name)
	}
	if m1.Interval != 10 {
		t.Errorf("Expected interval, wanted (10) got (%d)", m1.Interval)
	}
	if m1.MetricType != "rate" {
		t.Errorf("Expected metric type, wanted (rate) got (%s)", m1.MetricType)
	}
	tags := m1.Tags
	if len(tags) != 1 && tags[0] != "a:b" {
		t.Errorf("Expected tags, wanted ([\"a:b\"]) got (%v)", m1.Tags)
	}
	// The counter returns an array with a single tuple of timestamp,value
	if m1.Value[0][1] != 0.5 {
		t.Errorf("Expected value, wanted (0.5) got (%f)", m1.Value[0][1])
	}

	// Now the max
	m2 := metrics[1]
	if m2.Name != "a.b.c.max" {
		t.Errorf("Expected interval, wanted (a.b.c.max) got (%s)", m2.Name)
	}
	if m2.Interval != 0 {
		t.Errorf("Expected interval, wanted (0) got (%d)", m2.Interval)
	}
	if m2.MetricType != "gauge" {
		t.Errorf("Expected metric type, wanted (gauge) got (%s)", m2.MetricType)
	}
	if len(m2.Tags) != 1 && m2.Tags[0] != "a:b" {
		t.Errorf("Expected tags, wanted ([\"a:b\"]) got (%v)", m2.Tags)
	}
	// The counter returns an array with a single tuple of timestamp,value
	if m2.Value[0][1] != 25 {
		t.Errorf("Expected value, wanted (1) got (%f)", m2.Value[0][1])
	}

	// Now the min
	m3 := metrics[2]
	if m3.Name != "a.b.c.min" {
		t.Errorf("Expected interval, wanted (a.b.c.min) got (%s)", m3.Name)
	}
	if m3.Interval != 0 {
		t.Errorf("Expected interval, wanted (0) got (%d)", m3.Interval)
	}
	if m3.MetricType != "gauge" {
		t.Errorf("Expected metric type, wanted (gauge) got (%s)", m3.MetricType)
	}
	if len(m3.Tags) != 1 && m3.Tags[0] != "a:b" {
		t.Errorf("Expected tags, wanted ([\"a:b\"]) got (%v)", m3.Tags)
	}
	// The counter returns an array with a single tuple of timestamp,value
	if m3.Value[0][1] != 5 {
		t.Errorf("Expected value, wanted (2) got (%f)", m3.Value[0][1])
	}

	// And the percentile
	m4 := metrics[3]
	if m4.Name != "a.b.c.50percentile" {
		t.Errorf("Expected interval, wanted (a.b.c.50percentile) got (%s)", m4.Name)
	}
	if m4.Interval != 0 {
		t.Errorf("Expected interval, wanted (0) got (%d)", m4.Interval)
	}
	if m4.MetricType != "gauge" {
		t.Errorf("Expected metric type, wanted (gauge) got (%s)", m4.MetricType)
	}
	if len(m4.Tags) != 1 && m4.Tags[0] != "a:b" {
		t.Errorf("Expected tags, wanted ([\"a:b\"]) got (%v)", m4.Tags)
	}
	// The counter returns an array with a single tuple of timestamp,value
	if m4.Value[0][1] != 15 {
		t.Errorf("Expected value, wanted (15) got (%f)", m4.Value[0][1])
	}
}
<commit_msg>More test improvements<commit_after>package veneur

import (
	"testing"

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

func TestCounterEmpty(t *testing.T) {

	c := NewCounter("a.b.c", []string{"a:b"})
	c.Sample(1, 1.0)

	assert.Equal(t, "a.b.c", c.name, "Name")
	assert.Len(t, c.tags, 1, "Tag length")
	assert.Equal(t, c.tags[0], "a:b", "Tag contents")

	metrics := c.Flush()
	assert.Len(t, metrics, 1, "Flushes 1 metric")

	m1 := metrics[0]
	assert.Equal(t, int32(10), m1.Interval, "Interval")
	assert.Equal(t, "rate", m1.MetricType, "Type")
	assert.Len(t, c.tags, 1, "Tag length")
	assert.Equal(t, c.tags[0], "a:b", "Tag contents")
	// The counter returns an array with a single tuple of timestamp,value
	assert.Equal(t, 0.1, m1.Value[0][1], "Metric value")
}

func TestCounterRate(t *testing.T) {

	c := NewCounter("a.b.c", []string{"a:b"})

	c.Sample(5, 1.0)

	// The counter returns an array with a single tuple of timestamp,value
	metrics := c.Flush()
	assert.Equal(t, 0.5, metrics[0].Value[0][1], "Metric value")
}

func TestGauge(t *testing.T) {

	g := NewGauge("a.b.c", []string{"a:b"})

	assert.Equal(t, "a.b.c", g.name, "Name")
	assert.Len(t, g.tags, 1, "Tag length")
	assert.Equal(t, g.tags[0], "a:b", "Tag contents")

	g.Sample(5, 1.0)

	metrics := g.Flush()
	if len(metrics) != 1 {
		t.Errorf("Expected 1 DDMetric, got (%d)", len(metrics))
	}

	m1 := metrics[0]
	// Interval is not meaningful for this
	if m1.Interval != 0 {
		t.Errorf("Expected interval, wanted (0) got (%d)", m1.Interval)
	}
	if m1.MetricType != "gauge" {
		t.Errorf("Expected metric type, wanted (gauge) got (%s)", m1.MetricType)
	}
	tags := m1.Tags
	if len(tags) != 1 && tags[0] != "a:b" {
		t.Errorf("Expected tags, wanted ([\"a:b\"]) got (%v)", m1.Tags)
	}
	// The counter returns an array with a single tuple of timestamp,value
	if m1.Value[0][1] != 5 {
		t.Errorf("Expected value, wanted (5) got (%f)", m1.Value[0][1])
	}
}

func TestSet(t *testing.T) {

	s := NewSet("a.b.c", []string{"a:b"}, 1000, 0.99)

	assert.Equal(t, "a.b.c", s.name, "Name")
	assert.Len(t, s.tags, 1, "Tag count")
	assert.Equal(t, "a:b", s.tags[0], "First tag")

	s.Sample(5, 1.0)

	s.Sample(5, 1.0)

	s.Sample(123, 1.0)

	metrics := s.Flush()
	assert.Len(t, metrics, 1, "Flush")

	m1 := metrics[0]
	// Interval is not meaningful for this
	assert.Equal(t, int32(0), m1.Interval, "Interval")
	assert.Equal(t, "set", m1.MetricType, "Type")
	assert.Len(t, m1.Tags, 1, "Tag count")
	assert.Equal(t, "a:b", m1.Tags[0], "First tag")
	assert.Equal(t, float64(2), m1.Value[0][1], "Value")
}

func TestHisto(t *testing.T) {

	h := NewHist("a.b.c", []string{"a:b"}, []float64{0.50})

	if h.name != "a.b.c" {
		t.Errorf("Expected name, wanted (a.b.c) got (%s)", h.name)
	}
	if len(h.tags) != 1 && h.tags[0] != "a:b" {
		t.Errorf("Expected tags, wanted ([\"a:b\"]) got (%v)", h.tags)
	}

	h.Sample(5, 1.0)
	h.Sample(10, 1.0)
	h.Sample(15, 1.0)
	h.Sample(20, 1.0)
	h.Sample(25, 1.0)

	metrics := h.Flush()
	// We get lots of metrics back for histograms!
	if len(metrics) != 4 {
		t.Errorf("Expected 4 DDMetrics, got (%d)", len(metrics))
	}

	// First the count
	m1 := metrics[0]
	if m1.Name != "a.b.c.count" {
		t.Errorf("Expected interval, wanted (a.b.c.count) got (%s)", m1.Name)
	}
	if m1.Interval != 10 {
		t.Errorf("Expected interval, wanted (10) got (%d)", m1.Interval)
	}
	if m1.MetricType != "rate" {
		t.Errorf("Expected metric type, wanted (rate) got (%s)", m1.MetricType)
	}
	tags := m1.Tags
	if len(tags) != 1 && tags[0] != "a:b" {
		t.Errorf("Expected tags, wanted ([\"a:b\"]) got (%v)", m1.Tags)
	}
	// The counter returns an array with a single tuple of timestamp,value
	if m1.Value[0][1] != 0.5 {
		t.Errorf("Expected value, wanted (0.5) got (%f)", m1.Value[0][1])
	}

	// Now the max
	m2 := metrics[1]
	if m2.Name != "a.b.c.max" {
		t.Errorf("Expected interval, wanted (a.b.c.max) got (%s)", m2.Name)
	}
	if m2.Interval != 0 {
		t.Errorf("Expected interval, wanted (0) got (%d)", m2.Interval)
	}
	if m2.MetricType != "gauge" {
		t.Errorf("Expected metric type, wanted (gauge) got (%s)", m2.MetricType)
	}
	if len(m2.Tags) != 1 && m2.Tags[0] != "a:b" {
		t.Errorf("Expected tags, wanted ([\"a:b\"]) got (%v)", m2.Tags)
	}
	// The counter returns an array with a single tuple of timestamp,value
	if m2.Value[0][1] != 25 {
		t.Errorf("Expected value, wanted (1) got (%f)", m2.Value[0][1])
	}

	// Now the min
	m3 := metrics[2]
	if m3.Name != "a.b.c.min" {
		t.Errorf("Expected interval, wanted (a.b.c.min) got (%s)", m3.Name)
	}
	if m3.Interval != 0 {
		t.Errorf("Expected interval, wanted (0) got (%d)", m3.Interval)
	}
	if m3.MetricType != "gauge" {
		t.Errorf("Expected metric type, wanted (gauge) got (%s)", m3.MetricType)
	}
	if len(m3.Tags) != 1 && m3.Tags[0] != "a:b" {
		t.Errorf("Expected tags, wanted ([\"a:b\"]) got (%v)", m3.Tags)
	}
	// The counter returns an array with a single tuple of timestamp,value
	if m3.Value[0][1] != 5 {
		t.Errorf("Expected value, wanted (2) got (%f)", m3.Value[0][1])
	}

	// And the percentile
	m4 := metrics[3]
	if m4.Name != "a.b.c.50percentile" {
		t.Errorf("Expected interval, wanted (a.b.c.50percentile) got (%s)", m4.Name)
	}
	if m4.Interval != 0 {
		t.Errorf("Expected interval, wanted (0) got (%d)", m4.Interval)
	}
	if m4.MetricType != "gauge" {
		t.Errorf("Expected metric type, wanted (gauge) got (%s)", m4.MetricType)
	}
	if len(m4.Tags) != 1 && m4.Tags[0] != "a:b" {
		t.Errorf("Expected tags, wanted ([\"a:b\"]) got (%v)", m4.Tags)
	}
	// The counter returns an array with a single tuple of timestamp,value
	if m4.Value[0][1] != 15 {
		t.Errorf("Expected value, wanted (15) got (%f)", m4.Value[0][1])
	}
}
<|endoftext|>


<commit_before>package main

import (
	"encoding/xml"
	"github.com/gorilla/feeds"
	"github.com/kennygrant/sanitize"
	"golang.org/x/tools/blog/atom"
	"io/ioutil"
	"net/http"
	"net/url"
	"regexp"
	"strings"
	"sync"
	"time"
)

const (
	SanrioAlertsUrl = "http://scraper.mono0x.net/sanrio-alerts"
)

func GetSanrioAlerts() (*feeds.Feed, error) {

	urls := []string{
		"https://www.google.com/alerts/feeds/17240735437045332758/1863509270421926440",
		"https://www.google.com/alerts/feeds/17240735437045332758/1863509270421929515",
		"https://www.google.com/alerts/feeds/17240735437045332758/2414106377807123167",
		"https://www.google.com/alerts/feeds/17240735437045332758/2414106377807124539",
		"https://www.google.com/alerts/feeds/17240735437045332758/2414106377807125523",
		"https://www.google.com/alerts/feeds/17240735437045332758/2636887480119177525",
		"https://www.google.com/alerts/feeds/17240735437045332758/2636887480119178148",
		"https://www.google.com/alerts/feeds/17240735437045332758/2636887480119179073",
	}

	atomChan := make(chan *atom.Feed)
	quitChan := make(chan bool)
	errChan := make(chan error)

	go func() {
		var wg sync.WaitGroup
		for _, url := range urls {
			wg.Add(1)
			go func(url string) {
				defer wg.Done()

				resp, err := http.Get(url)
				if err != nil {
					errChan <- err
					return
				}
				defer resp.Body.Close()

				body, err := ioutil.ReadAll(resp.Body)
				if err != nil {
					errChan <- err
					return
				}

				var atom atom.Feed
				err = xml.Unmarshal(body, &atom)
				if err != nil {
					errChan <- err
					return
				}

				atomChan <- &atom
			}(url)
		}
		wg.Wait()

		quitChan <- true
	}()

	var atoms []*atom.Feed

loop:
	for {
		select {
		case atom := <-atomChan:
			atoms = append(atoms, atom)

		case <-quitChan:
			break loop

		case err := <-errChan:
			return nil, err
		}
	}

	return GetSanrioAlertsFromAtom(atoms)
}

func GetSanrioAlertsFromAtom(atoms []*atom.Feed) (*feeds.Feed, error) {
	var items []*feeds.Item

	hosts := []string{
		"auction.rakuten.co.jp",
		"pecolly.jp",
		"shoppies.jp",
		"auctions.yahoo.co.jp",
		"cookpad.com",
		"fril.jp",
		"item.mercali.com",
		"rakuma.rakuten.co.jp",
	}

	keywords := []string{
		"あす楽",
		"きせかえ",
		"サマンサ",
		"ポイント",
		"三輪車",
		"価格",
		"即納",
		"在庫",
		"安い",
		"定価",
		"新品",
		"楽天",
		"激安",
		"自転車",
		"販売",
		"送料",
		"通販",
		"限定",
	}

	keywordsRe := regexp.MustCompile(strings.Join(keywords, "|"))

	urls := map[string]bool{}

	for _, atom := range atoms {
	entryLoop:
		for _, entry := range atom.Entry {
			if len(entry.Link) == 0 {
				continue
			}

			href, err := url.Parse(entry.Link[0].Href)
			if err != nil {
				return nil, err
			}

			u, err := url.Parse(href.Query().Get("url"))
			if err != nil {
				return nil, err
			}

			urlString := u.String()
			if _, ok := urls[urlString]; ok {
				continue
			}
			urls[urlString] = true

			for _, host := range hosts {
				if strings.HasSuffix(u.Host, host) {
					continue entryLoop
				}
			}

			title := sanitize.HTML(entry.Title)
			if keywordsRe.MatchString(title) {
				continue
			}

			content := sanitize.HTML(entry.Content.Body)
			if keywordsRe.MatchString(content) {
				continue
			}

			published, err := time.Parse(time.RFC3339, string(entry.Published))
			if err != nil {
				return nil, err
			}
			updated, err := time.Parse(time.RFC3339, string(entry.Updated))
			if err != nil {
				return nil, err
			}

			items = append(items, &feeds.Item{
				Title:       title,
				Description: content,
				Id:          urlString,
				Link:        &feeds.Link{Href: urlString},
				Created:     published,
				Updated:     updated,
			})
		}
	}

	feed := &feeds.Feed{
		Title: "Sanrio Alerts",
		Link:  &feeds.Link{Href: SanrioAlertsUrl},
		Items: items,
	}

	return feed, nil
}
<commit_msg>Update keywords<commit_after>package main

import (
	"encoding/xml"
	"github.com/gorilla/feeds"
	"github.com/kennygrant/sanitize"
	"golang.org/x/tools/blog/atom"
	"io/ioutil"
	"net/http"
	"net/url"
	"regexp"
	"strings"
	"sync"
	"time"
)

const (
	SanrioAlertsUrl = "http://scraper.mono0x.net/sanrio-alerts"
)

func GetSanrioAlerts() (*feeds.Feed, error) {

	urls := []string{
		"https://www.google.com/alerts/feeds/17240735437045332758/1863509270421926440",
		"https://www.google.com/alerts/feeds/17240735437045332758/1863509270421929515",
		"https://www.google.com/alerts/feeds/17240735437045332758/2414106377807123167",
		"https://www.google.com/alerts/feeds/17240735437045332758/2414106377807124539",
		"https://www.google.com/alerts/feeds/17240735437045332758/2414106377807125523",
		"https://www.google.com/alerts/feeds/17240735437045332758/2636887480119177525",
		"https://www.google.com/alerts/feeds/17240735437045332758/2636887480119178148",
		"https://www.google.com/alerts/feeds/17240735437045332758/2636887480119179073",
	}

	atomChan := make(chan *atom.Feed)
	quitChan := make(chan bool)
	errChan := make(chan error)

	go func() {
		var wg sync.WaitGroup
		for _, url := range urls {
			wg.Add(1)
			go func(url string) {
				defer wg.Done()

				resp, err := http.Get(url)
				if err != nil {
					errChan <- err
					return
				}
				defer resp.Body.Close()

				body, err := ioutil.ReadAll(resp.Body)
				if err != nil {
					errChan <- err
					return
				}

				var atom atom.Feed
				err = xml.Unmarshal(body, &atom)
				if err != nil {
					errChan <- err
					return
				}

				atomChan <- &atom
			}(url)
		}
		wg.Wait()

		quitChan <- true
	}()

	var atoms []*atom.Feed

loop:
	for {
		select {
		case atom := <-atomChan:
			atoms = append(atoms, atom)

		case <-quitChan:
			break loop

		case err := <-errChan:
			return nil, err
		}
	}

	return GetSanrioAlertsFromAtom(atoms)
}

func GetSanrioAlertsFromAtom(atoms []*atom.Feed) (*feeds.Feed, error) {
	var items []*feeds.Item

	hosts := []string{
		"auction.rakuten.co.jp",
		"pecolly.jp",
		"shoppies.jp",
		"auctions.yahoo.co.jp",
		"cookpad.com",
		"fril.jp",
		"item.mercali.com",
		"rakuma.rakuten.co.jp",
	}

	keywords := []string{
		"iphone",
		"あす楽",
		"きせかえ",
		"サマンサ",
		"ポイント",
		"三輪車",
		"価格",
		"即納",
		"在庫",
		"安い",
		"定価",
		"新品",
		"楽天",
		"激安",
		"自転車",
		"販売",
		"送料",
		"通販",
		"限定",
	}

	keywordsRe := regexp.MustCompile(strings.Join(keywords, "|"))

	urls := map[string]bool{}

	for _, atom := range atoms {
	entryLoop:
		for _, entry := range atom.Entry {
			if len(entry.Link) == 0 {
				continue
			}

			href, err := url.Parse(entry.Link[0].Href)
			if err != nil {
				return nil, err
			}

			u, err := url.Parse(href.Query().Get("url"))
			if err != nil {
				return nil, err
			}

			urlString := u.String()
			if _, ok := urls[urlString]; ok {
				continue
			}
			urls[urlString] = true

			for _, host := range hosts {
				if strings.HasSuffix(u.Host, host) {
					continue entryLoop
				}
			}

			title := sanitize.HTML(entry.Title)
			if keywordsRe.MatchString(title) {
				continue
			}

			content := sanitize.HTML(entry.Content.Body)
			if keywordsRe.MatchString(content) {
				continue
			}

			published, err := time.Parse(time.RFC3339, string(entry.Published))
			if err != nil {
				return nil, err
			}
			updated, err := time.Parse(time.RFC3339, string(entry.Updated))
			if err != nil {
				return nil, err
			}

			items = append(items, &feeds.Item{
				Title:       title,
				Description: content,
				Id:          urlString,
				Link:        &feeds.Link{Href: urlString},
				Created:     published,
				Updated:     updated,
			})
		}
	}

	feed := &feeds.Feed{
		Title: "Sanrio Alerts",
		Link:  &feeds.Link{Href: SanrioAlertsUrl},
		Items: items,
	}

	return feed, nil
}
<|endoftext|>


<commit_before>package schema

import (
	"sort"

	"github.com/tmc/graphql"
	"github.com/tmc/graphql/executor/resolver"
)

// Schema represents the registered types that know how to respond to root calls.
type Schema struct {
	registeredTypes map[string]GraphQLTypeInfo
	rootFields      map[string]*GraphQLFieldSpec
}

// New prepares a new Schema.
func New() *Schema {
	s := &Schema{
		registeredTypes: map[string]GraphQLTypeInfo{},
		rootFields:      map[string]*GraphQLFieldSpec{},
	}
	// self-register
	s.Register(s)
	// register special introspection type
	//i := &GraphQLTypeIntrospector{schema: s}
	i := &GraphQLTypeIntrospector{}
	s.Register(i)
	//s.Register(&GraphQLFieldSpec{})
	return s
}

// Register registers a new type
func (s *Schema) Register(t GraphQLType) {
	typeInfo := t.GraphQLTypeInfo()
	s.registeredTypes[t.GraphQLTypeInfo().Name] = typeInfo
	// TODO(tmc): collision handling
	for name, fieldSpec := range typeInfo.Fields {
		if fieldSpec.IsRoot {
			s.rootFields[name] = fieldSpec
		}
	}
}

func WithIntrospectionField(typeInfo GraphQLTypeInfo) GraphQLTypeInfo {
	introSpectionFunc := newIntrospectionField(typeInfo)
	typeInfo.Fields["__type__"] = &GraphQLFieldSpec{
		Name:        "__type__",
		Description: "Introspection field that exposes field and type information",
		Func:        introSpectionFunc,
	}
	return typeInfo
}

// External entrypoint

/*
// HandleField dispatches a graphql.Field to the appropriate registered type.
func (s *Schema) HandleField(f *graphql.Field) (interface{}, error) {
	handler, ok := s.rootFields[f.Name]
	if !ok {
		return nil, fmt.Errorf("schema: no registered types handle the root call '%s'", f.Name)
	}
	return handler.Func(f)
}
*/

func (s *Schema) RootFields() map[string]*GraphQLFieldSpec {
	return s.rootFields
}

func (s *Schema) GetTypeInfo(o GraphQLType) GraphQLTypeInfo {
	panic(s)
	return s.registeredTypes[o.GraphQLTypeInfo().Name]
}

func (s *Schema) RegisteredTypes() map[string]GraphQLTypeInfo {
	return s.registeredTypes
}

// The below makes Schema itsself a GraphQLType and provides the root entry call of 'schema'

func (s *Schema) GraphQLTypeInfo() GraphQLTypeInfo {
	return GraphQLTypeInfo{
		Name:        "Schema",
		Description: "Root schema object",
		Fields: map[string]*GraphQLFieldSpec{
			"__schema":    {"__schema", "Schema entry root call", s.handleSchemaCall, nil, true},
			"__types":     {"__types", "Introspection of registered types", s.handleTypesCall, nil, true},
			"root_fields": {"root_fields", "List fields that are exposed at the root of the GraphQL schema.", s.handleRootFields, nil, false},
		},
	}
}

func (s *Schema) handleSchemaCall(r resolver.Resolver, f *graphql.Field) (interface{}, error) {
	return s, nil
}

func (s *Schema) handleTypesCall(r resolver.Resolver, f *graphql.Field) (interface{}, error) {
	typeNames := make([]string, 0, len(s.registeredTypes))
	for typeName := range s.registeredTypes {
		typeNames = append(typeNames, typeName)
	}
	sort.Strings(typeNames)
	result := make([]GraphQLTypeInfo, 0, len(typeNames))
	for _, typeName := range typeNames {
		result = append(result, s.registeredTypes[typeName])
	}
	return result, nil
}

func (s *Schema) handleRootFields(r resolver.Resolver, f *graphql.Field) (interface{}, error) {
	rootFields := []string{}
	for rootField := range s.rootFields {
		rootFields = append(rootFields, rootField)
	}
	sort.Strings(rootFields)
	result := make([]*GraphQLFieldSpec, 0, len(rootFields))
	for _, field := range rootFields {
		result = append(result, s.rootFields[field])
	}
	return result, nil
}
<commit_msg>Remove stale code<commit_after>package schema

import (
	"sort"

	"github.com/tmc/graphql"
	"github.com/tmc/graphql/executor/resolver"
)

// Schema represents the registered types that know how to respond to root calls.
type Schema struct {
	registeredTypes map[string]GraphQLTypeInfo
	rootFields      map[string]*GraphQLFieldSpec
}

// New prepares a new Schema.
func New() *Schema {
	s := &Schema{
		registeredTypes: map[string]GraphQLTypeInfo{},
		rootFields:      map[string]*GraphQLFieldSpec{},
	}
	// self-register
	s.Register(s)
	// register special introspection type
	//i := &GraphQLTypeIntrospector{schema: s}
	i := &GraphQLTypeIntrospector{}
	s.Register(i)
	//s.Register(&GraphQLFieldSpec{})
	return s
}

// Register registers a new type
func (s *Schema) Register(t GraphQLType) {
	typeInfo := t.GraphQLTypeInfo()
	s.registeredTypes[t.GraphQLTypeInfo().Name] = typeInfo
	// TODO(tmc): collision handling
	for name, fieldSpec := range typeInfo.Fields {
		if fieldSpec.IsRoot {
			s.rootFields[name] = fieldSpec
		}
	}
}

func WithIntrospectionField(typeInfo GraphQLTypeInfo) GraphQLTypeInfo {
	introSpectionFunc := newIntrospectionField(typeInfo)
	typeInfo.Fields["__type__"] = &GraphQLFieldSpec{
		Name:        "__type__",
		Description: "Introspection field that exposes field and type information",
		Func:        introSpectionFunc,
	}
	return typeInfo
}

func (s *Schema) RootFields() map[string]*GraphQLFieldSpec {
	return s.rootFields
}

func (s *Schema) GetTypeInfo(o GraphQLType) GraphQLTypeInfo {
	panic(s)
	return s.registeredTypes[o.GraphQLTypeInfo().Name]
}

func (s *Schema) RegisteredTypes() map[string]GraphQLTypeInfo {
	return s.registeredTypes
}

// The below makes Schema itsself a GraphQLType and provides the root entry call of 'schema'

func (s *Schema) GraphQLTypeInfo() GraphQLTypeInfo {
	return GraphQLTypeInfo{
		Name:        "Schema",
		Description: "Root schema object",
		Fields: map[string]*GraphQLFieldSpec{
			"__schema":    {"__schema", "Schema entry root call", s.handleSchemaCall, nil, true},
			"__types":     {"__types", "Introspection of registered types", s.handleTypesCall, nil, true},
			"root_fields": {"root_fields", "List fields that are exposed at the root of the GraphQL schema.", s.handleRootFields, nil, false},
		},
	}
}

func (s *Schema) handleSchemaCall(r resolver.Resolver, f *graphql.Field) (interface{}, error) {
	return s, nil
}

func (s *Schema) handleTypesCall(r resolver.Resolver, f *graphql.Field) (interface{}, error) {
	typeNames := make([]string, 0, len(s.registeredTypes))
	for typeName := range s.registeredTypes {
		typeNames = append(typeNames, typeName)
	}
	sort.Strings(typeNames)
	result := make([]GraphQLTypeInfo, 0, len(typeNames))
	for _, typeName := range typeNames {
		result = append(result, s.registeredTypes[typeName])
	}
	return result, nil
}

func (s *Schema) handleRootFields(r resolver.Resolver, f *graphql.Field) (interface{}, error) {
	rootFields := []string{}
	for rootField := range s.rootFields {
		rootFields = append(rootFields, rootField)
	}
	sort.Strings(rootFields)
	result := make([]*GraphQLFieldSpec, 0, len(rootFields))
	for _, field := range rootFields {
		result = append(result, s.rootFields[field])
	}
	return result, nil
}
<|endoftext|>


<commit_before>package scorer

import (
	"regexp"
	"strings"
	"unicode/utf8"
)

//PUNCTUATION is a regex string for finding ".", "?", and "!".
var PUNCTUATION = regexp.MustCompile("[.?!]+\\s")

// WORD is a regex string for words
var WORD = regexp.MustCompile("\\w+")

// Stats struct stores readability data for exports
type Stats struct {
	Syllables   int     `json:"syllables"`
	Words       int     `json:"words"`
	Sentences   int     `json:"sentences"`
	Readability float32 `json:"readability"`
}

// countSentences returns the number of sentances in the text
func countSentences(text string) int {
	return len(PUNCTUATION.Split(text, -1))
}

// getWords returns an array of words in the string
func getWords(text string) []string {
	return WORD.FindAllString(text, -1)
}

// getLetterType returns the type of letter
// 1 for weak vowel
// 2 for strong vowel
// 3 for consonant
func getLetterType(letter rune) int {
	switch letter {
	case 'i', 'u':
		return 1
	case 'a', 'e', 'o', 'í', 'ú':
		return 2
	}
	return 3
}

// countSyllables calculates the number of syllables using a modified
// version of the syllabification algorithm for spanish found in
// Heriberto Cuayáhuitl's article: http://www.dfki.de/~hecu01/publications/hc-cicling2004.pdf
func countSyllables(word string) int {
	word = strings.ToLower(word)
	var letterType, consonantRun, vowelRun, syllables int
	syllables = 1
	wordLength := utf8.RuneCountInString(word)
	for idx, letter := range word {
		letterType = getLetterType(letter)
		if letterType == 3 {
			if idx == 0 && wordLength > 3 {
				syllables--
			}
			consonantRun++
		} else {
			if consonantRun > 0 {
				syllables++
			}
			consonantRun = 0
		}
	}
	for _, letter := range word {
		letterType = getLetterType(letter)
		if letterType < 3 {
			vowelRun += letterType
		} else {
			if vowelRun > 3 {
				syllables++
			}
			vowelRun = 0
		}
	}
	if vowelRun > 3 && wordLength > 3 {
		syllables++
	}
	return syllables
}

// calculateReadability returns the spanish readability score
func calculateReadability(syllables int, words int, sentences int) float32 {
	return 206.84 - 60.0*(float32(syllables)/float32(words)) - 102.0*(float32(sentences)/float32(words))
}

// getCounts calculates syllables, words, and sentences
func getSyllablesAndWords(text string) (int, int) {
	var totalSyllables, totalWords int
	for _, word := range getWords(text) {
		totalWords++
		totalSyllables += countSyllables(word)
	}
	return totalSyllables, totalWords
}

// GetStats calculates Fernandez Huerta's readability scores using an updated formula found here:
// http://linguistlist.org/issues/22/22-2332.html
// This function also returns syllables, words, and sentences.
func GetStats(text string) Stats {
	var stats Stats
	stats.Sentences = countSentences(text)
	stats.Syllables, stats.Words = getSyllablesAndWords(text)
	stats.Readability = calculateReadability(stats.Sentences, stats.Words, stats.Sentences)
	return stats
}
<commit_msg>Developed concurent system for counting syllables<commit_after>package scorer

import (
	"regexp"
	"strings"
	"sync"
	"unicode/utf8"
)

//PUNCTUATION is a regex string for finding ".", "?", and "!".
var PUNCTUATION = regexp.MustCompile("[.?!]+\\s")

// WORD is a regex string for words
var WORD = regexp.MustCompile("\\w+")

// Stats struct stores readability data for exports
type Stats struct {
	Syllables   int     `json:"syllables"`
	Words       int     `json:"words"`
	Sentences   int     `json:"sentences"`
	Readability float32 `json:"readability"`
}

// countSentences returns the number of sentances in the text
func countSentences(text string) int {
	return len(PUNCTUATION.Split(text, -1))
}

// getWords returns an array of words in the string
func getWords(text string) []string {
	return WORD.FindAllString(text, -1)
}

// getLetterType returns the type of letter
// 1 for weak vowel
// 2 for strong vowel
// 3 for consonant
func getLetterType(letter rune) int {
	switch letter {
	case 'i', 'u':
		return 1
	case 'a', 'e', 'o', 'í', 'ú':
		return 2
	}
	return 3
}

// countSyllables calculates the number of syllables using a modified
// version of the syllabification algorithm for spanish found in
// Heriberto Cuayáhuitl's article: http://www.dfki.de/~hecu01/publications/hc-cicling2004.pdf
func countSyllables(word string) int {
	word = strings.ToLower(word)
	var letterType, consonantRun, vowelRun, syllables int
	syllables = 1
	wordLength := utf8.RuneCountInString(word)
	for idx, letter := range word {
		letterType = getLetterType(letter)
		if letterType == 3 {
			if idx == 0 && wordLength > 3 {
				syllables--
			}
			consonantRun++
		} else {
			if consonantRun > 0 {
				syllables++
			}
			consonantRun = 0
		}
	}
	for _, letter := range word {
		letterType = getLetterType(letter)
		if letterType < 3 {
			vowelRun += letterType
		} else {
			if vowelRun > 3 {
				syllables++
			}
			vowelRun = 0
		}
	}
	if vowelRun > 3 && wordLength > 3 {
		syllables++
	}
	return syllables
}

// calculateReadability returns the spanish readability score
func calculateReadability(syllables int, words int, sentences int) float32 {
	return 206.84 - 60.0*(float32(syllables)/float32(words)) - 102.0*(float32(sentences)/float32(words))
}

// getCounts calculates syllables, words, and sentences
func getSyllablesAndWords(text string) (int, int) {
	var totalSyllables int
	var wg sync.WaitGroup

	syllablesChannel := make(chan int)

	words := getWords(text)
	totalWords := len(words)

	wg.Add(totalWords)
	// Send words
	for _, word := range words {
		go func(word string) {
			defer wg.Done()
			syllablesChannel <- countSyllables(word)
		}(word)
	}
	// Get word counts
	go func() {
		for syllablesCount := range syllablesChannel {
			totalSyllables += syllablesCount
		}
	}()

	wg.Wait()

	return totalSyllables, totalWords
}

// GetStats calculates Fernandez Huerta's readability scores using an updated formula found here:
// http://linguistlist.org/issues/22/22-2332.html
// This function also returns syllables, words, and sentences.
func GetStats(text string) Stats {
	var stats Stats
	stats.Sentences = countSentences(text)
	stats.Syllables, stats.Words = getSyllablesAndWords(text)
	stats.Readability = calculateReadability(stats.Sentences, stats.Words, stats.Sentences)
	return stats
}
<|endoftext|>


<commit_before>package datadog

import (
	"bytes"
	"fmt"
	"log"
	"strconv"
	"time"
	"strings"

	"github.com/zorkian/go-datadog-api"

	"github.com/hashicorp/terraform/helper/schema"
	"github.com/hashicorp/terraform/helper/hashcode"
)

// Work around the nested struct in https://github.com/zorkian/go-datadog-api/blob/master/dashboards.go#L16
type GraphDefintionRequests struct {
	Query   string `json:"q"`
	Stacked bool   `json:"stacked"`
}

func resourceDatadogGraph() *schema.Resource {
	return &schema.Resource{
		Create: resourceDatadogGraphCreate,
		Exists: resourceDatadogGraphExists,
		Read:   resourceDatadogGraphRead,
		Delete: resourceDatadogGraphDelete,
		Update: resourceDatadogGraphUpdate,

		Schema: map[string]*schema.Schema{
			"dashboard_id": &schema.Schema{
				Type:     schema.TypeInt,
				//Computed: true,
				Required: true,
				ForceNew: true,
			},
			"title": &schema.Schema{
				Type:     schema.TypeString,
				Required: true,
				ForceNew: true,
			},
			"viz": &schema.Schema{
				Type:     schema.TypeString,
				Required: true,
				ForceNew: true,
			},
			"request": &schema.Schema{
				Type:     schema.TypeSet,
				Optional: true,
				ForceNew: true,
				Elem: &schema.Resource{
					Schema: map[string]*schema.Schema{
						"query": &schema.Schema{
							Type:     schema.TypeString,
							Required: true,
						},
						"stacked": &schema.Schema{
							Type:     schema.TypeBool,
							Required: true,
						},
					},

				},
				Set: resourceDatadogRequestHash,
			},

			// TODO: support events.
		},
	}
}

func resourceDatadogGraphCreate(d *schema.ResourceData, meta interface{}) error {
	// This should create graphs associated with dashboards.
	// it's a virtual resource, a la "resource_vpn_connection_route"
	// hence we will need to do a bit of hacking to find out what dashboard.

	// TODO: Delete placeholder graph. See https://github.com/ojongerius/terraform-provider-datadog/issues/8

	// TODO:
	// * In Create; use as ID, the hash of the whole graph.
	// * When matching in Read/Retrieve; use this hash to see if we found it (yes this is relatively resource intense)
	// * This does imply that we *must* delete all graphs that are *not* know to us. How do we pull that off?
	//                    ^^ do we do that by re-posting all graphs on an update?
	//                    ^^ this is tricky. The graph resources do not know about others graphs, so we will just not
	//                       find ourselves...
	//                       The trick used by Terraform is for route tables and routes in it. Which is a different case.
	// * Profit
	//
	// New approach:
    //
	// ID in title.
	//
	// Difficulty; we can't expect the user to have the ID in their description
	// 		       but they change detection needs be so that we add be aware of this -Use the ID to identify
	//                 remove the ID of the diff.
	//
	// * Change Read function so find it by the ID, but store the title without the ID
	// * Change Update function to append the ID when updating the Dashboard at DD

	if d.Id() == "" {
		Id := int(time.Now().Unix())
		d.SetId(strconv.Itoa(Id)) // Use seconds since Epoch, needs to be a string when saving.

		log.Printf("[INFO] Graph ID: %d", Id)
	}

	// TODO: swapped this around so Id is avail
	resourceDatadogGraphUpdate(d, meta)

	err := resourceDatadogGraphRetrieve(d, meta)

	if err != nil {
		return err
	}

	return nil
}

func resourceDatadogGraphExists(d *schema.ResourceData, meta interface{}) (bool, error) {
	client := meta.(*datadog.Client)

	// Verify our Dashboard(s) exist
	_, err := client.GetDashboard(d.Get("dashboard_id").(int))

	if err != nil {
		if strings.EqualFold(err.Error(), "API error: 404 Not Found") {
			return false, nil
		}

		return false, fmt.Errorf("Error retrieving dashboard: %s", err)
	}

	// Verify we exist
	err = resourceDatadogGraphRead(d, meta)

	if err != nil {
		return false, err
	}

	return true, nil
}

func resourceDatadogGraphRead(d *schema.ResourceData, meta interface{}) error {
	err := resourceDatadogGraphRetrieve(d, meta)

	if err != nil {
		return err
	}

	return nil
}

func resourceDatadogGraphRetrieve(d *schema.ResourceData, meta interface{}) error {
	client := meta.(*datadog.Client)

	// Get the dashboard(s)
	dashboard, err := client.GetDashboard(d.Get("dashboard_id").(int))

	if err != nil {
		return fmt.Errorf("Error retrieving associated dashboard: %s", err)
	}

	// Walk through the graphs
	for _, g := range dashboard.Graphs {
		// If it ends with our ID, go:
		if strings.HasSuffix(g.Title, fmt.Sprintf("(%s)", d.Id())){
			log.Printf("[DEBUG] Found matching title. Start setting/saving state.")
			d.Set("dashboard_id", d.Get("dashboard_id"))
			// Save title to state, without the ID
			d.Set("title", strings.Replace(g.Title, fmt.Sprintf(" (%s)", d.Id()), "", 1))
			d.Set("viz", g.Definition.Viz)

			// Create an empty schema to hold all the requests.
			request := &schema.Set{F: resourceDatadogRequestHash}

			for _, r := range g.Definition.Requests {
				m := make(map[string]interface{})

				if r.Query != "" {
					m["query"] = r.Query
				}

				m["stacked"] = r.Stacked

				request.Add(m)
			}

			d.Set("request", request)

			return nil

		}
	}

	// If we are still around we've not found ourselves. Set SetId to empty so Terraform will create the resource for us.
	d.SetId("")

	return nil
}

func resourceDatadogGraphUpdate(d *schema.ResourceData, meta interface{}) error {
	client := meta.(*datadog.Client)

	// Get the dashboard
	dashboard, err := client.GetDashboard(d.Get("dashboard_id").(int))

	if err != nil {
		return err
	}

	// Check if there are changes
	if d.HasChange("request") {
		graph_definition := datadog.Graph{}.Definition
		graph_requests := datadog.Graph{}.Definition.Requests
		graph_definition.Viz = d.Get("viz").(string)

		log.Printf("[DEBUG] Request has changed.")
		o, n := d.GetChange("request")
		ors := o.(*schema.Set).Difference(n.(*schema.Set))
		nrs := n.(*schema.Set).Difference(o.(*schema.Set))

		// Loop through all the old requests and delete any obsolete ones
		for _, request := range ors.List() {
			m := request.(map[string]interface{})

			// TODO: implement
			// Delete the query as it no longer exists in the config
			log.Printf("[DEBUG] Deleting graph query %s", m["query"].(string))
			log.Printf("[DEBUG] Deleting graph stacked %t", m["stacked"].(bool))

		}
		// Loop through all the new requests and append them
		for _, request := range nrs.List() {
			m := request.(map[string]interface{})

			// Add the request
			log.Printf("[DEBUG] Adding graph query %s", m["query"].(string))
			log.Printf("[DEBUG] Adding graph stacked %t", m["stacked"].(bool))
			graph_requests = append(graph_requests, GraphDefintionRequests{Query: m["query"].(string),
				Stacked: m["stacked"].(bool)})
		}

		// Add requests to the graph definition
		graph_definition.Requests = graph_requests
		title := d.Get("title").(string) + fmt.Sprintf(" (%s)", d.Id())
		the_graph := datadog.Graph{Title: title, Definition: graph_definition}

		dashboard.Graphs = append(dashboard.Graphs, the_graph) // Should be done for each
	}

	// Update/commit
	err = client.UpdateDashboard(dashboard)

	if err != nil {
		return err
	}

	return nil
}

func resourceDatadogGraphDelete(d *schema.ResourceData, meta interface{}) error {
	client := meta.(*datadog.Client)

	// Get the dashboard
	dashboard, err := client.GetDashboard(d.Get("dashboard_id").(int))

	if err != nil {
		return fmt.Errorf("Error retrieving associated dashboard: %s", err)
	}

	// Build a new slice of graphs, without the nominee to deleted.
	// TODO: Use the set for this.
	new_graphs := []datadog.Graph{}
	for _, r := range dashboard.Graphs {
		// TODO: Look for our ID in the title (what is the most efficient way in Golang?)
		if strings.HasSuffix(r.Title, fmt.Sprintf("(%s)", d.Id())) {
			//if r.Title == d.Get("title") {
			continue
		} else {
			new_graphs = append(new_graphs, r)
		}
	}

	dashboard.Graphs = new_graphs

	// Update/commit
	err = client.UpdateDashboard(dashboard)

	if err != nil {
		return err
	}

	err = resourceDatadogGraphRetrieve(d, meta)

	if err != nil {
		return err
	}

	return nil
}

func resourceDatadogRequestHash(v interface{}) int{
	var buf bytes.Buffer
	m := v.(map[string]interface{})

	if v, ok := m["query"];  ok {
		buf.WriteString(fmt.Sprintf("%s-", v.(string)))
	}

	if v, ok := m["stacked"];  ok {
		buf.WriteString(fmt.Sprintf("%t-", v.(bool)))
	}

	return hashcode.String(buf.String())
}
<commit_msg>Remove notes, update comments.<commit_after>package datadog

import (
	"bytes"
	"fmt"
	"log"
	"strconv"
	"time"
	"strings"

	"github.com/zorkian/go-datadog-api"

	"github.com/hashicorp/terraform/helper/schema"
	"github.com/hashicorp/terraform/helper/hashcode"
)

// Work around the nested struct in https://github.com/zorkian/go-datadog-api/blob/master/dashboards.go#L16
type GraphDefintionRequests struct {
	Query   string `json:"q"`
	Stacked bool   `json:"stacked"`
}

func resourceDatadogGraph() *schema.Resource {
	return &schema.Resource{
		Create: resourceDatadogGraphCreate,
		Exists: resourceDatadogGraphExists,
		Read:   resourceDatadogGraphRead,
		Delete: resourceDatadogGraphDelete,
		Update: resourceDatadogGraphUpdate,

		Schema: map[string]*schema.Schema{
			"dashboard_id": &schema.Schema{
				Type:     schema.TypeInt,
				//Computed: true,
				Required: true,
				ForceNew: true,
			},
			"title": &schema.Schema{
				Type:     schema.TypeString,
				Required: true,
				ForceNew: true,
			},
			"viz": &schema.Schema{
				Type:     schema.TypeString,
				Required: true,
				ForceNew: true,
			},
			"request": &schema.Schema{
				Type:     schema.TypeSet,
				Optional: true,
				ForceNew: true,
				Elem: &schema.Resource{
					Schema: map[string]*schema.Schema{
						"query": &schema.Schema{
							Type:     schema.TypeString,
							Required: true,
						},
						"stacked": &schema.Schema{
							Type:     schema.TypeBool,
							Required: true,
						},
					},

				},
				Set: resourceDatadogRequestHash,
			},

			// TODO: support events.
		},
	}
}

func resourceDatadogGraphCreate(d *schema.ResourceData, meta interface{}) error {
	// This should create graphs associated with dashboards.
	// it's a virtual resource, a la "resource_vpn_connection_route"
	// hence we will need to do a bit of hacking to find out what dashboard.

	// TODO: Delete placeholder graph. See https://github.com/ojongerius/terraform-provider-datadog/issues/8

	if d.Id() == "" {
		Id := int(time.Now().Unix())
		d.SetId(strconv.Itoa(Id)) // Use seconds since Epoch, needs to be a string when saving.

		log.Printf("[INFO] Graph ID: %d", Id)
	}

	resourceDatadogGraphUpdate(d, meta)

	err := resourceDatadogGraphRetrieve(d, meta)

	if err != nil {
		return err
	}

	return nil
}

func resourceDatadogGraphExists(d *schema.ResourceData, meta interface{}) (bool, error) {
	client := meta.(*datadog.Client)

	// Verify our Dashboard(s) exist
	_, err := client.GetDashboard(d.Get("dashboard_id").(int))

	if err != nil {
		if strings.EqualFold(err.Error(), "API error: 404 Not Found") {
			return false, nil
		}

		return false, fmt.Errorf("Error retrieving dashboard: %s", err)
	}

	// Verify we exist
	err = resourceDatadogGraphRead(d, meta)

	if err != nil {
		return false, err
	}

	return true, nil
}

func resourceDatadogGraphRead(d *schema.ResourceData, meta interface{}) error {
	err := resourceDatadogGraphRetrieve(d, meta)

	if err != nil {
		return err
	}

	return nil
}

func resourceDatadogGraphRetrieve(d *schema.ResourceData, meta interface{}) error {
	client := meta.(*datadog.Client)

	// Get the dashboard(s)
	dashboard, err := client.GetDashboard(d.Get("dashboard_id").(int))

	if err != nil {
		return fmt.Errorf("Error retrieving associated dashboard: %s", err)
	}

	// Walk through the graphs
	for _, g := range dashboard.Graphs {
		// If it ends with our ID, it's us:
		if strings.HasSuffix(g.Title, fmt.Sprintf("(%s)", d.Id())){
			log.Printf("[DEBUG] Found matching graph. Start setting/saving state.")
			d.Set("dashboard_id", d.Get("dashboard_id"))
			// Save title to state, but strip ID
			d.Set("title", strings.Replace(g.Title, fmt.Sprintf(" (%s)", d.Id()), "", 1))
			d.Set("viz", g.Definition.Viz)

			// Create an empty schema to hold all the requests.
			request := &schema.Set{F: resourceDatadogRequestHash}

			for _, r := range g.Definition.Requests {
				m := make(map[string]interface{})

				if r.Query != "" {
					m["query"] = r.Query
				}

				m["stacked"] = r.Stacked

				request.Add(m)
			}

			d.Set("request", request)

			return nil

		}
	}

	// If we are still around we've not found ourselves. Set SetId to empty and Terraform will create the resource for us.
	d.SetId("")

	return nil
}

func resourceDatadogGraphUpdate(d *schema.ResourceData, meta interface{}) error {
	client := meta.(*datadog.Client)

	// Get the dashboard
	dashboard, err := client.GetDashboard(d.Get("dashboard_id").(int))

	if err != nil {
		return err
	}

	// Check if there are changes
	if d.HasChange("request") {
		graph_definition := datadog.Graph{}.Definition
		graph_requests := datadog.Graph{}.Definition.Requests
		graph_definition.Viz = d.Get("viz").(string)

		log.Printf("[DEBUG] Request has changed.")
		o, n := d.GetChange("request")
		ors := o.(*schema.Set).Difference(n.(*schema.Set))
		nrs := n.(*schema.Set).Difference(o.(*schema.Set))

		// Loop through all the old requests and delete any obsolete ones
		for _, request := range ors.List() {
			m := request.(map[string]interface{})

			// TODO: implement
			// Delete the query as it no longer exists in the config
			log.Printf("[DEBUG] Deleting graph query %s", m["query"].(string))
			log.Printf("[DEBUG] Deleting graph stacked %t", m["stacked"].(bool))

		}
		// Loop through all the new requests and append them
		for _, request := range nrs.List() {
			m := request.(map[string]interface{})

			// Add the request
			log.Printf("[DEBUG] Adding graph query %s", m["query"].(string))
			log.Printf("[DEBUG] Adding graph stacked %t", m["stacked"].(bool))
			graph_requests = append(graph_requests, GraphDefintionRequests{Query: m["query"].(string),
				Stacked: m["stacked"].(bool)})
		}

		// Add requests to the graph definition
		graph_definition.Requests = graph_requests
		title := d.Get("title").(string) + fmt.Sprintf(" (%s)", d.Id())
		the_graph := datadog.Graph{Title: title, Definition: graph_definition}

		dashboard.Graphs = append(dashboard.Graphs, the_graph) // Should be done for each
	}

	// Update/commit
	err = client.UpdateDashboard(dashboard)

	if err != nil {
		return err
	}

	return nil
}

func resourceDatadogGraphDelete(d *schema.ResourceData, meta interface{}) error {
	client := meta.(*datadog.Client)

	// Get the dashboard
	dashboard, err := client.GetDashboard(d.Get("dashboard_id").(int))

	if err != nil {
		return fmt.Errorf("Error retrieving associated dashboard: %s", err)
	}

	// Build a new slice of graphs, without the nominee to deleted.
	new_graphs := []datadog.Graph{}
	for _, r := range dashboard.Graphs {
		// TODO: Find our ID in the title
		if strings.HasSuffix(r.Title, fmt.Sprintf("(%s)", d.Id())) {
			//if r.Title == d.Get("title") {
			continue
		} else {
			new_graphs = append(new_graphs, r)
		}
	}

	dashboard.Graphs = new_graphs

	// Update/commit
	err = client.UpdateDashboard(dashboard)

	if err != nil {
		return err
	}

	err = resourceDatadogGraphRetrieve(d, meta)

	if err != nil {
		return err
	}

	return nil
}

func resourceDatadogRequestHash(v interface{}) int{
	var buf bytes.Buffer
	m := v.(map[string]interface{})

	if v, ok := m["query"];  ok {
		buf.WriteString(fmt.Sprintf("%s-", v.(string)))
	}

	if v, ok := m["stacked"];  ok {
		buf.WriteString(fmt.Sprintf("%t-", v.(bool)))
	}

	return hashcode.String(buf.String())
}
<|endoftext|>


<commit_before>package hypervisor

import (
	"github.com/golang/glog"
	"github.com/hyperhq/runv/hypervisor/types"
)

// reportVmRun() send report to daemon, notify about that:
//    1. Vm has been running.
//    2. Init is ready for accepting commands
func (ctx *VmContext) reportVmRun() {
	ctx.client <- &types.VmResponse{
		VmId:  ctx.Id,
		Code:  types.E_VM_RUNNING,
		Cause: "Vm runs",
	}
}

// reportVmShutdown() send report to daemon, notify about that:
//    1. Vm has been shutdown
func (ctx *VmContext) reportVmShutdown() {
	defer func() {
		err := recover()
		if err != nil {
			glog.Warning("panic during send shutdown message to channel")
		}
	}()
	ctx.client <- &types.VmResponse{
		VmId:  ctx.Id,
		Code:  types.E_VM_SHUTDOWN,
		Cause: "VM shut down",
	}
}

func (ctx *VmContext) reportPodRunning(msg string, data interface{}) {
	ctx.client <- &types.VmResponse{
		VmId:  ctx.Id,
		Code:  types.E_POD_RUNNING,
		Cause: msg,
		Data:  data,
	}
}

func (ctx *VmContext) reportProcessFinished(code int, result *types.ProcessFinished) {
	ctx.client <- &types.VmResponse{
		VmId:  ctx.Id,
		Code:  code,
		Cause: "container finished",
		Data:  result,
	}
}

func (ctx *VmContext) reportSuccess(msg string, data interface{}) {
	ctx.client <- &types.VmResponse{
		VmId:  ctx.Id,
		Code:  types.E_OK,
		Cause: msg,
		Data:  data,
	}
}

func (ctx *VmContext) reportBusy(msg string) {
	ctx.client <- &types.VmResponse{
		VmId:  ctx.Id,
		Code:  types.E_BUSY,
		Cause: msg,
	}
}

// reportBadRequest send report to daemon, notify about that:
//   1. anything wrong in the request, such as json format, slice length, etc.
func (ctx *VmContext) reportBadRequest(cause string) {
	ctx.client <- &types.VmResponse{
		VmId:  ctx.Id,
		Code:  types.E_BAD_REQUEST,
		Cause: cause,
	}
}

// reportUnexpectedRequest send report to daemon, notify about that:
//   1. unexpected event in current state
func (ctx *VmContext) reportUnexpectedRequest(ev VmEvent, state string) {
	ctx.client <- &types.VmResponse{
		VmId:  ctx.Id,
		Code:  types.E_UNEXPECTED,
		Reply: ev,
		Cause: "unexpected event during " + state,
	}
}

// reportVmFault send report to daemon, notify about that:
//   1. vm op failed due to some reason described in `cause`
func (ctx *VmContext) reportVmFault(cause string) {
	ctx.client <- &types.VmResponse{
		VmId:  ctx.Id,
		Code:  types.E_FAILED,
		Cause: cause,
	}
}

func (ctx *VmContext) reportPodStats(ev VmEvent) {
	response := types.VmResponse{
		VmId:  ctx.Id,
		Code:  types.E_POD_STATS,
		Cause: "",
		Reply: ev,
		Data:  nil,
	}

	stats, err := ctx.DCtx.Stats(ctx)
	if err != nil {
		response.Cause = "Get pod stats failed"
	} else {
		response.Data = stats
	}

	ctx.client <- &response
}
<commit_msg>remove unused reportBadRequest()<commit_after>package hypervisor

import (
	"github.com/golang/glog"
	"github.com/hyperhq/runv/hypervisor/types"
)

// reportVmRun() send report to daemon, notify about that:
//    1. Vm has been running.
//    2. Init is ready for accepting commands
func (ctx *VmContext) reportVmRun() {
	ctx.client <- &types.VmResponse{
		VmId:  ctx.Id,
		Code:  types.E_VM_RUNNING,
		Cause: "Vm runs",
	}
}

// reportVmShutdown() send report to daemon, notify about that:
//    1. Vm has been shutdown
func (ctx *VmContext) reportVmShutdown() {
	defer func() {
		err := recover()
		if err != nil {
			glog.Warning("panic during send shutdown message to channel")
		}
	}()
	ctx.client <- &types.VmResponse{
		VmId:  ctx.Id,
		Code:  types.E_VM_SHUTDOWN,
		Cause: "VM shut down",
	}
}

func (ctx *VmContext) reportPodRunning(msg string, data interface{}) {
	ctx.client <- &types.VmResponse{
		VmId:  ctx.Id,
		Code:  types.E_POD_RUNNING,
		Cause: msg,
		Data:  data,
	}
}

func (ctx *VmContext) reportProcessFinished(code int, result *types.ProcessFinished) {
	ctx.client <- &types.VmResponse{
		VmId:  ctx.Id,
		Code:  code,
		Cause: "container finished",
		Data:  result,
	}
}

func (ctx *VmContext) reportSuccess(msg string, data interface{}) {
	ctx.client <- &types.VmResponse{
		VmId:  ctx.Id,
		Code:  types.E_OK,
		Cause: msg,
		Data:  data,
	}
}

func (ctx *VmContext) reportBusy(msg string) {
	ctx.client <- &types.VmResponse{
		VmId:  ctx.Id,
		Code:  types.E_BUSY,
		Cause: msg,
	}
}

// reportUnexpectedRequest send report to daemon, notify about that:
//   1. unexpected event in current state
func (ctx *VmContext) reportUnexpectedRequest(ev VmEvent, state string) {
	ctx.client <- &types.VmResponse{
		VmId:  ctx.Id,
		Code:  types.E_UNEXPECTED,
		Reply: ev,
		Cause: "unexpected event during " + state,
	}
}

// reportVmFault send report to daemon, notify about that:
//   1. vm op failed due to some reason described in `cause`
func (ctx *VmContext) reportVmFault(cause string) {
	ctx.client <- &types.VmResponse{
		VmId:  ctx.Id,
		Code:  types.E_FAILED,
		Cause: cause,
	}
}

func (ctx *VmContext) reportPodStats(ev VmEvent) {
	response := types.VmResponse{
		VmId:  ctx.Id,
		Code:  types.E_POD_STATS,
		Cause: "",
		Reply: ev,
		Data:  nil,
	}

	stats, err := ctx.DCtx.Stats(ctx)
	if err != nil {
		response.Cause = "Get pod stats failed"
	} else {
		response.Data = stats
	}

	ctx.client <- &response
}
<|endoftext|>


<commit_before>/*
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements.  See the NOTICE file
distributed with this work for additional information
regarding copyright ownership.  The ASF licenses this file
to you 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 crypto

import (
	obcca "github.com/openblockchain/obc-peer/obc-ca/protos"

	"crypto/ecdsa"
	"crypto/rand"
	"crypto/tls"
	"crypto/x509"
	"errors"
	"github.com/golang/protobuf/proto"
	"github.com/openblockchain/obc-peer/openchain/crypto/utils"
	"github.com/openblockchain/obc-peer/openchain/util"
	"golang.org/x/net/context"
	"google.golang.org/grpc"
	"google.golang.org/grpc/credentials"
	"google/protobuf"
	"time"
)

func (node *nodeImpl) initTLS() error {
	node.log.Debug("Initiliazing TLS...")

	pem, err := node.ks.loadExternalCert(node.conf.getTLSCACertsExternalPath())
	if err != nil {
		node.log.Error("Failed loading TLSCA certificates chain [%s].", err.Error())

		return err
	}

	node.tlsCertPool = x509.NewCertPool()
	ok := node.tlsCertPool.AppendCertsFromPEM(pem)
	if !ok {
		node.log.Error("Failed appending TLSCA certificates chain.")

		return errors.New("Failed appending TLSCA certificates chain.")
	}

	return nil

}

func (node *nodeImpl) retrieveTLSCertificate(id, affiliation string) error {
	key, tlsCertRaw, err := node.getTLSCertificateFromTLSCA(id, affiliation)
	if err != nil {
		node.log.Error("Failed getting tls certificate [id=%s] %s", id, err)

		return err
	}
	node.log.Debug("TLS Cert [%s]", utils.EncodeBase64(tlsCertRaw))

	node.log.Info("Storing TLS key and certificate for user [%s]...", id)

	// Store tls key.
	if err := node.ks.storePrivateKeyInClear(node.conf.getTLSKeyFilename(), key); err != nil {
		node.log.Error("Failed storing tls key [id=%s]: %s", id, err)
		return err
	}

	// Store tls cert
	if err := node.ks.storeCert(node.conf.getTLSCertFilename(), tlsCertRaw); err != nil {
		node.log.Error("Failed storing tls certificate [id=%s]: %s", id, err)
		return err
	}

	return nil
}

func (node *nodeImpl) loadTLSCertificate() error {
	node.log.Debug("Loading tls certificate...")

	cert, _, err := node.ks.loadCertX509AndDer(node.conf.getTLSCertFilename())
	if err != nil {
		node.log.Error("Failed parsing tls certificate [%s].", err.Error())

		return err
	}
	node.tlsCert = cert

	return nil
}

func (node *nodeImpl) loadTLSCACertsChain() error {
	node.log.Debug("Loading TLSCA certificates chain...")

	pem, err := node.ks.loadExternalCert(node.conf.getTLSCACertsExternalPath())
	if err != nil {
		node.log.Error("Failed loading TLSCA certificates chain [%s].", err.Error())

		return err
	}

	ok := node.tlsCertPool.AppendCertsFromPEM(pem)
	if !ok {
		node.log.Error("Failed appending TLSCA certificates chain.")

		return errors.New("Failed appending TLSCA certificates chain.")
	}

	return nil
}

func (node *nodeImpl) getTLSCertificateFromTLSCA(id, affiliation string) (interface{}, []byte, error) {
	node.log.Info("getTLSCertificate...")

	priv, err := utils.NewECDSAKey()

	if err != nil {
		node.log.Error("Failed generating key: %s", err)

		return nil, nil, err
	}

	uuid, err := util.GenerateUUID()
	if err != nil {
		node.log.Error("Failed generating uuid: %s", err)

		return nil, nil, err
	}

	// Prepare the request
	pubraw, _ := x509.MarshalPKIXPublicKey(&priv.PublicKey)
	now := time.Now()
	timestamp := google_protobuf.Timestamp{int64(now.Second()), int32(now.Nanosecond())}

	req := &obcca.TLSCertCreateReq{
		&timestamp,
		&obcca.Identity{Id: id + "-" + uuid},
		&obcca.PublicKey{
			Type: obcca.CryptoType_ECDSA,
			Key:  pubraw,
		}, nil}
	rawreq, _ := proto.Marshal(req)
	r, s, err := ecdsa.Sign(rand.Reader, priv, utils.Hash(rawreq))
	if err != nil {
		panic(err)
	}
	R, _ := r.MarshalText()
	S, _ := s.MarshalText()
	req.Sig = &obcca.Signature{obcca.CryptoType_ECDSA, R, S}

	pbCert, err := node.callTLSCACreateCertificate(context.Background(), req)
	if err != nil {
		node.log.Error("Failed requesting tls certificate: %s", err)

		return nil, nil, err
	}

	node.log.Info("Verifing tls certificate...")

	tlsCert, err := utils.DERToX509Certificate(pbCert.Cert.Cert)
	certPK := tlsCert.PublicKey.(*ecdsa.PublicKey)
	utils.VerifySignCapability(priv, certPK)

	node.log.Info("Verifing tls certificate...done!")

	return priv, pbCert.Cert.Cert, nil
}

func (node *nodeImpl) getClientConn(address string, serverName string) (*grpc.ClientConn, error) {
	node.log.Debug("Getting Client Connection to [%s]...", serverName)

	var conn *grpc.ClientConn
	var err error

	if node.conf.isTLSEnabled() {
		node.log.Debug("TLS enabled...")

		// setup tls options
		var opts []grpc.DialOption
		config := tls.Config{
			InsecureSkipVerify: false,
			RootCAs:            node.tlsCertPool,
			ServerName:         serverName,
		}
		if node.conf.isTLSClientAuthEnabled() {

		}

		creds := credentials.NewTLS(&config)
		opts = append(opts, grpc.WithTransportCredentials(creds))
		opts = append(opts, grpc.WithTimeout(time.Second*3))

		conn, err = grpc.Dial(address, opts...)
	} else {
		node.log.Debug("TLS disabled...")

		var opts []grpc.DialOption
		opts = append(opts, grpc.WithInsecure())
		opts = append(opts, grpc.WithTimeout(time.Second*3))

		conn, err = grpc.Dial(address, opts...)
	}

	if err != nil {
		node.log.Error("Failed dailing in [%s].", err.Error())

		return nil, err
	}

	node.log.Debug("Getting Client Connection to [%s]...done", serverName)

	return conn, nil
}

func (node *nodeImpl) getTLSCAClient() (*grpc.ClientConn, obcca.TLSCAPClient, error) {
	node.log.Debug("Getting TLSCA client...")

	conn, err := node.getClientConn(node.conf.getTLSCAPAddr(), node.conf.getTLSCAServerName())
	if err != nil {
		node.log.Error("Failed getting client connection: [%s]", err)
	}

	client := obcca.NewTLSCAPClient(conn)

	node.log.Debug("Getting TLSCA client...done")

	return conn, client, nil
}

func (node *nodeImpl) callTLSCACreateCertificate(ctx context.Context, in *obcca.TLSCertCreateReq, opts ...grpc.CallOption) (*obcca.TLSCertCreateResp, error) {
	conn, tlscaP, err := node.getTLSCAClient()
	if err != nil {
		node.log.Error("Failed dialing in: %s", err)

		return nil, err
	}
	defer conn.Close()

	resp, err := tlscaP.CreateCertificate(ctx, in, opts...)
	if err != nil {
		node.log.Error("Failed requesting tls certificate: %s", err)

		return nil, err
	}

	return resp, nil
}
<commit_msg>FIX: if TLS is disabled, the tls root cert must not loaded.<commit_after>/*
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements.  See the NOTICE file
distributed with this work for additional information
regarding copyright ownership.  The ASF licenses this file
to you 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 crypto

import (
	obcca "github.com/openblockchain/obc-peer/obc-ca/protos"

	"crypto/ecdsa"
	"crypto/rand"
	"crypto/tls"
	"crypto/x509"
	"errors"
	"github.com/golang/protobuf/proto"
	"github.com/openblockchain/obc-peer/openchain/crypto/utils"
	"github.com/openblockchain/obc-peer/openchain/util"
	"golang.org/x/net/context"
	"google.golang.org/grpc"
	"google.golang.org/grpc/credentials"
	"google/protobuf"
	"time"
)

func (node *nodeImpl) initTLS() error {
	node.log.Debug("Initiliazing TLS...")

	if node.conf.isTLSEnabled() {
		pem, err := node.ks.loadExternalCert(node.conf.getTLSCACertsExternalPath())
		if err != nil {
			node.log.Error("Failed loading TLSCA certificates chain [%s].", err.Error())

			return err
		}

		node.tlsCertPool = x509.NewCertPool()
		ok := node.tlsCertPool.AppendCertsFromPEM(pem)
		if !ok {
			node.log.Error("Failed appending TLSCA certificates chain.")

			return errors.New("Failed appending TLSCA certificates chain.")
		}
		node.log.Debug("Initiliazing TLS...Done")
	} else {
		node.log.Debug("Initiliazing TLS...Disabled!!!")
	}

	return nil
}

func (node *nodeImpl) retrieveTLSCertificate(id, affiliation string) error {
	key, tlsCertRaw, err := node.getTLSCertificateFromTLSCA(id, affiliation)
	if err != nil {
		node.log.Error("Failed getting tls certificate [id=%s] %s", id, err)

		return err
	}
	node.log.Debug("TLS Cert [%s]", utils.EncodeBase64(tlsCertRaw))

	node.log.Info("Storing TLS key and certificate for user [%s]...", id)

	// Store tls key.
	if err := node.ks.storePrivateKeyInClear(node.conf.getTLSKeyFilename(), key); err != nil {
		node.log.Error("Failed storing tls key [id=%s]: %s", id, err)
		return err
	}

	// Store tls cert
	if err := node.ks.storeCert(node.conf.getTLSCertFilename(), tlsCertRaw); err != nil {
		node.log.Error("Failed storing tls certificate [id=%s]: %s", id, err)
		return err
	}

	return nil
}

func (node *nodeImpl) loadTLSCertificate() error {
	node.log.Debug("Loading tls certificate...")

	cert, _, err := node.ks.loadCertX509AndDer(node.conf.getTLSCertFilename())
	if err != nil {
		node.log.Error("Failed parsing tls certificate [%s].", err.Error())

		return err
	}
	node.tlsCert = cert

	return nil
}

func (node *nodeImpl) loadTLSCACertsChain() error {
	if node.conf.isTLSEnabled() {
		node.log.Debug("Loading TLSCA certificates chain...")

		pem, err := node.ks.loadExternalCert(node.conf.getTLSCACertsExternalPath())
		if err != nil {
			node.log.Error("Failed loading TLSCA certificates chain [%s].", err.Error())

			return err
		}

		ok := node.tlsCertPool.AppendCertsFromPEM(pem)
		if !ok {
			node.log.Error("Failed appending TLSCA certificates chain.")

			return errors.New("Failed appending TLSCA certificates chain.")
		}

		node.log.Debug("Loading TLSCA certificates chain...done")

		return nil
	} else {
		node.log.Debug("TLS is disabled!!!")
	}

	return nil
}

func (node *nodeImpl) getTLSCertificateFromTLSCA(id, affiliation string) (interface{}, []byte, error) {
	node.log.Info("getTLSCertificate...")

	priv, err := utils.NewECDSAKey()

	if err != nil {
		node.log.Error("Failed generating key: %s", err)

		return nil, nil, err
	}

	uuid, err := util.GenerateUUID()
	if err != nil {
		node.log.Error("Failed generating uuid: %s", err)

		return nil, nil, err
	}

	// Prepare the request
	pubraw, _ := x509.MarshalPKIXPublicKey(&priv.PublicKey)
	now := time.Now()
	timestamp := google_protobuf.Timestamp{int64(now.Second()), int32(now.Nanosecond())}

	req := &obcca.TLSCertCreateReq{
		&timestamp,
		&obcca.Identity{Id: id + "-" + uuid},
		&obcca.PublicKey{
			Type: obcca.CryptoType_ECDSA,
			Key:  pubraw,
		}, nil}
	rawreq, _ := proto.Marshal(req)
	r, s, err := ecdsa.Sign(rand.Reader, priv, utils.Hash(rawreq))
	if err != nil {
		panic(err)
	}
	R, _ := r.MarshalText()
	S, _ := s.MarshalText()
	req.Sig = &obcca.Signature{obcca.CryptoType_ECDSA, R, S}

	pbCert, err := node.callTLSCACreateCertificate(context.Background(), req)
	if err != nil {
		node.log.Error("Failed requesting tls certificate: %s", err)

		return nil, nil, err
	}

	node.log.Info("Verifing tls certificate...")

	tlsCert, err := utils.DERToX509Certificate(pbCert.Cert.Cert)
	certPK := tlsCert.PublicKey.(*ecdsa.PublicKey)
	utils.VerifySignCapability(priv, certPK)

	node.log.Info("Verifing tls certificate...done!")

	return priv, pbCert.Cert.Cert, nil
}

func (node *nodeImpl) getClientConn(address string, serverName string) (*grpc.ClientConn, error) {
	node.log.Debug("Getting Client Connection to [%s]...", serverName)

	var conn *grpc.ClientConn
	var err error

	if node.conf.isTLSEnabled() {
		node.log.Debug("TLS enabled...")

		// setup tls options
		var opts []grpc.DialOption
		config := tls.Config{
			InsecureSkipVerify: false,
			RootCAs:            node.tlsCertPool,
			ServerName:         serverName,
		}
		if node.conf.isTLSClientAuthEnabled() {

		}

		creds := credentials.NewTLS(&config)
		opts = append(opts, grpc.WithTransportCredentials(creds))
		opts = append(opts, grpc.WithTimeout(time.Second*3))

		conn, err = grpc.Dial(address, opts...)
	} else {
		node.log.Debug("TLS disabled...")

		var opts []grpc.DialOption
		opts = append(opts, grpc.WithInsecure())
		opts = append(opts, grpc.WithTimeout(time.Second*3))

		conn, err = grpc.Dial(address, opts...)
	}

	if err != nil {
		node.log.Error("Failed dailing in [%s].", err.Error())

		return nil, err
	}

	node.log.Debug("Getting Client Connection to [%s]...done", serverName)

	return conn, nil
}

func (node *nodeImpl) getTLSCAClient() (*grpc.ClientConn, obcca.TLSCAPClient, error) {
	node.log.Debug("Getting TLSCA client...")

	conn, err := node.getClientConn(node.conf.getTLSCAPAddr(), node.conf.getTLSCAServerName())
	if err != nil {
		node.log.Error("Failed getting client connection: [%s]", err)
	}

	client := obcca.NewTLSCAPClient(conn)

	node.log.Debug("Getting TLSCA client...done")

	return conn, client, nil
}

func (node *nodeImpl) callTLSCACreateCertificate(ctx context.Context, in *obcca.TLSCertCreateReq, opts ...grpc.CallOption) (*obcca.TLSCertCreateResp, error) {
	conn, tlscaP, err := node.getTLSCAClient()
	if err != nil {
		node.log.Error("Failed dialing in: %s", err)

		return nil, err
	}
	defer conn.Close()

	resp, err := tlscaP.CreateCertificate(ctx, in, opts...)
	if err != nil {
		node.log.Error("Failed requesting tls certificate: %s", err)

		return nil, err
	}

	return resp, nil
}
<|endoftext|>


<commit_before>package search

import (
	_ "embed"
	"log"
	"strings"

	"github.com/dchest/jsmin"
)

//go:embed ui/stemmer.min.js
var stemmer string

//go:embed ui/search.js
var mainScript string

func GetSearchScript(searchIndexURL string) string {
	out := stemmer + strings.ReplaceAll(mainScript, "__KKR_SEARCH_INDEX_URL__", searchIndexURL)
	minified, err := jsmin.Minify([]byte(out))
	if err == nil {
		log.Printf("Failed to minify search-script, continuing with unminified")
		out = string(minified)
	}
	return out
}
<commit_msg>Fix error logging in search script minification<commit_after>package search

import (
	_ "embed"
	"log"
	"strings"

	"github.com/dchest/jsmin"
)

//go:embed ui/stemmer.min.js
var stemmer string

//go:embed ui/search.js
var mainScript string

func GetSearchScript(searchIndexURL string) string {
	out := stemmer + strings.ReplaceAll(mainScript, "__KKR_SEARCH_INDEX_URL__", searchIndexURL)
	minified, err := jsmin.Minify([]byte(out))
	if err != nil {
		log.Printf("Failed to minify search-script, continuing with unminified")
	} else {
		out = string(minified)
	}
	return out
}
<|endoftext|>


<commit_before>/*
Copyright 2016 The Kubernetes Authors.

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

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

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

package workqueue

// RateLimitingInterface is an interface that rate limits items being added to the queue.
type RateLimitingInterface interface {
	DelayingInterface

	// AddRateLimited adds an item to the workqueue after the rate limiter says its ok
	AddRateLimited(item interface{})

	// Forget indicates that an item is finished being retried.  Doesn't matter whether its for perm failing
	// or for success, we'll stop the rate limiter from tracking it.  This only clears the `rateLimiter`, you
	// still have to call `Done` on the queue.
	Forget(item interface{})

	// NumRequeues returns back how many times the item was requeued
	NumRequeues(item interface{}) int
}

// NewRateLimitingQueue constructs a new workqueue with rateLimited queuing ability
// Remember to call Forget!  If you don't, you may end up tracking failures forever.
func NewRateLimitingQueue(rateLimiter RateLimiter) RateLimitingInterface {
	return &rateLimitingType{
		DelayingInterface: NewDelayingQueue(),
		rateLimiter:       rateLimiter,
	}
}

func NewNamedRateLimitingQueue(rateLimiter RateLimiter, name string) RateLimitingInterface {
	return &rateLimitingType{
		DelayingInterface: NewNamedDelayingQueue(name),
		rateLimiter:       rateLimiter,
	}
}

// rateLimitingType wraps an Interface and provides rateLimited re-enquing
type rateLimitingType struct {
	DelayingInterface

	rateLimiter RateLimiter
}

// AddRateLimited AddAfter's the item based on the time when the rate limiter says its ok
func (q *rateLimitingType) AddRateLimited(item interface{}) {
	q.DelayingInterface.AddAfter(item, q.rateLimiter.When(item))
}

func (q *rateLimitingType) NumRequeues(item interface{}) int {
	return q.rateLimiter.NumRequeues(item)
}

func (q *rateLimitingType) Forget(item interface{}) {
	q.rateLimiter.Forget(item)
}
<commit_msg>fix syntax error:'its'<commit_after>/*
Copyright 2016 The Kubernetes Authors.

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

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

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

package workqueue

// RateLimitingInterface is an interface that rate limits items being added to the queue.
type RateLimitingInterface interface {
	DelayingInterface

	// AddRateLimited adds an item to the workqueue after the rate limiter says it's ok
	AddRateLimited(item interface{})

	// Forget indicates that an item is finished being retried.  Doesn't matter whether it's for perm failing
	// or for success, we'll stop the rate limiter from tracking it.  This only clears the `rateLimiter`, you
	// still have to call `Done` on the queue.
	Forget(item interface{})

	// NumRequeues returns back how many times the item was requeued
	NumRequeues(item interface{}) int
}

// NewRateLimitingQueue constructs a new workqueue with rateLimited queuing ability
// Remember to call Forget!  If you don't, you may end up tracking failures forever.
func NewRateLimitingQueue(rateLimiter RateLimiter) RateLimitingInterface {
	return &rateLimitingType{
		DelayingInterface: NewDelayingQueue(),
		rateLimiter:       rateLimiter,
	}
}

func NewNamedRateLimitingQueue(rateLimiter RateLimiter, name string) RateLimitingInterface {
	return &rateLimitingType{
		DelayingInterface: NewNamedDelayingQueue(name),
		rateLimiter:       rateLimiter,
	}
}

// rateLimitingType wraps an Interface and provides rateLimited re-enquing
type rateLimitingType struct {
	DelayingInterface

	rateLimiter RateLimiter
}

// AddRateLimited AddAfter's the item based on the time when the rate limiter says it's ok
func (q *rateLimitingType) AddRateLimited(item interface{}) {
	q.DelayingInterface.AddAfter(item, q.rateLimiter.When(item))
}

func (q *rateLimitingType) NumRequeues(item interface{}) int {
	return q.rateLimiter.NumRequeues(item)
}

func (q *rateLimitingType) Forget(item interface{}) {
	q.rateLimiter.Forget(item)
}
<|endoftext|>