<commit_before>// Copyright 2015 The Cockroach Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
// implied. See the License for the specific language governing
// permissions and limitations under the License.
//
// Author: Tamir Duberstein (tamird@gmail.com)

package rpc

import (
	"time"

	"golang.org/x/net/context"
	"google.golang.org/grpc"
	"google.golang.org/grpc/codes"
	"google.golang.org/grpc/credentials"

	"github.com/cockroachdb/cockroach/base"
	"github.com/cockroachdb/cockroach/roachpb"
	"github.com/cockroachdb/cockroach/util/grpcutil"
	"github.com/cockroachdb/cockroach/util/hlc"
	"github.com/cockroachdb/cockroach/util/log"
	"github.com/cockroachdb/cockroach/util/stop"
	"github.com/cockroachdb/cockroach/util/syncutil"
	"github.com/cockroachdb/cockroach/util/timeutil"
)

func init() {
	grpc.EnableTracing = false
}

const (
	defaultHeartbeatInterval = 3 * time.Second
	// The coefficient by which the maximum offset is multiplied to determine the
	// maximum acceptable measurement latency.
	maximumPingDurationMult = 2
)

// NewServer is a thin wrapper around grpc.NewServer that registers a heartbeat
// service.
func NewServer(ctx *Context) *grpc.Server {
	var s *grpc.Server
	if ctx.Insecure {
		s = grpc.NewServer()
	} else {
		tlsConfig, err := ctx.GetServerTLSConfig()
		if err != nil {
			panic(err)
		}
		s = grpc.NewServer(grpc.Creds(credentials.NewTLS(tlsConfig)))
	}
	RegisterHeartbeatServer(s, &HeartbeatService{
		clock:              ctx.localClock,
		remoteClockMonitor: ctx.RemoteClocks,
	})
	return s
}

type connMeta struct {
	conn    *grpc.ClientConn
	healthy bool
}

// Context contains the fields required by the rpc framework.
type Context struct {
	*base.Context

	localClock   *hlc.Clock
	Stopper      *stop.Stopper
	RemoteClocks *RemoteClockMonitor

	HeartbeatInterval time.Duration
	HeartbeatTimeout  time.Duration
	HeartbeatCB       func()

	localInternalServer roachpb.InternalServer

	conns struct {
		syncutil.Mutex
		cache map[string]connMeta
	}
}

// NewContext creates an rpc Context with the supplied values.
func NewContext(baseCtx *base.Context, clock *hlc.Clock, stopper *stop.Stopper) *Context {
	ctx := &Context{
		Context: baseCtx,
	}
	if clock != nil {
		ctx.localClock = clock
	} else {
		ctx.localClock = hlc.NewClock(hlc.UnixNano)
	}
	ctx.Stopper = stopper
	ctx.RemoteClocks = newRemoteClockMonitor(clock, 10*defaultHeartbeatInterval)
	ctx.HeartbeatInterval = defaultHeartbeatInterval
	ctx.HeartbeatTimeout = 2 * defaultHeartbeatInterval

	stopper.RunWorker(func() {
		<-stopper.ShouldQuiesce()

		ctx.conns.Lock()
		for key, meta := range ctx.conns.cache {
			ctx.removeConn(key, meta.conn)
		}
		ctx.conns.Unlock()
	})

	return ctx
}

// GetLocalInternalServerForAddr returns the context's internal batch server
// for addr, if it exists.
func (ctx *Context) GetLocalInternalServerForAddr(addr string) roachpb.InternalServer {
	if addr == ctx.Addr {
		return ctx.localInternalServer
	}
	return nil
}

// SetLocalInternalServer sets the context's local internal batch server.
func (ctx *Context) SetLocalInternalServer(internalServer roachpb.InternalServer) {
	ctx.localInternalServer = internalServer
}

func (ctx *Context) removeConn(key string, conn *grpc.ClientConn) {
	if err := conn.Close(); err != nil && !grpcutil.IsClosedConnection(err) {
		if log.V(1) {
			log.Errorf(context.TODO(), "failed to close client connection: %s", err)
		}
	}
	delete(ctx.conns.cache, key)
}

// GRPCDial calls grpc.Dial with the options appropriate for the context.
func (ctx *Context) GRPCDial(target string, opts ...grpc.DialOption) (*grpc.ClientConn, error) {
	ctx.conns.Lock()
	defer ctx.conns.Unlock()

	if meta, ok := ctx.conns.cache[target]; ok {
		return meta.conn, nil
	}

	var dialOpt grpc.DialOption
	if ctx.Insecure {
		dialOpt = grpc.WithInsecure()
	} else {
		tlsConfig, err := ctx.GetClientTLSConfig()
		if err != nil {
			return nil, err
		}
		dialOpt = grpc.WithTransportCredentials(credentials.NewTLS(tlsConfig))
	}

	dialOpts := make([]grpc.DialOption, 0, 1+len(opts))
	dialOpts = append(dialOpts, dialOpt)
	dialOpts = append(dialOpts, opts...)

	conn, err := grpc.Dial(target, dialOpts...)
	if err == nil {
		if ctx.conns.cache == nil {
			ctx.conns.cache = make(map[string]connMeta)
		}
		ctx.conns.cache[target] = connMeta{conn: conn}

		if ctx.Stopper.RunTask(func() {
			ctx.Stopper.RunWorker(func() {
				if err := ctx.runHeartbeat(conn, target); err != nil && !grpcutil.IsClosedConnection(err) {
					log.Error(context.TODO(), err)
				}
				ctx.conns.Lock()
				ctx.removeConn(target, conn)
				ctx.conns.Unlock()
			})
		}) != nil {
			ctx.removeConn(target, conn)
		}
	}
	return conn, err
}

// setConnHealthy sets the health status of the connection.
func (ctx *Context) setConnHealthy(remoteAddr string, healthy bool) {
	ctx.conns.Lock()
	defer ctx.conns.Unlock()

	meta, ok := ctx.conns.cache[remoteAddr]
	if ok {
		meta.healthy = healthy
		ctx.conns.cache[remoteAddr] = meta
	}
}

// IsConnHealthy returns whether the most recent heartbeat succeeded or not.
// This should not be used as a definite status of a nodes health and just used
// to prioritized healthy nodes over unhealthy ones.
func (ctx *Context) IsConnHealthy(remoteAddr string) bool {
	ctx.conns.Lock()
	defer ctx.conns.Unlock()

	return ctx.conns.cache[remoteAddr].healthy
}

func (ctx *Context) runHeartbeat(cc *grpc.ClientConn, remoteAddr string) error {
	request := PingRequest{Addr: ctx.Addr}
	heartbeatClient := NewHeartbeatClient(cc)

	var heartbeatTimer timeutil.Timer
	defer heartbeatTimer.Stop()
	for {
		// If we should stop, return immediately. Note that we check this
		// at the beginning and end of the loop because we may 'continue'
		// before reaching the end.
		select {
		case <-ctx.Stopper.ShouldStop():
			return nil
		default:
		}
		sendTime := ctx.localClock.PhysicalTime()
		response, err := ctx.heartbeat(heartbeatClient, request)
		ctx.setConnHealthy(remoteAddr, err == nil)
		if err != nil {
			if grpc.Code(err) == codes.DeadlineExceeded {
				continue
			}
			return err
		}
		receiveTime := ctx.localClock.PhysicalTime()

		// Only update the clock offset measurement if we actually got a
		// successful response from the server.
		if pingDuration := receiveTime.Sub(sendTime); pingDuration > maximumPingDurationMult*ctx.localClock.MaxOffset() {
			request.Offset.Reset()
		} else {
			// Offset and error are measured using the remote clock reading
			// technique described in
			// http://se.inf.tu-dresden.de/pubs/papers/SRDS1994.pdf, page 6.
			// However, we assume that drift and min message delay are 0, for
			// now.
			request.Offset.MeasuredAt = receiveTime.UnixNano()
			request.Offset.Uncertainty = (pingDuration / 2).Nanoseconds()
			remoteTimeNow := time.Unix(0, response.ServerTime).Add(pingDuration / 2)
			request.Offset.Offset = remoteTimeNow.Sub(receiveTime).Nanoseconds()
		}
		ctx.RemoteClocks.UpdateOffset(remoteAddr, request.Offset)

		if cb := ctx.HeartbeatCB; cb != nil {
			cb()
		}

		// Wait after the heartbeat so that the first iteration gets a wait-free
		// heartbeat attempt.
		heartbeatTimer.Reset(ctx.HeartbeatInterval)
		select {
		case <-ctx.Stopper.ShouldStop():
			return nil
		case <-heartbeatTimer.C:
			heartbeatTimer.Read = true
		}
	}
}

func (ctx *Context) heartbeat(heartbeatClient HeartbeatClient, request PingRequest) (*PingResponse, error) {
	goCtx, cancel := context.WithTimeout(context.Background(), ctx.HeartbeatTimeout)
	defer cancel()
	return heartbeatClient.Ping(goCtx, &request)
}
<commit_msg>Enable grpc tracing. Goes into /debug/requests automatically<commit_after>// Copyright 2015 The Cockroach Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
// implied. See the License for the specific language governing
// permissions and limitations under the License.
//
// Author: Tamir Duberstein (tamird@gmail.com)

package rpc

import (
	"time"

	"golang.org/x/net/context"
	"google.golang.org/grpc"
	"google.golang.org/grpc/codes"
	"google.golang.org/grpc/credentials"

	"github.com/cockroachdb/cockroach/base"
	"github.com/cockroachdb/cockroach/roachpb"
	"github.com/cockroachdb/cockroach/util/grpcutil"
	"github.com/cockroachdb/cockroach/util/hlc"
	"github.com/cockroachdb/cockroach/util/log"
	"github.com/cockroachdb/cockroach/util/stop"
	"github.com/cockroachdb/cockroach/util/syncutil"
	"github.com/cockroachdb/cockroach/util/timeutil"
)

const (
	defaultHeartbeatInterval = 3 * time.Second
	// The coefficient by which the maximum offset is multiplied to determine the
	// maximum acceptable measurement latency.
	maximumPingDurationMult = 2
)

// NewServer is a thin wrapper around grpc.NewServer that registers a heartbeat
// service.
func NewServer(ctx *Context) *grpc.Server {
	var s *grpc.Server
	if ctx.Insecure {
		s = grpc.NewServer()
	} else {
		tlsConfig, err := ctx.GetServerTLSConfig()
		if err != nil {
			panic(err)
		}
		s = grpc.NewServer(grpc.Creds(credentials.NewTLS(tlsConfig)))
	}
	RegisterHeartbeatServer(s, &HeartbeatService{
		clock:              ctx.localClock,
		remoteClockMonitor: ctx.RemoteClocks,
	})
	return s
}

type connMeta struct {
	conn    *grpc.ClientConn
	healthy bool
}

// Context contains the fields required by the rpc framework.
type Context struct {
	*base.Context

	localClock   *hlc.Clock
	Stopper      *stop.Stopper
	RemoteClocks *RemoteClockMonitor

	HeartbeatInterval time.Duration
	HeartbeatTimeout  time.Duration
	HeartbeatCB       func()

	localInternalServer roachpb.InternalServer

	conns struct {
		syncutil.Mutex
		cache map[string]connMeta
	}
}

// NewContext creates an rpc Context with the supplied values.
func NewContext(baseCtx *base.Context, clock *hlc.Clock, stopper *stop.Stopper) *Context {
	ctx := &Context{
		Context: baseCtx,
	}
	if clock != nil {
		ctx.localClock = clock
	} else {
		ctx.localClock = hlc.NewClock(hlc.UnixNano)
	}
	ctx.Stopper = stopper
	ctx.RemoteClocks = newRemoteClockMonitor(clock, 10*defaultHeartbeatInterval)
	ctx.HeartbeatInterval = defaultHeartbeatInterval
	ctx.HeartbeatTimeout = 2 * defaultHeartbeatInterval

	stopper.RunWorker(func() {
		<-stopper.ShouldQuiesce()

		ctx.conns.Lock()
		for key, meta := range ctx.conns.cache {
			ctx.removeConn(key, meta.conn)
		}
		ctx.conns.Unlock()
	})

	return ctx
}

