<commit_before>package main

import (
	"io/ioutil"
	"net/http"
	"net/http/httptest"
	"testing"
)

type testRequest struct {
	smartFolderID int
	siteID        int
	tags          string
	testIDs       string
	want          string
}

func newTestPostServer(check func([]byte)) *httptest.Server {
	return httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		body, err := ioutil.ReadAll(r.Body)
		if err != nil {
			panic(err)
		}
		check(body)
		w.WriteHeader(200)
		w.Write([]byte("Success"))
	}))
}

func TestRunByTags(t *testing.T) {
	testCases := []testRequest{
		{
			tags: "foo,bar",
			want: `{"tags":["foo","bar"]}`,
		},
		{
			tags: "foo",
			want: `{"tags":["foo"]}`,
		},
		{
			tags: "foo,bar     ",
			want: `{"tags":["foo","bar"]}`,
		},
		{
			tags: "    foo,bar",
			want: `{"tags":["foo","bar"]}`,
		},
		{
			testIDs: "200,300",
			tags:    "foo,bar",
			want:    `{"tests":"200,300"}`,
		},
	}
	for _, test := range testCases {
		checkBody := func(body []byte) {
			if string(body) != test.want {
				t.Errorf(`expected %v got %v`, test.want, string(body))
			}
		}
		ts := newTestPostServer(checkBody)
		baseURL = ts.URL
		smartFolderID = test.smartFolderID
		siteID = test.siteID
		tags = test.tags
		testIDs = test.testIDs
		createRun()
		ts.Close()
	}
}

func TestRunBySmartFolder(t *testing.T) {
	testCases := []testRequest{
		{
			smartFolderID: 0,
			want:          `{}`,
		},
		{
			smartFolderID: 200,
			want:          `{"smart_folder_id":200}`,
		},
		{
			testIDs:       "200,300",
			smartFolderID: 200,
			want:          `{"tests":"200,300"}`,
		},
	}
	for _, test := range testCases {
		checkBody := func(body []byte) {
			if string(body) != test.want {
				t.Errorf(`expected %v, got %v`, test.want, string(body))
			}
		}
		ts := newTestPostServer(checkBody)
		defer ts.Close()
		baseURL = ts.URL
		smartFolderID = test.smartFolderID
		siteID = test.siteID
		tags = test.tags
		testIDs = test.testIDs
		createRun()
	}
}

func TestRunBySiteId(t *testing.T) {
	testCases := []testRequest{
		{
			siteID: 0,
			want:   `{}`,
		},
		{
			siteID: 200,
			want:   `{"site_id":200}`,
		},
		{
			testIDs: "200,300",
			siteID:  200,
			want:    `{"tests":"200,300"}`,
		},
	}
	for _, test := range testCases {
		checkBody := func(body []byte) {
			if string(body) != test.want {
				t.Errorf(`expected %v, got %v`, test.want, string(body))
			}
		}
		ts := newTestPostServer(checkBody)
		defer ts.Close()
		baseURL = ts.URL
		smartFolderID = test.smartFolderID
		siteID = test.siteID
		tags = test.tags
		testIDs = test.testIDs
		createRun()
	}
}

func TestRunByTestID(t *testing.T) {
	testCases := []testRequest{
		{
			testIDs: "200",
			want:    `{"tests":"200"}`,
		},
		{
			testIDs: "",
			want:    `{}`,
		},
		{
			testIDs: "200,300",
			siteID:  200,
			want:    `{"tests":"200,300"}`,
		},
		{
			testIDs: "	200,300,400	",
			siteID: 200,
			want:   `{"tests":"200,300,400"}`,
		},
		{
			testIDs: " 200,300,400 ",
			siteID:  200,
			want:    `{"tests":"200,300,400"}`,
		},
		{
			smartFolderID: 200,
			siteID:        300,
			tags:          "foo, bar",
			testIDs:       "300,500,800",
			want:          `{"tests":"300,500,800"}`,
		},
	}

	for _, test := range testCases {
		checkBody := func(body []byte) {
			if string(body) != test.want {
				t.Errorf(`expected %v, got %v`, test.want, string(body))
			}
		}
		ts := newTestPostServer(checkBody)
		defer ts.Close()
		baseURL = ts.URL
		smartFolderID = test.smartFolderID
		siteID = test.siteID
		tags = test.tags
		testIDs = test.testIDs
		createRun()
	}
}
<commit_msg>added test for tags containing spaces<commit_after>package main

import (
	"io/ioutil"
	"net/http"
	"net/http/httptest"
	"testing"
)

type testRequest struct {
	smartFolderID int
	siteID        int
	tags          string
	testIDs       string
	want          string
}

func newTestPostServer(check func([]byte)) *httptest.Server {
	return httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		body, err := ioutil.ReadAll(r.Body)
		if err != nil {
			panic(err)
		}
		check(body)
		w.WriteHeader(200)
		w.Write([]byte("Success"))
	}))
}

func TestRunByTags(t *testing.T) {
	testCases := []testRequest{
		{
			tags: "foo,bar",
			want: `{"tags":["foo","bar"]}`,
		},
		{
			tags: "foo",
			want: `{"tags":["foo"]}`,
		},
		{
			tags: "foo bar,bar foo",
			want: `{"tags":["foo bar","bar foo"]}`,
		},
		{
			tags: "foo,bar     ",
			want: `{"tags":["foo","bar"]}`,
		},
		{
			tags: "    foo,bar",
			want: `{"tags":["foo","bar"]}`,
		},
		{
			testIDs: "200,300",
			tags:    "foo,bar",
			want:    `{"tests":"200,300"}`,
		},
	}
	for _, test := range testCases {
		checkBody := func(body []byte) {
			if string(body) != test.want {
				t.Errorf(`expected %v got %v`, test.want, string(body))
			}
		}
		ts := newTestPostServer(checkBody)
		baseURL = ts.URL
		smartFolderID = test.smartFolderID
		siteID = test.siteID
		tags = test.tags
		testIDs = test.testIDs
		createRun()
		ts.Close()
	}
}

func TestRunBySmartFolder(t *testing.T) {
	testCases := []testRequest{
		{
			smartFolderID: 0,
			want:          `{}`,
		},
		{
			smartFolderID: 200,
			want:          `{"smart_folder_id":200}`,
		},
		{
			testIDs:       "200,300",
			smartFolderID: 200,
			want:          `{"tests":"200,300"}`,
		},
	}
	for _, test := range testCases {
		checkBody := func(body []byte) {
			if string(body) != test.want {
				t.Errorf(`expected %v, got %v`, test.want, string(body))
			}
		}
		ts := newTestPostServer(checkBody)
		defer ts.Close()
		baseURL = ts.URL
		smartFolderID = test.smartFolderID
		siteID = test.siteID
		tags = test.tags
		testIDs = test.testIDs
		createRun()
	}
}

func TestRunBySiteId(t *testing.T) {
	testCases := []testRequest{
		{
			siteID: 0,
			want:   `{}`,
		},
		{
			siteID: 200,
			want:   `{"site_id":200}`,
		},
		{
			testIDs: "200,300",
			siteID:  200,
			want:    `{"tests":"200,300"}`,
		},
	}
	for _, test := range testCases {
		checkBody := func(body []byte) {
			if string(body) != test.want {
				t.Errorf(`expected %v, got %v`, test.want, string(body))
			}
		}
		ts := newTestPostServer(checkBody)
		defer ts.Close()
		baseURL = ts.URL
		smartFolderID = test.smartFolderID
		siteID = test.siteID
		tags = test.tags
		testIDs = test.testIDs
		createRun()
	}
}

func TestRunByTestID(t *testing.T) {
	testCases := []testRequest{
		{
			testIDs: "200",
			want:    `{"tests":"200"}`,
		},
		{
			testIDs: "",
			want:    `{}`,
		},
		{
			testIDs: "200,300",
			siteID:  200,
			want:    `{"tests":"200,300"}`,
		},
		{
			testIDs: "	200,300,400	",
			siteID: 200,
			want:   `{"tests":"200,300,400"}`,
		},
		{
			testIDs: " 200,300,400 ",
			siteID:  200,
			want:    `{"tests":"200,300,400"}`,
		},
		{
			smartFolderID: 200,
			siteID:        300,
			tags:          "foo, bar",
			testIDs:       "300,500,800",
			want:          `{"tests":"300,500,800"}`,
		},
	}

	for _, test := range testCases {
		checkBody := func(body []byte) {
			if string(body) != test.want {
				t.Errorf(`expected %v, got %v`, test.want, string(body))
			}
		}
		ts := newTestPostServer(checkBody)
		defer ts.Close()
		baseURL = ts.URL
		smartFolderID = test.smartFolderID
		siteID = test.siteID
		tags = test.tags
		testIDs = test.testIDs
		createRun()
	}
}
<|endoftext|>


<commit_before>// Package trace provies an experimental API for initiating
// traces. Veneur's tracing API also provides
// an opentracing compatibility layer. The Veneur tracing API
// is completely independent of the opentracing
// compatibility layer, with the exception of one convenience
// function.
package trace

import (
	"context"
	"errors"
	"fmt"
	"io"
	"math/rand"
	"net"
	"reflect"
	"runtime"
	"strconv"
	"strings"
	"sync"
	"time"

	"github.com/stripe/veneur/ssf"

	"github.com/Sirupsen/logrus"
	"github.com/golang/protobuf/proto"
	opentracing "github.com/opentracing/opentracing-go"
)

// Experimental
const NameKey = "name"

// Experimental
const ResourceKey = "resource"

func init() {
	rand.Seed(time.Now().Unix())
}

// (Experimental)
// If this is set to true,
// traces will be generated but not actually sent.
// This should only be set before any traces are generated
var disabled bool = false

var enabledMtx sync.RWMutex

var udpConn *net.UDPConn

// used to initialize udpConn inside sendSample
var udpInitOnce sync.Once
var udpInitFunc = func() { initUDPConn(localVeneurAddress) }
var udpConnUninitializedErr = errors.New("UDP connection is not yet initialized")

// Make an unexported `key` type that we use as a String such
// that we don't get lint warnings from using it as a key in
// Context. See https://blog.golang.org/context#TOC_3.2.
type key string

const traceKey key = "trace"

// Service is our service name and should be set exactly once,
// at startup
var Service = ""

const localVeneurAddress = "127.0.0.1:8128"

// For an error to be recorded correctly in DataDog, these three tags
// need to be set
const errorMessageTag = "error.msg"
const errorTypeTag = "error.type"
const errorStackTag = "error.stack"

// Trace is a convenient structural representation
// of a TraceSpan. It is intended to map transparently
// to the more general type SSFSample.
type Trace struct {
	// the ID for the root span
	// which is also the ID for the trace itself
	TraceID int64

	// For the root span, this will be equal
	// to the TraceId
	SpanID int64

	// For the root span, this will be <= 0
	ParentID int64

	// The Resource should be the same for all spans in the same trace
	Resource string

	Start time.Time

	End time.Time

	// If non-zero, the trace will be treated
	// as an error
	Status ssf.SSFSample_Status

	Tags map[string]string

	// Unlike the Resource, this should not contain spaces
	// It should be of the format foo.bar.baz
	Name string

	error bool
}

// Set the end timestamp and finalize Span state
func (t *Trace) finish() {
	if t.End.IsZero() {
		t.End = time.Now()
	}
}

// (Experimental)
// Enabled sets tracing to enabled.
func Enable() {
	enabledMtx.Lock()
	defer enabledMtx.Unlock()

	disabled = false
}

// (Experimental)
// Disabled sets tracing to disabled.
func Disable() {
	enabledMtx.Lock()
	defer enabledMtx.Unlock()

	disabled = true
}

func Disabled() bool {
	enabledMtx.RLock()
	defer enabledMtx.RUnlock()

	return disabled
}

// Duration is a convenience function for
// the difference between the Start and End timestamps.
// It assumes the span has already ended.
func (t *Trace) Duration() time.Duration {
	if t.End.IsZero() {
		return -1
	}
	return t.End.Sub(t.Start)
}

// SSFSample converts the Trace to an SSFSpan type.
// It sets the duration, so it assumes the span has already ended.
// (It is safe to call on a span that has not ended, but the duration
// field will be invalid)
func (t *Trace) SSFSpan() *ssf.SSFSpan {
	name := t.Name

	span := &ssf.SSFSpan{
		StartTimestamp: t.Start.UnixNano(),
		Error:          t.error,
		TraceId:        t.TraceID,
		Id:             t.SpanID,
		ParentId:       t.ParentID,
		EndTimestamp:   t.End.UnixNano(),
		Tags:           t.Tags,
		Service:        Service,
	}

	span.Tags[NameKey] = name
	span.Tags[ResourceKey] = t.Resource

	return span
}

// ProtoMarshalTo writes the Trace as a protocol buffer
// in text format to the specified writer.
func (t *Trace) ProtoMarshalTo(w io.Writer) error {
	packet, err := proto.Marshal(t.SSFSpan())
	if err != nil {
		return err
	}
	_, err = w.Write(packet)
	return err
}

// Record sends a trace to the (local) veneur instance,
// which will pass it on to the tracing agent running on the
// global veneur instance.
func (t *Trace) Record(name string, tags map[string]string) error {
	if t.Tags == nil {
		t.Tags = map[string]string{}
	}
	t.finish()

	for k, v := range tags {
		t.Tags[k] = v
	}

	if name == "" {
		name = t.Name
	}

	span := t.SSFSpan()
	span.Tags[NameKey] = name

	return sendSample(span)
}

