<commit_before>package controlplane

import (
	"context"

	"github.com/openshift/origin/pkg/monitor"

	"github.com/openshift/origin/pkg/monitor/backenddisruption"

	"k8s.io/client-go/rest"
)

func StartAllAPIMonitoring(ctx context.Context, m monitor.Recorder, clusterConfig *rest.Config) error {
	if err := startKubeAPIMonitoringWithNewConnections(ctx, m, clusterConfig); err != nil {
		return err
	}
	if err := startOpenShiftAPIMonitoringWithNewConnections(ctx, m, clusterConfig); err != nil {
		return err
	}
	if err := startOAuthAPIMonitoringWithNewConnections(ctx, m, clusterConfig); err != nil {
		return err
	}
	if err := startKubeAPIMonitoringWithConnectionReuse(ctx, m, clusterConfig); err != nil {
		return err
	}
	if err := startOpenShiftAPIMonitoringWithConnectionReuse(ctx, m, clusterConfig); err != nil {
		return err
	}
	if err := startOAuthAPIMonitoringWithConnectionReuse(ctx, m, clusterConfig); err != nil {
		return err
	}
	return nil
}

func startKubeAPIMonitoringWithNewConnections(ctx context.Context, m monitor.Recorder, clusterConfig *rest.Config) error {
	backendSampler, err := createKubeAPIMonitoringWithNewConnections(clusterConfig)
	if err != nil {
		return err
	}
	return backendSampler.StartEndpointMonitoring(ctx, m, nil)
}

func startOpenShiftAPIMonitoringWithNewConnections(ctx context.Context, m monitor.Recorder, clusterConfig *rest.Config) error {
	backendSampler, err := createOpenShiftAPIMonitoringWithNewConnections(clusterConfig)
	if err != nil {
		return err
	}
	return backendSampler.StartEndpointMonitoring(ctx, m, nil)
}

func startOAuthAPIMonitoringWithNewConnections(ctx context.Context, m monitor.Recorder, clusterConfig *rest.Config) error {
	backendSampler, err := createOAuthAPIMonitoringWithNewConnections(clusterConfig)
	if err != nil {
		return err
	}
	return backendSampler.StartEndpointMonitoring(ctx, m, nil)
}

func startKubeAPIMonitoringWithConnectionReuse(ctx context.Context, m monitor.Recorder, clusterConfig *rest.Config) error {
	backendSampler, err := createKubeAPIMonitoringWithConnectionReuse(clusterConfig)
	if err != nil {
		return err
	}
	return backendSampler.StartEndpointMonitoring(ctx, m, nil)
}

func startOpenShiftAPIMonitoringWithConnectionReuse(ctx context.Context, m monitor.Recorder, clusterConfig *rest.Config) error {
	backendSampler, err := createOpenShiftAPIMonitoringWithConnectionReuse(clusterConfig)
	if err != nil {
		return err
	}
	return backendSampler.StartEndpointMonitoring(ctx, m, nil)
}

func startOAuthAPIMonitoringWithConnectionReuse(ctx context.Context, m monitor.Recorder, clusterConfig *rest.Config) error {
	backendSampler, err := createOAuthAPIMonitoringWithConnectionReuse(clusterConfig)
	if err != nil {
		return err
	}
	return backendSampler.StartEndpointMonitoring(ctx, m, nil)
}

func createKubeAPIMonitoringWithNewConnections(clusterConfig *rest.Config) (*backenddisruption.BackendSampler, error) {
	return createAPIServerBackendSampler(clusterConfig, "kube-api", "/api/v1/namespaces/default", backenddisruption.NewConnectionType)
}

func createOpenShiftAPIMonitoringWithNewConnections(clusterConfig *rest.Config) (*backenddisruption.BackendSampler, error) {
	// this request should never 404, but should be empty/small
	return createAPIServerBackendSampler(clusterConfig, "openshift-api", "/apis/image.openshift.io/v1/namespaces/default/imagestreams", backenddisruption.NewConnectionType)
}

func createOAuthAPIMonitoringWithNewConnections(clusterConfig *rest.Config) (*backenddisruption.BackendSampler, error) {
	// this should be relatively small and should not ever 404
	return createAPIServerBackendSampler(clusterConfig, "oauth-api", "/apis/oauth.openshift.io/v1/oauthclients", backenddisruption.NewConnectionType)
}

func createKubeAPIMonitoringWithConnectionReuse(clusterConfig *rest.Config) (*backenddisruption.BackendSampler, error) {
	// default gets auto-created, so this should always exist
	return createAPIServerBackendSampler(clusterConfig, "kube-api", "/api/v1/namespaces/default", backenddisruption.ReusedConnectionType)
}

func createOpenShiftAPIMonitoringWithConnectionReuse(clusterConfig *rest.Config) (*backenddisruption.BackendSampler, error) {
	// this request should never 404, but should be empty/small
	return createAPIServerBackendSampler(clusterConfig, "openshift-api", "/apis/image.openshift.io/v1/namespaces/default/imagestreams", backenddisruption.ReusedConnectionType)
}

func createOAuthAPIMonitoringWithConnectionReuse(clusterConfig *rest.Config) (*backenddisruption.BackendSampler, error) {
	// this should be relatively small and should not ever 404
	return createAPIServerBackendSampler(clusterConfig, "oauth-api", "/apis/oauth.openshift.io/v1/oauthclients", backenddisruption.ReusedConnectionType)
}

func createAPIServerBackendSampler(clusterConfig *rest.Config, disruptionBackendName, url string, connectionType backenddisruption.BackendConnectionType) (*backenddisruption.BackendSampler, error) {
	// default gets auto-created, so this should always exist
	backendSampler, err := backenddisruption.NewAPIServerBackend(clusterConfig, disruptionBackendName, url, connectionType)
	if err != nil {
		return nil, err
	}

	return backendSampler, nil
}
<commit_msg>adds new test to the API monitor<commit_after>package controlplane

import (
	"context"

	"github.com/openshift/origin/pkg/monitor"

	"github.com/openshift/origin/pkg/monitor/backenddisruption"

	"k8s.io/client-go/rest"
)

func StartAllAPIMonitoring(ctx context.Context, m monitor.Recorder, clusterConfig *rest.Config) error {
	if err := startKubeAPIMonitoringWithNewConnections(ctx, m, clusterConfig); err != nil {
		return err
	}
	if err := startKubeAPIMonitoringWithNewConnectionsAgainstAPICache(ctx, m, clusterConfig); err != nil {
		return err
	}
	if err := startOpenShiftAPIMonitoringWithNewConnections(ctx, m, clusterConfig); err != nil {
		return err
	}
	if err := startOpenShiftAPIMonitoringWithNewConnectionsAgainstAPICache(ctx, m, clusterConfig); err != nil {
		return err
	}
	if err := startOAuthAPIMonitoringWithNewConnections(ctx, m, clusterConfig); err != nil {
		return err
	}
	if err := startOAuthAPIMonitoringWithNewConnectionsAgainstAPICache(ctx, m, clusterConfig); err != nil {
		return err
	}
	if err := startKubeAPIMonitoringWithConnectionReuse(ctx, m, clusterConfig); err != nil {
		return err
	}
	if err := startKubeAPIMonitoringWithConnectionReuseAgainstAPICache(ctx, m, clusterConfig); err != nil {
		return err
	}
	if err := startOpenShiftAPIMonitoringWithConnectionReuse(ctx, m, clusterConfig); err != nil {
		return err
	}
	if err := startOpenShiftAPIMonitoringWithConnectionReuseAgainstAPICache(ctx, m, clusterConfig); err != nil {
		return err
	}
	if err := startOAuthAPIMonitoringWithConnectionReuse(ctx, m, clusterConfig); err != nil {
		return err
	}
	if err := startOAuthAPIMonitoringWithConnectionReuseAgainstAPICache(ctx, m, clusterConfig); err != nil {
		return err
	}
	return nil
}

func startKubeAPIMonitoringWithNewConnections(ctx context.Context, m monitor.Recorder, clusterConfig *rest.Config) error {
	backendSampler, err := createKubeAPIMonitoringWithNewConnections(clusterConfig)
	if err != nil {
		return err
	}
	return backendSampler.StartEndpointMonitoring(ctx, m, nil)
}

func startKubeAPIMonitoringWithNewConnectionsAgainstAPICache(ctx context.Context, m monitor.Recorder, clusterConfig *rest.Config) error {
	backendSampler, err := createKubeAPIMonitoringWithNewConnectionsAgainstAPICache(clusterConfig)
	if err != nil {
		return err
	}
	return backendSampler.StartEndpointMonitoring(ctx, m, nil)
}

func startOpenShiftAPIMonitoringWithNewConnections(ctx context.Context, m monitor.Recorder, clusterConfig *rest.Config) error {
	backendSampler, err := createOpenShiftAPIMonitoringWithNewConnections(clusterConfig)
	if err != nil {
		return err
	}
	return backendSampler.StartEndpointMonitoring(ctx, m, nil)
}

func startOpenShiftAPIMonitoringWithNewConnectionsAgainstAPICache(ctx context.Context, m monitor.Recorder, clusterConfig *rest.Config) error {
	backendSampler, err := createOpenShiftAPIMonitoringWithNewConnectionsAgainstAPICache(clusterConfig)
	if err != nil {
		return err
	}
	return backendSampler.StartEndpointMonitoring(ctx, m, nil)
}

func startOAuthAPIMonitoringWithNewConnections(ctx context.Context, m monitor.Recorder, clusterConfig *rest.Config) error {
	backendSampler, err := createOAuthAPIMonitoringWithNewConnections(clusterConfig)
	if err != nil {
		return err
	}
	return backendSampler.StartEndpointMonitoring(ctx, m, nil)
}

func startOAuthAPIMonitoringWithNewConnectionsAgainstAPICache(ctx context.Context, m monitor.Recorder, clusterConfig *rest.Config) error {
	backendSampler, err := createOAuthAPIMonitoringWithNewConnectionsAgainstAPICache(clusterConfig)
	if err != nil {
		return err
	}
	return backendSampler.StartEndpointMonitoring(ctx, m, nil)
}

func startKubeAPIMonitoringWithConnectionReuse(ctx context.Context, m monitor.Recorder, clusterConfig *rest.Config) error {
	backendSampler, err := createKubeAPIMonitoringWithConnectionReuse(clusterConfig)
	if err != nil {
		return err
	}
	return backendSampler.StartEndpointMonitoring(ctx, m, nil)
}

func startKubeAPIMonitoringWithConnectionReuseAgainstAPICache(ctx context.Context, m monitor.Recorder, clusterConfig *rest.Config) error {
	backendSampler, err := createKubeAPIMonitoringWithConnectionReuseAgainstAPICache(clusterConfig)
	if err != nil {
		return err
	}
	return backendSampler.StartEndpointMonitoring(ctx, m, nil)
}

func startOpenShiftAPIMonitoringWithConnectionReuse(ctx context.Context, m monitor.Recorder, clusterConfig *rest.Config) error {
	backendSampler, err := createOpenShiftAPIMonitoringWithConnectionReuse(clusterConfig)
	if err != nil {
		return err
	}
	return backendSampler.StartEndpointMonitoring(ctx, m, nil)
}

func startOpenShiftAPIMonitoringWithConnectionReuseAgainstAPICache(ctx context.Context, m monitor.Recorder, clusterConfig *rest.Config) error {
	backendSampler, err := createOpenShiftAPIMonitoringWithConnectionReuseAgainstAPICache(clusterConfig)
	if err != nil {
		return err
	}
	return backendSampler.StartEndpointMonitoring(ctx, m, nil)
}

func startOAuthAPIMonitoringWithConnectionReuse(ctx context.Context, m monitor.Recorder, clusterConfig *rest.Config) error {
	backendSampler, err := createOAuthAPIMonitoringWithConnectionReuse(clusterConfig)
	if err != nil {
		return err
	}
	return backendSampler.StartEndpointMonitoring(ctx, m, nil)
}

func startOAuthAPIMonitoringWithConnectionReuseAgainstAPICache(ctx context.Context, m monitor.Recorder, clusterConfig *rest.Config) error {
	backendSampler, err := createOAuthAPIMonitoringWithConnectionReuseAgainstAPICache(clusterConfig)
	if err != nil {
		return err
	}
	return backendSampler.StartEndpointMonitoring(ctx, m, nil)
}

func createKubeAPIMonitoringWithNewConnections(clusterConfig *rest.Config) (*backenddisruption.BackendSampler, error) {
	return createAPIServerBackendSampler(clusterConfig, "kube-api", "/api/v1/namespaces/default", backenddisruption.NewConnectionType)
}

func createKubeAPIMonitoringWithNewConnectionsAgainstAPICache(clusterConfig *rest.Config) (*backenddisruption.BackendSampler, error) {
	// by setting resourceVersion="0" we instruct the server to get the data from the memory cache and avoid contacting with the etcd.
	return createAPIServerBackendSampler(clusterConfig, "cache-kube-api", "/api/v1/namespaces/default?resourceVersion=0", backenddisruption.NewConnectionType)
}