// GetLocalInternalServerForAddr returns the context's internal batch server
// for addr, if it exists.
func (ctx *Context) GetLocalInternalServerForAddr(addr string) roachpb.InternalServer {
	if addr == ctx.Addr {
		return ctx.localInternalServer
	}
	return nil
}

// SetLocalInternalServer sets the context's local internal batch server.
func (ctx *Context) SetLocalInternalServer(internalServer roachpb.InternalServer) {
	ctx.localInternalServer = internalServer
}

func (ctx *Context) removeConn(key string, conn *grpc.ClientConn) {
	if err := conn.Close(); err != nil && !grpcutil.IsClosedConnection(err) {
		if log.V(1) {
			log.Errorf(context.TODO(), "failed to close client connection: %s", err)
		}
	}
	delete(ctx.conns.cache, key)
}

// GRPCDial calls grpc.Dial with the options appropriate for the context.
func (ctx *Context) GRPCDial(target string, opts ...grpc.DialOption) (*grpc.ClientConn, error) {
	ctx.conns.Lock()
	defer ctx.conns.Unlock()

	if meta, ok := ctx.conns.cache[target]; ok {
		return meta.conn, nil
	}

	var dialOpt grpc.DialOption
	if ctx.Insecure {
		dialOpt = grpc.WithInsecure()
	} else {
		tlsConfig, err := ctx.GetClientTLSConfig()
		if err != nil {
			return nil, err
		}
		dialOpt = grpc.WithTransportCredentials(credentials.NewTLS(tlsConfig))
	}

	dialOpts := make([]grpc.DialOption, 0, 1+len(opts))
	dialOpts = append(dialOpts, dialOpt)
	dialOpts = append(dialOpts, opts...)

	conn, err := grpc.Dial(target, dialOpts...)
	if err == nil {
		if ctx.conns.cache == nil {
			ctx.conns.cache = make(map[string]connMeta)
		}
		ctx.conns.cache[target] = connMeta{conn: conn}

		if ctx.Stopper.RunTask(func() {
			ctx.Stopper.RunWorker(func() {
				if err := ctx.runHeartbeat(conn, target); err != nil && !grpcutil.IsClosedConnection(err) {
					log.Error(context.TODO(), err)
				}
				ctx.conns.Lock()
				ctx.removeConn(target, conn)
				ctx.conns.Unlock()
			})
		}) != nil {
			ctx.removeConn(target, conn)
		}
	}
	return conn, err
}

// setConnHealthy sets the health status of the connection.
func (ctx *Context) setConnHealthy(remoteAddr string, healthy bool) {
	ctx.conns.Lock()
	defer ctx.conns.Unlock()

	meta, ok := ctx.conns.cache[remoteAddr]
	if ok {
		meta.healthy = healthy
		ctx.conns.cache[remoteAddr] = meta
	}
}

// IsConnHealthy returns whether the most recent heartbeat succeeded or not.
// This should not be used as a definite status of a nodes health and just used
// to prioritized healthy nodes over unhealthy ones.
func (ctx *Context) IsConnHealthy(remoteAddr string) bool {
	ctx.conns.Lock()
	defer ctx.conns.Unlock()

	return ctx.conns.cache[remoteAddr].healthy
}

func (ctx *Context) runHeartbeat(cc *grpc.ClientConn, remoteAddr string) error {
	request := PingRequest{Addr: ctx.Addr}
	heartbeatClient := NewHeartbeatClient(cc)

	var heartbeatTimer timeutil.Timer
	defer heartbeatTimer.Stop()
	for {
		// If we should stop, return immediately. Note that we check this
		// at the beginning and end of the loop because we may 'continue'
		// before reaching the end.
		select {
		case <-ctx.Stopper.ShouldStop():
			return nil
		default:
		}
		sendTime := ctx.localClock.PhysicalTime()
		response, err := ctx.heartbeat(heartbeatClient, request)
		ctx.setConnHealthy(remoteAddr, err == nil)
		if err != nil {
			if grpc.Code(err) == codes.DeadlineExceeded {
				continue
			}
			return err
		}
		receiveTime := ctx.localClock.PhysicalTime()

		// Only update the clock offset measurement if we actually got a
		// successful response from the server.
		if pingDuration := receiveTime.Sub(sendTime); pingDuration > maximumPingDurationMult*ctx.localClock.MaxOffset() {
			request.Offset.Reset()
		} else {
			// Offset and error are measured using the remote clock reading
			// technique described in
			// http://se.inf.tu-dresden.de/pubs/papers/SRDS1994.pdf, page 6.
			// However, we assume that drift and min message delay are 0, for
			// now.
			request.Offset.MeasuredAt = receiveTime.UnixNano()
			request.Offset.Uncertainty = (pingDuration / 2).Nanoseconds()
			remoteTimeNow := time.Unix(0, response.ServerTime).Add(pingDuration / 2)
			request.Offset.Offset = remoteTimeNow.Sub(receiveTime).Nanoseconds()
		}
		ctx.RemoteClocks.UpdateOffset(remoteAddr, request.Offset)

		if cb := ctx.HeartbeatCB; cb != nil {
			cb()
		}

		// Wait after the heartbeat so that the first iteration gets a wait-free
		// heartbeat attempt.
		heartbeatTimer.Reset(ctx.HeartbeatInterval)
		select {
		case <-ctx.Stopper.ShouldStop():
			return nil
		case <-heartbeatTimer.C:
			heartbeatTimer.Read = true
		}
	}
}

func (ctx *Context) heartbeat(heartbeatClient HeartbeatClient, request PingRequest) (*PingResponse, error) {
	goCtx, cancel := context.WithTimeout(context.Background(), ctx.HeartbeatTimeout)
	defer cancel()
	return heartbeatClient.Ping(goCtx, &request)
}
<|endoftext|>


<commit_before>// Copyright 2015 The Cockroach Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
// implied. See the License for the specific language governing
// permissions and limitations under the License.
//
// Author: Tamir Duberstein (tamird@gmail.com)

package rpc

import (
	"math"
	"time"

	"github.com/rubyist/circuitbreaker"
	"golang.org/x/net/context"
	"google.golang.org/grpc"
	"google.golang.org/grpc/codes"
	"google.golang.org/grpc/credentials"

	"github.com/cockroachdb/cockroach/base"
	"github.com/cockroachdb/cockroach/roachpb"
	"github.com/cockroachdb/cockroach/util/grpcutil"
	"github.com/cockroachdb/cockroach/util/hlc"
	"github.com/cockroachdb/cockroach/util/log"
	"github.com/cockroachdb/cockroach/util/stop"
	"github.com/cockroachdb/cockroach/util/syncutil"
	"github.com/cockroachdb/cockroach/util/timeutil"
)

func init() {
	grpc.EnableTracing = false
}

const (
	defaultHeartbeatInterval = 3 * time.Second
	// The coefficient by which the maximum offset is multiplied to determine the
	// maximum acceptable measurement latency.
	maximumPingDurationMult = 2
)

// NewServer is a thin wrapper around grpc.NewServer that registers a heartbeat
// service.
func NewServer(ctx *Context) *grpc.Server {
	opts := []grpc.ServerOption{
		grpc.MaxMsgSize(math.MaxInt32), // TODO(peter,tamird): need tests before lowering
	}
	if !ctx.Insecure {
		tlsConfig, err := ctx.GetServerTLSConfig()
		if err != nil {
			panic(err)
		}
		opts = append(opts, grpc.Creds(credentials.NewTLS(tlsConfig)))
	}
	s := grpc.NewServer(opts...)
	RegisterHeartbeatServer(s, &HeartbeatService{
		clock:              ctx.localClock,
		remoteClockMonitor: ctx.RemoteClocks,
	})
	return s
}

type connMeta struct {
	conn    *grpc.ClientConn
	healthy bool
}

// Context contains the fields required by the rpc framework.
type Context struct {
	*base.Context

	localClock   *hlc.Clock
	breakerClock breakerClock
	Stopper      *stop.Stopper
	RemoteClocks *RemoteClockMonitor

	HeartbeatInterval time.Duration
	HeartbeatTimeout  time.Duration
	HeartbeatCB       func()

	localInternalServer roachpb.InternalServer

	conns struct {
		syncutil.Mutex
		cache map[string]connMeta
	}
}

// NewContext creates an rpc Context with the supplied values.
func NewContext(baseCtx *base.Context, hlcClock *hlc.Clock, stopper *stop.Stopper) *Context {
	ctx := &Context{
		Context: baseCtx,
	}
	if hlcClock != nil {
		ctx.localClock = hlcClock
	} else {
		ctx.localClock = hlc.NewClock(hlc.UnixNano)
	}
	ctx.breakerClock = breakerClock{
		clock: ctx.localClock,
	}
	ctx.Stopper = stopper
	ctx.RemoteClocks = newRemoteClockMonitor(ctx.localClock, 10*defaultHeartbeatInterval)
	ctx.HeartbeatInterval = defaultHeartbeatInterval
	ctx.HeartbeatTimeout = 2 * defaultHeartbeatInterval
	ctx.conns.cache = make(map[string]connMeta)

	stopper.RunWorker(func() {
		<-stopper.ShouldQuiesce()

		ctx.conns.Lock()
		for key, meta := range ctx.conns.cache {
			ctx.removeConn(key, meta.conn)
		}
		ctx.conns.Unlock()
	})

	return ctx
}

// GetLocalInternalServerForAddr returns the context's internal batch server
// for addr, if it exists.
func (ctx *Context) GetLocalInternalServerForAddr(addr string) roachpb.InternalServer {
	if addr == ctx.Addr {
		return ctx.localInternalServer
	}
	return nil
}

// SetLocalInternalServer sets the context's local internal batch server.
func (ctx *Context) SetLocalInternalServer(internalServer roachpb.InternalServer) {
	ctx.localInternalServer = internalServer
}

func (ctx *Context) removeConn(key string, conn *grpc.ClientConn) {
	if log.V(1) {
		log.Infof(context.TODO(), "closing %s", key)
	}
	if err := conn.Close(); err != nil && !grpcutil.IsClosedConnection(err) {
		if log.V(1) {
			log.Errorf(context.TODO(), "failed to close client connection: %s", err)
		}
	}
	delete(ctx.conns.cache, key)
}

// GRPCDial calls grpc.Dial with the options appropriate for the context.
func (ctx *Context) GRPCDial(target string, opts ...grpc.DialOption) (*grpc.ClientConn, error) {
	ctx.conns.Lock()
	defer ctx.conns.Unlock()

	if meta, ok := ctx.conns.cache[target]; ok {
		return meta.conn, nil
	}

	dialOpt, err := ctx.GRPCDialOption()
	if err != nil {
		return nil, err
	}

	dialOpts := make([]grpc.DialOption, 0, 1+len(opts))
	dialOpts = append(dialOpts, dialOpt)
	dialOpts = append(dialOpts, opts...)

	if log.V(1) {
		log.Infof(context.TODO(), "dialing %s", target)
	}
	conn, err := grpc.Dial(target, dialOpts...)
	if err == nil {
		ctx.conns.cache[target] = connMeta{conn: conn}

		if ctx.Stopper.RunTask(func() {
			ctx.Stopper.RunWorker(func() {
				err := ctx.runHeartbeat(conn, target)
				if err != nil && !grpcutil.IsClosedConnection(err) {
					log.Error(context.TODO(), err)
				}
				ctx.conns.Lock()
				ctx.removeConn(target, conn)
				ctx.conns.Unlock()
			})
		}) != nil {
			ctx.removeConn(target, conn)
		}
	}
	return conn, err
}

// GRPCDialOption returns the GRPC dialing option appropriate for the context.
func (ctx *Context) GRPCDialOption() (grpc.DialOption, error) {
	var dialOpt grpc.DialOption
	if ctx.Insecure {
		dialOpt = grpc.WithInsecure()
	} else {
		tlsConfig, err := ctx.GetClientTLSConfig()
		if err != nil {
			return dialOpt, err
		}
		dialOpt = grpc.WithTransportCredentials(credentials.NewTLS(tlsConfig))
	}
	return dialOpt, nil
}

