<commit_before>package log

// Logger is the minimal interface for logging methods
type Logger interface {
	Log(keyvals ...interface{})
}

// Disableable is an optional interface that a logger can implement to signal it is disabled and should not
// be sent log messages for optimization reasons
type Disableable interface {
	Disabled() bool
}

// ErrorHandler can handle errors that various loggers may return
type ErrorHandler interface {
	ErrorLogger(error) Logger
}

// ErrorHandlingLogger wraps Logger and ErrorHandler
type ErrorHandlingLogger interface {
	Logger
	ErrorHandler
}

// ErrorHandlingDisableableLogger wraps Logger and ErrorHandler and Disabled
type ErrorHandlingDisableableLogger interface {
	Logger
	ErrorHandler
	Disableable
}

// ErrorHandlerFunc converts a function into a ErrorHandler
type ErrorHandlerFunc func(error) Logger

// ErrorLogger calls the wrapped function
func (f ErrorHandlerFunc) ErrorLogger(e error) Logger {
	return f(e)
}

// Context allows users to create a logger that appends key/values to log statements.  Note that a nil Context is ok to
// use and works generally as expected, allowing optional logging in default struct{} objects.
type Context struct {
	Logger  Logger
	KeyVals []interface{}
}

// NewContext creates a context out of a logger
func NewContext(logger Logger) *Context {
	if logger == nil {
		return nil
	}
	if c, ok := logger.(*Context); ok {
		return c
	}
	ctx := &Context{
		Logger: logger,
	}
	return ctx
}

// IsDisabled returns true if the wrapped logger implements Disableable (or is nil).  Will signal that it's not worth
// sending a logger messages.
func IsDisabled(l Logger) bool {
	if l == nil {
		return true
	}
	if disable, ok := l.(Disableable); ok && disable.Disabled() {
		return true
	}
	return false
}

// addArrays will add two arrays.  Note that we CANNOT append(a, b...) because that will use the extra
// capacity of a and if two groutines call this at the same time they will race with each other.
func addArrays(a, b []interface{}) []interface{} {
	if len(a) == 0 && len(b) == 0 {
		return []interface{}{}
	}
	n := len(a) + len(b)
	ret := make([]interface{}, 0, n)
	ret = append(ret, a...)
	ret = append(ret, b...)
	return ret
}

// Log calls Log() on the wrapped logger appending the Context's values
func (l *Context) Log(keyvals ...interface{}) {
	// Note: The assumption here is that copyIfDynamic is "slow" since dynamic values
	//       could be slow to calculate.  So to optimize the case of "logs are turned off"
	//       we enable the ability to early return if the logger is off.
	if l == nil || IsDisabled(l.Logger) {
		return
	}
	l.Logger.Log(copyIfDynamic(addArrays(l.KeyVals, keyvals))...)
}

// Disabled returns true if the wrapped logger is disabled
func (l *Context) Disabled() bool {
	return l == nil || IsDisabled(l.Logger)
}

// With returns a new context that adds key/values to log statements
func (l *Context) With(keyvals ...interface{}) *Context {
	if len(keyvals)%2 != 0 {
		panic("Programmer error.  Please call log.Context.With() only with an even number of arguments.")
	}
	if len(keyvals) == 0 || l == nil {
		return l
	}
	return &Context{
		Logger:  l.Logger,
		KeyVals: addArrays(l.KeyVals, keyvals),
	}
}

// WithPrefix is like With but adds keyvalus to the beginning of the eventual log statement
func (l *Context) WithPrefix(keyvals ...interface{}) *Context {
	if len(keyvals)%2 != 0 {
		panic("Programmer error.  Please call log.Context.WithPrefix() only with an even number of arguments.")
	}
	if len(keyvals) == 0 || l == nil {
		return l
	}
	return &Context{
		Logger:  l.Logger,
		KeyVals: addArrays(keyvals, l.KeyVals),
	}
}

// LoggerFunc converts a function into a Logger
type LoggerFunc func(...interface{})

// Log calls the wrapped function
func (f LoggerFunc) Log(keyvals ...interface{}) {
	f(keyvals...)
}

// IfErr is a shorthand that will log an error if err is not nil
func IfErr(l Logger, err error) {
	if err != nil {
		if logCtx := NewContext(l); logCtx != nil && !IsDisabled(logCtx) {
			logCtx.Logger.Log(addArrays(copyIfDynamic(logCtx.KeyVals), []interface{}{err})...)
		}
	}
}

// IfErrAndReturn is a shorthand that will log an error if err is not nil and returns the original err
func IfErrAndReturn(l Logger, err error) error {
	if err != nil {
		if logCtx := NewContext(l); logCtx != nil && !IsDisabled(logCtx) {
			logCtx.Logger.Log(addArrays(copyIfDynamic(logCtx.KeyVals), []interface{}{err})...)
		}
	}
	return err
}

// IfErrWithKeys logs an error with the supplied logger if it is not nil.
// The error will be appended to the end of the supplied keys/messages
func IfErrWithKeys(l Logger, err error, intf ...interface{}) {
	if err != nil {
		if logCtx := NewContext(l); logCtx != nil && !IsDisabled(logCtx) {
			logCtx.Logger.Log(addArrays(copyIfDynamic(logCtx.KeyVals), addArrays(intf, []interface{}{err}))...)
		}
	}
}

