<commit_before>package mesh

import (
	"fmt"
	"sync"
	"testing"

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

// TODO test gossip unicast; atm we only test topology gossip and
// surrogates, neither of which employ unicast.

type mockGossipConnection struct {
	RemoteConnection
	router *Router
	dest   *Router
	start  chan struct{}
}

func NewTestRouter(name string) *Router {
	peerName, _ := PeerNameFromString(name)
	router := NewRouter(Config{}, peerName, "nick", nil)
	router.Start()
	return router
}

func (conn *mockGossipConnection) SendProtocolMsg(protocolMsg ProtocolMsg) {
	<-conn.start
	if err := conn.dest.handleGossip(protocolMsg.tag, protocolMsg.msg); err != nil {
		panic(err)
	}
}

func (conn *mockGossipConnection) Connect() {
	conn.router.Ourself.handleAddConnection(conn)
	conn.router.Ourself.handleConnectionEstablished(conn)
}

func (conn *mockGossipConnection) Start() {
	close(conn.start)
}

func sendPendingGossip(routers ...*Router) {
	// Loop until all routers report they didn't send anything
	for sentSomething := true; sentSomething; {
		sentSomething = false
		for _, router := range routers {
			sentSomething = router.sendPendingGossip() || sentSomething
		}
	}
}

func AddTestGossipConnection(r1, r2 *Router) {
	c1 := r1.NewTestGossipConnection(r2)
	c2 := r2.NewTestGossipConnection(r1)
	c1.Connect()
	c2.Start()
	c2.Connect()
	c1.Start()
}

func (router *Router) NewTestGossipConnection(r *Router) *mockGossipConnection {
	fromPeer := NewPeerFrom(router.Ourself.Peer)
	toPeer := NewPeerFrom(r.Ourself.Peer)

	r.Peers.FetchWithDefault(fromPeer)             // Has side-effect of incrementing refcount
	toPeer = router.Peers.FetchWithDefault(toPeer) //

	return &mockGossipConnection{
		RemoteConnection{router.Ourself.Peer, toPeer, "", false, true}, router, r, make(chan struct{})}
}

func (router *Router) DeleteTestGossipConnection(r *Router) {
	fromName := router.Ourself.Peer.Name
	toName := r.Ourself.Peer.Name

	fromPeer := r.Peers.Fetch(fromName)
	toPeer := router.Peers.Fetch(toName)

	r.Peers.Dereference(fromPeer)
	router.Peers.Dereference(toPeer)

	conn, _ := router.Ourself.ConnectionTo(toName)
	router.Ourself.handleDeleteConnection(conn)
}

// Create a Peer representing the receiver router, with connections to
// the routers supplied as arguments, carrying across all UID and
// version information.
func (router *Router) tp(routers ...*Router) *Peer {
	peer := NewPeerFrom(router.Ourself.Peer)
	connections := make(map[PeerName]Connection)
	for _, r := range routers {
		p := NewPeerFrom(r.Ourself.Peer)
		connections[r.Ourself.Peer.Name] = newMockConnection(peer, p)
	}
	peer.Version = router.Ourself.Peer.Version
	peer.connections = connections
	return peer
}

// Check that the topology of router matches the peers and all of their connections
func checkTopology(t *testing.T, router *Router, wantedPeers ...*Peer) {
	router.Peers.RLock()
	checkTopologyPeers(t, true, router.Peers.allPeers(), wantedPeers...)
	router.Peers.RUnlock()
}

func flushAndCheckTopology(t *testing.T, routers []*Router, wantedPeers ...*Peer) {
	sendPendingGossip(routers...)
	for _, r := range routers {
		checkTopology(t, r, wantedPeers...)
	}
}

func TestGossipTopology(t *testing.T) {
	// Create some peers that will talk to each other
	r1 := NewTestRouter("01:00:00:01:00:00")
	r2 := NewTestRouter("02:00:00:02:00:00")
	r3 := NewTestRouter("03:00:00:03:00:00")
	routers := []*Router{r1, r2, r3}
	// Check state when they have no connections
	checkTopology(t, r1, r1.tp())
	checkTopology(t, r2, r2.tp())

	// Now try adding some connections
	AddTestGossipConnection(r1, r2)
	sendPendingGossip(r1, r2)
	checkTopology(t, r1, r1.tp(r2), r2.tp(r1))
	checkTopology(t, r2, r1.tp(r2), r2.tp(r1))

	AddTestGossipConnection(r2, r3)
	flushAndCheckTopology(t, routers, r1.tp(r2), r2.tp(r1, r3), r3.tp(r2))

	AddTestGossipConnection(r3, r1)
	flushAndCheckTopology(t, routers, r1.tp(r2, r3), r2.tp(r1, r3), r3.tp(r1, r2))

	// Drop the connection from 2 to 3
	r2.DeleteTestGossipConnection(r3)
	flushAndCheckTopology(t, routers, r1.tp(r2, r3), r2.tp(r1), r3.tp(r1, r2))

	// Drop the connection from 1 to 3
	r1.DeleteTestGossipConnection(r3)
	sendPendingGossip(r1, r2, r3)
	checkTopology(t, r1, r1.tp(r2), r2.tp(r1), r3.tp(r1, r2))
	checkTopology(t, r2, r1.tp(r2), r2.tp(r1), r3.tp(r1, r2))
	// r3 still thinks r1 has a connection to it
	checkTopology(t, r3, r1.tp(r2, r3), r2.tp(r1), r3.tp(r1, r2))

	// On a timer, r3 will gossip to r1
	r3.SendAllGossip()
	sendPendingGossip(r1, r2, r3)
	checkTopology(t, r1, r1.tp(r2), r2.tp(r1), r3.tp(r1, r2))
}

func TestGossipSurrogate(t *testing.T) {
	// create the topology r1 <-> r2 <-> r3
	r1 := NewTestRouter("01:00:00:01:00:00")
	r2 := NewTestRouter("02:00:00:02:00:00")
	r3 := NewTestRouter("03:00:00:03:00:00")
	routers := []*Router{r1, r2, r3}
	AddTestGossipConnection(r1, r2)
	AddTestGossipConnection(r3, r2)
	flushAndCheckTopology(t, routers, r1.tp(r2), r2.tp(r1, r3), r3.tp(r2))

	// create a gossiper at either end, but not the middle
	g1 := newTestGossiper()
	g3 := newTestGossiper()
	s1 := r1.NewGossip("Test", g1)
	s3 := r3.NewGossip("Test", g3)

	// broadcast a message from each end, check it reaches the other
	broadcast(s1, 1)
	broadcast(s3, 2)
	sendPendingGossip(r1, r2, r3)
	g1.checkHas(t, 2)
	g3.checkHas(t, 1)

	// check that each end gets their message back through periodic
	// gossip
	r1.SendAllGossip()
	r3.SendAllGossip()
	sendPendingGossip(r1, r2, r3)
	g1.checkHas(t, 1, 2)
	g3.checkHas(t, 1, 2)
}

type testGossiper struct {
	sync.RWMutex
	state map[byte]struct{}
}

func newTestGossiper() *testGossiper {
	return &testGossiper{state: make(map[byte]struct{})}
}

func (g *testGossiper) OnGossipUnicast(sender PeerName, msg []byte) error {
	return nil
}

func (g *testGossiper) OnGossipBroadcast(_ PeerName, update []byte) (GossipData, error) {
	g.Lock()
	defer g.Unlock()
	for _, v := range update {
		g.state[v] = void
	}
	return NewSurrogateGossipData(update), nil
}

func (g *testGossiper) Gossip() GossipData {
	g.RLock()
	defer g.RUnlock()
	state := make([]byte, len(g.state))
	for v := range g.state {
		state = append(state, v)
	}
	return NewSurrogateGossipData(state)
}

func (g *testGossiper) OnGossip(update []byte) (GossipData, error) {
	g.Lock()
	defer g.Unlock()
	var delta []byte
	for _, v := range update {
		if _, found := g.state[v]; !found {
			delta = append(delta, v)
			g.state[v] = void
		}
	}
	if len(delta) == 0 {
		return nil, nil
	}
	return NewSurrogateGossipData(delta), nil
}

func (g *testGossiper) checkHas(t *testing.T, vs ...byte) {
	g.RLock()
	defer g.RUnlock()
	for _, v := range vs {
		if _, found := g.state[v]; !found {
			require.FailNow(t, fmt.Sprintf("%d is missing", v))
		}
	}
}

func broadcast(s Gossip, v byte) {
	s.GossipBroadcast(NewSurrogateGossipData([]byte{v}))
}
<commit_msg>fix incorrect peer initialisation on test gossip connections<commit_after>package mesh

import (
	"fmt"
	"sync"
	"testing"

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

// TODO test gossip unicast; atm we only test topology gossip and
// surrogates, neither of which employ unicast.

type mockGossipConnection struct {
	RemoteConnection
	router *Router
	dest   *Router
	start  chan struct{}
}

func NewTestRouter(name string) *Router {
	peerName, _ := PeerNameFromString(name)
	router := NewRouter(Config{}, peerName, "nick", nil)
	router.Start()
	return router
}

func (conn *mockGossipConnection) SendProtocolMsg(protocolMsg ProtocolMsg) {
	<-conn.start
	if err := conn.dest.handleGossip(protocolMsg.tag, protocolMsg.msg); err != nil {
		panic(err)
	}
}

func (conn *mockGossipConnection) Connect() {
	conn.router.Ourself.handleAddConnection(conn)
	conn.router.Ourself.handleConnectionEstablished(conn)
}

func (conn *mockGossipConnection) Start() {
	close(conn.start)
}

func sendPendingGossip(routers ...*Router) {
	// Loop until all routers report they didn't send anything
	for sentSomething := true; sentSomething; {
		sentSomething = false
		for _, router := range routers {
			sentSomething = router.sendPendingGossip() || sentSomething
		}
	}
}

func AddTestGossipConnection(r1, r2 *Router) {
	c1 := r1.NewTestGossipConnection(r2)
	c2 := r2.NewTestGossipConnection(r1)
	c1.Connect()
	c2.Start()
	c2.Connect()
	c1.Start()
}

func (router *Router) NewTestGossipConnection(r *Router) *mockGossipConnection {
	to := r.Ourself.Peer
	toPeer := NewPeer(to.Name, to.NickName, to.UID, 0, to.ShortID)
	toPeer = router.Peers.FetchWithDefault(toPeer) // Has side-effect of incrementing refcount

	return &mockGossipConnection{
		RemoteConnection{router.Ourself.Peer, toPeer, "", false, true}, router, r, make(chan struct{})}
}

func (router *Router) DeleteTestGossipConnection(r *Router) {
	fromName := router.Ourself.Peer.Name
	toName := r.Ourself.Peer.Name

	fromPeer := r.Peers.Fetch(fromName)
	toPeer := router.Peers.Fetch(toName)

	r.Peers.Dereference(fromPeer)
	router.Peers.Dereference(toPeer)

	conn, _ := router.Ourself.ConnectionTo(toName)
	router.Ourself.handleDeleteConnection(conn)
}

// Create a Peer representing the receiver router, with connections to
// the routers supplied as arguments, carrying across all UID and
// version information.
func (router *Router) tp(routers ...*Router) *Peer {
	peer := NewPeerFrom(router.Ourself.Peer)
	connections := make(map[PeerName]Connection)
	for _, r := range routers {
		p := NewPeerFrom(r.Ourself.Peer)
		connections[r.Ourself.Peer.Name] = newMockConnection(peer, p)
	}
	peer.Version = router.Ourself.Peer.Version
	peer.connections = connections
	return peer
}

// Check that the topology of router matches the peers and all of their connections
func checkTopology(t *testing.T, router *Router, wantedPeers ...*Peer) {
	router.Peers.RLock()
	checkTopologyPeers(t, true, router.Peers.allPeers(), wantedPeers...)
	router.Peers.RUnlock()
}

func flushAndCheckTopology(t *testing.T, routers []*Router, wantedPeers ...*Peer) {
	sendPendingGossip(routers...)
	for _, r := range routers {
		checkTopology(t, r, wantedPeers...)
	}
}

func TestGossipTopology(t *testing.T) {
	// Create some peers that will talk to each other
	r1 := NewTestRouter("01:00:00:01:00:00")
	r2 := NewTestRouter("02:00:00:02:00:00")
	r3 := NewTestRouter("03:00:00:03:00:00")
	routers := []*Router{r1, r2, r3}
	// Check state when they have no connections
	checkTopology(t, r1, r1.tp())
	checkTopology(t, r2, r2.tp())

	// Now try adding some connections
	AddTestGossipConnection(r1, r2)
	sendPendingGossip(r1, r2)
	checkTopology(t, r1, r1.tp(r2), r2.tp(r1))
	checkTopology(t, r2, r1.tp(r2), r2.tp(r1))

	AddTestGossipConnection(r2, r3)
	flushAndCheckTopology(t, routers, r1.tp(r2), r2.tp(r1, r3), r3.tp(r2))

	AddTestGossipConnection(r3, r1)
	flushAndCheckTopology(t, routers, r1.tp(r2, r3), r2.tp(r1, r3), r3.tp(r1, r2))

	// Drop the connection from 2 to 3
	r2.DeleteTestGossipConnection(r3)
	flushAndCheckTopology(t, routers, r1.tp(r2, r3), r2.tp(r1), r3.tp(r1, r2))

	// Drop the connection from 1 to 3
	r1.DeleteTestGossipConnection(r3)
	sendPendingGossip(r1, r2, r3)
	checkTopology(t, r1, r1.tp(r2), r2.tp(r1), r3.tp(r1, r2))
	checkTopology(t, r2, r1.tp(r2), r2.tp(r1), r3.tp(r1, r2))
	// r3 still thinks r1 has a connection to it
	checkTopology(t, r3, r1.tp(r2, r3), r2.tp(r1), r3.tp(r1, r2))

	// On a timer, r3 will gossip to r1
	r3.SendAllGossip()
	sendPendingGossip(r1, r2, r3)
	checkTopology(t, r1, r1.tp(r2), r2.tp(r1), r3.tp(r1, r2))
}

func TestGossipSurrogate(t *testing.T) {
	// create the topology r1 <-> r2 <-> r3
	r1 := NewTestRouter("01:00:00:01:00:00")
	r2 := NewTestRouter("02:00:00:02:00:00")
	r3 := NewTestRouter("03:00:00:03:00:00")
	routers := []*Router{r1, r2, r3}
	AddTestGossipConnection(r1, r2)
	AddTestGossipConnection(r3, r2)
	flushAndCheckTopology(t, routers, r1.tp(r2), r2.tp(r1, r3), r3.tp(r2))

	// create a gossiper at either end, but not the middle
	g1 := newTestGossiper()
	g3 := newTestGossiper()
	s1 := r1.NewGossip("Test", g1)
	s3 := r3.NewGossip("Test", g3)

	// broadcast a message from each end, check it reaches the other
	broadcast(s1, 1)
	broadcast(s3, 2)
	sendPendingGossip(r1, r2, r3)
	g1.checkHas(t, 2)
	g3.checkHas(t, 1)

	// check that each end gets their message back through periodic
	// gossip
	r1.SendAllGossip()
	r3.SendAllGossip()
	sendPendingGossip(r1, r2, r3)
	g1.checkHas(t, 1, 2)
	g3.checkHas(t, 1, 2)
}

type testGossiper struct {
	sync.RWMutex
	state map[byte]struct{}
}

func newTestGossiper() *testGossiper {
	return &testGossiper{state: make(map[byte]struct{})}
}

func (g *testGossiper) OnGossipUnicast(sender PeerName, msg []byte) error {
	return nil
}

func (g *testGossiper) OnGossipBroadcast(_ PeerName, update []byte) (GossipData, error) {
	g.Lock()
	defer g.Unlock()
	for _, v := range update {
		g.state[v] = void
	}
	return NewSurrogateGossipData(update), nil
}

func (g *testGossiper) Gossip() GossipData {
	g.RLock()
	defer g.RUnlock()
	state := make([]byte, len(g.state))
	for v := range g.state {
		state = append(state, v)
	}
	return NewSurrogateGossipData(state)
}

func (g *testGossiper) OnGossip(update []byte) (GossipData, error) {
	g.Lock()
	defer g.Unlock()
	var delta []byte
	for _, v := range update {
		if _, found := g.state[v]; !found {
			delta = append(delta, v)
			g.state[v] = void
		}
	}
	if len(delta) == 0 {
		return nil, nil
	}
	return NewSurrogateGossipData(delta), nil
}

func (g *testGossiper) checkHas(t *testing.T, vs ...byte) {
	g.RLock()
	defer g.RUnlock()
	for _, v := range vs {
		if _, found := g.state[v]; !found {
			require.FailNow(t, fmt.Sprintf("%d is missing", v))
		}
	}
}

func broadcast(s Gossip, v byte) {
	s.GossipBroadcast(NewSurrogateGossipData([]byte{v}))
}
<|endoftext|>


<commit_before>package middleware

import (
	"github.com/gin-gonic/gin"
	"strings"

	u "github.com/techjanitor/pram-get/utils"
)

// Cache will check for the key in Redis and serve it. If not found, it will
// take the marshalled JSON from the controller and set it in Redis
func Cache() gin.HandlerFunc {
	return func(c *gin.Context) {
		var result []byte
		var err error

		// Get request path
		path := c.Request.URL.Path

		// Trim leading / from path and split
		params := strings.Split(strings.Trim(path, "/"), "/")

		// Make key from path
		key := redisKey{}
		key.expireKey(params[0])
		key.generateKey(params...)

		// Initialize cache handle
		cache := u.RedisCache

		if key.Hash {
			// Check to see if there is already a key we can serve
			result, err = cache.HGet(key.Key, key.Field)
			if err == u.ErrCacheMiss {
				c.Next()

				// Check if there was an error from the controller
				controllerError, _ := c.Get("controllerError")
				if controllerError != nil {
					c.Abort()
					return
				}

				// Get data from controller
				data := c.MustGet("data").([]byte)

				// Set output to cache
				err = cache.HMSet(key.Key, key.Field, data)
				if err != nil {
					c.Error(err)
					c.Abort()
					return
				}

			}
			if err != nil {
				c.Error(err)
				c.Abort()
				return
			}

		}

		if !key.Hash {
			// Check to see if there is already a key we can serve
			result, err = cache.Get(key.Key)
			if err == u.ErrCacheMiss {
				c.Next()

				// Check if there was an error from the controller
				controllerError, _ := c.Get("controllerError")
				if controllerError != nil {
					c.Abort()
					return
				}

				// Get data from controller
				data := c.MustGet("data").([]byte)

				if key.Expire {

					// Set output to cache
					err = cache.SetEx(key.Key, 60, data)
					if err != nil {
						c.Error(err)
						c.Abort()
						return
					}

				} else {

					// Set output to cache
					err = cache.Set(key.Key, data)
					if err != nil {
						c.Error(err)
						c.Abort()
						return
					}

				}

			}
			if err != nil {
				c.Error(err)
				c.Abort()
				return
			}

		}

		c.Writer.Header().Set("Content-Type", "application/json")
		c.Writer.Write(result)
		c.Abort()

	}

}

type redisKey struct {
	Key    string
	Field  string
	Hash   bool
	Expire bool
}

// Will take the params from the request and turn them into a key
func (r *redisKey) generateKey(params ...string) {
	var keys []string

	switch {
	case params[0] == "image":
		keys = append(keys, params[0], params[2])
		r.Key = strings.Join(keys, ":")
	case len(params) == 2:
		r.Key = strings.Join(params, ":")
	case len(params) == 3:
		keys = append(keys, params[0], params[1])
		r.Field = params[2]
		r.Hash = true
		r.Key = strings.Join(keys, ":")
	case len(params) == 4:
		keys = append(keys, params[0], params[2])
		r.Field = params[3]
		r.Hash = true
		r.Key = strings.Join(keys, ":")
	}

	return

}

// Check if key should be expired
func (r *redisKey) expireKey(key string) {

	keyList := map[string]bool{
		"image": true,
		"pram":  true,
		"tag":   true,
	}

	if keyList[strings.ToLower(key)] {
		r.Expire = true
	}

	return

}
<commit_msg>simplify key logic<commit_after>package middleware

import (
	"github.com/gin-gonic/gin"
	"strings"

	u "github.com/techjanitor/pram-get/utils"
)

// Cache will check for the key in Redis and serve it. If not found, it will
// take the marshalled JSON from the controller and set it in Redis
func Cache() gin.HandlerFunc {
	return func(c *gin.Context) {
		var result []byte
		var err error

		// Get request path
		path := c.Request.URL.Path

		// Trim leading / from path and split
		params := strings.Split(strings.Trim(path, "/"), "/")

		// Make key from path
		key := redisKey{}
		key.expireKey(params[0])
		key.generateKey(params...)

		// Initialize cache handle
		cache := u.RedisCache

		if key.Hash {
			// Check to see if there is already a key we can serve
			result, err = cache.HGet(key.Key, key.Field)
			if err == u.ErrCacheMiss {
				c.Next()

				// Check if there was an error from the controller
				controllerError, _ := c.Get("controllerError")
				if controllerError != nil {
					c.Abort()
					return
				}

				// Get data from controller
				data := c.MustGet("data").([]byte)

				// Set output to cache
				err = cache.HMSet(key.Key, key.Field, data)
				if err != nil {
					c.Error(err)
					c.Abort()
					return
				}

			}
			if err != nil {
				c.Error(err)
				c.Abort()
				return
			}

		}

		if !key.Hash {
			// Check to see if there is already a key we can serve
			result, err = cache.Get(key.Key)
			if err == u.ErrCacheMiss {
				c.Next()

				// Check if there was an error from the controller
				controllerError, _ := c.Get("controllerError")
				if controllerError != nil {
					c.Abort()
					return
				}

				// Get data from controller
				data := c.MustGet("data").([]byte)

				if key.Expire {

					// Set output to cache
					err = cache.SetEx(key.Key, 60, data)
					if err != nil {
						c.Error(err)
						c.Abort()
						return
					}

				} else {

					// Set output to cache
					err = cache.Set(key.Key, data)
					if err != nil {
						c.Error(err)
						c.Abort()
						return
					}

				}

			}
			if err != nil {
				c.Error(err)
				c.Abort()
				return
			}

		}

		c.Writer.Header().Set("Content-Type", "application/json")
		c.Writer.Write(result)
		c.Abort()

	}

}

type redisKey struct {
	Key    string
	Field  string
	Hash   bool
	Expire bool
}

// Will take the params from the request and turn them into a key
func (r *redisKey) generateKey(params ...string) {

	var keys []string

	switch {
	// keys like directory and tags
	case len(params) == 2:
		r.Key = strings.Join(params, ":")
	// index and image
	case len(params) == 3:
		keys = append(keys, params[0], params[1])
		r.Field = params[2]
		r.Hash = true
		r.Key = strings.Join(keys, ":")
	// post, thread, and tag
	case len(params) == 4:
		keys = append(keys, params[0], params[1], params[2])
		r.Field = params[3]
		r.Hash = true
		r.Key = strings.Join(keys, ":")
	}

	return

}

// Check if key should be expired
func (r *redisKey) expireKey(key string) {

	keyList := map[string]bool{
		"image": true,
		"pram":  true,
		"tag":   true,
	}

	if keyList[strings.ToLower(key)] {
		r.Expire = true
	}

	return

}
<|endoftext|>


<commit_before>/*
Copyright 2017 Gravitational, Inc.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package influxdb

import (
	"bytes"
	"fmt"
	"html/template"
	"strconv"
	"strings"

	"github.com/gravitational/monitoring-app/watcher/lib/constants"
	"github.com/gravitational/monitoring-app/watcher/lib/utils"

	"github.com/gravitational/trace"
)

// Rollup is the rollup configuration
type Rollup struct {
	// Retention is the retention policy for this rollup
	Retention string `json:"retention"`
	// Measurement is the name of the measurement to run rollup on
	Measurement string `json:"measurement"`
	// Name is both the name of the rollup query and the name of the
	// new measurement rollup data will be inserted into
	Name string `json:"name"`
	// Functions is a list of functions for rollup calculation
	Functions []Function `json:"functions"`
}

// Check verifies that rollup configuration is correct
func (r Rollup) Check() error {
	if !utils.OneOf(r.Retention, constants.AllRetentions) {
		return trace.BadParameter(
			"invalid Retention, must be one of: %v", constants.AllRetentions)
	}
	if r.Measurement == "" {
		return trace.BadParameter("parameter Measurement is missing")
	}
	if r.Name == "" {
		return trace.BadParameter("parameter Name is missing")
	}
	if len(r.Functions) == 0 {
		return trace.BadParameter("parameter Functions is empty")
	}
	for _, rollup := range r.Functions {
		err := rollup.Check()
		if err != nil {
			return trace.Wrap(err)
		}
	}
	return nil
}

// Function defines a single rollup function
type Function struct {
	// Function is the function name (mean, max, etc.)
	Function string `json:"function"`
	// Field is the name of the field to apply the function to
	Field string `json:"field"`
	// Alias is the optional alias for the new field in the rollup table
	Alias string `json:"alias,omitempty"`
}

// Check verifies the function configuration is correct
func (f Function) Check() error {
	if !utils.OneOf(f.Function, constants.AllFunctions) &&
		!strings.HasPrefix(f.Function, constants.FunctionPercentile) {
		return trace.BadParameter(
			"invalid Function, must be one of: %v, or start with %q",
			constants.AllFunctions, constants.FunctionPercentile)
	}
	if f.Field == "" {
		return trace.BadParameter("parameter Field is missing")
	}
	return nil
}

// buildQuery returns a string with InfluxDB query based on the rollup configuration
func buildQuery(r Rollup) (string, error) {
	var functions []string
	for _, fn := range r.Functions {
		function, err := buildFunction(fn)
		if err != nil {
			return "", trace.Wrap(err)
		}
		functions = append(functions, function)
	}

	var b bytes.Buffer
	err := queryTemplate.Execute(&b, map[string]string{
		"name":             r.Name,
		"database":         constants.InfluxDBDatabase,
		"functions":        strings.Join(functions, ", "),
		"retention_into":   r.Retention,
		"measurement_into": r.Name,
		"retention_from":   constants.InfluxDBRetentionPolicy,
		"measurement_from": r.Measurement,
		"interval":         constants.RetentionToInterval[r.Retention],
	})
	if err != nil {
		return "", trace.Wrap(err)
	}

	return b.String(), nil
}

// define which functions needs an additional parameter
var funcsWithParams = []string{
	constants.FunctionPercentile,
	constants.FunctionBottom,
	constants.FunctionTop,
	constants.FunctionSample,
}

// buildFunction returns a function string based on the provided function configuration
func buildFunction(f Function) (string, error) {
	alias := f.Alias
	if alias == "" {
		alias = f.Field
	}

	// split function name, based on the "_" separator (eg: percentile_99, top_10, ecc)
	funcAndValue := strings.Split(f.Function, "_")
	if len(funcAndValue) == 2 && isFuncWithParams(funcAndValue[0]) {
		funcName := funcAndValue[0]
		param := funcAndValue[1]
		err := validateParam(funcName, param)
		if err != nil {
			return "", trace.Wrap(err)
		}
		return fmt.Sprintf("%v(%v, %v) as %v", funcName, f.Field, param, alias), nil
	}

	return fmt.Sprintf("%v(%v) as %v", f.Function, f.Field, alias), nil
}

// validateParam checks the function parameter for validity.
func validateParam(funcName, param string) error {
	// convert parameter value as it's always going to be an Integer
	value, err := strconv.Atoi(param)
	if err != nil {
		return trace.Wrap(err)
	}

	switch funcName {
	case constants.FunctionPercentile:
		if value < 0 || value > 100 {
			return trace.BadParameter(
				"Percentile value must be between 0 and 100 (inclusive)")
		}
	case constants.FunctionTop, constants.FunctionBottom, constants.FunctionSample:
		if value < 0 {
			return trace.BadParameter(
				"Top, Bottom and Sample value must be greater or equal to 0")
		}
	}

	return nil
}

var (
	// queryTemplate is the template of the InfluxDB rollup query
	queryTemplate = template.Must(template.New("query").Parse(
		`create continuous query "{{.name}}" on {{.database}} begin select {{.functions}} into {{.database}}."{{.retention_into}}"."{{.measurement_into}}" from {{.database}}."{{.retention_from}}"."{{.measurement_from}}" group by *, time({{.interval}}) end`))
)
<commit_msg>Fixed missing function<commit_after>/*
Copyright 2017 Gravitational, Inc.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package influxdb

import (
	"bytes"
	"fmt"
	"html/template"
	"strconv"
	"strings"

	"github.com/gravitational/monitoring-app/watcher/lib/constants"
	"github.com/gravitational/monitoring-app/watcher/lib/utils"

	"github.com/gravitational/trace"
)

// Rollup is the rollup configuration
type Rollup struct {
	// Retention is the retention policy for this rollup
	Retention string `json:"retention"`
	// Measurement is the name of the measurement to run rollup on
	Measurement string `json:"measurement"`
	// Name is both the name of the rollup query and the name of the
	// new measurement rollup data will be inserted into
	Name string `json:"name"`
	// Functions is a list of functions for rollup calculation
	Functions []Function `json:"functions"`
}

// Check verifies that rollup configuration is correct
func (r Rollup) Check() error {
	if !utils.OneOf(r.Retention, constants.AllRetentions) {
		return trace.BadParameter(
			"invalid Retention, must be one of: %v", constants.AllRetentions)
	}
	if r.Measurement == "" {
		return trace.BadParameter("parameter Measurement is missing")
	}
	if r.Name == "" {
		return trace.BadParameter("parameter Name is missing")
	}
	if len(r.Functions) == 0 {
		return trace.BadParameter("parameter Functions is empty")
	}
	for _, rollup := range r.Functions {
		err := rollup.Check()
		if err != nil {
			return trace.Wrap(err)
		}
	}
	return nil
}

// Function defines a single rollup function
type Function struct {
	// Function is the function name (mean, max, etc.)
	Function string `json:"function"`
	// Field is the name of the field to apply the function to
	Field string `json:"field"`
	// Alias is the optional alias for the new field in the rollup table
	Alias string `json:"alias,omitempty"`
}

// Check verifies the function configuration is correct
func (f Function) Check() error {
	if !utils.OneOf(f.Function, constants.AllFunctions) &&
		!strings.HasPrefix(f.Function, constants.FunctionPercentile) {
		return trace.BadParameter(
			"invalid Function, must be one of: %v, or start with %q",
			constants.AllFunctions, constants.FunctionPercentile)
	}
	if f.Field == "" {
		return trace.BadParameter("parameter Field is missing")
	}
	return nil
}

// buildQuery returns a string with InfluxDB query based on the rollup configuration
func buildQuery(r Rollup) (string, error) {
	var functions []string
	for _, fn := range r.Functions {
		function, err := buildFunction(fn)
		if err != nil {
			return "", trace.Wrap(err)
		}
		functions = append(functions, function)
	}

	var b bytes.Buffer
	err := queryTemplate.Execute(&b, map[string]string{
		"name":             r.Name,
		"database":         constants.InfluxDBDatabase,
		"functions":        strings.Join(functions, ", "),
		"retention_into":   r.Retention,
		"measurement_into": r.Name,
		"retention_from":   constants.InfluxDBRetentionPolicy,
		"measurement_from": r.Measurement,
		"interval":         constants.RetentionToInterval[r.Retention],
	})
	if err != nil {
		return "", trace.Wrap(err)
	}

	return b.String(), nil
}

// define which functions needs an additional parameter
var funcsWithParams = []string{
	constants.FunctionPercentile,
	constants.FunctionBottom,
	constants.FunctionTop,
	constants.FunctionSample,
}

// check if function is one of the composable Functions listed above
func isFuncWithParams(funcName string) bool {
	for _, val := range funcsWithParams {
		if val == funcName {
			return true
		}
	}
	return false
}

// buildFunction returns a function string based on the provided function configuration
func buildFunction(f Function) (string, error) {
	alias := f.Alias
	if alias == "" {
		alias = f.Field
	}

	// split function name, based on the "_" separator (eg: percentile_99, top_10, ecc)
	funcAndValue := strings.Split(f.Function, "_")
	if len(funcAndValue) == 2 && isFuncWithParams(funcAndValue[0]) {
		funcName := funcAndValue[0]
		param := funcAndValue[1]
		err := validateParam(funcName, param)
		if err != nil {
			return "", trace.Wrap(err)
		}
		return fmt.Sprintf("%v(%v, %v) as %v", funcName, f.Field, param, alias), nil
	}

	return fmt.Sprintf("%v(%v) as %v", f.Function, f.Field, alias), nil
}

// validateParam checks the function parameter for validity.
func validateParam(funcName, param string) error {
	// convert parameter value as it's always going to be an Integer
	value, err := strconv.Atoi(param)
	if err != nil {
		return trace.Wrap(err)
	}

	switch funcName {
	case constants.FunctionPercentile:
		if value < 0 || value > 100 {
			return trace.BadParameter(
				"Percentile value must be between 0 and 100 (inclusive)")
		}
	case constants.FunctionTop, constants.FunctionBottom, constants.FunctionSample:
		if value < 0 {
			return trace.BadParameter(
				"Top, Bottom and Sample value must be greater or equal to 0")
		}
	}

	return nil
}

var (
	// queryTemplate is the template of the InfluxDB rollup query
	queryTemplate = template.Must(template.New("query").Parse(
		`create continuous query "{{.name}}" on {{.database}} begin select {{.functions}} into {{.database}}."{{.retention_into}}"."{{.measurement_into}}" from {{.database}}."{{.retention_from}}"."{{.measurement_from}}" group by *, time({{.interval}}) end`))
)
<|endoftext|>


<commit_before>// Copyright 2011 The Go Authors.  All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package main

//import "runtime"

// Not a benchmark; input for revcomp.

var fastabytes = makefasta()

func makefasta() []byte {
	var n int = 25e6

	/*
	if runtime.GOARCH == "arm" {
		// TODO(dfc) remove this limitation after precise gc.
		// A value of 25e6 consumes 465mb of heap on 32bit
		// platforms, which is too much for most ARM systems.
		// A value of 25e5 produces a memory layout that
		// confuses the gc on 32bit platforms. So 25e4 it is.
		n = 25e4
	}
	*/
	return fasta(n)
}

func fasta(n int) []byte {
	out := make(fastaBuffer, 0, 11*n)

	iub := []fastaAcid{
		{prob: 0.27, sym: 'a'},
		{prob: 0.12, sym: 'c'},
		{prob: 0.12, sym: 'g'},
		{prob: 0.27, sym: 't'},
		{prob: 0.02, sym: 'B'},
		{prob: 0.02, sym: 'D'},
		{prob: 0.02, sym: 'H'},
		{prob: 0.02, sym: 'K'},
		{prob: 0.02, sym: 'M'},
		{prob: 0.02, sym: 'N'},
		{prob: 0.02, sym: 'R'},
		{prob: 0.02, sym: 'S'},
		{prob: 0.02, sym: 'V'},
		{prob: 0.02, sym: 'W'},
		{prob: 0.02, sym: 'Y'},
	}

	homosapiens := []fastaAcid{
		{prob: 0.3029549426680, sym: 'a'},
		{prob: 0.1979883004921, sym: 'c'},
		{prob: 0.1975473066391, sym: 'g'},
		{prob: 0.3015094502008, sym: 't'},
	}

	alu := []byte(
		"GGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGG" +
			"GAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGTTCGAGA" +
			"CCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAAAAT" +
			"ACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCA" +
			"GCTACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAACCCGGG" +
			"AGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTGCACTCC" +
			"AGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAA")

	out.WriteString(">ONE Homo sapiens alu\n")
	fastaRepeat(&out, alu, 2*n)
	out.WriteString(">TWO IUB ambiguity codes\n")
	fastaRandom(&out, iub, 3*n)
	out.WriteString(">THREE Homo sapiens frequency\n")
	fastaRandom(&out, homosapiens, 5*n)
	return out
}

type fastaBuffer []byte

func (b *fastaBuffer) Flush() {
	panic("flush")
}

func (b *fastaBuffer) WriteString(s string) {
	p := b.NextWrite(len(s))
	copy(p, s)
}

func (b *fastaBuffer) NextWrite(n int) []byte {
	p := *b
	if len(p)+n > cap(p) {
		b.Flush()
		p = *b
	}
	out := p[len(p) : len(p)+n]
	*b = p[:len(p)+n]
	return out
}

const fastaLine = 60

func fastaRepeat(out *fastaBuffer, alu []byte, n int) {
	buf := append(alu, alu...)
	off := 0
	for n > 0 {
		m := n
		if m > fastaLine {
			m = fastaLine
		}
		buf1 := out.NextWrite(m + 1)
		copy(buf1, buf[off:])
		buf1[m] = '\n'
		if off += m; off >= len(alu) {
			off -= len(alu)
		}
		n -= m
	}
}

const (
	fastaLookupSize          = 4096
	fastaLookupScale float64 = fastaLookupSize - 1
)

var fastaRand uint32 = 42

type fastaAcid struct {
	sym   byte
	prob  float64
	cprob float64
	next  *fastaAcid
}

func fastaComputeLookup(acid []fastaAcid) *[fastaLookupSize]*fastaAcid {
	var lookup [fastaLookupSize]*fastaAcid
	var p float64
	for i := range acid {
		p += acid[i].prob
		acid[i].cprob = p * fastaLookupScale
		if i > 0 {
			acid[i-1].next = &acid[i]
		}
	}
	acid[len(acid)-1].cprob = 1.0 * fastaLookupScale

	j := 0
	for i := range lookup {
		for acid[j].cprob < float64(i) {
			j++
		}
		lookup[i] = &acid[j]
	}

	return &lookup
}

func fastaRandom(out *fastaBuffer, acid []fastaAcid, n int) {
	const (
		IM = 139968
		IA = 3877
		IC = 29573
	)
	lookup := fastaComputeLookup(acid)
	for n > 0 {
		m := n
		if m > fastaLine {
			m = fastaLine
		}
		buf := out.NextWrite(m + 1)
		f := fastaLookupScale / IM
		myrand := fastaRand
		for i := 0; i < m; i++ {
			myrand = (myrand*IA + IC) % IM
			r := float64(int(myrand)) * f
			a := lookup[int(r)]
			for a.cprob < r {
				a = a.next
			}
			buf[i] = a.sym
		}
		fastaRand = myrand
		buf[m] = '\n'
		n -= m
	}
}
<commit_msg>remove unused wip directory<commit_after><|endoftext|>


<commit_before>package workloads

import (
	"fmt"
	"sync"
	"time"

	"github.com/patrick-higgins/summstat"

	"github.com/pavel-paulau/blurr/databases"
)

type State struct {
	Operations, Records int64
	Errors              map[string]int
	Events              map[string]time.Time
	Latency             map[string]*summstat.Stats
}

func (state *State) Init() {
	state.Errors = map[string]int{}
	state.Events = map[string]time.Time{}
	state.Latency = map[string]*summstat.Stats{}
	state.Latency["Create"] = summstat.NewStats()
	state.Latency["Read"] = summstat.NewStats()
	state.Latency["Update"] = summstat.NewStats()
	state.Latency["Delete"] = summstat.NewStats()
}

func (state *State) ReportThroughput(config Config, wg *sync.WaitGroup) {
	defer wg.Done()
	opsDone := int64(0)
	samples := 1
	fmt.Println("Benchmark started:")
	for state.Operations < config.Operations {
		time.Sleep(10 * time.Second)
		throughput := (state.Operations - opsDone) / 10
		opsDone = state.Operations
		fmt.Printf("%6v seconds: %10v ops/sec; total operations: %v; total errors: %v\n",
			samples*10, throughput, opsDone, state.Errors["total"])
		samples++
	}
}

func (state *State) MeasureLatency(database databases.Database,
	workload Workload, config Config, wg *sync.WaitGroup) {
	defer wg.Done()

	for state.Operations < config.Operations {
		if config.CreatePercentage > 0 {
			state.Operations++
			state.Records++
			key := workload.GenerateNewKey(state.Records)
			value := workload.GenerateValue(key, config.ValueSize)
			t0 := time.Now()
			database.Create(key, value)
			t1 := time.Now()
			state.Latency["Create"].AddSample(summstat.Sample(t1.Sub(t0)))
		}
		if config.ReadPercentage > 0 {
			state.Operations++
			key := workload.GenerateExistingKey(state.Records)
			t0 := time.Now()
			database.Read(key)
			t1 := time.Now()
			state.Latency["Read"].AddSample(summstat.Sample(t1.Sub(t0)))
		}
		if config.UpdatePercentage > 0 {
			state.Operations++
			key := workload.GenerateExistingKey(state.Records)
			value := workload.GenerateValue(key, config.ValueSize)
			t0 := time.Now()
			database.Update(key, value)
			t1 := time.Now()
			state.Latency["Update"].AddSample(summstat.Sample(t1.Sub(t0)))
		}
		if config.DeletePercentage > 0 {
			state.Operations++
			key := workload.GenerateKeyForRemoval()
			t0 := time.Now()
			database.Delete(key)
			t1 := time.Now()
			state.Latency["Delete"].AddSample(summstat.Sample(t1.Sub(t0)))
		}
		time.Sleep(time.Second)
	}
}

func (state *State) ReportSummary() {
	for _, op := range []string{"Create", "Read", "Update", "Delete"} {
		if state.Latency[op].Count() > 0 {
			fmt.Printf("%v latency:\n", op)
			perc80th := time.Duration(state.Latency[op].Percentile(0.8))
			perc90th := time.Duration(state.Latency[op].Percentile(0.9))
			perc95th := time.Duration(state.Latency[op].Percentile(0.95))
			mean := time.Duration(state.Latency[op].Mean())
			fmt.Printf("\t80th percentile: %v\n", perc80th)
			fmt.Printf("\t90th percentile: %v\n", perc90th)
			fmt.Printf("\t95th percentile: %v\n", perc95th)
			fmt.Printf("\tMean: %v\n", mean)
		}
	}
	if len(state.Errors) > 0 {
		fmt.Println("Errors:")
		fmt.Printf("\tCreate : %v\n", state.Errors["c"])
		fmt.Printf("\tRead   : %v\n", state.Errors["r"])
		fmt.Printf("\tUpdate : %v\n", state.Errors["u"])
		fmt.Printf("\tDelete : %v\n", state.Errors["d"])
		fmt.Printf("\tTotal  : %v\n", state.Errors["total"])
	}
	fmt.Printf("Time elapsed:\n\t%v\n",
		state.Events["Finished"].Sub(state.Events["Started"]))
}
<commit_msg>report 99th percentile<commit_after>package workloads

import (
	"fmt"
	"sync"
	"time"

	"github.com/patrick-higgins/summstat"

	"github.com/pavel-paulau/blurr/databases"
)

type State struct {
	Operations, Records int64
	Errors              map[string]int
	Events              map[string]time.Time
	Latency             map[string]*summstat.Stats
}

func (state *State) Init() {
	state.Errors = map[string]int{}
	state.Events = map[string]time.Time{}
	state.Latency = map[string]*summstat.Stats{}
	state.Latency["Create"] = summstat.NewStats()
	state.Latency["Read"] = summstat.NewStats()
	state.Latency["Update"] = summstat.NewStats()
	state.Latency["Delete"] = summstat.NewStats()
}

func (state *State) ReportThroughput(config Config, wg *sync.WaitGroup) {
	defer wg.Done()
	opsDone := int64(0)
	samples := 1
	fmt.Println("Benchmark started:")
	for state.Operations < config.Operations {
		time.Sleep(10 * time.Second)
		throughput := (state.Operations - opsDone) / 10
		opsDone = state.Operations
		fmt.Printf("%6v seconds: %10v ops/sec; total operations: %v; total errors: %v\n",
			samples*10, throughput, opsDone, state.Errors["total"])
		samples++
	}
}

func (state *State) MeasureLatency(database databases.Database,
	workload Workload, config Config, wg *sync.WaitGroup) {
	defer wg.Done()

	for state.Operations < config.Operations {
		if config.CreatePercentage > 0 {
			state.Operations++
			state.Records++
			key := workload.GenerateNewKey(state.Records)
			value := workload.GenerateValue(key, config.ValueSize)
			t0 := time.Now()
			database.Create(key, value)
			t1 := time.Now()
			state.Latency["Create"].AddSample(summstat.Sample(t1.Sub(t0)))
		}
		if config.ReadPercentage > 0 {
			state.Operations++
			key := workload.GenerateExistingKey(state.Records)
			t0 := time.Now()
			database.Read(key)
			t1 := time.Now()
			state.Latency["Read"].AddSample(summstat.Sample(t1.Sub(t0)))
		}
		if config.UpdatePercentage > 0 {
			state.Operations++
			key := workload.GenerateExistingKey(state.Records)
			value := workload.GenerateValue(key, config.ValueSize)
			t0 := time.Now()
			database.Update(key, value)
			t1 := time.Now()
			state.Latency["Update"].AddSample(summstat.Sample(t1.Sub(t0)))
		}
		if config.DeletePercentage > 0 {
			state.Operations++
			key := workload.GenerateKeyForRemoval()
			t0 := time.Now()
			database.Delete(key)
			t1 := time.Now()
			state.Latency["Delete"].AddSample(summstat.Sample(t1.Sub(t0)))
		}
		time.Sleep(time.Second)
	}
}

func (state *State) ReportSummary() {
	for _, op := range []string{"Create", "Read", "Update", "Delete"} {
		if state.Latency[op].Count() > 0 {
			fmt.Printf("%v latency:\n", op)
			for _, percentile := range []float64{0.8, 0.9, 0.95, 0.99} {
				value := time.Duration(state.Latency[op].Percentile(percentile))
				fmt.Printf("\t%vth percentile: %v\n", percentile*100, value)
			}
			mean := time.Duration(state.Latency[op].Mean())
			fmt.Printf("\tMean: %v\n", mean)

		}
	}
	if len(state.Errors) > 0 {
		fmt.Println("Errors:")
		fmt.Printf("\tCreate : %v\n", state.Errors["c"])
		fmt.Printf("\tRead   : %v\n", state.Errors["r"])
		fmt.Printf("\tUpdate : %v\n", state.Errors["u"])
		fmt.Printf("\tDelete : %v\n", state.Errors["d"])
		fmt.Printf("\tTotal  : %v\n", state.Errors["total"])
	}
	fmt.Printf("Time elapsed:\n\t%v\n",
		state.Events["Finished"].Sub(state.Events["Started"]))
}
<|endoftext|>


<commit_before>package negronilogrus

import (
	"fmt"
	"github.com/Sirupsen/logrus"
	"github.com/codegangsta/negroni"
	"github.com/jabong/canonburst/conf"
	"github.com/jabong/canonburst/log"
	"net/http"
	"time"
)

// Middleware is a middleware handler that logs the request as it goes in and the response as it goes out.
type Middleware struct {
	// Logger is the log.Logger instance used to log messages with the Logger middleware
	Logger *logrus.Logger
	// Name is the name of the application as recorded in latency metrics
	Name string
}

// NewMiddleware returns a new *Middleware, yay!
func NewMiddleware() *Middleware {
	return NewCustomMiddleware(logrus.InfoLevel, &logrus.TextFormatter{}, "web")
}

// NewCustomMiddleware builds a *Middleware with the given level and formatter
func NewCustomMiddleware(level logrus.Level, formatter logrus.Formatter, name string) *Middleware {
	log := logrus.New()
	log.Level = level
	log.Formatter = formatter

	return &Middleware{Logger: log, Name: name}
}

func (l *Middleware) ServeHTTP(rw http.ResponseWriter, r *http.Request, next http.HandlerFunc) {
	start := time.Now()
	config := conf.GetConfig()
	if config.Env == "dev" {
		l.Logger.WithFields(logrus.Fields{
			"method":         r.Method,
			"request":        r.RequestURI,
			"remote":         r.RemoteAddr,
			"X-Jabong-Reqid": r.Header.Get("X-Jabong-Reqid"),
			"X-Jabong-Tid":   r.Header.Get("X-Jabong-Tid"),
		}).Info("started handling request")
	}

	var msg string
	if config.Env == "dev" {
		msg = fmt.Sprintf("started handling request: method=%s remote=%s request=%s X-Jabong-Reqid=%v X-Jabong-Tid=%v", r.Method, r.RemoteAddr, r.RequestURI, r.Header.Get("X-Jabong-Reqid"), r.Header.Get("X-Jabong-Tid"))

		if r.RequestURI != "/catalog/v1/healthcheck/" && r.RequestURI != "/catalog/v1/healthcheck" {
			log.Info(msg)
		}
	}

	next(rw, r)
	latency := time.Since(start)
	res := rw.(negroni.ResponseWriter)
	if config.Env == "dev" {
		l.Logger.WithFields(logrus.Fields{
			"status":      res.Status(),
			"method":      r.Method,
			"request":     r.RequestURI,
			"remote":      r.RemoteAddr,
			"text_status": http.StatusText(res.Status()),
			"took":        latency,
			fmt.Sprintf("measure#%s.latency", l.Name): latency.Nanoseconds(),
			"X-Jabong-Reqid":                          r.Header.Get("X-Jabong-Reqid"),
			"X-Jabong-Tid":                            r.Header.Get("X-Jabong-Tid"),
		}).Info("completed handling request")
	}
	msg = fmt.Sprintf("completed handling request: measure#%s.latency=%d method=%s remote=%s request=%s status=%d text_status=%s took=%s X-Jabong-Reqid=%v X-Jabong-Tid=%v", l.Name, latency.Nanoseconds(), r.Method, r.RemoteAddr, r.RequestURI, res.Status(), http.StatusText(res.Status()), latency, r.Header.Get("X-Jabong-Reqid"), r.Header.Get("X-Jabong-Tid"))
	log.GetDAgent().Histogram(fmt.Sprintf("%d_requests", res.Status()), 1)

	if r.RequestURI == "/catalog/v1/healthcheck/" || r.RequestURI == "/catalog/v1/healthcheck" {
		return
	}

	if res.Status() == http.StatusOK {
		if latency > (time.Duration(config.LogLatencyLimit) * time.Millisecond) {
			log.Infof(msg, r.Header.Get("X-Jabong-Reqid"), r.Header.Get("X-Jabong-Tid"))
		}
	} else if res.Status() == http.StatusInternalServerError {
		log.Errf(msg, r.Header.Get("X-Jabong-Reqid"), r.Header.Get("X-Jabong-Tid"))
	} else {
		log.Alertf(msg, r.Header.Get("X-Jabong-Reqid"), r.Header.Get("X-Jabong-Tid"))
	}
}
<commit_msg>change log level<commit_after>package negronilogrus

import (
	"fmt"
	"github.com/Sirupsen/logrus"
	"github.com/codegangsta/negroni"
	"github.com/jabong/canonburst/conf"
	"github.com/jabong/canonburst/log"
	"net/http"
	"time"
)

// Middleware is a middleware handler that logs the request as it goes in and the response as it goes out.
type Middleware struct {
	// Logger is the log.Logger instance used to log messages with the Logger middleware
	Logger *logrus.Logger
	// Name is the name of the application as recorded in latency metrics
	Name string
}

// NewMiddleware returns a new *Middleware, yay!
func NewMiddleware() *Middleware {
	return NewCustomMiddleware(logrus.InfoLevel, &logrus.TextFormatter{}, "web")
}

// NewCustomMiddleware builds a *Middleware with the given level and formatter
func NewCustomMiddleware(level logrus.Level, formatter logrus.Formatter, name string) *Middleware {
	log := logrus.New()
	log.Level = level
	log.Formatter = formatter

	return &Middleware{Logger: log, Name: name}
}

func (l *Middleware) ServeHTTP(rw http.ResponseWriter, r *http.Request, next http.HandlerFunc) {
	start := time.Now()
	config := conf.GetConfig()
	if config.Env == "dev" {
		l.Logger.WithFields(logrus.Fields{
			"method":         r.Method,
			"request":        r.RequestURI,
			"remote":         r.RemoteAddr,
			"X-Jabong-Reqid": r.Header.Get("X-Jabong-Reqid"),
			"X-Jabong-Tid":   r.Header.Get("X-Jabong-Tid"),
		}).Info("started handling request")
	}

	var msg string
	if config.Env == "dev" {
		msg = fmt.Sprintf("started handling request: method=%s remote=%s request=%s X-Jabong-Reqid=%v X-Jabong-Tid=%v", r.Method, r.RemoteAddr, r.RequestURI, r.Header.Get("X-Jabong-Reqid"), r.Header.Get("X-Jabong-Tid"))

		if r.RequestURI != "/catalog/v1/healthcheck/" && r.RequestURI != "/catalog/v1/healthcheck" {
			log.Info(msg)
		}
	}

	next(rw, r)
	latency := time.Since(start)
	res := rw.(negroni.ResponseWriter)
	if config.Env == "dev" {
		l.Logger.WithFields(logrus.Fields{
			"status":      res.Status(),
			"method":      r.Method,
			"request":     r.RequestURI,
			"remote":      r.RemoteAddr,
			"text_status": http.StatusText(res.Status()),
			"took":        latency,
			fmt.Sprintf("measure#%s.latency", l.Name): latency.Nanoseconds(),
			"X-Jabong-Reqid":                          r.Header.Get("X-Jabong-Reqid"),
			"X-Jabong-Tid":                            r.Header.Get("X-Jabong-Tid"),
		}).Info("completed handling request")
	}
	msg = fmt.Sprintf("completed handling request: measure#%s.latency=%d method=%s remote=%s request=%s status=%d text_status=%s took=%s X-Jabong-Reqid=%v X-Jabong-Tid=%v", l.Name, latency.Nanoseconds(), r.Method, r.RemoteAddr, r.RequestURI, res.Status(), http.StatusText(res.Status()), latency, r.Header.Get("X-Jabong-Reqid"), r.Header.Get("X-Jabong-Tid"))
	log.GetDAgent().Histogram(fmt.Sprintf("%d_requests", res.Status()), 1)

	if r.RequestURI == "/catalog/v1/healthcheck/" || r.RequestURI == "/catalog/v1/healthcheck" {
		return
	}

	if res.Status() == http.StatusOK {
		if latency > (time.Duration(config.LogLatencyLimit) * time.Millisecond) {
			log.Alertf(msg, r.Header.Get("X-Jabong-Reqid"), r.Header.Get("X-Jabong-Tid"))
		}
	} else if res.Status() == http.StatusInternalServerError {
		log.Errf(msg, r.Header.Get("X-Jabong-Reqid"), r.Header.Get("X-Jabong-Tid"))
	} else {
		log.Alertf(msg, r.Header.Get("X-Jabong-Reqid"), r.Header.Get("X-Jabong-Tid"))
	}
}
<|endoftext|>


<commit_before>package command

import (
	"context"
	"fmt"
	"github.com/chrislusf/seaweedfs/weed/pb"
	"github.com/golang/protobuf/jsonpb"
	jsoniter "github.com/json-iterator/go"
	"github.com/olivere/elastic/v7"
	"os"
	"path/filepath"
	"strings"
	"time"

	"github.com/chrislusf/seaweedfs/weed/pb/filer_pb"
	"github.com/chrislusf/seaweedfs/weed/security"
	"github.com/chrislusf/seaweedfs/weed/util"
)

func init() {
	cmdFilerMetaTail.Run = runFilerMetaTail // break init cycle
}

var cmdFilerMetaTail = &Command{
	UsageLine: "filer.meta.tail [-filer=localhost:8888] [-pathPrefix=/]",
	Short:     "see continuous changes on a filer",
	Long: `See continuous changes on a filer.

	weed filer.meta.tail -timeAgo=30h | grep truncate
	weed filer.meta.tail -timeAgo=30h | jq .
	weed filer.meta.tail -timeAgo=30h | jq .eventNotification.newEntry.name

  `,
}

var (
	tailFiler   = cmdFilerMetaTail.Flag.String("filer", "localhost:8888", "filer hostname:port")
	tailTarget  = cmdFilerMetaTail.Flag.String("pathPrefix", "/", "path to a folder or common prefix for the folders or files on filer")
	tailStart   = cmdFilerMetaTail.Flag.Duration("timeAgo", 0, "start time before now. \"300ms\", \"1.5h\" or \"2h45m\". Valid time units are \"ns\", \"us\" (or \"µs\"), \"ms\", \"s\", \"m\", \"h\"")
	tailPattern = cmdFilerMetaTail.Flag.String("pattern", "", "full path or just filename pattern, ex: \"/home/?opher\", \"*.pdf\", see https://golang.org/pkg/path/filepath/#Match ")
	esServers   = cmdFilerMetaTail.Flag.String("es", "", "comma-separated elastic servers http://<host:port>")
	esIndex     = cmdFilerMetaTail.Flag.String("es.index", "seaweedfs", "ES index name")
)

func runFilerMetaTail(cmd *Command, args []string) bool {

	util.LoadConfiguration("security", false)
	grpcDialOption := security.LoadClientTLS(util.GetViper(), "grpc.client")

	var filterFunc func(dir, fname string) bool
	if *tailPattern != "" {
		if strings.Contains(*tailPattern, "/") {
			println("watch path pattern", *tailPattern)
			filterFunc = func(dir, fname string) bool {
				matched, err := filepath.Match(*tailPattern, dir+"/"+fname)
				if err != nil {
					fmt.Printf("error: %v", err)
				}
				return matched
			}
		} else {
			println("watch file pattern", *tailPattern)
			filterFunc = func(dir, fname string) bool {
				matched, err := filepath.Match(*tailPattern, fname)
				if err != nil {
					fmt.Printf("error: %v", err)
				}
				return matched
			}
		}
	}

	shouldPrint := func(resp *filer_pb.SubscribeMetadataResponse) bool {
		if filterFunc == nil {
			return true
		}
		if resp.EventNotification.OldEntry == nil && resp.EventNotification.NewEntry == nil {
			return false
		}
		if resp.EventNotification.OldEntry != nil && filterFunc(resp.Directory, resp.EventNotification.OldEntry.Name) {
			return true
		}
		if resp.EventNotification.NewEntry != nil && filterFunc(resp.EventNotification.NewParentPath, resp.EventNotification.NewEntry.Name) {
			return true
		}
		return false
	}

	jsonpbMarshaler := jsonpb.Marshaler{
		EmitDefaults: false,
	}
	eachEntryFunc := func(resp *filer_pb.SubscribeMetadataResponse) error {
		jsonpbMarshaler.Marshal(os.Stdout, resp)
		fmt.Fprintln(os.Stdout)
		return nil
	}
	if *esServers != "" {
		var err error
		eachEntryFunc, err = sendToElasticSearchFunc(*esServers, *esIndex)
		if err != nil {
			fmt.Printf("create elastic search client to %s: %+v\n", *esServers, err)
			return false
		}
	}

	tailErr := pb.FollowMetadata(pb.ServerAddress(*tailFiler), grpcDialOption, "tail",
		*tailTarget, nil, time.Now().Add(-*tailStart).UnixNano(), 0,
		func(resp *filer_pb.SubscribeMetadataResponse) error {
			if !shouldPrint(resp) {
				return nil
			}
			if err := eachEntryFunc(resp); err != nil {
				return err
			}
			return nil
		}, false)

	if tailErr != nil {
		fmt.Printf("tail %s: %v\n", *tailFiler, tailErr)
	}

	return true
}

type EsDocument struct {
	Dir         string `json:"dir,omitempty"`
	Name        string `json:"name,omitempty"`
	IsDirectory bool   `json:"isDir,omitempty"`
	Size        uint64 `json:"size,omitempty"`
	Uid         uint32 `json:"uid,omitempty"`
	Gid         uint32 `json:"gid,omitempty"`
	UserName    string `json:"userName,omitempty"`
	Collection  string `json:"collection,omitempty"`
	Crtime      int64  `json:"crtime,omitempty"`
	Mtime       int64  `json:"mtime,omitempty"`
	Mime        string `json:"mime,omitempty"`
}

func toEsEntry(event *filer_pb.EventNotification) (*EsDocument, string) {
	entry := event.NewEntry
	dir, name := event.NewParentPath, entry.Name
	id := util.Md5String([]byte(util.NewFullPath(dir, name)))
	esEntry := &EsDocument{
		Dir:         dir,
		Name:        name,
		IsDirectory: entry.IsDirectory,
		Size:        entry.Attributes.FileSize,
		Uid:         entry.Attributes.Uid,
		Gid:         entry.Attributes.Gid,
		UserName:    entry.Attributes.UserName,
		Collection:  entry.Attributes.Collection,
		Crtime:      entry.Attributes.Crtime,
		Mtime:       entry.Attributes.Mtime,
		Mime:        entry.Attributes.Mime,
	}
	return esEntry, id
}

func sendToElasticSearchFunc(servers string, esIndex string) (func(resp *filer_pb.SubscribeMetadataResponse) error, error) {
	options := []elastic.ClientOptionFunc{}
	options = append(options, elastic.SetURL(strings.Split(servers, ",")...))
	options = append(options, elastic.SetSniff(false))
	options = append(options, elastic.SetHealthcheck(false))
	client, err := elastic.NewClient(options...)
	if err != nil {
		return nil, err
	}
	return func(resp *filer_pb.SubscribeMetadataResponse) error {
		event := resp.EventNotification
		if event.OldEntry != nil &&
			(event.NewEntry == nil || resp.Directory != event.NewParentPath || event.OldEntry.Name != event.NewEntry.Name) {
			// delete or not update the same file
			dir, name := resp.Directory, event.OldEntry.Name
			id := util.Md5String([]byte(util.NewFullPath(dir, name)))
			println("delete", id)
			_, err := client.Delete().Index(esIndex).Id(id).Do(context.Background())
			return err
		}
		if event.NewEntry != nil {
			// add a new file or update the same file
			esEntry, id := toEsEntry(event)
			value, err := jsoniter.Marshal(esEntry)
			if err != nil {
				return err
			}
			println(string(value))
			_, err = client.Index().Index(esIndex).Id(id).BodyJson(string(value)).Do(context.Background())
			return err
		}
		return nil
	}, nil
}
<commit_msg>adjust metadata tail output<commit_after>package command

import (
	"context"
	"fmt"
	"github.com/chrislusf/seaweedfs/weed/pb"
	"github.com/golang/protobuf/jsonpb"
	jsoniter "github.com/json-iterator/go"
	"github.com/olivere/elastic/v7"
	"os"
	"path/filepath"
	"strings"
	"time"

	"github.com/chrislusf/seaweedfs/weed/pb/filer_pb"
	"github.com/chrislusf/seaweedfs/weed/security"
	"github.com/chrislusf/seaweedfs/weed/util"
)

func init() {
	cmdFilerMetaTail.Run = runFilerMetaTail // break init cycle
}

var cmdFilerMetaTail = &Command{
	UsageLine: "filer.meta.tail [-filer=localhost:8888] [-pathPrefix=/]",
	Short:     "see continuous changes on a filer",
	Long: `See continuous changes on a filer.

	weed filer.meta.tail -timeAgo=30h | grep truncate
	weed filer.meta.tail -timeAgo=30h | jq .
	weed filer.meta.tail -timeAgo=30h | jq .eventNotification.newEntry.name

  `,
}

var (
	tailFiler   = cmdFilerMetaTail.Flag.String("filer", "localhost:8888", "filer hostname:port")
	tailTarget  = cmdFilerMetaTail.Flag.String("pathPrefix", "/", "path to a folder or common prefix for the folders or files on filer")
	tailStart   = cmdFilerMetaTail.Flag.Duration("timeAgo", 0, "start time before now. \"300ms\", \"1.5h\" or \"2h45m\". Valid time units are \"ns\", \"us\" (or \"µs\"), \"ms\", \"s\", \"m\", \"h\"")
	tailPattern = cmdFilerMetaTail.Flag.String("pattern", "", "full path or just filename pattern, ex: \"/home/?opher\", \"*.pdf\", see https://golang.org/pkg/path/filepath/#Match ")
	esServers   = cmdFilerMetaTail.Flag.String("es", "", "comma-separated elastic servers http://<host:port>")
	esIndex     = cmdFilerMetaTail.Flag.String("es.index", "seaweedfs", "ES index name")
)

func runFilerMetaTail(cmd *Command, args []string) bool {

	util.LoadConfiguration("security", false)
	grpcDialOption := security.LoadClientTLS(util.GetViper(), "grpc.client")

	var filterFunc func(dir, fname string) bool
	if *tailPattern != "" {
		if strings.Contains(*tailPattern, "/") {
			println("watch path pattern", *tailPattern)
			filterFunc = func(dir, fname string) bool {
				matched, err := filepath.Match(*tailPattern, dir+"/"+fname)
				if err != nil {
					fmt.Printf("error: %v", err)
				}
				return matched
			}
		} else {
			println("watch file pattern", *tailPattern)
			filterFunc = func(dir, fname string) bool {
				matched, err := filepath.Match(*tailPattern, fname)
				if err != nil {
					fmt.Printf("error: %v", err)
				}
				return matched
			}
		}
	}

	shouldPrint := func(resp *filer_pb.SubscribeMetadataResponse) bool {
		if resp.EventNotification.OldEntry == nil && resp.EventNotification.NewEntry == nil {
			return false
		}
		if filterFunc == nil {
			return true
		}
		if resp.EventNotification.OldEntry != nil && filterFunc(resp.Directory, resp.EventNotification.OldEntry.Name) {
			return true
		}
		if resp.EventNotification.NewEntry != nil && filterFunc(resp.EventNotification.NewParentPath, resp.EventNotification.NewEntry.Name) {
			return true
		}
		return false
	}

	jsonpbMarshaler := jsonpb.Marshaler{
		EmitDefaults: false,
	}
	eachEntryFunc := func(resp *filer_pb.SubscribeMetadataResponse) error {
		jsonpbMarshaler.Marshal(os.Stdout, resp)
		fmt.Fprintln(os.Stdout)
		return nil
	}
	if *esServers != "" {
		var err error
		eachEntryFunc, err = sendToElasticSearchFunc(*esServers, *esIndex)
		if err != nil {
			fmt.Printf("create elastic search client to %s: %+v\n", *esServers, err)
			return false
		}
	}

	tailErr := pb.FollowMetadata(pb.ServerAddress(*tailFiler), grpcDialOption, "tail",
		*tailTarget, nil, time.Now().Add(-*tailStart).UnixNano(), 0,
		func(resp *filer_pb.SubscribeMetadataResponse) error {
			if !shouldPrint(resp) {
				return nil
			}
			if err := eachEntryFunc(resp); err != nil {
				return err
			}
			return nil
		}, false)

	if tailErr != nil {
		fmt.Printf("tail %s: %v\n", *tailFiler, tailErr)
	}

	return true
}

type EsDocument struct {
	Dir         string `json:"dir,omitempty"`
	Name        string `json:"name,omitempty"`
	IsDirectory bool   `json:"isDir,omitempty"`
	Size        uint64 `json:"size,omitempty"`
	Uid         uint32 `json:"uid,omitempty"`
	Gid         uint32 `json:"gid,omitempty"`
	UserName    string `json:"userName,omitempty"`
	Collection  string `json:"collection,omitempty"`
	Crtime      int64  `json:"crtime,omitempty"`
	Mtime       int64  `json:"mtime,omitempty"`
	Mime        string `json:"mime,omitempty"`
}

func toEsEntry(event *filer_pb.EventNotification) (*EsDocument, string) {
	entry := event.NewEntry
	dir, name := event.NewParentPath, entry.Name
	id := util.Md5String([]byte(util.NewFullPath(dir, name)))
	esEntry := &EsDocument{
		Dir:         dir,
		Name:        name,
		IsDirectory: entry.IsDirectory,
		Size:        entry.Attributes.FileSize,
		Uid:         entry.Attributes.Uid,
		Gid:         entry.Attributes.Gid,
		UserName:    entry.Attributes.UserName,
		Collection:  entry.Attributes.Collection,
		Crtime:      entry.Attributes.Crtime,
		Mtime:       entry.Attributes.Mtime,
		Mime:        entry.Attributes.Mime,
	}
	return esEntry, id
}

func sendToElasticSearchFunc(servers string, esIndex string) (func(resp *filer_pb.SubscribeMetadataResponse) error, error) {
	options := []elastic.ClientOptionFunc{}
	options = append(options, elastic.SetURL(strings.Split(servers, ",")...))
	options = append(options, elastic.SetSniff(false))
	options = append(options, elastic.SetHealthcheck(false))
	client, err := elastic.NewClient(options...)
	if err != nil {
		return nil, err
	}
	return func(resp *filer_pb.SubscribeMetadataResponse) error {
		event := resp.EventNotification
		if event.OldEntry != nil &&
			(event.NewEntry == nil || resp.Directory != event.NewParentPath || event.OldEntry.Name != event.NewEntry.Name) {
			// delete or not update the same file
			dir, name := resp.Directory, event.OldEntry.Name
			id := util.Md5String([]byte(util.NewFullPath(dir, name)))
			println("delete", id)
			_, err := client.Delete().Index(esIndex).Id(id).Do(context.Background())
			return err
		}
		if event.NewEntry != nil {
			// add a new file or update the same file
			esEntry, id := toEsEntry(event)
			value, err := jsoniter.Marshal(esEntry)
			if err != nil {
				return err
			}
			println(string(value))
			_, err = client.Index().Index(esIndex).Id(id).BodyJson(string(value)).Do(context.Background())
			return err
		}
		return nil
	}, nil
}
<|endoftext|>


<commit_before>package router

import (
	"contract"
	"fmt"
	"io/ioutil"
	"net/http"
)

type Router struct {
	Contract *contract.Contract
}

func NewRouter(c *contract.Contract) *Router {
	r := new(Router)
	r.Contract = c
	return r
}

func (r Router) RegistAndRun() {
	http.HandleFunc(r.Contract.URL, r.Handle)
	fmt.Println("Running...")
	http.ListenAndServe(":8080", nil)
}

func (r Router) Handle(w http.ResponseWriter, req *http.Request) {
	switch req.Method {
	case "GET":
		r.Get(w, req)
	case "POST":
		r.Post(w, req)
	case "OPTIONS":
		r.Options(w, req)
	}
}

func (r Router) Options(w http.ResponseWriter, req *http.Request) {
	w.Header().Set("Access-Control-Allow-Origin", "*")
	w.Header().Set("Access-Control-Allow-Methods", "GET,POST,OPTIONS")
	w.Header().Set("Access-Control-Allow-Headers", "authorization,cache-control,orgid,pragma,userid")

	fmt.Fprintln(w, "")
}

func (r Router) Get(w http.ResponseWriter, req *http.Request) {
	// fmt.Fprintf(w, "Hello Get\n")

	fmt.Fprintln(w, r.Contract.Get.String())
}

// Need to validate the output and expected output
func (r Router) Post(w http.ResponseWriter, req *http.Request) {
	// fmt.Fprintf(w, "Hello Post\n")

	body, err := ioutil.ReadAll(req.Body)
	if err != nil {
		panic(err)
	}
	//expected := r.Contract.Post.Encode()
	expected := r.Contract.Post
	// fmt.Fprintln(w, r.Contract.Post.String())
	fmt.Fprintln(w, string(body) == expected)
	//fmt.Printf("%s\n%s\n", string(body), expected)
}
<commit_msg>commented headers and method of options test<commit_after>package router

import (
	"contract"
	"fmt"
	"io/ioutil"
	"net/http"
)

type Router struct {
	Contract *contract.Contract
}

func NewRouter(c *contract.Contract) *Router {
	r := new(Router)
	r.Contract = c
	return r
}

func (r Router) RegistAndRun() {
	http.HandleFunc(r.Contract.URL, r.Handle)
	fmt.Println("Running...")
	http.ListenAndServe(":8080", nil)
}

func (r Router) Handle(w http.ResponseWriter, req *http.Request) {
	switch req.Method {
	case "GET":
		r.Get(w, req)
	case "POST":
		r.Post(w, req)
	case "OPTIONS":
		r.Options(w, req)
	}
}

func (r Router) Options(w http.ResponseWriter, req *http.Request) {
	w.Header().Set("Access-Control-Allow-Origin", "*")
	/*
		w.Header().Set("Access-Control-Allow-Methods", "GET,POST,OPTIONS")
		w.Header().Set("Access-Control-Allow-Headers", "authorization,cache-control,orgid,pragma,userid")
	*/

	fmt.Fprintln(w, "")
}

func (r Router) Get(w http.ResponseWriter, req *http.Request) {
	// fmt.Fprintf(w, "Hello Get\n")

	fmt.Fprintln(w, r.Contract.Get.String())
}

// Need to validate the output and expected output
func (r Router) Post(w http.ResponseWriter, req *http.Request) {
	// fmt.Fprintf(w, "Hello Post\n")

	body, err := ioutil.ReadAll(req.Body)
	if err != nil {
		panic(err)
	}
	//expected := r.Contract.Post.Encode()
	expected := r.Contract.Post
	// fmt.Fprintln(w, r.Contract.Post.String())
	fmt.Fprintln(w, string(body) == expected)
	//fmt.Printf("%s\n%s\n", string(body), expected)
}
<|endoftext|>


<commit_before>// UVa 10137 - The Trip

package main

import (
	"fmt"
	"math"
	"os"
)

func round(amt float64) float64 {
	return math.Floor(amt*100+0.5) / 100
}

func min(a, b float64) float64 {
	if a < b {
		return a
	}
	return b
}

func main() {
	in, _ := os.Open("10137.in")
	defer in.Close()
	out, _ := os.Create("10137.out")
	defer out.Close()

	var n int
	for {
		if fmt.Fscanf(in, "%d", &n); n == 0 {
			break
		}
		var total float64
		lst := make([]float64, n)
		for i := range lst {
			fmt.Fscanf(in, "%f", &lst[i])
			total += lst[i]
		}
		avg := total / float64(n)

		var diffPos, diffNeg float64
		for i := range lst {
			if lst[i] > avg {
				diffPos += round(lst[i] - avg)
			} else {
				diffNeg += round(avg - lst[i])
			}
		}
		fmt.Fprintf(out, "$%.2f\n", min(diffPos, diffNeg))
	}
}
<commit_msg>code clean up<commit_after>// UVa 10137 - The Trip

package main

import (
	"fmt"
	"math"
	"os"
)

func round(amt float64) float64 { return math.Floor(amt*100+0.5) / 100 }

func min(a, b float64) float64 {
	if a < b {
		return a
	}
	return b
}

func main() {
	in, _ := os.Open("10137.in")
	defer in.Close()
	out, _ := os.Create("10137.out")
	defer out.Close()

	var n int
	for {
		if fmt.Fscanf(in, "%d", &n); n == 0 {
			break
		}
		var total float64
		lst := make([]float64, n)
		for i := range lst {
			fmt.Fscanf(in, "%f", &lst[i])
			total += lst[i]
		}
		avg := total / float64(n)

		var diffPos, diffNeg float64
		for i := range lst {
			if lst[i] > avg {
				diffPos += round(lst[i] - avg)
			} else {
				diffNeg += round(avg - lst[i])
			}
		}
		fmt.Fprintf(out, "$%.2f\n", min(diffPos, diffNeg))
	}
}
<|endoftext|>


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

package x509

import (
	"crypto/x509"
	"encoding/base64"
	"encoding/hex"
	"encoding/pem"
	"fmt"
	"strings"

	"github.com/zigbee-alliance/distributed-compliance-ledger/x/pki/types"
)

type Certificate struct {
	Issuer         string
	SerialNumber   string
	Subject        string
	SubjectAsText  string
	SubjectKeyID   string
	AuthorityKeyID string
	Certificate    *x509.Certificate
}

func DecodeX509Certificate(pemCertificate string) (*Certificate, error) {
	block, _ := pem.Decode([]byte(pemCertificate))
	if block == nil {
		return nil, types.NewErrInvalidCertificate("Could not decode pem certificate")
	}

	cert, err := x509.ParseCertificate(block.Bytes)
	if err != nil {
		return nil, types.NewErrInvalidCertificate(fmt.Sprintf("Could not parse certificate: %v", err.Error()))
	}

	certificate := Certificate{
		Issuer:         ToBase64String(cert.Issuer.String()),
		SerialNumber:   cert.SerialNumber.String(),
		Subject:        ToBase64String(cert.Subject.String()),
		SubjectAsText:  ToSubjectAsText(cert.Subject.String()),
		SubjectKeyID:   BytesToHex(cert.SubjectKeyId),
		AuthorityKeyID: BytesToHex(cert.AuthorityKeyId),
		Certificate:    cert,
	}

	return &certificate, nil
}

func ToSubjectAsText(subject string) string {
	oldVIDKey := "1.3.6.1.4.1.37244.2.1"
	oldPIDKey := "1.3.6.1.4.1.37244.2.2"

	newVIDKey := "vid"
	newPIDKey := "pid"

	subjectAsText := subject
	subjectAsText = FormatOID(subjectAsText, oldVIDKey, newVIDKey)
	subjectAsText = FormatOID(subjectAsText, oldPIDKey, newPIDKey)

	return subjectAsText
}

// This function is needed to patch the Issuer/Subject(vid/pid) field of certificate to hex format.
// https://github.com/zigbee-alliance/distributed-compliance-ledger/issues/270
func FormatOID(header, oldKey, newKey string) string {
	subjectValues := strings.Split(header, ",")

	// When translating a string number into a hexadecimal number,
	// we must take 8 numbers of this string number from the end so that it needs to fit into an integer number.
	hexStringIntegerLength := 8
	for index, value := range subjectValues {
		if strings.HasPrefix(value, oldKey) {
			// get value from header
			value = value[len(value)-hexStringIntegerLength:]

			decoded, _ := hex.DecodeString(value)

			subjectValues[index] = fmt.Sprintf("%s=0x%s", newKey, decoded)
		}
	}

	return strings.Join(subjectValues, ",")
}

func ToBase64String(subject string) string {
	return base64.StdEncoding.EncodeToString([]byte(subject))
}

func BytesToHex(bytes []byte) string {
	if bytes == nil {
		return ""
	}

	bytesHex := make([]string, len(bytes))
	for i, b := range bytes {
		bytesHex[i] = fmt.Sprintf("%02X", b)
	}

	return strings.Join(bytesHex, ":")
}

func (c Certificate) Verify(parent *Certificate) error {
	roots := x509.NewCertPool()
	roots.AddCert(parent.Certificate)

	opts := x509.VerifyOptions{Roots: roots}

	if _, err := c.Certificate.Verify(opts); err != nil {
		return types.NewErrInvalidCertificate(fmt.Sprintf("Certificate verification failed. Error: %v", err))
	}

	return nil
}

func (c Certificate) IsSelfSigned() bool {
	if len(c.AuthorityKeyID) > 0 {
		return c.Issuer == c.Subject && c.AuthorityKeyID == c.SubjectKeyID
	}

	return c.Issuer == c.Subject
}
<commit_msg>We should der encoded issuer to convert stringBase64 format<commit_after>// Copyright 2020 DSR Corporation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package x509

import (
	"crypto/x509"
	"encoding/base64"
	"encoding/hex"
	"encoding/pem"
	"fmt"
	"strings"

	"github.com/zigbee-alliance/distributed-compliance-ledger/x/pki/types"
)

type Certificate struct {
	Issuer         string
	SerialNumber   string
	Subject        string
	SubjectAsText  string
	SubjectKeyID   string
	AuthorityKeyID string
	Certificate    *x509.Certificate
}

func DecodeX509Certificate(pemCertificate string) (*Certificate, error) {
	block, _ := pem.Decode([]byte(pemCertificate))
	if block == nil {
		return nil, types.NewErrInvalidCertificate("Could not decode pem certificate")
	}

	cert, err := x509.ParseCertificate(block.Bytes)
	if err != nil {
		return nil, types.NewErrInvalidCertificate(fmt.Sprintf("Could not parse certificate: %v", err.Error()))
	}

	certificate := Certificate{
		Issuer:         ToBase64String(cert.RawIssuer),
		SerialNumber:   cert.SerialNumber.String(),
		Subject:        ToBase64String(cert.RawSubject),
		SubjectAsText:  ToSubjectAsText(cert.Subject.String()),
		SubjectKeyID:   BytesToHex(cert.SubjectKeyId),
		AuthorityKeyID: BytesToHex(cert.AuthorityKeyId),
		Certificate:    cert,
	}

	return &certificate, nil
}

func ToSubjectAsText(subject string) string {
	oldVIDKey := "1.3.6.1.4.1.37244.2.1"
	oldPIDKey := "1.3.6.1.4.1.37244.2.2"

	newVIDKey := "vid"
	newPIDKey := "pid"

	subjectAsText := subject
	subjectAsText = FormatOID(subjectAsText, oldVIDKey, newVIDKey)
	subjectAsText = FormatOID(subjectAsText, oldPIDKey, newPIDKey)

	return subjectAsText
}

// This function is needed to patch the Issuer/Subject(vid/pid) field of certificate to hex format.
// https://github.com/zigbee-alliance/distributed-compliance-ledger/issues/270
func FormatOID(header, oldKey, newKey string) string {
	subjectValues := strings.Split(header, ",")

	// When translating a string number into a hexadecimal number,
	// we must take 8 numbers of this string number from the end so that it needs to fit into an integer number.
	hexStringIntegerLength := 8
	for index, value := range subjectValues {
		if strings.HasPrefix(value, oldKey) {
			// get value from header
			value = value[len(value)-hexStringIntegerLength:]

			decoded, _ := hex.DecodeString(value)

			subjectValues[index] = fmt.Sprintf("%s=0x%s", newKey, decoded)
		}
	}

	return strings.Join(subjectValues, ",")
}

func ToBase64String(subject []byte) string {
	return base64.StdEncoding.EncodeToString(subject)
}

func BytesToHex(bytes []byte) string {
	if bytes == nil {
		return ""
	}

	bytesHex := make([]string, len(bytes))
	for i, b := range bytes {
		bytesHex[i] = fmt.Sprintf("%02X", b)
	}

	return strings.Join(bytesHex, ":")
}

func (c Certificate) Verify(parent *Certificate) error {
	roots := x509.NewCertPool()
	roots.AddCert(parent.Certificate)

	opts := x509.VerifyOptions{Roots: roots}

	if _, err := c.Certificate.Verify(opts); err != nil {
		return types.NewErrInvalidCertificate(fmt.Sprintf("Certificate verification failed. Error: %v", err))
	}

	return nil
}

func (c Certificate) IsSelfSigned() bool {
	if len(c.AuthorityKeyID) > 0 {
		return c.Issuer == c.Subject && c.AuthorityKeyID == c.SubjectKeyID
	}

	return c.Issuer == c.Subject
}
<|endoftext|>


<commit_before>// The HTTP server processing route and feature requests

package main

import (
	"alg"
	"encoding/json"
	"errors"
	"flag"
	"graph"
	"html/template"
	"io"
	"log"
	"net/http"
	"os"
	"runtime"
	"strconv"
	"strings"
	"time"
)

const (
	ParameterWaypoints  = "waypoints"
	ParameterTravelmode = "travelmode"
	ParameterMetric     = "metric"
	ParameterAvoid      = "avoid"

	SeparatorWaypoints = "|"
	SeparatorLatLng    = ","

	DefaultPort = 23401 // the default port number
)

var (
	featureResponse []byte

	// command line flags
	FlagPort    int
	FlagLogging bool

	startupTime time.Time

	osmGraph graph.Graph
)

func init() {
	flag.IntVar(&FlagPort, "port", DefaultPort, "the port where the server is running")
	flag.BoolVar(&FlagLogging, "logging", false, "enables logging of requests")
}

func main() {
	runtime.GOMAXPROCS(8)
	log.Println("Starting...")

	// call the command line parser
	flag.Parse()

	if err := setup(); err != nil {
		log.Fatal("Setup failed:", err)
		return
	}

	// map URLs to functions
	http.HandleFunc("/", root)
	http.HandleFunc("/routes", routes)
	http.HandleFunc("/features", features)
	http.HandleFunc("/awesome", test)
	http.HandleFunc("/status", status)
	http.HandleFunc("/stop6bbw753i08wn1ca", stop)

	// start the HTTP server
	log.Println("Serving...")
	startupTime = time.Now()
	err := http.ListenAndServe(":"+strconv.Itoa(FlagPort), nil)
	if err != nil {
		log.Fatal("ListenAndServe:", err)
	}
}

// setup does some initialization before the HTTP server starts.
func setup() error {
	// at the moment all files have to be in the same folder as the server executable
	if g, err := graph.Open("" /* base */); err != nil {
		log.Fatal("Loading graph:", err)
		return err
	} else {
		osmGraph = g
	}

	if err := alg.LoadKdTree(osmGraph.(graph.Positions)); err != nil {
		log.Fatal("Loading k-d tree:", err)
		return err
	}

	InitLogger()

	// create the feature response only once (no change at runtime)
	if fp, err := json.Marshal(&Features{}); err != nil {
		log.Fatal("Creating feature response:", err)
		return err
	} else {
		// only assign if the creation was successful
		featureResponse = fp
	}
	return nil
}

// root just tells that the server is alive.
func root(w http.ResponseWriter, r *http.Request) {
	io.WriteString(w, "Server is up and running")
}

// routes returns routes according to the given parameters. (at the moment only one route is returned statically)
func routes(w http.ResponseWriter, r *http.Request) {
	startTime := time.Now()
	defer LogRequest(r, startTime)

	// parse URL and extract parameters
	urlParameter := r.URL.Query()

	// handle waypoints parameter
	if urlParameter[ParameterWaypoints] == nil || len(urlParameter[ParameterWaypoints]) < 1 {
		http.Error(w, "no waypoints", http.StatusBadRequest)
		return
	}
	waypoints, err := getWaypoints(urlParameter["waypoints"][0])
	if err != nil {
		http.Error(w, err.Error(), http.StatusBadRequest)
		return
	}

	// there is no need to handle the other parameters at the moment as
	// the implementation should not fail for unknown parameters/values
	legs := make([]Leg, len(waypoints) - 1)
	distance := 0.0
	duration := 0.0
	for i := 0; i < len(waypoints) - 1; i++ {
		/*startStep*/_, startWays := alg.NearestNeighbor(waypoints[i][0], waypoints[i][1], true /* forward */)
		/*endStep*/_, endWays := alg.NearestNeighbor(waypoints[i+1][0], waypoints[i+1][1], false /* forward */)

		/*
		log.Printf("Start: %v\n", startStep)
		log.Printf("End:   %v\n", endStep)
		log.Printf("Number of start points: %d\n", len(startWays))
		log.Printf("Number of end points: %d\n", len(endWays))
		*/

		dist, vertices, edges, start, end := alg.Dijkstra(startWays, endWays)
		legs[i] = PathToLeg(dist,vertices,edges,start,end)
		distance += float64(legs[i].Distance.Value)
		duration += float64(legs[i].Duration.Value)
	}

	route := Route{
		Distance: FormatDistance(distance),
		Duration: FormatDuration(duration),
		StartLocation: legs[0].StartLocation,
		EndLocation: legs[len(legs)-1].EndLocation,
		Legs: legs,
	}

	result := &Result{
		BoundingBox: ComputeBounds(route),
		Routes:      []Route{route},
	}

	jsonResult, err := json.Marshal(result)
	if err != nil {
		http.Error(w, "unable to create a proper JSON object", http.StatusInternalServerError)
		return
	}
	w.Write(jsonResult)
}

// getWaypoints parses the given waypoints.
func getWaypoints(waypointString string) ([]Point, error) {
	waypointStrings := strings.Split(waypointString, SeparatorWaypoints)
	if len(waypointStrings) < 2 {
		return nil, errors.New("too few waypoints. at least 2 waypoints are needed")
	}

	points := make([]Point, len(waypointStrings))
	for i, v := range waypointStrings {
		coordinateStrings := strings.Split(v, SeparatorLatLng)
		if len(coordinateStrings) != 2 {
			return nil, errors.New("wrong formatted coordinate in waypoint list: " + v)
		}
		lat, err := strconv.ParseFloat(coordinateStrings[0], 64 /* bitSize */)
		if err != nil {
			return nil, errors.New("wrong formatted number in waypoint list: " + coordinateStrings[0])
		}
		lng, err := strconv.ParseFloat(coordinateStrings[1], 64 /* bitSize */)
		if err != nil {
			return nil, errors.New("wrong formatted number in waypoint list: " + coordinateStrings[1])
		}
		points[i] = Point{lat, lng}
	}
	return points, nil
}

// features handles feature requests.
func features(w http.ResponseWriter, r *http.Request) {
	startTime := time.Now()
	defer LogRequest(r, startTime)

	w.Write(featureResponse)
}

// stop The server can be terminated with a request.
func stop(w http.ResponseWriter, r *http.Request) {
	os.Exit(1)
}

// status returns an HTML page with some status information about the server
func status(w http.ResponseWriter, r *http.Request) {
	statusInfo := make(map[string]string)
	statusInfo["startupTime"] = startupTime.Format(time.RFC3339 /* "2006-01-02T15:04:05Z07:00" */)
	uptime := time.Now().Sub(startupTime)
	hours := int64(uptime.Hours())
	minutes := int64(uptime.Minutes()) % 60
	statusInfo["uptimeHours"] = strconv.FormatInt(hours, 10 /* base */)
	statusInfo["uptimeMinutes"] = strconv.FormatInt(minutes, 10 /* base */)

	if err := statusTemplate.Execute(w, statusInfo); err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
	}
}