func createOpenShiftAPIMonitoringWithNewConnections(clusterConfig *rest.Config) (*backenddisruption.BackendSampler, error) {
	// this request should never 404, but should be empty/small
	return createAPIServerBackendSampler(clusterConfig, "openshift-api", "/apis/image.openshift.io/v1/namespaces/default/imagestreams", backenddisruption.NewConnectionType)
}

func createOpenShiftAPIMonitoringWithNewConnectionsAgainstAPICache(clusterConfig *rest.Config) (*backenddisruption.BackendSampler, error) {
	// by setting resourceVersion="0" we instruct the server to get the data from the memory cache and avoid contacting with the etcd.
	// this request should never 404, but should be empty/small
	return createAPIServerBackendSampler(clusterConfig, "cache-openshift-api", "/apis/image.openshift.io/v1/namespaces/default/imagestreams?resourceVersion=0", backenddisruption.NewConnectionType)
}

func createOAuthAPIMonitoringWithNewConnections(clusterConfig *rest.Config) (*backenddisruption.BackendSampler, error) {
	// this should be relatively small and should not ever 404
	return createAPIServerBackendSampler(clusterConfig, "oauth-api", "/apis/oauth.openshift.io/v1/oauthclients", backenddisruption.NewConnectionType)
}

func createOAuthAPIMonitoringWithNewConnectionsAgainstAPICache(clusterConfig *rest.Config) (*backenddisruption.BackendSampler, error) {
	// by setting resourceVersion="0" we instruct the server to get the data from the memory cache and avoid contacting with the etcd.
	// this should be relatively small and should not ever 404
	return createAPIServerBackendSampler(clusterConfig, "cache-oauth-api", "/apis/oauth.openshift.io/v1/oauthclients?resourceVersion=0", backenddisruption.NewConnectionType)
}

func createKubeAPIMonitoringWithConnectionReuse(clusterConfig *rest.Config) (*backenddisruption.BackendSampler, error) {
	// default gets auto-created, so this should always exist
	return createAPIServerBackendSampler(clusterConfig, "kube-api", "/api/v1/namespaces/default", backenddisruption.ReusedConnectionType)
}

func createKubeAPIMonitoringWithConnectionReuseAgainstAPICache(clusterConfig *rest.Config) (*backenddisruption.BackendSampler, error) {
	// by setting resourceVersion="0" we instruct the server to get the data from the memory cache and avoid contacting with the etcd.
	// default gets auto-created, so this should always exist
	return createAPIServerBackendSampler(clusterConfig, "cache-kube-api", "/api/v1/namespaces/default?resourceVersion=0", backenddisruption.ReusedConnectionType)
}

func createOpenShiftAPIMonitoringWithConnectionReuse(clusterConfig *rest.Config) (*backenddisruption.BackendSampler, error) {
	// this request should never 404, but should be empty/small
	return createAPIServerBackendSampler(clusterConfig, "openshift-api", "/apis/image.openshift.io/v1/namespaces/default/imagestreams", backenddisruption.ReusedConnectionType)
}

func createOpenShiftAPIMonitoringWithConnectionReuseAgainstAPICache(clusterConfig *rest.Config) (*backenddisruption.BackendSampler, error) {
	// by setting resourceVersion="0" we instruct the server to get the data from the memory cache and avoid contacting with the etcd.
	// this request should never 404, but should be empty/small
	return createAPIServerBackendSampler(clusterConfig, "cache-openshift-api", "/apis/image.openshift.io/v1/namespaces/default/imagestreams?resourceVersion=0", backenddisruption.ReusedConnectionType)
}

func createOAuthAPIMonitoringWithConnectionReuse(clusterConfig *rest.Config) (*backenddisruption.BackendSampler, error) {
	// this should be relatively small and should not ever 404
	return createAPIServerBackendSampler(clusterConfig, "oauth-api", "/apis/oauth.openshift.io/v1/oauthclients", backenddisruption.ReusedConnectionType)
}

func createOAuthAPIMonitoringWithConnectionReuseAgainstAPICache(clusterConfig *rest.Config) (*backenddisruption.BackendSampler, error) {
	// by setting resourceVersion="0" we instruct the server to get the data from the memory cache and avoid contacting with the etcd.
	// this should be relatively small and should not ever 404
	return createAPIServerBackendSampler(clusterConfig, "cache-oauth-api", "/apis/oauth.openshift.io/v1/oauthclients?resourceVersion=0", backenddisruption.ReusedConnectionType)
}

func createAPIServerBackendSampler(clusterConfig *rest.Config, disruptionBackendName, url string, connectionType backenddisruption.BackendConnectionType) (*backenddisruption.BackendSampler, error) {
	// default gets auto-created, so this should always exist
	backendSampler, err := backenddisruption.NewAPIServerBackend(clusterConfig, disruptionBackendName, url, connectionType)
	if err != nil {
		return nil, err
	}

	return backendSampler, nil
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"strings"
)

type fish struct{}

// Fish adds support for the fish shell as a host
var Fish Shell = fish{}

const fishHook = `
function __direnv_export_eval --on-event fish_postexec;
	"{{.SelfPath}}" export fish | source;
end
`

func (sh fish) Hook() (string, error) {
	return fishHook, nil
}

func (sh fish) Export(e ShellExport) (out string) {
	for key, value := range e {
		if value == nil {
			out += sh.unset(key)
		} else {
			out += sh.export(key, *value)
		}
	}
	return out
}

func (sh fish) Dump(env Env) (out string) {
	for key, value := range env {
		out += sh.export(key, value)
	}
	return out
}

func (sh fish) export(key, value string) string {
	if key == "PATH" {
		command := "set -x -g PATH"
		for _, path := range strings.Split(value, ":") {
			command += " " + sh.escape(path)
		}
		return command + ";"
	}
	return "set -x -g " + sh.escape(key) + " " + sh.escape(value) + ";"
}

func (sh fish) unset(key string) string {
	return "set -e -g " + sh.escape(key) + ";"
}

func (sh fish) escape(str string) string {
	in := []byte(str)
	out := "'"
	i := 0
	l := len(in)

	hex := func(char byte) {
		out += fmt.Sprintf("'\\x%02x'", char)
	}

	backslash := func(char byte) {
		out += string([]byte{BACKSLASH, char})
	}

	escaped := func(str string) {
		out += "'" + str + "'"
	}

	literal := func(char byte) {
		out += string([]byte{char})
	}

	for i < l {
		char := in[i]
		switch {
		case char == TAB:
			escaped(`\t`)
		case char == LF:
			escaped(`\n`)
		case char == CR:
			escaped(`\r`)
		case char <= US:
			hex(char)
		case char == SINGLE_QUOTE:
			backslash(char)
		case char == BACKSLASH:
			backslash(char)
		case char <= TILDA:
			literal(char)
		case char == DEL:
			hex(char)
		default:
			hex(char)
		}
		i++
	}

	out += "'"

	return out
}
<commit_msg>Update shell_fish.go to use \X for UTF encoding (#584)<commit_after>package main

import (
	"fmt"
	"strings"
)

type fish struct{}

// Fish adds support for the fish shell as a host
var Fish Shell = fish{}

const fishHook = `
function __direnv_export_eval --on-event fish_postexec;
	"{{.SelfPath}}" export fish | source;
end
`

func (sh fish) Hook() (string, error) {
	return fishHook, nil
}

func (sh fish) Export(e ShellExport) (out string) {
	for key, value := range e {
		if value == nil {
			out += sh.unset(key)
		} else {
			out += sh.export(key, *value)
		}
	}
	return out
}

func (sh fish) Dump(env Env) (out string) {
	for key, value := range env {
		out += sh.export(key, value)
	}
	return out
}

func (sh fish) export(key, value string) string {
	if key == "PATH" {
		command := "set -x -g PATH"
		for _, path := range strings.Split(value, ":") {
			command += " " + sh.escape(path)
		}
		return command + ";"
	}
	return "set -x -g " + sh.escape(key) + " " + sh.escape(value) + ";"
}

func (sh fish) unset(key string) string {
	return "set -e -g " + sh.escape(key) + ";"
}

func (sh fish) escape(str string) string {
	in := []byte(str)
	out := "'"
	i := 0
	l := len(in)

	hex := func(char byte) {
		out += fmt.Sprintf("'\\X%02x'", char)
	}

	backslash := func(char byte) {
		out += string([]byte{BACKSLASH, char})
	}

	escaped := func(str string) {
		out += "'" + str + "'"
	}

	literal := func(char byte) {
		out += string([]byte{char})
	}

	for i < l {
		char := in[i]
		switch {
		case char == TAB:
			escaped(`\t`)
		case char == LF:
			escaped(`\n`)
		case char == CR:
			escaped(`\r`)
		case char <= US:
			hex(char)
		case char == SINGLE_QUOTE:
			backslash(char)
		case char == BACKSLASH:
			backslash(char)
		case char <= TILDA:
			literal(char)
		case char == DEL:
			hex(char)
		default:
			hex(char)
		}
		i++
	}

	out += "'"

	return out
}
<|endoftext|>


<commit_before>package bloom

import (
	"encoding/binary"
	"math"

	"github.com/dchest/siphash"
)

// EstimateParameters estimates requirements for the number of bits and hash functions,
// to use in the Bloom Filter.
// Computed from the number of items to add and the false positive rate
func EstimateParameters(numItems uint64, fpRate float64) (numBits uint64, numHash uint64) {
	l := uint64(math.Ceil(-1 * float64(numItems) * math.Log(fpRate) / math.Pow(math.Log(2), 2)))
	h := uint64(math.Ceil(math.Log(2) * float64(l) / float64(numItems)))
	return l, h
}

// GetLocations will generate a list of numHash bit locations
// using a cryptographic hash function keyed on a 16-byte key
// and the specified data
func GetLocations(key []byte, numHash uint64, data []byte) []uint64 {
	var loc uint64
	buf := make([]byte, 8)
	result := make([]uint64, 0)

	h := siphash.New(key)
	h.Write(data)
	for i := uint64(0); i < numHash; i++ {
		binary.PutUvarint(buf, i)
		h.Write(buf)
		loc = h.Sum64()
		result = append(result, loc)
	}
	return result
}

// TestLocations returns true if all locations are set in the BitSet,
// false otherwise.
func TestLocations(b *BitSet, locations []uint64) bool {
	for i := 0; i < len(locations); i++ {
		if !b.Test(locations[i]) {
			return false
		}
	}
	return true
}

// SetLocations will set all specified bits to 1 in the bitset
func SetLocations(b *BitSet, locations []uint64) *BitSet {
	for _, loc := range locations {
		b.Set(loc)
	}
	return b
}
<commit_msg>add test<commit_after>package bloom

import (
	"encoding/binary"
	"math"

	"github.com/dchest/siphash"
)

// EstimateParameters estimates requirements for the number of bits and hash functions,
// to use in the Bloom Filter.
// Computed from the number of items to add and the false positive rate
func EstimateParameters(numItems uint64, fpRate float64) (numBits uint64, numHash uint64) {
	l := uint64(math.Ceil(-1 * float64(numItems) * math.Log(fpRate) / math.Pow(math.Log(2), 2)))
	h := uint64(math.Ceil(math.Log(2) * float64(l) / float64(numItems)))
	return l, h
}

// GetLocations will generate a list of numHash bit locations
// using a cryptographic hash function keyed on a 16-byte key
// and the specified data
func GetLocations(key []byte, numHash uint64, data []byte) []uint64 {
	var loc uint64
	buf := make([]byte, 8)
	result := make([]uint64, 0)

	h := siphash.New(key)
	h.Write(data)
	for i := uint64(0); i < numHash; i++ {
		binary.PutUvarint(buf, i)
		h.Write(buf)
		loc = h.Sum64()
		result = append(result, loc)
	}
	return result
}

// TestLocations returns true if all locations are set in the BitSet,
// false otherwise.
func TestLocations(b *BitSet, locations []uint64) bool {
	for i := 0; i < len(locations); i++ {
		if !b.Test(locations[i] % b.Length()) {
			return false
		}
	}
	return true
}

// SetLocations will set all specified bits to 1 in the bitset
func SetLocations(b *BitSet, locations []uint64) *BitSet {
	for _, loc := range locations {
		b.Set(loc % b.Length())
	}
	return b
}
<|endoftext|>


<commit_before>package appinsights

import (
	"time"

	"github.com/jjjordanmsft/ApplicationInsights-Go/appinsights/contracts"
)

type TelemetryClient interface {
	Context() *TelemetryContext
	InstrumentationKey() string
	Channel() TelemetryChannel
	IsEnabled() bool
	SetIsEnabled(bool)
	Track(Telemetry)
	TrackEvent(string)
	TrackMetric(string, float64)
	TrackTrace(string, contracts.SeverityLevel)
	TrackRequest(string, string, time.Duration, string)
	TrackRemoteDependency(name, dependencyType, target string, success bool)
	TrackAvailability(name string, duration time.Duration, success bool)
	TrackPageView(name, url string)
	TrackException(err interface{})
}

type telemetryClient struct {
	TelemetryConfiguration *TelemetryConfiguration
	channel                TelemetryChannel
	context                *TelemetryContext
	isEnabled              bool
}

func NewTelemetryClient(iKey string) TelemetryClient {
	return NewTelemetryClientFromConfig(NewTelemetryConfiguration(iKey))
}

func NewTelemetryClientFromConfig(config *TelemetryConfiguration) TelemetryClient {
	channel := NewInMemoryChannel(config)
	context := NewTelemetryContext()

	config.setupContext(context)

	return &telemetryClient{
		TelemetryConfiguration: config,
		channel:                channel,
		context:                context,
		isEnabled:              true,
	}
}

func (tc *telemetryClient) Context() *TelemetryContext {
	return tc.context
}

func (tc *telemetryClient) Channel() TelemetryChannel {
	return tc.channel
}

func (tc *telemetryClient) InstrumentationKey() string {
	return tc.TelemetryConfiguration.InstrumentationKey
}

func (tc *telemetryClient) IsEnabled() bool {
	return tc.isEnabled
}

func (tc *telemetryClient) SetIsEnabled(isEnabled bool) {
	tc.isEnabled = isEnabled
}

func (tc *telemetryClient) Track(item Telemetry) {
	if tc.isEnabled {
		tc.channel.Send(tc.context.envelop(item))
	}
}

func (tc *telemetryClient) TrackEvent(name string) {
	tc.Track(NewEventTelemetry(name))
}

func (tc *telemetryClient) TrackMetric(name string, value float64) {
	tc.Track(NewMetricTelemetry(name, value))
}

func (tc *telemetryClient) TrackTrace(message string, severity contracts.SeverityLevel) {
	tc.Track(NewTraceTelemetry(message, severity))
}

func (tc *telemetryClient) TrackRequest(method, url string, duration time.Duration, responseCode string) {
	tc.Track(NewRequestTelemetry(method, url, duration, responseCode))
}

func (tc *telemetryClient) TrackRemoteDependency(name, dependencyType, target string, success bool) {
	tc.Track(NewRemoteDependencyTelemetry(name, dependencyType, target, success))
}

func (tc *telemetryClient) TrackAvailability(name string, duration time.Duration, success bool) {
	tc.Track(NewAvailabilityTelemetry(name, duration, success))
}

func (tc *telemetryClient) TrackPageView(name, url string) {
	tc.Track(NewPageViewTelemetry(name, url))
}

func (tc *telemetryClient) TrackException(err interface{}) {
	tc.Track(NewExceptionTelemetry(err))
}
<commit_msg>Don't save configuration (we don't use it), get ikey from telemetry context<commit_after>package appinsights