// IfErrWithKeysAndReturn logs an error with the supplied logger if it is not nil and then returns the original error.
// The error will be appended to the end of the supplied keys/messages
func IfErrWithKeysAndReturn(l Logger, err error, intf ...interface{}) error {
	if err != nil {
		if logCtx := NewContext(l); logCtx != nil && !IsDisabled(logCtx) {
			logCtx.Logger.Log(addArrays(copyIfDynamic(logCtx.KeyVals), addArrays(intf, []interface{}{err}))...)
		}
	}
	return err
}
<commit_msg>Revert "make log.IfErr (and friends) fetch the dynamic keys so log.Caller is correct (#159)" (#161)<commit_after>package log

// Logger is the minimal interface for logging methods
type Logger interface {
	Log(keyvals ...interface{})
}

// Disableable is an optional interface that a logger can implement to signal it is disabled and should not
// be sent log messages for optimization reasons
type Disableable interface {
	Disabled() bool
}

// ErrorHandler can handle errors that various loggers may return
type ErrorHandler interface {
	ErrorLogger(error) Logger
}

// ErrorHandlingLogger wraps Logger and ErrorHandler
type ErrorHandlingLogger interface {
	Logger
	ErrorHandler
}

// ErrorHandlingDisableableLogger wraps Logger and ErrorHandler and Disabled
type ErrorHandlingDisableableLogger interface {
	Logger
	ErrorHandler
	Disableable
}

// ErrorHandlerFunc converts a function into a ErrorHandler
type ErrorHandlerFunc func(error) Logger

// ErrorLogger calls the wrapped function
func (f ErrorHandlerFunc) ErrorLogger(e error) Logger {
	return f(e)
}

// Context allows users to create a logger that appends key/values to log statements.  Note that a nil Context is ok to
// use and works generally as expected, allowing optional logging in default struct{} objects.
type Context struct {
	Logger  Logger
	KeyVals []interface{}
}

// NewContext creates a context out of a logger
func NewContext(logger Logger) *Context {
	if logger == nil {
		return nil
	}
	if c, ok := logger.(*Context); ok {
		return c
	}
	ctx := &Context{
		Logger: logger,
	}
	return ctx
}

// IsDisabled returns true if the wrapped logger implements Disableable (or is nil).  Will signal that it's not worth
// sending a logger messages.
func IsDisabled(l Logger) bool {
	if l == nil {
		return true
	}
	if disable, ok := l.(Disableable); ok && disable.Disabled() {
		return true
	}
	return false
}

// addArrays will add two arrays.  Note that we CANNOT append(a, b...) because that will use the extra
// capacity of a and if two groutines call this at the same time they will race with each other.
func addArrays(a, b []interface{}) []interface{} {
	if len(a) == 0 && len(b) == 0 {
		return []interface{}{}
	}
	n := len(a) + len(b)
	ret := make([]interface{}, 0, n)
	ret = append(ret, a...)
	ret = append(ret, b...)
	return ret
}

// Log calls Log() on the wrapped logger appending the Context's values
func (l *Context) Log(keyvals ...interface{}) {
	// Note: The assumption here is that copyIfDynamic is "slow" since dynamic values
	//       could be slow to calculate.  So to optimize the case of "logs are turned off"
	//       we enable the ability to early return if the logger is off.
	if l == nil || IsDisabled(l.Logger) {
		return
	}
	l.Logger.Log(copyIfDynamic(addArrays(l.KeyVals, keyvals))...)
}

// Disabled returns true if the wrapped logger is disabled
func (l *Context) Disabled() bool {
	return l == nil || IsDisabled(l.Logger)
}

// With returns a new context that adds key/values to log statements
func (l *Context) With(keyvals ...interface{}) *Context {
	if len(keyvals)%2 != 0 {
		panic("Programmer error.  Please call log.Context.With() only with an even number of arguments.")
	}
	if len(keyvals) == 0 || l == nil {
		return l
	}
	return &Context{
		Logger:  l.Logger,
		KeyVals: addArrays(l.KeyVals, keyvals),
	}
}

// WithPrefix is like With but adds keyvalus to the beginning of the eventual log statement
func (l *Context) WithPrefix(keyvals ...interface{}) *Context {
	if len(keyvals)%2 != 0 {
		panic("Programmer error.  Please call log.Context.WithPrefix() only with an even number of arguments.")
	}
	if len(keyvals) == 0 || l == nil {
		return l
	}
	return &Context{
		Logger:  l.Logger,
		KeyVals: addArrays(keyvals, l.KeyVals),
	}
}

// LoggerFunc converts a function into a Logger
type LoggerFunc func(...interface{})

// Log calls the wrapped function
func (f LoggerFunc) Log(keyvals ...interface{}) {
	f(keyvals...)
}

// IfErr is a shorthand that will log an error if err is not nil
func IfErr(l Logger, err error) {
	if err != nil {
		l.Log(Err, err)
	}
}

// IfErrAndReturn is a shorthand that will log an error if err is not nil and returns the original err
func IfErrAndReturn(l Logger, err error) error {
	if err != nil {
		l.Log(Err, err)
	}
	return err
}

// IfErrWithKeys logs an error with the supplied logger if it is not nil.
// The error will be appended to the end of the supplied keys/messages
func IfErrWithKeys(l Logger, err error, intf ...interface{}) {
	if err != nil && l != nil {
		l.Log(append(intf, err)...)
	}
}

// IfErrWithKeysAndReturn logs an error with the supplied logger if it is not nil and then returns the original error.
// The error will be appended to the end of the supplied keys/messages
func IfErrWithKeysAndReturn(l Logger, err error, intf ...interface{}) error {
	if err != nil && l != nil {
		l.Log(append(intf, err)...)
	}
	return err
}
<|endoftext|>


<commit_before>// Copyright 2014 mqant Author. 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.

// Package log 日志初始化
package log

import (
	beegolog "github.com/liangdas/mqant/log/beego"
	"github.com/liangdas/mqant/utils"
)

var beego *beegolog.BeeLogger
var bi *beegolog.BeeLogger

// InitLog 初始化日志
func InitLog(debug bool, ProcessID string, Logdir string, settings map[string]interface{}) {
	beego = NewBeegoLogger(debug, ProcessID, Logdir, settings)
}

// InitBI 初始化BI日志
func InitBI(debug bool, ProcessID string, Logdir string, settings map[string]interface{}) {
	bi = NewBeegoLogger(debug, ProcessID, Logdir, settings)
}

// LogBeego LogBeego
func LogBeego() *beegolog.BeeLogger {
	if beego == nil {
		beego = beegolog.NewLogger()
	}
	return beego
}

// BiBeego BiBeego
func BiBeego() *beegolog.BeeLogger {
	return bi
}

// CreateRootTrace CreateRootTrace
func CreateRootTrace() TraceSpan {
	return &TraceSpanImp{
		Trace: mqanttools.GenerateID().String(),
		Span:  mqanttools.GenerateID().String(),
	}
}

// CreateTrace CreateTrace
func CreateTrace(trace, span string) TraceSpan {
	return &TraceSpanImp{
		Trace: trace,
		Span:  span,
	}
}

// BiReport BiReport
func BiReport(msg string) {
	//gLogger.doPrintf(debugLevel, printDebugLevel, format, a...)
	l := BiBeego()
	if l != nil {
		l.BiReport(msg)
	}
}

// Debug Debug
func Debug(format string, a ...interface{}) {
	//gLogger.doPrintf(debugLevel, printDebugLevel, format, a...)
	logBeego().Debug(nil, format, a...)
}

// Info Info
func Info(format string, a ...interface{}) {
	//gLogger.doPrintf(releaseLevel, printReleaseLevel, format, a...)
	logBeego().Info(nil, format, a...)
}

// Error Error
func Error(format string, a ...interface{}) {
	//gLogger.doPrintf(errorLevel, printErrorLevel, format, a...)
	logBeego().Error(nil, format, a...)
}

// Warning Warning
func Warning(format string, a ...interface{}) {
	//gLogger.doPrintf(fatalLevel, printFatalLevel, format, a...)
	logBeego().Warning(nil, format, a...)
}

// TDebug TDebug
func TDebug(span TraceSpan, format string, a ...interface{}) {
	if span != nil {
		logBeego().Debug(
			&beegolog.BeegoTraceSpan{
				Trace: span.TraceId(),
				Span:  span.SpanId(),
			}, format, a...)
	} else {
		logBeego().Debug(nil, format, a...)
	}
}

// TInfo TInfo
func TInfo(span TraceSpan, format string, a ...interface{}) {
	if span != nil {
		logBeego().Info(
			&beegolog.BeegoTraceSpan{
				Trace: span.TraceId(),
				Span:  span.SpanId(),
			}, format, a...)
	} else {
		logBeego().Info(nil, format, a...)
	}
}

// TError TError
func TError(span TraceSpan, format string, a ...interface{}) {
	if span != nil {
		logBeego().Error(
			&beegolog.BeegoTraceSpan{
				Trace: span.TraceId(),
				Span:  span.SpanId(),
			}, format, a...)
	} else {
		logBeego().Error(nil, format, a...)
	}
}

// TWarning TWarning
func TWarning(span TraceSpan, format string, a ...interface{}) {
	if span != nil {
		logBeego().Warning(
			&beegolog.BeegoTraceSpan{
				Trace: span.TraceId(),
				Span:  span.SpanId(),
			}, format, a...)
	} else {
		logBeego().Warning(nil, format, a...)
	}
}

// Close Close
func Close() {
	logBeego().Close()
}
<commit_msg>=fix beego<commit_after>// Copyright 2014 mqant Author. 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.

// Package log 日志初始化
package log

import (
	beegolog "github.com/liangdas/mqant/log/beego"
	"github.com/liangdas/mqant/utils"
)

var beego *beegolog.BeeLogger
var bi *beegolog.BeeLogger

// InitLog 初始化日志
func InitLog(debug bool, ProcessID string, Logdir string, settings map[string]interface{}) {
	beego = NewBeegoLogger(debug, ProcessID, Logdir, settings)
}

// InitBI 初始化BI日志
func InitBI(debug bool, ProcessID string, Logdir string, settings map[string]interface{}) {
	bi = NewBeegoLogger(debug, ProcessID, Logdir, settings)
}

// LogBeego LogBeego
func LogBeego() *beegolog.BeeLogger {
	if beego == nil {
		beego = beegolog.NewLogger()
	}
	return beego
}

// BiBeego BiBeego
func BiBeego() *beegolog.BeeLogger {
	return bi
}

// CreateRootTrace CreateRootTrace
func CreateRootTrace() TraceSpan {
	return &TraceSpanImp{
		Trace: mqanttools.GenerateID().String(),
		Span:  mqanttools.GenerateID().String(),
	}
}

// CreateTrace CreateTrace
func CreateTrace(trace, span string) TraceSpan {
	return &TraceSpanImp{
		Trace: trace,
		Span:  span,
	}
}

// BiReport BiReport
func BiReport(msg string) {
	//gLogger.doPrintf(debugLevel, printDebugLevel, format, a...)
	l := BiBeego()
	if l != nil {
		l.BiReport(msg)
	}
}

// Debug Debug
func Debug(format string, a ...interface{}) {
	//gLogger.doPrintf(debugLevel, printDebugLevel, format, a...)
	LogBeego().Debug(nil, format, a...)
}

// Info Info
func Info(format string, a ...interface{}) {
	//gLogger.doPrintf(releaseLevel, printReleaseLevel, format, a...)
	LogBeego().Info(nil, format, a...)
}

// Error Error
func Error(format string, a ...interface{}) {
	//gLogger.doPrintf(errorLevel, printErrorLevel, format, a...)
	LogBeego().Error(nil, format, a...)
}

// Warning Warning
func Warning(format string, a ...interface{}) {
	//gLogger.doPrintf(fatalLevel, printFatalLevel, format, a...)
	LogBeego().Warning(nil, format, a...)
}

// TDebug TDebug
func TDebug(span TraceSpan, format string, a ...interface{}) {
	if span != nil {
		LogBeego().Debug(
			&beegolog.BeegoTraceSpan{
				Trace: span.TraceId(),
				Span:  span.SpanId(),
			}, format, a...)
	} else {
		LogBeego().Debug(nil, format, a...)
	}
}

// TInfo TInfo
func TInfo(span TraceSpan, format string, a ...interface{}) {
	if span != nil {
		LogBeego().Info(
			&beegolog.BeegoTraceSpan{
				Trace: span.TraceId(),
				Span:  span.SpanId(),
			}, format, a...)
	} else {
		LogBeego().Info(nil, format, a...)
	}
}

// TError TError
func TError(span TraceSpan, format string, a ...interface{}) {
	if span != nil {
		LogBeego().Error(
			&beegolog.BeegoTraceSpan{
				Trace: span.TraceId(),
				Span:  span.SpanId(),
			}, format, a...)
	} else {
		LogBeego().Error(nil, format, a...)
	}
}

// TWarning TWarning
func TWarning(span TraceSpan, format string, a ...interface{}) {
	if span != nil {
		LogBeego().Warning(
			&beegolog.BeegoTraceSpan{
				Trace: span.TraceId(),
				Span:  span.SpanId(),
			}, format, a...)
	} else {
		LogBeego().Warning(nil, format, a...)
	}
}

// Close Close
func Close() {
	LogBeego().Close()
}
<|endoftext|>


<commit_before>// Copyright 2017 Gruppe 12 IS-105. All rights reserved.
// diffie hellman key exchange implementation in golang
package Crypt

import (
	"math/big"
	"math/rand"
)

var P, G *big.Int

// a
func Randomkey() *big.Int {
	n := new(big.Int)
	tmp := make([]byte, 8)
	for i := 0; i < 8; i++ {
		tmp[i] = byte(rand.Intn(256))
	}
	return n.SetBytes(tmp)
}

// G**a mod p
func DHExchange(key *big.Int) *big.Int {
	n := new(big.Int)
	return n.Exp(G, key, P)
}

// exchange**a mod p
func DHSecret(key, exchange *big.Int) *big.Int {
	n := new(big.Int)
	return n.Exp(exchange, key, P)
}

func init() {
	P = new(big.Int)
	P.SetString("FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE65381FFFFFFFFFFFFFFFF", 16)
	G = new(big.Int)
	G.SetInt64(2)
}
<commit_msg>Update dhexchange.go<commit_after>// diffie hellman key exchange implementation in golang
package Crypt

import (
	"math/big"
	"math/rand"
)

var P, G *big.Int

// a
func Randomkey() *big.Int {
	n := new(big.Int)
	tmp := make([]byte, 8)
	for i := 0; i < 8; i++ {
		tmp[i] = byte(rand.Intn(256))
	}
	return n.SetBytes(tmp)
}

// G**a mod p
func DHExchange(key *big.Int) *big.Int {
	n := new(big.Int)
	return n.Exp(G, key, P)
}

// exchange**a mod p
func DHSecret(key, exchange *big.Int) *big.Int {
	n := new(big.Int)
	return n.Exp(exchange, key, P)
}

func init() {
	P = new(big.Int)
	P.SetString("FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE65381FFFFFFFFFFFFFFFF", 16)
	G = new(big.Int)
	G.SetInt64(2)
}
<|endoftext|>


<commit_before>///bin/true; exec /usr/bin/env go run "$0" "$@"

package main

import (
	"flag"
	"fmt"
	"github.com/omakoto/mlib"
	"log"
	"os/exec"
	"regexp"
	"strconv"
	"strings"
	"time"
)

var (
	// Patterns to extract PIDs from logs.
	pidPatterns = []*regexp.Regexp{
		// brief
		regexp.MustCompile(`^[A-Z]/.+?\(\s*(\d+)`),
		// process or thread
		regexp.MustCompile(`^[A-Z]\(\s*(\d+)`),
		// uid
		regexp.MustCompile(`^\d{2}-\d{2}\s+[\d\:\.]+\s+\d+\s+(\d+)\s+\d`),
		// threadtime
		regexp.MustCompile(`^\d{2}-\d{2}\s+[\d\:\.]+\s+(\d+)`),
		// time
		regexp.MustCompile(`^\d{2}-\d{2} [\d\:\.]+ [A-Z]\/.*?\(\s*(\d+)`),
		// regexp.MustCompile(`^.*?\(\s*(\d+)`),
		// long
		regexp.MustCompile(`^\[\s*\d{2}-\d{2}\s+[\d\:\.]+\s+(\d+)`),
	}

	// Patterns to extract PIDs for process deaths logs.
	diePatterns = []*regexp.Regexp{
		regexp.MustCompile(`ActivityManager.*?Process .*?\(pid (\d+)\) has died`),
		regexp.MustCompile(`ActivityManager.*?Killing (\d+)`),
		// Any more?
	}

	whiteSpaces = regexp.MustCompile(`\s+`)

	// Flags
	width = flag.Int("w", 40, "formatting width")
	// autoflush = flag.Bool("f", false, "autoflush") // Stdout seems like always flushing

	// Output line format
	outFormat string

	// Process info cache.
	procecces = make(map[int]processInfo)

	cacheExpiration = time.Minute * 10
)

const (
	PRE_INITIALIZED                       = "<pre-initialized>"
	MAX_PRE_INITIALIZED_RETRY             = 5
	MAX_PRE_INITIALIZED_RETRY_INTERVAL_MS = 200
)

type processInfo struct {
	name       string
	expiration time.Time
}

func getProcessNameFromAdbRaw(pid int) string {
	cmd := exec.Command("adb", "shell", fmt.Sprintf("cat /proc/%d/cmdline 2>/dev/null", pid))
	out, err := cmd.Output()
	if err != nil {
		return "(not found)"
	}

	procname := string(out)
	procname = strings.TrimRight(procname, "\000")
	procname = strings.Replace(procname, "\000", " ", -1)
	return procname
}

// Same as getProcessNameFromAdbRaw, but retries when getting PRE_INITIALIZED
func getProcessNameFromAdb(pid int) string {
	var pname string = "(unknown)"

	mlib.Debug("Getting process name for %d\n", pid)

	for i := 0; i <= MAX_PRE_INITIALIZED_RETRY; i++ {
		rawName := getProcessNameFromAdbRaw(pid)
		if rawName == PRE_INITIALIZED {
			mlib.Debug("%s detected\n", PRE_INITIALIZED)
			time.Sleep(MAX_PRE_INITIALIZED_RETRY_INTERVAL_MS * time.Millisecond)
			continue
		}
		if rawName != "" {
			pname = rawName
		}
		break
	}
	return fmt.Sprintf("%s %d", pname, pid)
}

func getProcessNameWithCache(pid int) string {
	now := time.Now()
	pinfo, ok := procecces[pid]
	if !ok || now.After(pinfo.expiration) {
		name := getProcessNameFromAdb(pid)
		pinfo = processInfo{name: name, expiration: now.Add(cacheExpiration)}
		procecces[pid] = pinfo
	}
	return pinfo.name
}

// Run for each line
func processLine(line string) {
	var pid = 0
	var processName = "(pid not found)"

	// Find the pid from the line and get the process name
	for _, re := range pidPatterns {
		s := re.FindStringSubmatch(line)
		if s != nil {
			pid, _ = strconv.Atoi(s[1])
			processName = getProcessNameWithCache(pid)
			break
		}
	}

	// Any process died?
	for _, re := range diePatterns {
		s := re.FindStringSubmatch(line)
		if s != nil {
			diedPid, _ := strconv.Atoi(s[1])
			log.Printf("Process %d died\n", diedPid)
			delete(procecces, diedPid)
			break
		}
	}

	fmt.Printf(outFormat, processName, line)
}

func main() {
	log.SetPrefix("logcatp: ")
	log.SetFlags(0)
	flag.Parse()

	outFormat = fmt.Sprintf("[%%-%ds] %%s", *width)

	for line := range mlib.ReadFilesFromArgs() {
		processLine(line)
	}
}
<commit_msg>update<commit_after>///bin/true; exec /usr/bin/env go run "$0" "$@"

package main

import (
	"flag"
	"fmt"
	"github.com/omakoto/mlib"
	"log"
	"os/exec"
	"regexp"
	"strconv"
	"strings"
	"time"
)

var (
	// Patterns to extract PIDs from logs.
	pidPatterns = []*regexp.Regexp{
		// uid
		regexp.MustCompile(`^\d{2}-\d{2}\s+[\d\:\.]+\s+[a-zA-Z_0-9]+\s+(\d+)\s+\d`),
		// threadtime
		regexp.MustCompile(`^\d{2}-\d{2}\s+[\d\:\.]+\s+(\d+)`),
		// brief
		regexp.MustCompile(`^[A-Z]/.+?\(\s*(\d+)`),
		// process or thread
		regexp.MustCompile(`^[A-Z]\(\s*(\d+)`),
		// time
		regexp.MustCompile(`^\d{2}-\d{2} [\d\:\.]+ [A-Z]\/.*?\(\s*(\d+)`),
		// regexp.MustCompile(`^.*?\(\s*(\d+)`),
		// long
		regexp.MustCompile(`^\[\s*\d{2}-\d{2}\s+[\d\:\.]+\s+(\d+)`),
	}

	// Patterns to extract PIDs for process deaths logs.
	diePatterns = []*regexp.Regexp{
		regexp.MustCompile(`ActivityManager.*?Process .*?\(pid (\d+)\) has died`),
		regexp.MustCompile(`ActivityManager.*?Killing (\d+)`),
		// Any more?
	}

	whiteSpaces = regexp.MustCompile(`\s+`)

	// Flags
	width = flag.Int("w", 40, "formatting width")
	// autoflush = flag.Bool("f", false, "autoflush") // Stdout seems like always flushing

	// Output line format
	outFormat string

	// Process info cache.
	procecces = make(map[int]processInfo)

	cacheExpiration = time.Minute * 10
)

const (
	PRE_INITIALIZED                       = "<pre-initialized>"
	MAX_PRE_INITIALIZED_RETRY             = 5
	MAX_PRE_INITIALIZED_RETRY_INTERVAL_MS = 200
)

type processInfo struct {
	name       string
	expiration time.Time
}

func getProcessNameFromAdbRaw(pid int) string {
	cmd := exec.Command("adb", "shell", fmt.Sprintf("cat /proc/%d/cmdline 2>/dev/null", pid))
	out, err := cmd.Output()
	if err != nil {
		return "(not found)"
	}

	procname := string(out)
	procname = strings.TrimRight(procname, "\000")
	procname = strings.Replace(procname, "\000", " ", -1)
	return procname
}

// Same as getProcessNameFromAdbRaw, but retries when getting PRE_INITIALIZED
func getProcessNameFromAdb(pid int) string {
	var pname string = "(unknown)"

	mlib.Debug("Getting process name for %d\n", pid)

	for i := 0; i <= MAX_PRE_INITIALIZED_RETRY; i++ {
		rawName := getProcessNameFromAdbRaw(pid)
		if rawName == PRE_INITIALIZED {
			mlib.Debug("%s detected\n", PRE_INITIALIZED)
			time.Sleep(MAX_PRE_INITIALIZED_RETRY_INTERVAL_MS * time.Millisecond)
			continue
		}
		if rawName != "" {
			pname = rawName
		}
		break
	}
	return fmt.Sprintf("%s %d", pname, pid)
}

func getProcessNameWithCache(pid int) string {
	now := time.Now()
	pinfo, ok := procecces[pid]
	if !ok || now.After(pinfo.expiration) {
		name := getProcessNameFromAdb(pid)
		pinfo = processInfo{name: name, expiration: now.Add(cacheExpiration)}
		procecces[pid] = pinfo
	}
	return pinfo.name
}

// Run for each line
func processLine(line string) {
	var pid = 0
	var processName = "(pid not found)"

	// Find the pid from the line and get the process name
	for _, re := range pidPatterns {
		s := re.FindStringSubmatch(line)
		if s != nil {
			pid, _ = strconv.Atoi(s[1])
			processName = getProcessNameWithCache(pid)
			break
		}
	}

	// Any process died?
	for _, re := range diePatterns {
		s := re.FindStringSubmatch(line)
		if s != nil {
			diedPid, _ := strconv.Atoi(s[1])
			log.Printf("Process %d died\n", diedPid)
			delete(procecces, diedPid)
			break
		}
	}

	fmt.Printf(outFormat, processName, line)
}

func main() {
	log.SetPrefix("logcatp: ")
	log.SetFlags(0)
	flag.Parse()

	outFormat = fmt.Sprintf("[%%-%ds] %%s", *width)

	for line := range mlib.ReadFilesFromArgs() {
		processLine(line)
	}
}
<|endoftext|>


<commit_before>package accesslog

import (
	"fmt"
	"log"
	"net/http"
	//"os"
	"strings"
	"time"
)

// Logger defines needed interfaces
// One can use any logger with this interface
type Logger interface {
	Info(m string)
}

type LoggerFunc func(m string)

func (f LoggerFunc) Info(m string) {
	f(m)
}

func WrapPrint(fn func(v ...interface{})) Logger {
	return LoggerFunc(func(m string) {
		fn(m)
	})
}

func WrapSyslog(fn func(m string) (err error)) Logger {
	return LoggerFunc(func(m string) {
		fn(m)
	})
}

type Log struct {
	Logger Logger
}

// Wrap ResponseWriter for determination of status and content length
type LogResponseWriter struct {
	http.ResponseWriter
	status        int
	writtenLength int
}

func (lrw *LogResponseWriter) WriteHeader(status int) {
	lrw.status = status
	lrw.ResponseWriter.WriteHeader(status)
}

func (lrw *LogResponseWriter) Write(b []byte) (int, error) {
	written, err := lrw.ResponseWriter.Write(b)
	lrw.writtenLength += written
	return written, err
}

func New() *Log {
	l := &Log{
		Logger: WrapPrint(log.Print),
	}
	return l
}

func (l *Log) logging(rw *LogResponseWriter, r *http.Request) {
	endTime := time.Now()
	userAgent := r.UserAgent()
	referer := r.Referer()
	if referer == "" {
		referer = "-"
	}
	if userAgent == "" {
		userAgent = "-"
	}

	ip := strings.Split(r.RemoteAddr, ":")[0]

	// IP user-identifier user-id [datetime] "method url protocol_version" status length "referer" "user-agent"
	const format = "%s - - [%s] \"%s %s %s\" %d %d \"%s\" \"%s\""
	// "%d/%b/%Y:%H:%M:%S %z"
	const layout = "2/Jan/2006:15:04:05 -0700"
	l.Logger.Info(fmt.Sprintf(format,
		ip,
		endTime.Format(layout),
		r.Method,
		r.URL.String(),
		r.Proto,
		rw.status,
		rw.writtenLength,
		referer,
		userAgent))
}

// Middleware implementing fun(next http.Handler) http.Handler
//
// router := r2router.NewSeeforRouter()
// logger := accesslog.New()
// router.Before(logger.Handler)
func (l *Log) Handler(next http.Handler) http.Handler {
	return http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
		lwr := &LogResponseWriter{rw, 0, 0}
		defer l.logging(lwr, r)
		next.ServeHTTP(lwr, r)
	})
}