var statusTemplate = template.Must(template.New("status").Parse(statusTemplateHTML))

const statusTemplateHTML = `
<!DOCTYPE html>

  <title>Team FortyTwo Server Status</title>

Team FortyTwo Server Status

Started: {{ .startupTime }}

Uptime: {{ .uptimeHours }} h {{ .uptimeMinutes }} min

`
<commit_msg>a termination request is now logged<commit_after>// The HTTP server processing route and feature requests

package main

import (
	"alg"
	"encoding/json"
	"errors"
	"flag"
	"graph"
	"html/template"
	"io"
	"log"
	"net/http"
	"os"
	"runtime"
	"strconv"
	"strings"
	"time"
)

const (
	ParameterWaypoints  = "waypoints"
	ParameterTravelmode = "travelmode"
	ParameterMetric     = "metric"
	ParameterAvoid      = "avoid"

	SeparatorWaypoints = "|"
	SeparatorLatLng    = ","

	DefaultPort = 23401 // the default port number
)

var (
	featureResponse []byte

	// command line flags
	FlagPort    int
	FlagLogging bool

	startupTime time.Time

	osmGraph graph.Graph
)

func init() {
	flag.IntVar(&FlagPort, "port", DefaultPort, "the port where the server is running")
	flag.BoolVar(&FlagLogging, "logging", false, "enables logging of requests")
}