import (
	"time"

	"github.com/jjjordanmsft/ApplicationInsights-Go/appinsights/contracts"
)

type TelemetryClient interface {
	Context() *TelemetryContext
	InstrumentationKey() string
	Channel() TelemetryChannel
	IsEnabled() bool
	SetIsEnabled(bool)
	Track(Telemetry)
	TrackEvent(string)
	TrackMetric(string, float64)
	TrackTrace(string, contracts.SeverityLevel)
	TrackRequest(string, string, time.Duration, string)
	TrackRemoteDependency(name, dependencyType, target string, success bool)
	TrackAvailability(name string, duration time.Duration, success bool)
	TrackPageView(name, url string)
	TrackException(err interface{})
}

type telemetryClient struct {
	channel                TelemetryChannel
	context                *TelemetryContext
	isEnabled              bool
}

func NewTelemetryClient(iKey string) TelemetryClient {
	return NewTelemetryClientFromConfig(NewTelemetryConfiguration(iKey))
}

func NewTelemetryClientFromConfig(config *TelemetryConfiguration) TelemetryClient {
	channel := NewInMemoryChannel(config)
	context := NewTelemetryContext()

	config.setupContext(context)

	return &telemetryClient{
		channel:                channel,
		context:                context,
		isEnabled:              true,
	}
}

func (tc *telemetryClient) Context() *TelemetryContext {
	return tc.context
}

func (tc *telemetryClient) Channel() TelemetryChannel {
	return tc.channel
}

func (tc *telemetryClient) InstrumentationKey() string {
	return tc.context.InstrumentationKey()
}

func (tc *telemetryClient) IsEnabled() bool {
	return tc.isEnabled
}

func (tc *telemetryClient) SetIsEnabled(isEnabled bool) {
	tc.isEnabled = isEnabled
}

func (tc *telemetryClient) Track(item Telemetry) {
	if tc.isEnabled {
		tc.channel.Send(tc.context.envelop(item))
	}
}

func (tc *telemetryClient) TrackEvent(name string) {
	tc.Track(NewEventTelemetry(name))
}

func (tc *telemetryClient) TrackMetric(name string, value float64) {
	tc.Track(NewMetricTelemetry(name, value))
}

func (tc *telemetryClient) TrackTrace(message string, severity contracts.SeverityLevel) {
	tc.Track(NewTraceTelemetry(message, severity))
}

func (tc *telemetryClient) TrackRequest(method, url string, duration time.Duration, responseCode string) {
	tc.Track(NewRequestTelemetry(method, url, duration, responseCode))
}

func (tc *telemetryClient) TrackRemoteDependency(name, dependencyType, target string, success bool) {
	tc.Track(NewRemoteDependencyTelemetry(name, dependencyType, target, success))
}

func (tc *telemetryClient) TrackAvailability(name string, duration time.Duration, success bool) {
	tc.Track(NewAvailabilityTelemetry(name, duration, success))
}

func (tc *telemetryClient) TrackPageView(name, url string) {
	tc.Track(NewPageViewTelemetry(name, url))
}

func (tc *telemetryClient) TrackException(err interface{}) {
	tc.Track(NewExceptionTelemetry(err))
}
<|endoftext|>


<commit_before>// Copyright 2015 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 repository contains types and function for git repository
// interaction.
package repository

import (
	"errors"

	"github.com/tsuru/config"
	"github.com/tsuru/go-gandalfclient"
	"github.com/tsuru/tsuru/hc"
	"github.com/tsuru/tsuru/log"
)

const defaultManager = "gandalf"

func init() {
	hc.AddChecker("Gandalf", healthCheck)
}

func healthCheck() error {
	serverURL, err := ServerURL()
	if err == ErrGandalfDisabled {
		return hc.ErrDisabledComponent
	}
	client := gandalf.Client{Endpoint: serverURL}
	result, err := client.GetHealthCheck()
	if err != nil {
		return err
	}
	status := string(result)
	if status == "WORKING" {
		return nil
	}
	return errors.New("unexpected status - " + status)
}

var ErrGandalfDisabled = errors.New("git server is disabled")

var managers map[string]RepositoryManager

// Key represents a public key, that is added to a repository to allow access
// to it.
type Key struct {
	Name string
	Body string
}

// RepositoryManager represents a manager of application repositories.
type RepositoryManager interface {
	CreateUser(username string) error
	RemoveUser(username string) error

	GrantAccess(repository, user string) error
	RevokeAccess(repository, user string) error

	AddKey(username string, key Key) error
	RemoveKey(username string, key Key) error
	ListKeys(username string) ([]Key, error)

	ReadOnlyURL(repository string) (string, error)
	ReadWriteURL(repository string) (string, error)
}

// Manager returns the current configured manager, as defined in the
// configuration file.
func Manager() RepositoryManager {
	managerName, err := config.GetString("repo-manager")
	if err != nil {
		managerName = defaultManager
	}
	if _, ok := managers[managerName]; !ok {
		managerName = "nop"
	}
	return managers[managerName]
}

// Register registers a new repository manager, that can be later configured
// and used.
func Register(name string, manager RepositoryManager) {
	if managers == nil {
		managers = make(map[string]RepositoryManager)
	}
	managers[name] = manager
}

// ServerURL returns the URL to Gandalf API.
func ServerURL() (string, error) {
	server, err := config.GetString("git:api-server")
	if err != nil {
		return "", ErrGandalfDisabled
	}
	return server, nil
}

// ReadWriteURL returns the SSH URL, for writing and reading operations.
func ReadWriteURL(app string) string {
	serverURL, err := ServerURL()
	if err != nil {
		log.Errorf("Error retrieving repository: %s", err)
		return "<none>"
	}
	c := gandalf.Client{Endpoint: serverURL}
	repository, err := c.GetRepository(app)
	if err != nil {
		log.Errorf("Caught error while retrieving repository: %s", err.Error())
		return ""
	}
	return repository.SshURL
}

// ReadOnlyURL returns the url for communication with git-daemon.
func ReadOnlyURL(app string) string {
	serverURL, err := ServerURL()
	if err != nil {
		log.Errorf("Error retrieving repository: %s", err)
		return "<none>"
	}
	c := gandalf.Client{Endpoint: serverURL}
	repository, err := c.GetRepository(app)
	if err != nil {
		log.Errorf("Caught error while retrieving repository: %s", err.Error())
		return ""
	}
	return repository.GitURL
}

// GetPath returns the path to the repository where the app code is in its
// units.
func GetPath() (string, error) {
	return config.GetString("git:unit-repo")
}
<commit_msg>repository: add repository methods in the RepositoryManager<commit_after>// Copyright 2015 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 repository contains types and function for git repository
// interaction.
package repository

import (
	"errors"

	"github.com/tsuru/config"
	"github.com/tsuru/go-gandalfclient"
	"github.com/tsuru/tsuru/hc"
	"github.com/tsuru/tsuru/log"
)

const defaultManager = "gandalf"

func init() {
	hc.AddChecker("Gandalf", healthCheck)
}

func healthCheck() error {
	serverURL, err := ServerURL()
	if err == ErrGandalfDisabled {
		return hc.ErrDisabledComponent
	}
	client := gandalf.Client{Endpoint: serverURL}
	result, err := client.GetHealthCheck()
	if err != nil {
		return err
	}
	status := string(result)
	if status == "WORKING" {
		return nil
	}
	return errors.New("unexpected status - " + status)
}

var ErrGandalfDisabled = errors.New("git server is disabled")

var managers map[string]RepositoryManager

// Key represents a public key, that is added to a repository to allow access
// to it.
type Key struct {
	Name string
	Body string
}

// Repository represents a repository in the manager.
type Repository struct {
	Name         string
	ReadOnlyURL  string
	ReadWriteURL string
}

// RepositoryManager represents a manager of application repositories.
type RepositoryManager interface {
	CreateUser(username string) error
	RemoveUser(username string) error

	GrantAccess(repository, user string) error
	RevokeAccess(repository, user string) error

	AddKey(username string, key Key) error
	RemoveKey(username string, key Key) error
	ListKeys(username string) ([]Key, error)

	CreateRepository(name string) error
	RemoveRepository(name string) error
	GetRepository(name string) (Repository, error)
}

// Manager returns the current configured manager, as defined in the
// configuration file.
func Manager() RepositoryManager {
	managerName, err := config.GetString("repo-manager")
	if err != nil {
		managerName = defaultManager
	}
	if _, ok := managers[managerName]; !ok {
		managerName = "nop"
	}
	return managers[managerName]
}

// Register registers a new repository manager, that can be later configured
// and used.
func Register(name string, manager RepositoryManager) {
	if managers == nil {
		managers = make(map[string]RepositoryManager)
	}
	managers[name] = manager
}

// ServerURL returns the URL to Gandalf API.
func ServerURL() (string, error) {
	server, err := config.GetString("git:api-server")
	if err != nil {
		return "", ErrGandalfDisabled
	}
	return server, nil
}

// ReadWriteURL returns the SSH URL, for writing and reading operations.
func ReadWriteURL(app string) string {
	serverURL, err := ServerURL()
	if err != nil {
		log.Errorf("Error retrieving repository: %s", err)
		return "<none>"
	}
	c := gandalf.Client{Endpoint: serverURL}
	repository, err := c.GetRepository(app)
	if err != nil {
		log.Errorf("Caught error while retrieving repository: %s", err.Error())
		return ""
	}
	return repository.SshURL
}

// ReadOnlyURL returns the url for communication with git-daemon.
func ReadOnlyURL(app string) string {
	serverURL, err := ServerURL()
	if err != nil {
		log.Errorf("Error retrieving repository: %s", err)
		return "<none>"
	}
	c := gandalf.Client{Endpoint: serverURL}
	repository, err := c.GetRepository(app)
	if err != nil {
		log.Errorf("Caught error while retrieving repository: %s", err.Error())
		return ""
	}
	return repository.GitURL
}

// GetPath returns the path to the repository where the app code is in its
// units.
func GetPath() (string, error) {
	return config.GetString("git:unit-repo")
}
<|endoftext|>


<commit_before>/* Mozilla InvestiGator Action Generator

Version: MPL 1.1/GPL 2.0/LGPL 2.1

The contents of this file are subject to the Mozilla Public License Version
1.1 (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.mozilla.org/MPL/

Software distributed under the License is distributed on an "AS IS" basis,
WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
for the specific language governing rights and limitations under the
License.

The Initial Developer of the Original Code is
Mozilla Corporation
Portions created by the Initial Developer are Copyright (C) 2014
the Initial Developer. All Rights Reserved.

Contributor(s):
Julien Vehent jvehent@mozilla.com [:ulfr]
Guillaume Destuynder gdestuynder@mozilla.com

Alternatively, the contents of this file may be used under the terms of
either the GNU General Public License Version 2 or later (the "GPL"), or
the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
in which case the provisions of the GPL or the LGPL are applicable instead
of those above. If you wish to allow use of your version of this file only
under the terms of either the GPL or the LGPL, and not to allow others to
use your version of this file under the terms of the MPL, indicate your
decision by deleting the provisions above and replace them with the notice
and other provisions required by the GPL or the LGPL. If you do not delete
the provisions above, a recipient may use your version of this file under
the terms of any one of the MPL, the GPL or the LGPL.
*/