// NewBreaker creates a new circuit breaker properly configured for RPC
// connections.
func (ctx *Context) NewBreaker() *circuit.Breaker {
	return newBreaker(&ctx.breakerClock)
}

// setConnHealthy sets the health status of the connection.
func (ctx *Context) setConnHealthy(remoteAddr string, healthy bool) {
	ctx.conns.Lock()
	defer ctx.conns.Unlock()

	meta, ok := ctx.conns.cache[remoteAddr]
	if ok {
		meta.healthy = healthy
		ctx.conns.cache[remoteAddr] = meta
	}
}

// IsConnHealthy returns whether the most recent heartbeat succeeded or not.
// This should not be used as a definite status of a nodes health and just used
// to prioritized healthy nodes over unhealthy ones.
func (ctx *Context) IsConnHealthy(remoteAddr string) bool {
	ctx.conns.Lock()
	defer ctx.conns.Unlock()

	return ctx.conns.cache[remoteAddr].healthy
}

func (ctx *Context) runHeartbeat(cc *grpc.ClientConn, remoteAddr string) error {
	request := PingRequest{Addr: ctx.Addr}
	heartbeatClient := NewHeartbeatClient(cc)

	var heartbeatTimer timeutil.Timer
	defer heartbeatTimer.Stop()

	// Give the first iteration a wait-free heartbeat attempt.
	nextHeartbeat := 0 * time.Nanosecond
	for {
		heartbeatTimer.Reset(nextHeartbeat)
		select {
		case <-ctx.Stopper.ShouldStop():
			return nil
		case <-heartbeatTimer.C:
			heartbeatTimer.Read = true
		}

		sendTime := ctx.localClock.PhysicalTime()
		response, err := ctx.heartbeat(heartbeatClient, request)
		ctx.setConnHealthy(remoteAddr, err == nil)
		if err == nil {
			receiveTime := ctx.localClock.PhysicalTime()

			// Only update the clock offset measurement if we actually got a
			// successful response from the server.
			if pingDuration := receiveTime.Sub(sendTime); pingDuration > maximumPingDurationMult*ctx.localClock.MaxOffset() {
				request.Offset.Reset()
			} else {
				// Offset and error are measured using the remote clock reading
				// technique described in
				// http://se.inf.tu-dresden.de/pubs/papers/SRDS1994.pdf, page 6.
				// However, we assume that drift and min message delay are 0, for
				// now.
				request.Offset.MeasuredAt = receiveTime.UnixNano()
				request.Offset.Uncertainty = (pingDuration / 2).Nanoseconds()
				remoteTimeNow := time.Unix(0, response.ServerTime).Add(pingDuration / 2)
				request.Offset.Offset = remoteTimeNow.Sub(receiveTime).Nanoseconds()
			}
			ctx.RemoteClocks.UpdateOffset(remoteAddr, request.Offset)

			if cb := ctx.HeartbeatCB; cb != nil {
				cb()
			}
		}

		// If the heartbeat timed out, run the next one immediately. Otherwise,
		// wait out the heartbeat interval on the next iteration.
		if grpc.Code(err) == codes.DeadlineExceeded {
			nextHeartbeat = 0
		} else {
			nextHeartbeat = ctx.HeartbeatInterval
		}
	}
}

func (ctx *Context) heartbeat(heartbeatClient HeartbeatClient, request PingRequest) (*PingResponse, error) {
	goCtx, cancel := context.WithTimeout(context.Background(), ctx.HeartbeatTimeout)
	defer cancel()
	// NB: We want the request to fail-fast (the default), otherwise we won't be
	// notified of transport failures.
	return heartbeatClient.Ping(goCtx, &request)
}
<commit_msg>Revert "Revert "Enable grpc tracing. Goes into /debug/requests automatically""<commit_after>// Copyright 2015 The Cockroach Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
// implied. See the License for the specific language governing
// permissions and limitations under the License.
//
// Author: Tamir Duberstein (tamird@gmail.com)

package rpc

import (
	"math"
	"time"

	"github.com/rubyist/circuitbreaker"
	"golang.org/x/net/context"
	"google.golang.org/grpc"
	"google.golang.org/grpc/codes"
	"google.golang.org/grpc/credentials"

	"github.com/cockroachdb/cockroach/base"
	"github.com/cockroachdb/cockroach/roachpb"
	"github.com/cockroachdb/cockroach/util/grpcutil"
	"github.com/cockroachdb/cockroach/util/hlc"
	"github.com/cockroachdb/cockroach/util/log"
	"github.com/cockroachdb/cockroach/util/stop"
	"github.com/cockroachdb/cockroach/util/syncutil"
	"github.com/cockroachdb/cockroach/util/timeutil"
)

const (
	defaultHeartbeatInterval = 3 * time.Second
	// The coefficient by which the maximum offset is multiplied to determine the
	// maximum acceptable measurement latency.
	maximumPingDurationMult = 2
)

// NewServer is a thin wrapper around grpc.NewServer that registers a heartbeat
// service.
func NewServer(ctx *Context) *grpc.Server {
	opts := []grpc.ServerOption{
		grpc.MaxMsgSize(math.MaxInt32), // TODO(peter,tamird): need tests before lowering
	}
	if !ctx.Insecure {
		tlsConfig, err := ctx.GetServerTLSConfig()
		if err != nil {
			panic(err)
		}
		opts = append(opts, grpc.Creds(credentials.NewTLS(tlsConfig)))
	}
	s := grpc.NewServer(opts...)
	RegisterHeartbeatServer(s, &HeartbeatService{
		clock:              ctx.localClock,
		remoteClockMonitor: ctx.RemoteClocks,
	})
	return s
}

type connMeta struct {
	conn    *grpc.ClientConn
	healthy bool
}

// Context contains the fields required by the rpc framework.
type Context struct {
	*base.Context

	localClock   *hlc.Clock
	breakerClock breakerClock
	Stopper      *stop.Stopper
	RemoteClocks *RemoteClockMonitor

	HeartbeatInterval time.Duration
	HeartbeatTimeout  time.Duration
	HeartbeatCB       func()

	localInternalServer roachpb.InternalServer

	conns struct {
		syncutil.Mutex
		cache map[string]connMeta
	}
}

// NewContext creates an rpc Context with the supplied values.
func NewContext(baseCtx *base.Context, hlcClock *hlc.Clock, stopper *stop.Stopper) *Context {
	ctx := &Context{
		Context: baseCtx,
	}
	if hlcClock != nil {
		ctx.localClock = hlcClock
	} else {
		ctx.localClock = hlc.NewClock(hlc.UnixNano)
	}
	ctx.breakerClock = breakerClock{
		clock: ctx.localClock,
	}
	ctx.Stopper = stopper
	ctx.RemoteClocks = newRemoteClockMonitor(ctx.localClock, 10*defaultHeartbeatInterval)
	ctx.HeartbeatInterval = defaultHeartbeatInterval
	ctx.HeartbeatTimeout = 2 * defaultHeartbeatInterval
	ctx.conns.cache = make(map[string]connMeta)

	stopper.RunWorker(func() {
		<-stopper.ShouldQuiesce()

		ctx.conns.Lock()
		for key, meta := range ctx.conns.cache {
			ctx.removeConn(key, meta.conn)
		}
		ctx.conns.Unlock()
	})

	return ctx
}

// GetLocalInternalServerForAddr returns the context's internal batch server
// for addr, if it exists.
func (ctx *Context) GetLocalInternalServerForAddr(addr string) roachpb.InternalServer {
	if addr == ctx.Addr {
		return ctx.localInternalServer
	}
	return nil
}

// SetLocalInternalServer sets the context's local internal batch server.
func (ctx *Context) SetLocalInternalServer(internalServer roachpb.InternalServer) {
	ctx.localInternalServer = internalServer
}

func (ctx *Context) removeConn(key string, conn *grpc.ClientConn) {
	if log.V(1) {
		log.Infof(context.TODO(), "closing %s", key)
	}
	if err := conn.Close(); err != nil && !grpcutil.IsClosedConnection(err) {
		if log.V(1) {
			log.Errorf(context.TODO(), "failed to close client connection: %s", err)
		}
	}
	delete(ctx.conns.cache, key)
}

// GRPCDial calls grpc.Dial with the options appropriate for the context.
func (ctx *Context) GRPCDial(target string, opts ...grpc.DialOption) (*grpc.ClientConn, error) {
	ctx.conns.Lock()
	defer ctx.conns.Unlock()

	if meta, ok := ctx.conns.cache[target]; ok {
		return meta.conn, nil
	}

	dialOpt, err := ctx.GRPCDialOption()
	if err != nil {
		return nil, err
	}

	dialOpts := make([]grpc.DialOption, 0, 1+len(opts))
	dialOpts = append(dialOpts, dialOpt)
	dialOpts = append(dialOpts, opts...)

	if log.V(1) {
		log.Infof(context.TODO(), "dialing %s", target)
	}
	conn, err := grpc.Dial(target, dialOpts...)
	if err == nil {
		ctx.conns.cache[target] = connMeta{conn: conn}

		if ctx.Stopper.RunTask(func() {
			ctx.Stopper.RunWorker(func() {
				err := ctx.runHeartbeat(conn, target)
				if err != nil && !grpcutil.IsClosedConnection(err) {
					log.Error(context.TODO(), err)
				}
				ctx.conns.Lock()
				ctx.removeConn(target, conn)
				ctx.conns.Unlock()
			})
		}) != nil {
			ctx.removeConn(target, conn)
		}
	}
	return conn, err
}

// GRPCDialOption returns the GRPC dialing option appropriate for the context.
func (ctx *Context) GRPCDialOption() (grpc.DialOption, error) {
	var dialOpt grpc.DialOption
	if ctx.Insecure {
		dialOpt = grpc.WithInsecure()
	} else {
		tlsConfig, err := ctx.GetClientTLSConfig()
		if err != nil {
			return dialOpt, err
		}
		dialOpt = grpc.WithTransportCredentials(credentials.NewTLS(tlsConfig))
	}
	return dialOpt, nil
}

// NewBreaker creates a new circuit breaker properly configured for RPC
// connections.
func (ctx *Context) NewBreaker() *circuit.Breaker {
	return newBreaker(&ctx.breakerClock)
}

// setConnHealthy sets the health status of the connection.
func (ctx *Context) setConnHealthy(remoteAddr string, healthy bool) {
	ctx.conns.Lock()
	defer ctx.conns.Unlock()

	meta, ok := ctx.conns.cache[remoteAddr]
	if ok {
		meta.healthy = healthy
		ctx.conns.cache[remoteAddr] = meta
	}
}

// IsConnHealthy returns whether the most recent heartbeat succeeded or not.
// This should not be used as a definite status of a nodes health and just used
// to prioritized healthy nodes over unhealthy ones.
func (ctx *Context) IsConnHealthy(remoteAddr string) bool {
	ctx.conns.Lock()
	defer ctx.conns.Unlock()

	return ctx.conns.cache[remoteAddr].healthy
}

func (ctx *Context) runHeartbeat(cc *grpc.ClientConn, remoteAddr string) error {
	request := PingRequest{Addr: ctx.Addr}
	heartbeatClient := NewHeartbeatClient(cc)

	var heartbeatTimer timeutil.Timer
	defer heartbeatTimer.Stop()

	// Give the first iteration a wait-free heartbeat attempt.
	nextHeartbeat := 0 * time.Nanosecond
	for {
		heartbeatTimer.Reset(nextHeartbeat)
		select {
		case <-ctx.Stopper.ShouldStop():
			return nil
		case <-heartbeatTimer.C:
			heartbeatTimer.Read = true
		}

		sendTime := ctx.localClock.PhysicalTime()
		response, err := ctx.heartbeat(heartbeatClient, request)
		ctx.setConnHealthy(remoteAddr, err == nil)
		if err == nil {
			receiveTime := ctx.localClock.PhysicalTime()

			// Only update the clock offset measurement if we actually got a
			// successful response from the server.
			if pingDuration := receiveTime.Sub(sendTime); pingDuration > maximumPingDurationMult*ctx.localClock.MaxOffset() {
				request.Offset.Reset()
			} else {
				// Offset and error are measured using the remote clock reading
				// technique described in
				// http://se.inf.tu-dresden.de/pubs/papers/SRDS1994.pdf, page 6.
				// However, we assume that drift and min message delay are 0, for
				// now.
				request.Offset.MeasuredAt = receiveTime.UnixNano()
				request.Offset.Uncertainty = (pingDuration / 2).Nanoseconds()
				remoteTimeNow := time.Unix(0, response.ServerTime).Add(pingDuration / 2)
				request.Offset.Offset = remoteTimeNow.Sub(receiveTime).Nanoseconds()
			}
			ctx.RemoteClocks.UpdateOffset(remoteAddr, request.Offset)

			if cb := ctx.HeartbeatCB; cb != nil {
				cb()
			}
		}

		// If the heartbeat timed out, run the next one immediately. Otherwise,
		// wait out the heartbeat interval on the next iteration.
		if grpc.Code(err) == codes.DeadlineExceeded {
			nextHeartbeat = 0
		} else {
			nextHeartbeat = ctx.HeartbeatInterval
		}
	}
}

