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

package floats

import (
	"errors"
	"math"
)

// Add returns the element-wise sum of all the slices with the
// results stored in the first slice.
// For computational efficiency, it is assumed that all of
// the variadic arguments have the same length. If this is
// in doubt, EqLen can be used.
func Add(dst []float64, slices ...[]float64) []float64 {
	if len(slices) == 0 {
		return nil
	}
	if len(dst) != len(slices[0]) {
		panic("floats: length of destination does not match length of the slices")
	}
	for _, slice := range slices {
		for j, val := range slice {
			dst[j] += val
		}
	}
	return dst
}

// AddConst adds the value c to all of the values in s
func AddConst(c float64, s []float64) {
	for i := range s {
		s[i] += c
	}
}

// ApplyFunc applies a function f (math.Exp, math.Sin, etc.) to every element
// of the slice s
func Apply(f func(float64) float64, s []float64) {
	for i, val := range s {
		s[i] = f(val)
	}
}

// Count applies the function f to every element of s and returns the number
// of times the function returned true
func Count(f func(float64) bool, s []float64) int {
	var n int
	for _, val := range s {
		if f(val) {
			n++
		}
	}
	return n
}

// Cumprod finds the cumulative product of the first i elements in
// s and puts them in place into the ith element of the
// destination. Panic will occur if lengths of do not match
func CumProd(dst, s []float64) []float64 {
	if len(dst) != len(s) {
		panic("floats: length of destination does not match length of the source")
	}
	dst[0] = s[0]
	for i := 1; i < len(s); i++ {
		dst[i] = dst[i-1] * s[i]
	}
	return dst
}

// Cumsum finds the cumulative sum of the first i elements in
// s and puts them in place into the ith element of the
// destination. Panic will occur if lengths of arguments do not match
func CumSum(dst, s []float64) []float64 {
	if len(dst) != len(s) {
		panic("floats: length of destination does not match length of the source")
	}
	dst[0] = s[0]
	for i := 1; i < len(s); i++ {
		dst[i] = dst[i-1] + s[i]
	}
	return dst
}

// Dot computes the dot product of s1 and s2, i.e.
// sum_{i = 1}^N s1[i]*s2[i]
// Panic will occur if lengths of arguments do not match
func Dot(s1, s2 []float64) float64 {
	if len(s1) != len(s2) {
		panic("floats: lengths of the slices do not match")
	}
	var sum float64
	for i, val := range s1 {
		sum += val * s2[i]
	}
	return sum
}

// Eq returns false if the slices have different lengths
// or if |s1[i] - s2[i]| > tol for any i.
func Eq(s1, s2 []float64, tol float64) bool {
	if len(s1) != len(s2) {
		return false
	}
	for i, val := range s1 {
		if math.Abs(s2[i]-val) > tol {
			return false
		}
	}
	return true
}

// Eqlen returns true if all of the slices have equal length,
// and false otherwise. Returns true if there are no input slices
func EqLen(slices ...[]float64) bool {
	// This length check is needed: http://play.golang.org/p/sdty6YiLhM
	if len(slices) == 0 {
		return true
	}
	l := len(slices[0])
	for i := 1; i < len(slices); i++ {
		if len(slices[i]) != l {
			return false
		}
	}
	return true
}

// Find applies f to every element of s and returns the first
// k elements for which the f returns true, or all such elements
// if k < 0.
// Find will reslice inds to have 0 length, and will append
// found indices to inds.
// If k > 0 and there are fewer than k elements in s satisfying f,
// all of the found elements will be returned along with an error
func Find(inds []int, f func(float64) bool, s []float64, k int) ([]int, error) {

	// inds is also returned to allow for calling with nil

	// Reslice inds to have zero length
	inds = inds[:0]

	// If zero elements requested, can just return
	if k == 0 {
		return inds, nil
	}

	// If k < 0, return all of the found indices
	if k < 0 {
		for i, val := range s {
			if f(val) {
				inds = append(inds, i)
			}
		}
		return inds, nil
	}

	// Otherwise, find the first k elements
	nFound := 0
	for i, val := range s {
		if f(val) {
			inds = append(inds, i)
			nFound++
			if nFound == k {
				return inds, nil
			}
		}
	}
	// Finished iterating over the loop, which means k elements were not found
	return inds, errors.New("floats: insufficient elements found")
}

// LogSpan returns a set of n equally spaced points in log space between,
// l and u where N is equal to len(dst). The first element of the
// resulting dst will be l and the final element of dst will be u.
// Panics if len(dst) < 2
// Note that this call will return NaNs if either l or u are negative, and
// will return all zeros if l or u is zero.
func LogSpan(dst []float64, l, u float64) []float64 {
	Span(dst, math.Log(l), math.Log(u))
	Apply(math.Exp, dst)
	return dst
}

// Logsumexp returns the log of the sum of the exponentials of the values in s
func LogSumExp(s []float64) (lse float64) {
	// Want to do this in a numerically stable way which avoids
	// overflow and underflow
	// First, find the maximum value in the slice.
	maxval, _ := Max(s)
	if math.IsInf(maxval, 0) {
		// If it's infinity either way, the logsumexp will be infinity as well
		// returning now avoids NaNs
		return maxval
	}
	// Compute the sumexp part
	for _, val := range s {
		lse += math.Exp(val - maxval)
	}
	// Take the log and add back on the constant taken out
	lse = math.Log(lse) + maxval
	return lse
}

// Max returns the maximum value in the slice and the location of
// the maximum value. If the input slice is empty, the code will panic
func Max(s []float64) (max float64, ind int) {
	max = s[0]
	ind = 0
	for i, val := range s {
		if val > max {
			max = val
			ind = i
		}
	}
	return max, ind
}

// Min returns the minimum value in the slice and the index of
// the minimum value. If the input slice is empty, zero is returned
// as the minimum value and -1 is returned as the index.
func Min(s []float64) (min float64, ind int) {
	min = s[0]
	ind = 0
	for i, val := range s {
		if val < min {
			min = val
			ind = i
		}
	}
	return min, ind
}

// Nearest returns the index of the element in s
// whose value is nearest to v.  If several such
// elements exist, the lowest index is returned
func Nearest(s []float64, v float64) (ind int) {
	dist := math.Abs(v - s[0])
	ind = 0
	for i, val := range s {
		newDist := math.Abs(v - val)
		if newDist < dist {
			dist = newDist
			ind = i
		}
	}
	return
}

// NearestInSpan return the index of a hypothetical vector created
// by Span with length n and bounds l and u whose value is closest
// to v. Assumes u > l. If the value is greater than u or less than
// l, the function will panic.
func NearestWithinSpan(n int, l, u float64, v float64) int {
	if v < l || v > u {
		panic("floats: value outside span bounds")
	}

	// Can't guarantee anything about exactly halfway between
	// because of floating point weirdness
	return int((float64(n)-1)/(u-l)*(v-l) + 0.5)
}

// Norm returns the L norm of the slice S, defined as
// (sum_{i=1}^N s[i]^N)^{1/N}
// Special cases:
// L = math.Inf(1) gives the maximum value
// Does not correctly compute the zero norm (use Count)
func Norm(s []float64, L float64) (norm float64) {
	// Should this complain if L is not positive?
	// Should this be done in log space for better numerical stability?
	//	would be more cost
	//	maybe only if L is high?
	if L == 2 {
		for _, val := range s {
			norm += val * val
		}
		return math.Pow(norm, 0.5)
	}
	if L == 1 {
		for _, val := range s {
			norm += math.Abs(val)
		}
		return norm
	}
	if math.IsInf(L, 1) {
		norm, _ = Max(s)
		return norm
	}
	for _, val := range s {
		norm += math.Pow(math.Abs(val), L)
	}
	return math.Pow(norm, 1/L)
}

// Prod returns the product of the elements of the slice
// Returns 1 if len(s) = 0
func Prod(s []float64) (prod float64) {
	prod = 1
	for _, val := range s {
		prod *= val
	}
	return prod
}

// Scale multiplies every element in s by c
func Scale(c float64, s []float64) {
	for i := range s {
		s[i] *= c
	}
}

// Span returns a set of N equally spaced points between l and u, where N
// is equal to the length of the destination. The first element of the destination
// is l, the final element of the destination is u.
// Panics if len(dst) < 2
func Span(dst []float64, l, u float64) []float64 {
	n := len(dst)
	if n < 2 {
		panic("floats: destination must have length >1")
	}
	step := (u - l) / float64(n-1)
	for i := range dst {
		dst[i] = l + step*float64(i)
	}
	return dst
}

// Sub subtracts, element-wise, the first argument from the second. Assumes
// the lengths of s and t match (can be tested with EqLen)
func Sub(s, t []float64) {
	if len(s) != len(t) {
		panic("floats: length of the slices do not match")
	}
	for i, val := range t {
		s[i] -= val
	}
}

// SubTo subtracts, element-wise, the first argument from the second and
// stores the result in dest. Panics if the lengths of s and t do not match
func SubTo(dst, s, t []float64) []float64 {
	if len(s) != len(t) {
		panic("floats: length of subtractor and subtractee do not match")
	}
	if len(dst) != len(s) {
		if dst == nil {
			dst = make([]float64, len(s))
		} else {
			panic("floats: length of destination does not match length of subtractor")
		}
	}
	for i, val := range t {
		dst[i] = s[i] - val
	}
	return dst
}

// Sum returns the sum of the elements of the slice
func Sum(s []float64) (sum float64) {
	for _, val := range s {
		sum += val
	}
	return
}
<commit_msg>Removed creation of data in SubTo<commit_after>// Copyright 2013 The Gonum Authors. All rights reserved.
// Use of this code is governed by a BSD-style
// license that can be found in the LICENSE file

package floats

import (
	"errors"
	"math"
)

// Add returns the element-wise sum of all the slices with the
// results stored in the first slice.
// For computational efficiency, it is assumed that all of
// the variadic arguments have the same length. If this is
// in doubt, EqLen can be used.
func Add(dst []float64, slices ...[]float64) []float64 {
	if len(slices) == 0 {
		return nil
	}
	if len(dst) != len(slices[0]) {
		panic("floats: length of destination does not match length of the slices")
	}
	for _, slice := range slices {
		for j, val := range slice {
			dst[j] += val
		}
	}
	return dst
}

// AddConst adds the value c to all of the values in s
func AddConst(c float64, s []float64) {
	for i := range s {
		s[i] += c
	}
}

// ApplyFunc applies a function f (math.Exp, math.Sin, etc.) to every element
// of the slice s
func Apply(f func(float64) float64, s []float64) {
	for i, val := range s {
		s[i] = f(val)
	}
}

// Count applies the function f to every element of s and returns the number
// of times the function returned true
func Count(f func(float64) bool, s []float64) int {
	var n int
	for _, val := range s {
		if f(val) {
			n++
		}
	}
	return n
}

// Cumprod finds the cumulative product of the first i elements in
// s and puts them in place into the ith element of the
// destination. Panic will occur if lengths of do not match
func CumProd(dst, s []float64) []float64 {
	if len(dst) != len(s) {
		panic("floats: length of destination does not match length of the source")
	}
	dst[0] = s[0]
	for i := 1; i < len(s); i++ {
		dst[i] = dst[i-1] * s[i]
	}
	return dst
}

// Cumsum finds the cumulative sum of the first i elements in
// s and puts them in place into the ith element of the
// destination. Panic will occur if lengths of arguments do not match
func CumSum(dst, s []float64) []float64 {
	if len(dst) != len(s) {
		panic("floats: length of destination does not match length of the source")
	}
	dst[0] = s[0]
	for i := 1; i < len(s); i++ {
		dst[i] = dst[i-1] + s[i]
	}
	return dst
}

// Dot computes the dot product of s1 and s2, i.e.
// sum_{i = 1}^N s1[i]*s2[i]
// Panic will occur if lengths of arguments do not match
func Dot(s1, s2 []float64) float64 {
	if len(s1) != len(s2) {
		panic("floats: lengths of the slices do not match")
	}
	var sum float64
	for i, val := range s1 {
		sum += val * s2[i]
	}
	return sum
}