package main

import (
	"encoding/json"
	"flag"
	"fmt"
	"log"
	"mig"
	"mig/pgp/sign"
	"net/http"
	"net/url"
	"os"
	"os/user"
	"time"
)

func main() {

	var Usage = func() {
		fmt.Fprintf(os.Stderr,
			"Mozilla InvestiGator Action Generator\n"+
				"usage: %s -k=<key id> (-i <input file)\n\n"+
				"Command line to generate and sign MIG Actions.\n"+
				"The resulting actions are display on stdout.\n\n"+
				"Options:\n",
			os.Args[0])
		flag.PrintDefaults()
	}

	// command line options
	var key = flag.String("k", "key identifier", "Key identifier used to sign the action (ex: B75C2346)")
	var pretty = flag.Bool("p", false, "Print signed action in pretty JSON format")
	var urlencode = flag.Bool("urlencode", false, "URL Encode marshalled JSON before output")
	var posturl = flag.String("posturl", "", "POST action to <url> (enforces urlencode)")
	var file = flag.String("i", "/path/to/file", "Load action from file")
	var validfrom = flag.String("validfrom", "now", "(optional) set an ISO8601 date the action will be valid from. If unset, use 'now'.")
	var expireafter = flag.String("expireafter", "30m", "(optional) set a validity duration for the action. If unset, use '30m'.")
	flag.Parse()

	// We need a key, if none is set on the command line, fail
	if *key == "key identifier" {
		Usage()
		os.Exit(-1)
	}

	var err error

	// if a file is defined, load action from that
	if *file == "/path/to/file" {
		fmt.Println("Missing action file")
		os.Exit(1)
	}
	a, err := mig.ActionFromFile(*file)
	if err != nil {
		panic(err)
	}

	// set the dates
	if *validfrom == "now" {
		// for immediate execution, set validity one minute in the past
		a.ValidFrom = time.Now().Add(-60 * time.Second).UTC()
	} else {
		a.ValidFrom, err = time.Parse("2014-01-01T00:00:00.0Z", *validfrom)
		if err != nil {
			panic(err)
		}
	}
	period, err := time.ParseDuration(*expireafter)
	if err != nil {
		log.Fatal(err)
	}
	a.ExpireAfter = a.ValidFrom.Add(period)

	// find keyring in default location
	u, err := user.Current()
	if err != nil {
		panic(err)
	}

	// load keyrings
	var gnupghome string
	gnupghome = os.Getenv("GNUPGHOME")
	if gnupghome == "" {
		gnupghome = "/.gnupg"
	}
	pubringFile, err := os.Open(u.HomeDir + gnupghome + "/pubring.gpg")

	if err != nil {
		panic(err)
	}
	defer pubringFile.Close()

	secringFile, err := os.Open(u.HomeDir + gnupghome + "/secring.gpg")
	if err != nil {
		panic(err)
	}
	defer secringFile.Close()

	// compute the signature
	str, err := a.String()
	if err != nil {
		panic(err)
	}
	pgpsig, err := sign.Sign(str, *key, secringFile)
	if err != nil {
		panic(err)
	}

	// store the signature in the action signature array
	a.PGPSignatures = append(a.PGPSignatures, pgpsig)

	// syntax checking
	err = a.Validate()
	if err != nil {
		panic(err)
	}

	// signature checking
	err = a.VerifySignatures(pubringFile)
	if err != nil {
		panic(err)
	}

	// if asked, pretty print the action
	var jsonAction []byte
	if *pretty {
		jsonAction, err = json.MarshalIndent(a, "", "\t")
		fmt.Printf("%s\n", jsonAction)
	} else {
		jsonAction, err = json.Marshal(a)
	}
	if err != nil {
		panic(err)
	}

	// if asked, url encode the action before marshaling it
	actionstr := string(jsonAction)
	if *urlencode {
		strJsonAction := string(jsonAction)
		actionstr = url.QueryEscape(strJsonAction)
		if *pretty {
			fmt.Println(actionstr)
		}
	}

	// http post the action to the posturl endpoint
	if *posturl != "" {
		resp, err := http.PostForm(*posturl, url.Values{"action": {actionstr}})
		if err != nil {
			panic(err)
		}
		var buf [4096]byte
		reader := resp.Body
		for {
			n, err := reader.Read(buf[0:])
			if err != nil {
				os.Exit(0)
			}
			fmt.Print(string(buf[0:n]))
		}
	}
}
<commit_msg>[minor] fix homedir detection on darwin<commit_after>/* Mozilla InvestiGator Action Generator

Version: MPL 1.1/GPL 2.0/LGPL 2.1

The contents of this file are subject to the Mozilla Public License Version
1.1 (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.mozilla.org/MPL/

Software distributed under the License is distributed on an "AS IS" basis,
WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
for the specific language governing rights and limitations under the
License.

The Initial Developer of the Original Code is
Mozilla Corporation
Portions created by the Initial Developer are Copyright (C) 2014
the Initial Developer. All Rights Reserved.

Contributor(s):
Julien Vehent jvehent@mozilla.com [:ulfr]
Guillaume Destuynder gdestuynder@mozilla.com

Alternatively, the contents of this file may be used under the terms of
either the GNU General Public License Version 2 or later (the "GPL"), or
the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
in which case the provisions of the GPL or the LGPL are applicable instead
of those above. If you wish to allow use of your version of this file only
under the terms of either the GPL or the LGPL, and not to allow others to
use your version of this file under the terms of the MPL, indicate your
decision by deleting the provisions above and replace them with the notice
and other provisions required by the GPL or the LGPL. If you do not delete
the provisions above, a recipient may use your version of this file under
the terms of any one of the MPL, the GPL or the LGPL.
*/

package main

import (
	"encoding/json"
	"flag"
	"fmt"
	"log"
	"mig"
	"mig/pgp/sign"
	"net/http"
	"net/url"
	"os"
	"os/user"
	"runtime"
	"time"
)

func main() {

	var Usage = func() {
		fmt.Fprintf(os.Stderr,
			"Mozilla InvestiGator Action Generator\n"+
				"usage: %s -k=<key id> (-i <input file)\n\n"+
				"Command line to generate and sign MIG Actions.\n"+
				"The resulting actions are display on stdout.\n\n"+
				"Options:\n",
			os.Args[0])
		flag.PrintDefaults()
	}

	// command line options
	var key = flag.String("k", "key identifier", "Key identifier used to sign the action (ex: B75C2346)")
	var pretty = flag.Bool("p", false, "Print signed action in pretty JSON format")
	var urlencode = flag.Bool("urlencode", false, "URL Encode marshalled JSON before output")
	var posturl = flag.String("posturl", "", "POST action to <url> (enforces urlencode)")
	var file = flag.String("i", "/path/to/file", "Load action from file")
	var validfrom = flag.String("validfrom", "now", "(optional) set an ISO8601 date the action will be valid from. If unset, use 'now'.")
	var expireafter = flag.String("expireafter", "30m", "(optional) set a validity duration for the action. If unset, use '30m'.")
	flag.Parse()

	// We need a key, if none is set on the command line, fail
	if *key == "key identifier" {
		Usage()
		os.Exit(-1)
	}

	var err error

	// if a file is defined, load action from that
	if *file == "/path/to/file" {
		fmt.Println("Missing action file")
		os.Exit(1)
	}
	a, err := mig.ActionFromFile(*file)
	if err != nil {
		panic(err)
	}

	// set the dates
	if *validfrom == "now" {
		// for immediate execution, set validity one minute in the past
		a.ValidFrom = time.Now().Add(-60 * time.Second).UTC()
	} else {
		a.ValidFrom, err = time.Parse("2014-01-01T00:00:00.0Z", *validfrom)
		if err != nil {
			panic(err)
		}
	}
	period, err := time.ParseDuration(*expireafter)
	if err != nil {
		log.Fatal(err)
	}
	a.ExpireAfter = a.ValidFrom.Add(period)

	// find homedir
	var homedir string
	if runtime.GOOS == "darwin" {
		homedir = os.Getenv("HOME")
	} else {
		// find keyring in default location
		u, err := user.Current()
		if err != nil {
			panic(err)
		}
		homedir = u.HomeDir
	}
	// load keyrings
	var gnupghome string
	gnupghome = os.Getenv("GNUPGHOME")
	if gnupghome == "" {
		gnupghome = "/.gnupg"
	}
	pubringFile, err := os.Open(homedir + gnupghome + "/pubring.gpg")

	if err != nil {
		panic(err)
	}
	defer pubringFile.Close()

	secringFile, err := os.Open(homedir + gnupghome + "/secring.gpg")
	if err != nil {
		panic(err)
	}
	defer secringFile.Close()

	// compute the signature
	str, err := a.String()
	if err != nil {
		panic(err)
	}
	pgpsig, err := sign.Sign(str, *key, secringFile)
	if err != nil {
		panic(err)
	}

	// store the signature in the action signature array
	a.PGPSignatures = append(a.PGPSignatures, pgpsig)

	// syntax checking
	err = a.Validate()
	if err != nil {
		panic(err)
	}

	// signature checking
	err = a.VerifySignatures(pubringFile)
	if err != nil {
		panic(err)
	}

	// if asked, pretty print the action
	var jsonAction []byte
	if *pretty {
		jsonAction, err = json.MarshalIndent(a, "", "\t")
		fmt.Printf("%s\n", jsonAction)
	} else {
		jsonAction, err = json.Marshal(a)
	}
	if err != nil {
		panic(err)
	}

	// if asked, url encode the action before marshaling it
	actionstr := string(jsonAction)
	if *urlencode {
		strJsonAction := string(jsonAction)
		actionstr = url.QueryEscape(strJsonAction)
		if *pretty {
			fmt.Println(actionstr)
		}
	}

	// http post the action to the posturl endpoint
	if *posturl != "" {
		resp, err := http.PostForm(*posturl, url.Values{"action": {actionstr}})
		if err != nil {
			panic(err)
		}
		var buf [4096]byte
		reader := resp.Body
		for {
			n, err := reader.Read(buf[0:])
			if err != nil {
				os.Exit(0)
			}
			fmt.Print(string(buf[0:n]))
		}
	}
}
<|endoftext|>


<commit_before>// Code generated by mockery v1.0.0
package mockdependencies

import context "context"
import db "github.com/Nivl/go-rest-tools/storage/db"

import filestorage "github.com/Nivl/go-rest-tools/storage/filestorage"
import logger "github.com/Nivl/go-rest-tools/logger"
import mailer "github.com/Nivl/go-rest-tools/notifiers/mailer"
import mock "github.com/stretchr/testify/mock"

// Dependencies is an autogenerated mock type for the Dependencies type
type Dependencies struct {
	mock.Mock
}

// DB provides a mock function with given fields:
func (_m *Dependencies) DB() db.Connection {
	ret := _m.Called()

	var r0 db.Connection
	if rf, ok := ret.Get(0).(func() db.Connection); ok {
		r0 = rf()
	} else {
		if ret.Get(0) != nil {
			r0 = ret.Get(0).(db.Connection)
		}
	}

	return r0
}

// FileStorage provides a mock function with given fields: ctx
func (_m *Dependencies) FileStorage(ctx context.Context) (filestorage.FileStorage, error) {
	ret := _m.Called(ctx)

	var r0 filestorage.FileStorage
	if rf, ok := ret.Get(0).(func(context.Context) filestorage.FileStorage); ok {
		r0 = rf(ctx)
	} else {
		if ret.Get(0) != nil {
			r0 = ret.Get(0).(filestorage.FileStorage)
		}
	}

	var r1 error
	if rf, ok := ret.Get(1).(func(context.Context) error); ok {
		r1 = rf(ctx)
	} else {
		r1 = ret.Error(1)
	}

	return r0, r1
}

// Logger provides a mock function with given fields:
func (_m *Dependencies) Logger() logger.Logger {
	ret := _m.Called()

	var r0 logger.Logger
	if rf, ok := ret.Get(0).(func() logger.Logger); ok {
		r0 = rf()
	} else {
		if ret.Get(0) != nil {
			r0 = ret.Get(0).(logger.Logger)
		}
	}

	return r0
}

// Mailer provides a mock function with given fields:
func (_m *Dependencies) Mailer() mailer.Mailer {
	ret := _m.Called()

	var r0 mailer.Mailer
	if rf, ok := ret.Get(0).(func() mailer.Mailer); ok {
		r0 = rf()
	} else {
		if ret.Get(0) != nil {
			r0 = ret.Get(0).(mailer.Mailer)
		}
	}

	return r0
}

// SetCloudinary provides a mock function with given fields: apiKey, secret, bucket
func (_m *Dependencies) SetCloudinary(apiKey string, secret string, bucket string) error {
	ret := _m.Called(apiKey, secret, bucket)

	var r0 error
	if rf, ok := ret.Get(0).(func(string, string, string) error); ok {
		r0 = rf(apiKey, secret, bucket)
	} else {
		r0 = ret.Error(0)
	}

	return r0
}