func (ctx *Context) heartbeat(heartbeatClient HeartbeatClient, request PingRequest) (*PingResponse, error) {
	goCtx, cancel := context.WithTimeout(context.Background(), ctx.HeartbeatTimeout)
	defer cancel()
	// NB: We want the request to fail-fast (the default), otherwise we won't be
	// notified of transport failures.
	return heartbeatClient.Ping(goCtx, &request)
}
<|endoftext|>


<commit_before>// Copyright 2017 gf Author(https://github.com/gogf/gf). All Rights Reserved.
//
// This Source Code Form is subject to the terms of the MIT License.
// If a copy of the MIT was not distributed with this file,
// You can obtain one at https://github.com/gogf/gf.

package gdb

import (
	"fmt"
	"github.com/gogf/gf/container/gset"
	"github.com/gogf/gf/text/gstr"
)

// Filter marks filtering the fields which does not exist in the fields of the operated table.
// Note that this function supports only single table operations.
func (m *Model) Filter() *Model {
	if gstr.Contains(m.tables, " ") {
		panic("function Filter supports only single table operations")
	}
	model := m.getModel()
	model.filter = true
	return model
}

// Fields sets the operation fields of the model, multiple fields joined using char ','.
func (m *Model) Fields(fields string) *Model {
	model := m.getModel()
	model.fields = fields
	return model
}

// FieldsEx sets the excluded operation fields of the model, multiple fields joined using char ','.
// Note that this function supports only single table operations.
func (m *Model) FieldsEx(fields string) *Model {
	model := m.getModel()
	model.fieldsEx = fields
	return model
}

// Deprecated, use GetFieldsStr instead.
// This function name confuses the user that it was a chaining function.
func (m *Model) FieldsStr(prefix ...string) string {
	return m.GetFieldsStr(prefix...)
}

// FieldsStr retrieves and returns all fields from the table, joined with char ','.
// The optional parameter <prefix> specifies the prefix for each field, eg: FieldsStr("u.").
func (m *Model) GetFieldsStr(prefix ...string) string {
	prefixStr := ""
	if len(prefix) > 0 {
		prefixStr = prefix[0]
	}
	tableFields, err := m.db.TableFields(m.tables)
	if err != nil {
		panic(err)
	}
	if len(tableFields) == 0 {
		panic(fmt.Sprintf(`empty table fields for table "%s"`, m.tables))
	}
	fieldsArray := make([]string, len(tableFields))
	for k, v := range tableFields {
		fieldsArray[v.Index] = k
	}
	newFields := ""
	for _, k := range fieldsArray {
		if len(newFields) > 0 {
			newFields += ","
		}
		newFields += prefixStr + k
	}
	newFields = m.db.QuoteString(newFields)
	return newFields
}

// Deprecated, use GetFieldsExStr instead.
// This function name confuses the user that it was a chaining function.
func (m *Model) FieldsExStr(fields string, prefix ...string) string {
	return m.GetFieldsExStr(fields, prefix...)
}

// FieldsExStr retrieves and returns fields which are not in parameter <fields> from the table,
// joined with char ','.
// The parameter <fields> specifies the fields that are excluded.
// The optional parameter <prefix> specifies the prefix for each field, eg: FieldsExStr("id", "u.").
func (m *Model) GetFieldsExStr(fields string, prefix ...string) string {
	prefixStr := ""
	if len(prefix) > 0 {
		prefixStr = prefix[0]
	}
	tableFields, err := m.db.TableFields(m.tables)
	if err != nil {
		panic(err)
	}
	if len(tableFields) == 0 {
		panic(fmt.Sprintf(`empty table fields for table "%s"`, m.tables))
	}
	fieldsExSet := gset.NewStrSetFrom(gstr.SplitAndTrim(fields, ","))
	fieldsArray := make([]string, len(tableFields))
	for k, v := range tableFields {
		fieldsArray[v.Index] = k
	}
	newFields := ""
	for _, k := range fieldsArray {
		if fieldsExSet.Contains(k) {
			continue
		}
		if len(newFields) > 0 {
			newFields += ","
		}
		newFields += prefixStr + k
	}
	newFields = m.db.QuoteString(newFields)
	return newFields
}

// HasField determine whether the field exists in the table.
func (m *Model) HasField(field string) (bool, error) {
	tableFields, err := m.db.TableFields(m.tables)
	if err != nil {
		return false, err
	}
	if len(tableFields) == 0 {
		return false, fmt.Errorf(`empty table fields for table "%s"`, m.tables)
	}
	fieldsArray := make([]string, len(tableFields))
	for k, v := range tableFields {
		fieldsArray[v.Index] = k
	}
	for _, f := range fieldsArray {
		if f == field {
			return true, nil
		}
	}
	return false, nil
}
<commit_msg>improve gdb.Model.Fields/FieldsEx for package gdb<commit_after>// Copyright 2017 gf Author(https://github.com/gogf/gf). All Rights Reserved.
//
// This Source Code Form is subject to the terms of the MIT License.
// If a copy of the MIT was not distributed with this file,
// You can obtain one at https://github.com/gogf/gf.

package gdb

import (
	"fmt"
	"github.com/gogf/gf/container/gset"
	"github.com/gogf/gf/text/gstr"
)

// Filter marks filtering the fields which does not exist in the fields of the operated table.
// Note that this function supports only single table operations.
func (m *Model) Filter() *Model {
	if gstr.Contains(m.tables, " ") {
		panic("function Filter supports only single table operations")
	}
	model := m.getModel()
	model.filter = true
	return model
}

// Fields sets the operation fields of the model, multiple fields joined using char ','.
func (m *Model) Fields(fields ...string) *Model {
	if len(fields) > 0 {
		model := m.getModel()
		model.fields = gstr.Join(fields, ",")
		return model
	}
	return m
}

// FieldsEx sets the excluded operation fields of the model, multiple fields joined using char ','.
// Note that this function supports only single table operations.
func (m *Model) FieldsEx(fields ...string) *Model {
	if len(fields) > 0 {
		model := m.getModel()
		model.fieldsEx = gstr.Join(fields, ",")
		return model
	}
	return m
}

// Deprecated, use GetFieldsStr instead.
// This function name confuses the user that it was a chaining function.
func (m *Model) FieldsStr(prefix ...string) string {
	return m.GetFieldsStr(prefix...)
}

// FieldsStr retrieves and returns all fields from the table, joined with char ','.
// The optional parameter <prefix> specifies the prefix for each field, eg: FieldsStr("u.").
func (m *Model) GetFieldsStr(prefix ...string) string {
	prefixStr := ""
	if len(prefix) > 0 {
		prefixStr = prefix[0]
	}
	tableFields, err := m.db.TableFields(m.tables)
	if err != nil {
		panic(err)
	}
	if len(tableFields) == 0 {
		panic(fmt.Sprintf(`empty table fields for table "%s"`, m.tables))
	}
	fieldsArray := make([]string, len(tableFields))
	for k, v := range tableFields {
		fieldsArray[v.Index] = k
	}
	newFields := ""
	for _, k := range fieldsArray {
		if len(newFields) > 0 {
			newFields += ","
		}
		newFields += prefixStr + k
	}
	newFields = m.db.QuoteString(newFields)
	return newFields
}

// Deprecated, use GetFieldsExStr instead.
// This function name confuses the user that it was a chaining function.
func (m *Model) FieldsExStr(fields string, prefix ...string) string {
	return m.GetFieldsExStr(fields, prefix...)
}

// FieldsExStr retrieves and returns fields which are not in parameter <fields> from the table,
// joined with char ','.
// The parameter <fields> specifies the fields that are excluded.
// The optional parameter <prefix> specifies the prefix for each field, eg: FieldsExStr("id", "u.").
func (m *Model) GetFieldsExStr(fields string, prefix ...string) string {
	prefixStr := ""
	if len(prefix) > 0 {
		prefixStr = prefix[0]
	}
	tableFields, err := m.db.TableFields(m.tables)
	if err != nil {
		panic(err)
	}
	if len(tableFields) == 0 {
		panic(fmt.Sprintf(`empty table fields for table "%s"`, m.tables))
	}
	fieldsExSet := gset.NewStrSetFrom(gstr.SplitAndTrim(fields, ","))
	fieldsArray := make([]string, len(tableFields))
	for k, v := range tableFields {
		fieldsArray[v.Index] = k
	}
	newFields := ""
	for _, k := range fieldsArray {
		if fieldsExSet.Contains(k) {
			continue
		}
		if len(newFields) > 0 {
			newFields += ","
		}
		newFields += prefixStr + k
	}
	newFields = m.db.QuoteString(newFields)
	return newFields
}

// HasField determine whether the field exists in the table.
func (m *Model) HasField(field string) (bool, error) {
	tableFields, err := m.db.TableFields(m.tables)
	if err != nil {
		return false, err
	}
	if len(tableFields) == 0 {
		return false, fmt.Errorf(`empty table fields for table "%s"`, m.tables)
	}
	fieldsArray := make([]string, len(tableFields))
	for k, v := range tableFields {
		fieldsArray[v.Index] = k
	}
	for _, f := range fieldsArray {
		if f == field {
			return true, nil
		}
	}
	return false, nil
}
<|endoftext|>


<commit_before>package daemon

import (
	"encoding/json"
	"os"
	"os/signal"

	log "github.com/socketplane/socketplane/Godeps/_workspace/src/github.com/Sirupsen/logrus"
	"github.com/socketplane/socketplane/Godeps/_workspace/src/github.com/codegangsta/cli"
	"github.com/socketplane/socketplane/datastore"
	"github.com/socketplane/socketplane/network"
	"github.com/socketplane/socketplane/ovs"
)

type Daemon struct {
	Configuration *Configuration
	Connections   map[string]*Connection
}

func NewDaemon() *Daemon {
	return &Daemon{
		&Configuration{},
		map[string]*Connection{},
	}
}

func (d *Daemon) Run(ctx *cli.Context) {
	if ctx.Bool("debug") {
		log.SetLevel(log.DebugLevel)
	}

	var bindInterface string
	if ctx.String("iface") != "auto" {
		bindInterface = ctx.String("iface")
	} else {
		intf := InterfaceToBind()
		if intf != nil {
			bindInterface = intf.Name
		}
	}
	log.Debugf("Binding to %s", bindInterface)
	go ServeAPI(d)
	go func() {
		ovs.CreateBridge("")
		network.CreateDefaultNetwork(ovs.OvsBridge.Subnet)
		d.populateConnections()
	}()
	go Bonjour(bindInterface)
	go datastore.Init(bindInterface, ctx.Bool("bootstrap"))
	c := make(chan os.Signal, 1)
	signal.Notify(c, os.Interrupt)
	go func() {
		for _ = range c {
			os.Exit(0)
		}
	}()
	select {}
}

func (d *Daemon) populateConnections() {
	for key, val := range ovs.ContextCache {
		connection := &Connection{}
		err := json.Unmarshal([]byte(val), connection)
		if err == nil {
			d.Connections[key] = connection
		}
	}
}
<commit_msg>Serialized bonjour, ipam, ecc and network services<commit_after>package daemon