func (t *Trace) Error(err error) {
	t.Status = ssf.SSFSample_CRITICAL
	t.error = true

	errorType := reflect.TypeOf(err).Name()
	if errorType == "" {
		errorType = "error"
	}

	t.Tags[errorMessageTag] = err.Error()
	t.Tags[errorTypeTag] = errorType
	t.Tags[errorStackTag] = err.Error()
}

// Attach attaches the current trace to the context
// and returns a copy of the context with that trace
// stored under the key "trace".
func (t *Trace) Attach(c context.Context) context.Context {
	return context.WithValue(c, traceKey, t)
}

// SpanFromContext is used to create a child span
// when the parent trace is in the context
func SpanFromContext(c context.Context) *Trace {
	parent, ok := c.Value(traceKey).(*Trace)
	if !ok {
		logrus.WithField("type", reflect.TypeOf(c.Value(traceKey))).Error("expected *Trace from context")
	}
	return StartChildSpan(parent)
}

// StartSpanFromContext is used to create a child span
// when the parent trace is in the context
func StartSpanFromContext(ctx context.Context, name string, opts ...opentracing.StartSpanOption) (s *Span, c context.Context) {
	defer func() {
		if r := recover(); r != nil {
			s = nil
			c = ctx
		}
	}()

	if name == "" {
		pc, _, _, ok := runtime.Caller(1)
		details := runtime.FuncForPC(pc)
		if ok && details != nil {
			name = stripPackageName(details.Name())
			opts = append(opts, NameTag(name))
		}
	}

	sp, c := opentracing.StartSpanFromContext(ctx, name, opts...)

	s = sp.(*Span)
	return s, c
}

// SetParent updates the ParentId, TraceId, and Resource of a trace
// based on the parent's values (SpanId, TraceId, Resource).
func (t *Trace) SetParent(parent *Trace) {
	t.ParentID = parent.SpanID
	t.TraceID = parent.TraceID
	t.Resource = parent.Resource
}

// context returns a spanContext representing the trace
// from the point of view of itself .
// (The parentid for the trace will be set as the parentid for the context)
func (t *Trace) context() *spanContext {

	c := &spanContext{}
	c.Init()
	c.baggageItems["traceid"] = strconv.FormatInt(t.TraceID, 10)
	c.baggageItems["parentid"] = strconv.FormatInt(t.ParentID, 10)
	c.baggageItems["spanid"] = strconv.FormatInt(t.SpanID, 10)
	c.baggageItems[ResourceKey] = t.Resource
	return c
}

// contextAsParent returns a spanContext representing the trace
// from the point of view of its direct children.
// (The SpanId for the trace will be set as the ParentId for the context)
func (t *Trace) contextAsParent() *spanContext {

	c := &spanContext{}
	c.Init()
	c.baggageItems["traceid"] = strconv.FormatInt(t.TraceID, 10)
	c.baggageItems["parentid"] = strconv.FormatInt(t.SpanID, 10)
	c.baggageItems[ResourceKey] = t.Resource
	return c
}

// StartTrace is called by to create the root-level span
// for a trace
func StartTrace(resource string) *Trace {
	traceID := proto.Int64(rand.Int63())

	t := &Trace{
		TraceID:  *traceID,
		SpanID:   *traceID,
		ParentID: 0,
		Resource: resource,
		Tags:     map[string]string{},
	}

	t.Start = time.Now()
	return t
}

// StartChildSpan creates a new Span with the specified parent
func StartChildSpan(parent *Trace) *Trace {
	spanID := proto.Int64(rand.Int63())
	span := &Trace{
		SpanID: *spanID,
	}

	span.SetParent(parent)
	span.Start = time.Now()

	return span
}

// sendSample marshals the sample using protobuf and sends it
// over UDP to the local veneur instance
func sendSample(sample *ssf.SSFSpan) (err error) {
	defer func() {
		if r := recover(); r != nil {
			err, ok := r.(error)
			if !ok {
				err = fmt.Errorf("encountered panic while sending sample %#v", err)
			}
		}
	}()

	if Disabled() {
		return nil
	}

	udpInitOnce.Do(udpInitFunc)

	// at this point, the connection should already be initialized

	if udpConn == nil {
		return udpConnUninitializedErr
	}

	data, err := proto.Marshal(sample)
	if err != nil {
		return
	}

	_, err = udpConn.Write(data)
	if err != nil {
		return
	}

	return nil
}

// initUDPConn will initialize the global UDP connection.
// It will panic if it encounters an error.
// It should only be called via the corresponding sync.Once
func initUDPConn(address string) {
	serverAddr, err := net.ResolveUDPAddr("udp", localVeneurAddress)
	if err != nil {
		panic(err)
	}

	conn, err := net.DialUDP("udp", nil, serverAddr)
	if err != nil {
		panic(err)
	}
	udpConn = conn
}

// stripPackageName strips the package name from a function
// name (as formatted by the runtime package)
func stripPackageName(name string) string {
	i := strings.LastIndex(name, "/")
	if i < 0 || i >= len(name)-1 {
		return name
	}

	return name[i+1:]
}
<commit_msg>Log error when dialing UDP connection in tracing client<commit_after>// Package trace provies an experimental API for initiating
// traces. Veneur's tracing API also provides
// an opentracing compatibility layer. The Veneur tracing API
// is completely independent of the opentracing
// compatibility layer, with the exception of one convenience
// function.
package trace

import (
	"context"
	"errors"
	"fmt"
	"io"
	"math/rand"
	"net"
	"reflect"
	"runtime"
	"strconv"
	"strings"
	"sync"
	"time"

	"github.com/stripe/veneur/ssf"

	"github.com/Sirupsen/logrus"
	"github.com/golang/protobuf/proto"
	opentracing "github.com/opentracing/opentracing-go"
)

// Experimental
const NameKey = "name"

// Experimental
const ResourceKey = "resource"

func init() {
	rand.Seed(time.Now().Unix())
}

// (Experimental)
// If this is set to true,
// traces will be generated but not actually sent.
// This should only be set before any traces are generated
var disabled bool = false

var enabledMtx sync.RWMutex

var udpConn *net.UDPConn

// used to initialize udpConn inside sendSample
var udpInitOnce sync.Once
var udpInitFunc = func() { initUDPConn(localVeneurAddress) }
var udpConnUninitializedErr = errors.New("UDP connection is not yet initialized")

// Make an unexported `key` type that we use as a String such
// that we don't get lint warnings from using it as a key in
// Context. See https://blog.golang.org/context#TOC_3.2.
type key string

const traceKey key = "trace"

// Service is our service name and should be set exactly once,
// at startup
var Service = ""

const localVeneurAddress = "127.0.0.1:8128"

// For an error to be recorded correctly in DataDog, these three tags
// need to be set
const errorMessageTag = "error.msg"
const errorTypeTag = "error.type"
const errorStackTag = "error.stack"

// Trace is a convenient structural representation
// of a TraceSpan. It is intended to map transparently
// to the more general type SSFSample.
type Trace struct {
	// the ID for the root span
	// which is also the ID for the trace itself
	TraceID int64

	// For the root span, this will be equal
	// to the TraceId
	SpanID int64

	// For the root span, this will be <= 0
	ParentID int64

	// The Resource should be the same for all spans in the same trace
	Resource string

	Start time.Time

	End time.Time

	// If non-zero, the trace will be treated
	// as an error
	Status ssf.SSFSample_Status

	Tags map[string]string

	// Unlike the Resource, this should not contain spaces
	// It should be of the format foo.bar.baz
	Name string

	error bool
}

// Set the end timestamp and finalize Span state
func (t *Trace) finish() {
	if t.End.IsZero() {
		t.End = time.Now()
	}
}

// (Experimental)
// Enabled sets tracing to enabled.
func Enable() {
	enabledMtx.Lock()
	defer enabledMtx.Unlock()

	disabled = false
}

// (Experimental)
// Disabled sets tracing to disabled.
func Disable() {
	enabledMtx.Lock()
	defer enabledMtx.Unlock()

	disabled = true
}

func Disabled() bool {
	enabledMtx.RLock()
	defer enabledMtx.RUnlock()

	return disabled
}

// Duration is a convenience function for
// the difference between the Start and End timestamps.
// It assumes the span has already ended.
func (t *Trace) Duration() time.Duration {
	if t.End.IsZero() {
		return -1
	}
	return t.End.Sub(t.Start)
}

// SSFSample converts the Trace to an SSFSpan type.
// It sets the duration, so it assumes the span has already ended.
// (It is safe to call on a span that has not ended, but the duration
// field will be invalid)
func (t *Trace) SSFSpan() *ssf.SSFSpan {
	name := t.Name

	span := &ssf.SSFSpan{
		StartTimestamp: t.Start.UnixNano(),
		Error:          t.error,
		TraceId:        t.TraceID,
		Id:             t.SpanID,
		ParentId:       t.ParentID,
		EndTimestamp:   t.End.UnixNano(),
		Tags:           t.Tags,
		Service:        Service,
	}

	span.Tags[NameKey] = name
	span.Tags[ResourceKey] = t.Resource

	return span
}

// ProtoMarshalTo writes the Trace as a protocol buffer
// in text format to the specified writer.
func (t *Trace) ProtoMarshalTo(w io.Writer) error {
	packet, err := proto.Marshal(t.SSFSpan())
	if err != nil {
		return err
	}
	_, err = w.Write(packet)
	return err
}

// Record sends a trace to the (local) veneur instance,
// which will pass it on to the tracing agent running on the
// global veneur instance.
func (t *Trace) Record(name string, tags map[string]string) error {
	if t.Tags == nil {
		t.Tags = map[string]string{}
	}
	t.finish()

	for k, v := range tags {
		t.Tags[k] = v
	}

	if name == "" {
		name = t.Name
	}

	span := t.SSFSpan()
	span.Tags[NameKey] = name

	return sendSample(span)
}

func (t *Trace) Error(err error) {
	t.Status = ssf.SSFSample_CRITICAL
	t.error = true

	errorType := reflect.TypeOf(err).Name()
	if errorType == "" {
		errorType = "error"
	}

	t.Tags[errorMessageTag] = err.Error()
	t.Tags[errorTypeTag] = errorType
	t.Tags[errorStackTag] = err.Error()
}

// Attach attaches the current trace to the context
// and returns a copy of the context with that trace
// stored under the key "trace".
func (t *Trace) Attach(c context.Context) context.Context {
	return context.WithValue(c, traceKey, t)
}

// SpanFromContext is used to create a child span
// when the parent trace is in the context
func SpanFromContext(c context.Context) *Trace {
	parent, ok := c.Value(traceKey).(*Trace)
	if !ok {
		logrus.WithField("type", reflect.TypeOf(c.Value(traceKey))).Error("expected *Trace from context")
	}
	return StartChildSpan(parent)
}

// StartSpanFromContext is used to create a child span
// when the parent trace is in the context
func StartSpanFromContext(ctx context.Context, name string, opts ...opentracing.StartSpanOption) (s *Span, c context.Context) {
	defer func() {
		if r := recover(); r != nil {
			s = nil
			c = ctx
		}
	}()

	if name == "" {
		pc, _, _, ok := runtime.Caller(1)
		details := runtime.FuncForPC(pc)
		if ok && details != nil {
			name = stripPackageName(details.Name())
			opts = append(opts, NameTag(name))
		}
	}

	sp, c := opentracing.StartSpanFromContext(ctx, name, opts...)

	s = sp.(*Span)
	return s, c
}

// SetParent updates the ParentId, TraceId, and Resource of a trace
// based on the parent's values (SpanId, TraceId, Resource).
func (t *Trace) SetParent(parent *Trace) {
	t.ParentID = parent.SpanID
	t.TraceID = parent.TraceID
	t.Resource = parent.Resource
}

// context returns a spanContext representing the trace
// from the point of view of itself .
// (The parentid for the trace will be set as the parentid for the context)
func (t *Trace) context() *spanContext {

	c := &spanContext{}
	c.Init()
	c.baggageItems["traceid"] = strconv.FormatInt(t.TraceID, 10)
	c.baggageItems["parentid"] = strconv.FormatInt(t.ParentID, 10)
	c.baggageItems["spanid"] = strconv.FormatInt(t.SpanID, 10)
	c.baggageItems[ResourceKey] = t.Resource
	return c
}

// contextAsParent returns a spanContext representing the trace
// from the point of view of its direct children.
// (The SpanId for the trace will be set as the ParentId for the context)
func (t *Trace) contextAsParent() *spanContext {

	c := &spanContext{}
	c.Init()
	c.baggageItems["traceid"] = strconv.FormatInt(t.TraceID, 10)
	c.baggageItems["parentid"] = strconv.FormatInt(t.SpanID, 10)
	c.baggageItems[ResourceKey] = t.Resource
	return c
}

// StartTrace is called by to create the root-level span
// for a trace
func StartTrace(resource string) *Trace {
	traceID := proto.Int64(rand.Int63())

	t := &Trace{
		TraceID:  *traceID,
		SpanID:   *traceID,
		ParentID: 0,
		Resource: resource,
		Tags:     map[string]string{},
	}

	t.Start = time.Now()
	return t
}

// StartChildSpan creates a new Span with the specified parent
func StartChildSpan(parent *Trace) *Trace {
	spanID := proto.Int64(rand.Int63())
	span := &Trace{
		SpanID: *spanID,
	}

	span.SetParent(parent)
	span.Start = time.Now()

	return span
}