// Eq returns false if the slices have different lengths
// or if |s1[i] - s2[i]| > tol for any i.
func Eq(s1, s2 []float64, tol float64) bool {
	if len(s1) != len(s2) {
		return false
	}
	for i, val := range s1 {
		if math.Abs(s2[i]-val) > tol {
			return false
		}
	}
	return true
}

// Eqlen returns true if all of the slices have equal length,
// and false otherwise. Returns true if there are no input slices
func EqLen(slices ...[]float64) bool {
	// This length check is needed: http://play.golang.org/p/sdty6YiLhM
	if len(slices) == 0 {
		return true
	}
	l := len(slices[0])
	for i := 1; i < len(slices); i++ {
		if len(slices[i]) != l {
			return false
		}
	}
	return true
}

// Find applies f to every element of s and returns the first
// k elements for which the f returns true, or all such elements
// if k < 0.
// Find will reslice inds to have 0 length, and will append
// found indices to inds.
// If k > 0 and there are fewer than k elements in s satisfying f,
// all of the found elements will be returned along with an error
func Find(inds []int, f func(float64) bool, s []float64, k int) ([]int, error) {

	// inds is also returned to allow for calling with nil

	// Reslice inds to have zero length
	inds = inds[:0]

	// If zero elements requested, can just return
	if k == 0 {
		return inds, nil
	}

	// If k < 0, return all of the found indices
	if k < 0 {
		for i, val := range s {
			if f(val) {
				inds = append(inds, i)
			}
		}
		return inds, nil
	}

	// Otherwise, find the first k elements
	nFound := 0
	for i, val := range s {
		if f(val) {
			inds = append(inds, i)
			nFound++
			if nFound == k {
				return inds, nil
			}
		}
	}
	// Finished iterating over the loop, which means k elements were not found
	return inds, errors.New("floats: insufficient elements found")
}

// LogSpan returns a set of n equally spaced points in log space between,
// l and u where N is equal to len(dst). The first element of the
// resulting dst will be l and the final element of dst will be u.
// Panics if len(dst) < 2
// Note that this call will return NaNs if either l or u are negative, and
// will return all zeros if l or u is zero.
func LogSpan(dst []float64, l, u float64) []float64 {
	Span(dst, math.Log(l), math.Log(u))
	Apply(math.Exp, dst)
	return dst
}

// Logsumexp returns the log of the sum of the exponentials of the values in s
func LogSumExp(s []float64) (lse float64) {
	// Want to do this in a numerically stable way which avoids
	// overflow and underflow
	// First, find the maximum value in the slice.
	maxval, _ := Max(s)
	if math.IsInf(maxval, 0) {
		// If it's infinity either way, the logsumexp will be infinity as well
		// returning now avoids NaNs
		return maxval
	}
	// Compute the sumexp part
	for _, val := range s {
		lse += math.Exp(val - maxval)
	}
	// Take the log and add back on the constant taken out
	lse = math.Log(lse) + maxval
	return lse
}

// Max returns the maximum value in the slice and the location of
// the maximum value. If the input slice is empty, the code will panic
func Max(s []float64) (max float64, ind int) {
	max = s[0]
	ind = 0
	for i, val := range s {
		if val > max {
			max = val
			ind = i
		}
	}
	return max, ind
}

// Min returns the minimum value in the slice and the index of
// the minimum value. If the input slice is empty, zero is returned
// as the minimum value and -1 is returned as the index.
func Min(s []float64) (min float64, ind int) {
	min = s[0]
	ind = 0
	for i, val := range s {
		if val < min {
			min = val
			ind = i
		}
	}
	return min, ind
}

// Nearest returns the index of the element in s
// whose value is nearest to v.  If several such
// elements exist, the lowest index is returned
func Nearest(s []float64, v float64) (ind int) {
	dist := math.Abs(v - s[0])
	ind = 0
	for i, val := range s {
		newDist := math.Abs(v - val)
		if newDist < dist {
			dist = newDist
			ind = i
		}
	}
	return
}

// NearestInSpan return the index of a hypothetical vector created
// by Span with length n and bounds l and u whose value is closest
// to v. Assumes u > l. If the value is greater than u or less than
// l, the function will panic.
func NearestWithinSpan(n int, l, u float64, v float64) int {
	if v < l || v > u {
		panic("floats: value outside span bounds")
	}

	// Can't guarantee anything about exactly halfway between
	// because of floating point weirdness
	return int((float64(n)-1)/(u-l)*(v-l) + 0.5)
}

// Norm returns the L norm of the slice S, defined as
// (sum_{i=1}^N s[i]^N)^{1/N}
// Special cases:
// L = math.Inf(1) gives the maximum value
// Does not correctly compute the zero norm (use Count)
func Norm(s []float64, L float64) (norm float64) {
	// Should this complain if L is not positive?
	// Should this be done in log space for better numerical stability?
	//	would be more cost
	//	maybe only if L is high?
	if L == 2 {
		for _, val := range s {
			norm += val * val
		}
		return math.Pow(norm, 0.5)
	}
	if L == 1 {
		for _, val := range s {
			norm += math.Abs(val)
		}
		return norm
	}
	if math.IsInf(L, 1) {
		norm, _ = Max(s)
		return norm
	}
	for _, val := range s {
		norm += math.Pow(math.Abs(val), L)
	}
	return math.Pow(norm, 1/L)
}

// Prod returns the product of the elements of the slice
// Returns 1 if len(s) = 0
func Prod(s []float64) (prod float64) {
	prod = 1
	for _, val := range s {
		prod *= val
	}
	return prod
}

// Scale multiplies every element in s by c
func Scale(c float64, s []float64) {
	for i := range s {
		s[i] *= c
	}
}

// Span returns a set of N equally spaced points between l and u, where N
// is equal to the length of the destination. The first element of the destination
// is l, the final element of the destination is u.
// Panics if len(dst) < 2
func Span(dst []float64, l, u float64) []float64 {
	n := len(dst)
	if n < 2 {
		panic("floats: destination must have length >1")
	}
	step := (u - l) / float64(n-1)
	for i := range dst {
		dst[i] = l + step*float64(i)
	}
	return dst
}

// Sub subtracts, element-wise, the first argument from the second. Assumes
// the lengths of s and t match (can be tested with EqLen)
func Sub(s, t []float64) {
	if len(s) != len(t) {
		panic("floats: length of the slices do not match")
	}
	for i, val := range t {
		s[i] -= val
	}
}

// SubTo subtracts, element-wise, the first argument from the second and
// stores the result in dest. Panics if the lengths of s and t do not match
func SubTo(dst, s, t []float64) []float64 {
	if len(s) != len(t) {
		panic("floats: length of subtractor and subtractee do not match")
	}
	if len(dst) != len(s) {
		panic("floats: length of destination does not match length of subtractor")
	}
	for i, val := range t {
		dst[i] = s[i] - val
	}
	return dst
}

// Sum returns the sum of the elements of the slice
func Sum(s []float64) (sum float64) {
	for _, val := range s {
		sum += val
	}
	return
}
<|endoftext|>


<commit_before>package main

import (
	"gopkg.in/yaml.v2"
)

// Flower struct represents a container which is exposing commands.
type Flower struct {
	Container *Container
	Path      string
}

// FlowerData struct represents a YAML file defining commands.
type FlowerData struct {
	Commands []CommandData `yaml:"commands"`
}

// CommandData struct represents a section in the YAML file defining a command.
type CommandData struct {
	Name    string           `yaml:"name"`
	Bin     string           `yaml:"bin"`
	Context string           `yaml:"context,omitempty"`
	User    string           `yaml:"user,omitempty"`
	Usage   string           `yaml:"usage,omitempty"`
	Help    string           `yaml:"help,omitempty"`
	Sub     []CommandSubData `yaml:"sub,omitempty"`
}

// CommandSubData struct represents a section in the YAML file defining
// option/value/sub-command of a command or another option/value/sub-command.
type CommandSubData struct {
	Name  string           `yaml:"name"`
	Usage string           `yaml:"usage,omitempty"`
	Help  string           `yaml:"help,omitempty"`
	Sub   []CommandSubData `yaml:"sub,omitempty"`
}

// NewFlower function instantiates a Flower.
func NewFlower(container *Container, path string) *Flower {
	return &Flower{
		Container: container,
		Path:      path,
	}
}

// Parse function retrieves data contained in a YAML file
// which path has been defined in the FLOWER_PATH
// container's environment variable.
func (flower *Flower) Parse() (*FlowerData, error) {
	command := []string{"cat", flower.Path}
	captured, err := flower.Container.Exec(command, true)
	if err != nil {
		return nil, err
	}
	flowerData := &FlowerData{}
	err = yaml.Unmarshal([]byte(captured), flowerData)
	if err != nil {
		return nil, err
	}

	return flowerData, nil
}
<commit_msg>regrouping flower.go struct into one type handler<commit_after>package main

import (
	"gopkg.in/yaml.v2"
)

type (
	// Flower struct represents a container which is exposing commands.
	Flower struct {
		Container *Container
		Path      string
	}

	// FlowerData struct represents a YAML file defining commands.
	FlowerData struct {
		Commands []CommandData `yaml:"commands"`
	}

	// CommandData struct represents a section in the YAML file defining a command.
	CommandData struct {
		Name    string           `yaml:"name"`
		Bin     string           `yaml:"bin"`
		Context string           `yaml:"context,omitempty"`
		User    string           `yaml:"user,omitempty"`
		Usage   string           `yaml:"usage,omitempty"`
		Help    string           `yaml:"help,omitempty"`
		Sub     []CommandSubData `yaml:"sub,omitempty"`
	}

	// CommandSubData struct represents a section in the YAML file defining
	// option/value/sub-command of a command or another option/value/sub-command.
	CommandSubData struct {
		Name  string           `yaml:"name"`
		Usage string           `yaml:"usage,omitempty"`
		Help  string           `yaml:"help,omitempty"`
		Sub   []CommandSubData `yaml:"sub,omitempty"`
	}
)

// NewFlower function instantiates a Flower.
func NewFlower(container *Container, path string) *Flower {
	return &Flower{
		Container: container,
		Path:      path,
	}
}

// Parse function retrieves data contained in a YAML file
// which path has been defined in the FLOWER_PATH
// container's environment variable.
func (flower *Flower) Parse() (*FlowerData, error) {
	command := []string{"cat", flower.Path}
	captured, err := flower.Container.Exec(command, true)
	if err != nil {
		return nil, err
	}
	flowerData := &FlowerData{}
	err = yaml.Unmarshal([]byte(captured), flowerData)
	if err != nil {
		return nil, err
	}

	return flowerData, nil
}
<|endoftext|>


<commit_before>package api

import (
	"net/http"

	"github.com/julienschmidt/httprouter"
	"github.com/packet-guardian/packet-guardian/src/common"
	"github.com/packet-guardian/packet-guardian/src/db"
	"github.com/packet-guardian/packet-guardian/src/models"
)

type Status struct {
	e *common.Environment
}

func NewStatusController(e *common.Environment) *Status {
	return &Status{e: e}
}

func (s *Status) GetStatus(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
	sessionUser := models.GetUserFromContext(r)

	if !sessionUser.Can(models.ViewDebugInfo) {
		w.WriteHeader(http.StatusUnauthorized)
		return
	}

	dbVer := s.e.DB.SchemaVersion()
	dbStatus := "ok"
	if dbVer != db.DBVersion {
		dbStatus = "warning"
	}

	data := map[string]interface{}{
		"database_version": dbVer,
		"database_status":  dbStatus,
		"database_type":    s.e.DB.Driver,
	}

	common.NewAPIResponse("", data).WriteResponse(w, http.StatusOK)
}
<commit_msg>Expand status api, added memory and goroutine info<commit_after>package api

import (
	"net/http"
	"runtime"
	"time"

	"github.com/julienschmidt/httprouter"
	"github.com/packet-guardian/packet-guardian/src/common"
	"github.com/packet-guardian/packet-guardian/src/db"
	"github.com/packet-guardian/packet-guardian/src/models"
)

