<commit_before>// Package lile provides helper methods to quickly create RPC based services
// that have metrics, tracing and pub/sub support
package lile

import (
	"net"
	"net/http"
	"os"
	"time"

	"github.com/grpc-ecosystem/go-grpc-middleware"
	"github.com/grpc-ecosystem/go-grpc-prometheus"
	"github.com/grpc-ecosystem/grpc-opentracing/go/otgrpc"
	"github.com/lileio/lile/fromenv"
	"github.com/prometheus/client_golang/prometheus"
	uuid "github.com/satori/go.uuid"
	"github.com/sirupsen/logrus"
	"google.golang.org/grpc"
)

var service = NewService("lile")

type registerImplementation func(s *grpc.Server)

// Service is a grpc compatible server with extra features
type Service struct {
	Name string
	Port string
	// Interceptors
	UnaryInts  []grpc.UnaryServerInterceptor
	StreamInts []grpc.StreamServerInterceptor
	// The RPC server implementation
	GRPCImplementation registerImplementation
}

func defaultOptions(n string) Service {
	return Service{
		Name:               n,
		Port:               ":8000",
		GRPCImplementation: func(s *grpc.Server) {},
	}
}

// NewService creates a lile service with N options
func NewService(name string) Service {
	return defaultOptions(name)
}

func GlobalService() *Service {
	return &service
}

func Name(n string) {
	service.Name = n
}

func Port(n string) {
	service.Port = n
}

// AddUnaryInterceptor adds a unary interceptor to the RPC server
func AddUnaryInterceptor(unint grpc.UnaryServerInterceptor) {
	service.UnaryInts = append(service.UnaryInts, unint)
}

// AddStreamInterceptor adds a stream interceptor to the RPC server
func AddStreamInterceptor(sint grpc.StreamServerInterceptor) {
	service.StreamInts = append(service.StreamInts, sint)
}

func Server(r registerImplementation) {
	service.GRPCImplementation = r
}

func Serve() error {
	lis, err := net.Listen("tcp", service.Port)
	if err != nil {
		return err
	}

	logrus.Infof("Serving gRPC on %s", service.Port)
	return CreateServer().Serve(lis)
}

func CreateServer() *grpc.Server {
	// Default interceptors, [prometheus, opentracing]
	AddUnaryInterceptor(grpc_prometheus.UnaryServerInterceptor)
	AddStreamInterceptor(grpc_prometheus.StreamServerInterceptor)
	AddUnaryInterceptor(otgrpc.OpenTracingServerInterceptor(
		fromenv.Tracer(service.Name)))

	gs := grpc.NewServer(
		grpc.UnaryInterceptor(
			grpc_middleware.ChainUnaryServer(service.UnaryInts...)),
		grpc.StreamInterceptor(
			grpc_middleware.ChainStreamServer(service.StreamInts...)),
	)

	service.GRPCImplementation(gs)

	grpc_prometheus.EnableHandlingTimeHistogram()
	grpc_prometheus.Register(gs)
	http.Handle("/metrics", prometheus.Handler())
	logrus.Infof("Prometheus metrics at :9000/metrics")
	port := "9000"
	if p := os.Getenv("PROMETHEUS_PORT"); p != "" {
		port = p
	}
	go http.ListenAndServe(":"+port, nil)

	return gs
}

//   Creates a server listener dependent on the underlying platform. Windows
// hosts will have a Windows Named pipe, anything else gets a UNIX socket
func getTestServerTransportOrPanic()(string, net.Listener) {
	var uniqueAddress string

	// Create a temp random unix socket
	uid, err := uuid.NewV1()
	if err != nil {
		panic(err)
	}
	uniqueAddress = formatPlatformTestSeverAddress(uid.String())

	serverListener, err := getTestServerListener(uniqueAddress)

	if err != nil {
		panic(err)
	}

	return uniqueAddress, serverListener
}

//   NewTestServer is a helper function to create a gRPC server on a non-network
// socket and it returns the socket location and a func to call which starts
// the server
func NewTestServer(s *grpc.Server) (string, func()) {

	socketAddress, listener := getTestServerTransportOrPanic()

	return socketAddress, func() {
		s.Serve(listener)
	}
}

// TestConn is a connection that connects to a socket based connection
func TestConn(addr string) *grpc.ClientConn {

	conn, err := grpc.Dial(
		addr,
		grpc.WithDialer(func(addr string, d time.Duration) (net.Conn, error) {
			return dialTestServer(addr)
		}),
		grpc.WithInsecure(),
		grpc.WithTimeout(1*time.Second),
		grpc.WithBlock(),
	)

	if err != nil {
		panic(err)
	}

	return conn
}
<commit_msg>Update style for platform-dependent test transports<commit_after>// Package lile provides helper methods to quickly create RPC based services
// that have metrics, tracing and pub/sub support
package lile

import (
	"net"
	"net/http"
	"os"
	"time"

	"github.com/grpc-ecosystem/go-grpc-middleware"
	"github.com/grpc-ecosystem/go-grpc-prometheus"
	"github.com/grpc-ecosystem/grpc-opentracing/go/otgrpc"
	"github.com/lileio/lile/fromenv"
	"github.com/prometheus/client_golang/prometheus"
	uuid "github.com/satori/go.uuid"
	"github.com/sirupsen/logrus"
	"google.golang.org/grpc"
)

var service = NewService("lile")

type registerImplementation func(s *grpc.Server)

// Service is a grpc compatible server with extra features
type Service struct {
	Name string
	Port string
	// Interceptors
	UnaryInts  []grpc.UnaryServerInterceptor
	StreamInts []grpc.StreamServerInterceptor
	// The RPC server implementation
	GRPCImplementation registerImplementation
}

func defaultOptions(n string) Service {
	return Service{
		Name:               n,
		Port:               ":8000",
		GRPCImplementation: func(s *grpc.Server) {},
	}
}

// NewService creates a lile service with N options
func NewService(name string) Service {
	return defaultOptions(name)
}

func GlobalService() *Service {
	return &service
}

func Name(n string) {
	service.Name = n
}

func Port(n string) {
	service.Port = n
}

// AddUnaryInterceptor adds a unary interceptor to the RPC server
func AddUnaryInterceptor(unint grpc.UnaryServerInterceptor) {
	service.UnaryInts = append(service.UnaryInts, unint)
}

// AddStreamInterceptor adds a stream interceptor to the RPC server
func AddStreamInterceptor(sint grpc.StreamServerInterceptor) {
	service.StreamInts = append(service.StreamInts, sint)
}

func Server(r registerImplementation) {
	service.GRPCImplementation = r
}

func Serve() error {
	lis, err := net.Listen("tcp", service.Port)
	if err != nil {
		return err
	}

	logrus.Infof("Serving gRPC on %s", service.Port)
	return CreateServer().Serve(lis)
}

func CreateServer() *grpc.Server {
	// Default interceptors, [prometheus, opentracing]
	AddUnaryInterceptor(grpc_prometheus.UnaryServerInterceptor)
	AddStreamInterceptor(grpc_prometheus.StreamServerInterceptor)
	AddUnaryInterceptor(otgrpc.OpenTracingServerInterceptor(
		fromenv.Tracer(service.Name)))

	gs := grpc.NewServer(
		grpc.UnaryInterceptor(
			grpc_middleware.ChainUnaryServer(service.UnaryInts...)),
		grpc.StreamInterceptor(
			grpc_middleware.ChainStreamServer(service.StreamInts...)),
	)

	service.GRPCImplementation(gs)

	grpc_prometheus.EnableHandlingTimeHistogram()
	grpc_prometheus.Register(gs)
	http.Handle("/metrics", prometheus.Handler())
	logrus.Infof("Prometheus metrics at :9000/metrics")
	port := "9000"
	if p := os.Getenv("PROMETHEUS_PORT"); p != "" {
		port = p
	}
	go http.ListenAndServe(":"+port, nil)

	return gs
}

//   Creates a server listener dependent on the underlying platform. Windows
// hosts will have a Windows Named pipe, anything else gets a UNIX socket
func getTestServerTransport()(string, net.Listener, error) {
	var uniqueAddress string

	// Create a random string for part of the address
	uid, err := uuid.NewV1()
	if err != nil {
		return "", nil, err
	}

	uniqueAddress = formatPlatformTestSeverAddress(uid.String())

	serverListener, err := getTestServerListener(uniqueAddress)
	if err != nil {
		return "", nil, err
	}

	return uniqueAddress, serverListener, nil
}

//   NewTestServer is a helper function to create a gRPC server on a non-network
// socket and it returns the socket location and a func to call which starts
// the server
func NewTestServer(s *grpc.Server) (string, func()) {
	socketAddress, listener, err := getTestServerTransport()
	if err != nil {
		panic(err)
	}

	return socketAddress, func() {
		s.Serve(listener)
	}
}

// TestConn is a connection that connects to a socket based connection
func TestConn(addr string) *grpc.ClientConn {

	conn, err := grpc.Dial(
		addr,
		grpc.WithDialer(func(addr string, d time.Duration) (net.Conn, error) {
			return dialTestServer(addr)
		}),
		grpc.WithInsecure(),
		grpc.WithTimeout(1*time.Second),
		grpc.WithBlock(),
	)

	if err != nil {
		panic(err)
	}

	return conn
}
<|endoftext|>


<commit_before>package geom

type Line struct {
	P1, P2 Point
}

func NewLine(p1, p2 Point) Line {
	return Line{P1:p1, P2: p2}
}

// Points is an implementation of Bresenham's Line Algorithm, copied
// directly from roguebasin.com. It returns all points line
func (l Line) Points() (points []Point) {
	x1, y1 := l.P1.X, l.P1.Y
	x2, y2 := l.P2.X, l.P2.Y

	isSteep := abs(y2-y1) > abs(x2-x1)
	if isSteep {
		x1, y1 = y1, x1
		x2, y2 = y2, x2
	}

	reversed := false
	if x1 > x2 {
		x1, x2 = x2, x1
		y1, y2 = y2, y1
		reversed = true
	}

	deltaX := x2 - x1
	deltaY := abs(y2 - y1)
	err := deltaX / 2
	y := y1
	var ystep int

	if y1 < y2 {
		ystep = 1
	} else {
		ystep = -1
	}

	for x := x1; x < x2+1; x++ {
		if isSteep {
			points = append(points, Pt(y, x))
		} else {
			points = append(points, Pt(x, y))
		}
		err -= deltaY
		if err < 0 {
			y += ystep
			err += deltaX
		}
	}

	if reversed {
		for i, j := 0, len(points)-1; i < j; i, j = i+1, j-1 {
			points[i], points[j] = points[j], points[i]
		}
	}

	return
}
<commit_msg>fixed comment typo<commit_after>package geom

type Line struct {
	P1, P2 Point
}

func NewLine(p1, p2 Point) Line {
	return Line{P1:p1, P2: p2}
}

// Points is an implementation of Bresenham's Line Algorithm, copied
// directly from roguebasin.com. It returns all points in a line
func (l Line) Points() (points []Point) {
	x1, y1 := l.P1.X, l.P1.Y
	x2, y2 := l.P2.X, l.P2.Y

	isSteep := abs(y2-y1) > abs(x2-x1)
	if isSteep {
		x1, y1 = y1, x1
		x2, y2 = y2, x2
	}

	reversed := false
	if x1 > x2 {
		x1, x2 = x2, x1
		y1, y2 = y2, y1
		reversed = true
	}

	deltaX := x2 - x1
	deltaY := abs(y2 - y1)
	err := deltaX / 2
	y := y1
	var ystep int

	if y1 < y2 {
		ystep = 1
	} else {
		ystep = -1
	}

	for x := x1; x < x2+1; x++ {
		if isSteep {
			points = append(points, Pt(y, x))
		} else {
			points = append(points, Pt(x, y))
		}
		err -= deltaY
		if err < 0 {
			y += ystep
			err += deltaX
		}
	}

	if reversed {
		for i, j := 0, len(points)-1; i < j; i, j = i+1, j-1 {
			points[i], points[j] = points[j], points[i]
		}
	}

	return
}
<|endoftext|>


<commit_before>package sprig

import (
	"errors"
	"fmt"
	"reflect"
	"sort"
)

// Reflection is used in these functions so that slices and arrays of strings,
// ints, and other types not implementing []interface{} can be worked with.
// For example, this is useful if you need to work on the output of regexs.

func list(v ...interface{}) []interface{} {
	return v
}

func push(list interface{}, v interface{}) ([]interface{}, error) {
	tp := reflect.TypeOf(list).Kind()
	switch tp {
	case reflect.Slice, reflect.Array:
		l2 := reflect.ValueOf(list)

		l := l2.Len()
		nl := make([]interface{}, l)
		for i := 0; i < l; i++ {
			nl[i] = l2.Index(i).Interface()
		}

		return append(nl, v), nil

	default:
		return nil, fmt.Errorf("Cannot push on type %s", tp)
	}
}

func prepend(list interface{}, v interface{}) ([]interface{}, error) {
	//return append([]interface{}{v}, list...)

	tp := reflect.TypeOf(list).Kind()
	switch tp {
	case reflect.Slice, reflect.Array:
		l2 := reflect.ValueOf(list)

		l := l2.Len()
		nl := make([]interface{}, l)
		for i := 0; i < l; i++ {
			nl[i] = l2.Index(i).Interface()
		}

		return append([]interface{}{v}, nl...), nil

	default:
		return nil, fmt.Errorf("Cannot prepend on type %s", tp)
	}
}