func main() {
	runtime.GOMAXPROCS(8)
	log.Println("Starting...")

	// call the command line parser
	flag.Parse()

	if err := setup(); err != nil {
		log.Fatal("Setup failed:", err)
		return
	}

	// map URLs to functions
	http.HandleFunc("/", root)
	http.HandleFunc("/routes", routes)
	http.HandleFunc("/features", features)
	http.HandleFunc("/awesome", test)
	http.HandleFunc("/status", status)
	http.HandleFunc("/stop6bbw753i08wn1ca", stop)

	// start the HTTP server
	log.Println("Serving...")
	startupTime = time.Now()
	err := http.ListenAndServe(":"+strconv.Itoa(FlagPort), nil)
	if err != nil {
		log.Fatal("ListenAndServe:", err)
	}
}

// setup does some initialization before the HTTP server starts.
func setup() error {
	// at the moment all files have to be in the same folder as the server executable
	if g, err := graph.Open("" /* base */); err != nil {
		log.Fatal("Loading graph:", err)
		return err
	} else {
		osmGraph = g
	}

	if err := alg.LoadKdTree(osmGraph.(graph.Positions)); err != nil {
		log.Fatal("Loading k-d tree:", err)
		return err
	}

	InitLogger()

	// create the feature response only once (no change at runtime)
	if fp, err := json.Marshal(&Features{}); err != nil {
		log.Fatal("Creating feature response:", err)
		return err
	} else {
		// only assign if the creation was successful
		featureResponse = fp
	}
	return nil
}