type Status struct {
	e *common.Environment
}

type StatusResp struct {
	Database   *DatabaseStatusResp  `json:"database"`
	GoRoutines *GoRoutineStatusResp `json:"go_routines"`
	Memory     *MemoryStatusResp    `json:"memory"`
}

type DatabaseStatusResp struct {
	DatabaseVersion int    `json:"database_version"`
	DatabaseStatus  string `json:"database_status"`
	DatabaseType    string `json:"database_type"`
}

type GoRoutineStatusResp struct {
	RoutineNum int `json:"routine_num"`
}

type MemoryStatusResp struct {
	Alloc        uint64 `json:"alloc"`
	TotalAlloc   uint64 `json:"total_alloc"`
	Sys          uint64 `json:"sys"`
	Mallocs      uint64 `json:"mallocs"`
	Frees        uint64 `json:"frees"`
	PauseTotalNs uint64 `json:"pause_total_ns"`
	NumGC        uint32 `json:"num_gc"`
	HeapObjects  uint64 `json:"head_objects"`
	LastGC       string `json:"last_gc"`
}

func NewStatusController(e *common.Environment) *Status {
	return &Status{e: e}
}

func (s *Status) GetStatus(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
	sessionUser := models.GetUserFromContext(r)

	if !sessionUser.Can(models.ViewDebugInfo) {
		w.WriteHeader(http.StatusUnauthorized)
		return
	}

	data := &StatusResp{
		Database:   s.databaseStatus(),
		GoRoutines: s.goRoutineStatus(),
		Memory:     s.memoryStatus(),
	}

	common.NewAPIResponse("", data).WriteResponse(w, http.StatusOK)
}

func (s *Status) databaseStatus() *DatabaseStatusResp {
	dbVer := s.e.DB.SchemaVersion()
	dbStatus := "ok"
	if dbVer != db.DBVersion {
		dbStatus = "warning"
	}

	return &DatabaseStatusResp{
		DatabaseVersion: dbVer,
		DatabaseStatus:  dbStatus,
		DatabaseType:    s.e.DB.Driver,
	}
}

func (s *Status) goRoutineStatus() *GoRoutineStatusResp {
	return &GoRoutineStatusResp{
		RoutineNum: runtime.NumGoroutine(),
	}
}

func (s *Status) memoryStatus() *MemoryStatusResp {
	m := &runtime.MemStats{}
	runtime.ReadMemStats(m)

	return &MemoryStatusResp{
		Alloc:        m.Alloc,
		TotalAlloc:   m.TotalAlloc,
		Sys:          m.Sys,
		Mallocs:      m.Mallocs,
		Frees:        m.Frees,
		PauseTotalNs: m.PauseTotalNs,
		NumGC:        m.NumGC,
		HeapObjects:  m.HeapObjects,
		LastGC:       time.Unix(0, int64(m.LastGC)).Format(time.RFC3339),
	}
}
<|endoftext|>


<commit_before>package raft

import (
	"bufio"
	"bytes"
	"encoding/json"
	"fmt"
	"hash"
	"hash/crc64"
	"io"
	"io/ioutil"
	"log"
	"os"
	"path/filepath"
	"sort"
	"strings"
	"time"
)

const (
	testPath      = "permTest"
	snapPath      = "snapshots"
	metaFilePath  = "meta.json"
	stateFilePath = "state.bin"
	tmpSuffix     = ".tmp"
)

// FileSnapshotStore implements the SnapshotStore interface and allows
// snapshots to be made on the local disk.
type FileSnapshotStore struct {
	path   string
	retain int
	logger *log.Logger
}

type snapMetaSlice []*fileSnapshotMeta

// Implements the SnapshotSink
type FileSnapshotSink struct {
	store  *FileSnapshotStore
	logger *log.Logger
	dir    string
	meta   fileSnapshotMeta

	stateFile *os.File
	stateHash hash.Hash64
	buffered  *bufio.Writer

	closed bool
}

// fileSnapshotMeta is stored on disk. We also put a CRC
// on disk so that we can verify the snapshot
type fileSnapshotMeta struct {
	SnapshotMeta
	CRC []byte
}

// bufferedFile is returned when we open a snapshot. This way
// reads are buffered and the file still gets closed.
type bufferedFile struct {
	bh *bufio.Reader
	fh *os.File
}

func (b *bufferedFile) Read(p []byte) (n int, err error) {
	return b.bh.Read(p)
}

func (b *bufferedFile) Close() error {
	return b.fh.Close()
}

// NewFileSnapshotStore creates a new FileSnapshotStore based
// on a base directory. The `retain` parameter controls how many
// snapshots are retained. Must be at least 1.
func NewFileSnapshotStore(base string, retain int, logOutput io.Writer) (*FileSnapshotStore, error) {
	if retain < 1 {
		return nil, fmt.Errorf("must retain at least one snapshot")
	}
	if logOutput == nil {
		logOutput = os.Stderr
	}

	// Ensure our path exists
	path := filepath.Join(base, snapPath)
	if err := os.Mkdir(path, 0755); err != nil && !os.IsExist(err) {
		return nil, fmt.Errorf("snapshot path not accessible: %v", err)
	}

	// Setup the store
	store := &FileSnapshotStore{
		path:   path,
		retain: retain,
		logger: log.New(logOutput, "", log.LstdFlags),
	}

	// Do a permissions test
	if err := store.testPermissions(); err != nil {
		return nil, fmt.Errorf("permissions test failed: %v", err)
	}
	return store, nil
}

// testPermissions tries to touch a file in our path to see if it works
func (f *FileSnapshotStore) testPermissions() error {
	path := filepath.Join(f.path, testPath)
	fh, err := os.Create(path)
	if err != nil {
		return err
	}
	fh.Close()
	os.Remove(path)
	return nil
}

// snapshotName generate s name for the snapshot
func snapshotName(term, index uint64) string {
	return fmt.Sprintf("%d-%d-%s", term, index, time.Now().Format(time.RFC3339Nano))
}

// parseName parse the components of a name
func parseName(name string) (uint64, uint64, time.Time, error) {
	var term, index uint64
	var timeString string
	if _, err := fmt.Sscanf(name, "%d-%d-%s", &term, &index, &timeString); err != nil {
		return 0, 0, time.Time{}, err
	}
	when, err := time.Parse(time.RFC3339Nano, timeString)
	if err != nil {
		return 0, 0, time.Time{}, err
	}
	return term, index, when, nil
}

// Create is used to start a new snapshot
func (f *FileSnapshotStore) Create(index, term uint64, peers []byte) (SnapshotSink, error) {
	// Create a new path
	name := snapshotName(term, index)
	path := filepath.Join(f.path, name+tmpSuffix)
	f.logger.Printf("[INFO] snapshot: Creating new snapshot at %s", path)

	// Make the directory
	if err := os.Mkdir(path, 0755); err != nil {
		f.logger.Printf("[ERR] snapshot: Failed to make snapshot directory: %v", err)
		return nil, err
	}

	// Create the sink
	sink := &FileSnapshotSink{
		store:  f,
		logger: f.logger,
		dir:    path,
		meta: fileSnapshotMeta{
			SnapshotMeta: SnapshotMeta{
				ID:    name,
				Index: index,
				Term:  term,
				Peers: peers,
			},
			CRC: nil,
		},
	}

	// Write out the meta data
	if err := sink.writeMeta(); err != nil {
		f.logger.Printf("[ERR] snapshot: Failed to write metadata: %v", err)
		return nil, err
	}

	// Open the state file
	statePath := filepath.Join(path, stateFilePath)
	fh, err := os.Create(statePath)
	if err != nil {
		f.logger.Printf("[ERR] snapshot: Failed to create state file: %v", err)
		return nil, err
	}
	sink.stateFile = fh

	// Create a CRC64 hash
	sink.stateHash = crc64.New(crc64.MakeTable(crc64.ECMA))

	// Wrap both the hash and file in a MultiWriter with buffering
	multi := io.MultiWriter(sink.stateFile, sink.stateHash)
	sink.buffered = bufio.NewWriter(multi)

	// Done
	return sink, nil
}

func (f *FileSnapshotStore) List() ([]*SnapshotMeta, error) {
	// Get the eligible snapshots
	snapshots, err := f.getSnapshots()
	if err != nil {
		f.logger.Printf("[ERR] snapshot: Failed to get snapshots: %v", err)
		return nil, err
	}

	var snapMeta []*SnapshotMeta
	for _, meta := range snapshots {
		snapMeta = append(snapMeta, &meta.SnapshotMeta)
		if len(snapMeta) == f.retain {
			break
		}
	}
	return snapMeta, nil
}

// getSnapshots returns all the known snapshots
func (f *FileSnapshotStore) getSnapshots() ([]*fileSnapshotMeta, error) {
	// Get the eligible snapshots
	snapshots, err := ioutil.ReadDir(f.path)
	if err != nil {
		f.logger.Printf("[ERR] snapshot: Failed to scan snapshot dir: %v", err)
		return nil, err
	}

	// Populate the metadata, reverse order (newest first)
	var snapMeta []*fileSnapshotMeta
	for _, snap := range snapshots {
		// Ignore any files
		if !snap.IsDir() {
			continue
		}

		// Ignore any temporary snapshots
		dirName := snap.Name()
		if strings.HasSuffix(dirName, tmpSuffix) {
			f.logger.Printf("[WARN] snapshot: Found temporary snapshot: %v", dirName)
			continue
		}

		// Try to read the meta data
		meta, err := f.readMeta(dirName)
		if err != nil {
			f.logger.Printf("[WARN] snapshot: Failed to read metadata for %v: %v", dirName, err)
			continue
		}

		// Append, but only return up to the retain count
		snapMeta = append(snapMeta, meta)
	}

	// Sort the snapshot, reverse so we get new -> old
	sort.Sort(sort.Reverse(snapMetaSlice(snapMeta)))

	return snapMeta, nil
}

// readMeta is used to read the meta data for a given named backup
func (f *FileSnapshotStore) readMeta(name string) (*fileSnapshotMeta, error) {
	// Open the meta file
	metaPath := filepath.Join(f.path, name, metaFilePath)
	fh, err := os.Open(metaPath)
	if err != nil {
		return nil, err
	}
	defer fh.Close()

	// Buffer the file IO
	buffered := bufio.NewReader(fh)

	// Read in the JSON
	meta := &fileSnapshotMeta{}
	dec := json.NewDecoder(buffered)
	if err := dec.Decode(meta); err != nil {
		return nil, err
	}
	return meta, nil
}

func (f *FileSnapshotStore) Open(id string) (*SnapshotMeta, io.ReadCloser, error) {
	// Get the metadata
	meta, err := f.readMeta(id)
	if err != nil {
		f.logger.Printf("[ERR] snapshot: Failed to get meta data to open snapshot: %v", err)
		return nil, nil, err
	}

	// Open the state file
	statePath := filepath.Join(f.path, id, stateFilePath)
	fh, err := os.Open(statePath)
	if err != nil {
		f.logger.Printf("[ERR] snapshot: Failed to open state file: %v", err)
		return nil, nil, err
	}

	// Create a CRC64 hash
	stateHash := crc64.New(crc64.MakeTable(crc64.ECMA))

	// Compute the hash
	_, err = io.Copy(stateHash, fh)
	if err != nil {
		f.logger.Printf("[ERR] snapshot: Failed to read state file: %v", err)
		fh.Close()
		return nil, nil, err
	}

	// Verify the hash
	computed := stateHash.Sum(nil)
	if bytes.Compare(meta.CRC, computed) != 0 {
		f.logger.Printf("[ERR] snapshot: CRC checksum failed (stored: %v computed: %v)",
			meta.CRC, computed)
		fh.Close()
		return nil, nil, fmt.Errorf("CRC mismatch")
	}

	// Seek to the start
	if _, err := fh.Seek(0, 0); err != nil {
		f.logger.Printf("[ERR] snapshot: State file seek failed: %v", err)
		fh.Close()
		return nil, nil, err
	}

	// Return a buffered file
	buffered := &bufferedFile{
		bh: bufio.NewReader(fh),
		fh: fh,
	}

	return &meta.SnapshotMeta, buffered, nil
}