// sendSample marshals the sample using protobuf and sends it
// over UDP to the local veneur instance
func sendSample(sample *ssf.SSFSpan) (err error) {
	defer func() {
		if r := recover(); r != nil {
			err, ok := r.(error)
			if !ok {
				err = fmt.Errorf("encountered panic while sending sample %#v", err)
			}
			log.WithError(err).Error("Panicked while dialing UDP connection - traces will not be sent")
		}
	}()

	if Disabled() {
		return nil
	}

	udpInitOnce.Do(udpInitFunc)

	// at this point, the connection should already be initialized

	if udpConn == nil {
		return udpConnUninitializedErr
	}

	data, err := proto.Marshal(sample)
	if err != nil {
		return
	}

	_, err = udpConn.Write(data)
	if err != nil {
		return
	}

	return nil
}

// initUDPConn will initialize the global UDP connection.
// It will panic if it encounters an error.
// It should only be called via the corresponding sync.Once
func initUDPConn(address string) {
	serverAddr, err := net.ResolveUDPAddr("udp", localVeneurAddress)
	if err != nil {
		panic(err)
	}

	conn, err := net.DialUDP("udp", nil, serverAddr)
	if err != nil {
		panic(err)
	}
	udpConn = conn
}

// stripPackageName strips the package name from a function
// name (as formatted by the runtime package)
func stripPackageName(name string) string {
	i := strings.LastIndex(name, "/")
	if i < 0 || i >= len(name)-1 {
		return name
	}

	return name[i+1:]
}
<|endoftext|>


<commit_before>package goldb

import "github.com/syndtr/goleveldb/leveldb"

type Transaction struct {
	Context
	tr   *leveldb.Transaction
	seq  map[Entity]uint64
	Data interface{}
}

func (t *Transaction) Discard() {
	t.tr.Discard()
}

func (t *Transaction) Commit() error {
	return t.tr.Commit()
}

func (t *Transaction) Fail(err error) {
	panic(err)
}

func panicOnErr(err error) {
	if err != nil {
		panic(err)
	}
}

const tabSequences Entity = 0x7fffffff

func (t *Transaction) SequenceCurVal(tab Entity) (seq uint64) {
	if t.seq == nil {
		t.seq = map[Entity]uint64{}
	}
	seq, ok := t.seq[tab]
	if ok {
		return
	}
	var key = Key(tabSequences, int(tab))
	t.GetVar(key, &seq)
	t.seq[tab] = seq
	return
}

func (t *Transaction) SequenceNextVal(tab Entity) (seq uint64) {
	seq = t.SequenceCurVal(tab) + 1
	t.seq[tab] = seq
	var key = Key(tabSequences, int(tab))
	t.PutVar(key, seq)
	return seq
}

func (t *Transaction) Put(key, data []byte) {
	if err := t.tr.Put(key, data, t.WriteOptions); err != nil {
		t.Fail(err)
	}
}

func (t *Transaction) PutID(key []byte, id uint64) {
	t.Put(key, encodeUint(id))
}

func (t *Transaction) PutInt(key []byte, num int64) {
	t.PutVar(key, num)
}

func (t *Transaction) PutVar(key []byte, v interface{}) {
	t.Put(key, encodeValue(v))
}

// Increment increments int-value by key
func (t *Transaction) Increment(key []byte, delta int64) (v int64) {
	if _, err := t.GetVar(key, &v); err != nil {
		t.Fail(err)
	}
	v += delta
	t.Put(key, encodeValue(v))
	return
}

func (t *Transaction) Delete(key []byte) {
	if err := t.tr.Delete(key, t.WriteOptions); err != nil {
		t.Fail(err)
	}
}
<commit_msg>Put returns error<commit_after>package goldb

import "github.com/syndtr/goleveldb/leveldb"

type Transaction struct {
	Context
	tr   *leveldb.Transaction
	seq  map[Entity]uint64
	Data interface{}
}

func (t *Transaction) Discard() {
	t.tr.Discard()
}

func (t *Transaction) Commit() error {
	return t.tr.Commit()
}

func (t *Transaction) Fail(err error) {
	panic(err)
}

func panicOnErr(err error) {
	if err != nil {
		panic(err)
	}
}

const tabSequences Entity = 0x7fffffff

func (t *Transaction) SequenceCurVal(tab Entity) (seq uint64) {
	if t.seq == nil {
		t.seq = map[Entity]uint64{}
	}
	seq, ok := t.seq[tab]
	if ok {
		return
	}
	var key = Key(tabSequences, int(tab))
	t.GetVar(key, &seq)
	t.seq[tab] = seq
	return
}

func (t *Transaction) SequenceNextVal(tab Entity) (seq uint64) {
	seq = t.SequenceCurVal(tab) + 1
	t.seq[tab] = seq
	var key = Key(tabSequences, int(tab))
	t.PutVar(key, seq)
	return seq
}

func (t *Transaction) Put(key, data []byte) error {
	if err := t.tr.Put(key, data, t.WriteOptions); err != nil {
		t.Fail(err)
	}
	return nil
}

func (t *Transaction) PutID(key []byte, id uint64) error {
	return t.Put(key, encodeUint(id))
}

func (t *Transaction) PutInt(key []byte, num int64) error {
	return t.PutVar(key, num)
}

func (t *Transaction) PutVar(key []byte, v interface{}) error {
	return t.Put(key, encodeValue(v))
}

// Increment increments int-value by key
func (t *Transaction) Increment(key []byte, delta int64) (v int64) {
	if _, err := t.GetVar(key, &v); err != nil {
		t.Fail(err)
	}
	v += delta
	t.Put(key, encodeValue(v))
	return
}

func (t *Transaction) Delete(key []byte) error {
	if err := t.tr.Delete(key, t.WriteOptions); err != nil {
		t.Fail(err)
	}
	return nil
}
<|endoftext|>


<commit_before>package tree

import (
	"fmt"
	"strings"

	"github.com/rgeorgiev583/gonflator/translation"
)

type Configuration map[string]Setting

type Setting struct {
	key   string
	value []byte
}

type ConfigurationServer interface {
	GetConfiguration() Configuration
	GetSetting(path string) (string, error)
	SetSetting(path string, value []byte) error
}

type ConfigurationTree struct {
	Prefix          string
	SubtreeHandlers map[string]*ConfigurationTree
}

type NonexistentSubtreeHandlerError struct {
	Prefix string
}

type InvalidPathError struct {
	Path string
}

type TreeAssignmentError struct {
	Path string
}

type NonexistentNodeError struct {
	Path string
}

func (nshe *NonexistentSubtreeHandlerError) Error() string {
	return fmt.Sprintf("prefix %s does not refer to an existing subtree handler for the current tree", nshe.Prefix)
}

func (ipe *InvalidPathError) Error() string {
	return fmt.Sprintf("configuration tree path %s does not refer to an existing tree or setting", ipe.Path)
}

func (tae *TreeAssignmentError) Error() string {
	return fmt.Sprintf("configuration tree path %s refers to a tree and so it cannot be assigned a value", tae.Path)
}

func (nne *NonexistentNodeError) Error() string {
	return fmt.Sprintf("configuration tree path %s does not refer to a valid tree or setting", nne.Path)
}

func (ct *ConfigurationTree) GetConfiguration() Configuration {
	mergedConf := make(Configuration)

	for prefix, handler := range ct.SubtreeHandlers {
		for path, value := range handler.GetConfiguration() {
			mergedConf[fmt.Sprintf("%s/%s", prefix, path)] = value
		}
	}

	return mergedConf
}

func (ct *ConfigurationTree) GetSetting(path string) (value []byte, err error) {
	for prefix, handler := range ct.SubtreeHandlers {
		if !strings.HasPrefix(path, prefix) {
			continue
		}

		value, err = handler.GetSetting(strings.TrimPrefix(path, prefix))

		if err == nil {
			return
		}
	}

	return nil, &NonexistentNodeError{path}
}

func (ct *ConfigurationTree) SetSetting(path string, value []byte) (err error) {
	for prefix, handler := range ct.SubtreeHandlers {
		if !strings.HasPrefix(path, prefix) {
			continue
		}

		err = handler.SetSetting(strings.TrimPrefix(path, prefix), value)

		if err == nil {
			return
		}
	}

	return &NonexistentNodeError{path}
}

func (ct *ConfigurationTree) TranslateToRdiff(diff chan<- translation.Delta) (translatedDiff <-chan translation.Delta, err error) {
	deltaHandlers := make(map[string]chan translation.Delta)

	go for delta := range diff {
		for prefix, handler := range ct.SubtreeHandlers {
			if !strings.HasPrefix(delta.OldPath, prefix) || !strings.HasPrefix(delta.NewPath, prefix) {
				continue
			}

			translatedDelta := handler.TranslateToRdiff()
			if handler, ok := deltaHandlers[prefix]; ok {
				deltaHandlers[prefix] <-
			}

			if err == nil {
				return
			}
		}
	}
}
<commit_msg>redesign: exported the members of the Setting struct<commit_after>package tree

import (
	"fmt"
	"strings"

	"github.com/rgeorgiev583/gonflator/translation"
)

type Configuration map[string]Setting

type Setting struct {
	Key   string
	Value []byte
}

type ConfigurationServer interface {
	GetConfiguration() Configuration
	GetSetting(path string) (string, error)
	SetSetting(path string, value []byte) error
}

type ConfigurationTree struct {
	Prefix          string
	SubtreeHandlers map[string]*ConfigurationTree
}

type NonexistentSubtreeHandlerError struct {
	Prefix string
}

type InvalidPathError struct {
	Path string
}

type TreeAssignmentError struct {
	Path string
}

type NonexistentNodeError struct {
	Path string
}

func (nshe *NonexistentSubtreeHandlerError) Error() string {
	return fmt.Sprintf("prefix %s does not refer to an existing subtree handler for the current tree", nshe.Prefix)
}

func (ipe *InvalidPathError) Error() string {
	return fmt.Sprintf("configuration tree path %s does not refer to an existing tree or setting", ipe.Path)
}

func (tae *TreeAssignmentError) Error() string {
	return fmt.Sprintf("configuration tree path %s refers to a tree and so it cannot be assigned a value", tae.Path)
}

func (nne *NonexistentNodeError) Error() string {
	return fmt.Sprintf("configuration tree path %s does not refer to a valid tree or setting", nne.Path)
}

func (ct *ConfigurationTree) GetConfiguration() Configuration {
	mergedConf := make(Configuration)

	for prefix, handler := range ct.SubtreeHandlers {
		for path, value := range handler.GetConfiguration() {
			mergedConf[fmt.Sprintf("%s/%s", prefix, path)] = value
		}
	}

	return mergedConf
}

func (ct *ConfigurationTree) GetSetting(path string) (value []byte, err error) {
	for prefix, handler := range ct.SubtreeHandlers {
		if !strings.HasPrefix(path, prefix) {
			continue
		}

		value, err = handler.GetSetting(strings.TrimPrefix(path, prefix))

		if err == nil {
			return
		}
	}

	return nil, &NonexistentNodeError{path}
}

func (ct *ConfigurationTree) SetSetting(path string, value []byte) (err error) {
	for prefix, handler := range ct.SubtreeHandlers {
		if !strings.HasPrefix(path, prefix) {
			continue
		}

		err = handler.SetSetting(strings.TrimPrefix(path, prefix), value)

		if err == nil {
			return
		}
	}

	return &NonexistentNodeError{path}
}

func (ct *ConfigurationTree) TranslateToRdiff(diff chan<- translation.Delta) (translatedDiff <-chan translation.Delta, err error) {
	deltaHandlers := make(map[string]chan translation.Delta)

	go for delta := range diff {
		for prefix, handler := range ct.SubtreeHandlers {
			if !strings.HasPrefix(delta.OldPath, prefix) || !strings.HasPrefix(delta.NewPath, prefix) {
				continue
			}

			translatedDelta := handler.TranslateToRdiff()
			if handler, ok := deltaHandlers[prefix]; ok {
				deltaHandlers[prefix] <-
			}

			if err == nil {
				return
			}
		}
	}
}
<|endoftext|>


<commit_before>package sched

import (
    "container/heap"
)

// An Item is something we manage in a priority queue.
type Item struct {
    value    int64 // The value of the item; arbitrary.
    priority int64    // The priority of the item in the queue.
    // The index is needed by update and is maintained by the heap.Interface methods.
    index    int // The index of the item in the heap.
}

// A PriorityQueue implements heap.Interface and holds Items.
type PriorityQueue []*Item

func (pq PriorityQueue) Len() int { return len(pq) }

func (pq PriorityQueue) Less(i, j int) bool {
    // We want Pop to give us the highest, not lowest, priority so we use greater than here.
    return pq[i].priority > pq[j].priority
}

func (pq PriorityQueue) Swap(i, j int) {
    pq[i], pq[j] = pq[j], pq[i]
    pq[i].index = i
    pq[j].index = j
}

func (pq *PriorityQueue) Push(x interface{}) {
    n := len(*pq)
    item := x.(*Item)
    item.index = n
    *pq = append(*pq, item)
}

func (pq *PriorityQueue) Pop() interface{} {
    old := *pq
    n := len(old)
    item := old[n-1]
    item.index = -1 // for safety
    *pq = old[0 : n-1]
    return item
}

// update modifies the priority and value of an Item in the queue.
func (pq *PriorityQueue) update(item *Item, value string, priority int) {
    item.value = value
    item.priority = priority
    heap.Fix(pq, item.index)
}
<commit_msg>Fix PriorityQueue type<commit_after>package sched

import (
    "container/heap"
)