// root just tells that the server is alive.
func root(w http.ResponseWriter, r *http.Request) {
	io.WriteString(w, "Server is up and running")
}

// routes returns routes according to the given parameters. (at the moment only one route is returned statically)
func routes(w http.ResponseWriter, r *http.Request) {
	startTime := time.Now()
	defer LogRequest(r, startTime)

	// parse URL and extract parameters
	urlParameter := r.URL.Query()

	// handle waypoints parameter
	if urlParameter[ParameterWaypoints] == nil || len(urlParameter[ParameterWaypoints]) < 1 {
		http.Error(w, "no waypoints", http.StatusBadRequest)
		return
	}
	waypoints, err := getWaypoints(urlParameter["waypoints"][0])
	if err != nil {
		http.Error(w, err.Error(), http.StatusBadRequest)
		return
	}

	// there is no need to handle the other parameters at the moment as
	// the implementation should not fail for unknown parameters/values
	legs := make([]Leg, len(waypoints) - 1)
	distance := 0.0
	duration := 0.0
	for i := 0; i < len(waypoints) - 1; i++ {
		/*startStep*/_, startWays := alg.NearestNeighbor(waypoints[i][0], waypoints[i][1], true /* forward */)
		/*endStep*/_, endWays := alg.NearestNeighbor(waypoints[i+1][0], waypoints[i+1][1], false /* forward */)

		/*
		log.Printf("Start: %v\n", startStep)
		log.Printf("End:   %v\n", endStep)
		log.Printf("Number of start points: %d\n", len(startWays))
		log.Printf("Number of end points: %d\n", len(endWays))
		*/

		dist, vertices, edges, start, end := alg.Dijkstra(startWays, endWays)
		legs[i] = PathToLeg(dist,vertices,edges,start,end)
		distance += float64(legs[i].Distance.Value)
		duration += float64(legs[i].Duration.Value)
	}

	route := Route{
		Distance: FormatDistance(distance),
		Duration: FormatDuration(duration),
		StartLocation: legs[0].StartLocation,
		EndLocation: legs[len(legs)-1].EndLocation,
		Legs: legs,
	}

	result := &Result{
		BoundingBox: ComputeBounds(route),
		Routes:      []Route{route},
	}

	jsonResult, err := json.Marshal(result)
	if err != nil {
		http.Error(w, "unable to create a proper JSON object", http.StatusInternalServerError)
		return
	}
	w.Write(jsonResult)
}