// Used to reap any snapshots beyond the retain count
func (f *FileSnapshotStore) ReapSnapshots() error {
	snapshots, err := f.getSnapshots()
	if err != nil {
		f.logger.Printf("[ERR] snapshot: Failed to get snapshots: %v", err)
		return err
	}

	for i := f.retain; i < len(snapshots); i++ {
		path := filepath.Join(f.path, snapshots[i].ID)
		f.logger.Printf("[INFO] snapshot: reaping snapshot %v", path)
		if err := os.RemoveAll(path); err != nil {
			f.logger.Printf("[ERR] snapshot: Failed to reap snapshot %v: %v", path, err)
			return err
		}
	}
	return nil
}

// ID returns the ID of the snapshot, can be used with Open()
// after the snapshot is finalized.
func (s *FileSnapshotSink) ID() string {
	return s.meta.ID
}

// Write is used to append to the state file. We write to the
// buffered IO object to reduce the amount of context switches
func (s *FileSnapshotSink) Write(b []byte) (int, error) {
	return s.buffered.Write(b)
}

// Close is used to indicate a successful end
func (s *FileSnapshotSink) Close() error {
	// Make sure close is idempotent
	if s.closed {
		return nil
	}
	s.closed = true

	// Close the open handles
	if err := s.finalize(); err != nil {
		s.logger.Printf("[ERR] snapshot: Failed to finalize snapshot: %v", err)
		return err
	}

	// Write out the meta data
	if err := s.writeMeta(); err != nil {
		s.logger.Printf("[ERR] snapshot: Failed to write metadata: %v", err)
		return err
	}

	// Move the directory into place
	newPath := strings.TrimSuffix(s.dir, tmpSuffix)
	if err := os.Rename(s.dir, newPath); err != nil {
		s.logger.Printf("[ERR] snapshot: Failed to move snapshot into place: %v", err)
		return err
	}

	// Reap any old snapshots
	s.store.ReapSnapshots()
	return nil
}

// Cancel is used to indicate an unsuccessful end
func (s *FileSnapshotSink) Cancel() error {
	// Make sure close is idempotent
	if s.closed {
		return nil
	}
	s.closed = true

	// Close the open handles
	if err := s.finalize(); err != nil {
		s.logger.Printf("[ERR] snapshot: Failed to finalize snapshot: %v", err)
		return err
	}

	// Attempt to remove all artifacts
	return os.RemoveAll(s.dir)
}

// finalize is used to close all of our resources
func (s *FileSnapshotSink) finalize() error {
	// Flush any remaining data
	if err := s.buffered.Flush(); err != nil {
		return err
	}

	// Get the file size
	stat, statErr := s.stateFile.Stat()

	// Close the file
	if err := s.stateFile.Close(); err != nil {
		return err
	}

	// Set the file size, check after we close
	if statErr != nil {
		return statErr
	}
	s.meta.Size = stat.Size()

	// Set the CRC
	s.meta.CRC = s.stateHash.Sum(nil)
	return nil
}

// writeMeta is used to write out the metadata we have
func (s *FileSnapshotSink) writeMeta() error {
	// Open the meta file
	metaPath := filepath.Join(s.dir, metaFilePath)
	fh, err := os.Create(metaPath)
	if err != nil {
		return err
	}
	defer fh.Close()

	// Buffer the file IO
	buffered := bufio.NewWriter(fh)
	defer buffered.Flush()

	// Write out as JSON
	enc := json.NewEncoder(buffered)
	if err := enc.Encode(&s.meta); err != nil {
		return err
	}
	return nil
}

// Implement the sort interface for []*fileSnapshotMeta
func (s snapMetaSlice) Len() int {
	return len(s)
}

func (s snapMetaSlice) Less(i, j int) bool {
	if s[i].Term != s[j].Term {
		return s[i].Term < s[j].Term
	}
	return s[i].Index < s[j].Index
}

func (s snapMetaSlice) Swap(i, j int) {
	s[i], s[j] = s[j], s[i]
}
<commit_msg>If there is a term+index collision use the timestamp<commit_after>package raft

import (
	"bufio"
	"bytes"
	"encoding/json"
	"fmt"
	"hash"
	"hash/crc64"
	"io"
	"io/ioutil"
	"log"
	"os"
	"path/filepath"
	"sort"
	"strings"
	"time"
)

const (
	testPath      = "permTest"
	snapPath      = "snapshots"
	metaFilePath  = "meta.json"
	stateFilePath = "state.bin"
	tmpSuffix     = ".tmp"
)

// FileSnapshotStore implements the SnapshotStore interface and allows
// snapshots to be made on the local disk.
type FileSnapshotStore struct {
	path   string
	retain int
	logger *log.Logger
}

type snapMetaSlice []*fileSnapshotMeta

// Implements the SnapshotSink
type FileSnapshotSink struct {
	store  *FileSnapshotStore
	logger *log.Logger
	dir    string
	meta   fileSnapshotMeta

	stateFile *os.File
	stateHash hash.Hash64
	buffered  *bufio.Writer

	closed bool
}

// fileSnapshotMeta is stored on disk. We also put a CRC
// on disk so that we can verify the snapshot
type fileSnapshotMeta struct {
	SnapshotMeta
	CRC []byte
}

// bufferedFile is returned when we open a snapshot. This way
// reads are buffered and the file still gets closed.
type bufferedFile struct {
	bh *bufio.Reader
	fh *os.File
}

func (b *bufferedFile) Read(p []byte) (n int, err error) {
	return b.bh.Read(p)
}

func (b *bufferedFile) Close() error {
	return b.fh.Close()
}

// NewFileSnapshotStore creates a new FileSnapshotStore based
// on a base directory. The `retain` parameter controls how many
// snapshots are retained. Must be at least 1.
func NewFileSnapshotStore(base string, retain int, logOutput io.Writer) (*FileSnapshotStore, error) {
	if retain < 1 {
		return nil, fmt.Errorf("must retain at least one snapshot")
	}
	if logOutput == nil {
		logOutput = os.Stderr
	}

	// Ensure our path exists
	path := filepath.Join(base, snapPath)
	if err := os.Mkdir(path, 0755); err != nil && !os.IsExist(err) {
		return nil, fmt.Errorf("snapshot path not accessible: %v", err)
	}

	// Setup the store
	store := &FileSnapshotStore{
		path:   path,
		retain: retain,
		logger: log.New(logOutput, "", log.LstdFlags),
	}

	// Do a permissions test
	if err := store.testPermissions(); err != nil {
		return nil, fmt.Errorf("permissions test failed: %v", err)
	}
	return store, nil
}

// testPermissions tries to touch a file in our path to see if it works
func (f *FileSnapshotStore) testPermissions() error {
	path := filepath.Join(f.path, testPath)
	fh, err := os.Create(path)
	if err != nil {
		return err
	}
	fh.Close()
	os.Remove(path)
	return nil
}

// snapshotName generate s name for the snapshot
func snapshotName(term, index uint64) string {
	return fmt.Sprintf("%d-%d-%s", term, index, time.Now().Format(time.RFC3339Nano))
}

// parseName parse the components of a name
func parseName(name string) (uint64, uint64, time.Time, error) {
	var term, index uint64
	var timeString string
	if _, err := fmt.Sscanf(name, "%d-%d-%s", &term, &index, &timeString); err != nil {
		return 0, 0, time.Time{}, err
	}
	when, err := time.Parse(time.RFC3339Nano, timeString)
	if err != nil {
		return 0, 0, time.Time{}, err
	}
	return term, index, when, nil
}

// Create is used to start a new snapshot
func (f *FileSnapshotStore) Create(index, term uint64, peers []byte) (SnapshotSink, error) {
	// Create a new path
	name := snapshotName(term, index)
	path := filepath.Join(f.path, name+tmpSuffix)
	f.logger.Printf("[INFO] snapshot: Creating new snapshot at %s", path)

	// Make the directory
	if err := os.Mkdir(path, 0755); err != nil {
		f.logger.Printf("[ERR] snapshot: Failed to make snapshot directory: %v", err)
		return nil, err
	}

	// Create the sink
	sink := &FileSnapshotSink{
		store:  f,
		logger: f.logger,
		dir:    path,
		meta: fileSnapshotMeta{
			SnapshotMeta: SnapshotMeta{
				ID:    name,
				Index: index,
				Term:  term,
				Peers: peers,
			},
			CRC: nil,
		},
	}

	// Write out the meta data
	if err := sink.writeMeta(); err != nil {
		f.logger.Printf("[ERR] snapshot: Failed to write metadata: %v", err)
		return nil, err
	}

	// Open the state file
	statePath := filepath.Join(path, stateFilePath)
	fh, err := os.Create(statePath)
	if err != nil {
		f.logger.Printf("[ERR] snapshot: Failed to create state file: %v", err)
		return nil, err
	}
	sink.stateFile = fh

	// Create a CRC64 hash
	sink.stateHash = crc64.New(crc64.MakeTable(crc64.ECMA))

	// Wrap both the hash and file in a MultiWriter with buffering
	multi := io.MultiWriter(sink.stateFile, sink.stateHash)
	sink.buffered = bufio.NewWriter(multi)

	// Done
	return sink, nil
}

func (f *FileSnapshotStore) List() ([]*SnapshotMeta, error) {
	// Get the eligible snapshots
	snapshots, err := f.getSnapshots()
	if err != nil {
		f.logger.Printf("[ERR] snapshot: Failed to get snapshots: %v", err)
		return nil, err
	}

	var snapMeta []*SnapshotMeta
	for _, meta := range snapshots {
		snapMeta = append(snapMeta, &meta.SnapshotMeta)
		if len(snapMeta) == f.retain {
			break
		}
	}
	return snapMeta, nil
}

// getSnapshots returns all the known snapshots
func (f *FileSnapshotStore) getSnapshots() ([]*fileSnapshotMeta, error) {
	// Get the eligible snapshots
	snapshots, err := ioutil.ReadDir(f.path)
	if err != nil {
		f.logger.Printf("[ERR] snapshot: Failed to scan snapshot dir: %v", err)
		return nil, err
	}

	// Populate the metadata, reverse order (newest first)
	var snapMeta []*fileSnapshotMeta
	for _, snap := range snapshots {
		// Ignore any files
		if !snap.IsDir() {
			continue
		}

		// Ignore any temporary snapshots
		dirName := snap.Name()
		if strings.HasSuffix(dirName, tmpSuffix) {
			f.logger.Printf("[WARN] snapshot: Found temporary snapshot: %v", dirName)
			continue
		}

		// Try to read the meta data
		meta, err := f.readMeta(dirName)
		if err != nil {
			f.logger.Printf("[WARN] snapshot: Failed to read metadata for %v: %v", dirName, err)
			continue
		}

		// Append, but only return up to the retain count
		snapMeta = append(snapMeta, meta)
	}

	// Sort the snapshot, reverse so we get new -> old
	sort.Sort(sort.Reverse(snapMetaSlice(snapMeta)))

	return snapMeta, nil
}

// readMeta is used to read the meta data for a given named backup
func (f *FileSnapshotStore) readMeta(name string) (*fileSnapshotMeta, error) {
	// Open the meta file
	metaPath := filepath.Join(f.path, name, metaFilePath)
	fh, err := os.Open(metaPath)
	if err != nil {
		return nil, err
	}
	defer fh.Close()

	// Buffer the file IO
	buffered := bufio.NewReader(fh)

	// Read in the JSON
	meta := &fileSnapshotMeta{}
	dec := json.NewDecoder(buffered)
	if err := dec.Decode(meta); err != nil {
		return nil, err
	}
	return meta, nil
}