func last(list interface{}) (interface{}, error) {
	tp := reflect.TypeOf(list).Kind()
	switch tp {
	case reflect.Slice, reflect.Array:
		l2 := reflect.ValueOf(list)

		l := l2.Len()
		if l == 0 {
			return nil, nil
		}

		return l2.Index(l - 1).Interface(), nil
	default:
		return nil, fmt.Errorf("Cannot find last on type %s", tp)
	}
}

func first(list interface{}) (interface{}, error) {
	tp := reflect.TypeOf(list).Kind()
	switch tp {
	case reflect.Slice, reflect.Array:
		l2 := reflect.ValueOf(list)

		l := l2.Len()
		if l == 0 {
			return nil, nil
		}

		return l2.Index(0).Interface(), nil
	default:
		return nil, fmt.Errorf("Cannot find first on type %s", tp)
	}
}

func rest(list interface{}) ([]interface{}, error) {
	tp := reflect.TypeOf(list).Kind()
	switch tp {
	case reflect.Slice, reflect.Array:
		l2 := reflect.ValueOf(list)

		l := l2.Len()
		if l == 0 {
			return nil, nil
		}

		nl := make([]interface{}, l-1)
		for i := 1; i < l; i++ {
			nl[i-1] = l2.Index(i).Interface()
		}

		return nl, nil
	default:
		return nil, fmt.Errorf("Cannot find rest on type %s", tp)
	}
}

func initial(list interface{}) ([]interface{}, error) {
	tp := reflect.TypeOf(list).Kind()
	switch tp {
	case reflect.Slice, reflect.Array:
		l2 := reflect.ValueOf(list)

		l := l2.Len()
		if l == 0 {
			return nil, nil
		}

		nl := make([]interface{}, l-1)
		for i := 0; i < l-1; i++ {
			nl[i] = l2.Index(i).Interface()
		}

		return nl, nil
	default:
		return nil, fmt.Errorf("Cannot find initial on type %s", tp)
	}
}

func sortAlpha(list interface{}) []string {
	k := reflect.Indirect(reflect.ValueOf(list)).Kind()
	switch k {
	case reflect.Slice, reflect.Array:
		a := strslice(list)
		s := sort.StringSlice(a)
		s.Sort()
		return s
	}
	return []string{strval(list)}
}

func reverse(v interface{}) ([]interface{}, error) {
	tp := reflect.TypeOf(v).Kind()
	switch tp {
	case reflect.Slice, reflect.Array:
		l2 := reflect.ValueOf(v)

		l := l2.Len()
		// We do not sort in place because the incoming array should not be altered.
		nl := make([]interface{}, l)
		for i := 0; i < l; i++ {
			nl[l-i-1] = l2.Index(i).Interface()
		}

		return nl, nil
	default:
		return nil, fmt.Errorf("Cannot find reverse on type %s", tp)
	}
}

func compact(list interface{}) ([]interface{}, error) {
	tp := reflect.TypeOf(list).Kind()
	switch tp {
	case reflect.Slice, reflect.Array:
		l2 := reflect.ValueOf(list)

		l := l2.Len()
		nl := []interface{}{}
		var item interface{}
		for i := 0; i < l; i++ {
			item = l2.Index(i).Interface()
			if !empty(item) {
				nl = append(nl, item)
			}
		}

		return nl, nil
	default:
		return nil, fmt.Errorf("Cannot compact on type %s", tp)
	}
}

func uniq(list interface{}) ([]interface{}, error) {
	tp := reflect.TypeOf(list).Kind()
	switch tp {
	case reflect.Slice, reflect.Array:
		l2 := reflect.ValueOf(list)

		l := l2.Len()
		dest := []interface{}{}
		var item interface{}
		for i := 0; i < l; i++ {
			item = l2.Index(i).Interface()
			if !inList(dest, item) {
				dest = append(dest, item)
			}
		}

		return dest, nil
	default:
		return nil, fmt.Errorf("Cannot find uniq on type %s", tp)
	}
}

func inList(haystack []interface{}, needle interface{}) bool {
	for _, h := range haystack {
		if reflect.DeepEqual(needle, h) {
			return true
		}
	}
	return false
}

func without(list interface{}, omit ...interface{}) ([]interface{}, error) {
	tp := reflect.TypeOf(list).Kind()
	switch tp {
	case reflect.Slice, reflect.Array:
		l2 := reflect.ValueOf(list)

		l := l2.Len()
		res := []interface{}{}
		var item interface{}
		for i := 0; i < l; i++ {
			item = l2.Index(i).Interface()
			if !inList(omit, item) {
				res = append(res, item)
			}
		}

		return res, nil
	default:
		return nil, fmt.Errorf("Cannot find without on type %s", tp)
	}
}

func has(needle interface{}, haystack interface{}) (bool, error) {
	if haystack == nil {
		return false, errors.New("The haystack is empty")
	}
	tp := reflect.TypeOf(haystack).Kind()
	switch tp {
	case reflect.Slice, reflect.Array:
		l2 := reflect.ValueOf(haystack)
		var item interface{}
		l := l2.Len()
		for i := 0; i < l; i++ {
			item = l2.Index(i).Interface()
			if reflect.DeepEqual(needle, item) {
				return true, nil
			}
		}

		return false, nil
	default:
		return false, fmt.Errorf("Cannot find has on type %s", tp)
	}
}

// $list := [1, 2, 3, 4, 5]
// slice $list     -> list[0:5] = list[:]
// slice $list 0 3 -> list[0:3] = list[:3]
// slice $list 3 5 -> list[3:5]
// slice $list 3   -> list[3:5] = list[3:]
func slice(list interface{}, indices ...interface{}) (interface{}, error) {
	tp := reflect.TypeOf(list).Kind()
	switch tp {
	case reflect.Slice, reflect.Array:
		l2 := reflect.ValueOf(list)

		l := l2.Len()
		if l == 0 {
			return nil, nil
		}

		var start, end int
		if len(indices) > 0 {
			start = toInt(indices[0])
		}
		if len(indices) < 2 {
			end = l
		} else {
			end = toInt(indices[1])
		}

		return l2.Slice(start, end).Interface(), nil
	default:
		return nil, fmt.Errorf("list should be type of slice or array but %s", tp)
	}
}
<commit_msg>fix haystack<commit_after>package sprig

import (
	"fmt"
	"reflect"
	"sort"
)

// Reflection is used in these functions so that slices and arrays of strings,
// ints, and other types not implementing []interface{} can be worked with.
// For example, this is useful if you need to work on the output of regexs.

func list(v ...interface{}) []interface{} {
	return v
}

func push(list interface{}, v interface{}) ([]interface{}, error) {
	tp := reflect.TypeOf(list).Kind()
	switch tp {
	case reflect.Slice, reflect.Array:
		l2 := reflect.ValueOf(list)

		l := l2.Len()
		nl := make([]interface{}, l)
		for i := 0; i < l; i++ {
			nl[i] = l2.Index(i).Interface()
		}

		return append(nl, v), nil

	default:
		return nil, fmt.Errorf("Cannot push on type %s", tp)
	}
}

func prepend(list interface{}, v interface{}) ([]interface{}, error) {
	//return append([]interface{}{v}, list...)

	tp := reflect.TypeOf(list).Kind()
	switch tp {
	case reflect.Slice, reflect.Array:
		l2 := reflect.ValueOf(list)

		l := l2.Len()
		nl := make([]interface{}, l)
		for i := 0; i < l; i++ {
			nl[i] = l2.Index(i).Interface()
		}

		return append([]interface{}{v}, nl...), nil

	default:
		return nil, fmt.Errorf("Cannot prepend on type %s", tp)
	}
}

func last(list interface{}) (interface{}, error) {
	tp := reflect.TypeOf(list).Kind()
	switch tp {
	case reflect.Slice, reflect.Array:
		l2 := reflect.ValueOf(list)

		l := l2.Len()
		if l == 0 {
			return nil, nil
		}

		return l2.Index(l - 1).Interface(), nil
	default:
		return nil, fmt.Errorf("Cannot find last on type %s", tp)
	}
}

func first(list interface{}) (interface{}, error) {
	tp := reflect.TypeOf(list).Kind()
	switch tp {
	case reflect.Slice, reflect.Array:
		l2 := reflect.ValueOf(list)

		l := l2.Len()
		if l == 0 {
			return nil, nil
		}

		return l2.Index(0).Interface(), nil
	default:
		return nil, fmt.Errorf("Cannot find first on type %s", tp)
	}
}

func rest(list interface{}) ([]interface{}, error) {
	tp := reflect.TypeOf(list).Kind()
	switch tp {
	case reflect.Slice, reflect.Array:
		l2 := reflect.ValueOf(list)

		l := l2.Len()
		if l == 0 {
			return nil, nil
		}

		nl := make([]interface{}, l-1)
		for i := 1; i < l; i++ {
			nl[i-1] = l2.Index(i).Interface()
		}

		return nl, nil
	default:
		return nil, fmt.Errorf("Cannot find rest on type %s", tp)
	}
}

func initial(list interface{}) ([]interface{}, error) {
	tp := reflect.TypeOf(list).Kind()
	switch tp {
	case reflect.Slice, reflect.Array:
		l2 := reflect.ValueOf(list)

		l := l2.Len()
		if l == 0 {
			return nil, nil
		}

		nl := make([]interface{}, l-1)
		for i := 0; i < l-1; i++ {
			nl[i] = l2.Index(i).Interface()
		}

		return nl, nil
	default:
		return nil, fmt.Errorf("Cannot find initial on type %s", tp)
	}
}

func sortAlpha(list interface{}) []string {
	k := reflect.Indirect(reflect.ValueOf(list)).Kind()
	switch k {
	case reflect.Slice, reflect.Array:
		a := strslice(list)
		s := sort.StringSlice(a)
		s.Sort()
		return s
	}
	return []string{strval(list)}
}

func reverse(v interface{}) ([]interface{}, error) {
	tp := reflect.TypeOf(v).Kind()
	switch tp {
	case reflect.Slice, reflect.Array:
		l2 := reflect.ValueOf(v)

		l := l2.Len()
		// We do not sort in place because the incoming array should not be altered.
		nl := make([]interface{}, l)
		for i := 0; i < l; i++ {
			nl[l-i-1] = l2.Index(i).Interface()
		}

		return nl, nil
	default:
		return nil, fmt.Errorf("Cannot find reverse on type %s", tp)
	}
}

func compact(list interface{}) ([]interface{}, error) {
	tp := reflect.TypeOf(list).Kind()
	switch tp {
	case reflect.Slice, reflect.Array:
		l2 := reflect.ValueOf(list)

		l := l2.Len()
		nl := []interface{}{}
		var item interface{}
		for i := 0; i < l; i++ {
			item = l2.Index(i).Interface()
			if !empty(item) {
				nl = append(nl, item)
			}
		}

		return nl, nil
	default:
		return nil, fmt.Errorf("Cannot compact on type %s", tp)
	}
}

func uniq(list interface{}) ([]interface{}, error) {
	tp := reflect.TypeOf(list).Kind()
	switch tp {
	case reflect.Slice, reflect.Array:
		l2 := reflect.ValueOf(list)

		l := l2.Len()
		dest := []interface{}{}
		var item interface{}
		for i := 0; i < l; i++ {
			item = l2.Index(i).Interface()
			if !inList(dest, item) {
				dest = append(dest, item)
			}
		}

		return dest, nil
	default:
		return nil, fmt.Errorf("Cannot find uniq on type %s", tp)
	}
}

func inList(haystack []interface{}, needle interface{}) bool {
	for _, h := range haystack {
		if reflect.DeepEqual(needle, h) {
			return true
		}
	}
	return false
}

func without(list interface{}, omit ...interface{}) ([]interface{}, error) {
	tp := reflect.TypeOf(list).Kind()
	switch tp {
	case reflect.Slice, reflect.Array:
		l2 := reflect.ValueOf(list)

		l := l2.Len()
		res := []interface{}{}
		var item interface{}
		for i := 0; i < l; i++ {
			item = l2.Index(i).Interface()
			if !inList(omit, item) {
				res = append(res, item)
			}
		}

		return res, nil
	default:
		return nil, fmt.Errorf("Cannot find without on type %s", tp)
	}
}

func has(needle interface{}, haystack interface{}) (bool, error) {
	if haystack == nil {
		return false, nil
	}
	tp := reflect.TypeOf(haystack).Kind()
	switch tp {
	case reflect.Slice, reflect.Array:
		l2 := reflect.ValueOf(haystack)
		var item interface{}
		l := l2.Len()
		for i := 0; i < l; i++ {
			item = l2.Index(i).Interface()
			if reflect.DeepEqual(needle, item) {
				return true, nil
			}
		}

		return false, nil
	default:
		return false, fmt.Errorf("Cannot find has on type %s", tp)
	}
}

// $list := [1, 2, 3, 4, 5]
// slice $list     -> list[0:5] = list[:]
// slice $list 0 3 -> list[0:3] = list[:3]
// slice $list 3 5 -> list[3:5]
// slice $list 3   -> list[3:5] = list[3:]
func slice(list interface{}, indices ...interface{}) (interface{}, error) {
	tp := reflect.TypeOf(list).Kind()
	switch tp {
	case reflect.Slice, reflect.Array:
		l2 := reflect.ValueOf(list)

		l := l2.Len()
		if l == 0 {
			return nil, nil
		}

		var start, end int
		if len(indices) > 0 {
			start = toInt(indices[0])
		}
		if len(indices) < 2 {
			end = l
		} else {
			end = toInt(indices[1])
		}

		return l2.Slice(start, end).Interface(), nil
	default:
		return nil, fmt.Errorf("list should be type of slice or array but %s", tp)
	}
}
<|endoftext|>


<commit_before>package cas

import "bytes"
import "math/big"