// Middleware implementing func(rw http.ResponseWriter, r *http.Request, next http.HandlerFunc)
//
// n := negroni.New()
// logger := accesslog.New()
// n.UseFunc(logger.HandlerFuncWithNext)
func (l *Log) HandlerFuncWithNext(rw http.ResponseWriter, r *http.Request, next http.HandlerFunc) {
	lwr := &LogResponseWriter{rw, 0, 0}
	defer l.logging(lwr, r)
	next(lwr, r)
}
<commit_msg>Adding docstr<commit_after>package accesslog

import (
	"fmt"
	"log"
	"net/http"
	"strings"
	"time"
)

// Logger defines needed interfaces
// One can use any logger with this interface
type Logger interface {
	Info(m string)
}

// Turn any logging function with this interface into Logger
type LoggerFunc func(m string)

func (f LoggerFunc) Info(m string) {
	f(m)
}

// Wrap Print function of log.Logger or any similar function
func WrapPrint(fn func(v ...interface{})) Logger {
	return LoggerFunc(func(m string) {
		fn(m)
	})
}

// Wrap any syslog.Writer function or any similar function
func WrapSyslog(fn func(m string) (err error)) Logger {
	return LoggerFunc(func(m string) {
		fn(m)
	})
}

type Log struct {
	Logger Logger
}

// Wrap ResponseWriter for determination of status and content length
type LogResponseWriter struct {
	http.ResponseWriter
	status        int
	writtenLength int
}

func (lrw *LogResponseWriter) WriteHeader(status int) {
	lrw.status = status
	lrw.ResponseWriter.WriteHeader(status)
}

func (lrw *LogResponseWriter) Write(b []byte) (int, error) {
	written, err := lrw.ResponseWriter.Write(b)
	lrw.writtenLength += written
	return written, err
}

func New() *Log {
	l := &Log{
		Logger: WrapPrint(log.Print),
	}
	return l
}

func (l *Log) logging(rw *LogResponseWriter, r *http.Request) {
	endTime := time.Now()
	userAgent := r.UserAgent()
	referer := r.Referer()
	if referer == "" {
		referer = "-"
	}
	if userAgent == "" {
		userAgent = "-"
	}

	ip := strings.Split(r.RemoteAddr, ":")[0]

	// IP user-identifier user-id [datetime] "method url protocol_version" status length "referer" "user-agent"
	const format = "%s - - [%s] \"%s %s %s\" %d %d \"%s\" \"%s\""
	// "%d/%b/%Y:%H:%M:%S %z"
	const layout = "2/Jan/2006:15:04:05 -0700"
	l.Logger.Info(fmt.Sprintf(format,
		ip,
		endTime.Format(layout),
		r.Method,
		r.URL.String(),
		r.Proto,
		rw.status,
		rw.writtenLength,
		referer,
		userAgent))
}

// Middleware implementing fun(next http.Handler) http.Handler
//
// router := r2router.NewSeeforRouter()
// logger := accesslog.New()
// router.Before(logger.Handler)
func (l *Log) Handler(next http.Handler) http.Handler {
	return http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
		lwr := &LogResponseWriter{rw, 0, 0}
		defer l.logging(lwr, r)
		next.ServeHTTP(lwr, r)
	})
}

// Middleware implementing func(rw http.ResponseWriter, r *http.Request, next http.HandlerFunc)
//
// n := negroni.New()
// logger := accesslog.New()
// n.UseFunc(logger.HandlerFuncWithNext)
func (l *Log) HandlerFuncWithNext(rw http.ResponseWriter, r *http.Request, next http.HandlerFunc) {
	lwr := &LogResponseWriter{rw, 0, 0}
	defer l.logging(lwr, r)
	next(lwr, r)
}
<|endoftext|>


<commit_before>package httpx

import (
	"github.com/gin-gonic/gin"
	"go.uber.org/zap"
)

func LogKeyHTTPContext(c *gin.Context,field ...zap.Field) []zap.Field{
	baseFileds :=  []zap.Field{zap.String("http_client_ip",c.ClientIP()),zap.String("http_method",c.Request.Method),zap.String("http_path",c.Request.URL.Path)}
	if len(field)>0{
		return append(field,baseFileds...)
	}
	return baseFileds
}
<commit_msg>2020-02-03 v1<commit_after>package httpx

import (
	"github.com/gin-gonic/gin"
	"go.uber.org/zap"
)

func LogKeyHTTPContext(c *gin.Context,field ...zap.Field) []zap.Field{
	baseFileds :=  []zap.Field{zap.Int("statusCode",c.Writer.Status()),zap.String("http_client_ip",c.ClientIP()),zap.String("http_method",c.Request.Method),zap.String("http_path",c.Request.URL.Path)}
	if len(field)>0{
		return append(field,baseFileds...)
	}
	return baseFileds
}
<|endoftext|>


<commit_before>package tsa

import (
	"crypto/rsa"
	"time"

	"github.com/dgrijalva/jwt-go"
)

//go:generate counterfeiter . TokenGenerator
type TokenGenerator interface {
	GenerateToken() (string, error)
}

type tokenGenerator struct {
	signingKey *rsa.PrivateKey
}

func NewTokenGenerator(signingKey *rsa.PrivateKey) TokenGenerator {
	return &tokenGenerator{signingKey: signingKey}
}

func (tk *tokenGenerator) GenerateToken() (string, error) {
	jwtToken := jwt.New(jwt.SigningMethodRS256)
	exp := time.Now().Add(time.Hour)
	jwtToken.Claims["exp"] = exp.Unix()
	jwtToken.Claims["system"] = true
	signedToken, err := jwtToken.SignedString(tk.signingKey)
	return signedToken, err
}
<commit_msg>updates for jwt claims interface<commit_after>package tsa

import (
	"crypto/rsa"
	"time"

	"github.com/dgrijalva/jwt-go"
)

//go:generate counterfeiter . TokenGenerator
type TokenGenerator interface {
	GenerateToken() (string, error)
}

type tokenGenerator struct {
	signingKey *rsa.PrivateKey
}

func NewTokenGenerator(signingKey *rsa.PrivateKey) TokenGenerator {
	return &tokenGenerator{signingKey: signingKey}
}

func (tk *tokenGenerator) GenerateToken() (string, error) {
	exp := time.Now().Add(time.Hour)
	jwtToken := jwt.NewWithClaims(jwt.SigningMethodRS256, jwt.MapClaims{
		"exp":    exp.Unix(),
		"system": true,
	})

	return jwtToken.SignedString(tk.signingKey)
}
<|endoftext|>


<commit_before>package weed_server

import (
	"context"
	"io"
	"mime"
	"mime/multipart"
	"net/http"
	"net/url"
	"path"
	"strconv"
	"strings"

	"github.com/chrislusf/seaweedfs/weed/filer2"
	"github.com/chrislusf/seaweedfs/weed/glog"
	"github.com/chrislusf/seaweedfs/weed/util"
)