func (f *FileSnapshotStore) Open(id string) (*SnapshotMeta, io.ReadCloser, error) {
	// Get the metadata
	meta, err := f.readMeta(id)
	if err != nil {
		f.logger.Printf("[ERR] snapshot: Failed to get meta data to open snapshot: %v", err)
		return nil, nil, err
	}

	// Open the state file
	statePath := filepath.Join(f.path, id, stateFilePath)
	fh, err := os.Open(statePath)
	if err != nil {
		f.logger.Printf("[ERR] snapshot: Failed to open state file: %v", err)
		return nil, nil, err
	}

	// Create a CRC64 hash
	stateHash := crc64.New(crc64.MakeTable(crc64.ECMA))

	// Compute the hash
	_, err = io.Copy(stateHash, fh)
	if err != nil {
		f.logger.Printf("[ERR] snapshot: Failed to read state file: %v", err)
		fh.Close()
		return nil, nil, err
	}

	// Verify the hash
	computed := stateHash.Sum(nil)
	if bytes.Compare(meta.CRC, computed) != 0 {
		f.logger.Printf("[ERR] snapshot: CRC checksum failed (stored: %v computed: %v)",
			meta.CRC, computed)
		fh.Close()
		return nil, nil, fmt.Errorf("CRC mismatch")
	}

	// Seek to the start
	if _, err := fh.Seek(0, 0); err != nil {
		f.logger.Printf("[ERR] snapshot: State file seek failed: %v", err)
		fh.Close()
		return nil, nil, err
	}

	// Return a buffered file
	buffered := &bufferedFile{
		bh: bufio.NewReader(fh),
		fh: fh,
	}

	return &meta.SnapshotMeta, buffered, nil
}

// Used to reap any snapshots beyond the retain count
func (f *FileSnapshotStore) ReapSnapshots() error {
	snapshots, err := f.getSnapshots()
	if err != nil {
		f.logger.Printf("[ERR] snapshot: Failed to get snapshots: %v", err)
		return err
	}

	for i := f.retain; i < len(snapshots); i++ {
		path := filepath.Join(f.path, snapshots[i].ID)
		f.logger.Printf("[INFO] snapshot: reaping snapshot %v", path)
		if err := os.RemoveAll(path); err != nil {
			f.logger.Printf("[ERR] snapshot: Failed to reap snapshot %v: %v", path, err)
			return err
		}
	}
	return nil
}

// ID returns the ID of the snapshot, can be used with Open()
// after the snapshot is finalized.
func (s *FileSnapshotSink) ID() string {
	return s.meta.ID
}

// Write is used to append to the state file. We write to the
// buffered IO object to reduce the amount of context switches
func (s *FileSnapshotSink) Write(b []byte) (int, error) {
	return s.buffered.Write(b)
}

// Close is used to indicate a successful end
func (s *FileSnapshotSink) Close() error {
	// Make sure close is idempotent
	if s.closed {
		return nil
	}
	s.closed = true

	// Close the open handles
	if err := s.finalize(); err != nil {
		s.logger.Printf("[ERR] snapshot: Failed to finalize snapshot: %v", err)
		return err
	}

	// Write out the meta data
	if err := s.writeMeta(); err != nil {
		s.logger.Printf("[ERR] snapshot: Failed to write metadata: %v", err)
		return err
	}

	// Move the directory into place
	newPath := strings.TrimSuffix(s.dir, tmpSuffix)
	if err := os.Rename(s.dir, newPath); err != nil {
		s.logger.Printf("[ERR] snapshot: Failed to move snapshot into place: %v", err)
		return err
	}

	// Reap any old snapshots
	s.store.ReapSnapshots()
	return nil
}

// Cancel is used to indicate an unsuccessful end
func (s *FileSnapshotSink) Cancel() error {
	// Make sure close is idempotent
	if s.closed {
		return nil
	}
	s.closed = true

	// Close the open handles
	if err := s.finalize(); err != nil {
		s.logger.Printf("[ERR] snapshot: Failed to finalize snapshot: %v", err)
		return err
	}

	// Attempt to remove all artifacts
	return os.RemoveAll(s.dir)
}

// finalize is used to close all of our resources
func (s *FileSnapshotSink) finalize() error {
	// Flush any remaining data
	if err := s.buffered.Flush(); err != nil {
		return err
	}

	// Get the file size
	stat, statErr := s.stateFile.Stat()

	// Close the file
	if err := s.stateFile.Close(); err != nil {
		return err
	}

	// Set the file size, check after we close
	if statErr != nil {
		return statErr
	}
	s.meta.Size = stat.Size()

	// Set the CRC
	s.meta.CRC = s.stateHash.Sum(nil)
	return nil
}

// writeMeta is used to write out the metadata we have
func (s *FileSnapshotSink) writeMeta() error {
	// Open the meta file
	metaPath := filepath.Join(s.dir, metaFilePath)
	fh, err := os.Create(metaPath)
	if err != nil {
		return err
	}
	defer fh.Close()

	// Buffer the file IO
	buffered := bufio.NewWriter(fh)
	defer buffered.Flush()

	// Write out as JSON
	enc := json.NewEncoder(buffered)
	if err := enc.Encode(&s.meta); err != nil {
		return err
	}
	return nil
}

// Implement the sort interface for []*fileSnapshotMeta
func (s snapMetaSlice) Len() int {
	return len(s)
}

func (s snapMetaSlice) Less(i, j int) bool {
	if s[i].Term != s[j].Term {
		return s[i].Term < s[j].Term
	}
	if s[i].Index != s[j].Index {
		return s[i].Index < s[j].Term
	}
	return s[i].ID < s[j].ID
}

func (s snapMetaSlice) Swap(i, j int) {
	s[i], s[j] = s[j], s[i]
}
<|endoftext|>


<commit_before>package twitter

import (
	"fmt"

	log "github.com/Sirupsen/logrus"
	"github.com/dghubble/go-twitter/twitter"
	"github.com/dghubble/oauth1"
	"github.com/jirwin/quadlek/quadlek"
)

func load(consumerKey, consumerSecret, accessToken, accessSecret string, filter map[string]string) func(bot *quadlek.Bot, store *quadlek.Store) error {

	return func(bot *quadlek.Bot, store *quadlek.Store) error {
		go func() {
			config := oauth1.NewConfig(consumerKey, consumerSecret)
			token := oauth1.NewToken(accessToken, accessSecret)
			httpClient := config.Client(oauth1.NoContext, token)
			client := twitter.NewClient(httpClient)

			followFilters := []string{}
			for follow, _ := range filter {
				followFilters = append(followFilters, follow)
			}

			filterParams := &twitter.StreamFilterParams{
				Follow:        followFilters,
				StallWarnings: twitter.Bool(true),
			}

			stream, err := client.Streams.Filter(filterParams)
			if err != nil {
				log.WithField("err", err).Error("Error streaming tweets.")
				return
			}

			for {
				select {
				case msg := <-stream.Messages:
					switch m := msg.(type) {
					case *twitter.Tweet:
						if channel, ok := filter[m.User.IDStr]; ok {
							if filter[m.InReplyToUserIDStr] not channel {
								twitterUrl := fmt.Sprintf("https://twitter.com/%s/status/%s", m.User.ScreenName, m.IDStr)
								chanId, err := bot.GetChannelId(channel)
								if err != nil {
									log.WithField("err", err).Error("unable to find channel.")
									continue
								}
								bot.Say(chanId, twitterUrl)
							}
						}
					}
				}
			}
		}()

		return nil
	}
}

func Register(consumerKey, consumerSecret, accessToken, accessSecret string, filter map[string]string) quadlek.Plugin {
	return quadlek.MakePlugin(
		"quadlek-twitter",
		nil,
		nil,
		nil,
		nil,
		load(consumerKey, consumerSecret, accessToken, accessSecret, filter),
	)
}
<commit_msg>Update twitter.go<commit_after>package twitter

import (
	"fmt"

	log "github.com/Sirupsen/logrus"
	"github.com/dghubble/go-twitter/twitter"
	"github.com/dghubble/oauth1"
	"github.com/jirwin/quadlek/quadlek"
)

func load(consumerKey, consumerSecret, accessToken, accessSecret string, filter map[string]string) func(bot *quadlek.Bot, store *quadlek.Store) error {

	return func(bot *quadlek.Bot, store *quadlek.Store) error {
		go func() {
			config := oauth1.NewConfig(consumerKey, consumerSecret)
			token := oauth1.NewToken(accessToken, accessSecret)
			httpClient := config.Client(oauth1.NoContext, token)
			client := twitter.NewClient(httpClient)

			followFilters := []string{}
			for follow, _ := range filter {
				followFilters = append(followFilters, follow)
			}

			filterParams := &twitter.StreamFilterParams{
				Follow:        followFilters,
				StallWarnings: twitter.Bool(true),
			}

			stream, err := client.Streams.Filter(filterParams)
			if err != nil {
				log.WithField("err", err).Error("Error streaming tweets.")
				return
			}

			for {
				select {
				case msg := <-stream.Messages:
					switch m := msg.(type) {
					case *twitter.Tweet:
						if channel, ok := filter[m.User.IDStr]; ok {
							if filter[m.InReplyToUserIDStr] != channel {
								twitterUrl := fmt.Sprintf("https://twitter.com/%s/status/%s", m.User.ScreenName, m.IDStr)
								chanId, err := bot.GetChannelId(channel)
								if err != nil {
									log.WithField("err", err).Error("unable to find channel.")
									continue
								}
								bot.Say(chanId, twitterUrl)
							}
						}
					}
				}
			}
		}()

		return nil
	}
}

func Register(consumerKey, consumerSecret, accessToken, accessSecret string, filter map[string]string) quadlek.Plugin {
	return quadlek.MakePlugin(
		"quadlek-twitter",
		nil,
		nil,
		nil,
		nil,
		load(consumerKey, consumerSecret, accessToken, accessSecret, filter),
	)
}
<|endoftext|>


<commit_before>// Copyright (c) 2013, Jan Voung
// All rights reserved.

// Test for file-type detection utilities for ELF linker.

package main

import (
	"os"
	"path"
	"testing"
)

func CheckARFiles(t *testing.T, base_dir string) {
	fnames := [...]string{
		path.Join(base_dir, "libcrt_platform.a"),
		path.Join(base_dir, "libgcc.a"),
		path.Join(base_dir, "libpnacl_irt_shim.a") }

	fhandles := make(map[string] *os.File, len(fnames))
	for _, fname := range fnames {
		f, err := os.Open(fname)
		if err != nil {
			t.Fatal("Failed to open file:", fname, "error:", err)
		}
		defer f.Close()
		fhandles[fname] = f
	}

	file_map := ValidateFiles(fhandles)
	for fname, typ := range file_map {
		if typ != AR_FILE {
			t.Errorf("%s should be AR_FILE, but is %v", fname, typ)
		}
	}
}

func CheckELFFiles(t *testing.T, base_dir string) {
	fnames := [...]string{
		path.Join(base_dir, "crtbegin.o"),
		path.Join(base_dir, "crtend.o")}

	fhandles := make(map[string] *os.File, len(fnames))
	for _, fname := range fnames {
		f, err := os.Open(fname)
		if err != nil {
			t.Fatal("Failed to open file:", fname, "error:", err)
		}
		defer f.Close()
		fhandles[fname] = f
	}

	file_map := ValidateFiles(fhandles)
	for fname, typ := range file_map {
		if typ != ELF_FILE {
			t.Errorf("%s should be ELF_FILE, but is %v", fname, typ)
		}
	}
}

func CheckBaseDirs(t *testing.T, check_func func(*testing.T, string)) {
	base_dirs := [...]string{
		TestX8632BaseDir(), TestX8664BaseDir(), TestARMBaseDir()}
	for _, b := range base_dirs {
		check_func(t, b)
	}
}

func TestARFile(t *testing.T) {
	CheckBaseDirs(t, CheckARFiles)
}

func TestELFFile(t *testing.T) {
	CheckBaseDirs(t, CheckELFFiles)
}
<commit_msg>Simplify array literals to be a slice<commit_after>// Copyright (c) 2013, Jan Voung
// All rights reserved.

// Test for file-type detection utilities for ELF linker.

package main

import (
	"os"
	"path"
	"testing"
)

