<commit_before>// File: ./blockfreight/lib/bft.go
// Summary: Application code for Blockfreight™ | The blockchain of global freight.
// License: MIT License
// Company: Blockfreight, Inc.
// Author: Julian Nunez, Neil Tran, Julian Smith, Gian Felipe & contributors
// Site: https://blockfreight.com
// Support: <support@blockfreight.com>

// Copyright © 2017 Blockfreight, Inc. All Rights Reserved.

// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:

// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.

// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

// =================================================================================================================================================
// =================================================================================================================================================
//
// BBBBBBBBBBBb     lll                                kkk             ffff                         iii                  hhh            ttt
// BBBB``````BBBB   lll                                kkk            fff                           ```                  hhh            ttt
// BBBB      BBBB   lll      oooooo        ccccccc     kkk    kkkk  fffffff  rrr  rrr    eeeee      iii     gggggg ggg   hhh  hhhhh   tttttttt
// BBBBBBBBBBBB     lll    ooo    oooo    ccc    ccc   kkk   kkk    fffffff  rrrrrrrr eee    eeee   iii   gggg   ggggg   hhhh   hhhh  tttttttt
// BBBBBBBBBBBBBB   lll   ooo      ooo   ccc           kkkkkkk        fff    rrrr    eeeeeeeeeeeee  iii  gggg      ggg   hhh     hhh    ttt
// BBBB       BBB   lll   ooo      ooo   ccc           kkkk kkkk      fff    rrr     eeeeeeeeeeeee  iii   ggg      ggg   hhh     hhh    ttt
// BBBB      BBBB   lll   oooo    oooo   cccc    ccc   kkk   kkkk     fff    rrr      eee      eee  iii    ggg    gggg   hhh     hhh    tttt    ....
// BBBBBBBBBBBBB    lll     oooooooo       ccccccc     kkk     kkkk   fff    rrr       eeeeeeeee    iii     gggggg ggg   hhh     hhh     ttttt  ....
//                                                                                ggg      ggg
//   Blockfreight™ | The blockchain of global freight.                                                      ggggggggg
//
// =================================================================================================================================================
// =================================================================================================================================================

// Package bft implements the main functions to work with the Blockfreight™ Network.
package bft

import (
	// =======================
	// Golang Standard library
	// =======================
	"strings" // Implements simple functions to manipulate UTF-8 encoded strings.

	// ===============
	// Tendermint Core
	// ===============
	"github.com/tendermint/abci/types"
	tendermint "github.com/tendermint/go-common"
	"github.com/tendermint/go-merkle"
)

// BftApplication struct
type BftApplication struct {
	types.BaseApplication

	state merkle.Tree
}

// NewBftApplication creates a new application
func NewBftApplication() *BftApplication {
	state := merkle.NewIAVLTree(0, nil)
	return &BftApplication{state: state}
}

// Info returns information
func (app *BftApplication) Info() (resInfo types.ResponseInfo) {
	return types.ResponseInfo{Data: tendermint.Fmt("{\"size\":%v}", app.state.Size()), LastBlockAppHash: app.state.Hash(), LastBlockHeight: uint64(app.state.Height())}
}

// tx is either "key=value" or just arbitrary bytes
func (app *BftApplication) DeliverTx(tx []byte) types.Result {
	parts := strings.Split(string(tx), "=")
	if len(parts) == 2 {
		app.state.Set([]byte(parts[0]), []byte(parts[1]))
	} else {
		app.state.Set(tx, tx)
	}
	return types.OK
}

// Checktx checks a transaction
func (app *BftApplication) CheckTx(tx []byte) types.Result {
	return types.OK
}

// Commit commits transactions
func (app *BftApplication) Commit() types.Result {
	newTree := app.state.Copy()
	hash := newTree.Save()
	return types.NewResultOK(hash, "")
}

// Query executes queries and returns the result
func (app *BftApplication) Query(reqQuery types.RequestQuery) (resQuery types.ResponseQuery) {
	if reqQuery.Prove {
		value, proof, exists := app.state.Proof(reqQuery.Data)
		resQuery.Index = -1 // TODO make Proof return index
		resQuery.Key = reqQuery.Data
		resQuery.Value = value
		resQuery.Proof = proof
		if exists {
			resQuery.Log = "exists"
		} else {
			resQuery.Log = "does not exist"
		}
		return
	} else {
		index, value, exists := app.state.Get(reqQuery.Data)
		resQuery.Index = int64(index)
		resQuery.Value = value
		if exists {
			resQuery.Log = "exists"
		} else {
			resQuery.Log = "does not exist"
		}
		return
	}
}

// =================================================
// Blockfreight™ | The blockchain of global freight.
// =================================================

// BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB
// BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB
// BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB
// BBBBBBB                    BBBBBBBBBBBBBBBBBBB
// BBBBBBB                       BBBBBBBBBBBBBBBB
// BBBBBBB                        BBBBBBBBBBBBBBB
// BBBBBBB       BBBBBBBBB        BBBBBBBBBBBBBBB
// BBBBBBB       BBBBBBBBB        BBBBBBBBBBBBBBB
// BBBBBBB       BBBBBBB         BBBBBBBBBBBBBBBB
// BBBBBBB                     BBBBBBBBBBBBBBBBBB
// BBBBBBB                        BBBBBBBBBBBBBBB
// BBBBBBB       BBBBBBBBBB        BBBBBBBBBBBBBB
// BBBBBBB       BBBBBBBBBBB       BBBBBBBBBBBBBB
// BBBBBBB       BBBBBBBBBB        BBBBBBBBBBBBBB
// BBBBBBB       BBBBBBBBB        BBB       BBBBB
// BBBBBBB                       BBBB       BBBBB
// BBBBBBB                    BBBBBBB       BBBBB
// BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB
// BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB
// BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB

// ==================================================
// Blockfreight™ | The blockchain for global freight.
// ==================================================
<commit_msg>Fixing golint issues<commit_after>// File: ./blockfreight/lib/bft.go
// Summary: Application code for Blockfreight™ | The blockchain of global freight.
// License: MIT License
// Company: Blockfreight, Inc.
// Author: Julian Nunez, Neil Tran, Julian Smith, Gian Felipe & contributors
// Site: https://blockfreight.com
// Support: <support@blockfreight.com>

// Copyright © 2017 Blockfreight, Inc. All Rights Reserved.

// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:

// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.

// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

// =================================================================================================================================================
// =================================================================================================================================================
//
// BBBBBBBBBBBb     lll                                kkk             ffff                         iii                  hhh            ttt
// BBBB``````BBBB   lll                                kkk            fff                           ```                  hhh            ttt
// BBBB      BBBB   lll      oooooo        ccccccc     kkk    kkkk  fffffff  rrr  rrr    eeeee      iii     gggggg ggg   hhh  hhhhh   tttttttt
// BBBBBBBBBBBB     lll    ooo    oooo    ccc    ccc   kkk   kkk    fffffff  rrrrrrrr eee    eeee   iii   gggg   ggggg   hhhh   hhhh  tttttttt
// BBBBBBBBBBBBBB   lll   ooo      ooo   ccc           kkkkkkk        fff    rrrr    eeeeeeeeeeeee  iii  gggg      ggg   hhh     hhh    ttt
// BBBB       BBB   lll   ooo      ooo   ccc           kkkk kkkk      fff    rrr     eeeeeeeeeeeee  iii   ggg      ggg   hhh     hhh    ttt
// BBBB      BBBB   lll   oooo    oooo   cccc    ccc   kkk   kkkk     fff    rrr      eee      eee  iii    ggg    gggg   hhh     hhh    tttt    ....
// BBBBBBBBBBBBB    lll     oooooooo       ccccccc     kkk     kkkk   fff    rrr       eeeeeeeee    iii     gggggg ggg   hhh     hhh     ttttt  ....
//                                                                                ggg      ggg
//   Blockfreight™ | The blockchain of global freight.                                                      ggggggggg
//
// =================================================================================================================================================
// =================================================================================================================================================

// Package bft implements the main functions to work with the Blockfreight™ Network.
package bft

import (
	// =======================
	// Golang Standard library
	// =======================
	"strings" // Implements simple functions to manipulate UTF-8 encoded strings.

	// ===============
	// Tendermint Core
	// ===============
	"github.com/tendermint/abci/types"
	tendermint "github.com/tendermint/go-common"
	"github.com/tendermint/go-merkle"
)

// BftApplication struct
type BftApplication struct {
	types.BaseApplication

	state merkle.Tree
}

// NewBftApplication creates a new application
func NewBftApplication() *BftApplication {
	state := merkle.NewIAVLTree(0, nil)
	return &BftApplication{state: state}
}

// Info returns information
func (app *BftApplication) Info() (resInfo types.ResponseInfo) {
	return types.ResponseInfo{Data: tendermint.Fmt("{\"size\":%v}", app.state.Size()), LastBlockAppHash: app.state.Hash(), LastBlockHeight: uint64(app.state.Height())}
}

// DeliverTx delivers transactions.Transactions are either "key=value" or just arbitrary bytes
func (app *BftApplication) DeliverTx(tx []byte) types.Result {
	parts := strings.Split(string(tx), "=")
	if len(parts) == 2 {
		app.state.Set([]byte(parts[0]), []byte(parts[1]))
	} else {
		app.state.Set(tx, tx)
	}
	return types.OK
}

// CheckTx checks a transaction
func (app *BftApplication) CheckTx(tx []byte) types.Result {
	return types.OK
}

// Commit commits transactions
func (app *BftApplication) Commit() types.Result {
	newTree := app.state.Copy()
	hash := newTree.Save()
	return types.NewResultOK(hash, "")
}

// Query executes queries and returns the result
func (app *BftApplication) Query(reqQuery types.RequestQuery) (resQuery types.ResponseQuery) {
	if reqQuery.Prove {
		value, proof, exists := app.state.Proof(reqQuery.Data)
		resQuery.Index = -1 // TODO make Proof return index
		resQuery.Key = reqQuery.Data
		resQuery.Value = value
		resQuery.Proof = proof
		if exists {
			resQuery.Log = "exists"
		} else {
			resQuery.Log = "does not exist"
		}
		return
	}

	index, value, exists := app.state.Get(reqQuery.Data)
	resQuery.Index = int64(index)
	resQuery.Value = value
	if exists {
		resQuery.Log = "exists"
	} else {
		resQuery.Log = "does not exist"
	}
	return

}

// =================================================
// Blockfreight™ | The blockchain of global freight.
// =================================================

// BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB
// BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB
// BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB
// BBBBBBB                    BBBBBBBBBBBBBBBBBBB
// BBBBBBB                       BBBBBBBBBBBBBBBB
// BBBBBBB                        BBBBBBBBBBBBBBB
// BBBBBBB       BBBBBBBBB        BBBBBBBBBBBBBBB
// BBBBBBB       BBBBBBBBB        BBBBBBBBBBBBBBB
// BBBBBBB       BBBBBBB         BBBBBBBBBBBBBBBB
// BBBBBBB                     BBBBBBBBBBBBBBBBBB
// BBBBBBB                        BBBBBBBBBBBBBBB
// BBBBBBB       BBBBBBBBBB        BBBBBBBBBBBBBB
// BBBBBBB       BBBBBBBBBBB       BBBBBBBBBBBBBB
// BBBBBBB       BBBBBBBBBB        BBBBBBBBBBBBBB
// BBBBBBB       BBBBBBBBB        BBB       BBBBB
// BBBBBBB                       BBBB       BBBBB
// BBBBBBB                    BBBBBBB       BBBBB
// BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB
// BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB
// BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB

// ==================================================
// Blockfreight™ | The blockchain for global freight.
// ==================================================
<|endoftext|>


<commit_before>package html

import (
	"fmt"
	"github.com/Symantec/Dominator/lib/format"
	"io"
	"runtime"
	"syscall"
	"time"
)

var timeFormat string = "02 Jan 2006 15:04:05.99 MST"

var startTime time.Time = time.Now()