import (
	"encoding/json"
	"os"
	"os/signal"

	log "github.com/socketplane/socketplane/Godeps/_workspace/src/github.com/Sirupsen/logrus"
	"github.com/socketplane/socketplane/Godeps/_workspace/src/github.com/codegangsta/cli"
	"github.com/socketplane/socketplane/datastore"
	"github.com/socketplane/socketplane/network"
	"github.com/socketplane/socketplane/ovs"
)

type Daemon struct {
	Configuration *Configuration
	Connections   map[string]*Connection
}

func NewDaemon() *Daemon {
	return &Daemon{
		&Configuration{},
		map[string]*Connection{},
	}
}

func (d *Daemon) Run(ctx *cli.Context) {
	if ctx.Bool("debug") {
		log.SetLevel(log.DebugLevel)
	}

	var bindInterface string
	if ctx.String("iface") != "auto" {
		bindInterface = ctx.String("iface")
	} else {
		intf := InterfaceToBind()
		if intf != nil {
			bindInterface = intf.Name
		}
	}
	log.Debugf("Binding to %s", bindInterface)
	go ServeAPI(d)
	go func() {
		ovs.CreateBridge("")
		d.populateConnections()
		datastore.Init(bindInterface, ctx.Bool("bootstrap"))
		network.CreateDefaultNetwork(ovs.OvsBridge.Subnet)
		Bonjour(bindInterface)
	}()
	c := make(chan os.Signal, 1)
	signal.Notify(c, os.Interrupt)
	go func() {
		for _ = range c {
			os.Exit(0)
		}
	}()
	select {}
}

func (d *Daemon) populateConnections() {
	for key, val := range ovs.ContextCache {
		connection := &Connection{}
		err := json.Unmarshal([]byte(val), connection)
		if err == nil {
			d.Connections[key] = connection
		}
	}
}
<|endoftext|>


<commit_before>package floatgeom

// A Rect2 represents a span from one point in 2D space to another.
// If Min is less than max on any axis, it will return undefined results
// for methods.
type Rect2 struct {
	Min, Max Point2
}

// MaxDimensions reports that a Rect2 has only two dimensions of definition.
func (r Rect2) MaxDimensions() int {
	return 2
}

// A Rect3 represents a span from one point in 3D space to another.
// If Min is less than Max on any axis, it will return undefined results
// for methods.
type Rect3 struct {
	Min, Max Point3
}

// MaxDimensions reports that a Rect3 has only three dimensions of definition.
func (r Rect3) MaxDimensions() int {
	return 3
}

// NewRect2 returns an (X,Y):(X2,Y2) rectangle. This enforces that
// x < x2 and y < y2, and will swap the inputs if that is not true.
// If that enforcement is not desired, construct the struct manually.
func NewRect2(x, y, x2, y2 float64) Rect2 {
	if x > x2 {
		x, x2 = x2, x
	}
	if y > y2 {
		y, y2 = y2, y
	}
	return Rect2{
		Min: Point2{x, y},
		Max: Point2{x2, y2},
	}
}

// NewRect2WH returns an (X,Y):(X+W,Y+H) rectangle. This enforces that
// w and h are positive, and will decrease x and y respectively if that is not true.
func NewRect2WH(x, y, w, h float64) Rect2 {
	if w < 0 {
		x += w
		w *= -1
	}
	if h < 0 {
		y += h
		h *= -1
	}
	return Rect2{
		Min: Point2{x, y},
		Max: Point2{x + w, y + h},
	}
}

// NewBoundingRect2 will produce the minimal rectangle that contains all of
// the input points.
func NewBoundingRect2(pts ...Point2) Rect2 {
	return Rect2{
		Min: pts[0].LesserOf(pts...),
		Max: pts[0].GreaterOf(pts...),
	}
}

// NewRect3 returns an (X,Y,Z):(X2,Y2,Z2) rectangle. This enforces that
// x < x2, y < y2, and z < z2, and will swap the inputs if that is not true.
func NewRect3(x, y, z, x2, y2, z2 float64) Rect3 {
	if x > x2 {
		x, x2 = x2, x
	}
	if y > y2 {
		y, y2 = y2, y
	}
	if z > z2 {
		z, z2 = z2, z
	}
	return Rect3{
		Min: Point3{x, y, z},
		Max: Point3{x2, y2, z2},
	}
}

// NewRect3WH returns an (X,Y,Z):(X+W,Y+H,Z+D) rectangle. This enforces that
// w, h, and d and positive, and will decrease x, y, and z respectively if that
// is not true.
func NewRect3WH(x, y, z, w, h, d float64) Rect3 {
	if w < 0 {
		x += w
		w *= -1
	}
	if h < 0 {
		y += h
		h *= -1
	}
	if d < 0 {
		z += d
		d *= -1
	}
	return Rect3{
		Min: Point3{x, y, z},
		Max: Point3{x + w, y + h, z + d},
	}
}

// NewBoundingRect3 will produce the minimal rectangle that contains all of
// the input points.
func NewBoundingRect3(pts ...Point3) Rect3 {
	return Rect3{
		Min: pts[0].LesserOf(pts...),
		Max: pts[0].GreaterOf(pts...),
	}
}

// Shift moves the rectangle by a point returns a new instance
func (r Rect2) Shift(p Point2) Rect2 {
	r.Min = r.Min.Add(p)
	r.Max = r.Max.Add(p)
	return r
}

// Shift moves the rectangle by a point returns a new instance
func (r Rect3) Shift(p Point3) Rect3 {
	r.Min = r.Min.Add(p)
	r.Max = r.Max.Add(p)
	return r
}

// Area returns W * H.
func (r Rect2) Area() float64 {
	return r.W() * r.H()
}

// Span returns the span on this rectangle's ith axis.
func (r Rect2) Span(i int) float64 {
	return r.Max[i] - r.Min[i]
}

// W returns the width of this rectangle.
func (r Rect2) W() float64 {
	return r.Span(0)
}

// H returns the height of this rectangle.
func (r Rect2) H() float64 {
	return r.Span(1)
}

// Space returns W * H * D
func (r Rect3) Space() float64 {
	return r.W() * r.H() * r.D()
}

// Span returns the span on this rectangle's ith axis.
func (r Rect3) Span(i int) float64 {
	return r.Max[i] - r.Min[i]
}

// W returns the width of this rectangle.
func (r Rect3) W() float64 {
	return r.Span(0)
}

// H returns the height of this rectangle.
func (r Rect3) H() float64 {
	return r.Span(1)
}

// D returns the depth of this rectangle.
func (r Rect3) D() float64 {
	return r.Span(2)
}

// Midpoint returns the midpoint of this rectangle's span over a given dimension.
func (r Rect2) Midpoint(i int) float64 {
	return (r.Min[i] + r.Max[i]) / 2
}

// Midpoint returns the midpoint of this rectangle's span over a given dimension.
func (r Rect3) Midpoint(i int) float64 {
	return (r.Min[i] + r.Max[i]) / 2
}

// Center returns the center of this rectangle
func (r Rect2) Center() Point2 {
	return Point2{
		r.Midpoint(0),
		r.Midpoint(1),
	}
}

// Center returns the center of this rectangle
func (r Rect3) Center() Point3 {
	return Point3{
		r.Midpoint(0),
		r.Midpoint(1),
		r.Midpoint(2),
	}
}

// Perimeter computes the sum of the edge lengths of a rectangle.
func (r Rect2) Perimeter() float64 {
	// The number of edges in an n-dimensional rectangle is n * 2^(n-1)
	// (http://en.wikipedia.org/wiki/Hypercube_graph).  Thus the number
	// of edges of length (ai - bi), where the rectangle is determined
	// by p = (a1, a2, ..., an) and q = (b1, b2, ..., bn), is 2^(n-1).
	//
	// The margin of the rectangle, then, is given by the formula
	// 2^(n-1) * [(b1 - a1) + (b2 - a2) + ... + (bn - an)].
	return 2 * (r.W() + r.H())
}

// Margin computes the sum of the edge lengths of a rectangle.
func (r Rect3) Margin() float64 {
	return 4 * (r.W() + r.H() + r.D())
}

// Contains tests whether p is located inside or on the boundary of r.
func (r Rect2) Contains(p Point2) bool {
	return (p.X() >= r.Min.X() &&
		p.X() <= r.Max.X() &&
		p.Y() >= r.Min.Y() &&
		p.Y() <= r.Max.Y())
}

// Contains tests whether p is located inside or on the boundary of r.
func (r Rect3) Contains(p Point3) bool {
	return (p.X() >= r.Min.X() &&
		p.X() <= r.Max.X() &&
		p.Y() >= r.Min.Y() &&
		p.Y() <= r.Max.Y() &&
		p.Z() >= r.Min.Z() &&
		p.Z() <= r.Max.Z())
}

// ContainsRect tests whether r2 is is located inside r1.
func (r Rect2) ContainsRect(r2 Rect2) bool {
	return (r2.Min.X() >= r.Min.X() &&
		r2.Max.X() <= r.Max.X() &&
		r2.Min.Y() >= r.Min.Y() &&
		r2.Max.Y() <= r.Max.Y())
}

// ContainsRect tests whether r2 is is located inside r1.
func (r Rect3) ContainsRect(r2 Rect3) bool {
	return (r2.Min.X() >= r.Min.X() &&
		r2.Max.X() <= r.Max.X() &&
		r2.Min.Y() >= r.Min.Y() &&
		r2.Max.Y() <= r.Max.Y() &&
		r2.Min.Z() >= r.Min.Z() &&
		r2.Max.Z() <= r.Max.Z())
}

// GreaterOf returns a rectangle formed of the lowest values on each
// dimension for Min, and the highest for Max.
func (r Rect2) GreaterOf(r2 Rect2) Rect2 {
	r.Min = r.Min.LesserOf(r2.Min)
	r.Max = r.Max.GreaterOf(r2.Max)
	return r
}

// GreaterOf returns a rectangle formed of the lowest values on each
// dimension for Min, and the highest for Max.
func (r Rect3) GreaterOf(r2 Rect3) Rect3 {
	r.Min = r.Min.LesserOf(r2.Min)
	r.Max = r.Max.GreaterOf(r2.Max)
	return r
}

// Intersects returns whether the two rectangles intersect.
func (r Rect3) Intersects(r2 Rect3) bool {
	// There are four cases of overlap:
	//
	//     1.  a1------------b1
	//              a2------------b2
	//              p--------q
	//
	//     2.       a1------------b1
	//         a2------------b2
	//              p--------q
	//
	//     3.  a1-----------------b1
	//              a2-------b2
	//              p--------q
	//
	//     4.       a1-------b1
	//         a2-----------------b2
	//              p--------q
	//
	// Thus there are only two cases of non-overlap:
	//
	//     1. a1------b1
	//                    a2------b2
	//
	//     2.             a1------b1
	//        a2------b2
	//
	// Enforced by constructor: a1 <= b1 and a2 <= b2.  So we can just
	// check the endpoints.

	return !((r2.Max.X() <= r.Min.X() || r.Max.X() <= r2.Min.X()) ||
		(r2.Max.Y() <= r.Min.Y() || r.Max.Y() <= r2.Min.Y()) ||
		(r2.Max.Z() <= r.Min.Z() || r.Max.Z() <= r2.Min.Z()))
}

// Intersects returns whether the two rectangles intersect.
func (r Rect2) Intersects(r2 Rect2) bool {
	// There are four cases of overlap:
	//
	//     1.  a1------------b1
	//              a2------------b2
	//              p--------q
	//
	//     2.       a1------------b1
	//         a2------------b2
	//              p--------q
	//
	//     3.  a1-----------------b1
	//              a2-------b2
	//              p--------q
	//
	//     4.       a1-------b1
	//         a2-----------------b2
	//              p--------q
	//
	// Thus there are only two cases of non-overlap:
	//
	//     1. a1------b1
	//                    a2------b2
	//
	//     2.             a1------b1
	//        a2------b2
	//
	// Enforced by constructor: a1 <= b1 and a2 <= b2.  So we can just
	// check the endpoints.

	return !((r2.Max.X() <= r.Min.X() || r.Max.X() <= r2.Min.X()) ||
		(r2.Max.Y() <= r.Min.Y() || r.Max.Y() <= r2.Min.Y()))
}