func CheckARFiles(t *testing.T, base_dir string) {
	fnames := []string{
		path.Join(base_dir, "libcrt_platform.a"),
		path.Join(base_dir, "libgcc.a"),
		path.Join(base_dir, "libpnacl_irt_shim.a") }

	fhandles := make(map[string] *os.File, len(fnames))
	for _, fname := range fnames {
		f, err := os.Open(fname)
		if err != nil {
			t.Fatal("Failed to open file:", fname, "error:", err)
		}
		defer f.Close()
		fhandles[fname] = f
	}

	file_map := ValidateFiles(fhandles)
	for fname, typ := range file_map {
		if typ != AR_FILE {
			t.Errorf("%s should be AR_FILE, but is %v", fname, typ)
		}
	}
}

func CheckELFFiles(t *testing.T, base_dir string) {
	fnames := []string{
		path.Join(base_dir, "crtbegin.o"),
		path.Join(base_dir, "crtend.o")}

	fhandles := make(map[string] *os.File, len(fnames))
	for _, fname := range fnames {
		f, err := os.Open(fname)
		if err != nil {
			t.Fatal("Failed to open file:", fname, "error:", err)
		}
		defer f.Close()
		fhandles[fname] = f
	}

	file_map := ValidateFiles(fhandles)
	for fname, typ := range file_map {
		if typ != ELF_FILE {
			t.Errorf("%s should be ELF_FILE, but is %v", fname, typ)
		}
	}
}

func CheckBaseDirs(t *testing.T, check_func func(*testing.T, string)) {
	base_dirs := []string{
		TestX8632BaseDir(), TestX8664BaseDir(), TestARMBaseDir()}
	for _, b := range base_dirs {
		check_func(t, b)
	}
}

func TestARFile(t *testing.T) {
	CheckBaseDirs(t, CheckARFiles)
}

func TestELFFile(t *testing.T) {
	CheckBaseDirs(t, CheckELFFiles)
}
<|endoftext|>


<commit_before>package fsync

import (
	"bytes"
	"io/ioutil"
	"os"
	"testing"
	"time"
)

func TestSync(t *testing.T) {
	// create test directory and chdir to it
	dir, err := ioutil.TempDir(os.TempDir(), "fsync_test")
	check(err)
	check(os.Chdir(dir))

	// create test files and directories
	check(os.MkdirAll("src/a", 0755))
	check(ioutil.WriteFile("src/a/b", []byte("file b"), 0644))
	check(ioutil.WriteFile("src/c", []byte("file c"), 0644))
	// set times in the past to make sure times are synced, not accidentally
	// the same
	tt := time.Now().Add(-1 * time.Hour)
	check(os.Chtimes("src/a/b", tt, tt))
	check(os.Chtimes("src/a", tt, tt))
	check(os.Chtimes("src/c", tt, tt))
	check(os.Chtimes("src", tt, tt))

	// create Syncer
	s := NewSyncer()

	// sync
	check(s.SyncTo("dst", "src/a", "src/c"))

	// check results
	testDirContents("dst", 2, t)
	testDirContents("dst/a", 1, t)
	testFile("dst/a/b", []byte("file b"), t)
	testFile("dst/c", []byte("file c"), t)
	testPerms("dst/a", getPerms("src/a"), t)
	testPerms("dst/a/b", getPerms("src/a/b"), t)
	testPerms("dst/c", getPerms("src/c"), t)
	testModTime("dst/a", getModTime("src/a"), t)
	testModTime("dst/a/b", getModTime("src/a/b"), t)
	testModTime("dst/c", getModTime("src/c"), t)

	// sync the parent directory too
	check(s.Sync("dst", "src"))

	// check the results
	testPerms("dst", getPerms("src"), t)
	testModTime("dst", getModTime("src"), t)

	// modify src
	check(ioutil.WriteFile("src/a/b", []byte("file b changed"), 0644))
	check(os.Chmod("src/a", 0775))

	// sync
	check(s.Sync("dst", "src"))

	// check results
	testFile("dst/a/b", []byte("file b changed"), t)
	testPerms("dst/a", getPerms("src/a"), t)
	testModTime("dst", getModTime("src"), t)
	testModTime("dst/a", getModTime("src/a"), t)
	testModTime("dst/a/b", getModTime("src/a/b"), t)
	testModTime("dst/c", getModTime("src/c"), t)

	// remove c
	check(os.Remove("src/c"))

	// sync
	check(s.Sync("dst", "src"))

	// check results; c should still exist
	testDirContents("dst", 2, t)
	testExistence("dst/c", true, t)

	// sync
	s.Delete = true
	check(s.Sync("dst", "src"))

	// check results; c should no longer exist
	testDirContents("dst", 1, t)
	testExistence("dst/c", false, t)

	s.Delete = false
	if err = s.Sync("dst", "src/a/b"); err == nil {
		t.Errorf("expecting ErrFileOverDir, got nothing.\n")
	} else if err != nil && err != ErrFileOverDir {
		panic(err)
	}
}

func TestDeleteFileFilter(t *testing.T) {
	// create test directory and chdir to it
	dir, err := ioutil.TempDir(os.TempDir(), "fsync_test_delete_filter")
	check(err)
	check(os.Chdir(dir))

	// create test files and directories
	check(os.MkdirAll("src/a", 0755))
	check(ioutil.WriteFile("src/a/b", []byte("file b"), 0644))

	check(os.MkdirAll("dst", 0755))
	check(ioutil.WriteFile("dst/c", []byte("file c"), 0644))
	check(ioutil.WriteFile("dst/d", []byte("file c"), 0644))

	// create Syncer
	s := NewSyncer()
	s.Delete = true

	s.DeleteFilter = func(f os.FileInfo) bool {
		return f.Name() == "d"
	}

	//precondition; dst contains 2 files `c` and `d`
	testDirContents("dst", 2, t)
	testExistence("dst/c", true, t)
	testExistence("dst/d", true, t)

	check(s.Sync("dst", "src"))

	// check results; c should no longer exist
	testDirContents("dst", 2, t)
	testExistence("dst/a/", true, t)
	testExistence("dst/a/b", true, t)
	testExistence("dst/c", false, t)
	testExistence("dst/d", true, t)
}

func TestDeleteFileFilterNotSet(t *testing.T) {
	// create test directory and chdir to it
	dir, err := ioutil.TempDir(os.TempDir(), "fsync_test_delete_filter")
	check(err)
	check(os.Chdir(dir))

	// create test files and directories
	check(os.MkdirAll("src/a", 0755))
	check(ioutil.WriteFile("src/a/b", []byte("file b"), 0644))

	check(os.MkdirAll("dst", 0755))
	check(ioutil.WriteFile("dst/c", []byte("file c"), 0644))
	check(ioutil.WriteFile("dst/d", []byte("file c"), 0644))

	// create Syncer
	s := NewSyncer()
	s.Delete = true

	//precondition; dst contains 2 files `c` and `d`
	testDirContents("dst", 2, t)
	testExistence("dst/c", true, t)
	testExistence("dst/d", true, t)

	check(s.Sync("dst", "src"))

	// check results; c should no longer exist
	testDirContents("dst", 1, t)
	testExistence("dst/a/", true, t)
	testExistence("dst/a/b", true, t)
	testExistence("dst/c", false, t)
	testExistence("dst/d", false, t)
}

func testFile(name string, b []byte, t *testing.T) {
	testExistence(name, true, t)
	c, err := ioutil.ReadFile(name)
	check(err)
	if !bytes.Equal(b, c) {
		t.Errorf("content of file \"%s\" is:\n%s\nexpected:\n%s\n",
			name, c, b)
	}
}

func testExistence(name string, e bool, t *testing.T) {
	_, err := os.Stat(name)
	if os.IsNotExist(err) {
		if e {
			t.Errorf("file \"%s\" does not exist.\n", name)
		}
	} else if err != nil {
		panic(err)
	} else {
		if !e {
			t.Errorf("file \"%s\" exists.\n", name)
		}
	}
}

func testDirContents(name string, count int, t *testing.T) {
	files, err := ioutil.ReadDir(name)
	check(err)
	if len(files) != count {
		t.Errorf("directory \"%s\" has %d children, shoud have %d.\n",
			name, len(files), count)
	}
}

func testPerms(name string, p os.FileMode, t *testing.T) {
	p2 := getPerms(name)
	if p2 != p {
		t.Errorf("permissions for \"%s\" is %v, should be %v.\n",
			name, p2, p)
	}
}

func testModTime(name string, m time.Time, t *testing.T) {
	m2 := getModTime(name)
	if !m2.Equal(m) {
		t.Errorf("modification time for \"%s\" is %v, should be %v.\n",
			name, m2, m)
	}
}

func getPerms(name string) os.FileMode {
	info, err := os.Stat(name)
	check(err)
	return info.Mode().Perm()
}

func getModTime(name string) time.Time {
	info, err := os.Stat(name)
	check(err)
	return info.ModTime()
}
<commit_msg>Add basic benchmark<commit_after>package fsync

import (
	"bytes"
	"fmt"
	"io/ioutil"
	"os"
	"path/filepath"
	"testing"
	"time"
)

func TestSync(t *testing.T) {
	// create test directory and chdir to it
	dir, err := ioutil.TempDir(os.TempDir(), "fsync_test")
	check(err)
	check(os.Chdir(dir))

	// create test files and directories
	check(os.MkdirAll("src/a", 0755))
	check(ioutil.WriteFile("src/a/b", []byte("file b"), 0644))
	check(ioutil.WriteFile("src/c", []byte("file c"), 0644))
	// set times in the past to make sure times are synced, not accidentally
	// the same
	tt := time.Now().Add(-1 * time.Hour)
	check(os.Chtimes("src/a/b", tt, tt))
	check(os.Chtimes("src/a", tt, tt))
	check(os.Chtimes("src/c", tt, tt))
	check(os.Chtimes("src", tt, tt))

	// create Syncer
	s := NewSyncer()

	// sync
	check(s.SyncTo("dst", "src/a", "src/c"))

	// check results
	testDirContents("dst", 2, t)
	testDirContents("dst/a", 1, t)
	testFile("dst/a/b", []byte("file b"), t)
	testFile("dst/c", []byte("file c"), t)
	testPerms("dst/a", getPerms("src/a"), t)
	testPerms("dst/a/b", getPerms("src/a/b"), t)
	testPerms("dst/c", getPerms("src/c"), t)
	testModTime("dst/a", getModTime("src/a"), t)
	testModTime("dst/a/b", getModTime("src/a/b"), t)
	testModTime("dst/c", getModTime("src/c"), t)

	// sync the parent directory too
	check(s.Sync("dst", "src"))

	// check the results
	testPerms("dst", getPerms("src"), t)
	testModTime("dst", getModTime("src"), t)

	// modify src
	check(ioutil.WriteFile("src/a/b", []byte("file b changed"), 0644))
	check(os.Chmod("src/a", 0775))

	// sync
	check(s.Sync("dst", "src"))

	// check results
	testFile("dst/a/b", []byte("file b changed"), t)
	testPerms("dst/a", getPerms("src/a"), t)
	testModTime("dst", getModTime("src"), t)
	testModTime("dst/a", getModTime("src/a"), t)
	testModTime("dst/a/b", getModTime("src/a/b"), t)
	testModTime("dst/c", getModTime("src/c"), t)

	// remove c
	check(os.Remove("src/c"))

	// sync
	check(s.Sync("dst", "src"))

	// check results; c should still exist
	testDirContents("dst", 2, t)
	testExistence("dst/c", true, t)

	// sync
	s.Delete = true
	check(s.Sync("dst", "src"))

	// check results; c should no longer exist
	testDirContents("dst", 1, t)
	testExistence("dst/c", false, t)

	s.Delete = false
	if err = s.Sync("dst", "src/a/b"); err == nil {
		t.Errorf("expecting ErrFileOverDir, got nothing.\n")
	} else if err != nil && err != ErrFileOverDir {
		panic(err)
	}
}