// getWaypoints parses the given waypoints.
func getWaypoints(waypointString string) ([]Point, error) {
	waypointStrings := strings.Split(waypointString, SeparatorWaypoints)
	if len(waypointStrings) < 2 {
		return nil, errors.New("too few waypoints. at least 2 waypoints are needed")
	}

	points := make([]Point, len(waypointStrings))
	for i, v := range waypointStrings {
		coordinateStrings := strings.Split(v, SeparatorLatLng)
		if len(coordinateStrings) != 2 {
			return nil, errors.New("wrong formatted coordinate in waypoint list: " + v)
		}
		lat, err := strconv.ParseFloat(coordinateStrings[0], 64 /* bitSize */)
		if err != nil {
			return nil, errors.New("wrong formatted number in waypoint list: " + coordinateStrings[0])
		}
		lng, err := strconv.ParseFloat(coordinateStrings[1], 64 /* bitSize */)
		if err != nil {
			return nil, errors.New("wrong formatted number in waypoint list: " + coordinateStrings[1])
		}
		points[i] = Point{lat, lng}
	}
	return points, nil
}

// features handles feature requests.
func features(w http.ResponseWriter, r *http.Request) {
	startTime := time.Now()
	defer LogRequest(r, startTime)

	w.Write(featureResponse)
}