func (this *Expression) ToStringList() string {
	var buffer bytes.Buffer
	buffer.WriteString("{")
	for i, e := range this.Parts[1:] {
		buffer.WriteString(e.String())
		if i != len(this.Parts[1:])-1 {
			buffer.WriteString(", ")
		}
	}
	buffer.WriteString("}")
	return buffer.String()
}

func (this *Expression) EvalLength(es *EvalState) Ex {
	if len(this.Parts) != 2 {
		return this
	}

	list, isList := HeadAssertion(this.Parts[1], "List")
	if isList {
		return &Integer{big.NewInt(int64(len(list.Parts) - 1))}
	}
	return this
}

func (this *Expression) EvalTable(es *EvalState) Ex {
	if len(this.Parts) != 3 {
		return this
	}

	list, isList := HeadAssertion(this.Parts[2], "List")
	if isList {
		if len(list.Parts) == 4 {
			i, iOk := list.Parts[1].(*Symbol)
			iMin, iMinOk := list.Parts[2].(*Integer)
			iMax, iMaxOk := list.Parts[3].(*Integer)
			if iOk && iMinOk && iMaxOk {
				origDef, isOrigDef := es.GetDef(i.Name, i)
				toReturn := &Expression{[]Ex{&Symbol{"List"}}}
				iMaxInt := iMax.Val.Int64()
				for curr := iMin.Val.Int64(); curr <= iMaxInt; curr++ {
					es.Define(i.Name, i, &Integer{big.NewInt(curr)})
					toReturn.Parts = append(toReturn.Parts, this.Parts[1].DeepCopy().Eval(es))
				}
				if isOrigDef {
					es.Define(i.Name, i, origDef)
				} else {
					es.Clear(i.Name)
				}
				return toReturn
			}
		}
	}
	return this
}

func (this *Expression) EvalIterationFunc(es *EvalState, init Ex, op string) Ex {
	if len(this.Parts) != 3 {
		return this
	}

	list, isList := HeadAssertion(this.Parts[2], "List")
	if isList {
		// Retrieve variables of iteration
		var i *Symbol
		var iMin, iMax *Integer
		iOk, iMinOk, iMaxOk := false, false, false
		if len(list.Parts) == 3 {
			i, iOk = list.Parts[1].(*Symbol)
			iMin, iMinOk = &Integer{big.NewInt(1)}, true
			iMax, iMaxOk = list.Parts[2].(*Integer)
		} else if len(list.Parts) == 4 {
			i, iOk = list.Parts[1].(*Symbol)
			iMin, iMinOk = list.Parts[2].(*Integer)
			iMax, iMaxOk = list.Parts[3].(*Integer)
		}

		if iOk && iMinOk && iMaxOk {
			origDef, isOrigDef := es.GetDef(i.Name, i)
			var toReturn Ex = init
			iMaxInt := iMax.Val.Int64()
			for curr := iMin.Val.Int64(); curr <= iMaxInt; curr++ {
				es.Define(i.Name, i, &Integer{big.NewInt(curr)})
				toReturn = (&Expression{[]Ex{&Symbol{op}, toReturn, this.Parts[1].DeepCopy().Eval(es)}}).Eval(es)
			}
			if isOrigDef {
				es.Define(i.Name, i, origDef)
			} else {
				es.Clear(i.Name)
			}
			return toReturn
		}
	}
	return this
}

func (this *Expression) EvalSum(es *EvalState) Ex {
	return this.EvalIterationFunc(es, &Integer{big.NewInt(0)}, "Plus")
}

func (this *Expression) EvalProduct(es *EvalState) Ex {
	return this.EvalIterationFunc(es, &Integer{big.NewInt(1)}, "Times")
}

func MemberQ(components []Ex, item Ex, cl *CASLogger) bool {
	for _, part := range components {
		if matchq, _ := IsMatchQ(part, item, EmptyPD(), cl); matchq {
			return true
		}
	}
	return false
}

func (this *Expression) EvalMemberQ(es *EvalState) Ex {
	if len(this.Parts) != 3 {
		return this
	}
	list, isList := HeadAssertion(this.Parts[1], "List")
	if isList {
		if MemberQ(list.Parts, this.Parts[2], &es.CASLogger) {
			return &Symbol{"True"}
		}
	}
	return &Symbol{"False"}
}

func (this *Expression) EvalMap(es *EvalState) Ex {
	if len(this.Parts) != 3 {
		return this
	}

	list, isList := HeadAssertion(this.Parts[2], "List")
	if isList {
		toReturn := &Expression{[]Ex{&Symbol{"List"}}}
		for i := 1; i < len(list.Parts); i++ {
			toReturn.Parts = append(toReturn.Parts, &Expression{[]Ex{
				this.Parts[1].DeepCopy(),
				list.Parts[i].DeepCopy(),
			}})
		}
		return toReturn
	}
	return this.Parts[2]
}

func (this *Expression) EvalArray(es *EvalState) Ex {
	if len(this.Parts) != 3 {
		return this
	}

	nInt, nOk := this.Parts[2].(*Integer)
	if nOk {
		n := nInt.Val.Int64()
		toReturn := &Expression{[]Ex{&Symbol{"List"}}}
		for i := int64(1); i <= n; i++ {
			toReturn.Parts = append(toReturn.Parts, &Expression{[]Ex{
				this.Parts[1].DeepCopy(),
				&Integer{big.NewInt(i)},
			}})
		}
		return toReturn
	}
	return this.Parts[2]
}

func (this *Expression) EvalCases(es *EvalState) Ex {
	if len(this.Parts) != 3 {
		return this
	}

	list, isList := HeadAssertion(this.Parts[1], "List")
	if isList {
		toReturn := &Expression{[]Ex{&Symbol{"List"}}}

		for i := 1; i < len(list.Parts); i++ {
			if matchq, _ := IsMatchQ(list.Parts[i], this.Parts[2], EmptyPD(), &es.CASLogger); matchq {
				toReturn.Parts = append(toReturn.Parts, list.Parts[i])
			}
		}

		return toReturn
	}
	return this
}
<commit_msg>Abstract out IterSpec.<commit_after>package cas

import "bytes"
import "math/big"

func (this *Expression) ToStringList() string {
	var buffer bytes.Buffer
	buffer.WriteString("{")
	for i, e := range this.Parts[1:] {
		buffer.WriteString(e.String())
		if i != len(this.Parts[1:])-1 {
			buffer.WriteString(", ")
		}
	}
	buffer.WriteString("}")
	return buffer.String()
}

func (this *Expression) EvalLength(es *EvalState) Ex {
	if len(this.Parts) != 2 {
		return this
	}

	list, isList := HeadAssertion(this.Parts[1], "List")
	if isList {
		return &Integer{big.NewInt(int64(len(list.Parts) - 1))}
	}
	return this
}

func (this *Expression) EvalTable(es *EvalState) Ex {
	if len(this.Parts) != 3 {
		return this
	}

	list, isList := HeadAssertion(this.Parts[2], "List")
	if isList {
		if len(list.Parts) == 4 {
			i, iOk := list.Parts[1].(*Symbol)
			iMin, iMinOk := list.Parts[2].(*Integer)
			iMax, iMaxOk := list.Parts[3].(*Integer)
			if iOk && iMinOk && iMaxOk {
				origDef, isOrigDef := es.GetDef(i.Name, i)
				toReturn := &Expression{[]Ex{&Symbol{"List"}}}
				iMaxInt := iMax.Val.Int64()
				for curr := iMin.Val.Int64(); curr <= iMaxInt; curr++ {
					es.Define(i.Name, i, &Integer{big.NewInt(curr)})
					toReturn.Parts = append(toReturn.Parts, this.Parts[1].DeepCopy().Eval(es))
				}
				if isOrigDef {
					es.Define(i.Name, i, origDef)
				} else {
					es.Clear(i.Name)
				}
				return toReturn
			}
		}
	}
	return this
}

type IterSpec struct {
	i    *Symbol
	iMin *Integer
	iMax *Integer
}

func IterSpecFromList(listEx Ex) (is IterSpec, isOk bool) {
	list, isList := HeadAssertion(listEx, "List")
	if isList {
		iOk, iMinOk, iMaxOk := false, false, false
		if len(list.Parts) == 3 {
			is.i, iOk = list.Parts[1].(*Symbol)
			is.iMin, iMinOk = &Integer{big.NewInt(1)}, true
			is.iMax, iMaxOk = list.Parts[2].(*Integer)
		} else if len(list.Parts) == 4 {
			is.i, iOk = list.Parts[1].(*Symbol)
			is.iMin, iMinOk = list.Parts[2].(*Integer)
			is.iMax, iMaxOk = list.Parts[3].(*Integer)
		}
		if iOk && iMinOk && iMaxOk {
			return is, true
		}
	}
	return is, false
}

func (this *Expression) EvalIterationFunc(es *EvalState, init Ex, op string) Ex {
	if len(this.Parts) != 3 {
		return this
	}

	// Retrieve variables of iteration
	is, isOk := IterSpecFromList(this.Parts[2])
	if isOk {
		origDef, isOrigDef := es.GetDef(is.i.Name, is.i)
		var toReturn Ex = init
		iMaxInt := is.iMax.Val.Int64()
		for curr := is.iMin.Val.Int64(); curr <= iMaxInt; curr++ {
			es.Define(is.i.Name, is.i, &Integer{big.NewInt(curr)})
			toReturn = (&Expression{[]Ex{&Symbol{op}, toReturn, this.Parts[1].DeepCopy().Eval(es)}}).Eval(es)
		}
		if isOrigDef {
			es.Define(is.i.Name, is.i, origDef)
		} else {
			es.Clear(is.i.Name)
		}
		return toReturn
	}
	return this
}

func (this *Expression) EvalSum(es *EvalState) Ex {
	return this.EvalIterationFunc(es, &Integer{big.NewInt(0)}, "Plus")
}

func (this *Expression) EvalProduct(es *EvalState) Ex {
	return this.EvalIterationFunc(es, &Integer{big.NewInt(1)}, "Times")
}

func MemberQ(components []Ex, item Ex, cl *CASLogger) bool {
	for _, part := range components {
		if matchq, _ := IsMatchQ(part, item, EmptyPD(), cl); matchq {
			return true
		}
	}
	return false
}

func (this *Expression) EvalMemberQ(es *EvalState) Ex {
	if len(this.Parts) != 3 {
		return this
	}
	list, isList := HeadAssertion(this.Parts[1], "List")
	if isList {
		if MemberQ(list.Parts, this.Parts[2], &es.CASLogger) {
			return &Symbol{"True"}
		}
	}
	return &Symbol{"False"}
}

func (this *Expression) EvalMap(es *EvalState) Ex {
	if len(this.Parts) != 3 {
		return this
	}

	list, isList := HeadAssertion(this.Parts[2], "List")
	if isList {
		toReturn := &Expression{[]Ex{&Symbol{"List"}}}
		for i := 1; i < len(list.Parts); i++ {
			toReturn.Parts = append(toReturn.Parts, &Expression{[]Ex{
				this.Parts[1].DeepCopy(),
				list.Parts[i].DeepCopy(),
			}})
		}
		return toReturn
	}
	return this.Parts[2]
}

func (this *Expression) EvalArray(es *EvalState) Ex {
	if len(this.Parts) != 3 {
		return this
	}

	nInt, nOk := this.Parts[2].(*Integer)
	if nOk {
		n := nInt.Val.Int64()
		toReturn := &Expression{[]Ex{&Symbol{"List"}}}
		for i := int64(1); i <= n; i++ {
			toReturn.Parts = append(toReturn.Parts, &Expression{[]Ex{
				this.Parts[1].DeepCopy(),
				&Integer{big.NewInt(i)},
			}})
		}
		return toReturn
	}
	return this.Parts[2]
}

func (this *Expression) EvalCases(es *EvalState) Ex {
	if len(this.Parts) != 3 {
		return this
	}

	list, isList := HeadAssertion(this.Parts[1], "List")
	if isList {
		toReturn := &Expression{[]Ex{&Symbol{"List"}}}

		for i := 1; i < len(list.Parts); i++ {
			if matchq, _ := IsMatchQ(list.Parts[i], this.Parts[2], EmptyPD(), &es.CASLogger); matchq {
				toReturn.Parts = append(toReturn.Parts, list.Parts[i])
			}
		}

		return toReturn
	}
	return this
}
<|endoftext|>


<commit_before>// Copyright ©2012 Dan Kortschak <dan.kortschak@adelaide.edu.au>
//
// This program 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.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.

// Package llrb implements a Left-Leaning Red Black tree as described in
//  http://www.cs.princeton.edu/~rs/talks/LLRB/LLRB.pdf
//  http://www.cs.princeton.edu/~rs/talks/LLRB/Java/RedBlackBST.java
//  http://www.teachsolaisgames.com/articles/balanced_left_leaning.html
package llrb

const (
	TD234 = iota
	BU23
)

// Operation mode of the LLRB tree. Currently only BU23 tests as correct.
const Mode = BU23

// A Comparable is a type that can be inserted into a Tree or used as a range
// or equality query on the tree,
type Comparable interface {
	// Compare returns a value indicating the sort order relationship between the
	// receiver and the parameter.
	//
	// Given c = a.Compare(b):
	//  c < 0 if a r < b;
	//  c == 0 if a == b; and
	//  c > 0 if a > b.
	//
	Compare(Comparable) int
}

// A Color represents the color of a Node.
type Color bool

// String returns a string representation of a Color.
func (c Color) String() string {
	if c {
		return "Black"
	}
	return "Red"
}

const (
	// Red as false give us the defined behaviour that new nodes are red. Although this
	// is incorrect for the root node, that is resolved on the first insertion.
	Red   Color = false
	Black Color = true
)