func TestDeleteFileFilter(t *testing.T) {
	// create test directory and chdir to it
	dir, err := ioutil.TempDir(os.TempDir(), "fsync_test_delete_filter")
	check(err)
	check(os.Chdir(dir))

	// create test files and directories
	check(os.MkdirAll("src/a", 0755))
	check(ioutil.WriteFile("src/a/b", []byte("file b"), 0644))

	check(os.MkdirAll("dst", 0755))
	check(ioutil.WriteFile("dst/c", []byte("file c"), 0644))
	check(ioutil.WriteFile("dst/d", []byte("file c"), 0644))

	// create Syncer
	s := NewSyncer()
	s.Delete = true

	s.DeleteFilter = func(f os.FileInfo) bool {
		return f.Name() == "d"
	}

	//precondition; dst contains 2 files `c` and `d`
	testDirContents("dst", 2, t)
	testExistence("dst/c", true, t)
	testExistence("dst/d", true, t)

	check(s.Sync("dst", "src"))

	// check results; c should no longer exist
	testDirContents("dst", 2, t)
	testExistence("dst/a/", true, t)
	testExistence("dst/a/b", true, t)
	testExistence("dst/c", false, t)
	testExistence("dst/d", true, t)
}

func TestDeleteFileFilterNotSet(t *testing.T) {
	// create test directory and chdir to it
	dir, err := ioutil.TempDir(os.TempDir(), "fsync_test_delete_filter")
	check(err)
	check(os.Chdir(dir))

	// create test files and directories
	check(os.MkdirAll("src/a", 0755))
	check(ioutil.WriteFile("src/a/b", []byte("file b"), 0644))

	check(os.MkdirAll("dst", 0755))
	check(ioutil.WriteFile("dst/c", []byte("file c"), 0644))
	check(ioutil.WriteFile("dst/d", []byte("file c"), 0644))

	// create Syncer
	s := NewSyncer()
	s.Delete = true

	//precondition; dst contains 2 files `c` and `d`
	testDirContents("dst", 2, t)
	testExistence("dst/c", true, t)
	testExistence("dst/d", true, t)

	check(s.Sync("dst", "src"))

	// check results; c should no longer exist
	testDirContents("dst", 1, t)
	testExistence("dst/a/", true, t)
	testExistence("dst/a/b", true, t)
	testExistence("dst/c", false, t)
	testExistence("dst/d", false, t)
}

func testFile(name string, b []byte, t *testing.T) {
	testExistence(name, true, t)
	c, err := ioutil.ReadFile(name)
	check(err)
	if !bytes.Equal(b, c) {
		t.Errorf("content of file \"%s\" is:\n%s\nexpected:\n%s\n",
			name, c, b)
	}
}

func testExistence(name string, e bool, t *testing.T) {
	_, err := os.Stat(name)
	if os.IsNotExist(err) {
		if e {
			t.Errorf("file \"%s\" does not exist.\n", name)
		}
	} else if err != nil {
		panic(err)
	} else {
		if !e {
			t.Errorf("file \"%s\" exists.\n", name)
		}
	}
}

func testDirContents(name string, count int, t *testing.T) {
	files, err := ioutil.ReadDir(name)
	check(err)
	if len(files) != count {
		t.Errorf("directory \"%s\" has %d children, shoud have %d.\n",
			name, len(files), count)
	}
}

func testPerms(name string, p os.FileMode, t *testing.T) {
	p2 := getPerms(name)
	if p2 != p {
		t.Errorf("permissions for \"%s\" is %v, should be %v.\n",
			name, p2, p)
	}
}

func testModTime(name string, m time.Time, t *testing.T) {
	m2 := getModTime(name)
	if !m2.Equal(m) {
		t.Errorf("modification time for \"%s\" is %v, should be %v.\n",
			name, m2, m)
	}
}

func getPerms(name string) os.FileMode {
	info, err := os.Stat(name)
	check(err)
	return info.Mode().Perm()
}

func getModTime(name string) time.Time {
	info, err := os.Stat(name)
	check(err)
	return info.ModTime()
}

func BenchmarkSync(b *testing.B) {
	createTempDir := func() string {
		tempDir, err := ioutil.TempDir(os.TempDir(), "fsync_test")
		check(err)
		return tempDir
	}

	tempDir := createTempDir()

	createSomeFiles := func(dirname string) {
		for i := 0; i < 5; i++ {
			f, err := os.Create(filepath.Join(tempDir, dirname, fmt.Sprintf("test%d.txt", i)))
			if err != nil {
				b.Fatal(err)
			}
			f.Close()
		}
	}

	depth := 5
	for level := depth; level > 0; level-- {
		dirname := ""
		for i := 0; i < level; i++ {
			dirname = filepath.Join(dirname, fmt.Sprintf("dir%d", i))
			err := os.MkdirAll(filepath.Join(tempDir, dirname), 0755)
			if err != nil && !os.IsExist(err) {
				b.Fatal(err)
			}
		}
		createSomeFiles(dirname)
	}

	src := tempDir
	b.ResetTimer()
	for i := 0; i < b.N; i++ {
		dst := createTempDir()
		s := NewSyncer()
		check(s.SyncTo(dst, filepath.Join(src, "dir0")))
		b.StopTimer()
		check(os.RemoveAll(src))
		src = dst
		b.StartTimer()

	}

}
<|endoftext|>


<commit_before>// Blatantly ripped from https://gobyexample.com/collection-functions
// Also added similar functions for integer arrays

package main

// Index returns the first index of the target string `t`, or
// -1 if no match is found.
func Index(vs []string, t string) int {
	for i, v := range vs {
		if v == t {
			return i
		}
	}
	return -1
}

// Include returns `true` if the target string t is in the
// slice.
func Include(vs []string, t string) bool {
	return Index(vs, t) >= 0
}

// Any returns `true` if one of the strings in the slice
// satisfies the predicate `f`.
func Any(vs []string, f func(string) bool) bool {
	for _, v := range vs {
		if f(v) {
			return true
		}
	}
	return false
}

// All returns `true` if all of the strings in the slice
// satisfy the predicate `f`.
func All(vs []string, f func(string) bool) bool {
	for _, v := range vs {
		if !f(v) {
			return false
		}
	}
	return true
}

// Filter returns a new slice containing all strings in the
// slice that satisfy the predicate `f`.
func Filter(vs []string, f func(string) bool) []string {
	var vsf []string
	for _, v := range vs {
		if f(v) {
			vsf = append(vsf, v)
		}
	}
	return vsf
}

// Map returns a new slice containing the results of applying
// the function `f` to each string in the original slice.
func Map(vs []string, f func(string) string) []string {
	vsm := make([]string, len(vs))
	for i, v := range vs {
		vsm[i] = f(v)
	}
	return vsm
}

// Integer functions

// Index returns the first index of the target int `t`, or
// -1 if no match is found.
func Index(vs []int, t int) int {
	for i, v := range vs {
		if v == t {
			return i
		}
	}
	return -1
}

// Include returns `true` if the target int t is in the
// slice.
func Include(vs []int, t int) bool {
	return Index(vs, t) >= 0
}

// Any returns `true` if one of the ints in the slice
// satisfies the predicate `f`.
func Any(vs []int, f func(int) bool) bool {
	for _, v := range vs {
		if f(v) {
			return true
		}
	}
	return false
}

// All returns `true` if all of the ints in the slice
// satisfy the predicate `f`.
func All(vs []int, f func(int) bool) bool {
	for _, v := range vs {
		if !f(v) {
			return false
		}
	}
	return true
}

// Filter returns a new slice containing all ints in the
// slice that satisfy the predicate `f`.
func Filter(vs []int, f func(int) bool) []int {
	var vsf []int
	for _, v := range vs {
		if f(v) {
			vsf = append(vsf, v)
		}
	}
	return vsf
}

// Map returns a new slice containing the results of applying
// the function `f` to each int in the original slice.
func Map(vs []int, f func(int) int) []int {
	vsm := make([]int, len(vs))
	for i, v := range vs {
		vsm[i] = f(v)
	}
	return vsm
}
<commit_msg>Remove integer functions...<commit_after>// Blatantly ripped from https://gobyexample.com/collection-functions
// Also added similar functions for integer arrays

package main

// Index returns the first index of the target string `t`, or
// -1 if no match is found.
func Index(vs []string, t string) int {
	for i, v := range vs {
		if v == t {
			return i
		}
	}
	return -1
}

// Include returns `true` if the target string t is in the
// slice.
func Include(vs []string, t string) bool {
	return Index(vs, t) >= 0
}

// Any returns `true` if one of the strings in the slice
// satisfies the predicate `f`.
func Any(vs []string, f func(string) bool) bool {
	for _, v := range vs {
		if f(v) {
			return true
		}
	}
	return false
}

// All returns `true` if all of the strings in the slice
// satisfy the predicate `f`.
func All(vs []string, f func(string) bool) bool {
	for _, v := range vs {
		if !f(v) {
			return false
		}
	}
	return true
}

// Filter returns a new slice containing all strings in the
// slice that satisfy the predicate `f`.
func Filter(vs []string, f func(string) bool) []string {
	var vsf []string
	for _, v := range vs {
		if f(v) {
			vsf = append(vsf, v)
		}
	}
	return vsf
}

// Map returns a new slice containing the results of applying
// the function `f` to each string in the original slice.
func Map(vs []string, f func(string) string) []string {
	vsm := make([]string, len(vs))
	for i, v := range vs {
		vsm[i] = f(v)
	}
	return vsm
}
<|endoftext|>


<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
	// =======================
	// Implements simple functions to manipulate UTF-8 encoded strings.

	// ===============
	// Tendermint Core
	// ===============

	"bytes"
	"strings"

	"github.com/tendermint/abci/types"
	tendermint "github.com/tendermint/go-common"
	dbm "github.com/tendermint/go-db"
	merkle "github.com/tendermint/go-merkle"
	wire "github.com/tendermint/go-wire"
)

// BftApplication struct
type BftApplication struct {
	types.BaseApplication

	state merkle.Tree

	db dbm.DB

	blockHeader *types.Header

	// validator set
	changes []*types.Validator
}

// NewBftApplication creates a new application
func NewBftApplication() *BftApplication {
	db := dbm.NewDB("bftx", "leveldb", "../../../bft-db/")
	lastBlock := LoadLastBlock(db)

	stateTree := merkle.NewIAVLTree(0, db)
	stateTree.Load(lastBlock.AppHash)

	return &BftApplication{
		state: stateTree,
		db:    db,
	}
}