// SetDB provides a mock function with given fields: uri
func (_m *Dependencies) SetDB(uri string) error {
	ret := _m.Called(uri)

	var r0 error
	if rf, ok := ret.Get(0).(func(string) error); ok {
		r0 = rf(uri)
	} else {
		r0 = ret.Error(0)
	}

	return r0
}

// SetGCP provides a mock function with given fields: apiKey, projectName, bucket
func (_m *Dependencies) SetGCP(apiKey string, projectName string, bucket string) error {
	ret := _m.Called(apiKey, projectName, bucket)

	var r0 error
	if rf, ok := ret.Get(0).(func(string, string, string) error); ok {
		r0 = rf(apiKey, projectName, bucket)
	} else {
		r0 = ret.Error(0)
	}

	return r0
}

// SetLogentries provides a mock function with given fields: token
func (_m *Dependencies) SetLogentries(token string) error {
	ret := _m.Called(token)

	var r0 error
	if rf, ok := ret.Get(0).(func(string) error); ok {
		r0 = rf(token)
	} else {
		r0 = ret.Error(0)
	}

	return r0
}

// SetSendgrid provides a mock function with given fields: apiKey, from, to, stacktraceUUID
func (_m *Dependencies) SetSendgrid(apiKey string, from string, to string, stacktraceUUID string) error {
	ret := _m.Called(apiKey, from, to, stacktraceUUID)

	var r0 error
	if rf, ok := ret.Get(0).(func(string, string, string, string) error); ok {
		r0 = rf(apiKey, from, to, stacktraceUUID)
	} else {
		r0 = ret.Error(0)
	}

	return r0
}
<commit_msg>fix: Update mockdependencies<commit_after>// Code generated by mockery v1.0.0
package mockdependencies

import context "context"
import db "github.com/Nivl/go-rest-tools/storage/db"

import filestorage "github.com/Nivl/go-rest-tools/storage/filestorage"
import logger "github.com/Nivl/go-rest-tools/logger"
import mailer "github.com/Nivl/go-rest-tools/notifiers/mailer"
import mock "github.com/stretchr/testify/mock"
import reporter "github.com/Nivl/go-rest-tools/notifiers/reporter"

// Dependencies is an autogenerated mock type for the Dependencies type
type Dependencies struct {
	mock.Mock
}

// DB provides a mock function with given fields:
func (_m *Dependencies) DB() db.Connection {
	ret := _m.Called()

	var r0 db.Connection
	if rf, ok := ret.Get(0).(func() db.Connection); ok {
		r0 = rf()
	} else {
		if ret.Get(0) != nil {
			r0 = ret.Get(0).(db.Connection)
		}
	}

	return r0
}

// EnableEmailReporting provides a mock function with given fields: con
func (_m *Dependencies) EnableEmailReporting(con string) error {
	ret := _m.Called(con)

	var r0 error
	if rf, ok := ret.Get(0).(func(string) error); ok {
		r0 = rf(con)
	} else {
		r0 = ret.Error(0)
	}

	return r0
}

// FileStorage provides a mock function with given fields: ctx
func (_m *Dependencies) FileStorage(ctx context.Context) (filestorage.FileStorage, error) {
	ret := _m.Called(ctx)

	var r0 filestorage.FileStorage
	if rf, ok := ret.Get(0).(func(context.Context) filestorage.FileStorage); ok {
		r0 = rf(ctx)
	} else {
		if ret.Get(0) != nil {
			r0 = ret.Get(0).(filestorage.FileStorage)
		}
	}

	var r1 error
	if rf, ok := ret.Get(1).(func(context.Context) error); ok {
		r1 = rf(ctx)
	} else {
		r1 = ret.Error(1)
	}

	return r0, r1
}

// Logger provides a mock function with given fields:
func (_m *Dependencies) Logger() logger.Logger {
	ret := _m.Called()

	var r0 logger.Logger
	if rf, ok := ret.Get(0).(func() logger.Logger); ok {
		r0 = rf()
	} else {
		if ret.Get(0) != nil {
			r0 = ret.Get(0).(logger.Logger)
		}
	}

	return r0
}

// Mailer provides a mock function with given fields:
func (_m *Dependencies) Mailer() mailer.Mailer {
	ret := _m.Called()

	var r0 mailer.Mailer
	if rf, ok := ret.Get(0).(func() mailer.Mailer); ok {
		r0 = rf()
	} else {
		if ret.Get(0) != nil {
			r0 = ret.Get(0).(mailer.Mailer)
		}
	}

	return r0
}

// Reporter provides a mock function with given fields:
func (_m *Dependencies) Reporter() reporter.Creator {
	ret := _m.Called()

	var r0 reporter.Creator
	if rf, ok := ret.Get(0).(func() reporter.Creator); ok {
		r0 = rf()
	} else {
		if ret.Get(0) != nil {
			r0 = ret.Get(0).(reporter.Creator)
		}
	}

	return r0
}

// SetCloudinary provides a mock function with given fields: apiKey, secret, bucket
func (_m *Dependencies) SetCloudinary(apiKey string, secret string, bucket string) error {
	ret := _m.Called(apiKey, secret, bucket)

	var r0 error
	if rf, ok := ret.Get(0).(func(string, string, string) error); ok {
		r0 = rf(apiKey, secret, bucket)
	} else {
		r0 = ret.Error(0)
	}

	return r0
}

// SetDB provides a mock function with given fields: uri
func (_m *Dependencies) SetDB(uri string) error {
	ret := _m.Called(uri)

	var r0 error
	if rf, ok := ret.Get(0).(func(string) error); ok {
		r0 = rf(uri)
	} else {
		r0 = ret.Error(0)
	}

	return r0
}

// SetGCP provides a mock function with given fields: apiKey, projectName, bucket
func (_m *Dependencies) SetGCP(apiKey string, projectName string, bucket string) error {
	ret := _m.Called(apiKey, projectName, bucket)

	var r0 error
	if rf, ok := ret.Get(0).(func(string, string, string) error); ok {
		r0 = rf(apiKey, projectName, bucket)
	} else {
		r0 = ret.Error(0)
	}

	return r0
}

// SetLogentries provides a mock function with given fields: token
func (_m *Dependencies) SetLogentries(token string) error {
	ret := _m.Called(token)

	var r0 error
	if rf, ok := ret.Get(0).(func(string) error); ok {
		r0 = rf(token)
	} else {
		r0 = ret.Error(0)
	}

	return r0
}

// SetSendgrid provides a mock function with given fields: apiKey, from, to, stacktraceUUID
func (_m *Dependencies) SetSendgrid(apiKey string, from string, to string, stacktraceUUID string) error {
	ret := _m.Called(apiKey, from, to, stacktraceUUID)

	var r0 error
	if rf, ok := ret.Get(0).(func(string, string, string, string) error); ok {
		r0 = rf(apiKey, from, to, stacktraceUUID)
	} else {
		r0 = ret.Error(0)
	}

	return r0
}

// SetSentry provides a mock function with given fields: con
func (_m *Dependencies) SetSentry(con string) error {
	ret := _m.Called(con)

	var r0 error
	if rf, ok := ret.Get(0).(func(string) error); ok {
		r0 = rf(con)
	} else {
		r0 = ret.Error(0)
	}

	return r0
}
<|endoftext|>


<commit_before>package application

import (
	"bytes"
	"encoding/json"
	"errors"
	"fmt"
	"io/ioutil"
	"net/http"
	"strconv"
	"strings"

	"github.com/Sirupsen/logrus"
	"github.com/codegangsta/negroni"
	"github.com/disintegration/imaging"
	"github.com/getsentry/raven-go"
	"github.com/gorilla/mux"
	"github.com/jmoiron/jsonq"
	"github.com/lizdeika/gostorages"
	"github.com/lizdeika/picfit/engines"
	"github.com/lizdeika/picfit/extractors"
	"github.com/lizdeika/picfit/hash"
	"github.com/lizdeika/picfit/image"
	"github.com/lizdeika/picfit/middleware"
	"github.com/meatballhat/negroni-logrus"
	"github.com/rs/cors"
	"github.com/thoas/gokvstores"
	"github.com/thoas/muxer"
	"github.com/thoas/stats"
)

var Extractors = map[string]extractors.Extractor{
	"op":   extractors.Operation,
	"url":  extractors.URL,
	"path": extractors.Path,
}

type Shard struct {
	Depth int
	Width int
}

type Application struct {
	EnableUpload  bool
	Prefix        string
	SecretKey     string
	KVStore       gokvstores.KVStore
	SourceStorage gostorages.Storage
	DestStorage   gostorages.Storage
	Shard         Shard
	Raven         *raven.Client
	Logger        *logrus.Logger
	Engine        engines.Engine
	Jq            *jsonq.JsonQuery
}

func NewApplication() *Application {
	return &Application{
		Logger:       logrus.New(),
		EnableUpload: false,
	}
}

func NewFromConfigPath(path string) (*Application, error) {
	content, err := ioutil.ReadFile(path)

	if err != nil {
		return nil, fmt.Errorf("Your config file %s cannot be loaded: %s", path, err)
	}

	return NewFromConfig(string(content))
}

func NewFromConfig(content string) (*Application, error) {
	data := map[string]interface{}{}
	dec := json.NewDecoder(strings.NewReader(content))
	err := dec.Decode(&data)

	if err != nil {
		return nil, fmt.Errorf("Your config file %s cannot be parsed: %s", content, err)
	}

	jq := jsonq.NewQuery(data)

	return NewFromJsonQuery(jq)
}

func NewFromJsonQuery(jq *jsonq.JsonQuery) (*Application, error) {
	app := NewApplication()
	app.Jq = jq

	for _, initializer := range Initializers {
		err := initializer(jq, app)

		if err != nil {
			return nil, fmt.Errorf("An error occured during init: %s", err)
		}
	}

	return app, nil
}

func (app *Application) ServeHTTP(h Handler) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
		con := app.KVStore.Connection()
		defer con.Close()

		res := muxer.NewResponse(w)

		request, err := NewRequest(req, con, app.Jq)

		if err != nil {
			app.Logger.Error(err)

			res.BadRequest()

			return
		}

		if app.SecretKey != "" && !request.IsAuthorized(app.SecretKey) {
			res.Unauthorized()

			return
		}

		h(res, request, app)
	})
}

func (a *Application) InitRouter() *negroni.Negroni {
	router := mux.NewRouter()
	router.NotFoundHandler = NotFoundHandler()

	methods := map[string]Handler{
		"redirect": RedirectHandler,
		"display":  ImageHandler,
		"get":      GetHandler,
	}

	for name, handler := range methods {
		handlerFunc := a.ServeHTTP(handler)

		router.Handle(fmt.Sprintf("/%s", name), handlerFunc)
		router.Handle(fmt.Sprintf("/%s/{sig}/{op}/x{h:[\\d]+}/{path:[\\w\\-/.]+}", name), handlerFunc)
		router.Handle(fmt.Sprintf("/%s/{sig}/{op}/{w:[\\d]+}x/{path:[\\w\\-/.]+}", name), handlerFunc)
		router.Handle(fmt.Sprintf("/%s/{sig}/{op}/{w:[\\d]+}x{h:[\\d]+}/{path:[\\w\\-/.]+}", name), handlerFunc)
		router.Handle(fmt.Sprintf("/%s/{op}/x{h:[\\d]+}/{path:[\\w\\-/.]+}", name), handlerFunc)
		router.Handle(fmt.Sprintf("/%s/{op}/{w:[\\d]+}x/{path:[\\w\\-/.]+}", name), handlerFunc)
		router.Handle(fmt.Sprintf("/%s/{op}/{w:[\\d]+}x{h:[\\d]+}/{path:[\\w\\-/.]+}", name), handlerFunc)
	}

	router.Handle("/upload", http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
		res := muxer.NewResponse(w)

		UploadHandler(res, req, a)
	}))

	allowedOrigins, err := a.Jq.ArrayOfStrings("allowed_origins")
	allowedMethods, err := a.Jq.ArrayOfStrings("allowed_methods")

	s := stats.New()

	router.HandleFunc("/stats", func(w http.ResponseWriter, r *http.Request) {
		w.Header().Set("Content-Type", "application/json")

		stats := s.Data()

		b, _ := json.Marshal(stats)

		w.Write(b)
	})

	debug, err := a.Jq.Bool("debug")

	if err != nil {
		debug = false
	}

	n := negroni.New(&middleware.Recovery{
		Raven:      a.Raven,
		Logger:     a.Logger,
		PrintStack: debug,
		StackAll:   false,
		StackSize:  1024 * 8,
	}, &middleware.Logger{a.Logger})
	n.Use(cors.New(cors.Options{
		AllowedOrigins: allowedOrigins,
		AllowedMethods: allowedMethods,
	}))
	n.Use(negronilogrus.NewMiddleware())
	n.UseHandler(router)

	return n
}

func (a *Application) Port() int {
	port, err := a.Jq.Int("port")

	if err != nil {
		port = DefaultPort
	}

	return port
}

func (a *Application) ShardFilename(filename string) string {
	results := hash.Shard(filename, a.Shard.Width, a.Shard.Depth, true)

	return strings.Join(results, "/")
}