// A Node represents a node in the LLRB tree.
type Node struct {
	Elem        Comparable
	Left, Right *Node
	Color       Color
}

// A Tree represent the root node of an LLRB tree. Public methods of nodes are exposed
// through this type.
type Tree Node

// Helper methods

// color returns the effect color of a Node. A nil node returns black.
func (self *Node) color() Color {
	if self == nil {
		return Black
	}
	return self.Color
}

// (a,c)b -rotL-> ((a,)b,)c
func (self *Node) rotateLeft() (root *Node) {
	// Assumes: self has two children.
	root = self.Right
	self.Right = root.Left
	root.Left = self
	root.Color = self.Color
	self.Color = Red
	return
}

// (a,c)b -rotR-> (,(,c)b)a
func (self *Node) rotateRight() (root *Node) {
	// Assumes: self has two children.
	root = self.Left
	self.Left = root.Right
	root.Right = self
	root.Color = self.Color
	self.Color = Red
	return
}

// (aR,cR)bB -flipC-> (aB,cB)bR | (aB,cB)bR -flipC-> (aR,cR)bB
func (self *Node) flipColors() {
	// Assumes: self has two children.
	self.Color = !self.Color
	self.Left.Color = !self.Left.Color
	self.Right.Color = !self.Right.Color
}

// fixUp ensures that black link balance is correct, that red nodes lean left,
// and that 4 nodes are split.
func (self *Node) fixUp() *Node {
	if self.Right.color() == Red {
		self = self.rotateLeft()
	}
	if self.Left.color() == Red && self.Left.Left.color() == Red {
		self = self.rotateRight()
	}
	if self.Left.color() == Red && self.Right.color() == Red {
		self.flipColors()
	}
	return self
}

func (self *Node) moveRedLeft() *Node {
	self.flipColors()
	if self.Right.Left.color() == Red {
		self.Right = self.Right.rotateRight()
		self = self.rotateLeft()
		self.flipColors()
	}
	return self
}

func (self *Node) moveRedRight() *Node {
	self.flipColors()
	if self.Left.Left.color() == Red {
		self = self.rotateRight()
		self.flipColors()
	}
	return self
}

// Get returns the first match of q in the Tree. If insertion without
// replacement is used, this is probably not what you want.
func (self *Tree) Get(q Comparable) Comparable {
	if self == nil {
		return nil
	}
	n := (*Node)(self).search(q)
	if n == nil {
		return nil
	}
	return n.Elem
}

func (self *Node) search(q Comparable) (n *Node) {
	n = self
	for n != nil {
		switch c := q.Compare(n.Elem); {
		case c == 0:
			return n
		case c < 0:
			n = n.Left
		default:
			n = n.Right
		}
	}

	return
}

// Insert inserts the Comparable e into the Tree at the first match found
// with e or when a nil node is reached. Insertion without replacement can
// specified by ensuring that e.Compare() never returns 0. If insert without
// replacement is performed, a distinct query Comparable must be used that
// does return 0 for a Compare() call.
func (self *Tree) Insert(e Comparable) (root *Tree) {
	root = (*Tree)((*Node)(self).insert(e))
	root.Color = Black
	return
}

func (self *Node) insert(e Comparable) (root *Node) {
	if self == nil {
		return &Node{Elem: e}
	} else if self.Elem == nil {
		self.Elem = e
		return self
	}

	if Mode == TD234 {
		if self.Left.color() == Red && self.Right.color() == Red {
			self.flipColors()
		}
	}

	switch c := e.Compare(self.Elem); {
	case c == 0:
		self.Elem = e
	case c < 0:
		self.Left = self.Left.insert(e)
	default:
		self.Right = self.Right.insert(e)
	}

	if self.Right.color() == Red && self.Left.color() == Black {
		self = self.rotateLeft()
	}
	if self.Left.color() == Red && self.Left.Left.color() == Red {
		self = self.rotateRight()
	}

	if Mode == BU23 {
		if self.Left.color() == Red && self.Right.color() == Red {
			self.flipColors()
		}
	}

	return self
}

// DeleteMin deletes the node with the minimum value in the tree.
func (self *Tree) DeleteMin() (root *Tree) {
	root = (*Tree)((*Node)(self).deleteMin())
	root.Color = Black
	return
}

func (self *Node) deleteMin() *Node {
	if self.Left == nil {
		return nil
	}
	if self.Left.color() == Black && self.Left.Left.color() == Black {
		self = self.moveRedLeft()
	}
	self.Left = self.Left.deleteMin()
	return self.fixUp()
}

// DeleteMax deletes the node with the maximum value in the tree.
func (self *Tree) DeleteMax() (root *Tree) {
	root = (*Tree)((*Node)(self).deleteMax())
	root.Color = Black
	return
}

func (self *Node) deleteMax() *Node {
	if self.Left != nil && self.Left.color() == Red {
		self = self.rotateRight()
	}
	if self.Right == nil {
		return nil
	}
	if self.Right.color() == Black && self.Right.Left.color() == Black {
		self = self.moveRedRight()
	}
	self.Right = self.Right.deleteMax()
	return self.fixUp()
}

// Delete deletes the first node found that matches e according to Compare().
func (self *Tree) Delete(e Comparable) (root *Tree) {
	root = (*Tree)((*Node)(self).delete(e))
	if root == nil {
		return
	}
	root.Color = Black
	return
}

func (self *Node) delete(e Comparable) (root *Node) {
	if self == nil {
		return
	}
	if e.Compare(self.Elem) < 0 {
		if self.Left.color() == Black && self.Left != nil && self.Left.Left.color() == Black {
			self = self.moveRedLeft()
		}
		self.Left = self.Left.delete(e)
	} else {
		if self.Left.color() == Red {
			self = self.rotateRight()
		}
		if e.Compare(self.Elem) == 0 && self.Right == nil {
			return nil
		}
		if self.Right.color() == Black && self.Right != nil && self.Right.Left.color() == Black {
			self = self.moveRedRight()
		}
		if e.Compare(self.Elem) == 0 {
			self.Elem = self.Right.min().Elem
			self.Right = self.Right.deleteMin()
		} else {
			self.Right = self.Right.delete(e)
		}
	}
	return self.fixUp()
}

// Return the minimum value stored in the tree. This will be the left-most value if
// insertion without replacement is allowed.
func (self *Tree) Min() Comparable {
	n := (*Node)(self).min()
	if n == nil {
		return nil
	}
	return n.Elem
}

func (self *Node) min() *Node {
	if self == nil {
		return nil
	}
	if self.Left == nil {
		return self
	}
	return self.Left.min()
}

// Return the maximum value stored in the tree. This will be the right-most value if
// insertion without replacement is allowed.
func (self *Tree) Max() Comparable {
	n := (*Node)(self).max()
	if n == nil {
		return nil
	}
	return n.Elem
}

func (self *Node) max() *Node {
	if self == nil {
		return nil
	}
	if self.Right == nil {
		return self
	}
	return self.Right.max()
}

// An Operation is a function that operates on a Comparable.
type Operation func(Comparable)

// Do performs fn on all values stored in the tree. If fn alters the values of
// stored values, future tree operation behaviors are undefined.
func (self *Tree) Do(fn Operation) {
	(*Node)(self).do(fn)
}

func (self *Node) do(fn Operation) {
	if self == nil {
		return
	}
	self.Left.do(fn)
	fn(self.Elem)
	self.Right.do(fn)
}

// DoRange performs fn on all values stored in the tree between from and to. If from is
// less than to, the operations are performed from left to right. If from is greater than
// to then the operations are performed from right to left. If fn alters the values of
// stored values, future tree operation behaviors are undefined.
func (self *Tree) DoRange(fn Operation, from, to Comparable) {
	switch order := from.Compare(to); {
	case order < 0:
		(*Node)(self).doRange(fn, from, to)
	case order > 0:
		(*Node)(self).doRangeReverse(fn, from, to)
	default:
		(*Node)(self).doMatch(fn, from)
	}
}

func (self *Node) doRange(fn Operation, from, to Comparable) {
	if self == nil {
		return
	}
	fc, tc := from.Compare(self.Elem), to.Compare(self.Elem)
	if fc <= 0 {
		self.Left.doRange(fn, from, to)
	}
	if fc <= 0 && tc >= 0 {
		fn(self.Elem)
	}
	if tc >= 0 {
		self.Right.doRange(fn, from, to)
	}
}

func (self *Node) doRangeReverse(fn Operation, from, to Comparable) {
	if self == nil {
		return
	}
	fc, tc := from.Compare(self.Elem), to.Compare(self.Elem)
	if tc >= 0 {
		self.Right.doRangeReverse(fn, from, to)
	}
	if fc <= 0 && tc >= 0 {
		fn(self.Elem)
	}
	if fc <= 0 {
		self.Left.doRangeReverse(fn, from, to)
	}
}

// DoMatch performs fn on all values stored in the tree that match q according to Compare.
// If fn alters the values of stored values, future tree operation behaviors are undefined.
func (self *Tree) DoMatching(fn Operation, q Comparable) {
	(*Node)(self).doMatch(fn, q)
}

func (self *Node) doMatch(fn Operation, q Comparable) {
	if self == nil {
		return
	}
	c := q.Compare(self.Elem)
	if c <= 0 {
		self.Left.doMatch(fn, q)
	}
	if c == 0 {
		fn(self.Elem)
	}
	if c >= 0 {
		self.Right.doMatch(fn, q)
	}
}
<commit_msg>Guard against nil receivers and returns<commit_after>// Copyright ©2012 Dan Kortschak <dan.kortschak@adelaide.edu.au>
//
// This program 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.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.

// Package llrb implements a Left-Leaning Red Black tree as described in
//  http://www.cs.princeton.edu/~rs/talks/LLRB/LLRB.pdf
//  http://www.cs.princeton.edu/~rs/talks/LLRB/Java/RedBlackBST.java
//  http://www.teachsolaisgames.com/articles/balanced_left_leaning.html
package llrb

const (
	TD234 = iota
	BU23
)

// Operation mode of the LLRB tree. Currently only BU23 tests as correct.
const Mode = BU23

// A Comparable is a type that can be inserted into a Tree or used as a range
// or equality query on the tree,
type Comparable interface {
	// Compare returns a value indicating the sort order relationship between the
	// receiver and the parameter.
	//
	// Given c = a.Compare(b):
	//  c < 0 if a r < b;
	//  c == 0 if a == b; and
	//  c > 0 if a > b.
	//
	Compare(Comparable) int
}

// A Color represents the color of a Node.
type Color bool

// String returns a string representation of a Color.
func (c Color) String() string {
	if c {
		return "Black"
	}
	return "Red"
}

const (
	// Red as false give us the defined behaviour that new nodes are red. Although this
	// is incorrect for the root node, that is resolved on the first insertion.
	Red   Color = false
	Black Color = true
)

// A Node represents a node in the LLRB tree.
type Node struct {
	Elem        Comparable
	Left, Right *Node
	Color       Color
}

// A Tree represent the root node of an LLRB tree. Public methods of nodes are exposed
// through this type.
type Tree Node

// Helper methods

// color returns the effect color of a Node. A nil node returns black.
func (self *Node) color() Color {
	if self == nil {
		return Black
	}
	return self.Color
}

// (a,c)b -rotL-> ((a,)b,)c
func (self *Node) rotateLeft() (root *Node) {
	// Assumes: self has two children.
	root = self.Right
	self.Right = root.Left
	root.Left = self
	root.Color = self.Color
	self.Color = Red
	return
}

// (a,c)b -rotR-> (,(,c)b)a
func (self *Node) rotateRight() (root *Node) {
	// Assumes: self has two children.
	root = self.Left
	self.Left = root.Right
	root.Right = self
	root.Color = self.Color
	self.Color = Red
	return
}

// (aR,cR)bB -flipC-> (aB,cB)bR | (aB,cB)bR -flipC-> (aR,cR)bB
func (self *Node) flipColors() {
	// Assumes: self has two children.
	self.Color = !self.Color
	self.Left.Color = !self.Left.Color
	self.Right.Color = !self.Right.Color
}

// fixUp ensures that black link balance is correct, that red nodes lean left,
// and that 4 nodes are split.
func (self *Node) fixUp() *Node {
	if self.Right.color() == Red {
		self = self.rotateLeft()
	}
	if self.Left.color() == Red && self.Left.Left.color() == Red {
		self = self.rotateRight()
	}
	if self.Left.color() == Red && self.Right.color() == Red {
		self.flipColors()
	}
	return self
}

func (self *Node) moveRedLeft() *Node {
	self.flipColors()
	if self.Right.Left.color() == Red {
		self.Right = self.Right.rotateRight()
		self = self.rotateLeft()
		self.flipColors()
	}
	return self
}

func (self *Node) moveRedRight() *Node {
	self.flipColors()
	if self.Left.Left.color() == Red {
		self = self.rotateRight()
		self.flipColors()
	}
	return self
}

// Get returns the first match of q in the Tree. If insertion without
// replacement is used, this is probably not what you want.
func (self *Tree) Get(q Comparable) Comparable {
	if self == nil {
		return nil
	}
	n := (*Node)(self).search(q)
	if n == nil {
		return nil
	}
	return n.Elem
}

func (self *Node) search(q Comparable) (n *Node) {
	n = self
	for n != nil {
		switch c := q.Compare(n.Elem); {
		case c == 0:
			return n
		case c < 0:
			n = n.Left
		default:
			n = n.Right
		}
	}

	return
}