// An Item is something we manage in a priority queue.
type Item struct {
    value    int64 // The value of the item; arbitrary.
    priority int64    // The priority of the item in the queue.
    // The index is needed by update and is maintained by the heap.Interface methods.
    index    int // The index of the item in the heap.
}

// A PriorityQueue implements heap.Interface and holds Items.
type PriorityQueue []*Item

func (pq PriorityQueue) Len() int { return len(pq) }

func (pq PriorityQueue) Less(i, j int) bool {
    // We want Pop to give us the highest, not lowest, priority so we use greater than here.
    return pq[i].priority > pq[j].priority
}

func (pq PriorityQueue) Swap(i, j int) {
    pq[i], pq[j] = pq[j], pq[i]
    pq[i].index = i
    pq[j].index = j
}

func (pq *PriorityQueue) Push(x interface{}) {
    n := len(*pq)
    item := x.(*Item)
    item.index = n
    *pq = append(*pq, item)
}

func (pq *PriorityQueue) Pop() interface{} {
    old := *pq
    n := len(old)
    item := old[n-1]
    item.index = -1 // for safety
    *pq = old[0 : n-1]
    return item
}

// update modifies the priority and value of an Item in the queue.
func (pq *PriorityQueue) update(item *Item, value int64, priority int64) {
    item.value = value
    item.priority = priority
    heap.Fix(pq, item.index)
}
<|endoftext|>


<commit_before>package semver_test

import (
	"fmt"
	"testing"

	"github.com/hansrodtang/semver"
)

type comparison struct {
	main     *semver.Version
	other    *semver.Version
	expected int
}

var correctVersions = []string{
	"1.0.3-app-beta.1",
}

var badVersions = []string{
	"",
	".",
	"1.",
	".1",
	"a.b.c",
	"1.a.b",
	"1.1.a",
	"1.a.1",
	"a.1.1",
	"..",
	"1..",
	"1.1.",
	"1..1",
	"1.1.+123",
	"1.1.-beta",
	"-1.1.1",
	"1.-1.1",
	"1.1.-1",
	// Leading zeroes
	"01.1.1",
	"001.1.1",
	"1.01.1",
	"1.001.1",
	"1.1.01",
	"1.1.001",
	"1.1.1-01",
	"1.1.1-001",
	"1.1.1-beta.01",
	"1.1.1-beta.001",
	"0.0.0-!",
	"0.0.0+!",
	// empty prerelease
	"0.0.0-.alpha",
	// empty build metadata
	"0.0.0-alpha+",
	"0.0.0-alpha+test.",
}

var comparisons = []comparison{
	{semver.Build(1, 0, 0), semver.Build(1, 0, 0), 0},
	{semver.Build(2, 0, 0), semver.Build(1, 0, 0), 1},
	{semver.Build(0, 1, 0), semver.Build(0, 1, 0), 0},
	{semver.Build(0, 2, 0), semver.Build(0, 1, 0), 1},
	{semver.Build(0, 0, 1), semver.Build(0, 0, 1), 0},
	{semver.Build(0, 0, 2), semver.Build(0, 0, 1), 1},
	{semver.Build(1, 2, 3), semver.Build(1, 2, 3), 0},
	{semver.Build(2, 2, 4), semver.Build(1, 2, 4), 1},
	{semver.Build(1, 3, 3), semver.Build(1, 2, 3), 1},
	{semver.Build(1, 2, 4), semver.Build(1, 2, 3), 1},

	// Spec Examples #11
	{semver.Build(1, 0, 0), semver.Build(2, 0, 0), -1},
	{semver.Build(2, 0, 0), semver.Build(2, 1, 0), -1},
	{semver.Build(2, 1, 0), semver.Build(2, 1, 1), -1},

	// Spec Examples #9
	{semver.Build(1, 0, 0), semver.Build(1, 0, 0, []string{"alpha"}), 1},
	{semver.Build(1, 0, 0, []string{"alpha"}), semver.Build(1, 0, 0, []string{"alpha", "1"}), -1},
	{semver.Build(1, 0, 0, []string{"alpha", "1"}), semver.Build(1, 0, 0, []string{"alpha"}), 1},
	{semver.Build(1, 0, 0, []string{"alpha", "1"}), semver.Build(1, 0, 0, []string{"alpha", "beta"}), -1},
	{semver.Build(1, 0, 0, []string{"alpha", "beta"}), semver.Build(1, 0, 0, []string{"beta"}), -1},
	{semver.Build(1, 0, 0, []string{"beta"}), semver.Build(1, 0, 0, []string{"beta", "2"}), -1},
	{semver.Build(1, 0, 0, []string{"beta", "2"}), semver.Build(1, 0, 0, []string{"beta", "11"}), -1},
	{semver.Build(1, 0, 0, []string{"beta", "11"}), semver.Build(1, 0, 0, []string{"beta", "2"}), 1},
	{semver.Build(1, 0, 0, []string{"beta", "11"}), semver.Build(1, 0, 0, []string{"rc", "1"}), -1},
	{semver.Build(1, 0, 0, []string{"beta", "beta"}), semver.Build(1, 0, 0, []string{"beta", "alpha"}), 1},
	{semver.Build(1, 0, 0, []string{"rc", "1"}), semver.Build(1, 0, 0), -1},

	{semver.Build(1, 0, 0, []string{"beta", "alpha", "1"}), semver.Build(1, 0, 0, []string{"beta", "alpha"}), 1},

	{semver.Build(1, 0, 0, []string{"rc", "1"}), semver.Build(1, 0, 0, []string{"rc", "1"}, []string{"435345345"}), 0},
}

var badPreRelease = [][]string{
	{"alpha", "-3"},
}

func TestStringer(t *testing.T) {
	ver := semver.Build(1, 2, 3)
	ver.SetPrerelease("alpha", "1")
	ver.SetMetadata("35", "45")

	expected := "1.2.3-alpha.1+35.45"
	result := fmt.Sprint(ver)

	if result != expected {
		t.Errorf("String() => %q, wanted %q", result, expected)
	}
}

func TestGetters(t *testing.T) {
	expectedMajor := uint64(1)
	expectedMinor := uint64(2)
	expectedPatch := uint64(3)
	expectedPrerelease := "alpha.1"
	expectedMetadata := "35.45"

	ver := semver.Build(expectedMajor, expectedMinor, expectedPatch)
	ver.SetPrerelease("alpha", "1")
	ver.SetMetadata("35", "45")

	if result := ver.Major(); result != expectedMajor {
		t.Errorf("%q.Major() => %q, wanted %q", ver, result, expectedMajor)
	}
	if result := ver.Minor(); result != expectedMinor {
		t.Errorf("%q.Minor() => %q, wanted %q", ver, result, expectedMinor)
	}
	if result := ver.Patch(); result != expectedPatch {
		t.Errorf("%q.Patch() => %q, wanted %q", ver, result, expectedPatch)
	}
	if result := ver.Prerelease(); result != expectedPrerelease {
		t.Errorf("%q.Prerelease() => %q, wanted %q", ver, result, expectedPrerelease)
	}
	if result := ver.Metadata(); result != expectedMetadata {
		t.Errorf("%q.Metadata() => %q, wanted %q", ver, result, expectedMetadata)
	}
}

func TestSetters(t *testing.T) {
	ver := semver.Build(1, 1, 1)
	ver.SetMajor(2)
	ver.SetMinor(3)
	ver.SetPatch(4)
	if err := ver.SetPrerelease("beta", "1"); err != nil {
		t.Errorf(fmt.Sprint(err))
	}
	if err := ver.SetMetadata("22", "43"); err != nil {
		t.Errorf(fmt.Sprint(err))
	}

	expected := "2.3.4-beta.1+22.43"
	result := fmt.Sprint(ver)
	if result != expected {
		t.Errorf("Stringer() => %q, wanted %q", result, expected)
	}
}

func TestNew(t *testing.T) {
	expected := "1.0.3-alpha.1+35.45"

	ver, err := semver.New(expected)
	if err != nil {
		t.Errorf(fmt.Sprint(err))
	}

	result := fmt.Sprint(ver)
	if result != expected {
		t.Errorf("Stringer() => %q, want %q", result, expected)
	}

}

func TestBadFormat(t *testing.T) {
	for _, version := range badVersions {
		_, err := semver.New(version)
		if err == nil {
			// TODO: Set up error types
			t.Errorf("New(%q) => %v, want Error", version, err)
		}

	}
}

func TestCorrectFormat(t *testing.T) {
	for _, version := range correctVersions {
		_, err := semver.New(version)
		if err != nil {
			t.Errorf("New(%q) => %v, want <nil>", version, err)
		}
	}
}

func TestComparison(t *testing.T) {
	for _, c := range comparisons {
		result := c.main.Compare(c.other)
		if result != c.expected {
			t.Errorf("%q.Compare(%q) => %#v, want %#v", c.main, c.other, result, c.expected)
		}
	}
}

func TestSetPrerelease(t *testing.T) {
	ver := semver.Build(1, 2, 3)
	err := ver.SetPrerelease("12", "1", "0", "43")
	if err != nil {
		t.Errorf(fmt.Sprint(err))
	}
}

func BenchmarkParseSimple(b *testing.B) {
	const VERSION = "0.0.1"
	b.ResetTimer()
	for n := 0; n < b.N; n++ {
		semver.New(VERSION)
	}
}

func BenchmarkParseComplex(b *testing.B) {
	const VERSION = "0.0.1-alpha.preview+123.456"
	b.ResetTimer()
	for n := 0; n < b.N; n++ {
		semver.New(VERSION)
	}
}

func BenchmarkCompareSimple(b *testing.B) {
	const VERSION = "0.0.1"
	v, _ := semver.New(VERSION)
	b.ResetTimer()
	for n := 0; n < b.N; n++ {
		v.Compare(v)
	}
}

func BenchmarkCompareComplex(b *testing.B) {
	const VERSION = "0.0.1-alpha.preview+123.456"
	const VERSION2 = "0.0.1-alpha.preview+123.456"
	v, _ := semver.New(VERSION)
	v2, _ := semver.New(VERSION2)
	b.ResetTimer()
	for n := 0; n < b.N; n++ {
		v.Compare(v2)
	}
}
<commit_msg>Added more weird but correct version strings.<commit_after>package semver_test

import (
	"fmt"
	"testing"

	"github.com/hansrodtang/semver"
)

type comparison struct {
	main     *semver.Version
	other    *semver.Version
	expected int
}

var correctVersions = []string{
	"0.0.1-alpha.preview+123.456",
	"1.2.3-alpha.1+123.456",
	"1.2.3-alpha.1",
	"1.2.3+123.456",
	"1.2.3-alpha.b-eta+123.b-uild",
	"1.2.3+123.b-uild",
	"1.2.3-alpha.b-eta",
}

var badVersions = []string{
	"",
	".",
	"1.",
	".1",
	"a.b.c",
	"1.a.b",
	"1.1.a",
	"1.a.1",
	"a.1.1",
	"..",
	"1..",
	"1.1.",
	"1..1",
	"1.1.+123",
	"1.1.-beta",
	"-1.1.1",
	"1.-1.1",
	"1.1.-1",
	// Leading zeroes
	"01.1.1",
	"001.1.1",
	"1.01.1",
	"1.001.1",
	"1.1.01",
	"1.1.001",
	"1.1.1-01",
	"1.1.1-001",
	"1.1.1-beta.01",
	"1.1.1-beta.001",
	"0.0.0-!",
	"0.0.0+!",
	// empty prerelease
	"0.0.0-.alpha",
	// empty build metadata
	"0.0.0-alpha+",
	"0.0.0-alpha+test.",
}

var comparisons = []comparison{
	{semver.Build(1, 0, 0), semver.Build(1, 0, 0), 0},
	{semver.Build(2, 0, 0), semver.Build(1, 0, 0), 1},
	{semver.Build(0, 1, 0), semver.Build(0, 1, 0), 0},
	{semver.Build(0, 2, 0), semver.Build(0, 1, 0), 1},
	{semver.Build(0, 0, 1), semver.Build(0, 0, 1), 0},
	{semver.Build(0, 0, 2), semver.Build(0, 0, 1), 1},
	{semver.Build(1, 2, 3), semver.Build(1, 2, 3), 0},
	{semver.Build(2, 2, 4), semver.Build(1, 2, 4), 1},
	{semver.Build(1, 3, 3), semver.Build(1, 2, 3), 1},
	{semver.Build(1, 2, 4), semver.Build(1, 2, 3), 1},

	// Spec Examples #11
	{semver.Build(1, 0, 0), semver.Build(2, 0, 0), -1},
	{semver.Build(2, 0, 0), semver.Build(2, 1, 0), -1},
	{semver.Build(2, 1, 0), semver.Build(2, 1, 1), -1},

	// Spec Examples #9
	{semver.Build(1, 0, 0), semver.Build(1, 0, 0, []string{"alpha"}), 1},
	{semver.Build(1, 0, 0, []string{"alpha"}), semver.Build(1, 0, 0, []string{"alpha", "1"}), -1},
	{semver.Build(1, 0, 0, []string{"alpha", "1"}), semver.Build(1, 0, 0, []string{"alpha"}), 1},
	{semver.Build(1, 0, 0, []string{"alpha", "1"}), semver.Build(1, 0, 0, []string{"alpha", "beta"}), -1},
	{semver.Build(1, 0, 0, []string{"alpha", "beta"}), semver.Build(1, 0, 0, []string{"beta"}), -1},
	{semver.Build(1, 0, 0, []string{"beta"}), semver.Build(1, 0, 0, []string{"beta", "2"}), -1},
	{semver.Build(1, 0, 0, []string{"beta", "2"}), semver.Build(1, 0, 0, []string{"beta", "11"}), -1},
	{semver.Build(1, 0, 0, []string{"beta", "11"}), semver.Build(1, 0, 0, []string{"beta", "2"}), 1},
	{semver.Build(1, 0, 0, []string{"beta", "11"}), semver.Build(1, 0, 0, []string{"rc", "1"}), -1},
	{semver.Build(1, 0, 0, []string{"beta", "beta"}), semver.Build(1, 0, 0, []string{"beta", "alpha"}), 1},
	{semver.Build(1, 0, 0, []string{"rc", "1"}), semver.Build(1, 0, 0), -1},

	{semver.Build(1, 0, 0, []string{"beta", "alpha", "1"}), semver.Build(1, 0, 0, []string{"beta", "alpha"}), 1},

	{semver.Build(1, 0, 0, []string{"rc", "1"}), semver.Build(1, 0, 0, []string{"rc", "1"}, []string{"435345345"}), 0},
}

