<commit_before>// Copyright (c) 2017 Uber Technologies, Inc.
//
// 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 pally

import (
	"testing"
	"time"

	"go.uber.org/yarpc/internal/pally/pallytest"

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

func TestSimpleVectors(t *testing.T) {
	tests := []struct {
		desc      string
		opts      Opts
		f         func(testing.TB, *Registry, Opts)
		wantTally TallyExpectation
		wantProm  string
	}{
		{
			desc: "valid counter labels",
			opts: Opts{
				Name:           "test_counter",
				Help:           "Some help.",
				VariableLabels: []string{"var"},
			},
			f: func(t testing.TB, r *Registry, opts Opts) {
				vec, err := r.NewCounterVector(opts)
				require.NoError(t, err, "Unexpected error constructing vector.")
				counter, err := vec.Get("x")
				require.NoError(t, err, "Unexpected error getting a counter with correct number of labels.")
				counter.Inc()
				vec.MustGet("x").Add(2)
				assert.Equal(t, int64(3), counter.Load(), "Unexpected in-memory metric value.")
			},
			wantTally: TallyExpectation{
				Type:   "counter",
				Name:   "test_counter",
				Labels: Labels{"var": "x"},
				Value:  3,
			},
			wantProm: "# HELP test_counter Some help.\n" +
				"# TYPE test_counter counter\n" +
				`test_counter{var="x"} 3`,
		},
		{
			desc: "invalid counter labels",
			opts: Opts{
				Name:           "test_counter",
				Help:           "Some help.",
				VariableLabels: []string{"var"},
			},
			f: func(t testing.TB, r *Registry, opts Opts) {
				vec, err := r.NewCounterVector(opts)
				require.NoError(t, err, "Unexpected error constructing vector.")
				counter, err := vec.Get("x!")
				require.NoError(t, err, "Unexpected error getting a counter with correct number of labels.")
				counter.Inc()
				vec.MustGet("x!").Add(2)
				assert.Equal(t, int64(3), counter.Load(), "Unexpected in-memory metric value.")
			},
			wantTally: TallyExpectation{
				Type:   "counter",
				Name:   "test_counter",
				Labels: Labels{"var": "x-"},
				Value:  3,
			},
			wantProm: "# HELP test_counter Some help.\n" +
				"# TYPE test_counter counter\n" +
				`test_counter{var="x-"} 3`,
		},
		{
			desc: "wrong number of counter labels",
			opts: Opts{
				Name:           "test_counter",
				Help:           "Some help.",
				VariableLabels: []string{"var"},
			},
			f: func(t testing.TB, r *Registry, opts Opts) {
				vec, err := r.NewCounterVector(opts)
				require.NoError(t, err, "Unexpected error constructing vector.")
				_, err = vec.Get("x", "y")
				require.Error(t, err, "Expected an error getting a counter with incorrect number of labels.")
				require.Panics(t, func() { vec.MustGet("x", "y") }, "Expected panic getting a counter with incorrect number of labels.")
			},
		},
		{
			desc: "valid gauge labels",
			opts: Opts{
				Name:           "test_gauge",
				Help:           "Some help.",
				VariableLabels: []string{"var"},
			},
			f: func(t testing.TB, r *Registry, opts Opts) {
				vec, err := r.NewGaugeVector(opts)
				require.NoError(t, err, "Unexpected error constructing vector.")
				gauge, err := vec.Get("x")
				require.NoError(t, err, "Unexpected error getting a gauge with correct number of labels.")
				gauge.Inc()
				vec.MustGet("x").Store(2)
				assert.Equal(t, int64(2), gauge.Load(), "Unexpected in-memory metric value.")
			},
			wantTally: TallyExpectation{
				Type:   "gauge",
				Name:   "test_gauge",
				Labels: Labels{"var": "x"},
				Value:  2,
			},
			wantProm: "# HELP test_gauge Some help.\n" +
				"# TYPE test_gauge gauge\n" +
				`test_gauge{var="x"} 2`,
		},
		{
			desc: "invalid gauge labels",
			opts: Opts{
				Name:           "test_gauge",
				Help:           "Some help.",
				VariableLabels: []string{"var"},
			},
			f: func(t testing.TB, r *Registry, opts Opts) {
				vec, err := r.NewGaugeVector(opts)
				require.NoError(t, err, "Unexpected error constructing vector.")
				gauge, err := vec.Get("x!")
				require.NoError(t, err, "Unexpected error getting a gauge with correct number of labels.")
				gauge.Inc()
				vec.MustGet("x!").Store(2)
				assert.Equal(t, int64(2), gauge.Load(), "Unexpected in-memory metric value.")
			},
			wantTally: TallyExpectation{
				Type:   "gauge",
				Name:   "test_gauge",
				Labels: Labels{"var": "x-"},
				Value:  2,
			},
			wantProm: "# HELP test_gauge Some help.\n" +
				"# TYPE test_gauge gauge\n" +
				`test_gauge{var="x-"} 2`,
		},
		{
			desc: "wrong number of gauge labels",
			opts: Opts{
				Name:           "test_gauge",
				Help:           "Some help.",
				VariableLabels: []string{"var"},
			},
			f: func(t testing.TB, r *Registry, opts Opts) {
				vec, err := r.NewGaugeVector(opts)
				require.NoError(t, err, "Unexpected error constructing vector.")
				_, err = vec.Get("x", "y")
				require.Error(t, err, "Expected an error getting a gauge with incorrect number of labels.")
				require.Panics(t, func() { vec.MustGet("x", "y") }, "Expected panic getting a gauge with incorrect number of labels.")
			},
		},
	}

	for _, tt := range tests {
		t.Run(tt.desc, func(t *testing.T) {
			r := NewRegistry()

			scope := newTestScope()
			stop, err := r.Push(scope, _tick)
			require.NoError(t, err, "Unexpected error starting Tally push.")
			defer stop()

			tt.f(t, r, tt.opts)

			time.Sleep(5 * _tick)
			tt.wantTally.Test(t, scope)

			pallytest.AssertPrometheus(t, r, tt.wantProm)
		})
	}
}
<commit_msg>Try to make TestSimpleVectors less flaky (#1123)<commit_after>// Copyright (c) 2017 Uber Technologies, Inc.
//
// 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 pally

import (
	"testing"
	"time"

	"go.uber.org/yarpc/internal/pally/pallytest"

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

func TestSimpleVectors(t *testing.T) {
	tests := []struct {
		desc      string
		opts      Opts
		f         func(testing.TB, *Registry, Opts)
		wantTally TallyExpectation
		wantProm  string
	}{
		{
			desc: "valid counter labels",
			opts: Opts{
				Name:           "test_counter",
				Help:           "Some help.",
				VariableLabels: []string{"var"},
			},
			f: func(t testing.TB, r *Registry, opts Opts) {
				vec, err := r.NewCounterVector(opts)
				require.NoError(t, err, "Unexpected error constructing vector.")
				counter, err := vec.Get("x")
				require.NoError(t, err, "Unexpected error getting a counter with correct number of labels.")
				counter.Inc()
				vec.MustGet("x").Add(2)
				assert.Equal(t, int64(3), counter.Load(), "Unexpected in-memory metric value.")
			},
			wantTally: TallyExpectation{
				Type:   "counter",
				Name:   "test_counter",
				Labels: Labels{"var": "x"},
				Value:  3,
			},
			wantProm: "# HELP test_counter Some help.\n" +
				"# TYPE test_counter counter\n" +
				`test_counter{var="x"} 3`,
		},
		{
			desc: "invalid counter labels",
			opts: Opts{
				Name:           "test_counter",
				Help:           "Some help.",
				VariableLabels: []string{"var"},
			},
			f: func(t testing.TB, r *Registry, opts Opts) {
				vec, err := r.NewCounterVector(opts)
				require.NoError(t, err, "Unexpected error constructing vector.")
				counter, err := vec.Get("x!")
				require.NoError(t, err, "Unexpected error getting a counter with correct number of labels.")
				counter.Inc()
				vec.MustGet("x!").Add(2)
				assert.Equal(t, int64(3), counter.Load(), "Unexpected in-memory metric value.")
			},
			wantTally: TallyExpectation{
				Type:   "counter",
				Name:   "test_counter",
				Labels: Labels{"var": "x-"},
				Value:  3,
			},
			wantProm: "# HELP test_counter Some help.\n" +
				"# TYPE test_counter counter\n" +
				`test_counter{var="x-"} 3`,
		},
		{
			desc: "wrong number of counter labels",
			opts: Opts{
				Name:           "test_counter",
				Help:           "Some help.",
				VariableLabels: []string{"var"},
			},
			f: func(t testing.TB, r *Registry, opts Opts) {
				vec, err := r.NewCounterVector(opts)
				require.NoError(t, err, "Unexpected error constructing vector.")
				_, err = vec.Get("x", "y")
				require.Error(t, err, "Expected an error getting a counter with incorrect number of labels.")
				require.Panics(t, func() { vec.MustGet("x", "y") }, "Expected panic getting a counter with incorrect number of labels.")
			},
		},
		{
			desc: "valid gauge labels",
			opts: Opts{
				Name:           "test_gauge",
				Help:           "Some help.",
				VariableLabels: []string{"var"},
			},
			f: func(t testing.TB, r *Registry, opts Opts) {
				vec, err := r.NewGaugeVector(opts)
				require.NoError(t, err, "Unexpected error constructing vector.")
				gauge, err := vec.Get("x")
				require.NoError(t, err, "Unexpected error getting a gauge with correct number of labels.")
				gauge.Inc()
				vec.MustGet("x").Store(2)
				assert.Equal(t, int64(2), gauge.Load(), "Unexpected in-memory metric value.")
			},
			wantTally: TallyExpectation{
				Type:   "gauge",
				Name:   "test_gauge",
				Labels: Labels{"var": "x"},
				Value:  2,
			},
			wantProm: "# HELP test_gauge Some help.\n" +
				"# TYPE test_gauge gauge\n" +
				`test_gauge{var="x"} 2`,
		},
		{
			desc: "invalid gauge labels",
			opts: Opts{
				Name:           "test_gauge",
				Help:           "Some help.",
				VariableLabels: []string{"var"},
			},
			f: func(t testing.TB, r *Registry, opts Opts) {
				vec, err := r.NewGaugeVector(opts)
				require.NoError(t, err, "Unexpected error constructing vector.")
				gauge, err := vec.Get("x!")
				require.NoError(t, err, "Unexpected error getting a gauge with correct number of labels.")
				gauge.Inc()
				vec.MustGet("x!").Store(2)
				assert.Equal(t, int64(2), gauge.Load(), "Unexpected in-memory metric value.")
			},
			wantTally: TallyExpectation{
				Type:   "gauge",
				Name:   "test_gauge",
				Labels: Labels{"var": "x-"},
				Value:  2,
			},
			wantProm: "# HELP test_gauge Some help.\n" +
				"# TYPE test_gauge gauge\n" +
				`test_gauge{var="x-"} 2`,
		},
		{
			desc: "wrong number of gauge labels",
			opts: Opts{
				Name:           "test_gauge",
				Help:           "Some help.",
				VariableLabels: []string{"var"},
			},
			f: func(t testing.TB, r *Registry, opts Opts) {
				vec, err := r.NewGaugeVector(opts)
				require.NoError(t, err, "Unexpected error constructing vector.")
				_, err = vec.Get("x", "y")
				require.Error(t, err, "Expected an error getting a gauge with incorrect number of labels.")
				require.Panics(t, func() { vec.MustGet("x", "y") }, "Expected panic getting a gauge with incorrect number of labels.")
			},
		},
	}

	for _, tt := range tests {
		t.Run(tt.desc, func(t *testing.T) {
			r := NewRegistry()

			scope := newTestScope()
			stop, err := r.Push(scope, _tick)
			require.NoError(t, err, "Unexpected error starting Tally push.")
			defer stop()

			tt.f(t, r, tt.opts)

			time.Sleep(10 * _tick)
			tt.wantTally.Test(t, scope)

			pallytest.AssertPrometheus(t, r, tt.wantProm)
		})
	}
}
<|endoftext|>


<commit_before>package errors

import (
	"fmt"

	"github.com/Sirupsen/logrus"
)

type Error interface {
	Status() int
	Error() string
	Code() string
	NotFound() bool
	BadRequest() bool
	Unauthorized() bool
	Forbidden() bool
	Logrus() *logrus.Entry
}

type Errors struct {
	ErrStatus  int    `json:"-"`
	ErrMessage string `json:"message"`
	ErrCode    string `json:"code,omitempty"`
}

func (e *Errors) Logrus() *logrus.Entry {
	return logrus.WithField("code", e.Code())
}

func (e *Errors) NotFound() bool {
	if e.ErrStatus == 404 {
		return true
	}

	return false
}

func (e *Errors) BadRequest() bool {
	if e.ErrStatus == 400 {
		return true
	}

	return false
}

func (e *Errors) Unauthorized() bool {
	if e.ErrStatus == 401 {
		return true
	}

	return false
}

func (e *Errors) Forbidden() bool {
	if e.ErrStatus == 403 {
		return true
	}

	return false
}

func (e *Errors) Status() int {
	return e.ErrStatus
}

func (e *Errors) Code() string {
	return e.ErrCode
}

func (e *Errors) Error() string {
	return e.ErrMessage
}

func New(message string) Error {
	return &Errors{
		ErrStatus:  500,
		ErrMessage: message,
	}
}

func NewStatus(status int, message string) Error {
	return &Errors{
		ErrStatus:  status,
		ErrMessage: message,
	}
}

func NewStatusf(status int, format string, v ...interface{}) Error {
	return &Errors{
		ErrStatus:  status,
		ErrMessage: fmt.Sprintf(format, v...),
	}
}

func Newf(format string, v ...interface{}) Error {
	return &Errors{
		ErrStatus:  500,
		ErrMessage: fmt.Sprintf(format, v...),
	}
}

func BadRequest(message string) Error {
	return &Errors{
		ErrStatus:  400,
		ErrMessage: message,
	}
}

func Unauthorized(message string) Error {
	return &Errors{
		ErrStatus:  401,
		ErrMessage: message,
	}
}

func Forbidden(message string) Error {
	return &Errors{
		ErrStatus:  403,
		ErrMessage: message,
	}
}

func NotFound(message string) Error {
	return &Errors{
		ErrStatus:  404,
		ErrMessage: message,
	}
}

func InternalError(message string) Error {
	return &Errors{
		ErrStatus:  500,
		ErrMessage: message,
	}
}

func BadRequestf(format string, v ...interface{}) Error {
	return &Errors{
		ErrStatus:  400,
		ErrMessage: fmt.Sprintf(format, v...),
	}
}

func Unauthorizedf(format string, v ...interface{}) Error {
	return &Errors{
		ErrStatus:  401,
		ErrMessage: fmt.Sprintf(format, v...),
	}
}

func Forbiddenf(format string, v ...interface{}) Error {
	return &Errors{
		ErrStatus:  403,
		ErrMessage: fmt.Sprintf(format, v...),
	}
}

func NotFoundf(format string, v ...interface{}) Error {
	return &Errors{
		ErrStatus:  404,
		ErrMessage: fmt.Sprintf(format, v...),
	}
}

func InternalErrorf(format string, v ...interface{}) Error {
	return &Errors{
		ErrStatus:  500,
		ErrMessage: fmt.Sprintf(format, v...),
	}
}

// With Code

func NewCode(code string, message string) Error {
	return &Errors{
		ErrStatus:  500,
		ErrCode:    code,
		ErrMessage: message,
	}
}

func NewStatusCode(status int, code, message string) Error {
	return &Errors{
		ErrStatus:  500,
		ErrCode:    code,
		ErrMessage: message,
	}
}

func NewStatusCodef(status int, code, format string, v ...interface{}) Error {
	return &Errors{
		ErrStatus:  status,
		ErrCode:    code,
		ErrMessage: fmt.Sprintf(format, v...),
	}
}

func NewCodef(code, format string, v ...interface{}) Error {
	return &Errors{
		ErrStatus:  500,
		ErrCode:    code,
		ErrMessage: fmt.Sprintf(format, v...),
	}
}

func BadRequestCode(code, message string) Error {
	return &Errors{
		ErrStatus:  400,
		ErrCode:    code,
		ErrMessage: message,
	}
}

func UnauthorizedCode(code, message string) Error {
	return &Errors{
		ErrStatus:  401,
		ErrCode:    code,
		ErrMessage: message,
	}
}

func ForbiddenCode(code, message string) Error {
	return &Errors{
		ErrStatus:  403,
		ErrCode:    code,
		ErrMessage: message,
	}
}

func NotFoundCode(code, message string) Error {
	return &Errors{
		ErrStatus:  404,
		ErrCode:    code,
		ErrMessage: message,
	}
}

func InternalErrorCode(code, message string) Error {
	return &Errors{
		ErrStatus:  500,
		ErrCode:    code,
		ErrMessage: message,
	}
}

func BadRequestCodef(code, format string, v ...interface{}) Error {
	return &Errors{
		ErrStatus:  400,
		ErrCode:    code,
		ErrMessage: fmt.Sprintf(format, v...),
	}
}

func UnauthorizedCodef(code, format string, v ...interface{}) Error {
	return &Errors{
		ErrStatus:  401,
		ErrCode:    code,
		ErrMessage: fmt.Sprintf(format, v...),
	}
}

func ForbiddenCodef(code, format string, v ...interface{}) Error {
	return &Errors{
		ErrStatus:  403,
		ErrCode:    code,
		ErrMessage: fmt.Sprintf(format, v...),
	}
}

func NotFoundCodef(code, format string, v ...interface{}) Error {
	return &Errors{
		ErrStatus:  404,
		ErrCode:    code,
		ErrMessage: fmt.Sprintf(format, v...),
	}
}

func InternalErrorCodef(code, format string, v ...interface{}) Error {
	return &Errors{
		ErrStatus:  500,
		ErrCode:    code,
		ErrMessage: fmt.Sprintf(format, v...),
	}
}

func IsNotFound(err error) bool {
	if cerr, ok := err.(Error); ok && cerr.Status() == 404 {
		return true
	}

	return false
}
<commit_msg>add logrus<commit_after>package errors

import (
	"fmt"

	"github.com/Sirupsen/logrus"
)

type Error interface {
	Status() int
	Error() string
	Code() string
	NotFound() bool
	BadRequest() bool
	Unauthorized() bool
	Forbidden() bool
	LogrusFields() logrus.Fields
}

type Errors struct {
	ErrStatus  int    `json:"-"`
	ErrMessage string `json:"message"`
	ErrCode    string `json:"code,omitempty"`
}

func (e *Errors) LogrusFields() logrus.Fields {
	return logrus.Fields{
		"code":   e.Code(),
		"status": e.Status(),
	}
}

func (e *Errors) NotFound() bool {
	if e.ErrStatus == 404 {
		return true
	}

	return false
}

func (e *Errors) BadRequest() bool {
	if e.ErrStatus == 400 {
		return true
	}

	return false
}

func (e *Errors) Unauthorized() bool {
	if e.ErrStatus == 401 {
		return true
	}

	return false
}

func (e *Errors) Forbidden() bool {
	if e.ErrStatus == 403 {
		return true
	}

	return false
}

func (e *Errors) Status() int {
	return e.ErrStatus
}

func (e *Errors) Code() string {
	return e.ErrCode
}

func (e *Errors) Error() string {
	return e.ErrMessage
}

func New(message string) Error {
	return &Errors{
		ErrStatus:  500,
		ErrMessage: message,
	}
}

func NewStatus(status int, message string) Error {
	return &Errors{
		ErrStatus:  status,
		ErrMessage: message,
	}
}

func NewStatusf(status int, format string, v ...interface{}) Error {
	return &Errors{
		ErrStatus:  status,
		ErrMessage: fmt.Sprintf(format, v...),
	}
}

func Newf(format string, v ...interface{}) Error {
	return &Errors{
		ErrStatus:  500,
		ErrMessage: fmt.Sprintf(format, v...),
	}
}

func BadRequest(message string) Error {
	return &Errors{
		ErrStatus:  400,
		ErrMessage: message,
	}
}

func Unauthorized(message string) Error {
	return &Errors{
		ErrStatus:  401,
		ErrMessage: message,
	}
}

func Forbidden(message string) Error {
	return &Errors{
		ErrStatus:  403,
		ErrMessage: message,
	}
}

func NotFound(message string) Error {
	return &Errors{
		ErrStatus:  404,
		ErrMessage: message,
	}
}

func InternalError(message string) Error {
	return &Errors{
		ErrStatus:  500,
		ErrMessage: message,
	}
}

func BadRequestf(format string, v ...interface{}) Error {
	return &Errors{
		ErrStatus:  400,
		ErrMessage: fmt.Sprintf(format, v...),
	}
}

func Unauthorizedf(format string, v ...interface{}) Error {
	return &Errors{
		ErrStatus:  401,
		ErrMessage: fmt.Sprintf(format, v...),
	}
}

func Forbiddenf(format string, v ...interface{}) Error {
	return &Errors{
		ErrStatus:  403,
		ErrMessage: fmt.Sprintf(format, v...),
	}
}

func NotFoundf(format string, v ...interface{}) Error {
	return &Errors{
		ErrStatus:  404,
		ErrMessage: fmt.Sprintf(format, v...),
	}
}

func InternalErrorf(format string, v ...interface{}) Error {
	return &Errors{
		ErrStatus:  500,
		ErrMessage: fmt.Sprintf(format, v...),
	}
}

// With Code

func NewCode(code string, message string) Error {
	return &Errors{
		ErrStatus:  500,
		ErrCode:    code,
		ErrMessage: message,
	}
}

func NewStatusCode(status int, code, message string) Error {
	return &Errors{
		ErrStatus:  500,
		ErrCode:    code,
		ErrMessage: message,
	}
}

func NewStatusCodef(status int, code, format string, v ...interface{}) Error {
	return &Errors{
		ErrStatus:  status,
		ErrCode:    code,
		ErrMessage: fmt.Sprintf(format, v...),
	}
}

func NewCodef(code, format string, v ...interface{}) Error {
	return &Errors{
		ErrStatus:  500,
		ErrCode:    code,
		ErrMessage: fmt.Sprintf(format, v...),
	}
}

func BadRequestCode(code, message string) Error {
	return &Errors{
		ErrStatus:  400,
		ErrCode:    code,
		ErrMessage: message,
	}
}

func UnauthorizedCode(code, message string) Error {
	return &Errors{
		ErrStatus:  401,
		ErrCode:    code,
		ErrMessage: message,
	}
}

func ForbiddenCode(code, message string) Error {
	return &Errors{
		ErrStatus:  403,
		ErrCode:    code,
		ErrMessage: message,
	}
}

func NotFoundCode(code, message string) Error {
	return &Errors{
		ErrStatus:  404,
		ErrCode:    code,
		ErrMessage: message,
	}
}

func InternalErrorCode(code, message string) Error {
	return &Errors{
		ErrStatus:  500,
		ErrCode:    code,
		ErrMessage: message,
	}
}

func BadRequestCodef(code, format string, v ...interface{}) Error {
	return &Errors{
		ErrStatus:  400,
		ErrCode:    code,
		ErrMessage: fmt.Sprintf(format, v...),
	}
}

func UnauthorizedCodef(code, format string, v ...interface{}) Error {
	return &Errors{
		ErrStatus:  401,
		ErrCode:    code,
		ErrMessage: fmt.Sprintf(format, v...),
	}
}

func ForbiddenCodef(code, format string, v ...interface{}) Error {
	return &Errors{
		ErrStatus:  403,
		ErrCode:    code,
		ErrMessage: fmt.Sprintf(format, v...),
	}
}

func NotFoundCodef(code, format string, v ...interface{}) Error {
	return &Errors{
		ErrStatus:  404,
		ErrCode:    code,
		ErrMessage: fmt.Sprintf(format, v...),
	}
}

func InternalErrorCodef(code, format string, v ...interface{}) Error {
	return &Errors{
		ErrStatus:  500,
		ErrCode:    code,
		ErrMessage: fmt.Sprintf(format, v...),
	}
}

func IsNotFound(err error) bool {
	if cerr, ok := err.(Error); ok && cerr.Status() == 404 {
		return true
	}

	return false
}
<|endoftext|>


<commit_before>package requests

import "bytes"

// InputErrors is an error type that maps input names to errors
// encountered while parsing their value.  A nil error will be stored
// for any input names that were parsed successfully.
type InputErrors map[string]error

// Error returns the InputError's full error string.
func (errs InputErrors) Error() string {
	buff := bytes.NewBufferString("Input errors:\n\n")
	for name, err := range errs {
		if err != nil {
			buff.WriteString(" * ")
			buff.WriteString(name)
			buff.WriteString(": ")
			buff.WriteString(err.Error())
			buff.WriteString("\n")
		}
	}
	return buff.String()
}

// Set takes an input and an error, and sets the error to the input if
// the error is non-nil.  The return value will be true if err is
// non-nil, false otherwise.
func (errs InputErrors) Set(input string, err error) bool {
	errs[input] = err
	return err == nil
}

func (errs InputErrors) Merge(newErrs InputErrors) InputErrors {
	for input, err := range newErrs {
		errs[input] = err
	}
	return errs
}

func (errs InputErrors) HasErrors() bool {
	for _, err := range errs {
		if err != nil {
			return true
		}
	}
	return false
}
<commit_msg>A few minor updates to InputErrors<commit_after>package requests

import "bytes"

// InputErrors is an error type that maps input names to errors
// encountered while parsing their value.  A nil error will be stored
// for any input names that were parsed successfully.
type InputErrors map[string]error

// Error returns the InputError's full error string.
func (errs InputErrors) Error() string {
	buff := bytes.NewBufferString("Input errors:\n\n")
	for name, err := range errs {
		if err != nil {
			buff.WriteString(" * ")
			buff.WriteString(name)
			buff.WriteString(": ")
			buff.WriteString(err.Error())
			buff.WriteString("\n")
		}
	}
	return buff.String()
}

// Set takes an input and an error, and sets the error to the input if
// the error is non-nil.  The return value will be true if err is
// non-nil, false otherwise.
func (errs InputErrors) Set(input string, err error) bool {
	errs[input] = err
	return err == nil
}

// Merge merges all keys and values from newErrs into errs.  Any
// values in newErrs that are also in errs will overwrite the values
// in errs.
func (errs InputErrors) Merge(newErrs InputErrors) InputErrors {
	for input, err := range newErrs {
		errs[input] = err
	}
	return errs
}

// HasErrors returns whether or not any of the errors in errs are
// non-nil.
func (errs InputErrors) HasErrors() bool {
	for _, err := range errs {
		if err != nil {
			return true
		}
	}
	return false
}

// Errors returns a map of all input names that have a non-nil error
// value.  Any input that has a nil error value will not be included
// in the return value.
func (errs InputErrors) Errors() map[string]error {
	errors := make(map[string]error)
	for input, err := range errs {
		if err != nil {
			errors[input] = err
		}
	}
	return errors
}
<|endoftext|>


<commit_before>package mnemosyned

import "strconv"

func address(host string, port int) string {
	return host + ":" + strconv.FormatInt(int64(port), 10)
}
<commit_msg>helpers removed<commit_after><|endoftext|>


<commit_before>package models

import (
	"errors"
	"time"

	"github.com/jinzhu/gorm"
	"github.com/koding/bongo"
)

type ChannelMessageList struct {
	// unique identifier of the channel message list
	Id int64 `json:"id"`

	// Id of the channel
	ChannelId int64 `json:"channelId"     sql:"NOT NULL"`

	// Id of the message
	MessageId int64 `json:"messageId"     sql:"NOT NULL"`

	// Addition date of the message to the channel
	AddedAt time.Time `json:"addedAt"     sql:"NOT NULL"`
}

func (c *ChannelMessageList) BeforeCreate() {
	c.AddedAt = time.Now()
}

func (c *ChannelMessageList) BeforeUpdate() {
	c.AddedAt = time.Now()
}

func (c *ChannelMessageList) AfterCreate() {
	bongo.B.AfterCreate(c)
}

func (c *ChannelMessageList) AfterUpdate() {
	bongo.B.AfterUpdate(c)
}

func (c *ChannelMessageList) AfterDelete() {
	bongo.B.AfterDelete(c)
}

func (c *ChannelMessageList) GetId() int64 {
	return c.Id
}

func (c *ChannelMessageList) TableName() string {
	return "channel_message_list"
}

func NewChannelMessageList() *ChannelMessageList {
	return &ChannelMessageList{}
}

func (c *ChannelMessageList) Fetch() error {
	return bongo.B.Fetch(c)
}

func (c *ChannelMessageList) One(q *bongo.Query) error {
	return bongo.B.One(c, c, q)
}

func (c *ChannelMessageList) UnreadCount(cp *ChannelParticipant) (int, error) {
	if cp.ChannelId == 0 {
		return 0, errors.New("ChannelId is not set")
	}

	if cp.AccountId == 0 {
		return 0, errors.New("AccountId is not set")
	}

	if cp.LastSeenAt.IsZero() {
		return 0, errors.New("Last seen at date is not valid - it is zero")
	}

	return bongo.B.Count(c,
		"channel_id = ? and added_at > ?",
		cp.ChannelId,
		// todo change this format to get from a specific place
		cp.LastSeenAt.UTC().Format(time.RFC822Z),
	)
}

func (c *ChannelMessageList) Create() error {
	return bongo.B.Create(c)
}

func (c *ChannelMessageList) Delete() error {
	return bongo.B.Delete(c)
}

func (c *ChannelMessageList) List(q *Query) (*HistoryResponse, error) {
	messageList, err := c.getMessages(q)
	if err != nil {
		return nil, err
	}

	hr := NewHistoryResponse()
	hr.MessageList = messageList

	unreadCount := 0
	cp := NewChannelParticipant()
	cp.ChannelId = c.ChannelId
	cp.AccountId = q.AccountId
	err = cp.FetchParticipant()
	// we are forcing unread count to 0 if user is not a participant
	// of the channel
	if err != nil && err != gorm.RecordNotFound {
		return nil, err
	}

	if err == nil {
		unreadCount, err = c.UnreadCount(cp)
		if err != nil {
			return nil, err
		}
	}

	hr.UnreadCount = unreadCount
	return hr, nil
}

func (c *ChannelMessageList) getMessages(q *Query) ([]*ChannelMessageContainer, error) {
	var messages []int64

	if c.ChannelId == 0 {
		return nil, errors.New("ChannelId is not set")
	}

	if err := bongo.B.DB.Table(c.TableName()).
		Order("added_at desc").
		Where("channel_id = ?", c.ChannelId).
		Offset(q.Skip).
		Limit(q.Limit).
		Pluck("message_id", &messages).
		Error; err != nil {
		return nil, err
	}

	parent := NewChannelMessage()
	channelMessages, err := parent.FetchByIds(messages)
	if err != nil {
		return nil, err
	}

	populatedChannelMessages, err := c.populateChannelMessages(channelMessages)
	if err != nil {
		return nil, err
	}

	return populatedChannelMessages, nil
}

func (c *ChannelMessageList) populateChannelMessages(channelMessages []ChannelMessage) ([]*ChannelMessageContainer, error) {
	channelMessageCount := len(channelMessages)

	populatedChannelMessages := make([]*ChannelMessageContainer, channelMessageCount)

	if channelMessageCount == 0 {
		return populatedChannelMessages, nil
	}

	for i := 0; i < channelMessageCount; i++ {
		cm := channelMessages[i]
		cmc, err := cm.FetchRelatives()
		if err != nil {
			return nil, err
		}

		populatedChannelMessages[i] = cmc

		mr := NewMessageReply()
		mr.MessageId = cm.Id
		replies, err := mr.List()
		if err != nil {
			return nil, err
		}

		populatedChannelMessagesReplies := make([]*ChannelMessageContainer, len(replies))

		for rl := 0; rl < len(replies); rl++ {
			cmrc, err := replies[rl].FetchRelatives()
			if err != nil {
				return nil, err
			}
			populatedChannelMessagesReplies[rl] = cmrc
		}
		populatedChannelMessages[i].Replies = populatedChannelMessagesReplies

	}
	return populatedChannelMessages, nil

}

func (c *ChannelMessageList) FetchMessageChannels(messageId int64) ([]Channel, error) {
	var channelIds []int64

	q := &bongo.Query{
		Selector: map[string]interface{}{
			"message_id": messageId,
		},
		Pluck: "channel_id",
	}

	err := bongo.B.Some(c, &channelIds, q)
	if err != nil {
		return nil, err
	}

	return NewChannel().FetchByIds(channelIds)
}

// seperate this fucntion into modelhelper
// as setting it to a variadic function
func (c *ChannelMessageList) DeleteMessagesBySelector(selector map[string]interface{}) error {
	var cmls []ChannelMessageList

	err := bongo.B.Some(c, &cmls, &bongo.Query{Selector: selector})
	if err != nil {
		return err
	}

	for _, cml := range cmls {
		if err := cml.Delete(); err != nil {
			return err
		}
	}
	return nil
}
<commit_msg>Social: add schema to table<commit_after>package models

import (
	"errors"
	"time"

	"github.com/jinzhu/gorm"
	"github.com/koding/bongo"
)

type ChannelMessageList struct {
	// unique identifier of the channel message list
	Id int64 `json:"id"`

	// Id of the channel
	ChannelId int64 `json:"channelId"     sql:"NOT NULL"`

	// Id of the message
	MessageId int64 `json:"messageId"     sql:"NOT NULL"`

	// Addition date of the message to the channel
	AddedAt time.Time `json:"addedAt"     sql:"NOT NULL"`
}

func (c *ChannelMessageList) BeforeCreate() {
	c.AddedAt = time.Now()
}

func (c *ChannelMessageList) BeforeUpdate() {
	c.AddedAt = time.Now()
}

func (c *ChannelMessageList) AfterCreate() {
	bongo.B.AfterCreate(c)
}

func (c *ChannelMessageList) AfterUpdate() {
	bongo.B.AfterUpdate(c)
}

func (c *ChannelMessageList) AfterDelete() {
	bongo.B.AfterDelete(c)
}

func (c *ChannelMessageList) GetId() int64 {
	return c.Id
}

func (c ChannelMessageList) TableName() string {
	return "api.channel_message_list"
}

func NewChannelMessageList() *ChannelMessageList {
	return &ChannelMessageList{}
}

func (c *ChannelMessageList) Fetch() error {
	return bongo.B.Fetch(c)
}

func (c *ChannelMessageList) One(q *bongo.Query) error {
	return bongo.B.One(c, c, q)
}

func (c *ChannelMessageList) UnreadCount(cp *ChannelParticipant) (int, error) {
	if cp.ChannelId == 0 {
		return 0, errors.New("ChannelId is not set")
	}

	if cp.AccountId == 0 {
		return 0, errors.New("AccountId is not set")
	}

	if cp.LastSeenAt.IsZero() {
		return 0, errors.New("Last seen at date is not valid - it is zero")
	}

	return bongo.B.Count(c,
		"channel_id = ? and added_at > ?",
		cp.ChannelId,
		// todo change this format to get from a specific place
		cp.LastSeenAt.UTC().Format(time.RFC822Z),
	)
}

func (c *ChannelMessageList) Create() error {
	return bongo.B.Create(c)
}

func (c *ChannelMessageList) Delete() error {
	return bongo.B.Delete(c)
}

func (c *ChannelMessageList) List(q *Query) (*HistoryResponse, error) {
	messageList, err := c.getMessages(q)
	if err != nil {
		return nil, err
	}

	hr := NewHistoryResponse()
	hr.MessageList = messageList

	unreadCount := 0
	cp := NewChannelParticipant()
	cp.ChannelId = c.ChannelId
	cp.AccountId = q.AccountId
	err = cp.FetchParticipant()
	// we are forcing unread count to 0 if user is not a participant
	// of the channel
	if err != nil && err != gorm.RecordNotFound {
		return nil, err
	}

	if err == nil {
		unreadCount, err = c.UnreadCount(cp)
		if err != nil {
			return nil, err
		}
	}

	hr.UnreadCount = unreadCount
	return hr, nil
}

func (c *ChannelMessageList) getMessages(q *Query) ([]*ChannelMessageContainer, error) {
	var messages []int64

	if c.ChannelId == 0 {
		return nil, errors.New("ChannelId is not set")
	}

	if err := bongo.B.DB.Table(c.TableName()).
		Order("added_at desc").
		Where("channel_id = ?", c.ChannelId).
		Offset(q.Skip).
		Limit(q.Limit).
		Pluck("message_id", &messages).
		Error; err != nil {
		return nil, err
	}

	parent := NewChannelMessage()
	channelMessages, err := parent.FetchByIds(messages)
	if err != nil {
		return nil, err
	}

	populatedChannelMessages, err := c.populateChannelMessages(channelMessages)
	if err != nil {
		return nil, err
	}

	return populatedChannelMessages, nil
}

func (c *ChannelMessageList) populateChannelMessages(channelMessages []ChannelMessage) ([]*ChannelMessageContainer, error) {
	channelMessageCount := len(channelMessages)

	populatedChannelMessages := make([]*ChannelMessageContainer, channelMessageCount)

	if channelMessageCount == 0 {
		return populatedChannelMessages, nil
	}

	for i := 0; i < channelMessageCount; i++ {
		cm := channelMessages[i]
		cmc, err := cm.FetchRelatives()
		if err != nil {
			return nil, err
		}

		populatedChannelMessages[i] = cmc

		mr := NewMessageReply()
		mr.MessageId = cm.Id
		replies, err := mr.List()
		if err != nil {
			return nil, err
		}

		populatedChannelMessagesReplies := make([]*ChannelMessageContainer, len(replies))

		for rl := 0; rl < len(replies); rl++ {
			cmrc, err := replies[rl].FetchRelatives()
			if err != nil {
				return nil, err
			}
			populatedChannelMessagesReplies[rl] = cmrc
		}
		populatedChannelMessages[i].Replies = populatedChannelMessagesReplies

	}
	return populatedChannelMessages, nil

}

func (c *ChannelMessageList) FetchMessageChannels(messageId int64) ([]Channel, error) {
	var channelIds []int64

	q := &bongo.Query{
		Selector: map[string]interface{}{
			"message_id": messageId,
		},
		Pluck: "channel_id",
	}

	err := bongo.B.Some(c, &channelIds, q)
	if err != nil {
		return nil, err
	}

	return NewChannel().FetchByIds(channelIds)
}

// seperate this fucntion into modelhelper
// as setting it to a variadic function
func (c *ChannelMessageList) DeleteMessagesBySelector(selector map[string]interface{}) error {
	var cmls []ChannelMessageList

	err := bongo.B.Some(c, &cmls, &bongo.Query{Selector: selector})
	if err != nil {
		return err
	}

	for _, cml := range cmls {
		if err := cml.Delete(); err != nil {
			return err
		}
	}
	return nil
}
<|endoftext|>


<commit_before>package eval

import (
	"fmt"
	"math/big"
)

// BigComplex behaves like a *big.Re, but has an imaginary component
// and separate implementation for + - * /
type BigComplex struct {
	Re big.Rat
	Im big.Rat
}

func (z *BigComplex) Add(x, y *BigComplex) *BigComplex {
	z.Re.Add(&x.Re, &y.Re)
	z.Im.Add(&x.Im, &y.Im)
	return z
}

func (z *BigComplex) Sub(x, y *BigComplex) *BigComplex {
	z.Re.Sub(&x.Re, &y.Re)
	z.Im.Sub(&x.Im, &y.Im)
	return z
}

func (z *BigComplex) Mul(x, y *BigComplex) *BigComplex {
	re := new(big.Rat).Mul(&x.Re, &y.Re)
	re.Sub(re, new(big.Rat).Mul(&x.Im, &y.Im))

	im := new(big.Rat).Mul(&x.Re, &y.Im)
	im.Add(im, new(big.Rat).Mul(&x.Im, &y.Re))

	z.Re = *re
	z.Im = *im
	return z
}

func (z *BigComplex) Quo(x, y *BigComplex) *BigComplex {
	// a+bi   ac+bd   bc-ad
	// ---- = ----- + ----- i
	// c+di   cc+dd   cc+dd

	cc := new(big.Rat).Mul(&y.Re, &y.Re)
	dd := new(big.Rat).Mul(&y.Im, &y.Im)
	ccdd := new(big.Rat).Add(cc, dd)

	ac := new(big.Rat).Mul(&x.Re, &y.Re)
	ad := new(big.Rat).Mul(&x.Re, &y.Im)
	bc := new(big.Rat).Mul(&x.Im, &y.Re)
	bd := new(big.Rat).Mul(&x.Im, &y.Im)

	z.Re.Add(ac, bd)
	z.Re.Quo(&z.Re, ccdd)

	z.Im.Sub(bc, ad)
	z.Im.Quo(&z.Im, ccdd)

	return z
}

func (z *BigComplex) IsZero() bool {
	return z.Re.Num().BitLen() == 0 && z.Im.Num().BitLen() == 0
}

// z.Int() returns a representation of z, truncated to be an int of
// length bits.  Valid values for bits are 8, 16, 32, 64. Result is
// otherwise undefined If a truncation occurs, the decimal part is
// dropped and the conversion continues as usual. truncation will be
// true If an overflow occurs, the result is equivelant to a cast of
// the form int32(x). overflow will be true.
func (z *BigComplex) Int(bits int) (_ int64, truncation, overflow bool) {
	var integer *BigComplex
	integer, truncation = z.Integer()
	res := new(big.Int).Set(integer.Re.Num())

	// Numerator must fit in bits - 1, with 1 bit left for sign
	if overflow = res.BitLen() > bits - 1; overflow {
		var mask uint64 = ^uint64(0) >> uint(64 - bits)
		res.And(res, new(big.Int).SetUint64(mask))
	}
	return res.Int64(), truncation, overflow
}

// z.Uint() returns a representation of z truncated to be a uint of
// length bits.  Valid values for bits are 0, 8, 16, 32, 64. The
// returned result is otherwise undefined. If a truncation occurs, the
// decimal part is dropped and the conversion continues as
// usual. Return values truncation and overflow will be true if an
// overflow occurs. The result is equivelant to a cast of the form
// uint32(x).
func (z *BigComplex) Uint(bits int) (_ uint64, truncation, overflow bool) {
	var integer *BigComplex
	integer, truncation = z.Integer()
	res := new(big.Int).Set(integer.Re.Num())

	var mask uint64 = ^uint64(0) >> uint(64 - bits)
	if overflow = res.BitLen() > bits; overflow {
		res.And(res, new(big.Int).SetUint64(mask))
		res = new(big.Int).And(res, new(big.Int).SetUint64(mask))
	}

	r := res.Uint64()
	if res.Sign() < 0 {
		overflow = true
		r = (^r + 1) & mask
	}
	return r, truncation, overflow
}

// z.Float64() returns a representation of z truncated to a float64 If
// a truncation from a complex occurs. The imaginary part is dropped
// and the conversion continues as usual. return value truncation will
// be true exact will be true if the conversion was completed without
// loss of precision.
func (z *BigComplex) Float64() (f float64, truncation, exact bool) {
	f, exact = z.Re.Float64()
	return f, !z.IsReal(), exact
}

// z.Complex128() returns a complex128 representation of z. Return value
// exact will be true if the conversion was completed without loss of
// precision.
func (z *BigComplex) Complex128() (_ complex128, exact bool) {
	r, re := z.Re.Float64()
	i, ie := z.Im.Float64()
	return complex(r, i), re && ie
}

// z.Integer() returns a representation of z, a *BigComplex, truncated
// to be a integer value. The second return value is true if a
// truncation occured in the real component.
func (z *BigComplex) Integer() (_ *BigComplex, truncation bool) {
	if z.IsInteger() {
		return z, false
	} else if z.Re.IsInt() {
		re := new(BigComplex)
		re.Re.Set(&z.Re)
		return re, false
	} else {
		trunc := new(BigComplex)
		trunc.Re.SetInt(z.Re.Num())
		trunc.Re.Num().Div(trunc.Re.Num(), z.Re.Denom())
		return trunc, true
	}
}

// z.Real() returns a representation of z, truncated to a real
// value. The second return valuie is true if a truncation occured.
func (z *BigComplex) Real() (_ *BigComplex, truncation bool) {
	if z.IsReal() {
		return z, false
	} else {
		return &BigComplex{Re: z.Re}, true
	}
}

func (z *BigComplex) IsInteger() bool {
	return z.Re.IsInt() && z.Im.Num().BitLen() == 0
}

func (z *BigComplex) IsReal() bool {
	return z.Im.Num().BitLen() == 0
}

func (z *BigComplex) Equals(other *BigComplex) bool {
	return new(BigComplex).Sub(z, other).IsZero()
}

func (z *BigComplex) String() string {
	return z.StringShow0i(true)
}

func (z *BigComplex) StringShow0i(show0i bool) string {
	var s string
	if z.Re.Num().BitLen() != 0 || show0i {
		if z.Re.IsInt() {
			s += z.Re.Num().String()
		} else {
			f, _ := z.Re.Float64()
			s += fmt.Sprintf("%.5g", f)
		}
	}
	if !z.IsReal() || show0i {
		if s != "" {
			s += "+"
		}
		if z.Im.IsInt() {
			s += z.Im.Num().String()
		} else {
			f, _ := z.Im.Float64()
			s += fmt.Sprintf("%.5g", f)
		}
		s += "i"
	}
	if s == "" {
		s = "0"
	}
	return s
}
<commit_msg>Fix -0x7fff... being detected as an underflow.<commit_after>package eval

import (
	"fmt"
	"math/big"
)

// BigComplex behaves like a *big.Re, but has an imaginary component
// and separate implementation for + - * /
type BigComplex struct {
	Re big.Rat
	Im big.Rat
}

func (z *BigComplex) Add(x, y *BigComplex) *BigComplex {
	z.Re.Add(&x.Re, &y.Re)
	z.Im.Add(&x.Im, &y.Im)
	return z
}

func (z *BigComplex) Sub(x, y *BigComplex) *BigComplex {
	z.Re.Sub(&x.Re, &y.Re)
	z.Im.Sub(&x.Im, &y.Im)
	return z
}

func (z *BigComplex) Mul(x, y *BigComplex) *BigComplex {
	re := new(big.Rat).Mul(&x.Re, &y.Re)
	re.Sub(re, new(big.Rat).Mul(&x.Im, &y.Im))

	im := new(big.Rat).Mul(&x.Re, &y.Im)
	im.Add(im, new(big.Rat).Mul(&x.Im, &y.Re))

	z.Re = *re
	z.Im = *im
	return z
}

func (z *BigComplex) Quo(x, y *BigComplex) *BigComplex {
	// a+bi   ac+bd   bc-ad
	// ---- = ----- + ----- i
	// c+di   cc+dd   cc+dd

	cc := new(big.Rat).Mul(&y.Re, &y.Re)
	dd := new(big.Rat).Mul(&y.Im, &y.Im)
	ccdd := new(big.Rat).Add(cc, dd)

	ac := new(big.Rat).Mul(&x.Re, &y.Re)
	ad := new(big.Rat).Mul(&x.Re, &y.Im)
	bc := new(big.Rat).Mul(&x.Im, &y.Re)
	bd := new(big.Rat).Mul(&x.Im, &y.Im)

	z.Re.Add(ac, bd)
	z.Re.Quo(&z.Re, ccdd)

	z.Im.Sub(bc, ad)
	z.Im.Quo(&z.Im, ccdd)

	return z
}

func (z *BigComplex) IsZero() bool {
	return z.Re.Num().BitLen() == 0 && z.Im.Num().BitLen() == 0
}

// z.Int() returns a representation of z, truncated to be an int of
// length bits.  Valid values for bits are 8, 16, 32, 64. Result is
// otherwise undefined If a truncation occurs, the decimal part is
// dropped and the conversion continues as usual. truncation will be
// true If an overflow occurs, the result is equivelant to a cast of
// the form int32(x). overflow will be true.
func (z *BigComplex) Int(bits int) (_ int64, truncation, overflow bool) {
	var integer *BigComplex
	integer, truncation = z.Integer()
	res := new(big.Int).Set(integer.Re.Num())

	// Numerator must fit in bits - 1, with 1 bit left for sign.
        // An exceptional case when only the signed bit is set.
	if overflow = res.BitLen() > bits - 1; overflow {
		var mask uint64 = ^uint64(0) >> uint(64 - bits)
                if res.BitLen() == bits && res.Sign() < 0 {
                        // To detect the edge of minus 0b1000..., add one
                        // to get 0b0ff... and recount the bits
                        plus1 := new(big.Int).Add(res, big.NewInt(1))
                        if plus1.BitLen() < bits {
	                        return res.Int64(), truncation, false
                        }
                }
		res.And(res, new(big.Int).SetUint64(mask))
	}
	return res.Int64(), truncation, overflow
}

// z.Uint() returns a representation of z truncated to be a uint of
// length bits.  Valid values for bits are 0, 8, 16, 32, 64. The
// returned result is otherwise undefined. If a truncation occurs, the
// decimal part is dropped and the conversion continues as
// usual. Return values truncation and overflow will be true if an
// overflow occurs. The result is equivelant to a cast of the form
// uint32(x).
func (z *BigComplex) Uint(bits int) (_ uint64, truncation, overflow bool) {
	var integer *BigComplex
	integer, truncation = z.Integer()
	res := new(big.Int).Set(integer.Re.Num())

	var mask uint64 = ^uint64(0) >> uint(64 - bits)
	if overflow = res.BitLen() > bits; overflow {
		res.And(res, new(big.Int).SetUint64(mask))
		res = new(big.Int).And(res, new(big.Int).SetUint64(mask))
	}

	r := res.Uint64()
	if res.Sign() < 0 {
		overflow = true
		r = (^r + 1) & mask
	}
	return r, truncation, overflow
}

// z.Float64() returns a representation of z truncated to a float64 If
// a truncation from a complex occurs. The imaginary part is dropped
// and the conversion continues as usual. return value truncation will
// be true exact will be true if the conversion was completed without
// loss of precision.
func (z *BigComplex) Float64() (f float64, truncation, exact bool) {
	f, exact = z.Re.Float64()
	return f, !z.IsReal(), exact
}

// z.Complex128() returns a complex128 representation of z. Return value
// exact will be true if the conversion was completed without loss of
// precision.
func (z *BigComplex) Complex128() (_ complex128, exact bool) {
	r, re := z.Re.Float64()
	i, ie := z.Im.Float64()
	return complex(r, i), re && ie
}

// z.Integer() returns a representation of z, a *BigComplex, truncated
// to be a integer value. The second return value is true if a
// truncation occured in the real component.
func (z *BigComplex) Integer() (_ *BigComplex, truncation bool) {
	if z.IsInteger() {
		return z, false
	} else if z.Re.IsInt() {
		re := new(BigComplex)
		re.Re.Set(&z.Re)
		return re, false
	} else {
		trunc := new(BigComplex)
		trunc.Re.SetInt(z.Re.Num())
		trunc.Re.Num().Div(trunc.Re.Num(), z.Re.Denom())
		return trunc, true
	}
}

// z.Real() returns a representation of z, truncated to a real
// value. The second return valuie is true if a truncation occured.
func (z *BigComplex) Real() (_ *BigComplex, truncation bool) {
	if z.IsReal() {
		return z, false
	} else {
		return &BigComplex{Re: z.Re}, true
	}
}

func (z *BigComplex) IsInteger() bool {
	return z.Re.IsInt() && z.Im.Num().BitLen() == 0
}

func (z *BigComplex) IsReal() bool {
	return z.Im.Num().BitLen() == 0
}

func (z *BigComplex) Equals(other *BigComplex) bool {
	return new(BigComplex).Sub(z, other).IsZero()
}

func (z *BigComplex) String() string {
	return z.StringShow0i(true)
}

func (z *BigComplex) StringShow0i(show0i bool) string {
	var s string
	if z.Re.Num().BitLen() != 0 || show0i {
		if z.Re.IsInt() {
			s += z.Re.Num().String()
		} else {
			f, _ := z.Re.Float64()
			s += fmt.Sprintf("%.5g", f)
		}
	}
	if !z.IsReal() || show0i {
		if s != "" {
			s += "+"
		}
		if z.Im.IsInt() {
			s += z.Im.Num().String()
		} else {
			f, _ := z.Im.Float64()
			s += fmt.Sprintf("%.5g", f)
		}
		s += "i"
	}
	if s == "" {
		s = "0"
	}
	return s
}
<|endoftext|>


<commit_before>package sqlpaxos

import "net"
import "fmt"
import "net/rpc"
import "log"
import "time"
import "paxos"
import "sync"
import "os"
import "syscall"
import "encoding/gob"
import "math/rand"
import "strconv"
import "math"
import "barista"
import "encoding/json"
import "logger"
import "db"

const Debug=0

func DPrintf(format string, a ...interface{}) (n int, err error) {
        if Debug > 0 {
                log.Printf(format, a...)
        }
        return
}

type LastSeen struct {
  RequestId int
  Reply interface{}
}

type SQLPaxos struct {
  mu sync.Mutex
  l net.Listener
  me int
  dead bool // for testing
  unreliable bool // for testing
  px *paxos.Paxos

  // Your definitions here.
  ops map[int]Op // log of operations
  replies map[int]interface{} // the replies for this sequence number
  done map[int]bool // true if we can delete the data for this sequence number
  data map[string]string // the database
  lastSeen map[int64]LastSeen // the last request/reply for this client
  connections map[int64]*db.DBManager // connections per client. Limited to a single connection per client
  next int // the next sequence number to be executed
  logger *logger.Logger // logger to write paxos log to file
}

func (sp *SQLPaxos) execute(op Op) interface{} {

  testing := true
  if testing {
    args := op.Args
    reply := ExecReply{}

    // @TODO remove this
    if op.NoOp {
       return reply
    }

    // @TODO remove get & put
    key := args.(ExecArgs).Key
    if args.(ExecArgs).Type == Put {
       // execute the put

       prevValue, ok := sp.data[key]
       if ok {
          reply.Value = prevValue
       } else {
          reply.Value = ""
       }

       if args.(ExecArgs).DoHash {
          sp.data[key] = strconv.Itoa(int(hash(reply.Value + args.(ExecArgs).Value)))
       } else {
          sp.data[key] = args.(ExecArgs).Value
       }

       reply.Err = OK

    } else if args.(ExecArgs).Type == Get {
       // execute the get

       value, ok := sp.data[key]
       if ok {
          reply.Value = value
          reply.Err = OK
       } else {
          reply.Value = ""
          reply.Err = ErrNoKey
       }
    }

    return reply

  } else {
    // not testing

    // write op to file
    err := sp.WriteToLog(op)
    if err != nil {
      // log something
    }

    switch {
    case op.Type == Open:
      return sp.OpenHelper(op.Args.(OpenArgs), op.SeqNum)
    case op.Type == Close:
      return sp.CloseHelper(op.Args.(CloseArgs), op.SeqNum)
    case op.Type == Execute:
      return sp.ExecuteHelper(op.Args.(ExecArgs), op.SeqNum)
    }
  }
  return nil
}

func (sp *SQLPaxos) WriteToLog(op Op) error {
  b, err := json.Marshal(op)
  if err != nil {
    return err
  }
  return sp.logger.WriteToLog(b)
}

func (sp *SQLPaxos) ExecuteHelper(args ExecArgs, seqnum int) ExecReply {
  rows, columns, err := sp.UpdateDatabase(args.ClientId, args.Query, args.QueryParams, seqnum)
  if err != OK {
    // log something
    return ExecReply{Value:"", Err:err}
  }

  tuples := []*barista.Tuple{}
  for _, row := range rows {
    tuple := barista.Tuple{Cells: &row}
    tuples = append(tuples, &tuple)
  }

  result_set := new(barista.ResultSet)
  //result_set.Con = con. @TODO: this will not be populating this
  result_set.Tuples = &tuples
  result_set.FieldNames = &columns
  return ExecReply{Value:result_set, Err:OK}
}

func (sp *SQLPaxos) OpenHelper(args OpenArgs, seqnum int) OpenReply {
  reply := OpenReply{}
  _, ok := sp.connections[args.ClientId]
  if ok {
    reply.Err = ConnAlreadyOpen
  } else {
      manager := new(db.DBManager)
      reply.Err = errorToErr(manager.OpenConnection(args.User, args.Password, args.Database))
      sp.connections[args.ClientId] = manager
  }
  _, _, err := sp.UpdateDatabase(args.ClientId, "", nil, seqnum)
  if err != OK {
    // log something
  }
  return reply
}

func errorToErr(error error) Err {
  if error != nil {
    return Err(error.Error())
  } else {
    return OK
  }
}

func (sp *SQLPaxos) CloseHelper(args CloseArgs, seqnum int) CloseReply {
  reply := CloseReply{}
  _, ok := sp.connections[args.ClientId]
  if !ok {
    reply.Err = ConnAlreadyClosed
  } else {
    reply.Err = errorToErr(sp.connections[args.ClientId].CloseConnection())
    delete(sp.connections, args.ClientId) //only delete on successful close?
  }
  _, _, err := sp.UpdateDatabase(args.ClientId, "", nil, seqnum)
  if err != OK {
    // log something
  }
  return reply
}

// note that NoOps don't update the state table
func (sp *SQLPaxos) UpdateDatabase(clientId int64, query string, query_params [][]byte, seqnum int) ([][][]byte, []string, Err) {
  query = "BEGIN TRANSACTION;" + query + "; UPDATE SQLPaxosLog SET lastSeqNum=" +
    strconv.Itoa(seqnum) + "; END TRANSACTION;"
  rows, columns, error := sp.connections[clientId].ExecuteSql(query, query_params)
  err := errorToErr(error)
  return rows, columns, err
}

func (sp *SQLPaxos) fillHoles(next int, seq int) interface{} {

  var reply interface{}

  // make sure there are no holes in the log before our operation
  for i := next; i <= seq; i++ {
     nwaits := 0
     for !sp.dead {
	if _, ok := sp.ops[i]; ok || sp.next > i {
      	   break
        }

        decided, v_i := sp.px.Status(i)
        if decided {
           // the operation in slot i has been decided
           sp.ops[i] = v_i.(Op)
           break
        } else {
           nwaits++
           sp.mu.Unlock()
           if nwaits == 5 || nwaits == 10 {
              // propose a no-op
              sp.px.Start(i, Op{NoOp: true})
           } else if nwaits > 10 {
              time.Sleep(100 * time.Millisecond)
           } else {
              time.Sleep(10 * time.Millisecond)
           }
           sp.mu.Lock()
        }
     }

     if i == sp.next {
        // the operation at slot i is next to be executed
	r, executed := sp.checkIfExecuted(sp.ops[i])
        if executed {
    	   sp.replies[i] = r
	} else {
	   r := sp.execute(sp.ops[i])
	   sp.replies[i] = r
	   sp.lastSeen[getOpClientId(sp.ops[i])] = LastSeen{ RequestId: getOpRequestId(sp.ops[i]), Reply: r }
	}
        sp.next++
     }

     if i == seq {
        reply = sp.replies[i]
     }
  }

  return reply
}

func getOpClientId(op Op) int64 {
  switch {
  case op.Type == Open:
    return op.Args.(OpenArgs).ClientId;
  case op.Type == Close:
    return op.Args.(CloseArgs).ClientId;
  case op.Type == Execute:
    return op.Args.(ExecArgs).ClientId;
  }
  return -1;
}

func getOpRequestId(op Op) int {
  switch {
  case op.Type == Open:
    return op.Args.(OpenArgs).RequestId;
  case op.Type == Close:
    return op.Args.(CloseArgs).RequestId;
  case op.Type == Execute:
    return op.Args.(ExecArgs).RequestId;
  }
  return -1;
}

// @TODO: update to support multiple types of operations
func (sp *SQLPaxos) checkIfExecuted(op Op) (interface{}, bool) {
  // need some casting here
  lastSeen, ok := sp.lastSeen[getOpClientId(op)]
  if ok {
     if lastSeen.RequestId == getOpRequestId(op) {
        return lastSeen.Reply, true
     } else if lastSeen.RequestId > getOpRequestId(op) {
        return nil, true // empty reply since this is an old request
     }
  }

  return nil, false
}

func (sp *SQLPaxos) reserveSlot(op Op) int {

  // propose this operation for slot seq
  seq := sp.px.Max() + 1
  v := op
  sp.px.Start(seq, v)

  nwaits := 0
  for !sp.dead {
     decided, v_a := sp.px.Status(seq)
     if decided && v_a != nil && getOpClientId(v_a.(Op)) == getOpClientId(v) &&
       getOpRequestId(v_a.(Op)) == getOpRequestId(v) {
        // we successfully claimed this slot for our operation
        if _, ok := sp.ops[seq]; !ok {
	   v.SeqNum = seq
           sp.ops[seq] = v
        }
        break
     } else if decided {
        // another proposer got this slot, so try to get our operation in a new slot
        seq = int(math.Max(float64(sp.px.Max() + 1), float64(seq + 1)))
        sp.px.Start(seq, v)
        nwaits = 0
     } else {
        nwaits++
  	sp.mu.Unlock()
        if nwaits == 5 || nwaits == 10 {
           // re-propose our operation
           sp.px.Start(seq, v)
     	} else if nwaits > 10 {
           time.Sleep(100 * time.Millisecond)
        } else {
           time.Sleep(10 * time.Millisecond)
     	}
  	sp.mu.Lock()
     }
  }
  v.SeqNum = seq // update sequence number
  return seq
}

func (sp *SQLPaxos) freeMemory(seq int) {

  sp.done[seq] = true
  minNotDone := seq + 1
  for i := seq; i >= 0; i-- {
     _, ok := sp.ops[i]
     if ok {
        if done, ok := sp.done[i]; ok && done || sp.ops[i].NoOp {
           delete(sp.ops, i)
           delete(sp.replies, i)
           delete(sp.done, i)
        } else {
           minNotDone = i
        }
     }
  }

  sp.px.Done(minNotDone - 1)
}

//@Make it work for multiple types of arguments
func (sp *SQLPaxos) commit(op Op) interface{} {

  sp.mu.Lock()
  defer sp.mu.Unlock()

  // first check if this request has already been executed
  reply, ok := sp.checkIfExecuted(op)
  if ok {
     return reply
  }

  // reserve a slot in the paxos log for this operation
  seq := sp.reserveSlot(op)

  next := sp.next
  if next > seq {
     // our operation has already been executed
     reply = sp.replies[seq]
  } else {
     // fill holes in the log and execute our operation
     reply = sp.fillHoles(next, seq)
  }

  // delete un-needed log entries to free up memory
  sp.freeMemory(seq)

  return reply
}

func (sp *SQLPaxos) ExecuteSQL(args *ExecArgs, reply *ExecReply) error {
  // execute this operation and store the response in r
  op := Op{Type:Execute, Args: *args}
  r := sp.commit(op)

  if r != nil {
     reply.Value = r.(ExecReply).Value
     reply.Err = r.(ExecReply).Err
  }

  return nil
}

// open the connection to the database
func (sp *SQLPaxos) Open(args *OpenArgs, reply *OpenReply) error {
  // execute this operation and store the response in r
  op := Op{Type:Open, Args: *args}
  r := sp.commit(op)

  if r != nil {
     reply.Err = r.(OpenReply).Err
  }

  return nil
}

// close the connection to the database
func (sp *SQLPaxos) Close(args *CloseArgs, reply *CloseReply) error {
  // execute this operation and store the response in r
  op := Op{Type:Close, Args: *args}
  r := sp.commit(op)

  if r != nil {
     reply.Err = r.(CloseReply).Err
  }

  return nil
}

// tell the server to shut itself down.
func (sp *SQLPaxos) kill() {
  sp.dead = true
  sp.l.Close()
  sp.px.Kill()
}

//
// servers[] contains the ports of the set of
// servers that will cooperate via Paxos to
// form the fault-tolerant key/value service.
// me is the index of the current server in servers[].
//
func StartServer(servers []string, me int) *SQLPaxos {
  // call gob.Register on structures you want
  // Go's RPC library to marshall/unmarshall.
  gob.Register(Op{})
  gob.Register(ExecArgs{})

  sp := new(SQLPaxos)
  sp.me = me

  // Your initialization code here.
  sp.ops = make(map[int]Op)
  sp.data = make(map[string]string)
  sp.replies = make(map[int]interface{})
  sp.done = make(map[int]bool)
  sp.lastSeen = make(map[int64]LastSeen)
  sp.next = 0
  sp.connections = make(map[int64]*db.DBManager)
  sp.logger = logger.Make("sqlpaxos_log.txt")

  rpcs := rpc.NewServer()
  rpcs.Register(sp)

  sp.px = paxos.Make(servers, me, rpcs)

  os.Remove(servers[me])
  l, e := net.Listen("unix", servers[me]);
  if e != nil {
    log.Fatal("listen error: ", e);
  }
  sp.l = l

  // please do not change any of the following code,
  // or do anything to subvert it.

  go func() {
    for sp.dead == false {
      conn, err := sp.l.Accept()
      if err == nil && sp.dead == false {
      if sp.unreliable && (rand.Int63() % 1000) < 100 {
          // discard the request.
          conn.Close()
        } else if sp.unreliable && (rand.Int63() % 1000) < 200 {
          // process the request but force discard of reply.
          c1 := conn.(*net.UnixConn)
          f, _ := c1.File()
          err := syscall.Shutdown(int(f.Fd()), syscall.SHUT_WR)
          if err != nil {
            fmt.Printf("shutdown: %v\n", err)
          }
          go rpcs.ServeConn(conn)
        } else {
          go rpcs.ServeConn(conn)
        }
      } else if err == nil {
        conn.Close()
      }
      if err != nil && sp.dead == false {
        fmt.Printf("SQLPaxos(%v) accept: %v\n", me, err.Error())
	sp.kill()
      }
    }
  }()

  return sp
}

<commit_msg>server fixes<commit_after>package sqlpaxos

import "net"
import "fmt"
import "net/rpc"
import "log"
import "time"
import "paxos"
import "sync"
import "os"
import "syscall"
import "encoding/gob"
import "math/rand"
import "strconv"
import "math"
import "barista"
import "encoding/json"
import "logger"
import "db"

const Debug=0

func DPrintf(format string, a ...interface{}) (n int, err error) {
        if Debug > 0 {
                log.Printf(format, a...)
        }
        return
}

type LastSeen struct {
  RequestId int
  Reply interface{}
}

type SQLPaxos struct {
  mu sync.Mutex
  l net.Listener
  me int
  dead bool // for testing
  unreliable bool // for testing
  px *paxos.Paxos

  // Your definitions here.
  ops map[int]Op // log of operations
  replies map[int]interface{} // the replies for this sequence number
  done map[int]bool // true if we can delete the data for this sequence number
  data map[string]string // the database
  lastSeen map[int64]LastSeen // the last request/reply for this client
  connections map[int64]*db.DBManager // connections per client. Limited to a single connection per client
  next int // the next sequence number to be executed
  logger *logger.Logger // logger to write paxos log to file
}

func (sp *SQLPaxos) execute(op Op) interface{} {

  testing := true
  if testing {
    args := op.Args
    reply := ExecReply{}

    // @TODO remove this
    if op.NoOp {
       return reply
    }

    // @TODO remove get & put
    key := args.(ExecArgs).Key
    if args.(ExecArgs).Type == Put {
       // execute the put

       prevValue, ok := sp.data[key]
       if ok {
          reply.Value = prevValue
       } else {
          reply.Value = ""
       }

       if args.(ExecArgs).DoHash {
          sp.data[key] = strconv.Itoa(int(hash(reply.Value + args.(ExecArgs).Value)))
       } else {
          sp.data[key] = args.(ExecArgs).Value
       }

       reply.Err = OK

    } else if args.(ExecArgs).Type == Get {
       // execute the get

       value, ok := sp.data[key]
       if ok {
          reply.Value = value
          reply.Err = OK
       } else {
          reply.Value = ""
          reply.Err = ErrNoKey
       }
    }

    return reply

  } else {
    // not testing

    // write op to file
    err := sp.WriteToLog(op)
    if err != nil {
      // log something
    }

    switch {
    case op.Type == Open:
      return sp.OpenHelper(op.Args.(OpenArgs), op.SeqNum)
    case op.Type == Close:
      return sp.CloseHelper(op.Args.(CloseArgs), op.SeqNum)
    case op.Type == Execute:
      return sp.ExecuteHelper(op.Args.(ExecArgs), op.SeqNum)
    }
  }
  return nil
}

func (sp *SQLPaxos) WriteToLog(op Op) error {
  b, err := json.Marshal(op)
  if err != nil {
    return err
  }
  return sp.logger.WriteToLog(b)
}

func (sp *SQLPaxos) ExecuteHelper(args ExecArgs, seqnum int) ExecReply {
  rows, columns, err := sp.UpdateDatabase(args.ClientId, args.Query, args.QueryParams, seqnum)
  if err != OK {
    // log something
    return ExecReply{Value:"", Err:err}
  }

  tuples := []*barista.Tuple{}
  for _, row := range rows {
    tuple := barista.Tuple{Cells: &row}
    tuples = append(tuples, &tuple)
  }

  result_set := new(barista.ResultSet)
  //result_set.Con = con. @TODO: this will not be populating this
  result_set.Tuples = &tuples
  result_set.FieldNames = &columns
  return ExecReply{Result:result_set, Err:OK}
}

func (sp *SQLPaxos) OpenHelper(args OpenArgs, seqnum int) OpenReply {
  reply := OpenReply{}
  _, ok := sp.connections[args.ClientId]
  if ok {
    reply.Err = ConnAlreadyOpen
  } else {
      manager := new(db.DBManager)
      reply.Err = errorToErr(manager.OpenConnection(args.User, args.Password, args.Database))
      sp.connections[args.ClientId] = manager
  }
  _, _, err := sp.UpdateDatabase(args.ClientId, "", nil, seqnum)
  if err != OK {
    // log something
  }
  return reply
}

func errorToErr(error error) Err {
  if error != nil {
    return Err(error.Error())
  } else {
    return OK
  }
}

func (sp *SQLPaxos) CloseHelper(args CloseArgs, seqnum int) CloseReply {
  reply := CloseReply{}
  _, ok := sp.connections[args.ClientId]
  if !ok {
    reply.Err = ConnAlreadyClosed
  } else {
    reply.Err = errorToErr(sp.connections[args.ClientId].CloseConnection())
    delete(sp.connections, args.ClientId) //only delete on successful close?
  }
  _, _, err := sp.UpdateDatabase(args.ClientId, "", nil, seqnum)
  if err != OK {
    // log something
  }
  return reply
}

// note that NoOps don't update the state table
func (sp *SQLPaxos) UpdateDatabase(clientId int64, query string, query_params [][]byte, seqnum int) ([][][]byte, []string, Err) {
  query = "BEGIN TRANSACTION;" + query + "; UPDATE SQLPaxosLog SET lastSeqNum=" +
    strconv.Itoa(seqnum) + "; END TRANSACTION;"
  rows, columns, error := sp.connections[clientId].ExecuteSql(query, query_params)
  err := errorToErr(error)
  return rows, columns, err
}

func (sp *SQLPaxos) fillHoles(next int, seq int) interface{} {

  var reply interface{}

  // make sure there are no holes in the log before our operation
  for i := next; i <= seq; i++ {
     nwaits := 0
     for !sp.dead {
	if _, ok := sp.ops[i]; ok || sp.next > i {
      	   break
        }

        decided, v_i := sp.px.Status(i)
        if decided {
           // the operation in slot i has been decided
           sp.ops[i] = v_i.(Op)
           break
        } else {
           nwaits++
           sp.mu.Unlock()
           if nwaits == 5 || nwaits == 10 {
              // propose a no-op
              sp.px.Start(i, Op{NoOp: true})
           } else if nwaits > 10 {
              time.Sleep(100 * time.Millisecond)
           } else {
              time.Sleep(10 * time.Millisecond)
           }
           sp.mu.Lock()
        }
     }

     if i == sp.next {
        // the operation at slot i is next to be executed
	r, executed := sp.checkIfExecuted(sp.ops[i])
        if executed {
    	   sp.replies[i] = r
	} else {
	   r := sp.execute(sp.ops[i])
	   sp.replies[i] = r
	   sp.lastSeen[getOpClientId(sp.ops[i])] = LastSeen{ RequestId: getOpRequestId(sp.ops[i]), Reply: r }
	}
        sp.next++
     }

     if i == seq {
        reply = sp.replies[i]
     }
  }

  return reply
}

func getOpClientId(op Op) int64 {
  switch {
  case op.Type == Open:
    return op.Args.(OpenArgs).ClientId;
  case op.Type == Close:
    return op.Args.(CloseArgs).ClientId;
  case op.Type == Execute:
    return op.Args.(ExecArgs).ClientId;
  }
  return -1;
}

func getOpRequestId(op Op) int {
  switch {
  case op.Type == Open:
    return op.Args.(OpenArgs).RequestId;
  case op.Type == Close:
    return op.Args.(CloseArgs).RequestId;
  case op.Type == Execute:
    return op.Args.(ExecArgs).RequestId;
  }
  return -1;
}

// @TODO: update to support multiple types of operations
func (sp *SQLPaxos) checkIfExecuted(op Op) (interface{}, bool) {
  // need some casting here
  lastSeen, ok := sp.lastSeen[getOpClientId(op)]
  if ok {
     if lastSeen.RequestId == getOpRequestId(op) {
        return lastSeen.Reply, true
     } else if lastSeen.RequestId > getOpRequestId(op) {
        return nil, true // empty reply since this is an old request
     }
  }

  return nil, false
}

func (sp *SQLPaxos) reserveSlot(op Op) int {

  // propose this operation for slot seq
  seq := sp.px.Max() + 1
  v := op
  sp.px.Start(seq, v)

  nwaits := 0
  for !sp.dead {
     decided, v_a := sp.px.Status(seq)
     if decided && v_a != nil && getOpClientId(v_a.(Op)) == getOpClientId(v) &&
       getOpRequestId(v_a.(Op)) == getOpRequestId(v) {
        // we successfully claimed this slot for our operation
        if _, ok := sp.ops[seq]; !ok {
	   v.SeqNum = seq
           sp.ops[seq] = v
        }
        break
     } else if decided {
        // another proposer got this slot, so try to get our operation in a new slot
        seq = int(math.Max(float64(sp.px.Max() + 1), float64(seq + 1)))
        sp.px.Start(seq, v)
        nwaits = 0
     } else {
        nwaits++
  	sp.mu.Unlock()
        if nwaits == 5 || nwaits == 10 {
           // re-propose our operation
           sp.px.Start(seq, v)
     	} else if nwaits > 10 {
           time.Sleep(100 * time.Millisecond)
        } else {
           time.Sleep(10 * time.Millisecond)
     	}
  	sp.mu.Lock()
     }
  }
  v.SeqNum = seq // update sequence number
  return seq
}

func (sp *SQLPaxos) freeMemory(seq int) {

  sp.done[seq] = true
  minNotDone := seq + 1
  for i := seq; i >= 0; i-- {
     _, ok := sp.ops[i]
     if ok {
        if done, ok := sp.done[i]; ok && done || sp.ops[i].NoOp {
           delete(sp.ops, i)
           delete(sp.replies, i)
           delete(sp.done, i)
        } else {
           minNotDone = i
        }
     }
  }

  sp.px.Done(minNotDone - 1)
}

//@Make it work for multiple types of arguments
func (sp *SQLPaxos) commit(op Op) interface{} {

  sp.mu.Lock()
  defer sp.mu.Unlock()

  // first check if this request has already been executed
  reply, ok := sp.checkIfExecuted(op)
  if ok {
     return reply
  }

  // reserve a slot in the paxos log for this operation
  seq := sp.reserveSlot(op)

  next := sp.next
  if next > seq {
     // our operation has already been executed
     reply = sp.replies[seq]
  } else {
     // fill holes in the log and execute our operation
     reply = sp.fillHoles(next, seq)
  }

  // delete un-needed log entries to free up memory
  sp.freeMemory(seq)

  return reply
}

func (sp *SQLPaxos) ExecuteSQL(args *ExecArgs, reply *ExecReply) error {
  // execute this operation and store the response in r
  op := Op{Type:Execute, Args: *args}
  r := sp.commit(op)

  if r != nil {
     reply.Value = r.(ExecReply).Value
     reply.Err = r.(ExecReply).Err
  }

  return nil
}

// open the connection to the database
func (sp *SQLPaxos) Open(args *OpenArgs, reply *OpenReply) error {
  // execute this operation and store the response in r
  op := Op{Type:Open, Args: *args}
  r := sp.commit(op)

  if r != nil {
     reply.Err = r.(OpenReply).Err
  }

  return nil
}

// close the connection to the database
func (sp *SQLPaxos) Close(args *CloseArgs, reply *CloseReply) error {
  // execute this operation and store the response in r
  op := Op{Type:Close, Args: *args}
  r := sp.commit(op)

  if r != nil {
     reply.Err = r.(CloseReply).Err
  }

  return nil
}

// tell the server to shut itself down.
func (sp *SQLPaxos) kill() {
  sp.dead = true
  sp.l.Close()
  sp.px.Kill()
}

//
// servers[] contains the ports of the set of
// servers that will cooperate via Paxos to
// form the fault-tolerant key/value service.
// me is the index of the current server in servers[].
//
func StartServer(servers []string, me int) *SQLPaxos {
  // call gob.Register on structures you want
  // Go's RPC library to marshall/unmarshall.
  gob.Register(Op{})
  gob.Register(ExecArgs{})

  sp := new(SQLPaxos)
  sp.me = me

  // Your initialization code here.
  sp.ops = make(map[int]Op)
  sp.data = make(map[string]string)
  sp.replies = make(map[int]interface{})
  sp.done = make(map[int]bool)
  sp.lastSeen = make(map[int64]LastSeen)
  sp.next = 0
  sp.connections = make(map[int64]*db.DBManager)
  sp.logger = logger.Make("sqlpaxos_log.txt")

  rpcs := rpc.NewServer()
  rpcs.Register(sp)

  sp.px = paxos.Make(servers, me, rpcs)

  os.Remove(servers[me])
  l, e := net.Listen("unix", servers[me]);
  if e != nil {
    log.Fatal("listen error: ", e);
  }
  sp.l = l

  // please do not change any of the following code,
  // or do anything to subvert it.

  go func() {
    for sp.dead == false {
      conn, err := sp.l.Accept()
      if err == nil && sp.dead == false {
      if sp.unreliable && (rand.Int63() % 1000) < 100 {
          // discard the request.
          conn.Close()
        } else if sp.unreliable && (rand.Int63() % 1000) < 200 {
          // process the request but force discard of reply.
          c1 := conn.(*net.UnixConn)
          f, _ := c1.File()
          err := syscall.Shutdown(int(f.Fd()), syscall.SHUT_WR)
          if err != nil {
            fmt.Printf("shutdown: %v\n", err)
          }
          go rpcs.ServeConn(conn)
        } else {
          go rpcs.ServeConn(conn)
        }
      } else if err == nil {
        conn.Close()
      }
      if err != nil && sp.dead == false {
        fmt.Printf("SQLPaxos(%v) accept: %v\n", me, err.Error())
	sp.kill()
      }
    }
  }()

  return sp
}

<|endoftext|>


<commit_before>package main

import (
	"encoding/json"
	"flag"
	"fmt"
	"io"
	"io/ioutil"
	"log"
	"mime/multipart"
	"net/http"
	"net/http/cookiejar"
	"net/url"
	"os"
	"path/filepath"
	"strings"

	"bitbucket.org/apihussain/atmotool/zip"

	"bytes"

	"github.com/docopt/docopt-go"
)

// Configuration
type Configuration struct {
	Url      string `json:"url"`
	Email    string `json:"email"`
	Password string `json:"password"`
}

type Auth struct {
	Email    string `json:"email"`
	Password string `json:"password"`
}

const LESS_URI = "/resources/theme/default/less?unpack=false"

var (
	config Configuration
	client *http.Client
)

func main() {

	usage := `Akana Community Manager Helper Tool.

Usage:
  atmosphere zip --prefix <prefix> [--dir <dir>] --config <config>
  atmosphere upload less <file> --config <config>
  atmosphere upload file --path <path> --config <config> <files>...
  atmosphere upload all --config <config> [--dir <dir>]
  atmosphere -h | --help
  atmosphere --version

Options:
  -h --help  Show help message and exit.
  --version  Show version and exit.
  --dir=<dir>  Directory. [default: .]
  --path=<cms_path>  CM CMS path.
`
	arguments, _ := docopt.Parse(usage, nil, true, "1.0 cirrus", false)

	// Debug for command-line args
	/*
		var keys []string
		for k := range arguments {
			keys = append(keys, k)
		}
		sort.Strings(keys)
		// print the argument keys and values
		for _, k := range keys {
			fmt.Printf("%9s %v\n", k, arguments[k])
		}
	*/

	configLocation, _ := arguments["<config>"].(string)
	configBytes, err := ioutil.ReadFile(configLocation)
	if err != nil {
		fmt.Printf("Error opening config file %s\n", err)
		flag.Usage()
		os.Exit(1)
	}
	//var config Configuration
	err = json.Unmarshal(configBytes, &config)
	if err != nil {
		fmt.Printf("Unable to parse configuration file. %s\n", err)
		os.Exit(1)
	}

	if len(config.Password) < 1 {
		fmt.Printf("Missing or blank password.")
		os.Exit(1)
	}

	if arguments["upload"] == true {
		if arguments["less"] == true {
			uploadFilePath := arguments["<file>"].(string)
			uploadLessFile(uploadFilePath, config)
		} else if arguments["all"] == true {
			dir, _ := arguments["--dir"].(string)
			uploadAllHelper(dir, config)
		} else if arguments["file"] == true {
			var files []string
			for _, v := range arguments["<files>"].([]string) {
				files = append(files, v)
			}
			path, _ := arguments["--path"].(string)
			upload(files, config, path)
		}
	} else if arguments["zip"] == true {
		prefix, _ := arguments["<prefix>"].(string)
		dir, _ := arguments["--dir"].(string)
		//zip.ZipPredefinedPath(prefix, dir)
		var fn string
		if dir == "." {
			fn = "this"
		} else {
			fn = strings.Replace(dir, "/", "-", -1)
		}
		fn = prefix + "_" + fn + ".zip"
		fmt.Printf("Zipping %s as %s...\n", dir, fn)

		zip.ZipFolder(dir, fn)
	}
}

// Convenience method
func uploadLessFile(uploadFilePath string, config Configuration) {
	log.Printf("Uploading Less file %s to %s\n", uploadFilePath, config.Url)

	err := loginToCM()
	if err != nil {
		log.Fatalln(err)
		return
	}

	// Upload
	log.Println("Uploading custom.less ...")
	extraParams := map[string]string{
		"none": "really",
	}
	uploadUri := config.Url + LESS_URI

	statusCode, err := uploadFile(uploadFilePath, extraParams, uploadUri)
	if err != nil {
		log.Fatalf("Issues. %v : %s", statusCode, err)
	}

	log.Printf("Upload status %v", statusCode)

	if statusCode == 200 {
		err = rebuildStyles("default")
		if err != nil {
			log.Fatalln(err)
		}
	}

}

func uploadFile(uploadFilePath string, extras map[string]string, uploadUri string) (int, error) {

	var uploadStatus int

	//uploadUri := config.Url + LESS_URI

	var request *http.Request
	request, err := newFileUploadRequest(uploadUri, extras, "File", uploadFilePath)
	if err != nil {
		log.Fatalln(err)
		return uploadStatus, err
	}
	request.Header.Add("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8")

	resp, err := client.Do(request)
	if err != nil {
		log.Fatal(err)
		return uploadStatus, err
	} else {
		body := &bytes.Buffer{}
		_, err := body.ReadFrom(resp.Body)
		if err != nil {
			log.Fatalln(err)
		}
		resp.Body.Close()

		uploadStatus = resp.StatusCode

		//log.Printf("Upload status %v", resp.StatusCode)
	}
	return uploadStatus, nil
}

func loginToCM() error {
	// Login
	log.Println("Logging in...")
	client = &http.Client{}
	jar, err := cookiejar.New(nil)
	if err != nil {
		log.Fatalln(err)
		return err
	}
	client.Jar = jar

	loginUri := config.Url + "/api/login"
	auth := Auth{config.Email, config.Password}
	buf, err := json.Marshal(auth)
	if err != nil {
		log.Fatalln(err)
		return err
	}
	req, err := http.NewRequest("POST", loginUri, bytes.NewReader(buf))
	req.Header.Add("Accept", "application/json")
	req.Header.Add("Content-Type", "application/json")

	resp, err := client.Do(req)
	if err != nil {
		log.Fatalln(err)
		return err
	}
	log.Printf("Login %s", resp.Status)

	return nil

}

func rebuildStyles(theme string) error {

	// call rebuild styles API
	// POST CM_URI/resources/branding/generatestyles
	// Form Data
	// theme: default
	log.Println("Rebuilding styles...")
	rebuildStylesUri := config.Url + "/resources/branding/generatestyles"
	resp, err := http.PostForm(rebuildStylesUri, url.Values{"theme": {theme}})

	data, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		log.Fatalln(err)
		return err
	}
	var results map[string]interface{}
	err = json.Unmarshal(data, &results)
	status := results["result"]
	log.Printf("Rebuild styles: %s", status)
	return nil
}

func newFileUploadRequest(uri string, params map[string]string, paramName string, path string) (*http.Request, error) {

	file, err := os.Open(path)
	if err != nil {
		return nil, err
	}
	defer file.Close()

	body := &bytes.Buffer{}
	writer := multipart.NewWriter(body)

	part, err := writer.CreateFormFile(paramName, filepath.Base(path))
	if err != nil {
		return nil, err
	}

	_, err = io.Copy(part, file)
	if err != nil {
		log.Fatalln(err)
		return nil, err
	}

	/*
		for key, val := range params {
			_ = writer.WriteField(key, val)
		}
	*/

	err = writer.Close()
	if err != nil {
		return nil, err
	}

	req, _ := http.NewRequest("POST", uri, body)
	req.Header.Add("Content-Type", writer.FormDataContentType())

	return req, nil
}

// Convenience method
func uploadAllHelper(dir string, config Configuration) {
	fmt.Printf("Uploading all in %s to %s\n", dir, config.Url)
	// upload PREFIX_resourcesThemeDefault.zip to CMS /resources/theme/default
	// upload PREFIX_contentHomeLanding.zip to CMS /content/home/landing
	// upload less file to CMS ??
	// call rebuild styles API

}

// basic upload to CMS
func upload(files []string, config Configuration, path string) {
	fmt.Printf("Uploading to %s cms location %s these: %s\n", config.Url, path, files)
	// upload FILE to CMS path PATH
	// iterate through []FILE

	err := loginToCM()
	if err != nil {
		log.Fatalln(err)
		return
	}

	uploadUri := config.Url + path

	extraParams := map[string]string{
		"none": "really",
	}

	for _, v := range files {
		log.Printf("Uploading %s ...\n", v)
		if strings.HasSuffix(v, ".zip") {
			uploadUri += "?unpack=true"
		}
		log.Println(uploadUri)
		statusCode, err := uploadFile(v, extraParams, uploadUri)
		if err != nil {
			log.Fatalf("Issues. %v : %s", statusCode, err)
		}
		log.Printf("Upload status %v", statusCode)
	}

}
<commit_msg>minor changes to zip output filename<commit_after>package main

import (
	"encoding/json"
	"flag"
	"fmt"
	"io"
	"io/ioutil"
	"log"
	"mime/multipart"
	"net/http"
	"net/http/cookiejar"
	"net/url"
	"os"
	"path/filepath"
	"strings"

	"bitbucket.org/apihussain/atmotool/zip"

	"bytes"

	"github.com/docopt/docopt-go"
)

// Configuration
type Configuration struct {
	Url      string `json:"url"`
	Email    string `json:"email"`
	Password string `json:"password"`
}

type Auth struct {
	Email    string `json:"email"`
	Password string `json:"password"`
}

const LESS_URI = "/resources/theme/default/less?unpack=false"

var (
	config Configuration
	client *http.Client
)

func main() {

	usage := `Akana Community Manager Helper Tool.

Usage:
  atmosphere zip --prefix <prefix> [--dir <dir>] --config <config>
  atmosphere upload less <file> --config <config>
  atmosphere upload file --path <path> --config <config> <files>...
  atmosphere upload all --config <config> [--dir <dir>]
  atmosphere -h | --help
  atmosphere --version

Options:
  -h --help  Show help message and exit.
  --version  Show version and exit.
  --dir=<dir>  Directory. [default: .]
  --path=<cms_path>  CM CMS path.
`
	arguments, _ := docopt.Parse(usage, nil, true, "1.0 cirrus", false)

	// Debug for command-line args
	/*
		var keys []string
		for k := range arguments {
			keys = append(keys, k)
		}
		sort.Strings(keys)
		// print the argument keys and values
		for _, k := range keys {
			fmt.Printf("%9s %v\n", k, arguments[k])
		}
	*/

	configLocation, _ := arguments["<config>"].(string)
	configBytes, err := ioutil.ReadFile(configLocation)
	if err != nil {
		fmt.Printf("Error opening config file %s\n", err)
		flag.Usage()
		os.Exit(1)
	}
	//var config Configuration
	err = json.Unmarshal(configBytes, &config)
	if err != nil {
		fmt.Printf("Unable to parse configuration file. %s\n", err)
		os.Exit(1)
	}

	if len(config.Password) < 1 {
		fmt.Printf("Missing or blank password.")
		os.Exit(1)
	}

	if arguments["upload"] == true {
		if arguments["less"] == true {
			uploadFilePath := arguments["<file>"].(string)
			uploadLessFile(uploadFilePath, config)
		} else if arguments["all"] == true {
			dir, _ := arguments["--dir"].(string)
			uploadAllHelper(dir, config)
		} else if arguments["file"] == true {
			var files []string
			for _, v := range arguments["<files>"].([]string) {
				files = append(files, v)
			}
			path, _ := arguments["--path"].(string)
			upload(files, config, path)
		}
	} else if arguments["zip"] == true {
		prefix, _ := arguments["<prefix>"].(string)
		dir, _ := arguments["--dir"].(string)
		//zip.ZipPredefinedPath(prefix, dir)
		var fn string
		if dir == "." {
			fn = "this"
		} else {
			fn = strings.Replace(dir, ".", "", -1)
			fn = strings.Replace(fn, "/", "-", -1)
		}
		fn = prefix + "_" + fn + ".zip"
		fmt.Printf("Zipping %s as %s...\n", dir, fn)

		zip.ZipFolder(dir, fn)
	}
}

// Convenience method
func uploadLessFile(uploadFilePath string, config Configuration) {
	log.Printf("Uploading Less file %s to %s\n", uploadFilePath, config.Url)

	err := loginToCM()
	if err != nil {
		log.Fatalln(err)
		return
	}

	// Upload
	log.Println("Uploading custom.less ...")
	extraParams := map[string]string{
		"none": "really",
	}
	uploadUri := config.Url + LESS_URI

	statusCode, err := uploadFile(uploadFilePath, extraParams, uploadUri)
	if err != nil {
		log.Fatalf("Issues. %v : %s", statusCode, err)
	}

	log.Printf("Upload status %v", statusCode)

	if statusCode == 200 {
		err = rebuildStyles("default")
		if err != nil {
			log.Fatalln(err)
		}
	}

}

func uploadFile(uploadFilePath string, extras map[string]string, uploadUri string) (int, error) {

	var uploadStatus int

	//uploadUri := config.Url + LESS_URI

	var request *http.Request
	request, err := newFileUploadRequest(uploadUri, extras, "File", uploadFilePath)
	if err != nil {
		log.Fatalln(err)
		return uploadStatus, err
	}
	request.Header.Add("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8")

	resp, err := client.Do(request)
	if err != nil {
		log.Fatal(err)
		return uploadStatus, err
	} else {
		body := &bytes.Buffer{}
		_, err := body.ReadFrom(resp.Body)
		if err != nil {
			log.Fatalln(err)
		}
		resp.Body.Close()

		uploadStatus = resp.StatusCode

		//log.Printf("Upload status %v", resp.StatusCode)
	}
	return uploadStatus, nil
}

func loginToCM() error {
	// Login
	log.Println("Logging in...")
	client = &http.Client{}
	jar, err := cookiejar.New(nil)
	if err != nil {
		log.Fatalln(err)
		return err
	}
	client.Jar = jar

	loginUri := config.Url + "/api/login"
	auth := Auth{config.Email, config.Password}
	buf, err := json.Marshal(auth)
	if err != nil {
		log.Fatalln(err)
		return err
	}
	req, err := http.NewRequest("POST", loginUri, bytes.NewReader(buf))
	req.Header.Add("Accept", "application/json")
	req.Header.Add("Content-Type", "application/json")

	resp, err := client.Do(req)
	if err != nil {
		log.Fatalln(err)
		return err
	}
	log.Printf("Login %s", resp.Status)

	return nil

}

func rebuildStyles(theme string) error {

	// call rebuild styles API
	// POST CM_URI/resources/branding/generatestyles
	// Form Data
	// theme: default
	log.Println("Rebuilding styles...")
	rebuildStylesUri := config.Url + "/resources/branding/generatestyles"
	resp, err := http.PostForm(rebuildStylesUri, url.Values{"theme": {theme}})

	data, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		log.Fatalln(err)
		return err
	}
	var results map[string]interface{}
	err = json.Unmarshal(data, &results)
	status := results["result"]
	log.Printf("Rebuild styles: %s", status)
	return nil
}

func newFileUploadRequest(uri string, params map[string]string, paramName string, path string) (*http.Request, error) {

	file, err := os.Open(path)
	if err != nil {
		return nil, err
	}
	defer file.Close()

	body := &bytes.Buffer{}
	writer := multipart.NewWriter(body)

	part, err := writer.CreateFormFile(paramName, filepath.Base(path))
	if err != nil {
		return nil, err
	}

	_, err = io.Copy(part, file)
	if err != nil {
		log.Fatalln(err)
		return nil, err
	}

	/*
		for key, val := range params {
			_ = writer.WriteField(key, val)
		}
	*/

	err = writer.Close()
	if err != nil {
		return nil, err
	}

	req, _ := http.NewRequest("POST", uri, body)
	req.Header.Add("Content-Type", writer.FormDataContentType())

	return req, nil
}

// Convenience method
func uploadAllHelper(dir string, config Configuration) {
	fmt.Printf("Uploading all in %s to %s\n", dir, config.Url)
	// upload PREFIX_resourcesThemeDefault.zip to CMS /resources/theme/default
	// upload PREFIX_contentHomeLanding.zip to CMS /content/home/landing
	// upload less file to CMS ??
	// call rebuild styles API

}

// basic upload to CMS
func upload(files []string, config Configuration, path string) {
	fmt.Printf("Uploading to %s cms location %s these: %s\n", config.Url, path, files)
	// upload FILE to CMS path PATH
	// iterate through []FILE

	err := loginToCM()
	if err != nil {
		log.Fatalln(err)
		return
	}

	uploadUri := config.Url + path

	extraParams := map[string]string{
		"none": "really",
	}

	for _, v := range files {
		log.Printf("Uploading %s ...\n", v)
		if strings.HasSuffix(v, ".zip") {
			uploadUri += "?unpack=true"
		}
		log.Println(uploadUri)
		statusCode, err := uploadFile(v, extraParams, uploadUri)
		if err != nil {
			log.Fatalf("Issues. %v : %s", statusCode, err)
		}
		log.Printf("Upload status %v", statusCode)
	}

}
<|endoftext|>


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

/*
 *     Author: Piyush Harsh,
 *     URL: piyush-harsh.info
 */

package main

import (
	"code.google.com/p/gcfg"
	"fmt"
	"github.com/gorilla/mux"
	"io"
	"io/ioutil"
	"log"
	"net/http"
	"os"
	"strings"
)

type Config struct {
	Gatekeeper struct {
		Port    string
		LogFile string
		DbFile  string
	}
	Tnova struct {
		Defaultadmin  string
		Adminpassword string
	}
}

type user_struct struct {
	Username       string `json:"username"`
	Password       string `json:"password"`
	AdminFlag      string `json:"isadmin"`
	CapabilityList string `json:"accesslist"`
}

type service_struct struct {
	Shortname   string `json:"shortname"`
	Description string `json:"description"`
}

var (
	Trace         *log.Logger
	Info          *log.Logger
	Warning       *log.Logger
	Error         *log.Logger
	MyFileTrace   *log.Logger
	MyFileInfo    *log.Logger
	MyFileWarning *log.Logger
	MyFileError   *log.Logger
	staticMsgs    [20]string
	cfg           Config
	dbArg         string
)

func main() {
	err := gcfg.ReadFileInto(&cfg, "gatekeeper.cfg")
	if err != nil {
		log.Fatalf("Failed to parse gcfg data: %s", err)
		os.Exit(1)
	}
	file, err := os.OpenFile(cfg.Gatekeeper.LogFile, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666)
	if err != nil {
		log.Fatalln("Failed to open log file", "auth-utils.log", ":", err)
	}
	multi := io.MultiWriter(file, ioutil.Discard)
	Initlogger(ioutil.Discard, os.Stdout, os.Stdout, os.Stderr, multi)
	//logger has been initialized at this point
	InitMsgs()
	dbArg = "file:foo.db?cache=shared&mode=rwc"
	dbArg = strings.Replace(dbArg, "foo.db", cfg.Gatekeeper.DbFile, 1)
	dbCheck := CheckDB(dbArg)

	if dbCheck {
		MyFileInfo.Println("Table already exists in DB, nothing to do, proceeding normally.")
	} else {
		InitDB(dbArg)
	}
	r := mux.NewRouter().StrictSlash(false)
	r.HandleFunc("/", HomeHandler)
	users := r.Path("/admin/user/").Subrouter()
	users.Methods("GET").HandlerFunc(UserListHandler)
	users.Methods("POST").HandlerFunc(UserCreateHandler)

	user := r.Path("/admin/user/{id}").Subrouter()
	user.Methods("GET").HandlerFunc(UserDetailsHandler)
	user.Methods("PUT").HandlerFunc(UserUpdateHandler)
	user.Methods("DELETE").HandlerFunc(UserDeleteHandler)

	auth := r.Path("/auth/{id}").Subrouter()
	auth.Methods("GET").HandlerFunc(UserAuthHandler)

	tokens := r.Path("/token/").Subrouter()
	tokens.Methods("POST").HandlerFunc(TokenGenHandler)

	tokenval := r.Path("/token/validate/{id}").Subrouter()
	tokenval.Methods("GET").HandlerFunc(TokenValidateHandler)

	services := r.Path("/admin/service/").Subrouter()
	services.Methods("GET").HandlerFunc(ServiceListHandler)
	services.Methods("POST").HandlerFunc(ServiceRegisterHandler)

	portArg := ":port"
	portArg = strings.Replace(portArg, "port", cfg.Gatekeeper.Port, 1)
	MyFileInfo.Println("Starting server on", portArg)
	http.ListenAndServe(portArg, r)
	MyFileInfo.Println("Stopping server on", portArg)
}

func HomeHandler(out http.ResponseWriter, in *http.Request) {
	out.Header().Set("Content-Type", "application/json")
	out.WriteHeader(http.StatusOK) //200 status code
	var jsonbody = staticMsgs[0]
	fmt.Fprintln(out, jsonbody)
	MyFileInfo.Println("Received request on URI:/ GET")
}
<commit_msg>Update auth-utils.go<commit_after>/*
 * Copyright (c) 2015. Zuercher Hochschule fuer Angewandte Wissenschaften
 *  All Rights Reserved.
 *
 *     Licensed under the Apache License, Version 2.0 (the "License"); you may
 *     not use this file except in compliance with the License. You may obtain
 *     a copy of the License at
 *
 *          http://www.apache.org/licenses/LICENSE-2.0
 *
 *     Unless required by applicable law or agreed to in writing, software
 *     distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 *     WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 *     License for the specific language governing permissions and limitations
 *     under the License.
 */

/*
 *     Author: Piyush Harsh,
 *     URL: piyush-harsh.info
 */

package main

import (
	"github.com/scalingdata/gcfg"
	"fmt"
	"github.com/gorilla/mux"
	"io"
	"io/ioutil"
	"log"
	"net/http"
	"os"
	"strings"
)

type Config struct {
	Gatekeeper struct {
		Port    string
		LogFile string
		DbFile  string
	}
	Tnova struct {
		Defaultadmin  string
		Adminpassword string
	}
}

type user_struct struct {
	Username       string `json:"username"`
	Password       string `json:"password"`
	AdminFlag      string `json:"isadmin"`
	CapabilityList string `json:"accesslist"`
}

type service_struct struct {
	Shortname   string `json:"shortname"`
	Description string `json:"description"`
}

var (
	Trace         *log.Logger
	Info          *log.Logger
	Warning       *log.Logger
	Error         *log.Logger
	MyFileTrace   *log.Logger
	MyFileInfo    *log.Logger
	MyFileWarning *log.Logger
	MyFileError   *log.Logger
	staticMsgs    [20]string
	cfg           Config
	dbArg         string
)

func main() {
	err := gcfg.ReadFileInto(&cfg, "gatekeeper.cfg")
	if err != nil {
		log.Fatalf("Failed to parse gcfg data: %s", err)
		os.Exit(1)
	}
	file, err := os.OpenFile(cfg.Gatekeeper.LogFile, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666)
	if err != nil {
		log.Fatalln("Failed to open log file", "auth-utils.log", ":", err)
	}
	multi := io.MultiWriter(file, ioutil.Discard)
	Initlogger(ioutil.Discard, os.Stdout, os.Stdout, os.Stderr, multi)
	//logger has been initialized at this point
	InitMsgs()
	dbArg = "file:foo.db?cache=shared&mode=rwc"
	dbArg = strings.Replace(dbArg, "foo.db", cfg.Gatekeeper.DbFile, 1)
	dbCheck := CheckDB(dbArg)

	if dbCheck {
		MyFileInfo.Println("Table already exists in DB, nothing to do, proceeding normally.")
	} else {
		InitDB(dbArg)
	}
	r := mux.NewRouter().StrictSlash(false)
	r.HandleFunc("/", HomeHandler)
	users := r.Path("/admin/user/").Subrouter()
	users.Methods("GET").HandlerFunc(UserListHandler)
	users.Methods("POST").HandlerFunc(UserCreateHandler)

	user := r.Path("/admin/user/{id}").Subrouter()
	user.Methods("GET").HandlerFunc(UserDetailsHandler)
	user.Methods("PUT").HandlerFunc(UserUpdateHandler)
	user.Methods("DELETE").HandlerFunc(UserDeleteHandler)

	auth := r.Path("/auth/{id}").Subrouter()
	auth.Methods("GET").HandlerFunc(UserAuthHandler)

	tokens := r.Path("/token/").Subrouter()
	tokens.Methods("POST").HandlerFunc(TokenGenHandler)

	tokenval := r.Path("/token/validate/{id}").Subrouter()
	tokenval.Methods("GET").HandlerFunc(TokenValidateHandler)

	services := r.Path("/admin/service/").Subrouter()
	services.Methods("GET").HandlerFunc(ServiceListHandler)
	services.Methods("POST").HandlerFunc(ServiceRegisterHandler)

	portArg := ":port"
	portArg = strings.Replace(portArg, "port", cfg.Gatekeeper.Port, 1)
	MyFileInfo.Println("Starting server on", portArg)
	http.ListenAndServe(portArg, r)
	MyFileInfo.Println("Stopping server on", portArg)
}

func HomeHandler(out http.ResponseWriter, in *http.Request) {
	out.Header().Set("Content-Type", "application/json")
	out.WriteHeader(http.StatusOK) //200 status code
	var jsonbody = staticMsgs[0]
	fmt.Fprintln(out, jsonbody)
	MyFileInfo.Println("Received request on URI:/ GET")
}
<|endoftext|>


<commit_before>// Copyright 2018 by caixw, All rights reserved.
// Use of this source code is governed by a MIT
// license that can be found in the LICENSE file.

package auth

import (
	"encoding/base64"
	"net/http"
	"strings"
)

type basic struct {
	next   http.Handler
	secret string
	realm  string
}

// NewBasic 新的 Basic 验证方式
func NewBasic(next http.Handler, username, password, realm string) http.Handler {
	return &basic{
		next:   next,
		secret: base64.StdEncoding.EncodeToString([]byte(username + ":" + password)),
		realm:  `Basic realm="` + realm + `"`,
	}
}

func (b *basic) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	auth := r.Header.Get("Authorization")
	index := strings.IndexByte(auth, ' ')

	if index <= 0 {
		b.unauthorization(w)
		return
	}

	if "Basic" != auth[:index] {
		b.unauthorization(w)
		return
	}

	secret, err := base64.StdEncoding.DecodeString(auth[index+1:])
	if err != nil {
		// TODO
	}
	if string(secret) != b.secret {
		b.unauthorization(w)
		return
	}

	b.next.ServeHTTP(w, r)
}