// Insert inserts the Comparable e into the Tree at the first match found
// with e or when a nil node is reached. Insertion without replacement can
// specified by ensuring that e.Compare() never returns 0. If insert without
// replacement is performed, a distinct query Comparable must be used that
// does return 0 for a Compare() call.
func (self *Tree) Insert(e Comparable) (root *Tree) {
	root = (*Tree)((*Node)(self).insert(e))
	root.Color = Black
	return
}

func (self *Node) insert(e Comparable) (root *Node) {
	if self == nil {
		return &Node{Elem: e}
	} else if self.Elem == nil {
		self.Elem = e
		return self
	}

	if Mode == TD234 {
		if self.Left.color() == Red && self.Right.color() == Red {
			self.flipColors()
		}
	}

	switch c := e.Compare(self.Elem); {
	case c == 0:
		self.Elem = e
	case c < 0:
		self.Left = self.Left.insert(e)
	default:
		self.Right = self.Right.insert(e)
	}

	if self.Right.color() == Red && self.Left.color() == Black {
		self = self.rotateLeft()
	}
	if self.Left.color() == Red && self.Left.Left.color() == Red {
		self = self.rotateRight()
	}

	if Mode == BU23 {
		if self.Left.color() == Red && self.Right.color() == Red {
			self.flipColors()
		}
	}

	return self
}

// DeleteMin deletes the node with the minimum value in the tree.
func (self *Tree) DeleteMin() (root *Tree) {
	if self == nil {
		return
	}
	root = (*Tree)((*Node)(self).deleteMin())
	if root == nil {
		return
	}
	root.Color = Black
	return
}

func (self *Node) deleteMin() *Node {
	if self.Left == nil {
		return nil
	}
	if self.Left.color() == Black && self.Left.Left.color() == Black {
		self = self.moveRedLeft()
	}
	self.Left = self.Left.deleteMin()
	return self.fixUp()
}

// DeleteMax deletes the node with the maximum value in the tree.
func (self *Tree) DeleteMax() (root *Tree) {
	if self == nil {
		return
	}
	root = (*Tree)((*Node)(self).deleteMax())
	if root == nil {
		return
	}
	root.Color = Black
	return
}

func (self *Node) deleteMax() *Node {
	if self.Left != nil && self.Left.color() == Red {
		self = self.rotateRight()
	}
	if self.Right == nil {
		return nil
	}
	if self.Right.color() == Black && self.Right.Left.color() == Black {
		self = self.moveRedRight()
	}
	self.Right = self.Right.deleteMax()
	return self.fixUp()
}

// Delete deletes the first node found that matches e according to Compare().
func (self *Tree) Delete(e Comparable) (root *Tree) {
	root = (*Tree)((*Node)(self).delete(e))
	if root == nil {
		return
	}
	root.Color = Black
	return
}

func (self *Node) delete(e Comparable) (root *Node) {
	if self == nil {
		return
	}
	if e.Compare(self.Elem) < 0 {
		if self.Left.color() == Black && self.Left != nil && self.Left.Left.color() == Black {
			self = self.moveRedLeft()
		}
		self.Left = self.Left.delete(e)
	} else {
		if self.Left.color() == Red {
			self = self.rotateRight()
		}
		if e.Compare(self.Elem) == 0 && self.Right == nil {
			return nil
		}
		if self.Right.color() == Black && self.Right != nil && self.Right.Left.color() == Black {
			self = self.moveRedRight()
		}
		if e.Compare(self.Elem) == 0 {
			self.Elem = self.Right.min().Elem
			self.Right = self.Right.deleteMin()
		} else {
			self.Right = self.Right.delete(e)
		}
	}
	return self.fixUp()
}

// Return the minimum value stored in the tree. This will be the left-most value if
// insertion without replacement is allowed.
func (self *Tree) Min() Comparable {
	n := (*Node)(self).min()
	if n == nil {
		return nil
	}
	return n.Elem
}

func (self *Node) min() *Node {
	if self == nil {
		return nil
	}
	if self.Left == nil {
		return self
	}
	return self.Left.min()
}

// Return the maximum value stored in the tree. This will be the right-most value if
// insertion without replacement is allowed.
func (self *Tree) Max() Comparable {
	n := (*Node)(self).max()
	if n == nil {
		return nil
	}
	return n.Elem
}

func (self *Node) max() *Node {
	if self == nil {
		return nil
	}
	if self.Right == nil {
		return self
	}
	return self.Right.max()
}

// An Operation is a function that operates on a Comparable.
type Operation func(Comparable)

// Do performs fn on all values stored in the tree. If fn alters the values of
// stored values, future tree operation behaviors are undefined.
func (self *Tree) Do(fn Operation) {
	(*Node)(self).do(fn)
}

func (self *Node) do(fn Operation) {
	if self == nil {
		return
	}
	self.Left.do(fn)
	fn(self.Elem)
	self.Right.do(fn)
}

// DoRange performs fn on all values stored in the tree between from and to. If from is
// less than to, the operations are performed from left to right. If from is greater than
// to then the operations are performed from right to left. If fn alters the values of
// stored values, future tree operation behaviors are undefined.
func (self *Tree) DoRange(fn Operation, from, to Comparable) {
	switch order := from.Compare(to); {
	case order < 0:
		(*Node)(self).doRange(fn, from, to)
	case order > 0:
		(*Node)(self).doRangeReverse(fn, from, to)
	default:
		(*Node)(self).doMatch(fn, from)
	}
}

func (self *Node) doRange(fn Operation, from, to Comparable) {
	if self == nil {
		return
	}
	fc, tc := from.Compare(self.Elem), to.Compare(self.Elem)
	if fc <= 0 {
		self.Left.doRange(fn, from, to)
	}
	if fc <= 0 && tc >= 0 {
		fn(self.Elem)
	}
	if tc >= 0 {
		self.Right.doRange(fn, from, to)
	}
}

func (self *Node) doRangeReverse(fn Operation, from, to Comparable) {
	if self == nil {
		return
	}
	fc, tc := from.Compare(self.Elem), to.Compare(self.Elem)
	if tc >= 0 {
		self.Right.doRangeReverse(fn, from, to)
	}
	if fc <= 0 && tc >= 0 {
		fn(self.Elem)
	}
	if fc <= 0 {
		self.Left.doRangeReverse(fn, from, to)
	}
}

// DoMatch performs fn on all values stored in the tree that match q according to Compare.
// If fn alters the values of stored values, future tree operation behaviors are undefined.
func (self *Tree) DoMatching(fn Operation, q Comparable) {
	(*Node)(self).doMatch(fn, q)
}

func (self *Node) doMatch(fn Operation, q Comparable) {
	if self == nil {
		return
	}
	c := q.Compare(self.Elem)
	if c <= 0 {
		self.Left.doMatch(fn, q)
	}
	if c == 0 {
		fn(self.Elem)
	}
	if c >= 0 {
		self.Right.doMatch(fn, q)
	}
}
<|endoftext|>


<commit_before>/*  lMDQ is a MDQ server that caches metadata locally so it's local clients can lookup
    pre-checked metadata and not depend on a working connection to a remote MDQ server.

    It uses SQLite as it's datastore and allows lookup by either entityID or Location.
    The latter is used by WAYF for it's mass hosting services BIRK and KRIB.

    It can also be used as a library for just looking up metadata inside a go program.

    Or a client can use the SQLite database directly using the following query:

		"select e.md, e.hash from entity e, lookup l where l.hash = $1 and l.entity_id_fk = e.id and e.validuntil >= $2"

    where $1 is the lowercase hex sha1 of the entityID or location without the {sha1} prefix
    $2 is the current epoch.

    to-do:
        √ caching interface
          invalidate cache ???
*/

package lmdq

import (
	"crypto/sha1"
	"database/sql"
	"encoding/hex"
	"errors"
	"io/ioutil"
	"net/http"
	"net/url"
	// 	_ "github.com/mattn/go-sqlite3" for handling sqlite3
	_ "github.com/mattn/go-sqlite3"
	"github.com/wayf-dk/gosaml"
	"github.com/wayf-dk/goxml"
	"regexp"
	"sort"
	"strings"
	"sync"
	"time"
)

type (
	// EntityRec refers entity info
	EntityRec struct {
		id       int64
		entityid string
		hash     string
	}
	// MDQ refers to metadata query
	MDQ struct {
		db                *sql.DB
		stmt              *sql.Stmt
		Path              string
		Cache             map[string]*MdXp
		Lock              sync.RWMutex
		Table, Rev, Short string
		mdq               bool
	}
	// MdXp refers to check validity
	MdXp struct {
		*goxml.Xp
		xml     []byte
		created time.Time
	}
)

var (
	cacheduration = time.Minute * 60
	// MetaDataNotFoundError refers to error
	MetaDataNotFoundError = errors.New("Metadata not found")
	hexChars              = regexp.MustCompile("^[a-fA-F0-9]+$")
)

// Valid refers to check the validity of metadata
func (xp *MdXp) Valid(duration time.Duration) bool {
	since := time.Since(xp.created)
	//log.Println(since, duration, since  < duration)
	return since < duration
}

// Open refers to open metadata file
func (mdq *MDQ) Open() (err error) {
	mdq.mdq = strings.HasPrefix(mdq.Path, "http")
	if mdq.mdq {
		return
	}
	mdq.Lock.Lock()
	defer mdq.Lock.Unlock()
	mdq.Cache = make(map[string]*MdXp)
	if mdq.db != nil {
		mdq.db.Close()
	}
	mdq.db, err = sql.Open("sqlite3", mdq.Path)
	if err != nil {
		return
	}
	mdq.stmt, err = mdq.db.Prepare("select e.md md from entity_" + mdq.Table + " e, lookup_" + mdq.Table + " l where ? < l.hash||'z' and l.hash||'z' <= ? and l.entity_id_fk = e.id")
	// This is supposed to be a very smart wayf do to prefix search - keep an eye on whether a 10 char prefix ie. using 40 bits is enough
	if err != nil {
		return
	}
	return
}

// MDQ looks up an entity using the supplied feed and key.
// The key can be an entityID or a location, optionally in {sha1} format
// It returns a non nil err if the entity is not found
// and the metadata and a hash/etag over the content if it is.
// The hash can be used to decide if a cached dom object is still valid,
// This might be an optimization as the database lookup is much faster that the parsing.
func (mdq *MDQ) MDQ(key string) (xp *goxml.Xp, err error) {
	xp, _, err = mdq.dbget(key, true)
	return
}

// WebMDQ - Export of dbget
func (mdq *MDQ) WebMDQ(key string) (xp *goxml.Xp, xml []byte, err error) {
	return mdq.dbget(key, true)
}

func (mdq *MDQ) dbget(key string, cache bool) (xp *goxml.Xp, xml []byte, err error) {
	if mdq.mdq {
		client := &http.Client{}
		q := mdq.Path + url.PathEscape(key)
		req, _ := http.NewRequest("GET", q, nil)
		response, err := client.Do(req)

		if err != nil || response.StatusCode == 500 {
	    		err = goxml.Wrap(MetaDataNotFoundError, "err:Metadata not found", "key:"+key, "table:"+mdq.Short)
			return nil, nil, err
		}

		defer response.Body.Close()
		xml, err = ioutil.ReadAll(response.Body)
		if err != nil {
			return nil, nil, err
		}
		//md := gosaml.Inflate(xml)
		xp = goxml.NewXp(xml)
		return xp, xml, err
	}

	k := key
	if strings.HasPrefix(key, "{sha1}") {
		key = key[6:]
	} else if hexChars.MatchString(key) {
		// already sha1'ed - do nothing
	} else {
		hash := sha1.Sum([]byte(key))
		key = hex.EncodeToString(append(hash[:]))
	}
	//key = key[:10] // only use the first 10 chars for key - why on earth do that???
	mdq.Lock.RLock()
	cachedxp := mdq.Cache[key]
	if cachedxp != nil && cachedxp.Valid(cacheduration) {
		xp = cachedxp.Xp.CpXp()
		xml = cachedxp.xml
		mdq.Lock.RUnlock()
		return
	}
	mdq.Lock.RUnlock()

	err = mdq.stmt.QueryRow(key, key+"z").Scan(&xml)
	switch {
	case err == sql.ErrNoRows:
		err = goxml.Wrap(MetaDataNotFoundError, "err:Metadata not found", "key:"+k, "table:"+mdq.Short)
		return
	case err != nil:
		return
	default:
		md := gosaml.Inflate(xml)
		xp = goxml.NewXp(md)
	}
	if cache {
		mdxp := new(MdXp)
		mdxp.Xp = xp
		mdxp.xml = xml
		mdxp.created = time.Now()
		mdq.Lock.Lock()
		mdq.Cache[key] = mdxp
		mdq.Lock.Unlock()
	}
	return
}

// MDQFilter refers Filtering by xpath for testing purposes
func (mdq *MDQ) MDQFilter(xpathfilter string) (xp *goxml.Xp, numberOfEntities int, err error) {
	recs, err := mdq.getEntityList()
	if err != nil {
		return
	}

	// get the entities into an ordered slice
	index := make([]string, len(recs))
	i := 0
	for k := range recs {
		index[i] = k
		i++
	}
	sort.Strings(index)

	//log.Println(xpathfilter)
	xp = goxml.NewXpFromString(`<md:EntitiesDescriptor xmlns:md="urn:oasis:names:tc:SAML:2.0:metadata" />`)

	root, _ := xp.Doc.DocumentElement()
	for _, entityID := range index {
		ent, _, _ := mdq.dbget(entityID, false)

		if xpathfilter == "" || len(ent.Query(nil, xpathfilter)) > 0 {
			entity, _ := ent.Doc.DocumentElement()
			root.AddChild(xp.CopyNode(entity, 1))
			numberOfEntities++
		}
	}
	return
}