func (fs *FilerServer) GetOrHeadHandler(w http.ResponseWriter, r *http.Request, isGetMethod bool) {
	path := r.URL.Path
	if strings.HasSuffix(path, "/") && len(path) > 1 {
		path = path[:len(path)-1]
	}

	entry, err := fs.filer.FindEntry(context.Background(), filer2.FullPath(path))
	if err != nil {
		if path == "/" {
			fs.listDirectoryHandler(w, r)
			return
		}
		glog.V(1).Infof("Not found %s: %v", path, err)
		w.WriteHeader(http.StatusNotFound)
		return
	}

	if entry.IsDirectory() {
		if fs.option.DisableDirListing {
			w.WriteHeader(http.StatusMethodNotAllowed)
			return
		}
		fs.listDirectoryHandler(w, r)
		return
	}

	if len(entry.Chunks) == 0 {
		glog.V(1).Infof("no file chunks for %s, attr=%+v", path, entry.Attr)
		w.WriteHeader(http.StatusNoContent)
		return
	}

	w.Header().Set("Accept-Ranges", "bytes")
	if r.Method == "HEAD" {
		w.Header().Set("Content-Length", strconv.FormatInt(int64(filer2.TotalSize(entry.Chunks)), 10))
		w.Header().Set("Last-Modified", entry.Attr.Mtime.Format(http.TimeFormat))
		setEtag(w, filer2.ETag(entry.Chunks))
		return
	}

	if len(entry.Chunks) == 1 {
		fs.handleSingleChunk(w, r, entry)
		return
	}

	fs.handleMultipleChunks(w, r, entry)

}

func (fs *FilerServer) handleSingleChunk(w http.ResponseWriter, r *http.Request, entry *filer2.Entry) {

	fileId := entry.Chunks[0].FileId

	urlString, err := fs.filer.MasterClient.LookupFileId(fileId)
	if err != nil {
		glog.V(1).Infof("operation LookupFileId %s failed, err: %v", fileId, err)
		w.WriteHeader(http.StatusNotFound)
		return
	}

	if fs.option.RedirectOnRead {
		http.Redirect(w, r, urlString, http.StatusFound)
		return
	}

	u, _ := url.Parse(urlString)
	q := u.Query()
	for key, values := range r.URL.Query() {
		for _, value := range values {
			q.Add(key, value)
		}
	}
	u.RawQuery = q.Encode()
	request := &http.Request{
		Method:        r.Method,
		URL:           u,
		Proto:         r.Proto,
		ProtoMajor:    r.ProtoMajor,
		ProtoMinor:    r.ProtoMinor,
		Header:        r.Header,
		Body:          r.Body,
		Host:          r.Host,
		ContentLength: r.ContentLength,
	}
	glog.V(3).Infoln("retrieving from", u)
	resp, do_err := util.Do(request)
	if do_err != nil {
		glog.V(0).Infoln("failing to connect to volume server", do_err.Error())
		writeJsonError(w, r, http.StatusInternalServerError, do_err)
		return
	}
	defer resp.Body.Close()
	for k, v := range resp.Header {
		w.Header()[k] = v
	}
	w.WriteHeader(resp.StatusCode)
	io.Copy(w, resp.Body)
}

func (fs *FilerServer) handleMultipleChunks(w http.ResponseWriter, r *http.Request, entry *filer2.Entry) {

	mimeType := entry.Mime
	if mimeType == "" {
		if ext := path.Ext(entry.Name()); ext != "" {
			mimeType = mime.TypeByExtension(ext)
		}
	}
	if mimeType != "" {
		w.Header().Set("Content-Type", mimeType)
	}
	setEtag(w, filer2.ETag(entry.Chunks))

	totalSize := int64(filer2.TotalSize(entry.Chunks))

	rangeReq := r.Header.Get("Range")

	if rangeReq == "" {
		w.Header().Set("Content-Length", strconv.FormatInt(totalSize, 10))
		if err := fs.writeContent(w, entry, 0, int(totalSize)); err != nil {
			http.Error(w, err.Error(), http.StatusInternalServerError)
			return
		}
		return
	}

	//the rest is dealing with partial content request
	//mostly copy from src/pkg/net/http/fs.go
	ranges, err := parseRange(rangeReq, totalSize)
	if err != nil {
		http.Error(w, err.Error(), http.StatusRequestedRangeNotSatisfiable)
		return
	}
	if sumRangesSize(ranges) > totalSize {
		// The total number of bytes in all the ranges
		// is larger than the size of the file by
		// itself, so this is probably an attack, or a
		// dumb client.  Ignore the range request.
		return
	}
	if len(ranges) == 0 {
		return
	}
	if len(ranges) == 1 {
		// RFC 2616, Section 14.16:
		// "When an HTTP message includes the content of a single
		// range (for example, a response to a request for a
		// single range, or to a request for a set of ranges
		// that overlap without any holes), this content is
		// transmitted with a Content-Range header, and a
		// Content-Length header showing the number of bytes
		// actually transferred.
		// ...
		// A response to a request for a single range MUST NOT
		// be sent using the multipart/byteranges media type."
		ra := ranges[0]
		w.Header().Set("Content-Length", strconv.FormatInt(ra.length, 10))
		w.Header().Set("Content-Range", ra.contentRange(totalSize))
		w.WriteHeader(http.StatusPartialContent)

		err = fs.writeContent(w, entry, ra.start, int(ra.length))
		if err != nil {
			http.Error(w, err.Error(), http.StatusInternalServerError)
			return
		}
		return
	}

	// process multiple ranges
	for _, ra := range ranges {
		if ra.start > totalSize {
			http.Error(w, "Out of Range", http.StatusRequestedRangeNotSatisfiable)
			return
		}
	}
	sendSize := rangesMIMESize(ranges, mimeType, totalSize)
	pr, pw := io.Pipe()
	mw := multipart.NewWriter(pw)
	w.Header().Set("Content-Type", "multipart/byteranges; boundary="+mw.Boundary())
	sendContent := pr
	defer pr.Close() // cause writing goroutine to fail and exit if CopyN doesn't finish.
	go func() {
		for _, ra := range ranges {
			part, e := mw.CreatePart(ra.mimeHeader(mimeType, totalSize))
			if e != nil {
				pw.CloseWithError(e)
				return
			}
			if e = fs.writeContent(part, entry, ra.start, int(ra.length)); e != nil {
				pw.CloseWithError(e)
				return
			}
		}
		mw.Close()
		pw.Close()
	}()
	if w.Header().Get("Content-Encoding") == "" {
		w.Header().Set("Content-Length", strconv.FormatInt(sendSize, 10))
	}
	w.WriteHeader(http.StatusPartialContent)
	if _, err := io.CopyN(w, sendContent, sendSize); err != nil {
		http.Error(w, "Internal Error", http.StatusInternalServerError)
		return
	}

}

func (fs *FilerServer) writeContent(w io.Writer, entry *filer2.Entry, offset int64, size int) error {

	chunkViews := filer2.ViewFromChunks(entry.Chunks, offset, size)

	fileId2Url := make(map[string]string)

	for _, chunkView := range chunkViews {

		urlString, err := fs.filer.MasterClient.LookupFileId(chunkView.FileId)
		if err != nil {
			glog.V(1).Infof("operation LookupFileId %s failed, err: %v", chunkView.FileId, err)
			return err
		}
		fileId2Url[chunkView.FileId] = urlString
	}

	for _, chunkView := range chunkViews {
		urlString := fileId2Url[chunkView.FileId]
		_, err := util.ReadUrlAsStream(urlString, chunkView.Offset, int(chunkView.Size), func(data []byte) {
			w.Write(data)
		})
		if err != nil {
			glog.V(1).Infof("read %s failed, err: %v", chunkView.FileId, err)
			return err
		}
	}

	return nil

}
<commit_msg>weed filer: set content-type consistent with filer store<commit_after>package weed_server

import (
	"context"
	"io"
	"mime"
	"mime/multipart"
	"net/http"
	"net/url"
	"path"
	"strconv"
	"strings"

	"github.com/chrislusf/seaweedfs/weed/filer2"
	"github.com/chrislusf/seaweedfs/weed/glog"
	"github.com/chrislusf/seaweedfs/weed/util"
)

func (fs *FilerServer) GetOrHeadHandler(w http.ResponseWriter, r *http.Request, isGetMethod bool) {
	path := r.URL.Path
	if strings.HasSuffix(path, "/") && len(path) > 1 {
		path = path[:len(path)-1]
	}

	entry, err := fs.filer.FindEntry(context.Background(), filer2.FullPath(path))
	if err != nil {
		if path == "/" {
			fs.listDirectoryHandler(w, r)
			return
		}
		glog.V(1).Infof("Not found %s: %v", path, err)
		w.WriteHeader(http.StatusNotFound)
		return
	}

	if entry.IsDirectory() {
		if fs.option.DisableDirListing {
			w.WriteHeader(http.StatusMethodNotAllowed)
			return
		}
		fs.listDirectoryHandler(w, r)
		return
	}

	if len(entry.Chunks) == 0 {
		glog.V(1).Infof("no file chunks for %s, attr=%+v", path, entry.Attr)
		w.WriteHeader(http.StatusNoContent)
		return
	}

	w.Header().Set("Accept-Ranges", "bytes")
	if r.Method == "HEAD" {
		w.Header().Set("Content-Length", strconv.FormatInt(int64(filer2.TotalSize(entry.Chunks)), 10))
		w.Header().Set("Last-Modified", entry.Attr.Mtime.Format(http.TimeFormat))
		setEtag(w, filer2.ETag(entry.Chunks))
		return
	}

	if len(entry.Chunks) == 1 {
		fs.handleSingleChunk(w, r, entry)
		return
	}

	fs.handleMultipleChunks(w, r, entry)

}

func (fs *FilerServer) handleSingleChunk(w http.ResponseWriter, r *http.Request, entry *filer2.Entry) {

	fileId := entry.Chunks[0].FileId

	urlString, err := fs.filer.MasterClient.LookupFileId(fileId)
	if err != nil {
		glog.V(1).Infof("operation LookupFileId %s failed, err: %v", fileId, err)
		w.WriteHeader(http.StatusNotFound)
		return
	}

	if fs.option.RedirectOnRead {
		http.Redirect(w, r, urlString, http.StatusFound)
		return
	}

	u, _ := url.Parse(urlString)
	q := u.Query()
	for key, values := range r.URL.Query() {
		for _, value := range values {
			q.Add(key, value)
		}
	}
	u.RawQuery = q.Encode()
	request := &http.Request{
		Method:        r.Method,
		URL:           u,
		Proto:         r.Proto,
		ProtoMajor:    r.ProtoMajor,
		ProtoMinor:    r.ProtoMinor,
		Header:        r.Header,
		Body:          r.Body,
		Host:          r.Host,
		ContentLength: r.ContentLength,
	}
	glog.V(3).Infoln("retrieving from", u)
	resp, do_err := util.Do(request)
	if do_err != nil {
		glog.V(0).Infoln("failing to connect to volume server", do_err.Error())
		writeJsonError(w, r, http.StatusInternalServerError, do_err)
		return
	}
	defer resp.Body.Close()
	for k, v := range resp.Header {
		w.Header()[k] = v
	}
	if entry.Attr.Mime != "" {
		w.Header().Set("Content-Type", entry.Attr.Mime)
	}
	w.WriteHeader(resp.StatusCode)
	io.Copy(w, resp.Body)
}

func (fs *FilerServer) handleMultipleChunks(w http.ResponseWriter, r *http.Request, entry *filer2.Entry) {

	mimeType := entry.Attr.Mime
	if mimeType == "" {
		if ext := path.Ext(entry.Name()); ext != "" {
			mimeType = mime.TypeByExtension(ext)
		}
	}
	if mimeType != "" {
		w.Header().Set("Content-Type", mimeType)
	}
	setEtag(w, filer2.ETag(entry.Chunks))

	totalSize := int64(filer2.TotalSize(entry.Chunks))

	rangeReq := r.Header.Get("Range")

	if rangeReq == "" {
		w.Header().Set("Content-Length", strconv.FormatInt(totalSize, 10))
		if err := fs.writeContent(w, entry, 0, int(totalSize)); err != nil {
			http.Error(w, err.Error(), http.StatusInternalServerError)
			return
		}
		return
	}

	//the rest is dealing with partial content request
	//mostly copy from src/pkg/net/http/fs.go
	ranges, err := parseRange(rangeReq, totalSize)
	if err != nil {
		http.Error(w, err.Error(), http.StatusRequestedRangeNotSatisfiable)
		return
	}
	if sumRangesSize(ranges) > totalSize {
		// The total number of bytes in all the ranges
		// is larger than the size of the file by
		// itself, so this is probably an attack, or a
		// dumb client.  Ignore the range request.
		return
	}
	if len(ranges) == 0 {
		return
	}
	if len(ranges) == 1 {
		// RFC 2616, Section 14.16:
		// "When an HTTP message includes the content of a single
		// range (for example, a response to a request for a
		// single range, or to a request for a set of ranges
		// that overlap without any holes), this content is
		// transmitted with a Content-Range header, and a
		// Content-Length header showing the number of bytes
		// actually transferred.
		// ...
		// A response to a request for a single range MUST NOT
		// be sent using the multipart/byteranges media type."
		ra := ranges[0]
		w.Header().Set("Content-Length", strconv.FormatInt(ra.length, 10))
		w.Header().Set("Content-Range", ra.contentRange(totalSize))
		w.WriteHeader(http.StatusPartialContent)

		err = fs.writeContent(w, entry, ra.start, int(ra.length))
		if err != nil {
			http.Error(w, err.Error(), http.StatusInternalServerError)
			return
		}
		return
	}

	// process multiple ranges
	for _, ra := range ranges {
		if ra.start > totalSize {
			http.Error(w, "Out of Range", http.StatusRequestedRangeNotSatisfiable)
			return
		}
	}
	sendSize := rangesMIMESize(ranges, mimeType, totalSize)
	pr, pw := io.Pipe()
	mw := multipart.NewWriter(pw)
	w.Header().Set("Content-Type", "multipart/byteranges; boundary="+mw.Boundary())
	sendContent := pr
	defer pr.Close() // cause writing goroutine to fail and exit if CopyN doesn't finish.
	go func() {
		for _, ra := range ranges {
			part, e := mw.CreatePart(ra.mimeHeader(mimeType, totalSize))
			if e != nil {
				pw.CloseWithError(e)
				return
			}
			if e = fs.writeContent(part, entry, ra.start, int(ra.length)); e != nil {
				pw.CloseWithError(e)
				return
			}
		}
		mw.Close()
		pw.Close()
	}()
	if w.Header().Get("Content-Encoding") == "" {
		w.Header().Set("Content-Length", strconv.FormatInt(sendSize, 10))
	}
	w.WriteHeader(http.StatusPartialContent)
	if _, err := io.CopyN(w, sendContent, sendSize); err != nil {
		http.Error(w, "Internal Error", http.StatusInternalServerError)
		return
	}

}