// ProjectZ projects the Rect3 onto the z axis, removing it's
// z component and returning a Rect2
func (r Rect3) ProjectZ() Rect2 {
	return Rect2{
		Min: r.Min.ProjectZ(),
		Max: r.Max.ProjectZ(),
	}
}
<commit_msg>floatgeom/rect: Implement methods for span Generic functions<commit_after>package floatgeom

// A Rect2 represents a span from one point in 2D space to another.
// If Min is less than max on any axis, it will return undefined results
// for methods.
type Rect2 struct {
	Min, Max Point2
}

// MaxDimensions reports that a Rect2 has only two dimensions of definition.
func (r Rect2) MaxDimensions() int {
	return 2
}

// A Rect3 represents a span from one point in 3D space to another.
// If Min is less than Max on any axis, it will return undefined results
// for methods.
type Rect3 struct {
	Min, Max Point3
}

// MaxDimensions reports that a Rect3 has only three dimensions of definition.
func (r Rect3) MaxDimensions() int {
	return 3
}

// NewRect2 returns an (X,Y):(X2,Y2) rectangle. This enforces that
// x < x2 and y < y2, and will swap the inputs if that is not true.
// If that enforcement is not desired, construct the struct manually.
func NewRect2(x, y, x2, y2 float64) Rect2 {
	if x > x2 {
		x, x2 = x2, x
	}
	if y > y2 {
		y, y2 = y2, y
	}
	return Rect2{
		Min: Point2{x, y},
		Max: Point2{x2, y2},
	}
}

// NewRect2WH returns an (X,Y):(X+W,Y+H) rectangle. This enforces that
// w and h are positive, and will decrease x and y respectively if that is not true.
func NewRect2WH(x, y, w, h float64) Rect2 {
	if w < 0 {
		x += w
		w *= -1
	}
	if h < 0 {
		y += h
		h *= -1
	}
	return Rect2{
		Min: Point2{x, y},
		Max: Point2{x + w, y + h},
	}
}

// NewBoundingRect2 will produce the minimal rectangle that contains all of
// the input points.
func NewBoundingRect2(pts ...Point2) Rect2 {
	return Rect2{
		Min: pts[0].LesserOf(pts...),
		Max: pts[0].GreaterOf(pts...),
	}
}

// NewRect3 returns an (X,Y,Z):(X2,Y2,Z2) rectangle. This enforces that
// x < x2, y < y2, and z < z2, and will swap the inputs if that is not true.
func NewRect3(x, y, z, x2, y2, z2 float64) Rect3 {
	if x > x2 {
		x, x2 = x2, x
	}
	if y > y2 {
		y, y2 = y2, y
	}
	if z > z2 {
		z, z2 = z2, z
	}
	return Rect3{
		Min: Point3{x, y, z},
		Max: Point3{x2, y2, z2},
	}
}

// NewRect3WH returns an (X,Y,Z):(X+W,Y+H,Z+D) rectangle. This enforces that
// w, h, and d and positive, and will decrease x, y, and z respectively if that
// is not true.
func NewRect3WH(x, y, z, w, h, d float64) Rect3 {
	if w < 0 {
		x += w
		w *= -1
	}
	if h < 0 {
		y += h
		h *= -1
	}
	if d < 0 {
		z += d
		d *= -1
	}
	return Rect3{
		Min: Point3{x, y, z},
		Max: Point3{x + w, y + h, z + d},
	}
}

// NewBoundingRect3 will produce the minimal rectangle that contains all of
// the input points.
func NewBoundingRect3(pts ...Point3) Rect3 {
	return Rect3{
		Min: pts[0].LesserOf(pts...),
		Max: pts[0].GreaterOf(pts...),
	}
}

// Shift moves the rectangle by a point returns a new instance
func (r Rect2) Shift(p Point2) Rect2 {
	r.Min = r.Min.Add(p)
	r.Max = r.Max.Add(p)
	return r
}

// Shift moves the rectangle by a point returns a new instance
func (r Rect3) Shift(p Point3) Rect3 {
	r.Min = r.Min.Add(p)
	r.Max = r.Max.Add(p)
	return r
}

// Area returns W * H.
func (r Rect2) Area() float64 {
	return r.W() * r.H()
}

// Span returns the span on this rectangle's ith axis.
func (r Rect2) Span(i int) float64 {
	return r.Max[i] - r.Min[i]
}

// W returns the width of this rectangle.
func (r Rect2) W() float64 {
	return r.Span(0)
}

// H returns the height of this rectangle.
func (r Rect2) H() float64 {
	return r.Span(1)
}

// Space returns W * H * D
func (r Rect3) Space() float64 {
	return r.W() * r.H() * r.D()
}

// Span returns the span on this rectangle's ith axis.
func (r Rect3) Span(i int) float64 {
	return r.Max[i] - r.Min[i]
}

// W returns the width of this rectangle.
func (r Rect3) W() float64 {
	return r.Span(0)
}

// H returns the height of this rectangle.
func (r Rect3) H() float64 {
	return r.Span(1)
}

// D returns the depth of this rectangle.
func (r Rect3) D() float64 {
	return r.Span(2)
}

// Midpoint returns the midpoint of this rectangle's span over a given dimension.
func (r Rect2) Midpoi int) float64 {
	return (r.Min[i] + r.Max[i]) / 2
}

// Midpoint returns the midpoint of this rectangle's span over a given dimension.
func (r Rect3) Midpoi int) float64 {
	return (r.Min[i] + r.Max[i]) / 2
}

// Center returns the center of this rectangle
func (r Rect2) Center() Point2 {
	return Point2{
		r.Midpo0),
		r.Midpo1),
	}
}

// Center returns the center of this rectangle
func (r Rect3) Center() Point3 {
	return Point3{
		r.Midpo0),
		r.Midpo1),
		r.Midpo2),
	}
}

// Perimeter computes the sum of the edge lengths of a rectangle.
func (r Rect2) Perimeter() float64 {
	// The number of edges in an n-dimensional rectangle is n * 2^(n-1)
	// (http://en.wikipedia.org/wiki/Hypercube_graph).  Thus the number
	// of edges of length (ai - bi), where the rectangle is determined
	// by p = (a1, a2, ..., an) and q = (b1, b2, ..., bn), is 2^(n-1).
	//
	// The margin of the rectangle, then, is given by the formula
	// 2^(n-1) * [(b1 - a1) + (b2 - a2) + ... + (bn - an)].
	return 2 * (r.W() + r.H())
}

// Margin computes the sum of the edge lengths of a rectangle.
func (r Rect3) Margin() float64 {
	return 4 * (r.W() + r.H() + r.D())
}

// Contains tests whether p is located inside or on the boundary of r.
func (r Rect2) Contains(p Point2) bool {
	return (p.X() >= r.Min.X() &&
		p.X() <= r.Max.X() &&
		p.Y() >= r.Min.Y() &&
		p.Y() <= r.Max.Y())
}

// Contains tests whether p is located inside or on the boundary of r.
func (r Rect3) Contains(p Point3) bool {
	return (p.X() >= r.Min.X() &&
		p.X() <= r.Max.X() &&
		p.Y() >= r.Min.Y() &&
		p.Y() <= r.Max.Y() &&
		p.Z() >= r.Min.Z() &&
		p.Z() <= r.Max.Z())
}

// ContainsRect tests whether r2 is is located inside r1.
func (r Rect2) ContainsRect(r2 Rect2) bool {
	return (r2.Min.X() >= r.Min.X() &&
		r2.Max.X() <= r.Max.X() &&
		r2.Min.Y() >= r.Min.Y() &&
		r2.Max.Y() <= r.Max.Y())
}

// ContainsRect tests whether r2 is is located inside r1.
func (r Rect3) ContainsRect(r2 Rect3) bool {
	return (r2.Min.X() >= r.Min.X() &&
		r2.Max.X() <= r.Max.X() &&
		r2.Min.Y() >= r.Min.Y() &&
		r2.Max.Y() <= r.Max.Y() &&
		r2.Min.Z() >= r.Min.Z() &&
		r2.Max.Z() <= r.Max.Z())
}

// GreaterOf returns a rectangle formed of the lowest values on each
// dimension for Min, and the highest for Max.
func (r Rect2) GreaterOf(r2 Rect2) Rect2 {
	r.Min = r.Min.LesserOf(r2.Min)
	r.Max = r.Max.GreaterOf(r2.Max)
	return r
}

// GreaterOf returns a rectangle formed of the lowest values on each
// dimension for Min, and the highest for Max.
func (r Rect3) GreaterOf(r2 Rect3) Rect3 {
	r.Min = r.Min.LesserOf(r2.Min)
	r.Max = r.Max.GreaterOf(r2.Max)
	return r
}

// Intersects returns whether the two rectangles intersect.
func (r Rect3) Intersects(r2 Rect3) bool {
	// There are four cases of overlap:
	//
	//     1.  a1------------b1
	//              a2------------b2
	//              p--------q
	//
	//     2.       a1------------b1
	//         a2------------b2
	//              p--------q
	//
	//     3.  a1-----------------b1
	//              a2-------b2
	//              p--------q
	//
	//     4.       a1-------b1
	//         a2-----------------b2
	//              p--------q
	//
	// Thus there are only two cases of non-overlap:
	//
	//     1. a1------b1
	//                    a2------b2
	//
	//     2.             a1------b1
	//        a2------b2
	//
	// Enforced by constructor: a1 <= b1 and a2 <= b2.  So we can just
	// check the endpoints.

	return !((r2.Max.X() <= r.Min.X() || r.Max.X() <= r2.Min.X()) ||
		(r2.Max.Y() <= r.Min.Y() || r.Max.Y() <= r2.Min.Y()) ||
		(r2.Max.Z() <= r.Min.Z() || r.Max.Z() <= r2.Min.Z()))
}

// Intersects returns whether the two rectangles intersect.
func (r Rect2) Intersects(r2 Rect2) bool {
	// There are four cases of overlap:
	//
	//     1.  a1------------b1
	//              a2------------b2
	//              p--------q
	//
	//     2.       a1------------b1
	//         a2------------b2
	//              p--------q
	//
	//     3.  a1-----------------b1
	//              a2-------b2
	//              p--------q
	//
	//     4.       a1-------b1
	//         a2-----------------b2
	//              p--------q
	//
	// Thus there are only two cases of non-overlap:
	//
	//     1. a1------b1
	//                    a2------b2
	//
	//     2.             a1------b1
	//        a2------b2
	//
	// Enforced by constructor: a1 <= b1 and a2 <= b2.  So we can just
	// check the endpoints.

	return !((r2.Max.X() <= r.Min.X() || r.Max.X() <= r2.Min.X()) ||
		(r2.Max.Y() <= r.Min.Y() || r.Max.Y() <= r2.Min.Y()))
}

// ProjectZ projects the Rect3 onto the z axis, removing it's
// z component and returning a Rect2
func (r Rect3) ProjectZ() Rect2 {
	return Rect2{
		Min: r.Min.ProjectZ(),
		Max: r.Max.ProjectZ(),
	}
}

// Poll returns a pseudorandom point from within this rectangle
func (r Rect2) Poll() Point2 {
	return Point2{
		r.Min.X() + rand.Float64()*float64(r.W()),
		r.Min.Y() + rand.Float64()*float64(r.H()),
	}
}

// Clamp returns a version of the provided point such that it is contained within r. If it was already contained in
// r, it will not be changed.
func (r Rect2) Clamp(pt Point2) Point2 {
	for i := 0; i < r.MaxDimensions(); i++ {
		if pt[i] < r.Min[i] {
			pt[i] = r.Min[i]
		} else if pt[i] > r.Max[i] {
			pt[i] = r.Max[i]
		}
	}
	return pt
}

// Percentile returns a point within this rectangle along the vector from the top left to the bottom right of the
// rectangle, where for example, 0.0 will be r.Min, 1.0 will be r.Max, and 2.0 will be project the vector beyond r
// and return r.Min + {r.W()*2, r.H()*2}
func (r Rect2) Percentile(f float64) Point2 {
	return Point2{
		r.Min.X() + f*float64(r.W()),
		r.Min.Y() + f*float64(r.H()),
	}
}