// getEntityList returns a map keyed by entityIDs for the
// current entities in the database
func (mdq *MDQ) getEntityList() (entities map[string]EntityRec, err error) {

	entities = make(map[string]EntityRec)
	var rows *sql.Rows
	rows, err = mdq.db.Query("select id, entityid, hash from entity_" + mdq.Table)
	if err != nil {
		return
	}
	defer rows.Close()
	for rows.Next() {
		var rec EntityRec
		if err = rows.Scan(&rec.id, &rec.entityid, &rec.hash); err != nil {
			return
		}
		entities[rec.entityid] = rec
	}
	if err = rows.Err(); err != nil { // no reason to actually check err, but if we later forget ...
		return
	}
	return
}
<commit_msg>Moved test mdq via localhost to lmdq2.go - controlled by buildtag<commit_after>// +build !testmdq

/*  lMDQ is a MDQ server that caches metadata locally so it's local clients can lookup
    pre-checked metadata and not depend on a working connection to a remote MDQ server.

    It uses SQLite as it's datastore and allows lookup by either entityID or Location.
    The latter is used by WAYF for it's mass hosting services BIRK and KRIB.

    It can also be used as a library for just looking up metadata inside a go program.

    Or a client can use the SQLite database directly using the following query:

		"select e.md, e.hash from entity e, lookup l where l.hash = $1 and l.entity_id_fk = e.id and e.validuntil >= $2"

    where $1 is the lowercase hex sha1 of the entityID or location without the {sha1} prefix
    $2 is the current epoch.

    to-do:
        √ caching interface
          invalidate cache ???
*/

package lmdq

import (
	"crypto/sha1"
	"database/sql"
	"encoding/hex"
	"errors"
	_ "github.com/mattn/go-sqlite3"
	"github.com/wayf-dk/gosaml"
	"github.com/wayf-dk/goxml"
	"regexp"
	"sort"
	"strings"
	"sync"
	"time"
)

type (
	// EntityRec refers entity info
	EntityRec struct {
		id       int64
		entityid string
		hash     string
	}
	// MDQ refers to metadata query
	MDQ struct {
		db                *sql.DB
		stmt              *sql.Stmt
		Path              string
		Cache             map[string]*MdXp
		Lock              sync.RWMutex
		Table, Rev, Short string
	}
	// MdXp refers to check validity
	MdXp struct {
		*goxml.Xp
		xml     []byte
		created time.Time
	}
)

var (
	cacheduration = time.Minute * 60
	// MetaDataNotFoundError refers to error
	MetaDataNotFoundError = errors.New("Metadata not found")
	hexChars              = regexp.MustCompile("^[a-fA-F0-9]+$")
)

// Valid refers to check the validity of metadata
func (xp *MdXp) Valid(duration time.Duration) bool {
	since := time.Since(xp.created)
	//log.Println(since, duration, since  < duration)
	return since < duration
}

// Open refers to open metadata file
func (mdq *MDQ) Open() (err error) {
	mdq.Lock.Lock()
	defer mdq.Lock.Unlock()
	mdq.Cache = make(map[string]*MdXp)
	if mdq.db != nil {
		mdq.db.Close()
	}
	mdq.db, err = sql.Open("sqlite3", mdq.Path)
	if err != nil {
		return
	}
	mdq.stmt, err = mdq.db.Prepare("select e.md md from entity_" + mdq.Table + " e, lookup_" + mdq.Table + " l where ? < l.hash||'z' and l.hash||'z' <= ? and l.entity_id_fk = e.id")
	// This is supposed to be a very smart wayf do to prefix search - keep an eye on whether a 10 char prefix ie. using 40 bits is enough
	if err != nil {
		return
	}
	return
}

// MDQ looks up an entity using the supplied feed and key.
// The key can be an entityID or a location, optionally in {sha1} format
// It returns a non nil err if the entity is not found
// and the metadata and a hash/etag over the content if it is.
// The hash can be used to decide if a cached dom object is still valid,
// This might be an optimization as the database lookup is much faster that the parsing.
func (mdq *MDQ) MDQ(key string) (xp *goxml.Xp, err error) {
	xp, _, err = mdq.dbget(key, true)
	return
}

// WebMDQ - Export of dbget
func (mdq *MDQ) WebMDQ(key string) (xp *goxml.Xp, xml []byte, err error) {
	return mdq.dbget(key, true)
}

func (mdq *MDQ) dbget(key string, cache bool) (xp *goxml.Xp, xml []byte, err error) {
	k := key
	if strings.HasPrefix(key, "{sha1}") {
		key = key[6:]
	} else if hexChars.MatchString(key) {
		// already sha1'ed - do nothing
	} else {
		hash := sha1.Sum([]byte(key))
		key = hex.EncodeToString(append(hash[:]))
	}
	//key = key[:10] // only use the first 10 chars for key - why on earth do that???
	mdq.Lock.RLock()
	cachedxp := mdq.Cache[key]
	if cachedxp != nil && cachedxp.Valid(cacheduration) {
		xp = cachedxp.Xp.CpXp()
		xml = cachedxp.xml
		mdq.Lock.RUnlock()
		return
	}
	mdq.Lock.RUnlock()

	err = mdq.stmt.QueryRow(key, key+"z").Scan(&xml)
	switch {
	case err == sql.ErrNoRows:
		err = goxml.Wrap(MetaDataNotFoundError, "err:Metadata not found", "key:"+k, "table:"+mdq.Short)
		return
	case err != nil:
		return
	default:
		md := gosaml.Inflate(xml)
		xp = goxml.NewXp(md)
	}
	if cache {
		mdxp := new(MdXp)
		mdxp.Xp = xp
		mdxp.xml = xml
		mdxp.created = time.Now()
		mdq.Lock.Lock()
		mdq.Cache[key] = mdxp
		mdq.Lock.Unlock()
	}
	return
}

// MDQFilter refers Filtering by xpath for testing purposes
func (mdq *MDQ) MDQFilter(xpathfilter string) (xp *goxml.Xp, numberOfEntities int, err error) {
	recs, err := mdq.getEntityList()
	if err != nil {
		return
	}

	// get the entities into an ordered slice
	index := make([]string, len(recs))
	i := 0
	for k := range recs {
		index[i] = k
		i++
	}
	sort.Strings(index)

	//log.Println(xpathfilter)
	xp = goxml.NewXpFromString(`<md:EntitiesDescriptor xmlns:md="urn:oasis:names:tc:SAML:2.0:metadata" />`)

	root, _ := xp.Doc.DocumentElement()
	for _, entityID := range index {
		ent, _, _ := mdq.dbget(entityID, false)

		if xpathfilter == "" || len(ent.Query(nil, xpathfilter)) > 0 {
			entity, _ := ent.Doc.DocumentElement()
			root.AddChild(xp.CopyNode(entity, 1))
			numberOfEntities++
		}
	}
	return
}

// getEntityList returns a map keyed by entityIDs for the
// current entities in the database
func (mdq *MDQ) getEntityList() (entities map[string]EntityRec, err error) {

	entities = make(map[string]EntityRec)
	var rows *sql.Rows
	rows, err = mdq.db.Query("select id, entityid, hash from entity_" + mdq.Table)
	if err != nil {
		return
	}
	defer rows.Close()
	for rows.Next() {
		var rec EntityRec
		if err = rows.Scan(&rec.id, &rec.entityid, &rec.hash); err != nil {
			return
		}
		entities[rec.entityid] = rec
	}
	if err = rows.Err(); err != nil { // no reason to actually check err, but if we later forget ...
		return
	}
	return
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/aws/awserr"
	"github.com/aws/aws-sdk-go/aws/credentials"
	"github.com/aws/aws-sdk-go/aws/session"
	"github.com/guregu/dynamo"
	"github.com/satori/go.uuid"
	"gopkg.in/codegangsta/cli.v2"
	"os"
	"os/exec"
	"time"
)

type Record struct {
	Hkey          string `dynamo:"Hkey,hash"`
	TransactionId string
	Expires       int
}

type Lock struct {
	Table         dynamo.Table
	TransactionId string
	Hkey          string
}

func (record Record) isExpire() bool {
	return record.Expires < int(time.Now().Unix())
}

func isConditionalCheckErr(err error) bool {
	if ae, ok := err.(awserr.RequestFailure); ok {
		return ae.Code() == "ConditionalCheckFailedException"
	}
	return false
}

func (lock Lock) acquire(expires int) error {
	record := Record{
		Hkey:          lock.Hkey,
		TransactionId: lock.TransactionId,
		Expires:       int(time.Now().Unix()) + expires}
	err := lock.Table.Put(record).
		If("attribute_not_exists(Hkey)").
		Run()
	// if attribute exists.
	// Check it's expires time, and begin acquire if expired.
	if !isConditionalCheckErr(err) {
		return err
	}
	lock.Table.Get("Hkey", lock.Hkey).One(&record)
	if record.isExpire() {
		err := lock.Table.Put(record).Run()
		if err != nil {
			return err
		}
	} else {
		return fmt.Errorf("failed acquire. transaction:%s running and not expires", record.TransactionId)
	}
	return nil
}

func (lock Lock) release() error {
	err := lock.Table.Delete("Hkey", lock.Hkey).
		If("begins_with(TransactionId, ?)", lock.TransactionId).
		Run()
	// if same transaction id is not found.
	// Other transaction begin, because this transaction expires.
	if !isConditionalCheckErr(err) {
		return err
	}
	return nil
}

func NewLock(table dynamo.Table, hkey string) Lock {
	return Lock{
		Table:         table,
		TransactionId: uuid.NewV4().String(),
		Hkey:          hkey,
	}
}

func main() {
	var region string
	var table string
	var domain string
	var expires int
	var access_key string
	var secret_key string
	app := cli.NewApp()
	app.Name = "lock"
	app.Usage = "acquire 'lock' to following commands."
	app.Flags = []cli.Flag{
		cli.StringFlag{
			Name:        "region, r",
			Value:       "ap-northeast-1",
			Usage:       "Specify Region name",
			Destination: &region,
		},
		cli.StringFlag{
			Name:        "table, t",
			Usage:       "Specify Table name",
			Destination: &table,
		},
		cli.StringFlag{
			Name:        "aws_access_key_id",
			Usage:       "",
			Destination: &access_key,
			EnvVar:      "AWS_ACCESS_KEY_ID",
		},
		cli.StringFlag{
			Name:        "aws_secret_access_key",
			Usage:       "",
			Destination: &secret_key,
			EnvVar:      "AWS_SECRET_ACCESS_KEY",
		},
	}
	app.Commands = []cli.Command{
		{
			Name:  "create-table",
			Usage: "Create table then exit",
			Action: func(c *cli.Context) error {
				db := dynamo.New(session.New(), &aws.Config{
					Region:     aws.String(region),
					DisableSSL: aws.Bool(true),
					Credentials: credentials.NewStaticCredentials(
						access_key, secret_key, ""),
				})
				return db.CreateTable(table, Record{}).Run()
			},
		},
		{
			Name:  "run",
			Usage: "run command in distributed lock",
			Flags: []cli.Flag{
				cli.StringFlag{
					Name:        "domain, d",
					Usage:       "Specify Lock resource name.",
					Destination: &domain,
				},
				cli.IntFlag{
					Name:        "expires, e",
					Usage:       "Specify Expire duration as seconds.",
					Destination: &expires,
				},
			},
			Action: func(c *cli.Context) error {
				if c.NArg() == 0 {
					return fmt.Errorf("No command to exec.")
				}
				db := dynamo.New(session.New(), &aws.Config{
					Region: aws.String(region),
					Credentials: credentials.NewStaticCredentials(
						access_key, secret_key, ""),
				})
				lock := NewLock(db.Table(table), domain)
				return func() error {
					err := lock.acquire(expires)
					defer lock.release()
					if err != nil {
						return err
					}
					cmd := exec.Command(c.Args().First(), c.Args()[1:]...)
					cmd.Stdout = os.Stdout
					cmd.Stderr = os.Stderr
					err = cmd.Run()
					if err != nil {
						return err
					}
					return nil
				}()
			},
		},
	}
	err := app.Run(os.Args)
	if err != nil {
		fmt.Println(err)
		os.Exit(1)
	}
}
<commit_msg>v0.1.0<commit_after>package main

import (
	"fmt"
	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/aws/awserr"
	"github.com/aws/aws-sdk-go/aws/credentials"
	"github.com/aws/aws-sdk-go/aws/session"
	"github.com/guregu/dynamo"
	"github.com/satori/go.uuid"
	"gopkg.in/codegangsta/cli.v2"
	"os"
	"os/exec"
	"time"
)

type Record struct {
	Hkey          string `dynamo:"Hkey,hash"`
	TransactionId string
	Expires       int
}

type Lock struct {
	Table         dynamo.Table
	TransactionId string
	Hkey          string
}

func (record Record) isExpire() bool {
	return record.Expires < int(time.Now().Unix())
}

func isConditionalCheckErr(err error) bool {
	if ae, ok := err.(awserr.RequestFailure); ok {
		return ae.Code() == "ConditionalCheckFailedException"
	}
	return false
}

func (lock Lock) acquire(expires int) error {
	record := Record{
		Hkey:          lock.Hkey,
		TransactionId: lock.TransactionId,
		Expires:       int(time.Now().Unix()) + expires}
	err := lock.Table.Put(record).
		If("attribute_not_exists(Hkey)").
		Run()
	// if attribute exists.
	// Check it's expires time, and begin acquire if expired.
	if !isConditionalCheckErr(err) {
		return err
	}
	lock.Table.Get("Hkey", lock.Hkey).One(&record)
	if record.isExpire() {
		err := lock.Table.Put(record).Run()
		if err != nil {
			return err
		}
	} else {
		return fmt.Errorf("failed acquire. transaction:%s running and not expires", record.TransactionId)
	}
	return nil
}