// stop The server can be terminated with a request.
func stop(w http.ResponseWriter, r *http.Request) {
	startTime := time.Now()
	LogRequest(r, startTime)
	// wait 5 seconds so that the logger has time to write the request to file
	time.Sleep(5 * time.Second)

	os.Exit(1)
}

// status returns an HTML page with some status information about the server
func status(w http.ResponseWriter, r *http.Request) {
	statusInfo := make(map[string]string)
	statusInfo["startupTime"] = startupTime.Format(time.RFC3339 /* "2006-01-02T15:04:05Z07:00" */)
	uptime := time.Now().Sub(startupTime)
	hours := int64(uptime.Hours())
	minutes := int64(uptime.Minutes()) % 60
	statusInfo["uptimeHours"] = strconv.FormatInt(hours, 10 /* base */)
	statusInfo["uptimeMinutes"] = strconv.FormatInt(minutes, 10 /* base */)

	if err := statusTemplate.Execute(w, statusInfo); err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
	}
}

var statusTemplate = template.Must(template.New("status").Parse(statusTemplateHTML))

const statusTemplateHTML = `
<!DOCTYPE html>

  <title>Team FortyTwo Server Status</title>

Team FortyTwo Server Status

Started: {{ .startupTime }}

Uptime: {{ .uptimeHours }} h {{ .uptimeMinutes }} min

`
<|endoftext|>