func (fs *FilerServer) writeContent(w io.Writer, entry *filer2.Entry, offset int64, size int) error {

	chunkViews := filer2.ViewFromChunks(entry.Chunks, offset, size)

	fileId2Url := make(map[string]string)

	for _, chunkView := range chunkViews {

		urlString, err := fs.filer.MasterClient.LookupFileId(chunkView.FileId)
		if err != nil {
			glog.V(1).Infof("operation LookupFileId %s failed, err: %v", chunkView.FileId, err)
			return err
		}
		fileId2Url[chunkView.FileId] = urlString
	}

	for _, chunkView := range chunkViews {
		urlString := fileId2Url[chunkView.FileId]
		_, err := util.ReadUrlAsStream(urlString, chunkView.Offset, int(chunkView.Size), func(data []byte) {
			w.Write(data)
		})
		if err != nil {
			glog.V(1).Infof("read %s failed, err: %v", chunkView.FileId, err)
			return err
		}
	}

	return nil

}
<|endoftext|>


<commit_before>/*
Package sqlhooks Attach hooks to any database/sql driver.

The purpose of sqlhooks is to provide anway to instrument your sql statements,
making really easy to log queries or measure execution time without modifying your actual code.

Example:
	package main

	import (
		"database/sql"
		"log"
		"time"

		"github.com/gchaincl/sqlhooks"
		_ "github.com/mattn/go-sqlite3"
	)

	func main() {
		hooks := sqlhooks.Hooks{
			Exec: func(query string, args ...interface{}) func(error) {
				log.Printf("[exec] %s, args: %v", query, args)
				return nil
			},
			Query: func(query string, args ...interface{}) func(error) {
				t := time.Now()
				id := t.Nanosecond()
				log.Printf("[query#%d] %s, args: %v", id, query, args)

				// This will be executed when Query statements has completed
				return func(err error) {
					log.Printf("[query#%d] took: %s (err: %v)", id, time.Since(t), err)
				}
			},
		}

		// Register the driver
		// "sqlite-hooked" is the attached driver, and "sqlite3" is where we're attaching to
		sqlhooks.Register("sqlite-hooked", sqlhooks.NewDriver("sqlite3", &hooks))

		// Connect to attached driver
		db, _ := sql.Open("sqlite-hooked", ":memory:")

		// Do you're stuff
		db.Exec("CREATE TABLE t (id INTEGER, text VARCHAR(16))")
		db.Exec("INSERT into t (text) VALUES(?), (?))", "foo", "bar")
		db.Query("SELECT id, text FROM t")
		db.Query("Invalid Query")
	}

*/
package sqlhooks

import (
	"database/sql"
	"fmt"
	"time"
)

var (
	drivers = make(map[*Hooks]string)
)

// Open Register a sqlhook driver and opens a connection against it
// driverName is the driver where we're attaching to
func Open(driverName, dsn string, hooks *Hooks) (*sql.DB, error) {
	if registeredName, ok := drivers[hooks]; ok {
		return sql.Open(registeredName, dsn)
	}

	registeredName := fmt.Sprintf("sqlhooks:%d", time.Now().UnixNano())
	sql.Register(registeredName, NewDriver(driverName, hooks))
	drivers[hooks] = registeredName

	return sql.Open(registeredName, dsn)
}
<commit_msg>Update example, use Open instead of Register<commit_after>/*
Package sqlhooks Attach hooks to any database/sql driver.

The purpose of sqlhooks is to provide anway to instrument your sql statements,
making really easy to log queries or measure execution time without modifying your actual code.

Example:
	package main

	import (
		"database/sql"
		"log"
		"time"

		"github.com/gchaincl/sqlhooks"
		_ "github.com/mattn/go-sqlite3"
	)

	func main() {
		hooks := sqlhooks.Hooks{
			Exec: func(query string, args ...interface{}) func(error) {
				log.Printf("[exec] %s, args: %v", query, args)
				return nil
			},
			Query: func(query string, args ...interface{}) func(error) {
				t := time.Now()
				id := t.Nanosecond()
				log.Printf("[query#%d] %s, args: %v", id, query, args)

				// This will be executed when Query statements has completed
				return func(err error) {
					log.Printf("[query#%d] took: %s (err: %v)", id, time.Since(t), err)
				}
			},
		}

		// Register the driver
		// "sqlite-hooked" is the attached driver, and "sqlite3" is where we're attaching to
		sql.Register("sqlite-hooked", sqlhooks.NewDriver("sqlite3", &hooks))

		// Connect to attached driver
		db, _ := sql.Open("sqlite-hooked", ":memory:")

		// Do you're stuff
		db.Exec("CREATE TABLE t (id INTEGER, text VARCHAR(16))")
		db.Exec("INSERT into t (text) VALUES(?), (?))", "foo", "bar")
		db.Query("SELECT id, text FROM t")
		db.Query("Invalid Query")
	}

*/
package sqlhooks

import (
	"database/sql"
	"fmt"
	"time"
)

var (
	drivers = make(map[*Hooks]string)
)

// Open Register a sqlhook driver and opens a connection against it
// driverName is the driver where we're attaching to
func Open(driverName, dsn string, hooks *Hooks) (*sql.DB, error) {
	if registeredName, ok := drivers[hooks]; ok {
		return sql.Open(registeredName, dsn)
	}

	registeredName := fmt.Sprintf("sqlhooks:%d", time.Now().UnixNano())
	sql.Register(registeredName, NewDriver(driverName, hooks))
	drivers[hooks] = registeredName

	return sql.Open(registeredName, dsn)
}
<|endoftext|>


<commit_before>package airstrike

import (
	"fmt"
	"time"

	"github.com/Sirupsen/logrus"
	"github.com/dysolution/airstrike/ordnance"
	"github.com/dysolution/sleepwalker"
	"github.com/speps/go-hashids"
)

// A Squadron is a collection of Planes that will simultaneously begin
// deploying their weapons.
type Squadron struct {
	ID     string  `json:"id"`
	Planes []Plane `json:"planes"`
}

// NewSquadron assigns each new Squadron a unique ID and logs its creation.
func NewSquadron(logger *logrus.Logger) Squadron {
	log = logger
	hd := hashids.NewData()
	hd.Salt = "awakened salt"
	hd.MinLength = 4
	h := hashids.NewWithData(hd)
	id, _ := h.Encode([]int{8, 2, 5, int(time.Now().UnixNano())})

	log.WithFields(logrus.Fields{
		"id": id,
	}).Debug("airstrike.NewSquadron")

	return Squadron{id, []Plane{}}
}

// Add associates the provided Plane with the Squadron, logging its addition.
func (s *Squadron) Add(plane Plane) {
	s.Planes = append(s.Planes, plane)
	log.WithFields(logrus.Fields{
		"plane": plane.Name,
	}).Debug("airstrike.(*Squadron).Add")
}

// AddClones creates the specified number of Planes, each armed with the
// payload described, which can be one or more weapons.
func (s *Squadron) AddClones(clones int, client sleepwalker.RESTClient, armory ordnance.Armory, weapons ...string) {
	for i := 1; i <= clones; i++ {
		name := fmt.Sprintf("clone_%d_of_%d", i, clones)
		for _, weapon := range weapons {
			name = fmt.Sprintf("%s_%s", name, weapon)
		}
		plane := NewPlane(name, client)
		for _, weapon := range weapons {
			plane.Arm(armory.GetArsenal(weapon))
		}
		s.Add(plane)
	}
}

// AddChaos creates the specified number of Planes that each have their own
// random selection of n weapons, quantified by their "deadliness."
func (s *Squadron) AddChaos(clones int, deadliness int, client sleepwalker.RESTClient, armory ordnance.Armory) {
	desc := "AddChaos"
	for i := 1; i <= clones; i++ {
		name := fmt.Sprintf("chaos_%d_of_%d", i, clones)
		plane := NewPlane(name, client)

		weaponNames := armory.GetRandomWeaponNames(deadliness)
		var arsenal ordnance.Arsenal
		for _, weaponName := range weaponNames {
			log.WithFields(logrus.Fields{
				"plane":  name,
				"weapon": weaponName,
				"msg":    "adding weapon",
			}).Debug(desc)
			arsenal = append(arsenal, armory.GetWeapon(weaponName))
		}
		plane.Arm(arsenal)
		s.Add(plane)
	}
}
<commit_msg>fix: properly arm multiple-weapon Clones<commit_after>package airstrike

import (
	"fmt"
	"time"

	"github.com/Sirupsen/logrus"
	"github.com/dysolution/airstrike/ordnance"
	"github.com/dysolution/sleepwalker"
	"github.com/speps/go-hashids"
)

// A Squadron is a collection of Planes that will simultaneously begin
// deploying their weapons.
type Squadron struct {
	ID     string  `json:"id"`
	Planes []Plane `json:"planes"`
}

// NewSquadron assigns each new Squadron a unique ID and logs its creation.
func NewSquadron(logger *logrus.Logger) Squadron {
	log = logger
	hd := hashids.NewData()
	hd.Salt = "awakened salt"
	hd.MinLength = 4
	h := hashids.NewWithData(hd)
	id, _ := h.Encode([]int{8, 2, 5, int(time.Now().UnixNano())})

	log.WithFields(logrus.Fields{
		"id": id,
	}).Debug("airstrike.NewSquadron")

	return Squadron{id, []Plane{}}
}

// Add associates the provided Plane with the Squadron, logging its addition.
func (s *Squadron) Add(plane Plane) {
	s.Planes = append(s.Planes, plane)
	log.WithFields(logrus.Fields{
		"plane": plane.Name,
	}).Debug("airstrike.(*Squadron).Add")
}

// AddClones creates the specified number of Planes, each armed with the
// payload described, which can be one or more weapons.
func (s *Squadron) AddClones(clones int, client sleepwalker.RESTClient, armory ordnance.Armory, weaponNames ...string) {
	for i := 1; i <= clones; i++ {
		var arsenal ordnance.Arsenal
		name := fmt.Sprintf("clone_%d_of_%d", i, clones)
		for _, weapon := range weaponNames {
			name = fmt.Sprintf("%s_%s", name, weapon)
			arsenal = append(arsenal, armory.GetWeapon(weapon))
		}
		plane := NewPlane(name, client)
		plane.Arm(arsenal)
		s.Add(plane)
	}
}

// AddChaos creates the specified number of Planes that each have their own
// random selection of n weapons, quantified by their "deadliness."
func (s *Squadron) AddChaos(clones int, deadliness int, client sleepwalker.RESTClient, armory ordnance.Armory) {
	desc := "AddChaos"
	for i := 1; i <= clones; i++ {
		name := fmt.Sprintf("chaos_%d_of_%d", i, clones)
		plane := NewPlane(name, client)

		weaponNames := armory.GetRandomWeaponNames(deadliness)
		var arsenal ordnance.Arsenal
		for _, weaponName := range weaponNames {
			log.WithFields(logrus.Fields{
				"plane":  name,
				"weapon": weaponName,
				"msg":    "adding weapon",
			}).Debug(desc)
			arsenal = append(arsenal, armory.GetWeapon(weaponName))
		}
		plane.Arm(arsenal)
		s.Add(plane)
	}
}
<|endoftext|>


<commit_before>/*package los computes line of sight densities oriented in rings around a point.
*/
package los

import (
	"math"
)

// ProfileRing is a ring of uniformly spaced profiles. The reported profiles are
// the average densities at each radial bin in the profile.
//
// The saved format of the profiles is not neccessarily the same as the output
// format of the profiles, so they must be accessed with the Retreive method.
type ProfileRing struct {
	derivs []float64 // Contiguous block of pofile data. Column-major.
	Lines []geom
	bins int // Length of an individual profile.
	n int // Number of Profiles.
	lowR, highR, dr float64
}

// Init initializes a profile ring made up of n profiles each of which consist
// of the given number of radial bins and extend between the two specified
// radii.
func (p *ProfileRing) Init(lowR, highR float64, bins, n int) {
	p.derivs = make([]float64, bins * n)
	p.bins = bins
	p.n = n
	p.lowR = lowR
	p.highR = highR

	p.Lines = make([]geom.Line, n)
	for i := 0; i < n; i++ {
		sin, cos := math.Sincos(p.Angle(i))
		p.Lines[i].Init(0, 0, )
	}
}