// MulSpan returns this rectangle as a Point2 Span after multiplying the boundary points of the rectangle by f.
func (r Rect2) MulSpan(f float64) span.Span[Point2] {
	return r.MulConst(f))
}<|endoftext|>


<commit_before>package chunkstore

import (
	. "chunkymonkey/types"
)

// MultiStore provides the ability to load a chunk from one or more potential
// sources of chunk data. The primary purpose of this is to read from a
// persistant store first, then fall back to generating a chunk if the
// persistant store does not have it. MultiStore implements IChunkStore.
type MultiStore struct {
	stores []IChunkStore
}

func NewMultiStore(stores []IChunkStore) *MultiStore {
	return &MultiStore{
		stores: stores,
	}
}

func (s *MultiStore) LoadChunk(chunkLoc *ChunkXz) (result <-chan ChunkResult) {
	resultChan := make(chan ChunkResult)

	go s.loadChunk(chunkLoc, resultChan)

	return resultChan
}

func (s *MultiStore) loadChunk(chunkLoc *ChunkXz, resultChan chan<- ChunkResult) {
	for _, store := range s.stores {
		result := <-store.LoadChunk(chunkLoc)
		if result.Err != nil {
			if _, ok := result.Err.(NoSuchChunkError); ok {
				// Fall through to next chunk store.
				continue
			}
		}

		resultChan<- result
	}

	resultChan<- ChunkResult{
		Reader: nil,
		Err:    NoSuchChunkError(false),
	}
}
<commit_msg>Added a TODO note to fix MultiStore.<commit_after>package chunkstore

import (
	. "chunkymonkey/types"
)

// MultiStore provides the ability to load a chunk from one or more potential
// sources of chunk data. The primary purpose of this is to read from a
// persistant store first, then fall back to generating a chunk if the
// persistant store does not have it. MultiStore implements IChunkStore.
type MultiStore struct {
	stores []IChunkStore
}

func NewMultiStore(stores []IChunkStore) *MultiStore {
	return &MultiStore{
		stores: stores,
	}
}

func (s *MultiStore) LoadChunk(chunkLoc *ChunkXz) (result <-chan ChunkResult) {
	resultChan := make(chan ChunkResult)

	// TODO This very rapidly creates large numbers of goroutines when generating
	// chunks and exhausts memory. Should generate from a pool instead.
	go s.loadChunk(chunkLoc, resultChan)

	return resultChan
}

func (s *MultiStore) loadChunk(chunkLoc *ChunkXz, resultChan chan<- ChunkResult) {
	for _, store := range s.stores {
		result := <-store.LoadChunk(chunkLoc)
		if result.Err != nil {
			if _, ok := result.Err.(NoSuchChunkError); ok {
				// Fall through to next chunk store.
				continue
			}
		}

		resultChan<- result
	}

	resultChan<- ChunkResult{
		Reader: nil,
		Err:    NoSuchChunkError(false),
	}
}
<|endoftext|>


<commit_before>package runner

import (
	"context"
	"encoding/json"
	"fmt"
	"io/ioutil"
	"math/rand"
	"net/http"
	"net/http/httptest"
	"testing"

	"github.com/Sirupsen/logrus"
	"github.com/gin-gonic/gin"
	"github.com/iron-io/functions/api/models"
	"github.com/iron-io/functions/api/mqs"
)

func getMockTask() models.Task {
	priority := int32(0)
	image := fmt.Sprintf("Image-%d", rand.Int31()%1000)
	task := &models.Task{}
	task.Image = &image
	task.ID = fmt.Sprintf("ID-%d", rand.Int31()%1000)
	task.RouteName = fmt.Sprintf("RouteName-%d", rand.Int31()%1000)
	task.Priority = &priority
	return *task
}

func getTestServer(mockTasks []*models.Task) *httptest.Server {
	ctx := context.TODO()

	mq, err := mqs.New("memory://test")
	if err != nil {
		panic(err)
	}

	for _, mt := range mockTasks {
		mq.Push(ctx, mt)
	}

	getHandler := func(c *gin.Context) {
		task, err := mq.Reserve(ctx)
		if err != nil {
			logrus.WithError(err)
			c.JSON(http.StatusInternalServerError, err)
			return
		}
		c.JSON(http.StatusAccepted, task)
	}

	delHandler := func(c *gin.Context) {
		body, err := ioutil.ReadAll(c.Request.Body)
		if err != nil {
			logrus.WithError(err)
			c.JSON(http.StatusInternalServerError, err.Error())
			return
		}
		var task models.Task
		if err = json.Unmarshal(body, &task); err != nil {
			logrus.WithError(err)
			c.JSON(http.StatusInternalServerError, err.Error())
			return
		}

		if err := mq.Delete(ctx, &task); err != nil {
			logrus.WithError(err)
			c.JSON(http.StatusInternalServerError, err.Error())
			return
		}
		c.JSON(http.StatusAccepted, task)
	}

	r := gin.Default()
	r.GET("/tasks", getHandler)
	r.DELETE("/tasks", delHandler)
	return httptest.NewServer(r)
}

func TestGetTask(t *testing.T) {
	mockTask := getMockTask()

	ts := getTestServer([]*models.Task{&mockTask})
	defer ts.Close()

	url := ts.URL + "/tasks"
	task, err := getTask(url)
	if err != nil {
		t.Error("expected no error, got", err)
	}
	if task.ID != mockTask.ID {
		t.Errorf("expected task ID '%s', got '%s'", task.ID, mockTask.ID)
	}
}

func TestGetTaskError(t *testing.T) {
	tests := []map[string]interface{}{
		map[string]interface{}{
			"url":   "/invalid",
			"task":  getMockTask(),
			"error": "invalid character 'p' after top-level value",
		},
	}

	var tasks []*models.Task
	for _, v := range tests {
		task := v["task"].(models.Task)
		tasks = append(tasks, &task)
	}

	ts := getTestServer(tasks)
	defer ts.Close()

	for i, test := range tests {
		url := ts.URL + test["url"].(string)
		_, err := getTask(url)
		if err == nil {
			t.Errorf("expected error '%s'", test["error"].(string))
		}
		if err.Error() != test["error"].(string) {
			t.Errorf("test %d: expected error '%s', got '%s'", i, test["error"].(string), err)
		}
	}
}

func TestDeleteTask(t *testing.T) {
	mockTask := getMockTask()

	ts := getTestServer([]*models.Task{&mockTask})
	defer ts.Close()

	url := ts.URL + "/tasks"
	err := deleteTask(url, &mockTask)
	if err == nil {
		t.Error("expected error 'Not reserver', got", err)
	}

	_, err = getTask(url)
	if err != nil {
		t.Error("expected no error, got", err)
	}

	err = deleteTask(url, &mockTask)
	if err != nil {
		t.Error("expected no error, got", err)
	}
}
<commit_msg>context -> golang.org/x/net/context<commit_after>package runner

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"math/rand"
	"net/http"
	"net/http/httptest"
	"testing"

	"github.com/Sirupsen/logrus"
	"github.com/gin-gonic/gin"
	"github.com/iron-io/functions/api/models"
	"github.com/iron-io/functions/api/mqs"
	"golang.org/x/net/context"
)

func getMockTask() models.Task {
	priority := int32(0)
	image := fmt.Sprintf("Image-%d", rand.Int31()%1000)
	task := &models.Task{}
	task.Image = &image
	task.ID = fmt.Sprintf("ID-%d", rand.Int31()%1000)
	task.RouteName = fmt.Sprintf("RouteName-%d", rand.Int31()%1000)
	task.Priority = &priority
	return *task
}

func getTestServer(mockTasks []*models.Task) *httptest.Server {
	ctx := context.TODO()

	mq, err := mqs.New("memory://test")
	if err != nil {
		panic(err)
	}

	for _, mt := range mockTasks {
		mq.Push(ctx, mt)
	}

	getHandler := func(c *gin.Context) {
		task, err := mq.Reserve(ctx)
		if err != nil {
			logrus.WithError(err)
			c.JSON(http.StatusInternalServerError, err)
			return
		}
		c.JSON(http.StatusAccepted, task)
	}

	delHandler := func(c *gin.Context) {
		body, err := ioutil.ReadAll(c.Request.Body)
		if err != nil {
			logrus.WithError(err)
			c.JSON(http.StatusInternalServerError, err.Error())
			return
		}
		var task models.Task
		if err = json.Unmarshal(body, &task); err != nil {
			logrus.WithError(err)
			c.JSON(http.StatusInternalServerError, err.Error())
			return
		}

		if err := mq.Delete(ctx, &task); err != nil {
			logrus.WithError(err)
			c.JSON(http.StatusInternalServerError, err.Error())
			return
		}
		c.JSON(http.StatusAccepted, task)
	}

	r := gin.Default()
	r.GET("/tasks", getHandler)
	r.DELETE("/tasks", delHandler)
	return httptest.NewServer(r)
}

func TestGetTask(t *testing.T) {
	mockTask := getMockTask()

	ts := getTestServer([]*models.Task{&mockTask})
	defer ts.Close()

	url := ts.URL + "/tasks"
	task, err := getTask(url)
	if err != nil {
		t.Error("expected no error, got", err)
	}
	if task.ID != mockTask.ID {
		t.Errorf("expected task ID '%s', got '%s'", task.ID, mockTask.ID)
	}
}

func TestGetTaskError(t *testing.T) {
	tests := []map[string]interface{}{
		map[string]interface{}{
			"url":   "/invalid",
			"task":  getMockTask(),
			"error": "invalid character 'p' after top-level value",
		},
	}

	var tasks []*models.Task
	for _, v := range tests {
		task := v["task"].(models.Task)
		tasks = append(tasks, &task)
	}

	ts := getTestServer(tasks)
	defer ts.Close()

	for i, test := range tests {
		url := ts.URL + test["url"].(string)
		_, err := getTask(url)
		if err == nil {
			t.Errorf("expected error '%s'", test["error"].(string))
		}
		if err.Error() != test["error"].(string) {
			t.Errorf("test %d: expected error '%s', got '%s'", i, test["error"].(string), err)
		}
	}
}

func TestDeleteTask(t *testing.T) {
	mockTask := getMockTask()

	ts := getTestServer([]*models.Task{&mockTask})
	defer ts.Close()

	url := ts.URL + "/tasks"
	err := deleteTask(url, &mockTask)
	if err == nil {
		t.Error("expected error 'Not reserver', got", err)
	}

	_, err = getTask(url)
	if err != nil {
		t.Error("expected no error, got", err)
	}

	err = deleteTask(url, &mockTask)
	if err != nil {
		t.Error("expected no error, got", err)
	}
}
<|endoftext|>


<commit_before>package codec

import (
	"fmt"
	"github.com/Aptomi/aptomi/pkg/runtime"
	"github.com/Aptomi/aptomi/pkg/runtime/codec/yaml"
	"io/ioutil"
	"net/http"
)

const (
	// Default is the default content type
	Default = YAML

	// YAML is the yaml codec content type
	YAML = "application/yaml"

	// JSON is the json codec content type
	JSON = "application/json"
)

// ContentTypeHandler is a helper for working with Content-Type header and doing read/write for http requests/response
type ContentTypeHandler struct {
	codecs map[string]runtime.Codec
}

// NewContentTypeHandler returns instance of ContentTypeHandler for provided runtime registry
func NewContentTypeHandler(reg *runtime.Registry) *ContentTypeHandler {
	codecs := make(map[string]runtime.Codec)
	codecs[YAML] = yaml.NewCodec(reg)
	codecs[JSON] = yaml.NewJSONCodec(reg)

	return &ContentTypeHandler{codecs}
}

// GetCodecByContentType returns runtime codec for provided content type that should be used
func (handler *ContentTypeHandler) GetCodecByContentType(contentType string) runtime.Codec {
	codec, exist := handler.codecs[contentType]
	if codec == nil || !exist {
		panic(fmt.Sprintf("Codec not found for content type: %s", contentType))
	}

	return codec
}

// GetCodec returns runtime codec for specified http headers based on the content type
func (handler *ContentTypeHandler) GetCodec(header http.Header) runtime.Codec {
	contentType := header.Get("Content-Type")
	if len(contentType) == 0 {
		contentType = Default
	}

	return handler.GetCodecByContentType(contentType)
}