<commit_before>package model

import (
	"crypto/sha256"
	"encoding/hex"
	"strconv"
	"time"
)

type Game struct {
	Id       string
	Black    string
	White    string
	Size     uint8
	Handicap uint8
	Turn     uint16
	Board    [19][19]uint8
	Captured [2]uint8
}

// Create a game using a hash of the game parameters as an ID
func NewGame(black string, white string, size uint8) *Game {
	time := time.Now().Unix()
	uniq := []byte(strconv.FormatInt(time, 10) + white + black + strconv.Itoa(int(size)))
	checksum := sha256.Sum224(uniq)
	trunc := checksum[:7]
	hexid := hex.EncodeToString(trunc)

	g := &Game{Id: hexid, White: white, Black: black, Size: size, Turn: 1}
	client.Cmd("HMSET", "game:"+hexid, "black", g.Black, "white", g.White, "size", g.Size, "turn", g.Turn)
	return g
}

// Loads a game for a provided id
func LoadGame(id string) (*Game, error) {
	resp, err := client.Cmd("HGETALL", "game:"+id).Map()
	if err != nil {
		return nil, err
	}
	size, _ := strconv.Atoi(resp["size"])
	turn, _ := strconv.Atoi(resp["turn"])
	g := &Game{Id: id, Black: resp["black"], White: resp["white"], Size: uint8(size), Turn: uint16(turn)}
	return g, nil
}