func (a *Application) Store(i *image.ImageFile, args ...string) error {
	con := a.KVStore.Connection()
	defer con.Close()

	err := i.Save()

	if err != nil {
		a.Logger.Fatal(err)
		return err
	}

	tipe := "thumbnail"
	if len(args) > 0 {
		tipe = args[0]
	}

	a.Logger.Infof("Save %s %s to storage", tipe, i.Filepath)

	key := a.WithPrefix(i.Key)

	err = con.Set(key, i.Filepath)

	if err != nil {
		a.Logger.Fatal(err)

		return err
	}

	a.Logger.Infof("Save key %s => %s to kvstore", key, i.Filepath)

	return nil
}

func (a *Application) WithPrefix(str string) string {
	return a.Prefix + str
}

func (a *Application) ImageFileFromRequest(req *Request, async bool, load bool) (*image.ImageFile, error) {
	var file *image.ImageFile = &image.ImageFile{
		Key:     req.Key,
		Storage: a.DestStorage,
		Headers: map[string]string{},
	}
	var err error

	key := a.WithPrefix(req.Key)

	// Image from the KVStore found
	stored, _ := gokvstores.String(req.Connection.Get(key))

	file.Filepath = stored

	if stored != "" {
		a.Logger.Infof("Key %s found in kvstore: %s", key, stored)

		if load {
			file, err = image.FromStorage(a.DestStorage, stored)

			if file == nil || err != nil {
				stored = ""
				err = nil
			}

			// if err != nil {
			// 	return nil, err
			// }
		}
	}

	if stored == "" {
		a.Logger.Infof("Key %s not found in kvstore OR file not found in dst", key)

		// Image not found from the KVStore, we need to process it
		// URL or Path available in Query String
		cacheOriginal := false
		fileKey := ""
		kvKey := ""
		if req.URL != nil {
			return nil, errors.New("404")
		} else {
			// URL provided we use http protocol to retrieve it
			fileKey = hash.Tokey(hash.Serialize(req.Filepath))
			kvKey = a.WithPrefix(fileKey)
			fileStored, err := gokvstores.String(req.Connection.Get(kvKey))
			if fileStored != "" {
				a.Logger.Infof("Key %s for original found in kvstore: %s", kvKey, fileStored)

				if load {
					file, err = image.FromStorage(a.DestStorage, fileStored)
					// not found in dest storage? Try getting from src storage
					if file == nil || err != nil {
						a.Logger.Infof("File %s for key %s not found in dst, try reget from src", fileStored, kvKey)
						file, err = image.FromStorage(a.SourceStorage, req.Filepath)
						if file == nil {
							return nil, errors.New("404")
						}
						cacheOriginal = true
					}
				}
			} else {
				file, err = image.FromStorage(a.SourceStorage, req.Filepath)
				if file == nil {
					return nil, errors.New("404")
				}
				cacheOriginal = true
			}
		}

		if err != nil {
			return nil, err
		}

		if cacheOriginal == true && fileKey != "" {
			file.Key = fileKey
			file.Storage = a.DestStorage
			file.Filepath = fmt.Sprintf("%s.%s", a.ShardFilename(fileKey), file.Format())
			if async == true {
				go a.Store(file, "original")
			} else {
				err = a.Store(file, "original")
			}
		}

		if err != nil {
			return nil, err
		}

		imageOrig, err := imaging.Decode(bytes.NewReader(file.Source))
		if err != nil {
			return nil, err
		}
		width, height := engines.ImageSize(imageOrig)
		rw, err := strconv.Atoi(req.QueryString["w"])
		if err != nil {
			return nil, err
		}
		rh, err := strconv.Atoi(req.QueryString["h"])
		if err != nil {
			return nil, err
		}
		if rw < width && rh < height {
			file, err = a.Engine.Transform(file, req.Operation, req.QueryString)
		} else {
			stored = "do not store"
		}

		// file, err = a.Engine.Transform(file, req.Operation, req.QueryString)

		if err != nil {
			return nil, err
		}
	}

	file.Headers["Content-Type"] = file.ContentType()
	file.Headers["ETag"] = req.Key

	if stored == "" {
		file.Filepath = fmt.Sprintf("%s.%s", a.ShardFilename(req.Key), file.Format())
		file.Key = req.Key
		file.Storage = a.DestStorage
		if async == true {
			go a.Store(file)
		} else {
			err = a.Store(file)
		}
	}

	return file, err
}
<commit_msg>router addons<commit_after>package application

import (
	"bytes"
	"encoding/json"
	"errors"
	"fmt"
	"io/ioutil"
	"net/http"
	"strconv"
	"strings"

	"github.com/Sirupsen/logrus"
	"github.com/codegangsta/negroni"
	"github.com/disintegration/imaging"
	"github.com/getsentry/raven-go"
	"github.com/gorilla/mux"
	"github.com/jmoiron/jsonq"
	"github.com/lizdeika/gostorages"
	"github.com/lizdeika/picfit/engines"
	"github.com/lizdeika/picfit/extractors"
	"github.com/lizdeika/picfit/hash"
	"github.com/lizdeika/picfit/image"
	"github.com/lizdeika/picfit/middleware"
	"github.com/meatballhat/negroni-logrus"
	"github.com/rs/cors"
	"github.com/thoas/gokvstores"
	"github.com/thoas/muxer"
	"github.com/thoas/stats"
)

var Extractors = map[string]extractors.Extractor{
	"op":   extractors.Operation,
	"url":  extractors.URL,
	"path": extractors.Path,
}

type Shard struct {
	Depth int
	Width int
}

type Application struct {
	EnableUpload  bool
	Prefix        string
	SecretKey     string
	KVStore       gokvstores.KVStore
	SourceStorage gostorages.Storage
	DestStorage   gostorages.Storage
	Shard         Shard
	Raven         *raven.Client
	Logger        *logrus.Logger
	Engine        engines.Engine
	Jq            *jsonq.JsonQuery
}

func NewApplication() *Application {
	return &Application{
		Logger:       logrus.New(),
		EnableUpload: false,
	}
}

func NewFromConfigPath(path string) (*Application, error) {
	content, err := ioutil.ReadFile(path)

	if err != nil {
		return nil, fmt.Errorf("Your config file %s cannot be loaded: %s", path, err)
	}

	return NewFromConfig(string(content))
}

func NewFromConfig(content string) (*Application, error) {
	data := map[string]interface{}{}
	dec := json.NewDecoder(strings.NewReader(content))
	err := dec.Decode(&data)

	if err != nil {
		return nil, fmt.Errorf("Your config file %s cannot be parsed: %s", content, err)
	}

	jq := jsonq.NewQuery(data)

	return NewFromJsonQuery(jq)
}

func NewFromJsonQuery(jq *jsonq.JsonQuery) (*Application, error) {
	app := NewApplication()
	app.Jq = jq

	for _, initializer := range Initializers {
		err := initializer(jq, app)

		if err != nil {
			return nil, fmt.Errorf("An error occured during init: %s", err)
		}
	}

	return app, nil
}

func (app *Application) ServeHTTP(h Handler) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
		con := app.KVStore.Connection()
		defer con.Close()

		res := muxer.NewResponse(w)

		request, err := NewRequest(req, con, app.Jq)

		if err != nil {
			app.Logger.Error(err)

			res.BadRequest()

			return
		}

		if app.SecretKey != "" && !request.IsAuthorized(app.SecretKey) {
			res.Unauthorized()

			return
		}

		h(res, request, app)
	})
}

func (a *Application) InitRouter() *negroni.Negroni {
	router := mux.NewRouter()
	router.NotFoundHandler = NotFoundHandler()

	methods := map[string]Handler{
		"redirect": RedirectHandler,
		"display":  ImageHandler,
		"get":      GetHandler,
	}

	for name, handler := range methods {
		handlerFunc := a.ServeHTTP(handler)

		router.Handle(fmt.Sprintf("/%s", name), handlerFunc)
		router.Handle(fmt.Sprintf("/%s/{sig}/{op}/x{h:[\\d]+}/{path:[\\w\\-/.]+}", name), handlerFunc)
		router.Handle(fmt.Sprintf("/%s/{sig}/{op}/{w:[\\d]+}x/{path:[\\w\\-/.]+}", name), handlerFunc)
		router.Handle(fmt.Sprintf("/%s/{sig}/{op}/{w:[\\d]+}x{h:[\\d]+}/{path:[\\w\\-/.]+}", name), handlerFunc)
		router.Handle(fmt.Sprintf("/%s/{op}/x{h:[\\d]+}/{path:[\\w\\-/.]+}", name), handlerFunc)
		router.Handle(fmt.Sprintf("/%s/{op}/{w:[\\d]+}x/{path:[\\w\\-/.]+}", name), handlerFunc)
		router.Handle(fmt.Sprintf("/%s/{op}/{w:[\\d]+}x{h:[\\d]+}/{path:[\\w\\-/.]+}", name), handlerFunc)

		router.Handle(fmt.Sprintf("/%s/{w:[\\d]+}x{h:[\\d]+}/{path:[\\w\\-/.]+}", name), handlerFunc)
		router.Handle(fmt.Sprintf("/%s/{path:[\\w\\-/.]+}", name), handlerFunc)
	}

	router.Handle("/upload", http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
		res := muxer.NewResponse(w)

		UploadHandler(res, req, a)
	}))

	allowedOrigins, err := a.Jq.ArrayOfStrings("allowed_origins")
	allowedMethods, err := a.Jq.ArrayOfStrings("allowed_methods")

	s := stats.New()

	router.HandleFunc("/stats", func(w http.ResponseWriter, r *http.Request) {
		w.Header().Set("Content-Type", "application/json")

		stats := s.Data()

		b, _ := json.Marshal(stats)

		w.Write(b)
	})

	debug, err := a.Jq.Bool("debug")

	if err != nil {
		debug = false
	}

	n := negroni.New(&middleware.Recovery{
		Raven:      a.Raven,
		Logger:     a.Logger,
		PrintStack: debug,
		StackAll:   false,
		StackSize:  1024 * 8,
	}, &middleware.Logger{a.Logger})
	n.Use(cors.New(cors.Options{
		AllowedOrigins: allowedOrigins,
		AllowedMethods: allowedMethods,
	}))
	n.Use(negronilogrus.NewMiddleware())
	n.UseHandler(router)

	return n
}

func (a *Application) Port() int {
	port, err := a.Jq.Int("port")

	if err != nil {
		port = DefaultPort
	}

	return port
}

func (a *Application) ShardFilename(filename string) string {
	results := hash.Shard(filename, a.Shard.Width, a.Shard.Depth, true)

	return strings.Join(results, "/")
}

func (a *Application) Store(i *image.ImageFile, args ...string) error {
	con := a.KVStore.Connection()
	defer con.Close()

	err := i.Save()

	if err != nil {
		a.Logger.Fatal(err)
		return err
	}

	tipe := "thumbnail"
	if len(args) > 0 {
		tipe = args[0]
	}

	a.Logger.Infof("Save %s %s to storage", tipe, i.Filepath)

	key := a.WithPrefix(i.Key)

	err = con.Set(key, i.Filepath)

	if err != nil {
		a.Logger.Fatal(err)

		return err
	}

	a.Logger.Infof("Save key %s => %s to kvstore", key, i.Filepath)

	return nil
}

func (a *Application) WithPrefix(str string) string {
	return a.Prefix + str
}