// GetContentType returns content type for provided http headers
func (handler *ContentTypeHandler) GetContentType(header http.Header) string {
	contentType := header.Get("Content-Type")
	if len(contentType) == 0 {
		contentType = "application/yaml"
	}

	return contentType
}

// Read runtime object(s) from the provided request using correct content type (taken from the request)
func (handler *ContentTypeHandler) Read(request *http.Request) []runtime.Object {
	body, err := ioutil.ReadAll(request.Body)
	if err != nil {
		panic(fmt.Sprintf("Error while reading bytes from request Body: %s", err))
	}

	objects, err := handler.GetCodec(request.Header).DecodeOneOrMany(body)
	if err != nil {
		// todo response with some bad request status code
		panic(fmt.Sprintf("Error decoding policy update request: %s", err))
	}

	return objects
}

// WriteOne runtime object into the provided response writer using correct content type (taken from provided request)
// with default http status (200 OK)
func (handler *ContentTypeHandler) WriteOne(writer http.ResponseWriter, request *http.Request, body runtime.Object) {
	handler.WriteOneWithStatus(writer, request, body, http.StatusOK)
}

// WriteOneWithStatus runtime object into the provided response writer using correct content type (taken from provided request)
// with specified http status
func (handler *ContentTypeHandler) WriteOneWithStatus(writer http.ResponseWriter, request *http.Request, body runtime.Object, status int) {
	writer.Header().Set("Content-Type", handler.GetContentType(request.Header))
	writer.WriteHeader(status)

	if body != nil {
		data, err := handler.GetCodec(request.Header).EncodeOne(body)
		if err != nil {
			panic(fmt.Sprintf("Error while encoding body of kind %s: %s", body.GetKind(), err))
		}

		_, wErr := fmt.Fprint(writer, string(data))
		if wErr != nil {
			panic(fmt.Sprintf("Error while writing body: %s", wErr))
		}
	}
}

// WriteMany runtime objects into the provided response writer using correct content type (taken from provided request)
// with default http status (200 OK)
func (handler *ContentTypeHandler) WriteMany(writer http.ResponseWriter, request *http.Request, body []runtime.Object) {
	handler.WriteManyWithStatus(writer, request, body, http.StatusOK)
}

// WriteManyWithStatus runtime objects into the provided response writer using correct content type (taken from provided request)
// with specified http status
func (handler *ContentTypeHandler) WriteManyWithStatus(writer http.ResponseWriter, request *http.Request, body []runtime.Object, status int) {
	writer.Header().Set("Content-Type", handler.GetContentType(request.Header))
	writer.WriteHeader(status)

	if body != nil {
		data, err := handler.GetCodec(request.Header).EncodeMany(body)
		if err != nil {
			if len(body) > 0 {
				panic(fmt.Sprintf("Error while encoding body of kind %s: %s", body[0].GetKind(), err))
			} else {
				panic(fmt.Sprintf("Error while encoding empty list: %s", err))
			}
		}

		_, wErr := fmt.Fprint(writer, string(data))
		if wErr != nil {
			panic(fmt.Sprintf("Error while writing body: %s", wErr))
		}
	}
}
<commit_msg>Improve default codec processing<commit_after>package codec

import (
	"fmt"
	"github.com/Aptomi/aptomi/pkg/runtime"
	"github.com/Aptomi/aptomi/pkg/runtime/codec/yaml"
	"io/ioutil"
	"net/http"
)

const (
	// Default is the default content type
	Default = YAML

	// YAML is the yaml codec content type
	YAML = "application/yaml"

	// JSON is the json codec content type
	JSON = "application/json"
)

// ContentTypeHandler is a helper for working with Content-Type header and doing read/write for http requests/response
type ContentTypeHandler struct {
	codecs map[string]runtime.Codec
}

// NewContentTypeHandler returns instance of ContentTypeHandler for provided runtime registry
func NewContentTypeHandler(reg *runtime.Registry) *ContentTypeHandler {
	codecs := make(map[string]runtime.Codec)
	codecs[YAML] = yaml.NewCodec(reg)
	codecs[JSON] = yaml.NewJSONCodec(reg)

	return &ContentTypeHandler{codecs}
}

// GetCodecByContentType returns runtime codec for provided content type that should be used
func (handler *ContentTypeHandler) GetCodecByContentType(contentType string) runtime.Codec {
	codec, exist := handler.codecs[contentType]
	if codec == nil || !exist {
		return handler.codecs[Default]
	}

	return codec
}

// GetCodec returns runtime codec for specified http headers based on the content type
func (handler *ContentTypeHandler) GetCodec(header http.Header) runtime.Codec {
	contentType := header.Get("Content-Type")
	if len(contentType) == 0 {
		contentType = Default
	}

	return handler.GetCodecByContentType(contentType)
}

// GetContentType returns content type for provided http headers
func (handler *ContentTypeHandler) GetContentType(header http.Header) string {
	contentType := header.Get("Content-Type")
	if len(contentType) == 0 {
		contentType = Default
	}
	if _, exist := handler.codecs[contentType]; !exist {
		contentType = Default
	}

	return contentType
}

// Read runtime object(s) from the provided request using correct content type (taken from the request)
func (handler *ContentTypeHandler) Read(request *http.Request) []runtime.Object {
	body, err := ioutil.ReadAll(request.Body)
	if err != nil {
		panic(fmt.Sprintf("Error while reading bytes from request Body: %s", err))
	}

	objects, err := handler.GetCodec(request.Header).DecodeOneOrMany(body)
	if err != nil {
		// todo response with some bad request status code
		panic(fmt.Sprintf("Error decoding policy update request: %s", err))
	}

	return objects
}

// WriteOne runtime object into the provided response writer using correct content type (taken from provided request)
// with default http status (200 OK)
func (handler *ContentTypeHandler) WriteOne(writer http.ResponseWriter, request *http.Request, body runtime.Object) {
	handler.WriteOneWithStatus(writer, request, body, http.StatusOK)
}

// WriteOneWithStatus runtime object into the provided response writer using correct content type (taken from provided request)
// with specified http status
func (handler *ContentTypeHandler) WriteOneWithStatus(writer http.ResponseWriter, request *http.Request, body runtime.Object, status int) {
	writer.Header().Set("Content-Type", handler.GetContentType(request.Header))
	writer.WriteHeader(status)

	if body != nil {
		data, err := handler.GetCodec(request.Header).EncodeOne(body)
		if err != nil {
			panic(fmt.Sprintf("Error while encoding body of kind %s: %s", body.GetKind(), err))
		}

		_, wErr := fmt.Fprint(writer, string(data))
		if wErr != nil {
			panic(fmt.Sprintf("Error while writing body: %s", wErr))
		}
	}
}

// WriteMany runtime objects into the provided response writer using correct content type (taken from provided request)
// with default http status (200 OK)
func (handler *ContentTypeHandler) WriteMany(writer http.ResponseWriter, request *http.Request, body []runtime.Object) {
	handler.WriteManyWithStatus(writer, request, body, http.StatusOK)
}

// WriteManyWithStatus runtime objects into the provided response writer using correct content type (taken from provided request)
// with specified http status
func (handler *ContentTypeHandler) WriteManyWithStatus(writer http.ResponseWriter, request *http.Request, body []runtime.Object, status int) {
	writer.Header().Set("Content-Type", handler.GetContentType(request.Header))
	writer.WriteHeader(status)

	if body != nil {
		data, err := handler.GetCodec(request.Header).EncodeMany(body)
		if err != nil {
			if len(body) > 0 {
				panic(fmt.Sprintf("Error while encoding body of kind %s: %s", body[0].GetKind(), err))
			} else {
				panic(fmt.Sprintf("Error while encoding empty list: %s", err))
			}
		}

		_, wErr := fmt.Fprint(writer, string(data))
		if wErr != nil {
			panic(fmt.Sprintf("Error while writing body: %s", wErr))
		}
	}
}
<|endoftext|>


<commit_before>package cli

import (
	"testing"

	"github.com/containers/common/pkg/completion"
	"github.com/spf13/pflag"
)

func testFlagCompletion(t *testing.T, flags pflag.FlagSet, flagCompletions completion.FlagCompletions) {
	// lookup if for each flag a flag completion function exists
	flags.VisitAll(func(f *pflag.Flag) {
		// skip hidden, deprecated and boolean flags
		if f.Hidden || len(f.Deprecated) > 0 || f.Value.Type() == "bool" {
			return
		}
		if _, ok := flagCompletions[f.Name]; !ok {
			t.Errorf("Flag %q has no shell completion function set.", f.Name)
		}
	})

	// make sure no unnecessary flag completion functions are defined
	for name := range flagCompletions {
		if flag := flags.Lookup(name); flag == nil {
			t.Errorf("Flag %q does not exist but has a shell completion function set.", name)
		}
	}
}

func TestUserNsFlagsCompletion(t *testing.T) {
	flags := GetUserNSFlags(&UserNSResults{})
	flagCompletions := GetUserNSFlagsCompletions()
	testFlagCompletion(t, flags, flagCompletions)
}

func TestNameSpaceFlagsCompletion(t *testing.T) {
	flags := GetNameSpaceFlags(&NameSpaceResults{})
	flagCompletions := GetNameSpaceFlagsCompletions()
	testFlagCompletion(t, flags, flagCompletions)
}

func TestBudFlagsCompletion(t *testing.T) {
	flags := GetBudFlags(&BudResults{})
	flagCompletions := GetBudFlagsCompletions()
	testFlagCompletion(t, flags, flagCompletions)
}

func TestFromAndBudFlagsCompletions(t *testing.T) {
	flags, err := GetFromAndBudFlags(&FromAndBudResults{}, &UserNSResults{}, &NameSpaceResults{})
	if err != nil {
		t.Error("Could load the from and build flags.")
	}
	flagCompletions := GetFromAndBudFlagsCompletions()
	testFlagCompletion(t, flags, flagCompletions)
}
<commit_msg>pkg/cli: improve completion test<commit_after>package cli

import (
	"testing"

	"github.com/containers/common/pkg/completion"
	"github.com/spf13/pflag"
)

func testFlagCompletion(t *testing.T, flags pflag.FlagSet, flagCompletions completion.FlagCompletions) {
	// lookup if for each flag a flag completion function exists
	flags.VisitAll(func(f *pflag.Flag) {
		// skip hidden and deprecated flags
		if f.Hidden || len(f.Deprecated) > 0 {
			return
		}
		if _, ok := flagCompletions[f.Name]; !ok && f.Value.Type() != "bool" {
			t.Errorf("Flag %q has no shell completion function set.", f.Name)
		} else if ok && f.Value.Type() == "bool" {
			// make sure bool flags don't have a completion function
			t.Errorf(`Flag %q is a bool flag but has a shell completion function set.
	You have to remove this shell completion function.`, f.Name)
			return

		}
	})

	// make sure no unnecessary flag completion functions are defined
	for name := range flagCompletions {
		if flag := flags.Lookup(name); flag == nil {
			t.Errorf("Flag %q does not exist but has a shell completion function set.", name)
		}
	}
}

func TestUserNsFlagsCompletion(t *testing.T) {
	flags := GetUserNSFlags(&UserNSResults{})
	flagCompletions := GetUserNSFlagsCompletions()
	testFlagCompletion(t, flags, flagCompletions)
}

func TestNameSpaceFlagsCompletion(t *testing.T) {
	flags := GetNameSpaceFlags(&NameSpaceResults{})
	flagCompletions := GetNameSpaceFlagsCompletions()
	testFlagCompletion(t, flags, flagCompletions)
}

func TestBudFlagsCompletion(t *testing.T) {
	flags := GetBudFlags(&BudResults{})
	flagCompletions := GetBudFlagsCompletions()
	testFlagCompletion(t, flags, flagCompletions)
}

func TestFromAndBudFlagsCompletions(t *testing.T) {
	flags, err := GetFromAndBudFlags(&FromAndBudResults{}, &UserNSResults{}, &NameSpaceResults{})
	if err != nil {
		t.Error("Could load the from and build flags.")
	}
	flagCompletions := GetFromAndBudFlagsCompletions()
	testFlagCompletion(t, flags, flagCompletions)
}
<|endoftext|>