// Insert inserts a plateau with the given radial extent and density to the
// profile.
func (p *ProfileRing) Insert(start, end rho float64, i int) {
	if end < p.lowR || start > p.highR {
		return
	}

	// You could be a bit more careful with floating point ops here.
	if start > p.lowR {
		idx, rem := Math.Modf((start - p.lowR) / dr)
		p.derivs[i*p.n + idx] += rho * rem
		if idx < p.depth - 1 {
			p.derivs[idx*p.n + idx+1] += rho * (1 - rem)
		}
	} else {
		p.derivs[0] += rho
	}

	if end < p.highR {
		idx, rem := Math.Modf((end - p.lowR) / dr)
		p.derivs[i*p.n + idx] -= rho * (1 - rem)
		if idx < p.depth - 1 {
			p.derivs[idx*p.n + idx+1] -= rho * rem
		}
	}
}

// Retrieve does any neccessary post-processing on the specified profile and
// writes in to an out buffer.
func (p *ProfileRing) Retrieve(i int, out []float64) {
	sum := 0
	for j := 0; j < p.depth; j++ {
		sum += p.derivs[i + p.N*j]
		out[j] = sum
	}
}

// Angle returns the angle that the line with the specified index points in.
func (p *ProfileRing) Angle(i int) float64 {
	return math.Pi * 2 * float64(n) / float64(p.n)
}
<commit_msg>Fixed compiler errors in los.go that I miraculously missed last time before I committed.<commit_after>/*package los computes line of sight densities oriented in rings around a point.
*/
package los

import (
	"math"
	"github.com/phil-mansfield/gotetra/los/geom"
)

// ProfileRing is a ring of uniformly spaced profiles. The reported profiles are
// the average densities at each radial bin in the profile.
//
// The saved format of the profiles is not neccessarily the same as the output
// format of the profiles, so they must be accessed with the Retreive method.
type ProfileRing struct {
	derivs []float64 // Contiguous block of pofile data. Column-major.
	Lines []geom.Line
	bins int // Length of an individual profile.
	n int // Number of Profiles.
	lowR, highR, dr float64
}

// Init initializes a profile ring made up of n profiles each of which consist
// of the given number of radial bins and extend between the two specified
// radii.
func (p *ProfileRing) Init(lowR, highR float64, bins, n int) {
	p.derivs = make([]float64, bins * n)
	p.bins = bins
	p.n = n
	p.lowR = lowR
	p.highR = highR

	p.Lines = make([]geom.Line, n)
	for i := 0; i < n; i++ {
		sin, cos := math.Sincos(p.Angle(i))
		p.Lines[i].Init(0, 0, float32(cos), float32(sin))
	}
}

// Insert inserts a plateau with the given radial extent and density to the
// profile.
func (p *ProfileRing) Insert(start, end, rho float64, i int) {
	if end < p.lowR || start > p.highR {
		return
	}

	// You could be a bit more careful with floating point ops here.
	if start > p.lowR {
		fidx, rem := math.Modf((start - p.lowR) / p.dr)
		idx := int(fidx)
		p.derivs[i*p.n + idx] += rho * rem
		if idx < p.bins - 1 {
			p.derivs[idx*p.n + idx+1] += rho * (1 - rem)
		}
	} else {
		p.derivs[0] += rho
	}

	if end < p.highR {
		fidx, rem := math.Modf((end - p.lowR) / p.dr)
		idx := int(fidx)
		p.derivs[i*p.n + idx] -= rho * (1 - rem)
		if idx < p.bins - 1 {
			p.derivs[idx*p.n + idx+1] -= rho * rem
		}
	}
}

// Retrieve does any neccessary post-processing on the specified profile and
// writes in to an out buffer.
func (p *ProfileRing) Retrieve(i int, out []float64) {
	sum := float64(0)
	for j := 0; j < p.bins; j++ {
		sum += p.derivs[i + p.n*j]
		out[j] = sum
	}
}

// Angle returns the angle that the line with the specified index points in.
func (p *ProfileRing) Angle(i int) float64 {
	return math.Pi * 2 * float64(i) / float64(p.n)
}
<|endoftext|>


<commit_before>package coremain