func writeHeader(writer io.Writer) {
	fmt.Fprintf(writer, "Start time: %s
\n", startTime.Format(timeFormat))
	uptime := time.Since(startTime) + time.Millisecond*50
	uptime = (uptime / time.Millisecond / 100) * time.Millisecond * 100
	fmt.Fprintf(writer, "Uptime: %s
\n", uptime)
	var rusage syscall.Rusage
	syscall.Getrusage(syscall.RUSAGE_SELF, &rusage)
	userCpuTime := time.Duration(rusage.Utime.Sec)*time.Second +
		time.Duration(rusage.Utime.Usec)*time.Microsecond
	sysCpuTime := time.Duration(rusage.Stime.Sec)*time.Second +
		time.Duration(rusage.Stime.Usec)*time.Microsecond
	cpuTime := rusage.Utime.Sec + rusage.Stime.Sec
	fmt.Fprintf(writer, "CPU Time: %.1f%% (User: %s Sys: %s)
\n",
		float64(cpuTime*100)/float64(uptime.Seconds()), userCpuTime, sysCpuTime)
	var memStatsBeforeGC, memStatsAfterGC runtime.MemStats
	runtime.ReadMemStats(&memStatsBeforeGC)
	runtime.GC()
	runtime.ReadMemStats(&memStatsAfterGC)
	fmt.Fprintf(writer, "Allocated memory: %s (%s after GC)
\n",
		format.FormatBytes(memStatsBeforeGC.Alloc),
		format.FormatBytes(memStatsAfterGC.Alloc))
	fmt.Fprintf(writer, "System memory: %s (%s after GC)
\n",
		format.FormatBytes(memStatsBeforeGC.Sys),
		format.FormatBytes(memStatsAfterGC.Sys))
}
<commit_msg>Add metrics link to standard HTML header.<commit_after>package html

import (
	"fmt"
	"github.com/Symantec/Dominator/lib/format"
	"io"
	"runtime"
	"syscall"
	"time"
)

var timeFormat string = "02 Jan 2006 15:04:05.99 MST"

var startTime time.Time = time.Now()

func writeHeader(writer io.Writer) {
	fmt.Fprintf(writer, "Start time: %s
\n", startTime.Format(timeFormat))
	uptime := time.Since(startTime) + time.Millisecond*50
	uptime = (uptime / time.Millisecond / 100) * time.Millisecond * 100
	fmt.Fprintf(writer, "Uptime: %s
\n", uptime)
	var rusage syscall.Rusage
	syscall.Getrusage(syscall.RUSAGE_SELF, &rusage)
	userCpuTime := time.Duration(rusage.Utime.Sec)*time.Second +
		time.Duration(rusage.Utime.Usec)*time.Microsecond
	sysCpuTime := time.Duration(rusage.Stime.Sec)*time.Second +
		time.Duration(rusage.Stime.Usec)*time.Microsecond
	cpuTime := rusage.Utime.Sec + rusage.Stime.Sec
	fmt.Fprintf(writer, "CPU Time: %.1f%% (User: %s Sys: %s)
\n",
		float64(cpuTime*100)/float64(uptime.Seconds()), userCpuTime, sysCpuTime)
	var memStatsBeforeGC, memStatsAfterGC runtime.MemStats
	runtime.ReadMemStats(&memStatsBeforeGC)
	runtime.GC()
	runtime.ReadMemStats(&memStatsAfterGC)
	fmt.Fprintf(writer, "Allocated memory: %s (%s after GC)
\n",
		format.FormatBytes(memStatsBeforeGC.Alloc),
		format.FormatBytes(memStatsAfterGC.Alloc))
	fmt.Fprintf(writer, "System memory: %s (%s after GC)
\n",
		format.FormatBytes(memStatsBeforeGC.Sys),
		format.FormatBytes(memStatsAfterGC.Sys))
	fmt.Fprintln(writer, "Raw metrics")
}
<|endoftext|>


<commit_before>package route

import (
	//"fmt"
	"reflect"
	"regexp"
)

func NewRoute() *Route {
	return &Route{
		Static: make(map[string]*StaticRoute),
		Regexp: make([]*RegexpRoute, 0),
	}
}

type Route struct {
	Static map[string]*StaticRoute
	Regexp []*RegexpRoute
}

//map[string]*StaticRoute
type StaticRoute struct {
	ReflectType   reflect.Type
	RequestMethod map[string]bool
	ExecuteFunc   string
}

//[]*RegexpRoute
type RegexpRoute struct {
	RouteRule     string
	Regexp        *regexp.Regexp
	StaticLength  int
	StaticPath    string
	ReflectType   reflect.Type
	RequestMethod map[string]bool
	ExecuteFunc   string
}

func (r *Route) Set(route string, execFunc string,
	reqMethod map[string]bool, refType reflect.Type) {
	routeReg := regexp.QuoteMeta(route)
	if route == routeReg {
		a := &StaticRoute{
			ReflectType:   refType,
			RequestMethod: reqMethod,
			ExecuteFunc:   execFunc,
		}
		r.Static[route] = a
	} else {
		length, staticPath, regexpInstance := r.Rego(route, routeReg)
		a := &RegexpRoute{
			RouteRule:     route,
			Regexp:        regexpInstance,
			StaticLength:  length,
			StaticPath:    staticPath,
			ReflectType:   refType,
			RequestMethod: reqMethod,
			ExecuteFunc:   execFunc,
		}
		r.Regexp = append(r.Regexp, a)
	}
}

func (r *Route) Get(reqPath string, reqMethod string) ([]reflect.Value,
	string, reflect.Type, bool) {
	if route, ok := r.Static[reqPath]; ok {
		on, ok := route.RequestMethod[reqMethod]
		if ok {
			return nil, route.ExecuteFunc, route.ReflectType, on
		}
	}
	length := len(reqPath)
	for _, route := range r.Regexp {
		if route.StaticLength >= length || reqPath[0:route.StaticLength] != route.StaticPath {
			continue
		}
		on, ok := route.RequestMethod[reqMethod]
		if !ok {
			continue
		}
		part := reqPath[route.StaticLength:]
		p := route.Regexp.FindStringSubmatch(part)
		if p[0] != part {
			continue
		}
		var args []reflect.Value
		for _, arg := range p[1:] {
			args = append(args, reflect.ValueOf(arg))
		}
		return args, route.ExecuteFunc, route.ReflectType, on
	}
	return nil, "", nil, false
}

func (r *Route) Rego(vOriginal string, vNew string) (length int, staticPath string, regexpInstance *regexp.Regexp) {
	var same []byte = make([]byte, 0)
	for k, v := range []byte(vNew) {
		if vOriginal[k] == v {
			same = append(same, v)
		} else {
			break
		}
	}
	length = len(same)
	staticPath = string(same)
	regexpInstance = regexp.MustCompile(vOriginal[length:])
	return
}
<commit_msg>fixed bug<commit_after>package route

import (
	//"fmt"
	"reflect"
	"regexp"
)

func NewRoute() *Route {
	return &Route{
		Static: make(map[string]*StaticRoute),
		Regexp: make([]*RegexpRoute, 0),
	}
}

type Route struct {
	Static map[string]*StaticRoute
	Regexp []*RegexpRoute
}

//map[string]*StaticRoute
type StaticRoute struct {
	ReflectType   reflect.Type
	RequestMethod map[string]bool
	ExecuteFunc   string
}

//[]*RegexpRoute
type RegexpRoute struct {
	RouteRule     string
	Regexp        *regexp.Regexp
	StaticLength  int
	StaticPath    string
	ReflectType   reflect.Type
	RequestMethod map[string]bool
	ExecuteFunc   string
}

func (r *Route) Set(route string, execFunc string,
	reqMethod map[string]bool, refType reflect.Type) {
	routeReg := regexp.QuoteMeta(route)
	if route == routeReg {
		a := &StaticRoute{
			ReflectType:   refType,
			RequestMethod: reqMethod,
			ExecuteFunc:   execFunc,
		}
		r.Static[route] = a
	} else {
		length, staticPath, regexpInstance := r.Rego(route, routeReg)
		a := &RegexpRoute{
			RouteRule:     route,
			Regexp:        regexpInstance,
			StaticLength:  length,
			StaticPath:    staticPath,
			ReflectType:   refType,
			RequestMethod: reqMethod,
			ExecuteFunc:   execFunc,
		}
		r.Regexp = append(r.Regexp, a)
	}
}

func (r *Route) Get(reqPath string, reqMethod string) ([]reflect.Value,
	string, reflect.Type, bool) {
	if route, ok := r.Static[reqPath]; ok {
		on, ok := route.RequestMethod[reqMethod]
		if ok {
			return nil, route.ExecuteFunc, route.ReflectType, on
		}
	}
	length := len(reqPath)
	for _, route := range r.Regexp {
		if route.StaticLength >= length || reqPath[0:route.StaticLength] != route.StaticPath {
			continue
		}
		on, ok := route.RequestMethod[reqMethod]
		if !ok {
			continue
		}
		part := reqPath[route.StaticLength:]
		p := route.Regexp.FindStringSubmatch(part)
		if len(p) < 1 || p[0] != part {
			continue
		}
		var args []reflect.Value
		for _, arg := range p[1:] {
			args = append(args, reflect.ValueOf(arg))
		}
		return args, route.ExecuteFunc, route.ReflectType, on
	}
	return nil, "", nil, false
}

func (r *Route) Rego(vOriginal string, vNew string) (length int, staticPath string, regexpInstance *regexp.Regexp) {
	var same []byte = make([]byte, 0)
	for k, v := range []byte(vNew) {
		if vOriginal[k] == v {
			same = append(same, v)
		} else {
			break
		}
	}
	length = len(same)
	staticPath = string(same)
	regexpInstance = regexp.MustCompile(vOriginal[length:])
	//println(vOriginal, staticPath, vOriginal[length:])
	return
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"fmt"
	"log"
	"os"

	"github.com/SpaceLeap/go-mavlink/mavlink"
	"github.com/ungerik/go-dry"
	"github.com/ungerik/goserial"
)

var (
	port string
	stop bool
)

func main() {
	flag.StringVar(&port, "port", "", "Serial port to connect to")
	flag.Parse()

	if port == "" && flag.NArg() == 0 {
		fmt.Fprintln(os.Stderr, "Call mavlink -port=PORT")
		flag.PrintDefaults()
		fmt.Fprintln(os.Stderr, "\nAvailable as PORT are:")
		for _, p := range goserial.ListPorts() {
			fmt.Fprintln(os.Stderr, "  ", p)
		}
		return
	}
	if port == "" {
		port = flag.Arg(0)
	}

	serialConn, err := goserial.OpenPort(&goserial.Config{Name: port, Baud: 115200})
	if err != nil {
		log.Fatal(err)
	}
	log.Println("Opened serial port", port)
	defer log.Println("Closed serial port", port, "with error", serialConn.Close())

	conn := mavlink.NewConnection(serialConn, 99)

	go func() {
		dry.WaitForStdin("Press any key to quit")
		stop = true
	}()

	for !stop {
		packet, err := conn.Receive()
		if err == nil {
			log.Println(packet)
		} else {
			log.Println(err)
		}
	}
}
<commit_msg>save debug stuff<commit_after>package main

import (
	"flag"
	"fmt"
	"log"
	"os"
	"time"

	"github.com/SpaceLeap/go-mavlink/mavlink"
	"github.com/ungerik/go-dry"
	"github.com/ungerik/goserial"
)

var (
	port      string
	quitAfter time.Duration

	stop bool
)

func main() {
	flag.StringVar(&port, "port", "COM3", "Serial port to connect to")
	flag.DurationVar(&quitAfter, "quitafter", time.Second*3, "Quit program after this duration")
	flag.Parse()

	if port == "" && flag.NArg() == 0 {
		fmt.Fprintln(os.Stderr, "Call mavlink -port=PORT")
		flag.PrintDefaults()
		fmt.Fprintln(os.Stderr, "\nAvailable as PORT are:")
		for _, p := range goserial.ListPorts() {
			fmt.Fprintln(os.Stderr, "  ", p)
		}
		return
	}
	if port == "" {
		port = flag.Arg(0)
	}

	serialConn, err := goserial.OpenPort(&goserial.Config{Name: port, Baud: 115200})
	if err != nil {
		log.Fatal(err)
	}
	log.Println("Opened serial port", port)
	defer log.Println("Closed serial port", port, "with error", serialConn.Close())

	//conn := mavlink.NewConnection(serialConn, 99)

	go func() {
		dry.WaitForStdin("Press any key to quit")
		stop = true
	}()

	time.AfterFunc(quitAfter, func() { stop = true })

	for !stop {
		packet, err := mavlink.Receive(serialConn)
		if err == nil {
			log.Println(packet)
		} else {
			log.Println(err)
		}
	}
}
<|endoftext|>


<commit_before>/*
Copyright 2020 The Knative Authors

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

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

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

package metrics

import (
	"errors"
	"fmt"
	"sort"
	"strings"
	"sync"
	"time"

	"go.opencensus.io/metric/metricdata"
	"go.opencensus.io/resource"
	"go.opencensus.io/stats"
	"go.opencensus.io/stats/view"
	"go.opencensus.io/tag"
)

type storedViews struct {
	views []*view.View
	lock  sync.Mutex
}

type meterExporter struct {
	m view.Meter    // NOTE: DO NOT RETURN THIS DIRECTLY; the view.Meter will not work for the empty Resource
	o stats.Options // Cache the option to reduce allocations
	e view.Exporter
}

// ResourceExporterFactory provides a hook for producing separate view.Exporters
// for each observed Resource. This is needed because OpenCensus support for
// Resources is a bit tacked-on rather than being a first-class component like
// Tags are.
type ResourceExporterFactory func(*resource.Resource) (view.Exporter, error)
type meters struct {
	meters  map[string]*meterExporter
	factory ResourceExporterFactory
	// Cache of Resource pointers from metricskey to Meters, to avoid
	// unnecessary stringify operations
	resourceToKey map[*resource.Resource]string
	lock          sync.Mutex
}

// Lock regime: lock allMeters before resourceViews. The critical path is in
// optionForResource, which must lock allMeters, but only needs to lock
// resourceViews if a new meter needs to be created.
var resourceViews = storedViews{}
var allMeters = meters{
	meters:        map[string]*meterExporter{"": &defaultMeter},
	resourceToKey: map[*resource.Resource]string{nil: ""},
}

// RegisterResourceView is similar to view.Register(), except that it will
// register the view across all Resources tracked by the system, rather than
// simply the default view.
func RegisterResourceView(views ...*view.View) error {
	var err error
	allMeters.lock.Lock()
	defer allMeters.lock.Unlock()
	resourceViews.lock.Lock()
	defer resourceViews.lock.Unlock()
	for _, meter := range allMeters.meters {
		// make a copy of views to avoid data races
		viewCopy := make([]*view.View, 0, len(views))
		for _, v := range views {
			c := *v
			viewCopy = append(viewCopy, &c)
		}
		if e := meter.m.Register(viewCopy...); e != nil {
			err = e
		}
	}
	if err != nil {
		return err
	}
	resourceViews.views = append(resourceViews.views, views...)
	return nil
}

// UnregisterResourceView is similar to view.Unregiste(), except that it will
// unregister the view across all Resources tracked byt he system, rather than
// simply the default view.
func UnregisterResourceView(views ...*view.View) {
	allMeters.lock.Lock()
	defer allMeters.lock.Unlock()

	resourceViews.lock.Lock()
	defer resourceViews.lock.Unlock()

	for _, meter := range allMeters.meters {
		// Since we make a defensive copy of all views in RegisterResourceView,
		// the caller might not have the same view pointer that was registered.
		// Use Meter.Find() to find the view with a matching name.
		for _, v := range views {
			name := v.Name
			if v.Name == "" {
				name = v.Measure.Name()
			}
			if v := meter.m.Find(name); v != nil {
				meter.m.Unregister(v)
			}
		}
	}

	j := 0
	for _, view := range resourceViews.views {
		toRemove := false
		for _, viewToRemove := range views {
			if view == viewToRemove {
				toRemove = true
				break
			}
		}
		if !toRemove {
			resourceViews.views[j] = view
			j++
		}
	}
	resourceViews.views = resourceViews.views[:j]
}

func setFactory(f ResourceExporterFactory) error {
	if f == nil {
		return errors.New("do not setFactory(nil)")
	}

	allMeters.lock.Lock()
	defer allMeters.lock.Unlock()

	allMeters.factory = f

	var retErr error

	for r, meter := range allMeters.meters {
		e, err := f(resourceFromKey(r))
		if err != nil {
			retErr = err
			continue // Keep trying to clean up remaining Meters.
		}
		meter.m.UnregisterExporter(meter.e)
		meter.m.RegisterExporter(e)
		meter.e = e
	}
	return retErr
}

func flushResourceExporters() {
	allMeters.lock.Lock()
	defer allMeters.lock.Unlock()

	for _, meter := range allMeters.meters {
		flushGivenExporter(meter.e)
	}
}

func meterExporterForResource(r *resource.Resource) *meterExporter {
	key, ok := allMeters.resourceToKey[r]
	if !ok {
		key = resourceToKey(r)
		allMeters.resourceToKey[r] = key
	}

	mE := allMeters.meters[key]
	if mE == nil {
		mE = &meterExporter{}
		allMeters.meters[key] = mE
	}
	if mE.o != nil {
		return mE
	}
	mE.m = view.NewMeter()
	mE.m.SetResource(r)
	mE.m.Start()
	resourceViews.lock.Lock()
	defer resourceViews.lock.Unlock()
	// make a copy of views to avoid data races
	viewsCopy := make([]*view.View, 0, len(resourceViews.views))
	for _, v := range resourceViews.views {
		c := *v
		viewsCopy = append(viewsCopy, &c)
	}
	mE.m.Register(viewsCopy...)
	mE.o = stats.WithRecorder(mE.m)
	allMeters.meters[key] = mE
	return mE
}

// optionForResource finds or creates a stats exporter for the resource, and
// returns a stats.Option indicating which meter to record to.
func optionForResource(r *resource.Resource) (stats.Options, error) {
	allMeters.lock.Lock()
	defer allMeters.lock.Unlock()

	mE := meterExporterForResource(r)
	if mE == nil {
		return nil, fmt.Errorf("failed lookup for resource %v", r)
	}

	if mE.e != nil {
		// Assume the exporter is already started.
		return mE.o, nil
	}

	if allMeters.factory == nil {
		if mE.o != nil {
			// If we can't create exporters but we have a Meter, return that.
			return mE.o, nil
		}
		return nil, fmt.Errorf("whoops, allMeters.factory is nil")
	}
	exporter, err := allMeters.factory(r)
	if err != nil {
		return nil, err
	}

	mE.m.RegisterExporter(exporter)
	mE.e = exporter
	return mE.o, nil
}

func resourceToKey(r *resource.Resource) string {
	var s strings.Builder
	l := len(r.Type)
	kvs := make([]string, 0, len(r.Labels))
	for k, v := range r.Labels {
		l += len(k) + len(v) + 2
		// We use byte values 1 and 2 to avoid colliding with valid resource labels
		// and to make unpacking easy
		kvs = append(kvs, fmt.Sprintf("\x01%s\x02%s", k, v))
	}
	s.Grow(l)
	s.WriteString(r.Type)

	sort.Strings(kvs) // Go maps are unsorted, so sort by key to produce stable output.
	for _, kv := range kvs {
		s.WriteString(kv)
	}

	return s.String()
}

func resourceFromKey(s string) *resource.Resource {
	if s == "" {
		return nil
	}
	r := &resource.Resource{Labels: map[string]string{}}
	parts := strings.Split(s, "\x01")
	r.Type = parts[0]
	for _, label := range parts[1:] {
		keyValue := strings.SplitN(label, "\x02", 2)
		r.Labels[keyValue[0]] = keyValue[1]
	}
	return r
}

// defaultMeterImpl is a pass-through to the default worker in OpenCensus.
type defaultMeterImpl struct{}

var _ view.Meter = (*defaultMeterImpl)(nil)

// defaultMeter is a custom meterExporter which passes through to the default
// worker in OpenCensus. This allows legacy code that uses OpenCensus and does
// not store a Resource in the context to continue to interoperate.
var defaultMeter = meterExporter{
	m: &defaultMeterImpl{},
	o: stats.WithRecorder(nil),
}

func (*defaultMeterImpl) Record(*tag.Map, interface{}, map[string]interface{}) {
	// using an empty option prevents this from being called
}

// Find calls view.Find
func (*defaultMeterImpl) Find(name string) *view.View {
	return view.Find(name)
}

// Register calls view.Register
func (*defaultMeterImpl) Register(views ...*view.View) error {
	return view.Register(views...)
}
func (*defaultMeterImpl) Unregister(views ...*view.View) {
	view.Unregister(views...)
}
func (*defaultMeterImpl) SetReportingPeriod(t time.Duration) {
	view.SetReportingPeriod(t)
}
func (*defaultMeterImpl) RegisterExporter(e view.Exporter) {
	view.RegisterExporter(e)
}
func (*defaultMeterImpl) UnregisterExporter(e view.Exporter) {
	view.UnregisterExporter(e)
}
func (*defaultMeterImpl) Start() {}
func (*defaultMeterImpl) Stop()  {}
func (*defaultMeterImpl) RetrieveData(viewName string) ([]*view.Row, error) {
	return view.RetrieveData(viewName)
}
func (*defaultMeterImpl) SetResource(*resource.Resource) {
}

// Read is implemented to support casting defaultMeterImpl to a metricproducer.Producer,
// but returns no values because the prometheus exporter (which is the only consumer)
// already has a built in path which collects these metrics via metricexport, which calls
// concat(x.Read() for x in metricproducer.GlobalManager.GetAll()).
func (*defaultMeterImpl) Read() []*metricdata.Metric {
	return []*metricdata.Metric{}
}
<commit_msg>Remove resourceToKey map (#1579)<commit_after>/*
Copyright 2020 The Knative Authors

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

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

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

package metrics

import (
	"errors"
	"fmt"
	"sort"
	"strings"
	"sync"
	"time"

	"go.opencensus.io/metric/metricdata"
	"go.opencensus.io/resource"
	"go.opencensus.io/stats"
	"go.opencensus.io/stats/view"
	"go.opencensus.io/tag"
)

type storedViews struct {
	views []*view.View
	lock  sync.Mutex
}

type meterExporter struct {
	m view.Meter    // NOTE: DO NOT RETURN THIS DIRECTLY; the view.Meter will not work for the empty Resource
	o stats.Options // Cache the option to reduce allocations
	e view.Exporter
}

// ResourceExporterFactory provides a hook for producing separate view.Exporters
// for each observed Resource. This is needed because OpenCensus support for
// Resources is a bit tacked-on rather than being a first-class component like
// Tags are.
type ResourceExporterFactory func(*resource.Resource) (view.Exporter, error)
type meters struct {
	meters  map[string]*meterExporter
	factory ResourceExporterFactory
	lock    sync.Mutex
}

// Lock regime: lock allMeters before resourceViews. The critical path is in
// optionForResource, which must lock allMeters, but only needs to lock
// resourceViews if a new meter needs to be created.
var resourceViews = storedViews{}
var allMeters = meters{
	meters: map[string]*meterExporter{"": &defaultMeter},
}

// RegisterResourceView is similar to view.Register(), except that it will
// register the view across all Resources tracked by the system, rather than
// simply the default view.
func RegisterResourceView(views ...*view.View) error {
	var err error
	allMeters.lock.Lock()
	defer allMeters.lock.Unlock()
	resourceViews.lock.Lock()
	defer resourceViews.lock.Unlock()
	for _, meter := range allMeters.meters {
		// make a copy of views to avoid data races
		viewCopy := make([]*view.View, 0, len(views))
		for _, v := range views {
			c := *v
			viewCopy = append(viewCopy, &c)
		}
		if e := meter.m.Register(viewCopy...); e != nil {
			err = e
		}
	}
	if err != nil {
		return err
	}
	resourceViews.views = append(resourceViews.views, views...)
	return nil
}

// UnregisterResourceView is similar to view.Unregiste(), except that it will
// unregister the view across all Resources tracked byt he system, rather than
// simply the default view.
func UnregisterResourceView(views ...*view.View) {
	allMeters.lock.Lock()
	defer allMeters.lock.Unlock()

	resourceViews.lock.Lock()
	defer resourceViews.lock.Unlock()

	for _, meter := range allMeters.meters {
		// Since we make a defensive copy of all views in RegisterResourceView,
		// the caller might not have the same view pointer that was registered.
		// Use Meter.Find() to find the view with a matching name.
		for _, v := range views {
			name := v.Name
			if v.Name == "" {
				name = v.Measure.Name()
			}
			if v := meter.m.Find(name); v != nil {
				meter.m.Unregister(v)
			}
		}
	}

	j := 0
	for _, view := range resourceViews.views {
		toRemove := false
		for _, viewToRemove := range views {
			if view == viewToRemove {
				toRemove = true
				break
			}
		}
		if !toRemove {
			resourceViews.views[j] = view
			j++
		}
	}
	resourceViews.views = resourceViews.views[:j]
}

func setFactory(f ResourceExporterFactory) error {
	if f == nil {
		return errors.New("do not setFactory(nil)")
	}

	allMeters.lock.Lock()
	defer allMeters.lock.Unlock()

	allMeters.factory = f

	var retErr error

	for r, meter := range allMeters.meters {
		e, err := f(resourceFromKey(r))
		if err != nil {
			retErr = err
			continue // Keep trying to clean up remaining Meters.
		}
		meter.m.UnregisterExporter(meter.e)
		meter.m.RegisterExporter(e)
		meter.e = e
	}
	return retErr
}

func flushResourceExporters() {
	allMeters.lock.Lock()
	defer allMeters.lock.Unlock()

	for _, meter := range allMeters.meters {
		flushGivenExporter(meter.e)
	}
}

func meterExporterForResource(r *resource.Resource) *meterExporter {
	key := resourceToKey(r)
	mE := allMeters.meters[key]
	if mE == nil {
		mE = &meterExporter{}
		allMeters.meters[key] = mE
	}
	if mE.o != nil {
		return mE
	}
	mE.m = view.NewMeter()
	mE.m.SetResource(r)
	mE.m.Start()
	resourceViews.lock.Lock()
	defer resourceViews.lock.Unlock()
	// make a copy of views to avoid data races
	viewsCopy := make([]*view.View, 0, len(resourceViews.views))
	for _, v := range resourceViews.views {
		c := *v
		viewsCopy = append(viewsCopy, &c)
	}
	mE.m.Register(viewsCopy...)
	mE.o = stats.WithRecorder(mE.m)
	allMeters.meters[key] = mE
	return mE
}

// optionForResource finds or creates a stats exporter for the resource, and
// returns a stats.Option indicating which meter to record to.
func optionForResource(r *resource.Resource) (stats.Options, error) {
	allMeters.lock.Lock()
	defer allMeters.lock.Unlock()

	mE := meterExporterForResource(r)
	if mE == nil {
		return nil, fmt.Errorf("failed lookup for resource %v", r)
	}

	if mE.e != nil {
		// Assume the exporter is already started.
		return mE.o, nil
	}

	if allMeters.factory == nil {
		if mE.o != nil {
			// If we can't create exporters but we have a Meter, return that.
			return mE.o, nil
		}
		return nil, fmt.Errorf("whoops, allMeters.factory is nil")
	}
	exporter, err := allMeters.factory(r)
	if err != nil {
		return nil, err
	}

	mE.m.RegisterExporter(exporter)
	mE.e = exporter
	return mE.o, nil
}

func resourceToKey(r *resource.Resource) string {
	if r == nil {
		return ""
	}
	var s strings.Builder
	l := len(r.Type)
	kvs := make([]string, 0, len(r.Labels))
	for k, v := range r.Labels {
		l += len(k) + len(v) + 2
		// We use byte values 1 and 2 to avoid colliding with valid resource labels
		// and to make unpacking easy
		kvs = append(kvs, fmt.Sprintf("\x01%s\x02%s", k, v))
	}
	s.Grow(l)
	s.WriteString(r.Type)

	sort.Strings(kvs) // Go maps are unsorted, so sort by key to produce stable output.
	for _, kv := range kvs {
		s.WriteString(kv)
	}

	return s.String()
}

func resourceFromKey(s string) *resource.Resource {
	if s == "" {
		return nil
	}
	r := &resource.Resource{Labels: map[string]string{}}
	parts := strings.Split(s, "\x01")
	r.Type = parts[0]
	for _, label := range parts[1:] {
		keyValue := strings.SplitN(label, "\x02", 2)
		r.Labels[keyValue[0]] = keyValue[1]
	}
	return r
}

// defaultMeterImpl is a pass-through to the default worker in OpenCensus.
type defaultMeterImpl struct{}

var _ view.Meter = (*defaultMeterImpl)(nil)

// defaultMeter is a custom meterExporter which passes through to the default
// worker in OpenCensus. This allows legacy code that uses OpenCensus and does
// not store a Resource in the context to continue to interoperate.
var defaultMeter = meterExporter{
	m: &defaultMeterImpl{},
	o: stats.WithRecorder(nil),
}

func (*defaultMeterImpl) Record(*tag.Map, interface{}, map[string]interface{}) {
	// using an empty option prevents this from being called
}

// Find calls view.Find
func (*defaultMeterImpl) Find(name string) *view.View {
	return view.Find(name)
}

// Register calls view.Register
func (*defaultMeterImpl) Register(views ...*view.View) error {
	return view.Register(views...)
}
func (*defaultMeterImpl) Unregister(views ...*view.View) {
	view.Unregister(views...)
}
func (*defaultMeterImpl) SetReportingPeriod(t time.Duration) {
	view.SetReportingPeriod(t)
}
func (*defaultMeterImpl) RegisterExporter(e view.Exporter) {
	view.RegisterExporter(e)
}
func (*defaultMeterImpl) UnregisterExporter(e view.Exporter) {
	view.UnregisterExporter(e)
}
func (*defaultMeterImpl) Start() {}
func (*defaultMeterImpl) Stop()  {}
func (*defaultMeterImpl) RetrieveData(viewName string) ([]*view.Row, error) {
	return view.RetrieveData(viewName)
}
func (*defaultMeterImpl) SetResource(*resource.Resource) {
}

// Read is implemented to support casting defaultMeterImpl to a metricproducer.Producer,
// but returns no values because the prometheus exporter (which is the only consumer)
// already has a built in path which collects these metrics via metricexport, which calls
// concat(x.Read() for x in metricproducer.GlobalManager.GetAll()).
func (*defaultMeterImpl) Read() []*metricdata.Metric {
	return []*metricdata.Metric{}
}
<|endoftext|>


<commit_before>package dao

import (
	"encoding/json"
	"errors"
	"fmt"
	resourcedmaster_storage "github.com/resourced/resourced-master/storage"
	"strings"
)

func NewHost(store resourcedmaster_storage.Storer, name string, appId string) *Host {
	h := &Host{}
	h.Name = name
	h.ApplicationId = appId
	h.store = store

	return h
}

// SaveHostByAppIdJson saves host data in JSON format with app id and hostname as keys.
func SaveHostByAppIdJson(store resourcedmaster_storage.Storer, id string, hostname string, data []byte) error {
	return store.Update(fmt.Sprintf("applications/id/%v/hosts/names/%v/record", id, hostname), data)
}

// DeleteHostByAppId delete host data in JSON format with app id and hostname as keys.
func DeleteHostByAppId(store resourcedmaster_storage.Storer, id string, hostname string) error {
	return store.Delete(fmt.Sprintf("applications/id/%v/hosts/names/%v/record", id, hostname))
}

// GetHostByAppId returns Host struct with app id and hostname as keys.
func GetHostByAppId(store resourcedmaster_storage.Storer, id string, hostname string) (*Host, error) {
	jsonBytes, err := store.Get(fmt.Sprintf("applications/id/%v/hosts/names/%v/record", id, hostname))

	h := &Host{}

	err = json.Unmarshal(jsonBytes, h)
	if err != nil {
		return nil, err
	}
	h.store = store

	return h, nil
}

// AllHosts returns a slice of all Host structs.
func AllHosts(store resourcedmaster_storage.Storer, id string) ([]*Host, error) {
	hostnamesAndData, err := store.List(fmt.Sprintf("applications/id/%v/hosts/names", id))
	if err != nil {
		return nil, err
	}

	hosts := make([]*Host, 0)

	for _, hostnameAndData := range hostnamesAndData {
		pathInChunk := strings.Split(hostnameAndData, "/")
		if len(pathInChunk) < 1 {
			continue
		}

		hostname := pathInChunk[0]

		host, err := GetHostByAppId(store, id, hostname)
		if err == nil {
			hosts = append(hosts, host)
		}
	}

	return hosts, nil
}

type Host struct {
	ApplicationId string
	Name          string
	Tags          []string
	store         resourcedmaster_storage.Storer
}

// validateBeforeSave checks various conditions before saving.
func (h *Host) validateBeforeSave() error {
	if h.ApplicationId == "" {
		return errors.New("ApplicationId must not be empty.")
	}
	if h.Name == "" {
		return errors.New("Name must not be empty.")
	}
	return nil
}

// Save host in JSON format.
func (h *Host) Save() error {
	err := h.validateBeforeSave()
	if err != nil {
		return err
	}

	jsonBytes, err := json.Marshal(h)
	if err != nil {
		return err
	}

	return SaveHostByAppIdJson(h.store, h.ApplicationId, h.Name, jsonBytes)
}

func (h *Host) Delete() error {
	return DeleteHostByAppId(h.store, h.ApplicationId, h.Name)
}
<commit_msg>I think we still want to store NetworkInterfaces.<commit_after>package dao

import (
	"encoding/json"
	"errors"
	"fmt"
	resourcedmaster_storage "github.com/resourced/resourced-master/storage"
	"strings"
)

func NewHost(store resourcedmaster_storage.Storer, name string, appId string) *Host {
	h := &Host{}
	h.Name = name
	h.ApplicationId = appId
	h.store = store

	return h
}

// SaveHostByAppIdJson saves host data in JSON format with app id and hostname as keys.
func SaveHostByAppIdJson(store resourcedmaster_storage.Storer, id string, hostname string, data []byte) error {
	return store.Update(fmt.Sprintf("applications/id/%v/hosts/names/%v/record", id, hostname), data)
}

// DeleteHostByAppId delete host data in JSON format with app id and hostname as keys.
func DeleteHostByAppId(store resourcedmaster_storage.Storer, id string, hostname string) error {
	return store.Delete(fmt.Sprintf("applications/id/%v/hosts/names/%v/record", id, hostname))
}

// GetHostByAppId returns Host struct with app id and hostname as keys.
func GetHostByAppId(store resourcedmaster_storage.Storer, id string, hostname string) (*Host, error) {
	jsonBytes, err := store.Get(fmt.Sprintf("applications/id/%v/hosts/names/%v/record", id, hostname))

	h := &Host{}

	err = json.Unmarshal(jsonBytes, h)
	if err != nil {
		return nil, err
	}
	h.store = store

	return h, nil
}

// AllHosts returns a slice of all Host structs.
func AllHosts(store resourcedmaster_storage.Storer, id string) ([]*Host, error) {
	hostnamesAndData, err := store.List(fmt.Sprintf("applications/id/%v/hosts/names", id))
	if err != nil {
		return nil, err
	}

	hosts := make([]*Host, 0)

	for _, hostnameAndData := range hostnamesAndData {
		pathInChunk := strings.Split(hostnameAndData, "/")
		if len(pathInChunk) < 1 {
			continue
		}

		hostname := pathInChunk[0]

		host, err := GetHostByAppId(store, id, hostname)
		if err == nil {
			hosts = append(hosts, host)
		}
	}

	return hosts, nil
}

type Host struct {
	ApplicationId     string
	Name              string
	Tags              []string
	NetworkInterfaces map[string]map[string]interface{}

	store resourcedmaster_storage.Storer
}

// validateBeforeSave checks various conditions before saving.
func (h *Host) validateBeforeSave() error {
	if h.ApplicationId == "" {
		return errors.New("ApplicationId must not be empty.")
	}
	if h.Name == "" {
		return errors.New("Name must not be empty.")
	}
	return nil
}

// Save host in JSON format.
func (h *Host) Save() error {
	err := h.validateBeforeSave()
	if err != nil {
		return err
	}

	jsonBytes, err := json.Marshal(h)
	if err != nil {
		return err
	}

	return SaveHostByAppIdJson(h.store, h.ApplicationId, h.Name, jsonBytes)
}

func (h *Host) Delete() error {
	return DeleteHostByAppId(h.store, h.ApplicationId, h.Name)
}
<|endoftext|>


<commit_before>// Package logging provides a simple leveled logging API

package logging

import (
	"fmt"
	"io"
	"os"
	"path/filepath"
	"runtime"
	"sync"
	"time"
)

// ISO8601 timestamp
const tsFormat = "2006-01-02T15:04:05.999-0700"

// Log levels
const (
	TRACE = iota
	DEBUG
	INFO
	WARN
	ERROR
	FATAL
	STATS
)

// Log levels are used to control the level of verbosity in the logs
type Level int

// String representations of each log level (for display)
var levelStrings = map[Level]string{
	TRACE: "TRACE",
	DEBUG: "DEBUG",
	INFO:  "INFO",
	WARN:  "WARN",
	ERROR: "ERROR",
	FATAL: "FATAL",
	STATS: "STATS",
}

func (level Level) String() string {
	highestLevel := len(levelStrings) - 1

	if level < 0 || int(level) > highestLevel {
		return "UNKNOWN"
	}

	return levelStrings[level]
}

// A Logger writes out log messages
type Logger struct {
	mu     sync.Mutex
	Name   string
	Level  Level
	Writer io.Writer
}

// Set the minimum log level
func (l *Logger) SetLevel(level Level) {
	l.Level = level
}

// Set the output destination
func (l *Logger) SetWriter(w io.Writer) {
	l.Writer = w
}

// Set the logger name
func (l *Logger) SetName(name string) {
	l.Name = name
}

// Log a message
func (l *Logger) Log(level Level, format string, v ...interface{}) {
	if level < l.Level {
		return
	}

	l.mu.Lock()
	defer l.mu.Unlock()

	buf := []byte(fmt.Sprintf("%s %s %s: %s\n", time.Now().Format(tsFormat),
		l.Name, level, fmt.Sprintf(format, v...)))

	l.Writer.Write(buf)
}

//-----------------------------------------------------------------------------
// Default logger

func newDefaultLogger() *Logger {
	// Use the filename and pid as the default name
	var name string

	_, file, _, ok := runtime.Caller(2)

	if ok {
		name = fmt.Sprintf("%s[%d]", filepath.Base(file), os.Getpid)
	}

	l := &Logger{
		Name:   name,
		Level:  TRACE,
		Writer: os.Stderr,
	}

	return l
}

var std = newDefaultLogger()

func SetLevel(level Level) {
	std.SetLevel(level)
}

func SetWriter(w io.Writer) {
	std.SetWriter(w)
}

func Stats(format string, v ...interface{}) {
	std.Log(STATS, format, v...)
}

func Fatal(format string, v ...interface{}) {
	std.Log(FATAL, format, v...)
	os.Exit(1)
}

func Error(format string, v ...interface{}) {
	std.Log(ERROR, format, v...)
}

func Warn(format string, v ...interface{}) {
	std.Log(WARN, format, v...)
}

func Info(format string, v ...interface{}) {
	std.Log(INFO, format, v...)
}

func Debug(format string, v ...interface{}) {
	std.Log(DEBUG, format, v...)
}
<commit_msg>Fixed silly bug where Getpid was not being executed<commit_after>// Package logging provides a simple leveled logging API

package logging

import (
	"fmt"
	"io"
	"os"
	"path/filepath"
	"runtime"
	"sync"
	"time"
)

// ISO8601 timestamp
const tsFormat = "2006-01-02T15:04:05.999-0700"

// Log levels
const (
	TRACE = iota
	DEBUG
	INFO
	WARN
	ERROR
	FATAL
	STATS
)

// Log levels are used to control the level of verbosity in the logs
type Level int

// String representations of each log level (for display)
var levelStrings = map[Level]string{
	TRACE: "TRACE",
	DEBUG: "DEBUG",
	INFO:  "INFO",
	WARN:  "WARN",
	ERROR: "ERROR",
	FATAL: "FATAL",
	STATS: "STATS",
}

func (level Level) String() string {
	highestLevel := len(levelStrings) - 1

	if level < 0 || int(level) > highestLevel {
		return "UNKNOWN"
	}

	return levelStrings[level]
}

// A Logger writes out log messages
type Logger struct {
	mu     sync.Mutex
	Name   string
	Level  Level
	Writer io.Writer
}

// Set the minimum log level
func (l *Logger) SetLevel(level Level) {
	l.Level = level
}

// Set the output destination
func (l *Logger) SetWriter(w io.Writer) {
	l.Writer = w
}

// Set the logger name
func (l *Logger) SetName(name string) {
	l.Name = name
}

// Log a message
func (l *Logger) Log(level Level, format string, v ...interface{}) {
	if level < l.Level {
		return
	}

	l.mu.Lock()
	defer l.mu.Unlock()

	buf := []byte(fmt.Sprintf("%s %s %s: %s\n", time.Now().Format(tsFormat),
		l.Name, level, fmt.Sprintf(format, v...)))

	l.Writer.Write(buf)
}

//-----------------------------------------------------------------------------
// Default logger

func newDefaultLogger() *Logger {
	// Use the filename and pid as the default name
	var name string

	_, file, _, ok := runtime.Caller(2)

	if ok {
		name = fmt.Sprintf("%s[%d]", filepath.Base(file), os.Getpid())
	}

	l := &Logger{
		Name:   name,
		Level:  TRACE,
		Writer: os.Stderr,
	}

	return l
}

var std = newDefaultLogger()

func SetLevel(level Level) {
	std.SetLevel(level)
}

func SetWriter(w io.Writer) {
	std.SetWriter(w)
}

func Stats(format string, v ...interface{}) {
	std.Log(STATS, format, v...)
}

func Fatal(format string, v ...interface{}) {
	std.Log(FATAL, format, v...)
	os.Exit(1)
}

func Error(format string, v ...interface{}) {
	std.Log(ERROR, format, v...)
}

func Warn(format string, v ...interface{}) {
	std.Log(WARN, format, v...)
}

func Info(format string, v ...interface{}) {
	std.Log(INFO, format, v...)
}

func Debug(format string, v ...interface{}) {
	std.Log(DEBUG, format, v...)
}
<|endoftext|>


<commit_before>package httpclient

import (
	"crypto/tls"
	"fmt"
	"io"
	"log"
	"net/http"
	"net/http/httptrace"
	"net/http/httputil"
	"os"
	"strconv"
	"time"
)

// A transport that prints request and response

type LoggingTransport struct {
	t            *http.Transport
	requestBody  bool
	responseBody bool
	timing       bool
}

func (lt *LoggingTransport) RoundTrip(req *http.Request) (resp *http.Response, err error) {
	dreq, _ := httputil.DumpRequest(req, lt.requestBody)
	//fmt.Println("REQUEST:", strconv.Quote(string(dreq)))
	fmt.Println("URL:", req.URL)
	fmt.Println("REQUEST:", string(dreq))

	for _, t := range req.TransferEncoding {
		fmt.Println("Transfer-Encoding:", t)
	}

	fmt.Println("")

	var startTime time.Time
	var elapsed time.Duration

	if lt.timing {
		startTime = time.Now()
	}

	resp, err = lt.t.RoundTrip(req)

	if lt.timing {
		elapsed = time.Since(startTime)
	}

	if err != nil {
		if lt.requestBody {
			// don't print the body twice
			dreq, _ = httputil.DumpRequest(req, false)
		}
		fmt.Println("ERROR:", err, "REQUEST:", strconv.Quote(string(dreq)))
	}
	if resp != nil {
		dresp, _ := httputil.DumpResponse(resp, lt.responseBody)
		fmt.Println("RESPONSE:", string(dresp))

		for _, t := range resp.Request.TransferEncoding {
			fmt.Println("RQ Transfer-Encoding:", t)
		}
	}

	if elapsed > 0 {
		fmt.Println("ELAPSED TIME:", elapsed.Round(time.Millisecond))
	}

	fmt.Println("")
	return
}

func (lt *LoggingTransport) CancelRequest(req *http.Request) {
	dreq, _ := httputil.DumpRequest(req, false)
	fmt.Println("CANCEL REQUEST:", strconv.Quote(string(dreq)))
	lt.t.CancelRequest(req)
}

// Enable logging requests/response headers
//
// if requestBody == true, also log request body
// if responseBody == true, also log response body
// if timing == true, also log elapsed time
func StartLogging(requestBody, responseBody, timing bool) {
	http.DefaultTransport = &LoggingTransport{&http.Transport{}, requestBody, responseBody, timing}
}

// Disable logging requests/responses
func StopLogging() {
	http.DefaultTransport = &http.Transport{}
}

// Wrap input transport into a LoggingTransport
func LoggedTransport(t *http.Transport, requestBody, responseBody, timing bool) http.RoundTripper {
	return &LoggingTransport{t, requestBody, responseBody, timing}
}

// A Reader that "logs" progress

type ProgressReader struct {
	r         io.Reader
	c         [1]byte
	threshold int
	curr      int
}

func NewProgressReader(r io.Reader, c byte, threshold int) *ProgressReader {
	if c == 0 {
		c = '.'
	}
	if threshold <= 0 {
		threshold = 10240
	}
	p := &ProgressReader{r: r, c: [1]byte{c}, threshold: threshold, curr: 0}
	return p
}

func (p *ProgressReader) Read(b []byte) (int, error) {
	n, err := p.r.Read(b)

	p.curr += n

	if err == io.EOF {
		os.Stdout.Write([]byte{'\n'})
		os.Stdout.Sync()
	} else if p.curr >= p.threshold {
		p.curr -= p.threshold

		os.Stdout.Write(p.c[:])
		os.Stdout.Sync()
	}

	return n, err
}

func (p *ProgressReader) Close() error {
	if rc, ok := p.r.(io.ReadCloser); ok {
		return rc.Close()
	} else {
		return nil
	}
}

// A Logger that can be disabled

type DebugLog bool

func (d DebugLog) Println(args ...interface{}) {
	if d {
		log.Println(args...)
	}
}

func (d DebugLog) Printf(fmt string, args ...interface{}) {
	if d {
		log.Printf(fmt, args...)
	}
}

// A ClientTrace implementation that collects request time

type RequestTrace struct {
	DNS          time.Duration
	Connect      time.Duration
	Connected    bool
	TLSHandshake time.Duration
	Request      time.Duration
	Wait         time.Duration
	Response     time.Duration

	Local  string
	Remote string

	startTime time.Time
}

func (r *RequestTrace) Reset() {
	r.DNS = 0
	r.Connect = 0
	r.Connected = false
	r.TLSHandshake = 0
	r.Request = 0
	r.Wait = 0
	r.Response = 0
}

func (r *RequestTrace) NewClientTrace(trace bool) *httptrace.ClientTrace {
	return &httptrace.ClientTrace{
		GotConn: func(info httptrace.GotConnInfo) {
			r.Connected = info.WasIdle
			r.Local = info.Conn.LocalAddr().String()
			r.Remote = info.Conn.RemoteAddr().String()

			if trace {
				log.Println("GotConn", r.Remote, "reused:", info.Reused, "wasIdle:", info.WasIdle)
			}
		},

		ConnectStart: func(network, addr string) {
			r.startTime = time.Now()

			if trace {
				log.Println("ConnectStart", network, addr)
			}
		},

		ConnectDone: func(network, addr string, err error) {
			r.Connect = time.Since(r.startTime)
			r.startTime = time.Time{}

			if trace {
				log.Println("ConnectDone", network, addr, err, r.Connect)
			}
		},

		DNSStart: func(info httptrace.DNSStartInfo) {
			r.startTime = time.Now()

			if trace {
				log.Println("DNSStart", info.Host)
			}
		},

		DNSDone: func(info httptrace.DNSDoneInfo) {
			r.DNS = time.Since(r.startTime)
			r.startTime = time.Time{}

			if trace {
				log.Println("DNSDone", info.Addrs, r.DNS)
			}
		},

		TLSHandshakeStart: func() {
			r.startTime = time.Now()

			if trace {
				log.Println("TLSHandshakeStart")
			}
		},

		TLSHandshakeDone: func(state tls.ConnectionState, err error) {
			r.TLSHandshake = time.Since(r.startTime)
			r.startTime = time.Time{}

			if trace {
				log.Println("TLSHandshakeDone", err, r.TLSHandshake)
			}
		},

		WroteHeaderField: func(string, []string) {
			if r.startTime.IsZero() {
				r.startTime = time.Now()

				if trace {
					log.Println("WroteHeader")
				}
			}
		},

		WroteRequest: func(info httptrace.WroteRequestInfo) {
			r.Request = time.Since(r.startTime)
			r.startTime = time.Now()

			if trace {
				log.Println("WroteRequest", r.Request)
			}
		},

		GotFirstResponseByte: func() {
			r.Wait = time.Since(r.startTime)
			r.startTime = time.Now()

			if trace {
				log.Println("GotFirstResponseByte", r.Wait)
			}
		},
	}
}

// Call this after the response has been received to set the Response duration
// (there is no callback for this)

func (r *RequestTrace) Done() {
	r.Response = time.Since(r.startTime)
	r.startTime = time.Now()
}

func (r *RequestTrace) String() string {
	return fmt.Sprintf("{DNS:%v, Connect:%v, Connected:%v, TLSHandshake:%v, Request:%v, Wait:%v, Response:%v}",
		r.DNS.Truncate(100*time.Microsecond),
		r.Connect.Truncate(100*time.Microsecond),
		r.Connected,
		r.TLSHandshake.Truncate(100*time.Microsecond),
		r.Request.Truncate(100*time.Microsecond),
		r.Wait.Truncate(100*time.Microsecond),
		r.Response.Truncate(100*time.Microsecond))
}
<commit_msg>http.Client.Transport is an http.RoundTripper now<commit_after>package httpclient

import (
	"crypto/tls"
	"fmt"
	"io"
	"log"
	"net/http"
	"net/http/httptrace"
	"net/http/httputil"
	"os"
	"strconv"
	"time"
)

// A transport that prints request and response

type LoggingTransport struct {
	t            http.RoundTripper
	requestBody  bool
	responseBody bool
	timing       bool
}

func (lt *LoggingTransport) RoundTrip(req *http.Request) (resp *http.Response, err error) {
	dreq, _ := httputil.DumpRequest(req, lt.requestBody)
	//fmt.Println("REQUEST:", strconv.Quote(string(dreq)))
	fmt.Println("URL:", req.URL)
	fmt.Println("REQUEST:", string(dreq))

	for _, t := range req.TransferEncoding {
		fmt.Println("Transfer-Encoding:", t)
	}

	fmt.Println("")

	var startTime time.Time
	var elapsed time.Duration

	if lt.timing {
		startTime = time.Now()
	}

	resp, err = lt.t.RoundTrip(req)

	if lt.timing {
		elapsed = time.Since(startTime)
	}

	if err != nil {
		if lt.requestBody {
			// don't print the body twice
			dreq, _ = httputil.DumpRequest(req, false)
		}
		fmt.Println("ERROR:", err, "REQUEST:", strconv.Quote(string(dreq)))
	}
	if resp != nil {
		dresp, _ := httputil.DumpResponse(resp, lt.responseBody)
		fmt.Println("RESPONSE:", string(dresp))

		for _, t := range resp.Request.TransferEncoding {
			fmt.Println("RQ Transfer-Encoding:", t)
		}
	}

	if elapsed > 0 {
		fmt.Println("ELAPSED TIME:", elapsed.Round(time.Millisecond))
	}

	fmt.Println("")
	return
}

/*
func (lt *LoggingTransport) CancelRequest(req *http.Request) {
	dreq, _ := httputil.DumpRequest(req, false)
	fmt.Println("CANCEL REQUEST:", strconv.Quote(string(dreq)))
	lt.t.CancelRequest(req)
}
*/

// Enable logging requests/response headers
//
// if requestBody == true, also log request body
// if responseBody == true, also log response body
// if timing == true, also log elapsed time
func StartLogging(requestBody, responseBody, timing bool) {
	http.DefaultTransport = &LoggingTransport{&http.Transport{}, requestBody, responseBody, timing}
}

// Disable logging requests/responses
func StopLogging() {
	http.DefaultTransport = &http.Transport{}
}

// Wrap input transport into a LoggingTransport
func LoggedTransport(t http.RoundTripper, requestBody, responseBody, timing bool) http.RoundTripper {
	return &LoggingTransport{t, requestBody, responseBody, timing}
}

// A Reader that "logs" progress

type ProgressReader struct {
	r         io.Reader
	c         [1]byte
	threshold int
	curr      int
}

func NewProgressReader(r io.Reader, c byte, threshold int) *ProgressReader {
	if c == 0 {
		c = '.'
	}
	if threshold <= 0 {
		threshold = 10240
	}
	p := &ProgressReader{r: r, c: [1]byte{c}, threshold: threshold, curr: 0}
	return p
}

func (p *ProgressReader) Read(b []byte) (int, error) {
	n, err := p.r.Read(b)

	p.curr += n

	if err == io.EOF {
		os.Stdout.Write([]byte{'\n'})
		os.Stdout.Sync()
	} else if p.curr >= p.threshold {
		p.curr -= p.threshold

		os.Stdout.Write(p.c[:])
		os.Stdout.Sync()
	}

	return n, err
}

func (p *ProgressReader) Close() error {
	if rc, ok := p.r.(io.ReadCloser); ok {
		return rc.Close()
	} else {
		return nil
	}
}

// A Logger that can be disabled

type DebugLog bool

func (d DebugLog) Println(args ...interface{}) {
	if d {
		log.Println(args...)
	}
}

func (d DebugLog) Printf(fmt string, args ...interface{}) {
	if d {
		log.Printf(fmt, args...)
	}
}

// A ClientTrace implementation that collects request time

type RequestTrace struct {
	DNS          time.Duration
	Connect      time.Duration
	Connected    bool
	TLSHandshake time.Duration
	Request      time.Duration
	Wait         time.Duration
	Response     time.Duration

	Local  string
	Remote string

	startTime time.Time
}

func (r *RequestTrace) Reset() {
	r.DNS = 0
	r.Connect = 0
	r.Connected = false
	r.TLSHandshake = 0
	r.Request = 0
	r.Wait = 0
	r.Response = 0
}

func (r *RequestTrace) NewClientTrace(trace bool) *httptrace.ClientTrace {
	return &httptrace.ClientTrace{
		GotConn: func(info httptrace.GotConnInfo) {
			r.Connected = info.WasIdle
			r.Local = info.Conn.LocalAddr().String()
			r.Remote = info.Conn.RemoteAddr().String()

			if trace {
				log.Println("GotConn", r.Remote, "reused:", info.Reused, "wasIdle:", info.WasIdle)
			}
		},

		ConnectStart: func(network, addr string) {
			r.startTime = time.Now()

			if trace {
				log.Println("ConnectStart", network, addr)
			}
		},

		ConnectDone: func(network, addr string, err error) {
			r.Connect = time.Since(r.startTime)
			r.startTime = time.Time{}

			if trace {
				log.Println("ConnectDone", network, addr, err, r.Connect)
			}
		},

		DNSStart: func(info httptrace.DNSStartInfo) {
			r.startTime = time.Now()

			if trace {
				log.Println("DNSStart", info.Host)
			}
		},

		DNSDone: func(info httptrace.DNSDoneInfo) {
			r.DNS = time.Since(r.startTime)
			r.startTime = time.Time{}

			if trace {
				log.Println("DNSDone", info.Addrs, r.DNS)
			}
		},

		TLSHandshakeStart: func() {
			r.startTime = time.Now()

			if trace {
				log.Println("TLSHandshakeStart")
			}
		},

		TLSHandshakeDone: func(state tls.ConnectionState, err error) {
			r.TLSHandshake = time.Since(r.startTime)
			r.startTime = time.Time{}

			if trace {
				log.Println("TLSHandshakeDone", err, r.TLSHandshake)
			}
		},

		WroteHeaderField: func(string, []string) {
			if r.startTime.IsZero() {
				r.startTime = time.Now()

				if trace {
					log.Println("WroteHeader")
				}
			}
		},

		WroteRequest: func(info httptrace.WroteRequestInfo) {
			r.Request = time.Since(r.startTime)
			r.startTime = time.Now()

			if trace {
				log.Println("WroteRequest", r.Request)
			}
		},

		GotFirstResponseByte: func() {
			r.Wait = time.Since(r.startTime)
			r.startTime = time.Now()

			if trace {
				log.Println("GotFirstResponseByte", r.Wait)
			}
		},
	}
}

// Call this after the response has been received to set the Response duration
// (there is no callback for this)

func (r *RequestTrace) Done() {
	r.Response = time.Since(r.startTime)
	r.startTime = time.Now()
}

func (r *RequestTrace) String() string {
	return fmt.Sprintf("{DNS:%v, Connect:%v, Connected:%v, TLSHandshake:%v, Request:%v, Wait:%v, Response:%v}",
		r.DNS.Truncate(100*time.Microsecond),
		r.Connect.Truncate(100*time.Microsecond),
		r.Connected,
		r.TLSHandshake.Truncate(100*time.Microsecond),
		r.Request.Truncate(100*time.Microsecond),
		r.Wait.Truncate(100*time.Microsecond),
		r.Response.Truncate(100*time.Microsecond))
}
<|endoftext|>


<commit_before>package main

import (
	"encoding/json"
	"fmt"
	"log"
	"strings"
	"time"
)

type logEntry interface {
	fmt.Stringer
	eventType() string
}

type authAccepted bool

func (accepted authAccepted) String() string {
	if accepted {
		return "accepted"
	}
	return "rejected"
}

type authLog struct {
	User     string       `json:"user"`
	Accepted authAccepted `json:"accepted"`
}

type noAuthLog struct {
	authLog
}

func (entry noAuthLog) String() string {
	return fmt.Sprintf("authentication for user %q without credentials %v", entry.User, entry.Accepted)
}
func (entry noAuthLog) eventType() string {
	return "no_auth"
}

type passwordAuthLog struct {
	authLog
	Password string `json:"password"`
}

func (entry passwordAuthLog) String() string {
	return fmt.Sprintf("authentication for user %q with password %q %v", entry.User, entry.Password, entry.Accepted)
}
func (entry passwordAuthLog) eventType() string {
	return "password_auth"
}

type publicKeyAuthLog struct {
	authLog
	PublicKeyFingerprint string `json:"public_key"`
}

func (entry publicKeyAuthLog) String() string {
	return fmt.Sprintf("authentication for user %q with public key %q %v", entry.User, entry.PublicKeyFingerprint, entry.Accepted)
}
func (entry publicKeyAuthLog) eventType() string {
	return "public_key_auth"
}

type keyboardInteractiveAuthLog struct {
	authLog
	Answers []string `json:"answers"`
}

func (entry keyboardInteractiveAuthLog) String() string {
	return fmt.Sprintf("authentication for user %q with keyboard interactive answers %q %v", entry.User, entry.Answers, entry.Accepted)
}
func (entry keyboardInteractiveAuthLog) eventType() string {
	return "keyboard_interactive_auth"
}

type connectionLog struct {
	ClientVersion string `json:"client_version"`
}

func (entry connectionLog) String() string {
	return fmt.Sprintf("connection with client version %q established", entry.ClientVersion)
}
func (entry connectionLog) eventType() string {
	return "connection"
}

type connectionCloseLog struct {
}

func (entry connectionCloseLog) String() string {
	return "connection closed"
}
func (entry connectionCloseLog) eventType() string {
	return "connection_close"
}

type tcpipForwardLog struct {
	Address string `json:"address"`
}

func (entry tcpipForwardLog) String() string {
	return fmt.Sprintf("TCP/IP forwarding on %v requested", entry.Address)
}
func (entry tcpipForwardLog) eventType() string {
	return "tcpip_forward"
}

type cancelTCPIPForwardLog struct {
	Address string `json:"address"`
}

func (entry cancelTCPIPForwardLog) String() string {
	return fmt.Sprintf("TCP/IP forwarding on %v canceled", entry.Address)
}
func (entry cancelTCPIPForwardLog) eventType() string {
	return "cancel_tcpip_forward"
}

type noMoreSessionsLog struct {
}

func (entry noMoreSessionsLog) String() string {
	return "rejection of further session channels requested"
}
func (entry noMoreSessionsLog) eventType() string {
	return "no_more_sessions"
}

type channelLog struct {
	ChannelID int `json:"channel_id"`
}

type sessionLog struct {
	channelLog
}

func (entry sessionLog) String() string {
	return fmt.Sprintf("[channel %v] session requested", entry.ChannelID)
}
func (entry sessionLog) eventType() string {
	return "session"
}

type sessionCloseLog struct {
	channelLog
}

func (entry sessionCloseLog) String() string {
	return fmt.Sprintf("[channel %v] closed", entry.ChannelID)
}
func (entry sessionCloseLog) eventType() string {
	return "session_close"
}

type sessionInputLog struct {
	channelLog
	Input string `json:"input"`
}

func (entry sessionInputLog) String() string {
	return fmt.Sprintf("[channel %v] input: %q", entry.ChannelID, entry.Input)
}
func (entry sessionInputLog) eventType() string {
	return "session_input"
}

type directTCPIPLog struct {
	channelLog
	From string `json:"from"`
	To   string `json:"to"`
}

func (entry directTCPIPLog) String() string {
	return fmt.Sprintf("[channel %v] direct TCP/IP forwarding from %v to %v requested", entry.ChannelID, entry.From, entry.To)
}
func (entry directTCPIPLog) eventType() string {
	return "direct_tcpip"
}

type directTCPIPCloseLog struct {
	channelLog
}

func (entry directTCPIPCloseLog) String() string {
	return fmt.Sprintf("[channel %v] closed", entry.ChannelID)
}
func (entry directTCPIPCloseLog) eventType() string {
	return "direct_tcpip_close"
}

type directTCPIPInputLog struct {
	channelLog
	Input string `json:"input"`
}

func (entry directTCPIPInputLog) String() string {
	return fmt.Sprintf("[channel %v] input: %q", entry.ChannelID, entry.Input)
}
func (entry directTCPIPInputLog) eventType() string {
	return "direct_tcpip_input"
}

type ptyLog struct {
	channelLog
	Terminal string `json:"terminal"`
	Width    uint32 `json:"width"`
	Height   uint32 `json:"height"`
}

func (entry ptyLog) String() string {
	return fmt.Sprintf("[channel %v] PTY using terminal %q (size %vx%v) requested", entry.ChannelID, entry.Terminal, entry.Width, entry.Height)
}
func (entry ptyLog) eventType() string {
	return "pty"
}

type shellLog struct {
	channelLog
}

func (entry shellLog) String() string {
	return fmt.Sprintf("[channel %v] shell requested", entry.ChannelID)
}
func (entry shellLog) eventType() string {
	return "shell"
}

type execLog struct {
	channelLog
	Command string `json:"command"`
}

func (entry execLog) String() string {
	return fmt.Sprintf("[channel %v] command %q requested", entry.ChannelID, entry.Command)
}
func (entry execLog) eventType() string {
	return "exec"
}

type subsystemLog struct {
	channelLog
	Subsystem string `json:"subsystem"`
}

func (entry subsystemLog) String() string {
	return fmt.Sprintf("[channel %v] subsystem %q requested", entry.ChannelID, entry.Subsystem)
}
func (entry subsystemLog) eventType() string {
	return "subsystem"
}

type x11Log struct {
	channelLog
	Screen uint32 `json:"screen"`
}

func (entry x11Log) String() string {
	return fmt.Sprintf("[channel %v] X11 forwarding on screen %v requested", entry.ChannelID, entry.Screen)
}
func (entry x11Log) eventType() string {
	return "x11"
}

type envLog struct {
	channelLog
	Name  string `json:"name"`
	Value string `json:"value"`
}

func (entry envLog) String() string {
	return fmt.Sprintf("[channel %v] environment variable %q with value %q requested", entry.ChannelID, entry.Name, entry.Value)
}
func (entry envLog) eventType() string {
	return "env"
}

type windowChangeLog struct {
	channelLog
	Width  uint32 `json:"width"`
	Height uint32 `json:"height"`
}

func (entry windowChangeLog) String() string {
	return fmt.Sprintf("[channel %v] window size change to %vx%v requested", entry.ChannelID, entry.Width, entry.Height)
}
func (entry windowChangeLog) eventType() string {
	return "window_change"
}

type debugGlobalRequestLog struct {
	RequestType string `json:"request_type"`
	WantReply   bool   `json:"want_reply"`
	Payload     string `json:"payload"`
}

func (entry debugGlobalRequestLog) String() string {
	jsonBytes, err := json.Marshal(entry)
	if err != nil {
		warningLogger.Printf("Failed to log event: %v", err)
		return ""
	}
	return fmt.Sprintf("DEBUG global request received: %v\n", string(jsonBytes))
}
func (entry debugGlobalRequestLog) eventType() string {
	return "debug_global_request"
}

type debugChannelLog struct {
	channelLog
	ChannelType string `json:"channel_type"`
	ExtraData   string `json:"extra_data"`
}

func (entry debugChannelLog) String() string {
	jsonBytes, err := json.Marshal(entry)
	if err != nil {
		warningLogger.Printf("Failed to log event: %v", err)
		return ""
	}
	return fmt.Sprintf("DEBUG new channel requested: %v\n", string(jsonBytes))
}
func (entry debugChannelLog) eventType() string {
	return "debug_channel"
}

type debugChannelRequestLog struct {
	channelLog
	RequestType string `json:"request_type"`
	WantReply   bool   `json:"want_reply"`
	Payload     string `json:"payload"`
}

func (entry debugChannelRequestLog) String() string {
	jsonBytes, err := json.Marshal(entry)
	if err != nil {
		warningLogger.Printf("Failed to log event: %v", err)
		return ""
	}
	return fmt.Sprintf("DEBUG channel request received: %v\n", string(jsonBytes))
}
func (entry debugChannelRequestLog) eventType() string {
	return "debug_channel_request"
}

func (context connContext) logEvent(entry logEntry) {
	if strings.HasPrefix(entry.eventType(), "debug_") && !context.cfg.Logging.Debug {
		return
	}
	if context.cfg.Logging.JSON {
		var jsonEntry interface{}
		if context.cfg.Logging.Timestamps {
			jsonEntry = struct {
				Time      string   `json:"time"`
				Source    string   `json:"source"`
				EventType string   `json:"event_type"`
				Event     logEntry `json:"event"`
			}{time.Now().Format(time.RFC3339), context.RemoteAddr().String(), entry.eventType(), entry}
		} else {
			jsonEntry = struct {
				Source    string   `json:"source"`
				EventType string   `json:"event_type"`
				Event     logEntry `json:"event"`
			}{context.RemoteAddr().String(), entry.eventType(), entry}
		}
		logBytes, err := json.Marshal(jsonEntry)
		if err != nil {
			warningLogger.Printf("Failed to log event: %v", err)
			return
		}
		log.Print(string(logBytes))
	} else {
		log.Printf("[%v] %v", context.RemoteAddr().String(), entry)
	}
}
<commit_msg>logging: Add hostKeysProveLog<commit_after>package main

import (
	"encoding/json"
	"fmt"
	"log"
	"path/filepath"
	"strings"
	"time"
)

type logEntry interface {
	fmt.Stringer
	eventType() string
}

type authAccepted bool

func (accepted authAccepted) String() string {
	if accepted {
		return "accepted"
	}
	return "rejected"
}

type authLog struct {
	User     string       `json:"user"`
	Accepted authAccepted `json:"accepted"`
}

type noAuthLog struct {
	authLog
}

func (entry noAuthLog) String() string {
	return fmt.Sprintf("authentication for user %q without credentials %v", entry.User, entry.Accepted)
}
func (entry noAuthLog) eventType() string {
	return "no_auth"
}

type passwordAuthLog struct {
	authLog
	Password string `json:"password"`
}

func (entry passwordAuthLog) String() string {
	return fmt.Sprintf("authentication for user %q with password %q %v", entry.User, entry.Password, entry.Accepted)
}
func (entry passwordAuthLog) eventType() string {
	return "password_auth"
}

type publicKeyAuthLog struct {
	authLog
	PublicKeyFingerprint string `json:"public_key"`
}

func (entry publicKeyAuthLog) String() string {
	return fmt.Sprintf("authentication for user %q with public key %q %v", entry.User, entry.PublicKeyFingerprint, entry.Accepted)
}
func (entry publicKeyAuthLog) eventType() string {
	return "public_key_auth"
}

type keyboardInteractiveAuthLog struct {
	authLog
	Answers []string `json:"answers"`
}

func (entry keyboardInteractiveAuthLog) String() string {
	return fmt.Sprintf("authentication for user %q with keyboard interactive answers %q %v", entry.User, entry.Answers, entry.Accepted)
}
func (entry keyboardInteractiveAuthLog) eventType() string {
	return "keyboard_interactive_auth"
}

type connectionLog struct {
	ClientVersion string `json:"client_version"`
}

func (entry connectionLog) String() string {
	return fmt.Sprintf("connection with client version %q established", entry.ClientVersion)
}
func (entry connectionLog) eventType() string {
	return "connection"
}

type connectionCloseLog struct {
}

func (entry connectionCloseLog) String() string {
	return "connection closed"
}
func (entry connectionCloseLog) eventType() string {
	return "connection_close"
}

type tcpipForwardLog struct {
	Address string `json:"address"`
}

func (entry tcpipForwardLog) String() string {
	return fmt.Sprintf("TCP/IP forwarding on %v requested", entry.Address)
}
func (entry tcpipForwardLog) eventType() string {
	return "tcpip_forward"
}

type cancelTCPIPForwardLog struct {
	Address string `json:"address"`
}

func (entry cancelTCPIPForwardLog) String() string {
	return fmt.Sprintf("TCP/IP forwarding on %v canceled", entry.Address)
}
func (entry cancelTCPIPForwardLog) eventType() string {
	return "cancel_tcpip_forward"
}

type noMoreSessionsLog struct {
}

func (entry noMoreSessionsLog) String() string {
	return "rejection of further session channels requested"
}
func (entry noMoreSessionsLog) eventType() string {
	return "no_more_sessions"
}

type hostKeysProveLog struct {
	HostKeyFiles []string `json:"host_key_files"`
}

func (entry hostKeysProveLog) String() string {
	baseNames := make([]string, len(entry.HostKeyFiles))
	for i, hostKeyFile := range entry.HostKeyFiles {
		baseNames[i] = fmt.Sprintf("%q", filepath.Base(hostKeyFile))
	}
	return fmt.Sprintf("proof of ownership of host keys %v requested", strings.Join(baseNames, ", "))
}
func (entry hostKeysProveLog) eventType() string {
	return "host_keys_prove"
}

type channelLog struct {
	ChannelID int `json:"channel_id"`
}

type sessionLog struct {
	channelLog
}

func (entry sessionLog) String() string {
	return fmt.Sprintf("[channel %v] session requested", entry.ChannelID)
}
func (entry sessionLog) eventType() string {
	return "session"
}

type sessionCloseLog struct {
	channelLog
}

func (entry sessionCloseLog) String() string {
	return fmt.Sprintf("[channel %v] closed", entry.ChannelID)
}
func (entry sessionCloseLog) eventType() string {
	return "session_close"
}

type sessionInputLog struct {
	channelLog
	Input string `json:"input"`
}

func (entry sessionInputLog) String() string {
	return fmt.Sprintf("[channel %v] input: %q", entry.ChannelID, entry.Input)
}
func (entry sessionInputLog) eventType() string {
	return "session_input"
}

type directTCPIPLog struct {
	channelLog
	From string `json:"from"`
	To   string `json:"to"`
}

func (entry directTCPIPLog) String() string {
	return fmt.Sprintf("[channel %v] direct TCP/IP forwarding from %v to %v requested", entry.ChannelID, entry.From, entry.To)
}
func (entry directTCPIPLog) eventType() string {
	return "direct_tcpip"
}

type directTCPIPCloseLog struct {
	channelLog
}

func (entry directTCPIPCloseLog) String() string {
	return fmt.Sprintf("[channel %v] closed", entry.ChannelID)
}
func (entry directTCPIPCloseLog) eventType() string {
	return "direct_tcpip_close"
}

type directTCPIPInputLog struct {
	channelLog
	Input string `json:"input"`
}

func (entry directTCPIPInputLog) String() string {
	return fmt.Sprintf("[channel %v] input: %q", entry.ChannelID, entry.Input)
}
func (entry directTCPIPInputLog) eventType() string {
	return "direct_tcpip_input"
}

type ptyLog struct {
	channelLog
	Terminal string `json:"terminal"`
	Width    uint32 `json:"width"`
	Height   uint32 `json:"height"`
}

func (entry ptyLog) String() string {
	return fmt.Sprintf("[channel %v] PTY using terminal %q (size %vx%v) requested", entry.ChannelID, entry.Terminal, entry.Width, entry.Height)
}
func (entry ptyLog) eventType() string {
	return "pty"
}

type shellLog struct {
	channelLog
}

func (entry shellLog) String() string {
	return fmt.Sprintf("[channel %v] shell requested", entry.ChannelID)
}
func (entry shellLog) eventType() string {
	return "shell"
}

type execLog struct {
	channelLog
	Command string `json:"command"`
}

func (entry execLog) String() string {
	return fmt.Sprintf("[channel %v] command %q requested", entry.ChannelID, entry.Command)
}
func (entry execLog) eventType() string {
	return "exec"
}

type subsystemLog struct {
	channelLog
	Subsystem string `json:"subsystem"`
}

func (entry subsystemLog) String() string {
	return fmt.Sprintf("[channel %v] subsystem %q requested", entry.ChannelID, entry.Subsystem)
}
func (entry subsystemLog) eventType() string {
	return "subsystem"
}

type x11Log struct {
	channelLog
	Screen uint32 `json:"screen"`
}

func (entry x11Log) String() string {
	return fmt.Sprintf("[channel %v] X11 forwarding on screen %v requested", entry.ChannelID, entry.Screen)
}
func (entry x11Log) eventType() string {
	return "x11"
}

type envLog struct {
	channelLog
	Name  string `json:"name"`
	Value string `json:"value"`
}

func (entry envLog) String() string {
	return fmt.Sprintf("[channel %v] environment variable %q with value %q requested", entry.ChannelID, entry.Name, entry.Value)
}
func (entry envLog) eventType() string {
	return "env"
}

type windowChangeLog struct {
	channelLog
	Width  uint32 `json:"width"`
	Height uint32 `json:"height"`
}

func (entry windowChangeLog) String() string {
	return fmt.Sprintf("[channel %v] window size change to %vx%v requested", entry.ChannelID, entry.Width, entry.Height)
}
func (entry windowChangeLog) eventType() string {
	return "window_change"
}

type debugGlobalRequestLog struct {
	RequestType string `json:"request_type"`
	WantReply   bool   `json:"want_reply"`
	Payload     string `json:"payload"`
}

func (entry debugGlobalRequestLog) String() string {
	jsonBytes, err := json.Marshal(entry)
	if err != nil {
		warningLogger.Printf("Failed to log event: %v", err)
		return ""
	}
	return fmt.Sprintf("DEBUG global request received: %v\n", string(jsonBytes))
}
func (entry debugGlobalRequestLog) eventType() string {
	return "debug_global_request"
}

type debugChannelLog struct {
	channelLog
	ChannelType string `json:"channel_type"`
	ExtraData   string `json:"extra_data"`
}

func (entry debugChannelLog) String() string {
	jsonBytes, err := json.Marshal(entry)
	if err != nil {
		warningLogger.Printf("Failed to log event: %v", err)
		return ""
	}
	return fmt.Sprintf("DEBUG new channel requested: %v\n", string(jsonBytes))
}
func (entry debugChannelLog) eventType() string {
	return "debug_channel"
}

type debugChannelRequestLog struct {
	channelLog
	RequestType string `json:"request_type"`
	WantReply   bool   `json:"want_reply"`
	Payload     string `json:"payload"`
}

func (entry debugChannelRequestLog) String() string {
	jsonBytes, err := json.Marshal(entry)
	if err != nil {
		warningLogger.Printf("Failed to log event: %v", err)
		return ""
	}
	return fmt.Sprintf("DEBUG channel request received: %v\n", string(jsonBytes))
}
func (entry debugChannelRequestLog) eventType() string {
	return "debug_channel_request"
}

func (context connContext) logEvent(entry logEntry) {
	if strings.HasPrefix(entry.eventType(), "debug_") && !context.cfg.Logging.Debug {
		return
	}
	if context.cfg.Logging.JSON {
		var jsonEntry interface{}
		if context.cfg.Logging.Timestamps {
			jsonEntry = struct {
				Time      string   `json:"time"`
				Source    string   `json:"source"`
				EventType string   `json:"event_type"`
				Event     logEntry `json:"event"`
			}{time.Now().Format(time.RFC3339), context.RemoteAddr().String(), entry.eventType(), entry}
		} else {
			jsonEntry = struct {
				Source    string   `json:"source"`
				EventType string   `json:"event_type"`
				Event     logEntry `json:"event"`
			}{context.RemoteAddr().String(), entry.eventType(), entry}
		}
		logBytes, err := json.Marshal(jsonEntry)
		if err != nil {
			warningLogger.Printf("Failed to log event: %v", err)
			return
		}
		log.Print(string(logBytes))
	} else {
		log.Printf("[%v] %v", context.RemoteAddr().String(), entry)
	}
}
<|endoftext|>


<commit_before>// Package dashboard implements a web dashboard for monitoring.
package dashboard // import "hkjn.me/dashboard"

import (
	"sync"

	"github.com/golang/glog"
	"github.com/gorilla/mux"
	"hkjn.me/config"
	"hkjn.me/googleauth"
	"hkjn.me/probes"
)

var (
	emailTemplate = `{{define "email"}}
The probe {{.Name}} failed enough that this alert fired, as the arbitrary metric of 'badness' is {{.Badness}}, which we can all agree is a big number.

The description of the probe is: “{{.Desc}}”

Failure details follow:

{{range $r := .Records.RecentFailures}}

{{$r.Timestamp}} ({{$r.Ago}})

{{$r.Details}}

{{end}}
{{end}}`
	cfg      = configT{}
	probecfg = struct {
		WebProbes []struct {
			Target, Want, Name string
			WantStatus         int
		}
		DnsProbe struct {
			Target  string
			Records struct {
				Cname string
				A     []string
				Mx    []struct {
					Host string
					Pref uint16
				}
				Ns  []string
				Txt []string
			}
		}
	}{}
	loadConfigOnce = sync.Once{}
)

// Structure of config.yaml.
type configT struct {
	loaded    bool
	Live      bool
	Version   string
	Whitelist []string
	Sendgrid  struct {
		User, Password string
	}
	Alerts struct {
		Sender, Recipient string
	}
	Service struct {
		Id, Secret string
	}
}

func (c *configT) Loaded() bool {
	return c.loaded
}

func (c *configT) Load() error {
	err := config.Load(&cfg, config.Name("config.yaml"))
	if err != nil {
		return err
	}
	glog.Infoln("successfully loaded config")
	c.loaded = true

	glog.Infoln("Starting probes..")
	for _, p := range getProbes() {
		go p.Run()
	}

	googleauth.SetCredentials(cfg.Service.Id, cfg.Service.Secret)
	googleauth.SetGatingFunc(func(gplusId string) bool {
		for _, id := range cfg.Whitelist {
			if gplusId == id {
				return true
			}
		}
		return false
	})
	probes.Config.Sendgrid = cfg.Sendgrid
	probes.Config.Template = emailTemplate
	probes.Config.Alert.Sender = cfg.Alerts.Sender
	probes.Config.Alert.Recipient = cfg.Alerts.Recipient
	return nil
}

// Start returns the HTTP routes for the dashboard.
//
// If config.yaml is missing, the dashboard will remain inactive, but
// we'll keep retrying to load it on every page request.
func Start() *mux.Router {
	config.MustLoad(&probecfg, config.Name("probes.yaml"))

	err := cfg.Load()
	if err != nil {
		glog.Warningf("couldn't load config.yaml: %v\n", err)
	}
	return newRouter()
}
<commit_msg>Update email template to use Result.Info<commit_after>// Package dashboard implements a web dashboard for monitoring.
package dashboard // import "hkjn.me/dashboard"

import (
	"sync"

	"github.com/golang/glog"
	"github.com/gorilla/mux"
	"hkjn.me/config"
	"hkjn.me/googleauth"
	"hkjn.me/probes"
)

var (
	emailTemplate = `{{define "email"}}
The probe {{.Name}} failed enough that this alert fired, as the arbitrary metric of 'badness' is {{.Badness}}, which we can all agree is a big number.

The description of the probe is: “{{.Desc}}”

Failure details follow:

{{range $r := .Records.RecentFailures}}

{{$r.Timestamp}} ({{$r.Ago}})

{{$r.Result.Info}}

{{end}}
{{end}}`
	cfg      = configT{}
	probecfg = struct {
		WebProbes []struct {
			Target, Want, Name string
			WantStatus         int
		}
		DnsProbe struct {
			Target  string
			Records struct {
				Cname string
				A     []string
				Mx    []struct {
					Host string
					Pref uint16
				}
				Ns  []string
				Txt []string
			}
		}
	}{}
	loadConfigOnce = sync.Once{}
)

// Structure of config.yaml.
type configT struct {
	loaded    bool
	Live      bool
	Version   string
	Whitelist []string
	Sendgrid  struct {
		User, Password string
	}
	Alerts struct {
		Sender, Recipient string
	}
	Service struct {
		Id, Secret string
	}
}

func (c *configT) Loaded() bool {
	return c.loaded
}

func (c *configT) Load() error {
	err := config.Load(&cfg, config.Name("config.yaml"))
	if err != nil {
		return err
	}
	glog.Infoln("successfully loaded config")
	c.loaded = true

	glog.Infoln("Starting probes..")
	for _, p := range getProbes() {
		go p.Run()
	}

	googleauth.SetCredentials(cfg.Service.Id, cfg.Service.Secret)
	googleauth.SetGatingFunc(func(gplusId string) bool {
		for _, id := range cfg.Whitelist {
			if gplusId == id {
				return true
			}
		}
		return false
	})
	probes.Config.Sendgrid = cfg.Sendgrid
	probes.Config.Template = emailTemplate
	probes.Config.Alert.Sender = cfg.Alerts.Sender
	probes.Config.Alert.Recipient = cfg.Alerts.Recipient
	return nil
}

// Start returns the HTTP routes for the dashboard.
//
// If config.yaml is missing, the dashboard will remain inactive, but
// we'll keep retrying to load it on every page request.
func Start() *mux.Router {
	config.MustLoad(&probecfg, config.Name("probes.yaml"))

	err := cfg.Load()
	if err != nil {
		glog.Warningf("couldn't load config.yaml: %v\n", err)
	}
	return newRouter()
}
<|endoftext|>


<commit_before>package env

import (
	"os"
	"strings"

	"github.com/gogolfing/config"
)

//Equal is the string around which results from os.Environ() are split into keys
//and their respective values.
const Equal = "="

//UnderscoreSeparatorKeyParser is a config.SeparatorKeyParser that parses keys
//around the "_" character.
const UnderscoreSeparatorKeyParser = config.SeparatorKeyParser("_")

type prefixParserLoader struct {
	prefix string
	parser config.KeyParser
}

//NewPrefixLowerUnderscoreLoader creates a config.Loader that
//reads in all entries from os.Environ() and inserts into the resulting Values all
//key, value associations whose keys start with prefix.
//The key inserted is parsed with UnderscoreSeparatorKeyParser after prefix is removed.
func NewPrefixLowerUnderscoreLoader(prefix string) config.Loader {
	parser := config.KeyParserFunc(func(k string) config.Key {
		return UnderscoreSeparatorKeyParser.Parse(strings.ToLower(k))
	})
	return NewPrefixParserLoader(prefix, parser)
}

//NewPrefixParserLoader creates a config.Loader that
//reads in all entries from os.Environ() and inserts into the resulting Values all
//key, value associations whose keys start with prefix.
//The key inserted is parsed with parser after prefix is removed.
func NewPrefixParserLoader(prefix string, parser config.KeyParser) config.Loader {
	return &prefixParserLoader{
		prefix: prefix,
		parser: parser,
	}
}

func (p *prefixParserLoader) Load() (*config.Values, error) {
	values := config.NewValues()
	environment := os.Environ()
	for _, envVar := range environment {
		key, value := p.loadPossibleEnvironmentVariable(envVar)
		if !key.IsEmpty() {
			values.Put(key, value)
		}
	}
	return values, nil
}

func (p *prefixParserLoader) loadPossibleEnvironmentVariable(envVar string) (config.Key, string) {
	equalIndex := strings.Index(envVar, Equal)
	if equalIndex < 0 {
		return config.Key(nil), ""
	}
	key, value := envVar[:equalIndex], envVar[equalIndex+1:]
	if !strings.HasPrefix(key, p.prefix) {
		return config.Key(nil), ""
	}
	key = strings.TrimPrefix(key, p.prefix)
	return p.parser.Parse(key), value
}
<commit_msg>Removes unused code from loaders/env.<commit_after>package env

import (
	"os"
	"strings"

	"github.com/gogolfing/config"
)

//Equal is the string around which results from os.Environ() are split into keys
//and their respective values.
const Equal = "="

//UnderscoreSeparatorKeyParser is a config.SeparatorKeyParser that parses keys
//around the "_" character.
const UnderscoreSeparatorKeyParser = config.SeparatorKeyParser("_")

type prefixParserLoader struct {
	prefix string
	parser config.KeyParser
}

//NewPrefixLowerUnderscoreLoader creates a config.Loader that
//reads in all entries from os.Environ() and inserts into the resulting Values all
//key, value associations whose keys start with prefix.
//The key inserted is parsed with UnderscoreSeparatorKeyParser after prefix is removed.
func NewPrefixLowerUnderscoreLoader(prefix string) config.Loader {
	parser := config.KeyParserFunc(func(k string) config.Key {
		return UnderscoreSeparatorKeyParser.Parse(strings.ToLower(k))
	})
	return NewPrefixParserLoader(prefix, parser)
}

//NewPrefixParserLoader creates a config.Loader that
//reads in all entries from os.Environ() and inserts into the resulting Values all
//key, value associations whose keys start with prefix.
//The key inserted is parsed with parser after prefix is removed.
func NewPrefixParserLoader(prefix string, parser config.KeyParser) config.Loader {
	return &prefixParserLoader{
		prefix: prefix,
		parser: parser,
	}
}

func (p *prefixParserLoader) Load() (*config.Values, error) {
	values := config.NewValues()
	environment := os.Environ()
	for _, envVar := range environment {
		key, value := p.loadPossibleEnvironmentVariable(envVar)
		if !key.IsEmpty() {
			values.Put(key, value)
		}
	}
	return values, nil
}

func (p *prefixParserLoader) loadPossibleEnvironmentVariable(envVar string) (config.Key, string) {
	equalIndex := strings.Index(envVar, Equal)
	key, value := envVar[:equalIndex], envVar[equalIndex+1:]
	if !strings.HasPrefix(key, p.prefix) {
		return config.Key(nil), ""
	}
	key = strings.TrimPrefix(key, p.prefix)
	return p.parser.Parse(key), value
}
<|endoftext|>


<commit_before>package model

type Model interface {
	StopAreas() StopAreas
	StopVisits() StopVisits
	VehicleJourneys() VehicleJourneys
	Lines() Lines
	Date() Date
	Reset() error
	// ...
}

type MemoryModel struct {
	stopAreas       StopAreas
	stopVisits      StopVisits
	vehicleJourneys VehicleJourneys
	lines           Lines
	date            Date
}

func NewMemoryModel() *MemoryModel {
	model := &MemoryModel{}

	stopAreas := NewMemoryStopAreas()
	stopAreas.model = model
	model.stopAreas = stopAreas

	stopVisits := NewMemoryStopVisits()
	stopVisits.model = model
	model.stopVisits = stopVisits

	vehicleJourneys := NewMemoryVehicleJourneys()
	vehicleJourneys.model = model
	model.vehicleJourneys = vehicleJourneys

	lines := NewMemoryLines()
	lines.model = model
	model.lines = lines

	model.date = NewDate(DefaultClock().Now())

	return model
}

func (model *MemoryModel) Reset() error {
	tx := NewTransaction(model)
	defer tx.Close()

	for _, vehicleJourney := range tx.Model().VehicleJourneys().FindAll() {
		tx.Model().VehicleJourneys().Delete(&vehicleJourney)
	}
	for _, stopVisit := range tx.Model().StopVisits().FindAll() {
		tx.Model().StopVisits().Delete(&stopVisit)
	}
	for _, line := range tx.Model().Lines().FindAll() {
		tx.Model().Lines().Delete(&line)
	}

	model.date = NewDate(DefaultClock().Now())
	return nil
}

func (model *MemoryModel) Date() Date {
	return model.date
}

func (model *MemoryModel) StopAreas() StopAreas {
	return model.stopAreas
}

func (model *MemoryModel) StopVisits() StopVisits {
	return model.stopVisits
}

func (model *MemoryModel) VehicleJourneys() VehicleJourneys {
	return model.vehicleJourneys
}

func (model *MemoryModel) Lines() Lines {
	return model.lines
}

func (model *MemoryModel) NewTransaction() *Transaction {
	return NewTransaction(model)
}
<commit_msg>Commit transaction in MemoryModel#Reset. Fixes model reloading. Refs #2539<commit_after>package model

type Model interface {
	StopAreas() StopAreas
	StopVisits() StopVisits
	VehicleJourneys() VehicleJourneys
	Lines() Lines
	Date() Date
	Reset() error
	// ...
}

type MemoryModel struct {
	stopAreas       StopAreas
	stopVisits      StopVisits
	vehicleJourneys VehicleJourneys
	lines           Lines
	date            Date
}

func NewMemoryModel() *MemoryModel {
	model := &MemoryModel{}

	stopAreas := NewMemoryStopAreas()
	stopAreas.model = model
	model.stopAreas = stopAreas

	stopVisits := NewMemoryStopVisits()
	stopVisits.model = model
	model.stopVisits = stopVisits

	vehicleJourneys := NewMemoryVehicleJourneys()
	vehicleJourneys.model = model
	model.vehicleJourneys = vehicleJourneys

	lines := NewMemoryLines()
	lines.model = model
	model.lines = lines

	model.date = NewDate(DefaultClock().Now())

	return model
}

func (model *MemoryModel) Reset() error {
	tx := NewTransaction(model)
	defer tx.Close()

	for _, vehicleJourney := range tx.Model().VehicleJourneys().FindAll() {
		tx.Model().VehicleJourneys().Delete(&vehicleJourney)
	}
	for _, stopVisit := range tx.Model().StopVisits().FindAll() {
		tx.Model().StopVisits().Delete(&stopVisit)
	}
	for _, line := range tx.Model().Lines().FindAll() {
		tx.Model().Lines().Delete(&line)
	}

	tx.Commit()

	model.date = NewDate(DefaultClock().Now())
	return nil
}

func (model *MemoryModel) Date() Date {
	return model.date
}

func (model *MemoryModel) StopAreas() StopAreas {
	return model.stopAreas
}

func (model *MemoryModel) StopVisits() StopVisits {
	return model.stopVisits
}

func (model *MemoryModel) VehicleJourneys() VehicleJourneys {
	return model.vehicleJourneys
}

func (model *MemoryModel) Lines() Lines {
	return model.lines
}

func (model *MemoryModel) NewTransaction() *Transaction {
	return NewTransaction(model)
}
<|endoftext|>