// Info returns information
func (app *BftApplication) Info() (resInfo types.ResponseInfo) {
	lastBlock := LoadLastBlock(app.db)

	return types.ResponseInfo{Data: tendermint.Fmt("{\"size\":%v}", app.state.Size()), LastBlockAppHash: lastBlock.AppHash, LastBlockHeight: lastBlock.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 {
	// Save
	appHash := app.state.Save()

	lastBlock := LastBlockInfo{
		Height:  uint64(app.state.Height()),
		AppHash: appHash, // this hash will be in the next block header
	}
	SaveLastBlock(app.db, lastBlock)
	return types.NewResultOK(appHash, "")
}

/* func (app *BftApplication) Query(reqQuery types.RequestQuery) (resQuery types.ResponseQuery) {
	if reqQuery.Prove {
		value, proof, err := app.state.GetWithProof(reqQuery.Data)
		// if this wasn't a dummy app, we'd do something smarter
		if err != nil {
			panic(err)
		}
		resQuery.Index = -1 // TODO make Proof return index
		resQuery.Key = reqQuery.Data
		resQuery.Value = value
		resQuery.Proof = wire.BinaryBytes(proof)
		if value != nil {
			resQuery.Log = "exists"
		} else {
			resQuery.Log = "does not exist"
		}
		return
	} else {
		index, value := app.state.Get(reqQuery.Data)
		resQuery.Index = int64(index)
		resQuery.Value = value
		if value != nil {
			resQuery.Log = "exists"
		} else {
			resQuery.Log = "does not exist"
		}
		return
	}
} */

var lastBlockKey = []byte("lastblock")

type LastBlockInfo struct {
	Height  uint64
	AppHash []byte
}

// Get the last block from the db
func LoadLastBlock(db dbm.DB) (lastBlock LastBlockInfo) {
	buf := db.Get(lastBlockKey)
	if len(buf) != 0 {
		r, n, err := bytes.NewReader(buf), new(int), new(error)
		wire.ReadBinaryPtr(&lastBlock, r, 0, n, err)
		if *err != nil {
			// DATA HAS BEEN CORRUPTED OR THE SPEC HAS CHANGED
			panic(err)
		}
		// TODO: ensure that buf is completely read.
	}

	return lastBlock
}

func SaveLastBlock(db dbm.DB, lastBlock LastBlockInfo) {
	buf, n, err := new(bytes.Buffer), new(int), new(error)
	wire.WriteBinary(lastBlock, buf, n, err)
	if *err != nil {
		// TODO
		panic(err)
	}
	db.Set(lastBlockKey, buf.Bytes())
}

// Track the block hash and header information
func (app *BftApplication) BeginBlock(hash []byte, header *types.Header) {
	// update latest block info
	//app.blockHeader = header

	// reset valset changes
	app.changes = make([]*types.Validator, 0)
}

// Update the validator set
func (app *BftApplication) EndBlock(height uint64) (resEndBlock types.ResponseEndBlock) {
	return types.ResponseEndBlock{Diffs: app.changes}
}

// =================================================
// 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>Adding query function and changing beginblock function<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
	// =======================
	// Implements simple functions to manipulate UTF-8 encoded strings.

	// ===============
	// Tendermint Core
	// ===============

	"bytes"
	"strings"

	"github.com/tendermint/abci/types"
	tendermint "github.com/tendermint/go-common"
	dbm "github.com/tendermint/go-db"
	merkle "github.com/tendermint/go-merkle"
	wire "github.com/tendermint/go-wire"
)

// BftApplication struct
type BftApplication struct {
	types.BaseApplication

	state merkle.Tree

	db dbm.DB

	blockHeader *types.Header

	// validator set
	changes []*types.Validator
}

// NewBftApplication creates a new application
func NewBftApplication() *BftApplication {
	db := dbm.NewDB("bftx", "leveldb", "../../../bft-db/")
	lastBlock := LoadLastBlock(db)

	stateTree := merkle.NewIAVLTree(0, db)
	stateTree.Load(lastBlock.AppHash)

	return &BftApplication{
		state: stateTree,
		db:    db,
	}
}

// Info returns information
func (app *BftApplication) Info() (resInfo types.ResponseInfo) {
	lastBlock := LoadLastBlock(app.db)

	return types.ResponseInfo{Data: tendermint.Fmt("{\"size\":%v}", app.state.Size()), LastBlockAppHash: lastBlock.AppHash, LastBlockHeight: lastBlock.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 {
	// Save
	appHash := app.state.Save()

	lastBlock := LastBlockInfo{
		Height:  uint64(app.state.Height()),
		AppHash: appHash, // this hash will be in the next block header
	}
	SaveLastBlock(app.db, lastBlock)
	return types.NewResultOK(appHash, "")
}

func (app *DummyApplication) 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
	}
}

var lastBlockKey = []byte("lastblock")

type LastBlockInfo struct {
	Height  uint64
	AppHash []byte
}

// Get the last block from the db
func LoadLastBlock(db dbm.DB) (lastBlock LastBlockInfo) {
	buf := db.Get(lastBlockKey)
	if len(buf) != 0 {
		r, n, err := bytes.NewReader(buf), new(int), new(error)
		wire.ReadBinaryPtr(&lastBlock, r, 0, n, err)
		if *err != nil {
			// DATA HAS BEEN CORRUPTED OR THE SPEC HAS CHANGED
			panic(err)
		}
		// TODO: ensure that buf is completely read.
	}

	return lastBlock
}

func SaveLastBlock(db dbm.DB, lastBlock LastBlockInfo) {
	buf, n, err := new(bytes.Buffer), new(int), new(error)
	wire.WriteBinary(lastBlock, buf, n, err)
	if *err != nil {
		// TODO
		panic(err)
	}
	db.Set(lastBlockKey, buf.Bytes())
}

// Track the block hash and header information
func (app *BftApplication) BeginBlock(hash []byte, header *types.Header) {
	// update latest block info
	app.blockHeader = header

	// reset valset changes
	app.changes = make([]*types.Validator, 0)
}

// Update the validator set
func (app *BftApplication) EndBlock(height uint64) (resEndBlock types.ResponseEndBlock) {
	return types.ResponseEndBlock{Diffs: app.changes}
}

// =================================================
// 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 gumble

import (
	"io"

	"code.google.com/p/goprotobuf/proto"
	"github.com/layeh/gumble/gumble/MumbleProto"
)

type voiceTargetChannel struct {
	channel          *Channel
	links, recursive bool
}

// VoiceTarget represents a set of users and/or channels that the client can
// whisper to.
type VoiceTarget struct {
	id       int
	users    []*User
	channels []*voiceTargetChannel
}

// Clear removes all users and channels from the voice target.
func (vt *VoiceTarget) Clear() {
	vt.users = nil
	vt.channels = nil
}

// ID returns the voice target ID.
func (vt *VoiceTarget) ID() int {
	return vt.id
}

// SetID sets the ID of the voice target. This value must be in the range
// [1, 30].
func (vt *VoiceTarget) SetID(id int) {
	vt.id = id
}

// AddUser adds a user to the voice target.
func (vt *VoiceTarget) AddUser(user *User) {
	vt.users = append(vt.users, user)
}

// AddChannel adds a user to the voice target.
func (vt *VoiceTarget) AddChannel(channel *Channel, recursive, links bool) {
	vt.channels = append(vt.channels, &voiceTargetChannel{
		channel:   channel,
		links:     links,
		recursive: recursive,
	})
}

func (vt *VoiceTarget) writeTo(client *Client, w io.Writer) (int64, error) {
	packet := MumbleProto.VoiceTarget{
		Id:      proto.Uint32(uint32(vt.id)),
		Targets: make([]*MumbleProto.VoiceTarget_Target, 0, len(vt.users)+len(vt.channels)),
	}
	for _, user := range vt.users {
		packet.Targets = append(packet.Targets, &MumbleProto.VoiceTarget_Target{
			Session: []uint32{user.session},
		})
	}
	for _, vtChannel := range vt.channels {
		packet.Targets = append(packet.Targets, &MumbleProto.VoiceTarget_Target{
			ChannelId: &vtChannel.channel.id,
			Links:     &vtChannel.links,
			Children:  &vtChannel.recursive,
		})
	}

	proto := protoMessage{&packet}
	return proto.writeTo(client, w)
}
<commit_msg>add TargetLoopback<commit_after>package gumble

import (
	"io"

	"code.google.com/p/goprotobuf/proto"
	"github.com/layeh/gumble/gumble/MumbleProto"
)

var targetLoopback VoiceTarget = VoiceTarget{
	id: 31,
}

// TargetLoopback is a special voice target which causes any audio sent to the
// server to be returned to the client.
//
// Its ID should not be modified, and it does not have to to be sent to the
// server before use.
var TargetLoopback *VoiceTarget = &targetLoopback

type voiceTargetChannel struct {
	channel          *Channel
	links, recursive bool
}

// VoiceTarget represents a set of users and/or channels that the client can
// whisper to.
type VoiceTarget struct {
	id       int
	users    []*User
	channels []*voiceTargetChannel
}

// Clear removes all users and channels from the voice target.
func (vt *VoiceTarget) Clear() {
	vt.users = nil
	vt.channels = nil
}

// ID returns the voice target ID.
func (vt *VoiceTarget) ID() int {
	return vt.id
}

// SetID sets the ID of the voice target. This value must be in the range
// [1, 30].
func (vt *VoiceTarget) SetID(id int) {
	vt.id = id
}

// AddUser adds a user to the voice target.
func (vt *VoiceTarget) AddUser(user *User) {
	vt.users = append(vt.users, user)
}

// AddChannel adds a user to the voice target.
func (vt *VoiceTarget) AddChannel(channel *Channel, recursive, links bool) {
	vt.channels = append(vt.channels, &voiceTargetChannel{
		channel:   channel,
		links:     links,
		recursive: recursive,
	})
}

func (vt *VoiceTarget) writeTo(client *Client, w io.Writer) (int64, error) {
	packet := MumbleProto.VoiceTarget{
		Id:      proto.Uint32(uint32(vt.id)),
		Targets: make([]*MumbleProto.VoiceTarget_Target, 0, len(vt.users)+len(vt.channels)),
	}
	for _, user := range vt.users {
		packet.Targets = append(packet.Targets, &MumbleProto.VoiceTarget_Target{
			Session: []uint32{user.session},
		})
	}
	for _, vtChannel := range vt.channels {
		packet.Targets = append(packet.Targets, &MumbleProto.VoiceTarget_Target{
			ChannelId: &vtChannel.channel.id,
			Links:     &vtChannel.links,
			Children:  &vtChannel.recursive,
		})
	}

	proto := protoMessage{&packet}
	return proto.writeTo(client, w)
}
<|endoftext|>


<commit_before>// Copyright © 2018 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 main

import (
	"fmt"
	"log"
	"os"
	"path/filepath"
	"strconv"
	"strings"

	"github.com/spf13/cobra/doc"
	"knative.dev/client/pkg/kn/core"
)

func main() {
	rootCmd := core.NewKnCommand()

	dir := "."
	if len(os.Args) > 1 {
		dir = os.Args[1]
	}
	var withFrontMatter bool
	var err error
	if len(os.Args) > 2 {
		withFrontMatter, err = strconv.ParseBool(os.Args[2])
		if err != nil {
			log.Panicf("Invalid argument %s, has to be boolean to switch on/off generation of frontmatter", os.Args[2])
		}
	}
	prependFunc := emptyString
	if withFrontMatter {
		prependFunc = addFrontMatter
	}
	err = doc.GenMarkdownTreeCustom(rootCmd, dir+"/docs/cmd/", prependFunc, identity)
	if err != nil {
		fmt.Fprintln(os.Stderr, err)
		os.Exit(1)
	}
}

func emptyString(filename string) string {
	return ""
}

func addFrontMatter(fileName string) string {
	// Convert to a title
	title := filepath.Base(fileName)
	title = title[0:len(title) - len(filepath.Ext(title))]
	title = strings.ReplaceAll(title, "_", " ")
	ret := `
---
title: "%s"
#linkTitle: "OPTIONAL_ALTERNATE_NAV_TITLE"
weight: 5
type: "docs"
---
`
	return fmt.Sprintf(ret, title)
}

func identity(s string) string {
	return s
}
<commit_msg>golang format tools (#711)<commit_after>// Copyright © 2018 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 main

import (
	"fmt"
	"log"
	"os"
	"path/filepath"
	"strconv"
	"strings"

	"github.com/spf13/cobra/doc"
	"knative.dev/client/pkg/kn/core"
)

func main() {
	rootCmd := core.NewKnCommand()

	dir := "."
	if len(os.Args) > 1 {
		dir = os.Args[1]
	}
	var withFrontMatter bool
	var err error
	if len(os.Args) > 2 {
		withFrontMatter, err = strconv.ParseBool(os.Args[2])
		if err != nil {
			log.Panicf("Invalid argument %s, has to be boolean to switch on/off generation of frontmatter", os.Args[2])
		}
	}
	prependFunc := emptyString
	if withFrontMatter {
		prependFunc = addFrontMatter
	}
	err = doc.GenMarkdownTreeCustom(rootCmd, dir+"/docs/cmd/", prependFunc, identity)
	if err != nil {
		fmt.Fprintln(os.Stderr, err)
		os.Exit(1)
	}
}

func emptyString(filename string) string {
	return ""
}

func addFrontMatter(fileName string) string {
	// Convert to a title
	title := filepath.Base(fileName)
	title = title[0 : len(title)-len(filepath.Ext(title))]
	title = strings.ReplaceAll(title, "_", " ")
	ret := `
---
title: "%s"
#linkTitle: "OPTIONAL_ALTERNATE_NAV_TITLE"
weight: 5
type: "docs"
---
`
	return fmt.Sprintf(ret, title)
}

func identity(s string) string {
	return s
}
<|endoftext|>