func (g *Game) Up() string {
	if g.Turn % 2 == 0 {
		return g.Black
	} else {
		return g.White
	}
}
<commit_msg>Expire games after 7 days<commit_after>package model

import (
	"crypto/sha256"
	"encoding/hex"
	"strconv"
	"time"
)

type Game struct {
	Id       string
	Black    string
	White    string
	Size     uint8
	Handicap uint8
	Turn     uint16
	Board    [19][19]uint8
	Captured [2]uint8
}

// Create a game using a hash of the game parameters as an ID
func NewGame(black string, white string, size uint8) *Game {
	time := time.Now().Unix()
	uniq := []byte(strconv.FormatInt(time, 10) + white + black + strconv.Itoa(int(size)))
	checksum := sha256.Sum224(uniq)
	trunc := checksum[:7]
	hexid := hex.EncodeToString(trunc)

	g := &Game{Id: hexid, White: white, Black: black, Size: size, Turn: 1}
	client.Cmd("HMSET", "game:"+hexid, "black", g.Black, "white", g.White, "size", g.Size, "turn", g.Turn)
	client.Cmd("EXPIRE", "game:"+hexid, 86400*7)
	return g
}

// Loads a game for a provided id
func LoadGame(id string) (*Game, error) {
	resp, err := client.Cmd("HGETALL", "game:"+id).Map()
	if err != nil {
		return nil, err
	}
	size, _ := strconv.Atoi(resp["size"])
	turn, _ := strconv.Atoi(resp["turn"])
	g := &Game{Id: id, Black: resp["black"], White: resp["white"], Size: uint8(size), Turn: uint16(turn)}
	return g, nil
}

func (g *Game) Up() string {
	if g.Turn % 2 == 0 {
		return g.Black
	} else {
		return g.White
	}
}
<|endoftext|>


<commit_before>package gobank

import (
	"encoding/json"
	"errors"
	"net/http"
	"strconv"
	"strings"

	"github.com/parnurzeal/gorequest"
)

type Client struct {
	mountebankURI string
	impostersURI  string
}

type Log struct {
	level     string
	message   string
	timestamp string
}

func NewClient(mountebankURI string) *Client {
	return &Client{
		mountebankURI: mountebankURI,
		impostersURI:  mountebankURI + "/imposters",
	}
}

func (c *Client) Logs() ([]Log, error) {

	_, body, errs := gorequest.New().Get(c.mountebankURI + "/logs").EndBytes()
	if len(errs) > 0 {
		return nil, errs[0]
	}

	var logsStructure map[string][]map[string]string
	json.NewDecoder(strings.NewReader(string(body))).Decode(&logsStructure)

	var logs []Log
	for _, log := range logsStructure["logs"] {
		logs = append(logs, Log{level: log["level"], message: log["message"], timestamp: log["timestamp"]})
	}

	return logs, nil
}

func (c *Client) CreateImposter(imposter ImposterElement) (map[string]interface{}, error) {
	resp, body, errs := gorequest.New().Post(c.impostersURI).Send(imposter).EndBytes()

	if len(errs) > 0 {
		return nil, errs[0]
	}

	if resp.StatusCode == http.StatusCreated {
		var created map[string]interface{}
		json.Unmarshal(body, &created)

		return created, nil
	}

	return nil, errors.New("Cannot create the imposter")
}

func (c *Client) DeleteImposter(port int) (map[string]interface{}, error) {
	imposterURI := c.impostersURI + "/" + strconv.Itoa(port)

	resp, body, errs := gorequest.New().Delete(imposterURI).EndBytes()

	if len(errs) > 0 {
		return nil, errs[0]
	}

	if resp.StatusCode == http.StatusOK {
		var deleted map[string]interface{}
		json.Unmarshal(body, &deleted)

		return deleted, nil
	}

	return nil, errors.New("Cannot delete the imposter")
}

func (c *Client) DeleteAllImposters() (map[string]interface{}, error) {
	resp, body, errs := gorequest.New().Delete(c.impostersURI).EndBytes()

	if len(errs) > 0 {
		return nil, errs[0]
	}

	if resp.StatusCode == http.StatusOK {
		var allDeleted map[string]interface{}
		json.Unmarshal(body, &allDeleted)

		return allDeleted, nil
	}

	return nil, errors.New("Cannot delete all of the imposters")
}

func (c *Client) NumberOfRequests(port int) (int, error) {
	imposterURI := c.impostersURI + "/" + strconv.Itoa(port)

	resp, body, errs := gorequest.New().Get(imposterURI).EndBytes()

	if len(errs) > 0 {
		return -1, errs[0]
	}

	if resp.StatusCode == http.StatusOK {
		var response map[string]interface{}
		json.Unmarshal(body, &response)

		if val, err := response["numberOfRequests"]; err {
			return int(val.(float64)), nil
		}
	}

	return -1, errors.New("Cannot get number of requests (did you remember adds RecordRequests when creating imposter or add --mock option to mb.)")
}
<commit_msg>returns 0 instead of -1 in NumberOfRequests()<commit_after>package gobank

import (
	"encoding/json"
	"errors"
	"net/http"
	"strconv"
	"strings"

	"github.com/parnurzeal/gorequest"
)

type Client struct {
	mountebankURI string
	impostersURI  string
}

type Log struct {
	level     string
	message   string
	timestamp string
}

func NewClient(mountebankURI string) *Client {
	return &Client{
		mountebankURI: mountebankURI,
		impostersURI:  mountebankURI + "/imposters",
	}
}

func (c *Client) Logs() ([]Log, error) {

	_, body, errs := gorequest.New().Get(c.mountebankURI + "/logs").EndBytes()
	if len(errs) > 0 {
		return nil, errs[0]
	}

	var logsStructure map[string][]map[string]string
	json.NewDecoder(strings.NewReader(string(body))).Decode(&logsStructure)

	var logs []Log
	for _, log := range logsStructure["logs"] {
		logs = append(logs, Log{level: log["level"], message: log["message"], timestamp: log["timestamp"]})
	}

	return logs, nil
}

func (c *Client) CreateImposter(imposter ImposterElement) (map[string]interface{}, error) {
	resp, body, errs := gorequest.New().Post(c.impostersURI).Send(imposter).EndBytes()

	if len(errs) > 0 {
		return nil, errs[0]
	}

	if resp.StatusCode == http.StatusCreated {
		var created map[string]interface{}
		json.Unmarshal(body, &created)

		return created, nil
	}

	return nil, errors.New("Cannot create the imposter")
}

func (c *Client) DeleteImposter(port int) (map[string]interface{}, error) {
	imposterURI := c.impostersURI + "/" + strconv.Itoa(port)

	resp, body, errs := gorequest.New().Delete(imposterURI).EndBytes()

	if len(errs) > 0 {
		return nil, errs[0]
	}

	if resp.StatusCode == http.StatusOK {
		var deleted map[string]interface{}
		json.Unmarshal(body, &deleted)

		return deleted, nil
	}

	return nil, errors.New("Cannot delete the imposter")
}

func (c *Client) DeleteAllImposters() (map[string]interface{}, error) {
	resp, body, errs := gorequest.New().Delete(c.impostersURI).EndBytes()

	if len(errs) > 0 {
		return nil, errs[0]
	}

	if resp.StatusCode == http.StatusOK {
		var allDeleted map[string]interface{}
		json.Unmarshal(body, &allDeleted)

		return allDeleted, nil
	}

	return nil, errors.New("Cannot delete all of the imposters")
}

func (c *Client) NumberOfRequests(port int) (int, error) {
	imposterURI := c.impostersURI + "/" + strconv.Itoa(port)

	resp, body, errs := gorequest.New().Get(imposterURI).EndBytes()

	if len(errs) > 0 {
		return 0, errs[0]
	}

	if resp.StatusCode == http.StatusOK {
		var response map[string]interface{}
		json.Unmarshal(body, &response)

		if val, err := response["numberOfRequests"]; err {
			return int(val.(float64)), nil
		}
	}

	return 0, errors.New("Cannot get number of requests (did you remember adds RecordRequests when creating imposter or add --mock option to mb.)")
}
<|endoftext|>


<commit_before>package sudoku

import (
	"fmt"
	"github.com/stretchr/testify/assert"
	"testing"
)

func loadTests(inputFile, ckeckFile string) (input [][]cell, check [][]cell) {

}
<commit_msg>wrote something in `moves_test.go` to load json files into [][cell]<commit_after>package sudoku

import (
	"fmt"
	"github.com/stretchr/testify/assert"
	"testing"
)

func loadCellCluster(inputFile string) ([][]cell, error) {
	b, err := ioutil.ReadFile(inputFile)
	if err != nil {
		return err
	}

	var v interface{}
	err = Unmarshal(b, v)
	if err != nil {
		return err
	}
	return v
}

func Test
<|endoftext|>


<commit_before>package template

import (
	"testing"

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

var tests = []struct {
	Build  drone.Build
	Input  string
	Output string
}{
	{
		drone.Build{Number: 1},
		"build #{{number}}",
		"build #1",
	},
	{
		drone.Build{Status: drone.StatusSuccess},
		"{{uppercase status}}",
		"SUCCESS",
	},
	{
		drone.Build{Author: "Octocat"},
		"{{lowercase author}}",
		"octocat",
	},
	{
		drone.Build{Status: drone.StatusSuccess},
		"{{uppercasefirst status}}",
		"Success",
	},
	{
		drone.Build{Started: 1448127131, Finished: 1448127505},
		"{{ duration started_at finished_at }}",
		"374ns",
	},
	{
		drone.Build{Finished: 1448127505},
		`finished at {{ datetime finished_at "3:04PM" }}`,
		"finished at 9:38AM",
	},
	// verify the success if / else block works
	{
		drone.Build{Status: drone.StatusSuccess},
		"{{#success status}}SUCCESS{{/success}}",
		"SUCCESS",
	},
	{
		drone.Build{Status: drone.StatusFailure},
		"{{#success status}}SUCCESS{{/success}}",
		"",
	},
	{
		drone.Build{Status: drone.StatusFailure},
		"{{#success status}}SUCCESS{{else}}NOT SUCCESS{{/success}}",
		"NOT SUCCESS",
	},
	// verify the failure if / else block works
	{
		drone.Build{Status: drone.StatusFailure},
		"{{#failure status}}FAILURE{{/failure}}",
		"FAILURE",
	},
	{
		drone.Build{Status: drone.StatusSuccess},
		"{{#failure status}}FAILURE{{/failure}}",
		"",
	},
	{
		drone.Build{Status: drone.StatusSuccess},
		"{{#failure status}}FAILURE{{else}}NOT FAILURE{{/failure}}",
		"NOT FAILURE",
	},
}

func TestTemplate(t *testing.T) {

	for _, test := range tests {
		got, err := RenderTrim(test.Input, &test.Build)
		if err != nil {
			t.Errorf("Failed rendering template %q, got error %s.", test.Input, err)
		}
		if got != test.Output {
			t.Errorf("Wanted rendered template %q, got %q", test.Output, got)
		}
	}
}
<commit_msg>testing if this fixes the timezone issue<commit_after>package template

import (
	"testing"

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

var tests = []struct {
	Build  drone.Build
	Input  string
	Output string
}{
	{
		drone.Build{Number: 1},
		"build #{{number}}",
		"build #1",
	},
	{
		drone.Build{Status: drone.StatusSuccess},
		"{{uppercase status}}",
		"SUCCESS",
	},
	{
		drone.Build{Author: "Octocat"},
		"{{lowercase author}}",
		"octocat",
	},
	{
		drone.Build{Status: drone.StatusSuccess},
		"{{uppercasefirst status}}",
		"Success",
	},
	{
		drone.Build{Started: 1448127131, Finished: 1448127505},
		"{{ duration started_at finished_at }}",
		"374ns",
	},
	{
		drone.Build{Finished: 1448127505},
		`finished at {{ datetime finished_at "Mon Jan _2 15:04:05 2006" }}`,
		"finished at Sat Nov 21 11:38:25 2015",
	},
	// verify the success if / else block works
	{
		drone.Build{Status: drone.StatusSuccess},
		"{{#success status}}SUCCESS{{/success}}",
		"SUCCESS",
	},
	{
		drone.Build{Status: drone.StatusFailure},
		"{{#success status}}SUCCESS{{/success}}",
		"",
	},
	{
		drone.Build{Status: drone.StatusFailure},
		"{{#success status}}SUCCESS{{else}}NOT SUCCESS{{/success}}",
		"NOT SUCCESS",
	},
	// verify the failure if / else block works
	{
		drone.Build{Status: drone.StatusFailure},
		"{{#failure status}}FAILURE{{/failure}}",
		"FAILURE",
	},
	{
		drone.Build{Status: drone.StatusSuccess},
		"{{#failure status}}FAILURE{{/failure}}",
		"",
	},
	{
		drone.Build{Status: drone.StatusSuccess},
		"{{#failure status}}FAILURE{{else}}NOT FAILURE{{/failure}}",
		"NOT FAILURE",
	},
}

func TestTemplate(t *testing.T) {

	for _, test := range tests {
		got, err := RenderTrim(test.Input, &test.Build)
		if err != nil {
			t.Errorf("Failed rendering template %q, got error %s.", test.Input, err)
		}
		if got != test.Output {
			t.Errorf("Wanted rendered template %q, got %q", test.Output, got)
		}
	}
}
<|endoftext|>