func (a *Application) ImageFileFromRequest(req *Request, async bool, load bool) (*image.ImageFile, error) {
	var file *image.ImageFile = &image.ImageFile{
		Key:     req.Key,
		Storage: a.DestStorage,
		Headers: map[string]string{},
	}
	var err error

	key := a.WithPrefix(req.Key)

	// Image from the KVStore found
	stored, _ := gokvstores.String(req.Connection.Get(key))

	file.Filepath = stored

	if stored != "" {
		a.Logger.Infof("Key %s found in kvstore: %s", key, stored)

		if load {
			file, err = image.FromStorage(a.DestStorage, stored)

			if file == nil || err != nil {
				stored = ""
				err = nil
			}

			// if err != nil {
			// 	return nil, err
			// }
		}
	}

	if stored == "" {
		a.Logger.Infof("Key %s not found in kvstore OR file not found in dst", key)

		// Image not found from the KVStore, we need to process it
		// URL or Path available in Query String
		cacheOriginal := false
		fileKey := ""
		kvKey := ""
		if req.URL != nil {
			return nil, errors.New("404")
		} else {
			// URL provided we use http protocol to retrieve it
			fileKey = hash.Tokey(hash.Serialize(req.Filepath))
			kvKey = a.WithPrefix(fileKey)
			fileStored, err := gokvstores.String(req.Connection.Get(kvKey))
			if fileStored != "" {
				a.Logger.Infof("Key %s for original found in kvstore: %s", kvKey, fileStored)

				if load {
					file, err = image.FromStorage(a.DestStorage, fileStored)
					// not found in dest storage? Try getting from src storage
					if file == nil || err != nil {
						a.Logger.Infof("File %s for key %s not found in dst, try reget from src", fileStored, kvKey)
						file, err = image.FromStorage(a.SourceStorage, req.Filepath)
						if file == nil {
							return nil, errors.New("404")
						}
						cacheOriginal = true
					}
				}
			} else {
				file, err = image.FromStorage(a.SourceStorage, req.Filepath)
				if file == nil {
					return nil, errors.New("404")
				}
				cacheOriginal = true
			}
		}

		if err != nil {
			return nil, err
		}

		if cacheOriginal == true && fileKey != "" {
			file.Key = fileKey
			file.Storage = a.DestStorage
			file.Filepath = fmt.Sprintf("%s.%s", a.ShardFilename(fileKey), file.Format())
			if async == true {
				go a.Store(file, "original")
			} else {
				err = a.Store(file, "original")
			}
		}

		if err != nil {
			return nil, err
		}

		imageOrig, err := imaging.Decode(bytes.NewReader(file.Source))
		if err != nil {
			return nil, err
		}
		width, height := engines.ImageSize(imageOrig)
		rw, err := strconv.Atoi(req.QueryString["w"])
		if err != nil {
			return nil, err
		}
		rh, err := strconv.Atoi(req.QueryString["h"])
		if err != nil {
			return nil, err
		}
		if rw < width && rh < height {
			file, err = a.Engine.Transform(file, req.Operation, req.QueryString)
		} else {
			stored = "do not store"
		}

		// file, err = a.Engine.Transform(file, req.Operation, req.QueryString)

		if err != nil {
			return nil, err
		}
	}

	file.Headers["Content-Type"] = file.ContentType()
	file.Headers["ETag"] = req.Key

	if stored == "" {
		file.Filepath = fmt.Sprintf("%s.%s", a.ShardFilename(req.Key), file.Format())
		file.Key = req.Key
		file.Storage = a.DestStorage
		if async == true {
			go a.Store(file)
		} else {
			err = a.Store(file)
		}
	}

	return file, err
}
<|endoftext|>


<commit_before>package ast

import (
	"encoding/json"

	"github.com/carlcui/expressive/symbolTable"
	"github.com/carlcui/expressive/token"
	"github.com/carlcui/expressive/typing"
)

// IdentifierNode represents an identifier node.
type IdentifierNode struct {
	*BaseNode
	binding       *symbolTable.Binding
	declaredScope *symbolTable.Scope
}

func (node *IdentifierNode) SetBinding(binding *symbolTable.Binding) {
	node.binding = binding
}

func (node *IdentifierNode) GetBinding() *symbolTable.Binding {
	return node.binding
}

func (node *IdentifierNode) IsBeingDeclared() bool {
	if node.Parent == nil {
		return false
	}

	declarationNode, ok := node.Parent.(*VariableDeclarationNode)

	if !ok {
		return false
	}

	return declarationNode.Identifier == node
}

func (node *IdentifierNode) FindDeclarationScope() *symbolTable.Scope {
	identifier := node.Tok.Raw

	scope := node.GetLocalScope()
	found := scope.VariableDeclared(identifier)

	for !found && scope.BaseScope != nil {
		scope = scope.BaseScope
		found = scope.VariableDeclared(identifier)
	}

	if !found {
		return nil
	}

	return scope
}

func (node *IdentifierNode) FindVariableBinding() *symbolTable.Binding {
	identifier := node.Tok.Raw

	scope := node.FindDeclarationScope()

	return scope.FindBinding(identifier)
}

// LocalIdentifier returns the localized identifier name in corresponding scope (appends scope identifier)
func (node *IdentifierNode) LocalIdentifier() string {
	scope := node.FindDeclarationScope()

	if scope == nil {
		panic("cannot get local scope for identifier node")
	}

	return node.BaseNode.Tok.Raw + scope.GetScopeIdentifier()
}

// Accept is part of visitor pattern.
func (node *IdentifierNode) Accept(visitor Visitor) {
	visitor.VisitIdentifierNode(node)
}

// VisitChildren is part of visitor pattern. Literal node does not have any child.
func (node *IdentifierNode) VisitChildren(visitor Visitor) {

}

func (node *IdentifierNode) MarshalJSON() ([]byte, error) {
	return json.Marshal(struct {
		NodeType string
		Token    *token.Token
		Typing   typing.Typing
		Binding  *symbolTable.Binding
	}{
		NodeType: "identifier",
		Token:    node.BaseNode.Tok,
		Typing:   node.Typing,
		Binding:  node.binding,
	})
}
<commit_msg>fix null reference when getting binding for identifier with null scope<commit_after>package ast

import (
	"encoding/json"

	"github.com/carlcui/expressive/symbolTable"
	"github.com/carlcui/expressive/token"
	"github.com/carlcui/expressive/typing"
)

// IdentifierNode represents an identifier node.
type IdentifierNode struct {
	*BaseNode
	binding       *symbolTable.Binding
	declaredScope *symbolTable.Scope
}

func (node *IdentifierNode) SetBinding(binding *symbolTable.Binding) {
	node.binding = binding
}

func (node *IdentifierNode) GetBinding() *symbolTable.Binding {
	return node.binding
}

func (node *IdentifierNode) IsBeingDeclared() bool {
	if node.Parent == nil {
		return false
	}

	declarationNode, ok := node.Parent.(*VariableDeclarationNode)

	if !ok {
		return false
	}

	return declarationNode.Identifier == node
}

func (node *IdentifierNode) FindDeclarationScope() *symbolTable.Scope {
	identifier := node.Tok.Raw

	scope := node.GetLocalScope()
	found := scope.VariableDeclared(identifier)

	for !found && scope.BaseScope != nil {
		scope = scope.BaseScope
		found = scope.VariableDeclared(identifier)
	}

	if !found {
		return nil
	}

	return scope
}

func (node *IdentifierNode) FindVariableBinding() *symbolTable.Binding {
	identifier := node.Tok.Raw

	scope := node.FindDeclarationScope()

	if scope == nil {
		return nil
	}

	return scope.FindBinding(identifier)
}

// LocalIdentifier returns the localized identifier name in corresponding scope (appends scope identifier)
func (node *IdentifierNode) LocalIdentifier() string {
	scope := node.FindDeclarationScope()

	if scope == nil {
		panic("cannot get local scope for identifier node")
	}

	return node.BaseNode.Tok.Raw + scope.GetScopeIdentifier()
}

// Accept is part of visitor pattern.
func (node *IdentifierNode) Accept(visitor Visitor) {
	visitor.VisitIdentifierNode(node)
}

// VisitChildren is part of visitor pattern. Literal node does not have any child.
func (node *IdentifierNode) VisitChildren(visitor Visitor) {

}

func (node *IdentifierNode) MarshalJSON() ([]byte, error) {
	return json.Marshal(struct {
		NodeType string
		Token    *token.Token
		Typing   typing.Typing
		Binding  *symbolTable.Binding
	}{
		NodeType: "identifier",
		Token:    node.BaseNode.Tok,
		Typing:   node.Typing,
		Binding:  node.binding,
	})
}
<|endoftext|>


<commit_before>package home

import (
  "errors"
  "github.com/keep94/appcommon/http_util"
  "github.com/keep94/finance/fin"
  "github.com/keep94/mortgage"
  "github.com/keep94/mortgage/apps/mortgage/common"
  "html/template"
  "net/http"
  "net/url"
  "strconv"
)

const (
  kRowsAtTop = 1
)

var (
kTemplateSpec = `

  <title>Mortgage</title>
  <link rel="stylesheet" type="text/css" href="/static/theme.css" />
  <link rel="shortcut icon" href="/images/favicon.ico" type="image/x-icon" />

Mortgage

{{if .Error}}
  {{.Error}}
{{end}}
<form>

      Start Date:

        <select name="month">
{{with .GetSelection .Months "month"}}
          <option value="{{.Value}}">{{.Name}}</option>
{{else}}
          <option value="">--Pick one--</option>
{{end}}
{{range .Months.Items}}
          <option value="{{.Value}}">{{.Name}}</option>
{{end}}
        </select>
        <input type="text" name="year" value="{{.Get "year"}}">

     Amount:
     <input type="text" name="amount" value="{{.Get "amount"}}">

     Rate:
     <input type="text" name="rate" value="{{.Get "rate"}}">%

     Term in months:
     <input type="text" name="term" value="{{.Get "term"}}">

  <input type="submit" name="calculate" value="Calculate">
</form>
{{if .Loan}}

    Monthly payment:
    {{FormatUSD .Loan.Payment}}

    Total Cost:
    {{FormatUSD .Totals.Payment}}

    Total Finance Charges:
    {{FormatUSD .Totals.Interest}}

    Date
    Payment
    Interest
    Principal
    Balance

  {{range $year, $ytotals := .Totals.Years}}
    {{range $ytotals.Terms}}

    {{FormatDate .Date}}
    {{FormatUSD .Payment}}
    {{FormatUSD .Interest}}
    {{FormatUSD .Principal}}
    {{FormatUSD .Balance}}

    {{end}}

    {{$year}} Totals
    {{FormatUSD $ytotals.Payment}}
    {{FormatUSD $ytotals.Interest}}
    {{FormatUSD $ytotals.Principal}}
    &nbsp

  {{end}}
{{end}}

`
)

var (
  kTemplate *template.Template
)

var (
  kMaxTerms = 1200
  kMonths = http_util.ComboBox{
      {"January", 1},
      {"February", 2},
      {"March", 3},
      {"April", 4},
      {"May", 5},
      {"June", 6},
      {"July", 7},
      {"August", 8},
      {"September", 9},
      {"October", 10},
      {"November", 11},
      {"December", 12},
  }
)

type Handler struct {
}

func (h Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
  r.ParseForm()
  if hasNoneOf(r.Form, "month", "year", "amount", "rate", "term") {
    http_util.WriteTemplate(
        w,
        kTemplate,
        &view{
            Values: http_util.Values{r.Form},
            Months: kMonths,
        })
    return
  }
  month, _ := kMonths.ToValue(r.Form.Get("month")).(int)
  year, _ := strconv.Atoi(r.Form.Get("year"))
  amount, _ := fin.ParseUSD(r.Form.Get("amount"))
  rate, _ := strconv.ParseFloat(r.Form.Get("rate"), 64)
  rate /= 100.0
  length, _ := strconv.Atoi(r.Form.Get("term"))
  var message string
  if month == 0 {
    message = "Please choose a month."
  } else if year < 1900 || year > 2200 {
    message = "Please enter a year between 1900 and 2200"
  } else if amount <= 0 {
    message = "Please enter a positive amount."
  } else if length <= 0 {
    message = "Please enter a positive term in months."
  }
  if message != "" {
    http_util.WriteTemplate(
        w,
        kTemplate,
        &view{
            Values: http_util.Values{r.Form},
            Months: kMonths,
            Error: errors.New(message),
        })
    return
  }
  loan := mortgage.NewLoan(amount, rate, length)
  terms := loan.Terms(year, month, kMaxTerms + 1)
  if len(terms) == kMaxTerms + 1 {
    http_util.WriteTemplate(
        w,
        kTemplate,
        &view{
            Values: http_util.Values{r.Form},
            Months: kMonths,
            Error: errors.New("Too many terms to display"),
        })
    return
  }
  http_util.WriteTemplate(
      w,
      kTemplate,
      &view{
          Values: http_util.Values{r.Form},
          Loan: loan,
          Totals: aggregate(terms),
          Months: kMonths,
      })
}

type yearTotals struct {
  Principal int64
  Interest int64
  Payment int64
  start int
  end int
  terms []*mortgage.Term
}

func newYearTotals(terms []*mortgage.Term, idx int) *yearTotals {
  return &yearTotals{
      start: idx,
      end: idx,
      terms: terms}
}

func (y *yearTotals) Terms() []*mortgage.Term {
  return y.terms[y.start:y.end]
}

func (y *yearTotals) add() {
  y.Principal += y.terms[y.end].Principal()
  y.Interest += y.terms[y.end].Interest
  y.Payment += y.terms[y.end].Payment
  y.end++
}

type loanTotals struct {
  Principal int64
  Interest int64
  Payment int64
  Years map[int]*yearTotals
}

type view struct {
  http_util.Values
  Loan *mortgage.Loan
  Totals *loanTotals
  Error error
  Months http_util.ComboBox
}

func aggregate(terms []*mortgage.Term) *loanTotals {
  result := &loanTotals{Years: make(map[int]*yearTotals)}
  for i := range terms {
    result.Payment += terms[i].Payment
    result.Interest += terms[i].Interest
    result.Principal += terms[i].Principal()
    year := terms[i].Date.Year()
    yTotal := result.Years[year]
    if yTotal == nil {
      yTotal = newYearTotals(terms, i)
      result.Years[year] = yTotal
    }
    yTotal.add()
  }
  return result
}

func hasNoneOf(values url.Values, paramNames... string) bool {
  for _, name := range paramNames {
    if http_util.HasParam(values, name) {
      return false
    }
  }
  return true
}

func init() {
  kTemplate = common.NewTemplate("home", kTemplateSpec)
}
<commit_msg>Let Jan 1 payments be included in previous year totals.<commit_after>package home

import (
  "errors"
  "github.com/keep94/appcommon/http_util"
  "github.com/keep94/finance/fin"
  "github.com/keep94/mortgage"
  "github.com/keep94/mortgage/apps/mortgage/common"
  "html/template"
  "net/http"
  "net/url"
  "strconv"
)