var badPreRelease = [][]string{
	{"alpha", "-3"},
}

func TestStringer(t *testing.T) {
	ver := semver.Build(1, 2, 3)
	ver.SetPrerelease("alpha", "1")
	ver.SetMetadata("35", "45")

	expected := "1.2.3-alpha.1+35.45"
	result := fmt.Sprint(ver)

	if result != expected {
		t.Errorf("String() => %q, wanted %q", result, expected)
	}
}

func TestGetters(t *testing.T) {
	expectedMajor := uint64(1)
	expectedMinor := uint64(2)
	expectedPatch := uint64(3)
	expectedPrerelease := "alpha.1"
	expectedMetadata := "35.45"

	ver := semver.Build(expectedMajor, expectedMinor, expectedPatch)
	ver.SetPrerelease("alpha", "1")
	ver.SetMetadata("35", "45")

	if result := ver.Major(); result != expectedMajor {
		t.Errorf("%q.Major() => %q, wanted %q", ver, result, expectedMajor)
	}
	if result := ver.Minor(); result != expectedMinor {
		t.Errorf("%q.Minor() => %q, wanted %q", ver, result, expectedMinor)
	}
	if result := ver.Patch(); result != expectedPatch {
		t.Errorf("%q.Patch() => %q, wanted %q", ver, result, expectedPatch)
	}
	if result := ver.Prerelease(); result != expectedPrerelease {
		t.Errorf("%q.Prerelease() => %q, wanted %q", ver, result, expectedPrerelease)
	}
	if result := ver.Metadata(); result != expectedMetadata {
		t.Errorf("%q.Metadata() => %q, wanted %q", ver, result, expectedMetadata)
	}
}

func TestSetters(t *testing.T) {
	ver := semver.Build(1, 1, 1)
	ver.SetMajor(2)
	ver.SetMinor(3)
	ver.SetPatch(4)
	if err := ver.SetPrerelease("beta", "1"); err != nil {
		t.Errorf(fmt.Sprint(err))
	}
	if err := ver.SetMetadata("22", "43"); err != nil {
		t.Errorf(fmt.Sprint(err))
	}

	expected := "2.3.4-beta.1+22.43"
	result := fmt.Sprint(ver)
	if result != expected {
		t.Errorf("Stringer() => %q, wanted %q", result, expected)
	}
}

func TestNew(t *testing.T) {
	expected := "1.0.3-alpha.1+35.45"

	ver, err := semver.New(expected)
	if err != nil {
		t.Errorf(fmt.Sprint(err))
	}

	result := fmt.Sprint(ver)
	if result != expected {
		t.Errorf("Stringer() => %q, want %q", result, expected)
	}

}

func TestBadFormat(t *testing.T) {
	for _, version := range badVersions {
		_, err := semver.New(version)
		if err == nil {
			// TODO: Set up error types
			t.Errorf("New(%q) => %v, want Error", version, err)
		}

	}
}

func TestCorrectFormat(t *testing.T) {
	for _, version := range correctVersions {
		_, err := semver.New(version)
		if err != nil {
			t.Errorf("New(%q) => %v, want <nil>", version, err)
		}
	}
}

func TestComparison(t *testing.T) {
	for _, c := range comparisons {
		result := c.main.Compare(c.other)
		if result != c.expected {
			t.Errorf("%q.Compare(%q) => %#v, want %#v", c.main, c.other, result, c.expected)
		}
	}
}

func TestSetPrerelease(t *testing.T) {
	ver := semver.Build(1, 2, 3)
	err := ver.SetPrerelease("12", "1", "0", "43")
	if err != nil {
		t.Errorf(fmt.Sprint(err))
	}
}

func BenchmarkParseSimple(b *testing.B) {
	const VERSION = "0.0.1"
	b.ResetTimer()
	for n := 0; n < b.N; n++ {
		semver.New(VERSION)
	}
}

func BenchmarkParseComplex(b *testing.B) {
	const VERSION = "0.0.1-alpha.preview+123.456"
	b.ResetTimer()
	for n := 0; n < b.N; n++ {
		semver.New(VERSION)
	}
}

func BenchmarkCompareSimple(b *testing.B) {
	const VERSION = "0.0.1"
	v, _ := semver.New(VERSION)
	b.ResetTimer()
	for n := 0; n < b.N; n++ {
		v.Compare(v)
	}
}

func BenchmarkCompareComplex(b *testing.B) {
	const VERSION = "0.0.1-alpha.preview+123.456"
	const VERSION2 = "0.0.1-alpha.preview+123.456"
	v, _ := semver.New(VERSION)
	v2, _ := semver.New(VERSION2)
	b.ResetTimer()
	for n := 0; n < b.N; n++ {
		v.Compare(v2)
	}
}
<|endoftext|>


<commit_before>package server

import (
  "net"
  "fmt"
)

func Run(address, port string) {
  fmt.Println("[SERVER] Server started")
  hostWithPort := fmt.Sprintf("%s:%s", address, port)

  ln, err := net.Listen("tcp", hostWithPort)
  if err != nil {
    fmt.Println("[SERVER] Unable to bind server on", hostWithPort)
  }

  for {
    conn, err := ln.Accept()
    if err != nil {
      fmt.Println("[SERVER] Unable to handle connect")
    }
    go handleConnection(conn)
  }
}

func handleConnection(conn net.Conn) {
  fmt.Println("[SERVER] Handling connection")
  var message []byte
  fmt.Fscan(conn, &message)
  fmt.Println("Message:", string(message))
  conn.Close()
}
<commit_msg>Change server read mechanism<commit_after>package server

import (
  "net"
  "fmt"
  "bufio"
)

func Run(address, port string) {
  fmt.Println("[SERVER] Server started")
  hostWithPort := fmt.Sprintf("%s:%s", address, port)

  ln, err := net.Listen("tcp", hostWithPort)
  if err != nil {
    fmt.Println("[SERVER] Unable to bind server on", hostWithPort)
  }

  for {
    conn, err := ln.Accept()
    if err != nil {
      fmt.Println("[SERVER] Unable to handle connect")
    }
    go handleConnection(conn)
  }
}

func handleConnection(conn net.Conn) {
  fmt.Println("[SERVER] Handling connection")
  scanner := bufio.NewScanner(conn)
  scanner.Scan()
  message := scanner.Text()
  fmt.Println("Message:", message)
  conn.Close()
}
<|endoftext|>


<commit_before>package main

import (
	"encoding/json"
	"fmt"
	"log"
	"strconv"
	"time"
)

type Game struct {
	// All the important game variables
	constants *GameConstants

	// Registered clients.
	clients map[*Client]bool

	// Register requests from the clients.
	register chan *Client

	// Unregister requests from clients.
	unregister chan *Client

	// Inbound events from the clients/AIs.
	events chan interface{}

	// Game objects that currently exist
	ships       map[string]*Ship
	projectiles map[string]*Projectile
	asteroids   map[string]*Asteroid

	// Next valid game object id.
	nextId int

	// Whether or not to print debug messages.
	debug bool

	// Last physics update time
	lastUpdate uint64
}

type GameConstants struct {
	ShipAcceleration uint16 `json:"ship_acceleration"`
	ShipRotation     uint16 `json:"ship_rotation"`
	ProjectileSpeed  uint16 `json:"projectile_speed"`
}

type GameError struct {
	What string
}

func (e GameError) Error() string {
	return e.What
}

const (
	clientUpdatePeriod = 100 * time.Millisecond
	gameTickPeriod     = 10 * time.Millisecond
)

// TODO: Get this working without a global variable, I guess pass a ref to game into the web socket handler function?
var game = CreateGame()

func CreateGame() *Game {
	g := &Game{
		clients:     make(map[*Client]bool),
		register:    make(chan *Client),
		unregister:  make(chan *Client),
		events:      make(chan interface{}),
		ships:       make(map[string]*Ship),
		projectiles: make(map[string]*Projectile),
		asteroids:   make(map[string]*Asteroid),
		debug:       false,

		// Game constants, values per second
		constants: &GameConstants{
			ShipAcceleration: 100, // Pixels per second
			ShipRotation:     100, // Degrees per second
			ProjectileSpeed:  150, // Pixels per second
		},

		// beginning of game time
		lastUpdate: MakeTimestamp(),
	}

	// Generate asteroids
	for i := 0; i < 100; i++ {
		id := g.generateId()
		g.asteroids[id] = CreateAsteroid(id)
	}

	return g
}

func (g *Game) run(debug bool) {
	g.debug = debug
	updateTicker := time.NewTicker(gameTickPeriod)
	gameTicker := time.NewTicker(clientUpdatePeriod)
	defer func() {
		updateTicker.Stop()
		gameTicker.Stop()
	}()

	for {
		select {
		case c := <-g.register:
			// Register client
			g.clients[c] = true

			// Create ship
			id := g.generateId()
			pos := &Coordinate{X: 0, Y: 0}
			s := &Ship{Id: id, Angle: 0, Position: pos}
			g.ships[id] = s

			// Send game state dump to player
			c.Initialize(id, g.constants, g.fullState())
		case c := <-g.unregister:
			if _, ok := g.clients[c]; ok {
				delete(g.clients, c)
			}
		case e := <-g.events:
			err := g.applyEvent(e)
			if err != nil {
				log.Println("Error applying event", e, err)
				continue
			}
		case <-gameTicker.C:
			err := g.cleanup()
			if err != nil {
				log.Println("Error Cleaning Up", err)
				continue
			}

			// calculate time since last update (in milliseconds)
			now := MakeTimestamp()
			g.lastUpdate = now
			elapsed := uint64(gameTickPeriod / time.Millisecond)

			// update physics
			for _, o := range g.ships {
				o.Tick(elapsed)
			}
			for _, o := range g.projectiles {
				o.Tick(elapsed)
			}
			for _, o := range g.asteroids {
				o.Tick(elapsed)
			}
		case <-updateTicker.C:
			g.broadcastUpdate(g.lastUpdate)
		}
	}
}

func (g *Game) applyEvent(o interface{}) error {
	switch e := o.(type) {
	case *ChangeAccelerationEvent:
		s := g.ships[e.PlayerId]
		if s == nil {
			return GameError{"Ship doesn't exist for player"}
		}

		s.Acceleration = e.Direction
		return nil
	case *ChangeRotationEvent:
		s := g.ships[e.PlayerId]
		if s == nil {
			return GameError{"Ship doesn't exist for player"}
		}

		s.Rotation = e.Direction
		return nil
	case *FireEvent:
		s := g.ships[e.PlayerId]
		if s == nil {
			return GameError{"Ship doesn't exist for player"}
		}

		pos := *s.Position // Clone ship position
		projectile := Projectile{
			Id:       e.ProjectileId,
			Velocity: AngleAndSpeedToVector(s.Angle, game.constants.ProjectileSpeed),
			Position: &pos,
			Created:  e.Created,
			Owner:    e.PlayerId,
		}
		g.projectiles[projectile.Id] = &projectile
		return nil
	default:
		return GameError{"Don't know how to apply event"}
	}
}

func (g *Game) cleanup() error {
	dead := []string{}

	for k, v := range g.projectiles {
		if !v.Alive() {
			dead = append(dead, k)
		}
	}

	for i := range dead {
		delete(g.projectiles, dead[i])
	}

	return nil
}

func (g *Game) fullState() *UpdateData {
	return &UpdateData{g.ships, g.projectiles, g.asteroids}
}

func (g *Game) broadcastUpdate(t uint64) {
	data := g.fullState()
	b, err := json.Marshal(data)
	if err != nil {
		panic(err)
	}

	raw := json.RawMessage(b)
	m := &Message{"update", t, &raw}

	if g.debug {
		log.Println(fmt.Sprintf("Ships: %d, Projectiles: %d", len(g.ships), len(g.projectiles)))
	}

	for c := range g.clients {
		c.Send(m)
	}
}

func (g *Game) generateId() string {
	g.nextId++
	return strconv.Itoa(g.nextId)
}
<commit_msg>Fixed game/client update time periods.<commit_after>package main

import (
	"encoding/json"
	"fmt"
	"log"
	"strconv"
	"time"
)

type Game struct {
	// All the important game variables
	constants *GameConstants

	// Registered clients.
	clients map[*Client]bool

	// Register requests from the clients.
	register chan *Client

	// Unregister requests from clients.
	unregister chan *Client

	// Inbound events from the clients/AIs.
	events chan interface{}

	// Game objects that currently exist
	ships       map[string]*Ship
	projectiles map[string]*Projectile
	asteroids   map[string]*Asteroid

	// Next valid game object id.
	nextId int

	// Whether or not to print debug messages.
	debug bool

	// Last physics update time
	lastUpdate uint64
}