func (b *basic) unauthorization(w http.ResponseWriter) {
	w.Header().Set("WWW-Authenticate", b.realm)
	http.Error(w, http.StatusText(http.StatusUnauthorized), http.StatusUnauthorized)
}
<commit_msg>添加 proxy 功能<commit_after>// Copyright 2018 by caixw, All rights reserved.
// Use of this source code is governed by a MIT
// license that can be found in the LICENSE file.

package auth

import (
	"encoding/base64"
	"net/http"
	"strings"
)

type basic struct {
	next   http.Handler
	secret string
	realm  string

	authorization string
	authenticate  string
}

// NewBasic 新的 Basic 验证方式
func NewBasic(next http.Handler, username, password, realm string, proxy bool) http.Handler {
	authorization := "Authorization"
	authenticate := "WWW-Authenticate"
	if proxy {
		authorization = "Proxy-Authorization"
		authenticate = "Proxy-Authenticate"
	}

	return &basic{
		next:   next,
		secret: base64.StdEncoding.EncodeToString([]byte(username + ":" + password)),
		realm:  `Basic realm="` + realm + `"`,

		authorization: authorization,
		authenticate:  authenticate,
	}
}

func (b *basic) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	auth := r.Header.Get(b.authorization)
	index := strings.IndexByte(auth, ' ')

	if index <= 0 {
		b.unauthorization(w)
		return
	}

	if "Basic" != auth[:index] {
		b.unauthorization(w)
		return
	}

	secret, err := base64.StdEncoding.DecodeString(auth[index+1:])
	if err != nil {
		// TODO
	}
	if string(secret) != b.secret {
		b.unauthorization(w)
		return
	}

	b.next.ServeHTTP(w, r)
}

func (b *basic) unauthorization(w http.ResponseWriter) {
	w.Header().Set(b.authenticate, b.realm)
	http.Error(w, http.StatusText(http.StatusUnauthorized), http.StatusUnauthorized)
}
<|endoftext|>