// Various CoreDNS constants.
const (
	CoreVersion = "1.2.4"
	coreName    = "CoreDNS"
	serverType  = "dns"
)
<commit_msg>Bump version 1.2.5 (#2235)<commit_after>package coremain

// Various CoreDNS constants.
const (
	CoreVersion = "1.2.5"
	coreName    = "CoreDNS"
	serverType  = "dns"
)
<|endoftext|>


<commit_before>// Copyright 2015 ThoughtWorks, Inc.

// This file is part of Gauge.

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

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

// You should have received a copy of the GNU General Public License
// along with Gauge.  If not, see <http://www.gnu.org/licenses/>.

package execution

import (
	"fmt"
	"path"
	"strconv"
	"strings"
	"sync"
	"time"

	"os"

	"github.com/getgauge/common"
	"github.com/getgauge/gauge/config"
	"github.com/getgauge/gauge/conn"
	"github.com/getgauge/gauge/execution/event"
	"github.com/getgauge/gauge/execution/result"
	"github.com/getgauge/gauge/filter"
	"github.com/getgauge/gauge/gauge"
	"github.com/getgauge/gauge/gauge_messages"
	"github.com/getgauge/gauge/logger"
	"github.com/getgauge/gauge/manifest"
	"github.com/getgauge/gauge/plugin"
	"github.com/getgauge/gauge/reporter"
	"github.com/getgauge/gauge/runner"
	"github.com/getgauge/gauge/util"
)

var Strategy string

// Eager is a parallelization strategy for execution. In this case tests are distributed before execution, thus making them an equal number based distribution.
const Eager string = "eager"

// Lazy is a parallelization strategy for execution. In this case tests assignment will be dynamic during execution, i.e. assign the next spec in line to the stream that has completed it’s previous execution and is waiting for more work.
const Lazy string = "lazy"
const enableMultithreadingEnv = "enable_multithreading"

type parallelExecution struct {
	wg                       sync.WaitGroup
	manifest                 *manifest.Manifest
	specCollection           *gauge.SpecCollection
	pluginHandler            plugin.Handler
	currentExecutionInfo     *gauge_messages.ExecutionInfo
	runner                   runner.Runner
	suiteResult              *result.SuiteResult
	numberOfExecutionStreams int
	errMaps                  *gauge.BuildErrors
	startTime                time.Time
}

func newParallelExecution(e *executionInfo) *parallelExecution {
	return &parallelExecution{
		manifest:                 e.manifest,
		specCollection:           e.specs,
		runner:                   e.runner,
		pluginHandler:            e.pluginHandler,
		numberOfExecutionStreams: e.numberOfStreams,
		errMaps:                  e.errMaps,
	}
}

type streamExecError struct {
	specsSkipped []string
	message      string
}

func (s streamExecError) Error() string {
	var specNames string
	for _, spec := range s.specsSkipped {
		specNames += fmt.Sprintf("%s\n", spec)
	}
	return fmt.Sprintf("The following specifications could not be executed:\n%sReason : %s.", specNames, s.message)
}

func (e *parallelExecution) numberOfStreams() int {
	nStreams := e.numberOfExecutionStreams
	size := e.specCollection.Size()
	if nStreams > size {
		nStreams = size
	}
	return nStreams
}

func (e *parallelExecution) start() {
	e.startTime = time.Now()
	event.Notify(event.NewExecutionEvent(event.SuiteStart, nil, nil, 0, gauge_messages.ExecutionInfo{}))
	e.pluginHandler = plugin.StartPlugins(e.manifest)
}

func (e *parallelExecution) run() *result.SuiteResult {
	e.start()

	nStreams := e.numberOfStreams()
	logger.Infof(true, "Executing in %s parallel streams.", strconv.Itoa(nStreams))

	resChan := make(chan *result.SuiteResult)
	if e.isMultithreaded() {
		logger.Debugf(true, "Using multithreading for parallel execution.")
		go e.executeMultithreaded(nStreams, resChan)
	} else if isLazy() {
		go e.executeLazily(nStreams, resChan)
	} else {
		go e.executeEagerly(nStreams, resChan)
	}

	var res []*result.SuiteResult
	for r := range resChan {
		res = append(res, r)
	}
	e.aggregateResults(res)

	e.finish()
	return e.suiteResult
}

func (e *parallelExecution) executeLazily(totalStreams int, resChan chan *result.SuiteResult) {
	e.wg.Add(totalStreams)
	for i := 0; i < totalStreams; i++ {
		go e.startStream(e.specCollection, resChan, i+1)
	}
	e.wg.Wait()
	close(resChan)
}

func (e *parallelExecution) executeMultithreaded(totalStreams int, resChan chan *result.SuiteResult) {
	e.wg.Add(totalStreams)
	handlers := make([]*conn.GaugeConnectionHandler, 0)
	var ports []string
	for i := 0; i < totalStreams; i++ {
		port, err := conn.GetPortFromEnvironmentVariable(common.GaugePortEnvName)
		if err != nil {
			port = 0
		}
		handler, err := conn.NewGaugeConnectionHandler(port, nil)
		if err != nil {
			fmt.Println(err)
		}
		ports = append(ports, strconv.Itoa(handler.ConnectionPortNumber()))
		handlers = append(handlers, handler)
	}
	os.Setenv("GAUGE_API_PORTS", strings.Join(ports, ","))
	r, err := runner.StartRunner(e.manifest, "0", reporter.ParallelReporter(0), make(chan bool), false)
	if err != nil {
		fmt.Println(err)
		return
	}
	for i := 0; i < totalStreams; i++ {
		connection, err := handlers[i].AcceptConnection(config.RunnerConnectionTimeout(), make(chan error))
		if err != nil {
			fmt.Println(err)
		}
		crapRunner := &runner.MultithreadedRunner{}
		crapRunner.SetConnection(connection)
		go e.startMultithreaded(crapRunner, resChan, i+1)
	}
	e.wg.Wait()
	r.Cmd.Process.Kill()
	close(resChan)
}

func (e *parallelExecution) startMultithreaded(r runner.Runner, resChan chan *result.SuiteResult, stream int) {
	defer e.wg.Done()
	e.startSpecsExecutionWithRunner(e.specCollection, resChan, r, stream)
}

func (e *parallelExecution) executeEagerly(distributions int, resChan chan *result.SuiteResult) {
	specs := filter.DistributeSpecs(e.specCollection.Specs(), distributions)
	e.wg.Add(distributions)
	for i, s := range specs {
		go e.startSpecsExecution(s, resChan, i+1)
	}
	e.wg.Wait()
	close(resChan)
}

func (e *parallelExecution) startStream(s *gauge.SpecCollection, resChan chan *result.SuiteResult, stream int) {
	defer e.wg.Done()
	os.Setenv("GAUGE_CUSTOM_BUILD_PATH", path.Join(os.Getenv("GAUGE_PROJECT_ROOT"), "gauge-bin"))
	runner, err := runner.Start(e.manifest, reporter.ParallelReporter(stream), make(chan bool), false)
	if err != nil {
		logger.Errorf(true, "Failed to start runner. %s", err.Error())
		resChan <- &result.SuiteResult{UnhandledErrors: []error{fmt.Errorf("Failed to start runner. %s", err.Error())}}
		return
	}
	e.startSpecsExecutionWithRunner(s, resChan, runner, stream)
}

func (e *parallelExecution) startSpecsExecution(s *gauge.SpecCollection, resChan chan *result.SuiteResult, stream int) {
	defer e.wg.Done()
	os.Setenv("GAUGE_CUSTOM_BUILD_PATH", path.Join(os.Getenv("GAUGE_PROJECT_ROOT"), "gauge-bin"))
	runner, err := runner.Start(e.manifest, reporter.ParallelReporter(stream), make(chan bool), false)
	if err != nil {
		logger.Errorf(true, "Failed to start runner. %s", err.Error())
		logger.Debugf(true, "Skipping %d specifications", s.Size())
		resChan <- &result.SuiteResult{UnhandledErrors: []error{streamExecError{specsSkipped: s.SpecNames(), message: fmt.Sprintf("Failed to start runner. %s", err.Error())}}}
		return
	}
	e.startSpecsExecutionWithRunner(s, resChan, runner, stream)
}

func (e *parallelExecution) startSpecsExecutionWithRunner(s *gauge.SpecCollection, resChan chan *result.SuiteResult, runner runner.Runner, stream int) {
	executionInfo := newExecutionInfo(s, runner, e.pluginHandler, e.errMaps, false, stream)
	se := newSimpleExecution(executionInfo, false)
	se.execute()
	runner.Kill()
	resChan <- se.suiteResult
}

func (e *parallelExecution) finish() {
	e.suiteResult = mergeDataTableSpecResults(e.suiteResult)
	event.Notify(event.NewExecutionEvent(event.SuiteEnd, nil, e.suiteResult, 0, gauge_messages.ExecutionInfo{}))
	message := &gauge_messages.Message{
		MessageType: gauge_messages.Message_SuiteExecutionResult,
		SuiteExecutionResult: &gauge_messages.SuiteExecutionResult{
			SuiteResult: gauge.ConvertToProtoSuiteResult(e.suiteResult),
		},
	}
	e.pluginHandler.NotifyPlugins(message)
	e.pluginHandler.GracefullyKillPlugins()
}

func (e *parallelExecution) aggregateResults(suiteResults []*result.SuiteResult) {
	r := result.NewSuiteResult(ExecuteTags, e.startTime)
	for _, result := range suiteResults {
		r.SpecsFailedCount += result.SpecsFailedCount
		r.SpecResults = append(r.SpecResults, result.SpecResults...)
		if result.IsFailed {
			r.IsFailed = true
		}
		if result.PreSuite != nil {
			r.PreSuite = result.PreSuite
		}
		if result.PostSuite != nil {
			r.PostSuite = result.PostSuite
		}
		if result.UnhandledErrors != nil {
			r.UnhandledErrors = append(r.UnhandledErrors, result.UnhandledErrors...)
		}
	}
	r.ExecutionTime = int64(time.Since(e.startTime) / 1e6)
	e.suiteResult = r
	e.suiteResult.SetSpecsSkippedCount()
}

func isLazy() bool {
	return strings.ToLower(Strategy) == Lazy
}

func isValidStrategy(strategy string) bool {
	strategy = strings.ToLower(strategy)
	return strategy == Lazy || strategy == Eager
}

func (e *parallelExecution) isMultithreaded() bool {
	value := util.ConvertToBool(os.Getenv(enableMultithreadingEnv), enableMultithreadingEnv, false)
	if !value {
		return false
	}
	if !e.runner.IsMultithreaded() {
		logger.Warningf(true, "Runner doesn't support mutithreading, using multiprocess parallel execution.")
		return false
	}
	return true
}
<commit_msg>use gauge_bin instead of gauge-bin, #980<commit_after>// Copyright 2015 ThoughtWorks, Inc.

// This file is part of Gauge.

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

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

// You should have received a copy of the GNU General Public License
// along with Gauge.  If not, see <http://www.gnu.org/licenses/>.

package execution

import (
	"fmt"
	"path"
	"strconv"
	"strings"
	"sync"
	"time"

	"os"

	"github.com/getgauge/common"
	"github.com/getgauge/gauge/config"
	"github.com/getgauge/gauge/conn"
	"github.com/getgauge/gauge/execution/event"
	"github.com/getgauge/gauge/execution/result"
	"github.com/getgauge/gauge/filter"
	"github.com/getgauge/gauge/gauge"
	"github.com/getgauge/gauge/gauge_messages"
	"github.com/getgauge/gauge/logger"
	"github.com/getgauge/gauge/manifest"
	"github.com/getgauge/gauge/plugin"
	"github.com/getgauge/gauge/reporter"
	"github.com/getgauge/gauge/runner"
	"github.com/getgauge/gauge/util"
)

var Strategy string

// Eager is a parallelization strategy for execution. In this case tests are distributed before execution, thus making them an equal number based distribution.
const Eager string = "eager"

// Lazy is a parallelization strategy for execution. In this case tests assignment will be dynamic during execution, i.e. assign the next spec in line to the stream that has completed it’s previous execution and is waiting for more work.
const Lazy string = "lazy"
const enableMultithreadingEnv = "enable_multithreading"

type parallelExecution struct {
	wg                       sync.WaitGroup
	manifest                 *manifest.Manifest
	specCollection           *gauge.SpecCollection
	pluginHandler            plugin.Handler
	currentExecutionInfo     *gauge_messages.ExecutionInfo
	runner                   runner.Runner
	suiteResult              *result.SuiteResult
	numberOfExecutionStreams int
	errMaps                  *gauge.BuildErrors
	startTime                time.Time
}

func newParallelExecution(e *executionInfo) *parallelExecution {
	return &parallelExecution{
		manifest:                 e.manifest,
		specCollection:           e.specs,
		runner:                   e.runner,
		pluginHandler:            e.pluginHandler,
		numberOfExecutionStreams: e.numberOfStreams,
		errMaps:                  e.errMaps,
	}
}

type streamExecError struct {
	specsSkipped []string
	message      string
}

func (s streamExecError) Error() string {
	var specNames string
	for _, spec := range s.specsSkipped {
		specNames += fmt.Sprintf("%s\n", spec)
	}
	return fmt.Sprintf("The following specifications could not be executed:\n%sReason : %s.", specNames, s.message)
}

func (e *parallelExecution) numberOfStreams() int {
	nStreams := e.numberOfExecutionStreams
	size := e.specCollection.Size()
	if nStreams > size {
		nStreams = size
	}
	return nStreams
}

func (e *parallelExecution) start() {
	e.startTime = time.Now()
	event.Notify(event.NewExecutionEvent(event.SuiteStart, nil, nil, 0, gauge_messages.ExecutionInfo{}))
	e.pluginHandler = plugin.StartPlugins(e.manifest)
}

func (e *parallelExecution) run() *result.SuiteResult {
	e.start()

	nStreams := e.numberOfStreams()
	logger.Infof(true, "Executing in %s parallel streams.", strconv.Itoa(nStreams))

	resChan := make(chan *result.SuiteResult)
	if e.isMultithreaded() {
		logger.Debugf(true, "Using multithreading for parallel execution.")
		go e.executeMultithreaded(nStreams, resChan)
	} else if isLazy() {
		go e.executeLazily(nStreams, resChan)
	} else {
		go e.executeEagerly(nStreams, resChan)
	}

	var res []*result.SuiteResult
	for r := range resChan {
		res = append(res, r)
	}
	e.aggregateResults(res)

	e.finish()
	return e.suiteResult
}

func (e *parallelExecution) executeLazily(totalStreams int, resChan chan *result.SuiteResult) {
	e.wg.Add(totalStreams)
	for i := 0; i < totalStreams; i++ {
		go e.startStream(e.specCollection, resChan, i+1)
	}
	e.wg.Wait()
	close(resChan)
}

func (e *parallelExecution) executeMultithreaded(totalStreams int, resChan chan *result.SuiteResult) {
	e.wg.Add(totalStreams)
	handlers := make([]*conn.GaugeConnectionHandler, 0)
	var ports []string
	for i := 0; i < totalStreams; i++ {
		port, err := conn.GetPortFromEnvironmentVariable(common.GaugePortEnvName)
		if err != nil {
			port = 0
		}
		handler, err := conn.NewGaugeConnectionHandler(port, nil)
		if err != nil {
			fmt.Println(err)
		}
		ports = append(ports, strconv.Itoa(handler.ConnectionPortNumber()))
		handlers = append(handlers, handler)
	}
	os.Setenv("GAUGE_API_PORTS", strings.Join(ports, ","))
	r, err := runner.StartRunner(e.manifest, "0", reporter.ParallelReporter(0), make(chan bool), false)
	if err != nil {
		fmt.Println(err)
		return
	}
	for i := 0; i < totalStreams; i++ {
		connection, err := handlers[i].AcceptConnection(config.RunnerConnectionTimeout(), make(chan error))
		if err != nil {
			fmt.Println(err)
		}
		crapRunner := &runner.MultithreadedRunner{}
		crapRunner.SetConnection(connection)
		go e.startMultithreaded(crapRunner, resChan, i+1)
	}
	e.wg.Wait()
	r.Cmd.Process.Kill()
	close(resChan)
}

func (e *parallelExecution) startMultithreaded(r runner.Runner, resChan chan *result.SuiteResult, stream int) {
	defer e.wg.Done()
	e.startSpecsExecutionWithRunner(e.specCollection, resChan, r, stream)
}

func (e *parallelExecution) executeEagerly(distributions int, resChan chan *result.SuiteResult) {
	specs := filter.DistributeSpecs(e.specCollection.Specs(), distributions)
	e.wg.Add(distributions)
	for i, s := range specs {
		go e.startSpecsExecution(s, resChan, i+1)
	}
	e.wg.Wait()
	close(resChan)
}

func (e *parallelExecution) startStream(s *gauge.SpecCollection, resChan chan *result.SuiteResult, stream int) {
	defer e.wg.Done()
	os.Setenv("GAUGE_CUSTOM_BUILD_PATH", path.Join(os.Getenv("GAUGE_PROJECT_ROOT"), "gauge_bin"))
	runner, err := runner.Start(e.manifest, reporter.ParallelReporter(stream), make(chan bool), false)
	if err != nil {
		logger.Errorf(true, "Failed to start runner. %s", err.Error())
		resChan <- &result.SuiteResult{UnhandledErrors: []error{fmt.Errorf("Failed to start runner. %s", err.Error())}}
		return
	}
	e.startSpecsExecutionWithRunner(s, resChan, runner, stream)
}

func (e *parallelExecution) startSpecsExecution(s *gauge.SpecCollection, resChan chan *result.SuiteResult, stream int) {
	defer e.wg.Done()
	os.Setenv("GAUGE_CUSTOM_BUILD_PATH", path.Join(os.Getenv("GAUGE_PROJECT_ROOT"), "gauge_bin"))
	runner, err := runner.Start(e.manifest, reporter.ParallelReporter(stream), make(chan bool), false)
	if err != nil {
		logger.Errorf(true, "Failed to start runner. %s", err.Error())
		logger.Debugf(true, "Skipping %d specifications", s.Size())
		resChan <- &result.SuiteResult{UnhandledErrors: []error{streamExecError{specsSkipped: s.SpecNames(), message: fmt.Sprintf("Failed to start runner. %s", err.Error())}}}
		return
	}
	e.startSpecsExecutionWithRunner(s, resChan, runner, stream)
}

func (e *parallelExecution) startSpecsExecutionWithRunner(s *gauge.SpecCollection, resChan chan *result.SuiteResult, runner runner.Runner, stream int) {
	executionInfo := newExecutionInfo(s, runner, e.pluginHandler, e.errMaps, false, stream)
	se := newSimpleExecution(executionInfo, false)
	se.execute()
	runner.Kill()
	resChan <- se.suiteResult
}

func (e *parallelExecution) finish() {
	e.suiteResult = mergeDataTableSpecResults(e.suiteResult)
	event.Notify(event.NewExecutionEvent(event.SuiteEnd, nil, e.suiteResult, 0, gauge_messages.ExecutionInfo{}))
	message := &gauge_messages.Message{
		MessageType: gauge_messages.Message_SuiteExecutionResult,
		SuiteExecutionResult: &gauge_messages.SuiteExecutionResult{
			SuiteResult: gauge.ConvertToProtoSuiteResult(e.suiteResult),
		},
	}
	e.pluginHandler.NotifyPlugins(message)
	e.pluginHandler.GracefullyKillPlugins()
}

func (e *parallelExecution) aggregateResults(suiteResults []*result.SuiteResult) {
	r := result.NewSuiteResult(ExecuteTags, e.startTime)
	for _, result := range suiteResults {
		r.SpecsFailedCount += result.SpecsFailedCount
		r.SpecResults = append(r.SpecResults, result.SpecResults...)
		if result.IsFailed {
			r.IsFailed = true
		}
		if result.PreSuite != nil {
			r.PreSuite = result.PreSuite
		}
		if result.PostSuite != nil {
			r.PostSuite = result.PostSuite
		}
		if result.UnhandledErrors != nil {
			r.UnhandledErrors = append(r.UnhandledErrors, result.UnhandledErrors...)
		}
	}
	r.ExecutionTime = int64(time.Since(e.startTime) / 1e6)
	e.suiteResult = r
	e.suiteResult.SetSpecsSkippedCount()
}

func isLazy() bool {
	return strings.ToLower(Strategy) == Lazy
}

func isValidStrategy(strategy string) bool {
	strategy = strings.ToLower(strategy)
	return strategy == Lazy || strategy == Eager
}

func (e *parallelExecution) isMultithreaded() bool {
	value := util.ConvertToBool(os.Getenv(enableMultithreadingEnv), enableMultithreadingEnv, false)
	if !value {
		return false
	}
	if !e.runner.IsMultithreaded() {
		logger.Warningf(true, "Runner doesn't support mutithreading, using multiprocess parallel execution.")
		return false
	}
	return true
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"github.com/lambrospetrou/newmath"
)

func main(){
	fmt.Println("hello, world\n")
	fmt.Println("using newmath lib: ", newmath.Sqrt(9), newmath.Sqrt(2))
}
<commit_msg>removed hello world source<commit_after><|endoftext|>


<commit_before>package concourse

import (
	"bytes"
	"mime/multipart"
	"net/http"
	"net/textproto"

	"github.com/concourse/atc"
	"github.com/tedsuo/rata"
	"gopkg.in/yaml.v2"
)

func (client *client) PipelineConfig(pipelineName string) (atc.Config, string, bool, error) {
	params := rata.Params{"pipeline_name": pipelineName}

	var config atc.Config
	var version string
	responseHeaders := http.Header{}

	err := client.connection.Send(Request{
		RequestName: atc.GetConfig,
		Params:      params,
	}, &Response{
		Result:  &config,
		Headers: &responseHeaders,
	})

	version = responseHeaders.Get(atc.ConfigVersionHeader)

	switch err.(type) {
	case nil:
		return config, version, true, nil
	case ResourceNotFoundError:
		return config, version, false, nil
	default:
		return config, version, false, err
	}
}

func (client *client) CreateOrUpdatePipelineConfig(pipelineName string, configVersion string, passedConfig atc.Config) (bool, bool, error) {
	params := rata.Params{"pipeline_name": pipelineName}
	response := Response{}
	body := &bytes.Buffer{}
	writer := multipart.NewWriter(body)

	yamlWriter, err := writer.CreatePart(
		textproto.MIMEHeader{
			"Content-type": {"application/x-yaml"},
		},
	)
	if err != nil {
		return false, false, err
	}

	rawConfig, err := yaml.Marshal(passedConfig)
	if err != nil {
		return false, false, err
	}

	_, err = yamlWriter.Write(rawConfig)

	writer.Close()

	err = client.connection.Send(Request{
		RequestName: atc.SaveConfig,
		Params:      params,
		Body:        body,
		Header: http.Header{
			"Content-Type":          {writer.FormDataContentType()},
			atc.ConfigVersionHeader: {configVersion},
		},
	},
		&response,
	)
	if err != nil {
		return false, false, err
	}

	if response.Created {
		return true, false, nil
	}

	return false, true, nil
}
<commit_msg>Return error if problems with marshalling<commit_after>package concourse

import (
	"bytes"
	"mime/multipart"
	"net/http"
	"net/textproto"

	"github.com/concourse/atc"
	"github.com/tedsuo/rata"
	"gopkg.in/yaml.v2"
)

func (client *client) PipelineConfig(pipelineName string) (atc.Config, string, bool, error) {
	params := rata.Params{"pipeline_name": pipelineName}

	var config atc.Config
	var version string
	responseHeaders := http.Header{}

	err := client.connection.Send(Request{
		RequestName: atc.GetConfig,
		Params:      params,
	}, &Response{
		Result:  &config,
		Headers: &responseHeaders,
	})

	version = responseHeaders.Get(atc.ConfigVersionHeader)

	switch err.(type) {
	case nil:
		return config, version, true, nil
	case ResourceNotFoundError:
		return config, version, false, nil
	default:
		return config, version, false, err
	}
}

func (client *client) CreateOrUpdatePipelineConfig(pipelineName string, configVersion string, passedConfig atc.Config) (bool, bool, error) {
	params := rata.Params{"pipeline_name": pipelineName}
	response := Response{}
	body := &bytes.Buffer{}
	writer := multipart.NewWriter(body)

	yamlWriter, err := writer.CreatePart(
		textproto.MIMEHeader{
			"Content-type": {"application/x-yaml"},
		},
	)
	if err != nil {
		return false, false, err
	}

	rawConfig, err := yaml.Marshal(passedConfig)
	if err != nil {
		return false, false, err
	}

	_, err = yamlWriter.Write(rawConfig)
	if err != nil {
		return false, false, err
	}

	writer.Close()

	err = client.connection.Send(Request{
		RequestName: atc.SaveConfig,
		Params:      params,
		Body:        body,
		Header: http.Header{
			"Content-Type":          {writer.FormDataContentType()},
			atc.ConfigVersionHeader: {configVersion},
		},
	},
		&response,
	)
	if err != nil {
		return false, false, err
	}

	if response.Created {
		return true, false, nil
	}

	return false, true, nil
}
<|endoftext|>


<commit_before>package routes

import (
	"encoding/json"
	"fmt"
	"log"
	"net/http"
	"time"

	"github.com/gorilla/mux"
	"github.com/schimmy/shorty/db"
	"gopkg.in/Clever/kayvee-go.v2"
)

const (
	errMsgTemplate  = "Unable to find long URL for slug: '%s', please consult http://%s or the proper admin instance to add this slug."
	readOnlyMessage = "You have reached the read-only instance of this shortener. If you have access, please visit the admin instance to perform write operations."
)

var (
	reserved = []string{"delete", "shorten", "list", "meta", "Shortener.jsx", "favicon.png"}
)

// msg is a convenience type for kayvee
type msg map[string]interface{}

// returnJSON
func returnJSON(data interface{}, err error, errNum int, w http.ResponseWriter) {
	if err != nil {
		log.Println(kayvee.FormatLog("shorty", kayvee.Error, "internal.error", msg{
			"err": err.Error(),
		}))
		data = msg{"error": err.Error()}
		// if errNum not set
		if errNum == 0 {
			errNum = http.StatusInternalServerError
		}
		w.WriteHeader(errNum)
	}

	w.Header().Add("Content-Type", "application/json; charset=utf-8")
	err = json.NewEncoder(w).Encode(data)
	if err != nil {
		log.Println(kayvee.FormatLog("shorty", kayvee.Error, "json.encoding", msg{
			"err": err.Error(),
		}))
	}

	return
}

// ReadOnlyHandler returns a message to the user saying that they need
// to find the write-domain to modify things. This shouldn't be hit too
// often as the admin interface itself will hide the user-facing input
func ReadOnlyHandler() func(http.ResponseWriter, *http.Request) {
	return func(w http.ResponseWriter, r *http.Request) {
		log.Println("In read-only mode, returning 401")
		returnJSON(nil, fmt.Errorf(readOnlyMessage), 401, w)
		return
	}
}

//ShortenHandler generates a HTTP handler for a shortening URLs given a datastore backend.
func ShortenHandler(db db.ShortenBackend) func(http.ResponseWriter, *http.Request) {
	return func(w http.ResponseWriter, r *http.Request) {
		if err := r.ParseForm(); err != nil {
			returnJSON(nil, fmt.Errorf("couldn't parse form: %s", err.Error()), 500, w)
			return
		}
		slug := r.PostForm.Get("slug")
		longURL := r.PostForm.Get("long_url")
		owner := r.PostForm.Get("owner")

		for _, reserved := range reserved {
			if slug == reserved {
				returnJSON(nil, fmt.Errorf("That slug is reserved: %s", slug), 400, w)
				return
			}
		}

		// for now set expiry to never
		var t time.Time
		err := db.ShortenURL(slug, longURL, owner, t)
		returnJSON(nil, err, 0, w)
		return
	}
}

// DeleteHandler generates a HTTP handler for deleting URL's given a datastore backend.
func DeleteHandler(db db.ShortenBackend) func(http.ResponseWriter, *http.Request) {
	return func(w http.ResponseWriter, r *http.Request) {
		if err := r.ParseForm(); err != nil {
			returnJSON(nil, fmt.Errorf("couldn't parse form: %s", err.Error()), 500, w)
			return
		}
		slug := r.PostForm.Get("slug")
		err := db.DeleteURL(slug)
		returnJSON(nil, err, 0, w)
	}
}

// MetaHandler returns info on the protocol and the domain for our short URLs
// Seems a little weird, but follows react patterns
func MetaHandler(protocol, domain string) func(http.ResponseWriter, *http.Request) {
	return func(w http.ResponseWriter, r *http.Request) {
		retObj := map[string]string{
			"protocol": protocol,
			"domain":   domain,
		}
		returnJSON(retObj, nil, 0, w)
	}
}

// ListHandler generates a HTTP handler for listing URL's given a datastore backend.
func ListHandler(db db.ShortenBackend) func(http.ResponseWriter, *http.Request) {
	return func(w http.ResponseWriter, r *http.Request) {
		sObj, err := db.GetList()
		returnJSON(sObj, err, 0, w)
	}
}

// RedirectHandler redirects users to their desired location.
// Not accessed via Ajax, just by end users
func RedirectHandler(db db.ShortenBackend, domain string) func(http.ResponseWriter, *http.Request) {
	return func(w http.ResponseWriter, r *http.Request) {
		slug := mux.Vars(r)["slug"]
		long, err := db.GetLongURL(slug)
		if long == "" {
			w.WriteHeader(404)
			fmt.Fprintf(w, fmt.Sprintf(errMsgTemplate, slug, domain, domain))
			return
		}
		if err != nil {
			log.Println(kayvee.FormatLog("shorty", kayvee.Error, "redirect", msg{
				"err": err.Error(),
			}))
			w.WriteHeader(500)
			w.Write([]byte(err.Error()))
			return
		}
		http.Redirect(w, r, long, 301)
		return
	}
}
<commit_msg>return a pointer to a custom error for simplicity<commit_after>package routes

import (
	"encoding/json"
	"fmt"
	"log"
	"net/http"
	"time"

	"github.com/gorilla/mux"
	"github.com/schimmy/shorty/db"
	"gopkg.in/Clever/kayvee-go.v2"
)

const (
	errMsgTemplate  = "Unable to find long URL for slug: '%s', please consult http://%s or the proper admin instance to add this slug."
	readOnlyMessage = "You have reached the read-only instance of this shortener. If you have access, please visit the admin instance to perform write operations."
)

var (
	reserved = []string{"delete", "shorten", "list", "meta", "Shortener.jsx", "favicon.png"}
)

// msg is a convenience type for kayvee
type msg map[string]interface{}

type httpError struct {
	Err  string
	Code int
}

func (h *httpError) Error() string {
	return h.Err
}

// returnJSON takes in the data, an error that just consists of a message and a code,
// and a response writer. If the error is not nil, we write the err code out and log
// that there was an error, otherwise we JSON encode the data and return
func returnJSON(data interface{}, inErr *httpError, w http.ResponseWriter) {
	if inErr != nil {
		log.Println(kayvee.FormatLog("shorty", kayvee.Error, "internal.error", msg{
			"err": inErr.Error(),
		}))
		data = msg{"error": inErr.Error()}
		w.WriteHeader(inErr.Code)
	}

	w.Header().Add("Content-Type", "application/json; charset=utf-8")
	err := json.NewEncoder(w).Encode(data)
	if err != nil {
		log.Println(kayvee.FormatLog("shorty", kayvee.Error, "json.encoding", msg{
			"err": err.Error(),
		}))
	}

	return
}

// ReadOnlyHandler returns a message to the user saying that they need
// to find the write-domain to modify things. This shouldn't be hit too
// often as the admin interface itself will hide the user-facing input
func ReadOnlyHandler() func(http.ResponseWriter, *http.Request) {
	return func(w http.ResponseWriter, r *http.Request) {
		log.Println("In read-only mode, returning 401")
		returnJSON(nil, &httpError{readOnlyMessage, 401}, w)
		return
	}
}

//ShortenHandler generates a HTTP handler for a shortening URLs given a datastore backend.
func ShortenHandler(db db.ShortenBackend) func(http.ResponseWriter, *http.Request) {
	return func(w http.ResponseWriter, r *http.Request) {
		if err := r.ParseForm(); err != nil {
			returnJSON(nil, &httpError{fmt.Sprintf("couldn't parse form: %s", err.Error()), 500}, w)
			return
		}
		slug := r.PostForm.Get("slug")
		longURL := r.PostForm.Get("long_url")
		owner := r.PostForm.Get("owner")

		for _, res := range reserved {
			if slug == res {
				returnJSON(nil, &httpError{fmt.Sprintf("That slug is reserved: %s", slug), 400}, w)
				return
			}
		}

		// for now set expiry to never
		var t time.Time
		err := db.ShortenURL(slug, longURL, owner, t)
		var hErr *httpError = nil
		if err != nil {
			hErr = &httpError{err.Error(), 500}
		}
		returnJSON(nil, hErr, w)
		return
	}
}

// DeleteHandler generates a HTTP handler for deleting URL's given a datastore backend.
func DeleteHandler(db db.ShortenBackend) func(http.ResponseWriter, *http.Request) {
	return func(w http.ResponseWriter, r *http.Request) {
		if err := r.ParseForm(); err != nil {
			returnJSON(nil, &httpError{fmt.Sprintf("couldn't parse form: %s", err.Error()), 500}, w)
			return
		}
		slug := r.PostForm.Get("slug")
		var hErr *httpError = nil
		err := db.DeleteURL(slug)
		if err != nil {
			hErr = &httpError{err.Error(), 500}
		}
		returnJSON(nil, hErr, w)
	}
}

// MetaHandler returns info on the protocol and the domain for our short URLs
// Seems a little weird, but follows react patterns
func MetaHandler(protocol, domain string) func(http.ResponseWriter, *http.Request) {
	return func(w http.ResponseWriter, r *http.Request) {
		retObj := map[string]string{
			"protocol": protocol,
			"domain":   domain,
		}
		returnJSON(retObj, nil, w)
	}
}

// ListHandler generates a HTTP handler for listing URL's given a datastore backend.
func ListHandler(db db.ShortenBackend) func(http.ResponseWriter, *http.Request) {
	return func(w http.ResponseWriter, r *http.Request) {
		var hErr *httpError = nil
		sObj, err := db.GetList()
		if err != nil {
			hErr = &httpError{err.Error(), 500}
		}

		returnJSON(sObj, hErr, w)
	}
}

// RedirectHandler redirects users to their desired location.
// Not accessed via Ajax, just by end users
func RedirectHandler(db db.ShortenBackend, domain string) func(http.ResponseWriter, *http.Request) {
	return func(w http.ResponseWriter, r *http.Request) {
		slug := mux.Vars(r)["slug"]
		long, err := db.GetLongURL(slug)
		if long == "" {
			w.WriteHeader(404)
			fmt.Fprintf(w, fmt.Sprintf(errMsgTemplate, slug, domain, domain))
			return
		}
		if err != nil {
			log.Println(kayvee.FormatLog("shorty", kayvee.Error, "redirect", msg{
				"err": err.Error(),
			}))
			w.WriteHeader(500)
			w.Write([]byte(err.Error()))
			return
		}
		http.Redirect(w, r, long, 301)
		return
	}
}
<|endoftext|>