type GameConstants struct {
	ShipAcceleration uint16 `json:"ship_acceleration"`
	ShipRotation     uint16 `json:"ship_rotation"`
	ProjectileSpeed  uint16 `json:"projectile_speed"`
}

type GameError struct {
	What string
}

func (e GameError) Error() string {
	return e.What
}

const (
	gameUpdatePeriod   = 10 * time.Millisecond
	clientUpdatePeriod = 100 * time.Millisecond
)

// TODO: Get this working without a global variable, I guess pass a ref to game into the web socket handler function?
var game = CreateGame()

func CreateGame() *Game {
	g := &Game{
		clients:     make(map[*Client]bool),
		register:    make(chan *Client),
		unregister:  make(chan *Client),
		events:      make(chan interface{}),
		ships:       make(map[string]*Ship),
		projectiles: make(map[string]*Projectile),
		asteroids:   make(map[string]*Asteroid),
		debug:       false,

		// Game constants, values per second
		constants: &GameConstants{
			ShipAcceleration: 100, // Pixels per second
			ShipRotation:     100, // Degrees per second
			ProjectileSpeed:  150, // Pixels per second
		},

		// beginning of game time
		lastUpdate: MakeTimestamp(),
	}

	// Generate asteroids
	for i := 0; i < 100; i++ {
		id := g.generateId()
		g.asteroids[id] = CreateAsteroid(id)
	}

	return g
}

func (g *Game) run(debug bool) {
	g.debug = debug
	gameUpdateTicker := time.NewTicker(gameUpdatePeriod)
	clientUpdateTicker := time.NewTicker(clientUpdatePeriod)
	defer func() {
		gameUpdateTicker.Stop()
		clientUpdateTicker.Stop()
	}()

	for {
		select {
		case c := <-g.register:
			// Register client
			g.clients[c] = true

			// Create ship
			id := g.generateId()
			pos := &Coordinate{X: 0, Y: 0}
			s := &Ship{Id: id, Angle: 0, Position: pos}
			g.ships[id] = s

			// Send game state dump to player
			c.Initialize(id, g.constants, g.fullState())
		case c := <-g.unregister:
			if _, ok := g.clients[c]; ok {
				delete(g.clients, c)
			}
		case e := <-g.events:
			err := g.applyEvent(e)
			if err != nil {
				log.Println("Error applying event", e, err)
				continue
			}
		case <-gameUpdateTicker.C:
			err := g.cleanup()
			if err != nil {
				log.Println("Error Cleaning Up", err)
				continue
			}

			// calculate time since last update (in milliseconds)
			now := MakeTimestamp()
			g.lastUpdate = now
			elapsed := uint64(gameUpdatePeriod / time.Millisecond)

			// update physics
			for _, o := range g.ships {
				o.Tick(elapsed)
			}
			for _, o := range g.projectiles {
				o.Tick(elapsed)
			}
			for _, o := range g.asteroids {
				o.Tick(elapsed)
			}
		case <-clientUpdateTicker.C:
			g.broadcastUpdate(g.lastUpdate)
		}
	}
}

func (g *Game) applyEvent(o interface{}) error {
	switch e := o.(type) {
	case *ChangeAccelerationEvent:
		s := g.ships[e.PlayerId]
		if s == nil {
			return GameError{"Ship doesn't exist for player"}
		}

		s.Acceleration = e.Direction
		return nil
	case *ChangeRotationEvent:
		s := g.ships[e.PlayerId]
		if s == nil {
			return GameError{"Ship doesn't exist for player"}
		}

		s.Rotation = e.Direction
		return nil
	case *FireEvent:
		s := g.ships[e.PlayerId]
		if s == nil {
			return GameError{"Ship doesn't exist for player"}
		}

		pos := *s.Position // Clone ship position
		projectile := Projectile{
			Id:       e.ProjectileId,
			Velocity: AngleAndSpeedToVector(s.Angle, game.constants.ProjectileSpeed),
			Position: &pos,
			Created:  e.Created,
			Owner:    e.PlayerId,
		}
		g.projectiles[projectile.Id] = &projectile
		return nil
	default:
		return GameError{"Don't know how to apply event"}
	}
}

func (g *Game) cleanup() error {
	dead := []string{}

	for k, v := range g.projectiles {
		if !v.Alive() {
			dead = append(dead, k)
		}
	}

	for i := range dead {
		delete(g.projectiles, dead[i])
	}

	return nil
}

func (g *Game) fullState() *UpdateData {
	return &UpdateData{g.ships, g.projectiles, g.asteroids}
}

func (g *Game) broadcastUpdate(t uint64) {
	data := g.fullState()
	b, err := json.Marshal(data)
	if err != nil {
		panic(err)
	}

	raw := json.RawMessage(b)
	m := &Message{"update", t, &raw}

	if g.debug {
		log.Println(fmt.Sprintf("Ships: %d, Projectiles: %d", len(g.ships), len(g.projectiles)))
	}

	for c := range g.clients {
		c.Send(m)
	}
}

func (g *Game) generateId() string {
	g.nextId++
	return strconv.Itoa(g.nextId)
}
<|endoftext|>


<commit_before>package server

import (
	"fmt"
	"io"
	"net/http"

	"github.com/gorilla/mux"
)

type Instance struct {
	ListenAddress string
	ListenPort    string

	StaticFilesDirectory string

	Router *mux.Router
}

func New() Instance {
	fmt.Printf("in server New()\n")

	var instance Instance
	return instance
}

func (instance *Instance) Initialize() {
	router := mux.NewRouter()

	router.HandleFunc("/status", StatusHandler)
	router.HandleFunc("/api", ApiHandler)
	router.PathPrefix("/static").Handler(
		http.StripPrefix("/static",
			http.FileServer(
				http.Dir(
					// TODO: replace "static" with instance.StaticFilesDirectory
					"./static")),
		),
	)

	instance.Router = router
}

func (instance *Instance) Run() {
	fmt.Printf("in server.Run().\n") // debug
	http.ListenAndServe(
		// TODO: replace the "8080" with instance.ListenPort
		fmt.Sprintf(":%d", 8080),
		instance.Router,
	)
}

func StatusHandler(respW http.ResponseWriter, req *http.Request) {
	fmt.Printf("in status handler.\n") // debug

	respW.WriteHeader(http.StatusOK)
	io.WriteString(respW, "status OK\n")
}

func ApiHandler(respW http.ResponseWriter, req *http.Request) {
	fmt.Printf("in api handler.\n") // debug

	respW.WriteHeader(http.StatusOK)
	io.WriteString(respW, "api response here\n")
}
<commit_msg>stub out api responses.<commit_after>package server

import (
	"fmt"
	"io"
	"net/http"

	"github.com/gorilla/mux"
)

type Instance struct {
	ListenAddress string
	ListenPort    string

	StaticFilesDirectory string

	Router *mux.Router
}

func New() Instance {
	fmt.Printf("in server New()\n")

	var instance Instance
	return instance
}

func (instance *Instance) Initialize() {
	router := mux.NewRouter()

	apiRouter := router.PathPrefix("/api").Subrouter()
	apiRouter.PathPrefix("/configurations").HandlerFunc(
		ConfigurationsHandler)
	apiRouter.PathPrefix("/configuration/{configurationId}").HandlerFunc(
		GetPutConfigurationHandler)
	apiRouter.PathPrefix("/configuration").HandlerFunc(
		NewConfigurationHandler)

	router.PathPrefix("/status").HandlerFunc(StatusHandler)
	router.PathPrefix("/static").Handler(
		http.StripPrefix("/static",
			http.FileServer(
				http.Dir(
					// TODO: replace "static" with instance.StaticFilesDirectory
					"./static")),
		),
	)

	instance.Router = router
}

func (instance *Instance) Run() {
	fmt.Printf("in server.Run().\n") // debug
	http.ListenAndServe(
		// TODO: replace the "8080" with instance.ListenPort
		fmt.Sprintf(":%d", 8080),
		instance.Router,
	)
}

func StatusHandler(respW http.ResponseWriter, req *http.Request) {
	fmt.Printf("in status handler.\n") // debug

	respW.WriteHeader(http.StatusOK)
	io.WriteString(respW, "status OK\n")
}

func NewApiRouter() http.Handler {
	fmt.Printf("in NewApiRouter().")
	router := mux.NewRouter()

	router.HandleFunc("/api/configurations", ConfigurationsHandler)

	return router
}

func ConfigurationsHandler(respW http.ResponseWriter, req *http.Request) {
	fmt.Printf("in configurations handler.\n") // debug

	// respW.WriteHeader(http.StatusOK)
	// io.WriteString(respW, "api response here\n")

	respW.WriteHeader(http.StatusOK)                            // debug
	io.WriteString(respW, "configurations api response here\n") // debug
}

func NewConfigurationHandler(respW http.ResponseWriter, req *http.Request) {
	fmt.Printf("in new configuration handler.\n")

	respW.WriteHeader(http.StatusOK)                                // debug
	io.WriteString(respW, "new configuration api response here.\n") // debug
}

func GetPutConfigurationHandler(respW http.ResponseWriter, req *http.Request) {
	fmt.Printf("in GET/PUT configuration handler.\n")

	respW.WriteHeader(http.StatusOK)                               // debug
	io.WriteString(respW, "get put configuration handler here.\n") // debug
}
<|endoftext|>


<commit_before>package main

import (
	// "bufio"
	"fmt"
	"net"
	"os"
	// "strings"
)

const (
	CONN_HOST = "localhost"
	CONN_PORT = "3333"
	CONN_TYPE = "tcp"
)

func main() {
	// Listen for incoming connections.
	ln, err := net.Listen(CONN_TYPE, CONN_HOST+":"+CONN_PORT)
	if err != nil {
		fmt.Println("Error listening:", err.Error())
		os.Exit(1)
	}
	// Close the listener when the application closes.
	defer ln.Close()
	fmt.Println("Listening on " + CONN_HOST + ":" + CONN_PORT)
	for {
		// Listen for an incoming connection.
		conn, err := ln.Accept()
		if err != nil {
			fmt.Println("Error accepting: ", err.Error())
			os.Exit(1)
		}
		// Handle connections in a new goroutine.
		go handleRequest(conn)
	}
}

// Handles incoming requests.
func handleRequest(conn net.Conn) {
	// Make a buffer to hold incoming data.
	buf := make([]byte, 1024)
	for {
		reqLen, err := conn.Read(buf)
		if reqLen == 0 {
			return
		}
		if err != nil {
			fmt.Println("Error reading:", err.Error())
			return
		}
		fmt.Printf("%3d>> %s\n", reqLen, buf[0:reqLen])
	}
}

//
// func main() {
//
// 	fmt.Println("Launching server...")
//
// 	// listen on all interfaces
// 	ln, _ := net.Listen("tcp", ":8081")
//
// 	// accept connection on port
// 	conn, _ := ln.Accept()
//
// 	// run loop forever (or until ctrl-c)
// 	for {
// 		// will listen for message to process ending in newline (\n)
// 		message, err := bufio.NewReader(conn).ReadString('\n')
// 		if err != nil {
// 			fmt.Printf("%v", err)
// 		}
// 		if len(message) > 0 {
// 			// output message received
// 			fmt.Print("Message Received:", string(message))
// 			// sample process for string received
// 			newmessage := strings.ToUpper(message)
// 			// send new string back to client
// 			conn.Write([]byte(newmessage + "\n"))
//
// 		}
// 	}
// }
<commit_msg>test: change server default port<commit_after>package main

import (
	// "bufio"
	"fmt"
	"net"
	"os"
	// "strings"
)

const (
	CONN_HOST = "localhost"
	CONN_PORT = "7000"
	CONN_TYPE = "tcp"
)

func main() {
	// Listen for incoming connections.
	ln, err := net.Listen(CONN_TYPE, CONN_HOST+":"+CONN_PORT)
	if err != nil {
		fmt.Println("Error listening:", err.Error())
		os.Exit(1)
	}
	// Close the listener when the application closes.
	defer ln.Close()
	fmt.Println("Listening on " + CONN_HOST + ":" + CONN_PORT)
	for {
		// Listen for an incoming connection.
		conn, err := ln.Accept()
		if err != nil {
			fmt.Println("Error accepting: ", err.Error())
			os.Exit(1)
		}
		// Handle connections in a new goroutine.
		go handleRequest(conn)
	}
}

// Handles incoming requests.
func handleRequest(conn net.Conn) {
	// Make a buffer to hold incoming data.
	buf := make([]byte, 1024)
	for {
		reqLen, err := conn.Read(buf)
		if reqLen == 0 {
			return
		}
		if err != nil {
			fmt.Println("Error reading:", err.Error())
			return
		}
		fmt.Printf("%3d>> %s\n", reqLen, buf[0:reqLen])
	}
}

//
// func main() {
//
// 	fmt.Println("Launching server...")
//
// 	// listen on all interfaces
// 	ln, _ := net.Listen("tcp", ":8081")
//
// 	// accept connection on port
// 	conn, _ := ln.Accept()
//
// 	// run loop forever (or until ctrl-c)
// 	for {
// 		// will listen for message to process ending in newline (\n)
// 		message, err := bufio.NewReader(conn).ReadString('\n')
// 		if err != nil {
// 			fmt.Printf("%v", err)
// 		}
// 		if len(message) > 0 {
// 			// output message received
// 			fmt.Print("Message Received:", string(message))
// 			// sample process for string received
// 			newmessage := strings.ToUpper(message)
// 			// send new string back to client
// 			conn.Write([]byte(newmessage + "\n"))
//
// 		}
// 	}
// }
<|endoftext|>