const (
  kRowsAtTop = 1
)

var (
kTemplateSpec = `

  <title>Mortgage</title>
  <link rel="stylesheet" type="text/css" href="/static/theme.css" />
  <link rel="shortcut icon" href="/images/favicon.ico" type="image/x-icon" />

Mortgage

{{if .Error}}
  {{.Error}}
{{end}}
<form>

      Start Date:

        <select name="month">
{{with .GetSelection .Months "month"}}
          <option value="{{.Value}}">{{.Name}}</option>
{{else}}
          <option value="">--Pick one--</option>
{{end}}
{{range .Months.Items}}
          <option value="{{.Value}}">{{.Name}}</option>
{{end}}
        </select>
        <input type="text" name="year" value="{{.Get "year"}}">

     Amount:
     <input type="text" name="amount" value="{{.Get "amount"}}">

     Rate:
     <input type="text" name="rate" value="{{.Get "rate"}}">%

     Term in months:
     <input type="text" name="term" value="{{.Get "term"}}">

  <input type="submit" name="calculate" value="Calculate">
</form>
{{if .Loan}}

    Monthly payment:
    {{FormatUSD .Loan.Payment}}

    Total Cost:
    {{FormatUSD .Totals.Payment}}

    Total Finance Charges:
    {{FormatUSD .Totals.Interest}}

    Date
    Payment
    Interest
    Principal
    Balance

  {{range $year, $ytotals := .Totals.Years}}
    {{range $ytotals.Terms}}

    {{FormatDate .Date}}
    {{FormatUSD .Payment}}
    {{FormatUSD .Interest}}
    {{FormatUSD .Principal}}
    {{FormatUSD .Balance}}

    {{end}}

    {{$year}} Totals
    {{FormatUSD $ytotals.Payment}}
    {{FormatUSD $ytotals.Interest}}
    {{FormatUSD $ytotals.Principal}}
    &nbsp

  {{end}}
{{end}}

`
)

var (
  kTemplate *template.Template
)

var (
  kMaxTerms = 1200
  kMonths = http_util.ComboBox{
      {"January", 1},
      {"February", 2},
      {"March", 3},
      {"April", 4},
      {"May", 5},
      {"June", 6},
      {"July", 7},
      {"August", 8},
      {"September", 9},
      {"October", 10},
      {"November", 11},
      {"December", 12},
  }
)

type Handler struct {
}

func (h Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
  r.ParseForm()
  if hasNoneOf(r.Form, "month", "year", "amount", "rate", "term") {
    http_util.WriteTemplate(
        w,
        kTemplate,
        &view{
            Values: http_util.Values{r.Form},
            Months: kMonths,
        })
    return
  }
  month, _ := kMonths.ToValue(r.Form.Get("month")).(int)
  year, _ := strconv.Atoi(r.Form.Get("year"))
  amount, _ := fin.ParseUSD(r.Form.Get("amount"))
  rate, _ := strconv.ParseFloat(r.Form.Get("rate"), 64)
  rate /= 100.0
  length, _ := strconv.Atoi(r.Form.Get("term"))
  var message string
  if month == 0 {
    message = "Please choose a month."
  } else if year < 1900 || year > 2200 {
    message = "Please enter a year between 1900 and 2200"
  } else if amount <= 0 {
    message = "Please enter a positive amount."
  } else if length <= 0 {
    message = "Please enter a positive term in months."
  }
  if message != "" {
    http_util.WriteTemplate(
        w,
        kTemplate,
        &view{
            Values: http_util.Values{r.Form},
            Months: kMonths,
            Error: errors.New(message),
        })
    return
  }
  loan := mortgage.NewLoan(amount, rate, length)
  terms := loan.Terms(year, month, kMaxTerms + 1)
  if len(terms) == kMaxTerms + 1 {
    http_util.WriteTemplate(
        w,
        kTemplate,
        &view{
            Values: http_util.Values{r.Form},
            Months: kMonths,
            Error: errors.New("Too many terms to display"),
        })
    return
  }
  http_util.WriteTemplate(
      w,
      kTemplate,
      &view{
          Values: http_util.Values{r.Form},
          Loan: loan,
          Totals: aggregate(terms),
          Months: kMonths,
      })
}

type yearTotals struct {
  Principal int64
  Interest int64
  Payment int64
  start int
  end int
  terms []*mortgage.Term
}

func newYearTotals(terms []*mortgage.Term, idx int) *yearTotals {
  return &yearTotals{
      start: idx,
      end: idx,
      terms: terms}
}

func (y *yearTotals) Terms() []*mortgage.Term {
  return y.terms[y.start:y.end]
}

func (y *yearTotals) add() {
  y.Principal += y.terms[y.end].Principal()
  y.Interest += y.terms[y.end].Interest
  y.Payment += y.terms[y.end].Payment
  y.end++
}

type loanTotals struct {
  Principal int64
  Interest int64
  Payment int64
  Years map[int]*yearTotals
}

type view struct {
  http_util.Values
  Loan *mortgage.Loan
  Totals *loanTotals
  Error error
  Months http_util.ComboBox
}

func aggregate(terms []*mortgage.Term) *loanTotals {
  result := &loanTotals{Years: make(map[int]*yearTotals)}
  for i := range terms {
    result.Payment += terms[i].Payment
    result.Interest += terms[i].Interest
    result.Principal += terms[i].Principal()
    // This way payments due on Jan 1 are aggregated with previous year.
    // We assume payment is made one day before due date. While this
    // does the right thing for payments due on the 1st, generally it won't
    // work if we ever support payments due on a day other than the 1st
    // because then it depends on when payment is made.
    year := terms[i].Date.AddDate(0, 0, -1).Year()
    yTotal := result.Years[year]
    if yTotal == nil {
      yTotal = newYearTotals(terms, i)
      result.Years[year] = yTotal
    }
    yTotal.add()
  }
  return result
}

func hasNoneOf(values url.Values, paramNames... string) bool {
  for _, name := range paramNames {
    if http_util.HasParam(values, name) {
      return false
    }
  }
  return true
}

func init() {
  kTemplate = common.NewTemplate("home", kTemplateSpec)
}
<|endoftext|>


<commit_before>package pbReader

import (
	"errors"
	"fmt"
	"log"
	"sync"

	"github.com/dh1tw/remoteAudio/audio"
	"github.com/dh1tw/remoteAudio/audiocodec/opus"
	sbAudio "github.com/dh1tw/remoteAudio/sb_audio"
	"github.com/gogo/protobuf/proto"
)

// PbReader implements the audio.Source interface and is used to read
// audio frames encapsulated in Protocol Buffer messages, typically
// received from the network.
type PbReader struct {
	sync.RWMutex
	options Options
	enabled bool
}

func NewPbReader(opts ...Option) (*PbReader, error) {

	pbr := &PbReader{
		options: Options{
			DeviceName: "ProtoBufReader",
			Channels:   1,
			Samplerate: 48000,
		},
	}

	for _, option := range opts {
		option(&pbr.options)
	}

	decChannels := opus.Channels(pbr.options.Channels)
	decSR := opus.Samplerate(pbr.options.Samplerate)

	dec, err := opus.NewOpusDecoder(decChannels, decSR)
	if err != nil {
		return nil, err
	}

	pbr.options.Decoder = dec

	return pbr, nil
}

func (pbr *PbReader) Start() error {
	pbr.Lock()
	defer pbr.Unlock()
	pbr.enabled = true
	return nil
}

func (pbr *PbReader) Stop() error {
	pbr.Lock()
	defer pbr.Unlock()
	pbr.enabled = false
	return nil
}

func (pbr *PbReader) Close() error {
	return nil
}

func (pbr *PbReader) SetCb(cb audio.OnDataCb) {
	pbr.Lock()
	defer pbr.Unlock()
	pbr.options.Callback = cb
}

func (pbr *PbReader) Enqueue(data []byte) error {
	pbr.Lock()
	defer pbr.Unlock()

	if pbr.options.Callback == nil {
		return nil
	}

	if !pbr.enabled {
		return nil
	}

	if pbr.options.Decoder == nil {
		return errors.New("no decoder set")
	}

	if len(data) == 0 {
		log.Println("incoming audio frame empty")
		return nil
	}

	msg := sbAudio.Frame{}
	err := proto.Unmarshal(data, &msg)
	if err != nil {
		return err
	}

	if msg.Codec.String() != pbr.options.Decoder.Name() {
		return fmt.Errorf("unknown codec %v", msg.Codec.String())
	}

	buf := make([]float32, msg.FrameLength)

	num, err := pbr.options.Decoder.Decode(msg.Data, buf)
	if err != nil {
		return err
	}

	audioMsg := audio.Msg{
		Channels:   pbr.options.Channels,
		Data:       buf,
		EOF:        false,
		Frames:     num,
		IsStream:   true,
		Samplerate: pbr.options.Samplerate,
	}

	pbr.options.Callback(audioMsg)

	return nil
}
<commit_msg>accept decoder via option<commit_after>package pbReader

import (
	"errors"
	"fmt"
	"log"
	"sync"

	"github.com/dh1tw/remoteAudio/audio"
	"github.com/dh1tw/remoteAudio/audiocodec/opus"
	sbAudio "github.com/dh1tw/remoteAudio/sb_audio"
	"github.com/gogo/protobuf/proto"
)

// PbReader implements the audio.Source interface and is used to read
// audio frames encapsulated in Protocol Buffer messages, typically
// received from the network.
type PbReader struct {
	sync.RWMutex
	options Options
	enabled bool
}

// NewPbReader is the constructor for a PbReader object.
func NewPbReader(opts ...Option) (*PbReader, error) {

	pbr := &PbReader{
		options: Options{
			DeviceName: "ProtoBufReader",
			Channels:   1,
			Samplerate: 48000,
		},
	}

	for _, option := range opts {
		option(&pbr.options)
	}

	// if no decoder was passed in as a function we create
	// our default opus decoder
	if pbr.options.Decoder == nil {
		decChannels := opus.Channels(pbr.options.Channels)
		decSR := opus.Samplerate(pbr.options.Samplerate)

		dec, err := opus.NewOpusDecoder(decChannels, decSR)
		if err != nil {
			return nil, err
		}
		pbr.options.Decoder = dec
	}

	return pbr, nil
}

func (pbr *PbReader) Start() error {
	pbr.Lock()
	defer pbr.Unlock()
	pbr.enabled = true
	return nil
}

func (pbr *PbReader) Stop() error {
	pbr.Lock()
	defer pbr.Unlock()
	pbr.enabled = false
	return nil
}

func (pbr *PbReader) Close() error {
	return nil
}

func (pbr *PbReader) SetCb(cb audio.OnDataCb) {
	pbr.Lock()
	defer pbr.Unlock()
	pbr.options.Callback = cb
}

func (pbr *PbReader) Enqueue(data []byte) error {
	pbr.Lock()
	defer pbr.Unlock()

	if pbr.options.Callback == nil {
		return nil
	}

	if !pbr.enabled {
		return nil
	}

	if pbr.options.Decoder == nil {
		return errors.New("no decoder set")
	}

	if len(data) == 0 {
		log.Println("incoming audio frame empty")
		return nil
	}

	msg := sbAudio.Frame{}
	err := proto.Unmarshal(data, &msg)
	if err != nil {
		return err
	}

	if msg.Codec.String() != pbr.options.Decoder.Name() {
		return fmt.Errorf("unknown codec %v", msg.Codec.String())
	}

	buf := make([]float32, msg.FrameLength)

	num, err := pbr.options.Decoder.Decode(msg.Data, buf)
	if err != nil {
		return err
	}

	audioMsg := audio.Msg{
		Channels:   pbr.options.Channels,
		Data:       buf,
		EOF:        false,
		Frames:     num,
		IsStream:   true,
		Samplerate: pbr.options.Samplerate, // we want 48kHz for internal processing
	}

	pbr.options.Callback(audioMsg)

	return nil
}
<|endoftext|>


<commit_before>package atom

import (
	"github.com/JREAMLU/core/com"
	"github.com/astaxie/beego"
)

var IP string

func init() {
	IP = com.GetServerIP()
}

func GetHeader(requestID string) map[string]string {
	var header = map[string]string{
		"Content-Type":    beego.AppConfig.String("Content-Type"),
		"Accept":          beego.AppConfig.String("Accept"),
		"Accept-Language": beego.AppConfig.String("lang.default"),
		"source":          beego.AppConfig.String("appname"),
		"Request-ID":      requestID,
		"ip":              IP,
	}

	return header
}
<commit_msg>update get ip func<commit_after>package atom

import (
	"github.com/JREAMLU/core/com"
	"github.com/astaxie/beego"
)

var IP string

func init() {
	IP, _ = com.ExternalIP()
}

func GetHeader(requestID string) map[string]string {
	var header = map[string]string{
		"Content-Type":    beego.AppConfig.String("Content-Type"),
		"Accept":          beego.AppConfig.String("Accept"),
		"Accept-Language": beego.AppConfig.String("lang.default"),
		"source":          beego.AppConfig.String("appname"),
		"Request-ID":      requestID,
		"ip":              IP,
	}

	return header
}
<|endoftext|>