func (lock Lock) release() error {
	err := lock.Table.Delete("Hkey", lock.Hkey).
		If("begins_with(TransactionId, ?)", lock.TransactionId).
		Run()
	// if same transaction id is not found.
	// Other transaction begin, because this transaction expires.
	if !isConditionalCheckErr(err) {
		return err
	}
	return nil
}

func NewLock(table dynamo.Table, hkey string) Lock {
	return Lock{
		Table:         table,
		TransactionId: uuid.NewV4().String(),
		Hkey:          hkey,
	}
}

func main() {
	var region string
	var table string
	var domain string
	var expires int
	var access_key string
	var secret_key string
	app := cli.NewApp()
	app.Name = "lock"
	app.Usage = "acquire 'lock' to following commands."
	app.Version = "0.1.0"
	app.Flags = []cli.Flag{
		cli.StringFlag{
			Name:        "region, r",
			Value:       "ap-northeast-1",
			Usage:       "Specify Region name",
			Destination: &region,
		},
		cli.StringFlag{
			Name:        "table, t",
			Usage:       "Specify Table name",
			Destination: &table,
		},
		cli.StringFlag{
			Name:        "aws_access_key_id",
			Usage:       "",
			Destination: &access_key,
			EnvVar:      "AWS_ACCESS_KEY_ID",
		},
		cli.StringFlag{
			Name:        "aws_secret_access_key",
			Usage:       "",
			Destination: &secret_key,
			EnvVar:      "AWS_SECRET_ACCESS_KEY",
		},
	}
	app.Commands = []cli.Command{
		{
			Name:  "create-table",
			Usage: "Create table then exit",
			Action: func(c *cli.Context) error {
				db := dynamo.New(session.New(), &aws.Config{
					Region:     aws.String(region),
					DisableSSL: aws.Bool(true),
					Credentials: credentials.NewStaticCredentials(
						access_key, secret_key, ""),
				})
				return db.CreateTable(table, Record{}).Run()
			},
		},
		{
			Name:  "run",
			Usage: "run command in distributed lock",
			Flags: []cli.Flag{
				cli.StringFlag{
					Name:        "domain, d",
					Usage:       "Specify Lock resource name.",
					Destination: &domain,
				},
				cli.IntFlag{
					Name:        "expires, e",
					Usage:       "Specify Expire duration as seconds.",
					Destination: &expires,
				},
			},
			Action: func(c *cli.Context) error {
				if c.NArg() == 0 {
					return fmt.Errorf("No command to exec.")
				}
				db := dynamo.New(session.New(), &aws.Config{
					Region: aws.String(region),
					Credentials: credentials.NewStaticCredentials(
						access_key, secret_key, ""),
				})
				lock := NewLock(db.Table(table), domain)
				return func() error {
					err := lock.acquire(expires)
					defer lock.release()
					if err != nil {
						return err
					}
					cmd := exec.Command(c.Args().First(), c.Args()[1:]...)
					cmd.Stdout = os.Stdout
					cmd.Stderr = os.Stderr
					err = cmd.Run()
					if err != nil {
						return err
					}
					return nil
				}()
			},
		},
	}
	err := app.Run(os.Args)
	if err != nil {
		fmt.Println(err)
		os.Exit(1)
	}
}
<|endoftext|>


<commit_before>package listeners

import (
	"net"
	"net/http"
	"sync"
	"time"

	"github.com/getlantern/measured"
)

const (
	rateInterval = 1 * time.Second
)

// MeasuredReportFN is a function that gets called to report stats from the
// measured connection. deltaStats is like stats except that SentTotal and
// RecvTotal are deltas relative to the prior reported stats. final indicates
// whether this is the last call for a connection (i.e. connection has been
// closed).
type MeasuredReportFN func(ctx map[string]interface{}, stats *measured.Stats, deltaStats *measured.Stats,
	final bool)

// Wrapped stateAwareMeasuredListener that generates the wrapped wrapMeasuredConn
type stateAwareMeasuredListener struct {
	net.Listener
	reportInterval time.Duration
	report         MeasuredReportFN
}

func NewMeasuredListener(l net.Listener, reportInterval time.Duration, report MeasuredReportFN) net.Listener {
	return &stateAwareMeasuredListener{l, reportInterval, report}
}

func (l *stateAwareMeasuredListener) Accept() (c net.Conn, err error) {
	c, err = l.Listener.Accept()
	if err != nil {
		return nil, err
	}
	fs := make(chan *measured.Stats)
	wc := &wrapMeasuredConn{
		Conn: measured.Wrap(c, rateInterval, func(mc measured.Conn) {
			fs <- mc.Stats()
		}),
		ctx:        make(map[string]interface{}),
		finalStats: make(chan *measured.Stats),
	}
	sac, _ := c.(WrapConnEmbeddable)
	wc.WrapConnEmbeddable = sac
	go wc.track(l.reportInterval, l.report)
	return wc, nil
}

// Wrapped MeasuredConn that supports OnState
type wrapMeasuredConn struct {
	WrapConnEmbeddable
	measured.Conn
	ctx        map[string]interface{}
	ctxMx      sync.RWMutex
	finalStats chan *measured.Stats
}

func (c *wrapMeasuredConn) track(reportInterval time.Duration, report MeasuredReportFN) {
	ticker := time.NewTicker(reportInterval)
	var priorStats *measured.Stats
	applyStats := func(stats *measured.Stats, final bool) {
		deltaStats := stats
		if priorStats != nil {
			deltaStats.SentTotal -= priorStats.SentTotal
			deltaStats.RecvTotal -= priorStats.RecvTotal
		}
		priorStats = stats
		c.ctxMx.RLock()
		ctx := c.ctx
		c.ctxMx.RUnlock()
		report(ctx, stats, deltaStats, final)
	}

	for {
		select {
		case <-ticker.C:
			applyStats(c.Conn.Stats(), false)
		case stats := <-c.finalStats:
			applyStats(stats, true)
			return
		}
	}
}

func (c *wrapMeasuredConn) OnState(s http.ConnState) {
	if c.WrapConnEmbeddable != nil {
		c.WrapConnEmbeddable.OnState(s)
	}
}

// Responds to the "measured" message type
func (c *wrapMeasuredConn) ControlMessage(msgType string, data interface{}) {
	if msgType == "measured" {
		ctxUpdate := data.(map[string]interface{})
		c.ctxMx.Lock()
		defer c.ctxMx.Unlock()
		newContext := make(map[string]interface{}, len(c.ctx))
		// Copy context
		for key, value := range c.ctx {
			newContext[key] = value
		}
		// Update context
		for key, value := range ctxUpdate {
			newContext[key] = value
		}
		c.ctx = newContext
	}

	if c.WrapConnEmbeddable != nil {
		// Pass it down too, just in case other wrapper does something with
		c.WrapConnEmbeddable.ControlMessage(msgType, data)
	}
}
<commit_msg>Code review updates<commit_after>package listeners

import (
	"net"
	"net/http"
	"sync"
	"time"

	"github.com/getlantern/measured"
)

const (
	rateInterval = 1 * time.Second
)

// MeasuredReportFN is a function that gets called to report stats from the
// measured connection. deltaStats is like stats except that SentTotal and
// RecvTotal are deltas relative to the prior reported stats. final indicates
// whether this is the last call for a connection (i.e. connection has been
// closed).
type MeasuredReportFN func(ctx map[string]interface{}, stats *measured.Stats, deltaStats *measured.Stats,
	final bool)

// Wrapped stateAwareMeasuredListener that generates the wrapped wrapMeasuredConn
type stateAwareMeasuredListener struct {
	net.Listener
	reportInterval time.Duration
	report         MeasuredReportFN
}

func NewMeasuredListener(l net.Listener, reportInterval time.Duration, report MeasuredReportFN) net.Listener {
	return &stateAwareMeasuredListener{l, reportInterval, report}
}

func (l *stateAwareMeasuredListener) Accept() (c net.Conn, err error) {
	c, err = l.Listener.Accept()
	if err != nil {
		return nil, err
	}
	fs := make(chan *measured.Stats)
	wc := &wrapMeasuredConn{
		Conn: measured.Wrap(c, rateInterval, func(mc measured.Conn) {
			fs <- mc.Stats()
		}),
		ctx:        make(map[string]interface{}),
		finalStats: fs,
	}
	sac, _ := c.(WrapConnEmbeddable)
	wc.WrapConnEmbeddable = sac
	go wc.track(l.reportInterval, l.report)
	return wc, nil
}

// Wrapped MeasuredConn that supports OnState
type wrapMeasuredConn struct {
	WrapConnEmbeddable
	measured.Conn
	ctx        map[string]interface{}
	ctxMx      sync.RWMutex
	finalStats chan *measured.Stats
}

func (c *wrapMeasuredConn) track(reportInterval time.Duration, report MeasuredReportFN) {
	ticker := time.NewTicker(reportInterval)
	var priorStats *measured.Stats
	applyStats := func(stats *measured.Stats, final bool) {
		deltaStats := stats
		if priorStats != nil {
			deltaStats.SentTotal -= priorStats.SentTotal
			deltaStats.RecvTotal -= priorStats.RecvTotal
		}
		priorStats = stats
		c.ctxMx.RLock()
		ctx := c.ctx
		c.ctxMx.RUnlock()
		report(ctx, stats, deltaStats, final)
	}

	for {
		select {
		case <-ticker.C:
			applyStats(c.Conn.Stats(), false)
		case stats := <-c.finalStats:
			applyStats(stats, true)
			return
		}
	}
}

func (c *wrapMeasuredConn) OnState(s http.ConnState) {
	if c.WrapConnEmbeddable != nil {
		c.WrapConnEmbeddable.OnState(s)
	}
}

// Responds to the "measured" message type
func (c *wrapMeasuredConn) ControlMessage(msgType string, data interface{}) {
	if msgType == "measured" {
		ctxUpdate := data.(map[string]interface{})
		c.ctxMx.Lock()
		defer c.ctxMx.Unlock()
		newContext := make(map[string]interface{}, len(c.ctx))
		// Copy context
		for key, value := range c.ctx {
			newContext[key] = value
		}
		// Update context
		for key, value := range ctxUpdate {
			newContext[key] = value
		}
		c.ctx = newContext
	}

	if c.WrapConnEmbeddable != nil {
		// Pass it down too, just in case other wrapper does something with
		c.WrapConnEmbeddable.ControlMessage(msgType, data)
	}
}
<|endoftext|>


<commit_before>// List of Integers, Implements List interface

// Initial attempt at implementing list interface. Inefficient, useful for
// testing against more complex implementations.

package list

type List []int

// Len: length of list
func (l *List) Len() int {
	return len(*l)
}

// Get item at index i
func (l *List) Get(i int) int {
	return (*l)[i]
}

// Set item at index i to x
func (l *List) Set(i, x int) {
	(*l)[i] = x
}

// Insert x at index i
func (l *List) Insert(i, x int) {
	if l.Len() != i {
		panic("insert at end of list only")
	}
	*l = append(*l, x)
}

// Delete item at index i
func (l *List) Delete(i int) {
	*l = append((*l)[:i], (*l)[i+1:]...)
}
<commit_msg>Capitalize List in package comment<commit_after>// List of Integers, Implements list interface

// Initial attempt at implementing list interface. Inefficient, useful for
// testing against more complex implementations.

package list

type List []int

// Len: length of list
func (l *List) Len() int {
	return len(*l)
}

// Get item at index i
func (l *List) Get(i int) int {
	return (*l)[i]
}

// Set item at index i to x
func (l *List) Set(i, x int) {
	(*l)[i] = x
}

// Insert x at index i
func (l *List) Insert(i, x int) {
	if l.Len() != i {
		panic("insert at end of list only")
	}
	*l = append(*l, x)
}

// Delete item at index i
func (l *List) Delete(i int) {
	*l = append((*l)[:i], (*l)[i+1:]...)
}
<|endoftext|>


<commit_before>package logging

import (
	"compress/gzip"
	"io"
	"os/exec"
	"time"
)

type RemoteLog struct {
	Host          string
	User          string
	Pattern       string
	Tail          bool
	Time          time.Time
	Compress      bool
	CustomLogRoot string
	FromBegin     bool // to be used with tail
}

const (
	DEFAULT_LOG_ROOT = "/var/log/hourly"
	HOURLY_PATTERN   = "2006/01/02/2006-01-02T15.log"
)

func NewRemoteLogFromTime(host string, t time.Time, pattern string) *RemoteLog {
	return &RemoteLog{
		Time:    t,
		Host:    host,
		Pattern: pattern,
	}
}

func (rl *RemoteLog) LogRoot() string {
	if rl.CustomLogRoot != "" {
		return rl.CustomLogRoot
	}
	return DEFAULT_LOG_ROOT
}

func (rl *RemoteLog) Current() string {
	return rl.LogRoot() + "/current"
}

func (rl *RemoteLog) Path() string {
	if !rl.Time.IsZero() {
		return rl.Time.UTC().Format(rl.LogRoot() + "/" + HOURLY_PATTERN)
	}
	return rl.Current()
}

func (rl *RemoteLog) GzipPath() string {
	return rl.Path() + ".gz"
}

func (rl *RemoteLog) Command() string {
	cmd := rl.CatCmd()
	if rl.Pattern != "" {
		cmd += " | " + rl.GrepCmd()
	}
	if rl.Compress {
		cmd += " | gzip"
	}
	return cmd
}

func (rl *RemoteLog) GrepCmd() string {
	return "grep " + rl.Pattern
}