<commit_before>// Copyright © 2017 Alexander Sosna <alexander@xxor.de>
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
package util

import (
	"bytes"
	"errors"
	"io"
	"io/ioutil"
	"os/exec"
	"regexp"
	"time"

	log "github.com/Sirupsen/logrus"
)

const (
	BackupTimeFormat  = time.RFC3339
	saneBackupMinSize = 2 * 1000000 // ~ 4MB

	// Larger files are most likely no backup label
	maxBackupLabelSize = 2048
)

// Backup stores information about a backup
type Backup struct {
	Name             string
	Extension        string
	Path             string
	Bucket           string
	Size             int64
	Created          time.Time
	LabelFile        string
	BackupLabel      string
	StartWalLocation string
	Backups          *Backups
}

// IsSane returns true if the backup seams sane
func (b *Backup) IsSane() (sane bool) {
	if b.Size < saneBackupMinSize {
		return false
	}

	if b.StorageType() == "" {
		return false
	}

	return true
}

// StorageType returns the type of storage the backup is on
func (b *Backup) StorageType() (storageType string) {
	if b.Path > "" {
		return "file"
	}

	if b.Bucket > "" {
		return "s3"
	}

	// Not defined
	return ""
}

// GetStartWalLocation returns the oldest needed WAL file
// Every older WAL file is not required to use this backup
func (b *Backup) GetStartWalLocation() (startWalLocation string, err error) {
	switch b.StorageType() {
	case "file":
		return b.GetStartWalLocationFromFile()
	case "s3":
		return b.GetStartWalLocationFromS3()
	}
	return "", errors.New("Not supported StorageType: " + b.StorageType())
}

// GetStartWalLocationFromFile returns the oldest needed WAL file
// Every older WAL file is not required to use this backup
func (b *Backup) GetStartWalLocationFromFile() (startWalLocation string, err error) {
	// Regex to identify a backup label file
	// 000000010000001200000062.00000028.backup, make better regex
	regBackupLabelFile := regexp.MustCompile(`.*\.backup`)

	// Regex to identify the right file
	regLabel := regexp.MustCompile(`.*LABEL: ` + b.Name)

	files, _ := ioutil.ReadDir(b.Backups.WalDir)
	// find all backup labels
	for _, f := range files {
		if f.Size() > maxBackupLabelSize {
			// size is to big for backup label
			continue
		}
		if regBackupLabelFile.MatchString(f.Name()) {
			log.Debug(f.Name(), " => seems to be a backup Label, by size and name")

			labelFile := b.Backups.WalDir + "/" + f.Name()
			catCmd := exec.Command("/usr/bin/zstdcat", labelFile)
			catCmdStdout, err := catCmd.StdoutPipe()
			if err != nil {
				// if we can not open the file we continue with next
				log.Warn("catCmd.StdoutPipe(), ", err)
				continue
			}

			err = catCmd.Start()
			if err != nil {
				log.Warn("catCmd.Start(), ", err)
				continue
			}

			buf, err := ioutil.ReadAll(catCmdStdout)
			if err != nil {
				log.Warn("Reading from command: ", err)
				continue
			}

			err = catCmd.Wait()
			if err != nil {
				log.Warn("catCmd.Wait(), ", err)
				continue
			}

			if len(regLabel.Find(buf)) > 1 {
				log.Debug("Found matching backup label file: ", f.Name())
				err = b.parseBackupLabel(buf)
				if err == nil {
					b.LabelFile = labelFile
				}
				return b.StartWalLocation, err
			}
		}
	}
	return "", errors.New("START WAL LOCATION not found")
}

// GetStartWalLocationFromS3 returns the oldest needed WAL file
// Every older WAL file is not required to use this backup
func (b *Backup) GetStartWalLocationFromS3() (startWalLocation string, err error) {
	// Regex to identify a backup label file
	// 000000010000001200000062.00000028.backup, make better regex
	regBackupLabelFile := regexp.MustCompile(`.*\.backup`)

	// Escape the name so we can use it in a regular expression
	searchName := regexp.QuoteMeta(b.Name)
	// Regex to identify the right file
	regLabel := regexp.MustCompile(`.*LABEL: ` + searchName)
	log.Debug("regLabel: ", regLabel)

	log.Debug("Looking for the backup label that contains: ", b.Name)

	// Create a done channel to control 'ListObjects' go routine.
	doneCh := make(chan struct{})
	defer close(doneCh)

	isRecursive := true
	objectCh := b.Backups.MinioClient.ListObjects(b.Backups.WalBucket, "", isRecursive, doneCh)
	for object := range objectCh {
		if object.Err != nil {
			log.Error(object.Err)
		}

		if object.Size > maxBackupLabelSize {
			// size is to big for backup label
			// log.Debug("Object is to big to be a backup label, size: ", object.Size)
			continue
		}

		if regBackupLabelFile.MatchString(object.Key) {
			log.Debug(object.Key, " => seems to be a backup Label, by size and name")

			backupLabelFile, err := b.Backups.MinioClient.GetObject(b.Backups.WalBucket, object.Key)
			if err != nil {
				log.Warn("Can not get backupLabel, ", err)
				continue
			}

			bufCompressed := make([]byte, maxBackupLabelSize)
			readCount, err := backupLabelFile.Read(bufCompressed)
			if err != nil && err != io.EOF {
				log.Warn("Can not read backupLabel, ", err)
				continue
			}
			log.Debug("Read ", readCount, " from backupLabel")

			// Command to decompress the backuplabel
			catCmd := exec.Command("zstd", "-d", "--stdout")
			catCmdStdout, err := catCmd.StdoutPipe()
			if err != nil {
				// if we can not open the file we continue with next
				log.Warn("catCmd.StdoutPipe(), ", err)
				continue
			}

			// Use backupLabel as input for catCmd
			catCmd.Stdin = bytes.NewReader(bufCompressed)
			catCmdStderror, err := catCmd.StderrPipe()
			go WatchOutput(catCmdStderror, log.Debug)

			err = catCmd.Start()
			if err != nil {
				log.Warn("catCmd.Start(), ", err)
				continue
			}

			bufPlain, err := ioutil.ReadAll(catCmdStdout)
			if err != nil {
				log.Warn("Reading from command: ", err)
				continue
			}

			err = catCmd.Wait()
			if err != nil {
				// We ignore errors here, zstd returns 1 even if everything is fine here
				log.Debug("catCmd.Wait(), ", err)
			}
			log.Debug("Backuplabel:\n", string(bufPlain))

			if len(regLabel.Find(bufPlain)) > 1 {
				log.Debug("Found matching backup label")
				err = b.parseBackupLabel(bufPlain)
				if err != nil {
					log.Error(err)
				}
				b.LabelFile = object.Key
				return b.StartWalLocation, err
			}
		}
	}
	return "", errors.New("START WAL LOCATION not found")
}

func (b *Backup) parseBackupLabel(backupLabel []byte) (err error) {
	regStartWalLine := regexp.MustCompile(`^START WAL LOCATION: .*\/.* \(file [0-9A-Fa-f]{24}\)`)
	regStartWal := regexp.MustCompile(`[0-9A-Fa-f]{24}`)

	startWalLine := regStartWalLine.Find(backupLabel)
	if len(startWalLine) < 1 {
		log.Debug(string(backupLabel))
		return errors.New("Can not find line with START WAL LOCATION")
	}

	startWal := regStartWal.Find(startWalLine)
	if len(startWal) < 1 {
		return errors.New("Can not find START WAL")
	}

	b.StartWalLocation = string(startWal)
	return nil
}
<commit_msg>Fix WAL deletion problem for fs backups<commit_after>// Copyright © 2017 Alexander Sosna <alexander@xxor.de>
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
package util

import (
	"bytes"
	"errors"
	"io"
	"io/ioutil"
	"os/exec"
	"regexp"
	"time"

	log "github.com/Sirupsen/logrus"
)

const (
	BackupTimeFormat  = time.RFC3339
	saneBackupMinSize = 2 * 1000000 // ~ 4MB

	// Larger files are most likely no backup label
	maxBackupLabelSize = 2048
)

// Backup stores information about a backup
type Backup struct {
	Name             string
	Extension        string
	Path             string
	Bucket           string
	Size             int64
	Created          time.Time
	LabelFile        string
	BackupLabel      string
	StartWalLocation string
	Backups          *Backups
}

// IsSane returns true if the backup seams sane
func (b *Backup) IsSane() (sane bool) {
	if b.Size < saneBackupMinSize {
		return false
	}

	if b.StorageType() == "" {
		return false
	}

	return true
}

// StorageType returns the type of storage the backup is on
func (b *Backup) StorageType() (storageType string) {
	if b.Path > "" {
		return "file"
	}

	if b.Bucket > "" {
		return "s3"
	}

	// Not defined
	return ""
}

// GetStartWalLocation returns the oldest needed WAL file
// Every older WAL file is not required to use this backup
func (b *Backup) GetStartWalLocation() (startWalLocation string, err error) {
	switch b.StorageType() {
	case "file":
		return b.GetStartWalLocationFromFile()
	case "s3":
		return b.GetStartWalLocationFromS3()
	}
	return "", errors.New("Not supported StorageType: " + b.StorageType())
}

// GetStartWalLocationFromFile returns the oldest needed WAL file
// Every older WAL file is not required to use this backup
func (b *Backup) GetStartWalLocationFromFile() (startWalLocation string, err error) {
	// Regex to identify a backup label file
	// 000000010000001200000062.00000028.backup, make better regex
	regBackupLabelFile := regexp.MustCompile(`.*\.backup`)

	// Escape the name so we can use it in a regular expression
	searchName := regexp.QuoteMeta(b.Name)
	// Regex to identify the right file
	regLabel := regexp.MustCompile(`.*LABEL: ` + searchName)
	log.Debug("regLabel: ", regLabel)

	files, _ := ioutil.ReadDir(b.Backups.WalDir)
	// find all backup labels
	for _, f := range files {
		if f.Size() > maxBackupLabelSize {
			// size is to big for backup label
			continue
		}
		if regBackupLabelFile.MatchString(f.Name()) {
			log.Debug(f.Name(), " => seems to be a backup Label, by size and name")

			labelFile := b.Backups.WalDir + "/" + f.Name()
			catCmd := exec.Command("/usr/bin/zstdcat", labelFile)
			catCmdStdout, err := catCmd.StdoutPipe()
			if err != nil {
				// if we can not open the file we continue with next
				log.Warn("catCmd.StdoutPipe(), ", err)
				continue
			}

			err = catCmd.Start()
			if err != nil {
				log.Warn("catCmd.Start(), ", err)
				continue
			}

			buf, err := ioutil.ReadAll(catCmdStdout)
			if err != nil {
				log.Warn("Reading from command: ", err)
				continue
			}

			err = catCmd.Wait()
			if err != nil {
				log.Warn("catCmd.Wait(), ", err)
				continue
			}

			if len(regLabel.Find(buf)) > 1 {
				log.Debug("Found matching backup label file: ", f.Name())
				err = b.parseBackupLabel(buf)
				if err == nil {
					b.LabelFile = labelFile
				}
				return b.StartWalLocation, err
			}
		}
	}
	return "", errors.New("START WAL LOCATION not found")
}

// GetStartWalLocationFromS3 returns the oldest needed WAL file
// Every older WAL file is not required to use this backup
func (b *Backup) GetStartWalLocationFromS3() (startWalLocation string, err error) {
	// Regex to identify a backup label file
	// 000000010000001200000062.00000028.backup, make better regex
	regBackupLabelFile := regexp.MustCompile(`.*\.backup`)

	// Escape the name so we can use it in a regular expression
	searchName := regexp.QuoteMeta(b.Name)
	// Regex to identify the right file
	regLabel := regexp.MustCompile(`.*LABEL: ` + searchName)
	log.Debug("regLabel: ", regLabel)

	log.Debug("Looking for the backup label that contains: ", b.Name)

	// Create a done channel to control 'ListObjects' go routine.
	doneCh := make(chan struct{})
	defer close(doneCh)

	isRecursive := true
	objectCh := b.Backups.MinioClient.ListObjects(b.Backups.WalBucket, "", isRecursive, doneCh)
	for object := range objectCh {
		if object.Err != nil {
			log.Error(object.Err)
		}

		if object.Size > maxBackupLabelSize {
			// size is to big for backup label
			// log.Debug("Object is to big to be a backup label, size: ", object.Size)
			continue
		}

		if regBackupLabelFile.MatchString(object.Key) {
			log.Debug(object.Key, " => seems to be a backup Label, by size and name")

			backupLabelFile, err := b.Backups.MinioClient.GetObject(b.Backups.WalBucket, object.Key)
			if err != nil {
				log.Warn("Can not get backupLabel, ", err)
				continue
			}

			bufCompressed := make([]byte, maxBackupLabelSize)
			readCount, err := backupLabelFile.Read(bufCompressed)
			if err != nil && err != io.EOF {
				log.Warn("Can not read backupLabel, ", err)
				continue
			}
			log.Debug("Read ", readCount, " from backupLabel")

			// Command to decompress the backuplabel
			catCmd := exec.Command("zstd", "-d", "--stdout")
			catCmdStdout, err := catCmd.StdoutPipe()
			if err != nil {
				// if we can not open the file we continue with next
				log.Warn("catCmd.StdoutPipe(), ", err)
				continue
			}

			// Use backupLabel as input for catCmd
			catCmd.Stdin = bytes.NewReader(bufCompressed)
			catCmdStderror, err := catCmd.StderrPipe()
			go WatchOutput(catCmdStderror, log.Debug)

			err = catCmd.Start()
			if err != nil {
				log.Warn("catCmd.Start(), ", err)
				continue
			}

			bufPlain, err := ioutil.ReadAll(catCmdStdout)
			if err != nil {
				log.Warn("Reading from command: ", err)
				continue
			}

			err = catCmd.Wait()
			if err != nil {
				// We ignore errors here, zstd returns 1 even if everything is fine here
				log.Debug("catCmd.Wait(), ", err)
			}
			log.Debug("Backuplabel:\n", string(bufPlain))

			if len(regLabel.Find(bufPlain)) > 1 {
				log.Debug("Found matching backup label")
				err = b.parseBackupLabel(bufPlain)
				if err != nil {
					log.Error(err)
				}
				b.LabelFile = object.Key
				return b.StartWalLocation, err
			}
		}
	}
	return "", errors.New("START WAL LOCATION not found")
}

func (b *Backup) parseBackupLabel(backupLabel []byte) (err error) {
	regStartWalLine := regexp.MustCompile(`^START WAL LOCATION: .*\/.* \(file [0-9A-Fa-f]{24}\)`)
	regStartWal := regexp.MustCompile(`[0-9A-Fa-f]{24}`)

	startWalLine := regStartWalLine.Find(backupLabel)
	if len(startWalLine) < 1 {
		log.Debug(string(backupLabel))
		return errors.New("Can not find line with START WAL LOCATION")
	}

	startWal := regStartWal.Find(startWalLine)
	if len(startWal) < 1 {
		return errors.New("Can not find START WAL")
	}

	b.StartWalLocation = string(startWal)
	return nil
}
<|endoftext|>


<commit_before>package util

import (
	"fmt"
	"time"

	"github.com/101loops/clock"
)

type Bucket struct {
	prefix     string
	bucketSize time.Duration
	timestamp  time.Time
}

func (b Bucket) String() string {
	return fmt.Sprintf("%s:%d", b.prefix, b.timestamp.Unix()/int64(b.bucketSize.Seconds()))
}

func CurrentBucket(c clock.Clock, prefix string, bucketSize time.Duration) Bucket {
	return BucketWithOffset(c, prefix, bucketSize, 0)
}

func BucketWithOffset(c clock.Clock, prefix string, bucketSize time.Duration, offset int) Bucket {
	if bucketSize <= time.Second {
		bucketSize = time.Second
	}
	return Bucket{
		prefix:     prefix,
		bucketSize: bucketSize,
		timestamp:  c.Now().Add(time.Duration(offset) * bucketSize),
	}
}

func BucketRange(c clock.Clock, prefix string, bucketSize time.Duration, offsetStart int, offsetEnd int) []Bucket {
	buckets := make([]Bucket, 0, offsetEnd-offsetStart)
	for i := offsetStart; i <= offsetEnd; i++ {
		buckets = append(buckets, BucketWithOffset(c, prefix, bucketSize, i))
	}
	return buckets
}
<commit_msg>Make bucket name concatenation more efficient.<commit_after>package util

import (
	"strconv"
	"time"

	"github.com/101loops/clock"
)

type Bucket struct {
	prefix     string
	bucketSize time.Duration
	timestamp  time.Time
}

func (b Bucket) String() string {
	return b.prefix + ":" + strconv.FormatInt(b.timestamp.Unix()/int64(b.bucketSize.Seconds()), 10)
}

func CurrentBucket(c clock.Clock, prefix string, bucketSize time.Duration) Bucket {
	return BucketWithOffset(c, prefix, bucketSize, 0)
}

func BucketWithOffset(c clock.Clock, prefix string, bucketSize time.Duration, offset int) Bucket {
	if bucketSize <= time.Second {
		bucketSize = time.Second
	}
	return Bucket{
		prefix:     prefix,
		bucketSize: bucketSize,
		timestamp:  c.Now().Add(time.Duration(offset) * bucketSize),
	}
}

func BucketRange(c clock.Clock, prefix string, bucketSize time.Duration, offsetStart int, offsetEnd int) []Bucket {
	buckets := make([]Bucket, 0, offsetEnd-offsetStart)
	for i := offsetStart; i <= offsetEnd; i++ {
		buckets = append(buckets, BucketWithOffset(c, prefix, bucketSize, i))
	}
	return buckets
}
<|endoftext|>


<commit_before>package main

import (
	//"flag"
	"os"
	"fmt"
	"io/ioutil"
	. "github.com/sebkl/gotojs"
)

func printUsage() {
	cmd:= os.Args[0]
	fmt.Printf(`
Usage:
	%s <command> [argument]

The Commands are:
	example <path_to_app_root>	Create a sample app.
	create 	<path_to_app_root>	Create a sample directory structure.
	export 	<path_to_template_dir>	Exports internally used templates.

Examples:
	%s create /var/www/helloworld
`,cmd,cmd)
}

const (
	fflag = os.FileMode(0644)
	dflag = os.FileMode(0755)
)

func check(e error) {
	if e != nil {
		printUsage()
		panic(e)
	}
}

func exportTemplates(path string) {
	fflag := os.FileMode(0644)

	temp := DefaultTemplates()
	err := ioutil.WriteFile(path + "/" + Template,[]byte(temp.Binding),fflag);
	check(err)
	err = ioutil.WriteFile(path + "/" + InterfaceTemplate,[]byte(temp.Interface),fflag);
	check(err)
	err = ioutil.WriteFile(path + "/" + MethodTemplate,[]byte(temp.Method),fflag);
	check(err)
}

func createBaseDirs(path string) {
	err := os.MkdirAll(path,dflag)
	check(err)
	err = os.MkdirAll(path + "/" + DefaultFileServerDir,dflag)
	check(err)
	err = os.MkdirAll(path + "/" + RelativePath,dflag)
	check(err)
	err = os.MkdirAll(path + "/" + RelativeLibPath,dflag)
	check(err)
}

func createSampleFiles(path string) {
	createBaseDirs(path)
	err := ioutil.WriteFile(path + "/" + DefaultFileServerDir + "/index.html",[]byte(`
<!DOCTYPE HTML>

  <title>gotojs example</title>
  <link type="text/css" href="css/main.css" rel="Stylesheet"/>

Hello World !

 `),fflag);
	check(err)
	err = os.MkdirAll(path + "/" + DefaultFileServerDir + "/css",dflag)
	check(err)
	err = os.MkdirAll(path + "/" + DefaultFileServerDir + "/js",dflag)
	check(err)
	err = ioutil.WriteFile(path + "/" + DefaultFileServerDir + "/css/main.css",[]byte(`
h1{ font-family: sans-serif; color: #AAAAAA; }
`),fflag);
	check(err)

	err = ioutil.WriteFile(path + "/app.go",[]byte(`
package main

import (
	"log"
	"fmt"
	"strings"
	. "github.com/sebkl/gotojs"
)

// Declare Service to be exposed.
type Service struct {}

// Methods of Service that will be exposed.
func (s *Service) UpperCase(mes string) string {
    return fmt.Sprintf("%s",strings.ToUpper(mes))
}

// Function that takes the HTTPContext as injection.
func AppendURL(context *HTTPContext, source string) string{
	return fmt.Sprintf("%s (%s)",source,context.Request.URL.String())
}

func main() {
	// Initialize the frontend.
	frontend := NewFrontend(F_DEFAULT, map[int]string{
		P_EXTERNALURL: "http://localhost:8080/gotojs"})

	// Setup the service object.
	service := Service{}

        // Declare some js code that is doing the calls. Usually this is done by a flat file in the public directory,
        // but in this case we would like to show how to use HandleStatic.
        myjs := "$(document).ready(function() {"
        myjs += "       var text = $('h1').html();"
        myjs += "       text = PROXY.Service.UpperCase(text);" // Make the title uppcase by the server side implementation
        myjs += "       text = PROXY.Service.AppendURL(text);" // Append the URL by the server side  implementation
        myjs += "       $('h1').html(text);"
        myjs += "});"

	// Expose the interface and setup the request routing.
	frontend.ExposeInterface(&service,"Service")
	frontend.ExposeFunction(AppendURL,"Service","AppendURL") // Name the function and expose it to existing interface.
	frontend.Redirect("/", "/public/index.html")
	frontend.HandleStatic("/my.js",myjs,"application/javascript")

	log.Fatal(frontend.Start())
}
`),fflag);
	check(err)
}

func main() {
	al := len(os.Args)
	if al < 3 {
		printUsage()
		return
	}

	cmd := os.Args[1]
	arg := os.Args[2]

	switch cmd {
		case "example":
			createSampleFiles(arg)
			exportTemplates(arg + "/" + RelativePath)
		case "create":
			createBaseDirs(arg)
			exportTemplates(arg + "/" + RelativePath)
		case "export":
			exportTemplates(arg)
		default:
			fmt.Printf("Unknown command: %s\n\n",cmd)
			printUsage()
	}

}
<commit_msg>Fixed initialization bug.<commit_after>package main

import (
	//"flag"
	"os"
	"fmt"
	"io/ioutil"
	. "github.com/sebkl/gotojs"
)

func printUsage() {
	cmd:= os.Args[0]
	fmt.Printf(`
Usage:
	%s <command> [argument]

The Commands are:
	example <path_to_app_root>	Create a sample app.
	create 	<path_to_app_root>	Create a sample directory structure.
	export 	<path_to_template_dir>	Exports internally used templates.

Examples:
	%s create /var/www/helloworld
`,cmd,cmd)
}

const (
	fflag = os.FileMode(0644)
	dflag = os.FileMode(0755)
)

func check(e error) {
	if e != nil {
		printUsage()
		panic(e)
	}
}

func exportTemplates(path string) {
	fflag := os.FileMode(0644)

	temp := DefaultTemplates()
	err := ioutil.WriteFile(path + "/" + Template,[]byte(temp.Binding),fflag);
	check(err)
	err = ioutil.WriteFile(path + "/" + InterfaceTemplate,[]byte(temp.Interface),fflag);
	check(err)
	err = ioutil.WriteFile(path + "/" + MethodTemplate,[]byte(temp.Method),fflag);
	check(err)
}

func createBaseDirs(path string) {
	err := os.MkdirAll(path,dflag)
	check(err)
	err = os.MkdirAll(path + "/" + DefaultFileServerDir,dflag)
	check(err)
	err = os.MkdirAll(path + "/" + RelativePath,dflag)
	check(err)
	err = os.MkdirAll(path + "/" + RelativeLibPath,dflag)
	check(err)
}

func createSampleFiles(path string) {
	createBaseDirs(path)
	err := ioutil.WriteFile(path + "/" + DefaultFileServerDir + "/index.html",[]byte(`
<!DOCTYPE HTML>

  <title>gotojs example</title>
  <link type="text/css" href="css/main.css" rel="Stylesheet"/>

Hello World !

 `),fflag);
	check(err)
	err = os.MkdirAll(path + "/" + DefaultFileServerDir + "/css",dflag)
	check(err)
	err = os.MkdirAll(path + "/" + DefaultFileServerDir + "/js",dflag)
	check(err)
	err = ioutil.WriteFile(path + "/" + DefaultFileServerDir + "/css/main.css",[]byte(`
h1{ font-family: sans-serif; color: #AAAAAA; }
`),fflag);
	check(err)

	err = ioutil.WriteFile(path + "/app.go",[]byte(`
package main

import (
	"log"
	"fmt"
	"strings"
	. "github.com/sebkl/gotojs"
)

// Declare Service to be exposed.
type Service struct {}

// Methods of Service that will be exposed.
func (s *Service) UpperCase(mes string) string {
    return fmt.Sprintf("%s",strings.ToUpper(mes))
}

// Function that takes the HTTPContext as injection.
func AppendURL(context *HTTPContext, source string) string{
	return fmt.Sprintf("%s (%s)",source,context.Request.URL.String())
}

func main() {
	// Initialize the frontend.
	frontend := NewFrontend()

	// Setup the service object.
	service := Service{}

        // Declare some js code that is doing the calls. Usually this is done by a flat file in the public directory,
        // but in this case we would like to show how to use HandleStatic.
        myjs := "$(document).ready(function() {"
        myjs += "       var text = $('h1').html();"
        myjs += "       text = PROXY.Service.UpperCase(text);" // Make the title uppcase by the server side implementation
        myjs += "       text = PROXY.Service.AppendURL(text);" // Append the URL by the server side  implementation
        myjs += "       $('h1').html(text);"
        myjs += "});"

	// Expose the interface and setup the request routing.
	frontend.ExposeInterface(&service,"Service")
	frontend.ExposeFunction(AppendURL,"Service","AppendURL") // Name the function and expose it to existing interface.
	frontend.Redirect("/", "/public/index.html")
	frontend.HandleStatic("/my.js",myjs,"application/javascript")
	log.Fatal(frontend.Start(":8080","/gotojs"))
}
`),fflag);
	check(err)
}

func main() {
	al := len(os.Args)
	if al < 3 {
		printUsage()
		return
	}

	cmd := os.Args[1]
	arg := os.Args[2]

	switch cmd {
		case "example":
			createSampleFiles(arg)
			exportTemplates(arg + "/" + RelativePath)
		case "create":
			createBaseDirs(arg)
			exportTemplates(arg + "/" + RelativePath)
		case "export":
			exportTemplates(arg)
		default:
			fmt.Printf("Unknown command: %s\n\n",cmd)
			printUsage()
	}

}
<|endoftext|>