func (rl *RemoteLog) CatCmd() string {
	if rl.Tail {
		n := "0"
		if rl.FromBegin {
			n = "+0"
		}
		return "tail -n " + n + " -F " + rl.Current()
	}
	return "{ test -e " + rl.Path() + " && cat " + rl.Path() + "; test -e " + rl.GzipPath() + " && cat " + rl.GzipPath() + " | gunzip; }"
}

func (rl *RemoteLog) Open() (reader io.ReadCloser, e error) {
	c := rl.Command()
	var cmd *exec.Cmd
	user := rl.User
	if user == "" {
		user = "root"
	}
	if rl.Host != "" {
		cmd = exec.Command("ssh", "-t", "-l", user, rl.Host, c)
	} else {
		cmd = exec.Command("bash", "-c", c)
	}
	dbg.Printf("using cmd %q", cmd)
	reader, e = cmd.StdoutPipe()
	if e != nil {
		return nil, e
	}
	dbg.Print("starting command %q", c)
	e = cmd.Start()
	if e != nil {
		return nil, e
	}
	dbg.Print("command started")
	if rl.Compress {
		reader, e = gzip.NewReader(reader)
		if e != nil {
			return nil, e
		}
	}
	dbg.Print("returning reader")
	return reader, nil
}
<commit_msg>fix debug log<commit_after>package logging

import (
	"compress/gzip"
	"io"
	"os/exec"
	"time"
)

type RemoteLog struct {
	Host          string
	User          string
	Pattern       string
	Tail          bool
	Time          time.Time
	Compress      bool
	CustomLogRoot string
	FromBegin     bool // to be used with tail
}

const (
	DEFAULT_LOG_ROOT = "/var/log/hourly"
	HOURLY_PATTERN   = "2006/01/02/2006-01-02T15.log"
)

func NewRemoteLogFromTime(host string, t time.Time, pattern string) *RemoteLog {
	return &RemoteLog{
		Time:    t,
		Host:    host,
		Pattern: pattern,
	}
}

func (rl *RemoteLog) LogRoot() string {
	if rl.CustomLogRoot != "" {
		return rl.CustomLogRoot
	}
	return DEFAULT_LOG_ROOT
}

func (rl *RemoteLog) Current() string {
	return rl.LogRoot() + "/current"
}

func (rl *RemoteLog) Path() string {
	if !rl.Time.IsZero() {
		return rl.Time.UTC().Format(rl.LogRoot() + "/" + HOURLY_PATTERN)
	}
	return rl.Current()
}

func (rl *RemoteLog) GzipPath() string {
	return rl.Path() + ".gz"
}

func (rl *RemoteLog) Command() string {
	cmd := rl.CatCmd()
	if rl.Pattern != "" {
		cmd += " | " + rl.GrepCmd()
	}
	if rl.Compress {
		cmd += " | gzip"
	}
	return cmd
}

func (rl *RemoteLog) GrepCmd() string {
	return "grep " + rl.Pattern
}

func (rl *RemoteLog) CatCmd() string {
	if rl.Tail {
		n := "0"
		if rl.FromBegin {
			n = "+0"
		}
		return "tail -n " + n + " -F " + rl.Current()
	}
	return "{ test -e " + rl.Path() + " && cat " + rl.Path() + "; test -e " + rl.GzipPath() + " && cat " + rl.GzipPath() + " | gunzip; }"
}

func (rl *RemoteLog) Open() (reader io.ReadCloser, e error) {
	c := rl.Command()
	var cmd *exec.Cmd
	user := rl.User
	if user == "" {
		user = "root"
	}
	if rl.Host != "" {
		cmd = exec.Command("ssh", "-t", "-l", user, rl.Host, c)
	} else {
		cmd = exec.Command("bash", "-c", c)
	}
	dbg.Printf("using cmd %q", cmd)
	reader, e = cmd.StdoutPipe()
	if e != nil {
		return nil, e
	}
	dbg.Printf("starting command %q", c)
	e = cmd.Start()
	if e != nil {
		return nil, e
	}
	dbg.Print("command started")
	if rl.Compress {
		reader, e = gzip.NewReader(reader)
		if e != nil {
			return nil, e
		}
	}
	dbg.Print("returning reader")
	return reader, nil
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"io/ioutil"
	"net/http"
	"os"
	"strings"

	"github.com/gorilla/mux"

	"github.com/lxc/lxd/shared"
)

func containerLogsGet(d *Daemon, r *http.Request) Response {
	/* Let's explicitly *not* try to do a containerLoadByName here. In some
	 * cases (e.g. when container creation failed), the container won't
	 * exist in the DB but it does have some log files on disk.
	 *
	 * However, we should check this name and ensure it's a valid container
	 * name just so that people can't list arbitrary directories.
	 */
	name := mux.Vars(r)["name"]

	if err := containerValidName(name); err != nil {
		return BadRequest(err)
	}

	result := []string{}

	dents, err := ioutil.ReadDir(shared.LogPath(name))
	if err != nil {
		return SmartError(err)
	}

	for _, f := range dents {
		result = append(result, fmt.Sprintf("/%s/containers/%s/logs/%s", shared.APIVersion, name, f.Name()))
	}

	return SyncResponse(true, result)
}

var containerLogsCmd = Command{
	name: "containers/{name}/logs",
	get:  containerLogsGet,
}

func validLogFileName(fname string) bool {
	/* Let's just require that the paths be relative, so that we don't have
	 * to deal with any escaping or whatever.
	 */
	return fname == "lxc.log" ||
		fname == "lxc.conf" ||
		strings.HasPrefix(fname, "migration_") ||
		strings.HasPrefix(fname, "snapshot_")
}

func containerLogGet(d *Daemon, r *http.Request) Response {
	name := mux.Vars(r)["name"]
	file := mux.Vars(r)["file"]

	if err := containerValidName(name); err != nil {
		return BadRequest(err)
	}

	if !validLogFileName(file) {
		return BadRequest(fmt.Errorf("log file name %s not valid", file))
	}

	ent := fileResponseEntry{
		path:     shared.LogPath(name, file),
		filename: file,
	}

	return FileResponse(r, []fileResponseEntry{ent}, nil, false)
}

func containerLogDelete(d *Daemon, r *http.Request) Response {
	name := mux.Vars(r)["name"]
	file := mux.Vars(r)["file"]

	if err := containerValidName(name); err != nil {
		return BadRequest(err)
	}

	if !validLogFileName(file) {
		return BadRequest(fmt.Errorf("log file name %s not valid", file))
	}

	return SmartError(os.Remove(shared.LogPath(name, file)))
}

var containerLogCmd = Command{
	name:   "containers/{name}/logs/{file}",
	get:    containerLogGet,
	delete: containerLogDelete,
}
<commit_msg>logs: Don't show invalid logs<commit_after>package main

import (
	"fmt"
	"io/ioutil"
	"net/http"
	"os"
	"strings"

	"github.com/gorilla/mux"

	"github.com/lxc/lxd/shared"
)

func containerLogsGet(d *Daemon, r *http.Request) Response {
	/* Let's explicitly *not* try to do a containerLoadByName here. In some
	 * cases (e.g. when container creation failed), the container won't
	 * exist in the DB but it does have some log files on disk.
	 *
	 * However, we should check this name and ensure it's a valid container
	 * name just so that people can't list arbitrary directories.
	 */
	name := mux.Vars(r)["name"]

	if err := containerValidName(name); err != nil {
		return BadRequest(err)
	}

	result := []string{}

	dents, err := ioutil.ReadDir(shared.LogPath(name))
	if err != nil {
		return SmartError(err)
	}

	for _, f := range dents {
		if !validLogFileName(f.Name()) {
			continue
		}

		result = append(result, fmt.Sprintf("/%s/containers/%s/logs/%s", shared.APIVersion, name, f.Name()))
	}

	return SyncResponse(true, result)
}

var containerLogsCmd = Command{
	name: "containers/{name}/logs",
	get:  containerLogsGet,
}

func validLogFileName(fname string) bool {
	/* Let's just require that the paths be relative, so that we don't have
	 * to deal with any escaping or whatever.
	 */
	return fname == "lxc.log" ||
		fname == "lxc.conf" ||
		strings.HasPrefix(fname, "migration_") ||
		strings.HasPrefix(fname, "snapshot_")
}

func containerLogGet(d *Daemon, r *http.Request) Response {
	name := mux.Vars(r)["name"]
	file := mux.Vars(r)["file"]

	if err := containerValidName(name); err != nil {
		return BadRequest(err)
	}

	if !validLogFileName(file) {
		return BadRequest(fmt.Errorf("log file name %s not valid", file))
	}

	ent := fileResponseEntry{
		path:     shared.LogPath(name, file),
		filename: file,
	}

	return FileResponse(r, []fileResponseEntry{ent}, nil, false)
}

func containerLogDelete(d *Daemon, r *http.Request) Response {
	name := mux.Vars(r)["name"]
	file := mux.Vars(r)["file"]

	if err := containerValidName(name); err != nil {
		return BadRequest(err)
	}

	if !validLogFileName(file) {
		return BadRequest(fmt.Errorf("log file name %s not valid", file))
	}

	return SmartError(os.Remove(shared.LogPath(name, file)))
}

var containerLogCmd = Command{
	name:   "containers/{name}/logs/{file}",
	get:    containerLogGet,
	delete: containerLogDelete,
}
<|endoftext|>


<commit_before>//go:build linux && cgo && !agent
// +build linux,cgo,!agent

package db

import (
	"database/sql"
	"fmt"
)

// NodeTx models a single interaction with a LXD node-local database.
//
// It wraps low-level sql.Tx objects and offers a high-level API to fetch and
// update data.
type NodeTx struct {
	tx *sql.Tx // Handle to a transaction in the node-level SQLite database.
}

// Tx returns the low level database handle to the node-local SQLite
// transaction.
//
// FIXME: this is a transitional method needed for compatibility with some
//        legacy call sites. It should be removed when there are no more
//        consumers.
func (n *NodeTx) Tx() *sql.Tx {
	return n.tx
}

// ClusterTx models a single interaction with a LXD cluster database.
//
// It wraps low-level sql.Tx objects and offers a high-level API to fetch and
// update data.
type ClusterTx struct {
	tx     *sql.Tx           // Handle to a transaction in the cluster dqlite database.
	nodeID int64             // Node ID of this LXD instance.
	stmts  map[int]*sql.Stmt // Prepared statements by code.
}

// NodeID sets the the node NodeID associated with this cluster transaction.
func (c *ClusterTx) NodeID(id int64) {
	c.nodeID = id
}

func (c *ClusterTx) stmt(code int) *sql.Stmt {
	stmt, ok := c.stmts[code]
	if !ok {
		panic(fmt.Sprintf("No prepared statement registered with code %d", code))
	}
	return c.tx.Stmt(stmt)
}
<commit_msg>lxd/db/transaction: add GetNodeID<commit_after>//go:build linux && cgo && !agent
// +build linux,cgo,!agent

package db

import (
	"database/sql"
	"fmt"
)

// NodeTx models a single interaction with a LXD node-local database.
//
// It wraps low-level sql.Tx objects and offers a high-level API to fetch and
// update data.
type NodeTx struct {
	tx *sql.Tx // Handle to a transaction in the node-level SQLite database.
}

// Tx returns the low level database handle to the node-local SQLite
// transaction.
//
// FIXME: this is a transitional method needed for compatibility with some
//        legacy call sites. It should be removed when there are no more
//        consumers.
func (n *NodeTx) Tx() *sql.Tx {
	return n.tx
}

// ClusterTx models a single interaction with a LXD cluster database.
//
// It wraps low-level sql.Tx objects and offers a high-level API to fetch and
// update data.
type ClusterTx struct {
	tx     *sql.Tx           // Handle to a transaction in the cluster dqlite database.
	nodeID int64             // Node ID of this LXD instance.
	stmts  map[int]*sql.Stmt // Prepared statements by code.
}

// NodeID sets the the node NodeID associated with this cluster transaction.
func (c *ClusterTx) NodeID(id int64) {
	c.nodeID = id
}

// GetNodeID gets the ID of the node associated with this cluster transaction.
func (c *ClusterTx) GetNodeID() int64 {
	return c.nodeID
}

func (c *ClusterTx) stmt(code int) *sql.Stmt {
	stmt, ok := c.stmts[code]
	if !ok {
		panic(fmt.Sprintf("No prepared statement registered with code %d", code))
	}
	return c.tx.Stmt(stmt)
}
<|endoftext|>


<commit_before>package middleware

import (
	"net/http"
	"time"
)

// Timeout middleware panics if the request hasn't completed after the time limit
type Timeout struct {
	Limit time.Duration
}

func (m *Timeout) ServeHTTP(w http.ResponseWriter, r *http.Request, next http.HandlerFunc) {
	doneChan := make(chan bool)
	go func() {
		next(w, r)
		doneChan <- true
	}()
	select {
	case <-doneChan:
	case <-time.After(m.Limit):
		panic("request processing exceeded time limit")
	}
}
<commit_msg>added NewTimeout method<commit_after>package middleware

import (
	"net/http"
	"time"
)

// Timeout middleware panics if the request hasn't completed after the time limit
type Timeout struct {
	Limit time.Duration
}

// NewTimeout builds a new timeout middleware
func NewTimeout(limit time.Duration) *Timeout {
	return &Timeout{limit}
}

func (m *Timeout) ServeHTTP(w http.ResponseWriter, r *http.Request, next http.HandlerFunc) {
	doneChan := make(chan bool)
	go func() {
		next(w, r)
		doneChan <- true
	}()
	select {
	case <-doneChan:
	case <-time.After(m.Limit):
		panic("request processing exceeded time limit")
	}
}
<|endoftext|>