<commit_before>package types

import (
	"database/sql/driver"
	"encoding/hex"
	"math"
	"reflect"
	"strconv"
	"time"
)

func Append(b []byte, v interface{}, flags int) []byte {
	switch v := v.(type) {
	case nil:
		return AppendNull(b, flags)
	case bool:
		return appendBool(b, v)
	case int32:
		return strconv.AppendInt(b, int64(v), 10)
	case int64:
		return strconv.AppendInt(b, v, 10)
	case int:
		return strconv.AppendInt(b, int64(v), 10)
	case float32:
		return appendFloat(b, float64(v), flags, 32)
	case float64:
		return appendFloat(b, v, flags, 64)
	case string:
		return AppendString(b, v, flags)
	case time.Time:
		return AppendTime(b, v, flags)
	case []byte:
		return AppendBytes(b, v, flags)
	case ValueAppender:
		return appendAppender(b, v, flags)
	case driver.Valuer:
		return appendDriverValuer(b, v, flags)
	default:
		return appendValue(b, reflect.ValueOf(v), flags)
	}
}

func AppendError(b []byte, err error) []byte {
	b = append(b, "?!("...)
	b = append(b, err.Error()...)
	b = append(b, ')')
	return b
}

func AppendNull(b []byte, flags int) []byte {
	if hasFlag(flags, quoteFlag) {
		return append(b, "NULL"...)
	}
	return nil
}

func appendBool(dst []byte, v bool) []byte {
	if v {
		return append(dst, "TRUE"...)
	}
	return append(dst, "FALSE"...)
}

func appendFloat(dst []byte, v float64, flags int, bitSize int) []byte {
	if hasFlag(flags, arrayFlag) {
		return appendFloat2(dst, v, flags)
	}

	switch {
	case math.IsNaN(v):
		if hasFlag(flags, quoteFlag) {
			return append(dst, "'NaN'"...)
		}
		return append(dst, "NaN"...)
	case math.IsInf(v, 1):
		if hasFlag(flags, quoteFlag) {
			return append(dst, "'Infinity'"...)
		}
		return append(dst, "Infinity"...)
	case math.IsInf(v, -1):
		if hasFlag(flags, quoteFlag) {
			return append(dst, "'-Infinity'"...)
		}
		return append(dst, "-Infinity"...)
	default:
		return strconv.AppendFloat(dst, v, 'f', -1, bitSize)
	}
}

func appendFloat2(dst []byte, v float64, _ int) []byte {
	switch {
	case math.IsNaN(v):
		return append(dst, "NaN"...)
	case math.IsInf(v, 1):
		return append(dst, "Infinity"...)
	case math.IsInf(v, -1):
		return append(dst, "-Infinity"...)
	default:
		return strconv.AppendFloat(dst, v, 'f', -1, 64)
	}
}

func AppendString(b []byte, s string, flags int) []byte {
	if hasFlag(flags, arrayFlag) {
		return appendString2(b, s, flags)
	}

	if hasFlag(flags, quoteFlag) {
		b = append(b, '\'')
		for i := 0; i < len(s); i++ {
			c := s[i]

			if c == '\000' {
				continue
			}

			if c == '\'' {
				b = append(b, '\'', '\'')
			} else {
				b = append(b, c)
			}
		}
		b = append(b, '\'')
		return b
	}

	for i := 0; i < len(s); i++ {
		c := s[i]
		if c != '\000' {
			b = append(b, c)
		}
	}
	return b
}

func appendString2(b []byte, s string, flags int) []byte {
	b = append(b, '"')
	for i := 0; i < len(s); i++ {
		c := s[i]

		if c == '\000' {
			continue
		}

		switch c {
		case '\'':
			if hasFlag(flags, quoteFlag) {
				b = append(b, '\'')
			}
			b = append(b, '\'')
		case '"':
			b = append(b, '\\', '"')
		case '\\':
			b = append(b, '\\', '\\')
		default:
			b = append(b, c)
		}
	}
	b = append(b, '"')
	return b
}

func AppendBytes(b []byte, bytes []byte, flags int) []byte {
	if bytes == nil {
		return AppendNull(b, flags)
	}

	if hasFlag(flags, arrayFlag) {
		b = append(b, '"')
	} else if hasFlag(flags, quoteFlag) {
		b = append(b, '\'')
	}

	tmp := make([]byte, hex.EncodedLen(len(bytes)))
	hex.Encode(tmp, bytes)

	if hasFlag(flags, arrayFlag) {
		b = append(b, '\\')
	}
	b = append(b, "\\x"...)
	b = append(b, tmp...)

	if hasFlag(flags, arrayFlag) {
		b = append(b, '"')
	} else if hasFlag(flags, quoteFlag) {
		b = append(b, '\'')
	}

	return b
}

func appendDriverValuer(b []byte, v driver.Valuer, flags int) []byte {
	value, err := v.Value()
	if err != nil {
		return AppendError(b, err)
	}
	return Append(b, value, flags)
}

func appendAppender(b []byte, v ValueAppender, flags int) []byte {
	bb, err := v.AppendValue(b, flags)
	if err != nil {
		return AppendError(b, err)
	}
	return bb
}
<commit_msg>types: hex encode without tmp buffer<commit_after>package types

import (
	"database/sql/driver"
	"encoding/hex"
	"math"
	"reflect"
	"strconv"
	"time"
)

func Append(b []byte, v interface{}, flags int) []byte {
	switch v := v.(type) {
	case nil:
		return AppendNull(b, flags)
	case bool:
		return appendBool(b, v)
	case int32:
		return strconv.AppendInt(b, int64(v), 10)
	case int64:
		return strconv.AppendInt(b, v, 10)
	case int:
		return strconv.AppendInt(b, int64(v), 10)
	case float32:
		return appendFloat(b, float64(v), flags, 32)
	case float64:
		return appendFloat(b, v, flags, 64)
	case string:
		return AppendString(b, v, flags)
	case time.Time:
		return AppendTime(b, v, flags)
	case []byte:
		return AppendBytes(b, v, flags)
	case ValueAppender:
		return appendAppender(b, v, flags)
	case driver.Valuer:
		return appendDriverValuer(b, v, flags)
	default:
		return appendValue(b, reflect.ValueOf(v), flags)
	}
}

func AppendError(b []byte, err error) []byte {
	b = append(b, "?!("...)
	b = append(b, err.Error()...)
	b = append(b, ')')
	return b
}

func AppendNull(b []byte, flags int) []byte {
	if hasFlag(flags, quoteFlag) {
		return append(b, "NULL"...)
	}
	return nil
}

func appendBool(dst []byte, v bool) []byte {
	if v {
		return append(dst, "TRUE"...)
	}
	return append(dst, "FALSE"...)
}

func appendFloat(dst []byte, v float64, flags int, bitSize int) []byte {
	if hasFlag(flags, arrayFlag) {
		return appendFloat2(dst, v, flags)
	}

	switch {
	case math.IsNaN(v):
		if hasFlag(flags, quoteFlag) {
			return append(dst, "'NaN'"...)
		}
		return append(dst, "NaN"...)
	case math.IsInf(v, 1):
		if hasFlag(flags, quoteFlag) {
			return append(dst, "'Infinity'"...)
		}
		return append(dst, "Infinity"...)
	case math.IsInf(v, -1):
		if hasFlag(flags, quoteFlag) {
			return append(dst, "'-Infinity'"...)
		}
		return append(dst, "-Infinity"...)
	default:
		return strconv.AppendFloat(dst, v, 'f', -1, bitSize)
	}
}

func appendFloat2(dst []byte, v float64, _ int) []byte {
	switch {
	case math.IsNaN(v):
		return append(dst, "NaN"...)
	case math.IsInf(v, 1):
		return append(dst, "Infinity"...)
	case math.IsInf(v, -1):
		return append(dst, "-Infinity"...)
	default:
		return strconv.AppendFloat(dst, v, 'f', -1, 64)
	}
}

func AppendString(b []byte, s string, flags int) []byte {
	if hasFlag(flags, arrayFlag) {
		return appendString2(b, s, flags)
	}

	if hasFlag(flags, quoteFlag) {
		b = append(b, '\'')
		for i := 0; i < len(s); i++ {
			c := s[i]

			if c == '\000' {
				continue
			}

			if c == '\'' {
				b = append(b, '\'', '\'')
			} else {
				b = append(b, c)
			}
		}
		b = append(b, '\'')
		return b
	}

	for i := 0; i < len(s); i++ {
		c := s[i]
		if c != '\000' {
			b = append(b, c)
		}
	}
	return b
}

func appendString2(b []byte, s string, flags int) []byte {
	b = append(b, '"')
	for i := 0; i < len(s); i++ {
		c := s[i]

		if c == '\000' {
			continue
		}

		switch c {
		case '\'':
			if hasFlag(flags, quoteFlag) {
				b = append(b, '\'')
			}
			b = append(b, '\'')
		case '"':
			b = append(b, '\\', '"')
		case '\\':
			b = append(b, '\\', '\\')
		default:
			b = append(b, c)
		}
	}
	b = append(b, '"')
	return b
}

func AppendBytes(b []byte, bytes []byte, flags int) []byte {
	if bytes == nil {
		return AppendNull(b, flags)
	}

	if hasFlag(flags, arrayFlag) {
		b = append(b, '"')
	} else if hasFlag(flags, quoteFlag) {
		b = append(b, '\'')
	}

	if hasFlag(flags, arrayFlag) {
		b = append(b, '\\')
	}
	b = append(b, "\\x"...)

	s := len(b)
	b = append(b, make([]byte, hex.EncodedLen(len(bytes)))...)
	hex.Encode(b[s:], bytes)

	if hasFlag(flags, arrayFlag) {
		b = append(b, '"')
	} else if hasFlag(flags, quoteFlag) {
		b = append(b, '\'')
	}

	return b
}

func appendDriverValuer(b []byte, v driver.Valuer, flags int) []byte {
	value, err := v.Value()
	if err != nil {
		return AppendError(b, err)
	}
	return Append(b, value, flags)
}

func appendAppender(b []byte, v ValueAppender, flags int) []byte {
	bb, err := v.AppendValue(b, flags)
	if err != nil {
		return AppendError(b, err)
	}
	return bb
}
<|endoftext|>


<commit_before>package types

// Storage key is used to identify a key that a command is taking place at (for
// example, SET, DEL, or any other redis command, assuming redis is your
// datastore).
type StorageKey []byte

// Implements the Bytes method for the Byter interface
func (s StorageKey) Bytes() []byte {
	return []byte(s)
}

// ClientCommand is the structure that commands from the client are parsed into.
// This is going to be the same regardless of the client interface or data
// format.
type ClientCommand struct {

	// Command gets passed through to the backend data-store.
	Command []byte `json:"cmd"`

	// StorageKey is the key used to route the command to the proper hyrax node.
	// Depending on the datastore backend it may also be incorporated into the
	// actual command sent to the datastore.
	StorageKey `json:"key"`

	// Args are extra arguments needed for the command. This will depend on the
	// datastore used. The items in the args list can be of any type, but I
	// can't imagine needing anything except strings and numbers.
	Args []interface{} `json:"args"`

	// Id is an optional identifier for who is sending this command.
	Id []byte `json:"id"`

	// Secret is the sha1-hmac which is required for all commands which
	// add/change data in the datastore. The secret encompasses the command, the
	// key, the args, and the id.
	Secret []byte `json:"secret"`
}

// ClientReturn is the structure that returns to the client are parsed into.
// This is going to be the same regardless of the client interface or data
// format.
type ClientReturn struct {

	// Error will be filled out if there was an error somewhere in the command
	Error []byte `json:"error,omitempty"`

	// Return will be filled out if the command completed successfully. It will
	// be filled with whatever was returned from the command
	Return interface{} `json:"return,omitempty"`

}

// ErrorReturn takes in an error and returns a ClientReturn for it
func ErrorReturn(err error) *ClientReturn {
	return &ClientReturn{Error: []byte(err.Error())}
}
<commit_msg>fixed error in auth docs<commit_after>package types

// Storage key is used to identify a key that a command is taking place at (for
// example, SET, DEL, or any other redis command, assuming redis is your
// datastore).
type StorageKey []byte

// Implements the Bytes method for the Byter interface
func (s StorageKey) Bytes() []byte {
	return []byte(s)
}

// ClientCommand is the structure that commands from the client are parsed into.
// This is going to be the same regardless of the client interface or data
// format.
type ClientCommand struct {

	// Command gets passed through to the backend data-store.
	Command []byte `json:"cmd"`

	// StorageKey is the key used to route the command to the proper hyrax node.
	// Depending on the datastore backend it may also be incorporated into the
	// actual command sent to the datastore.
	StorageKey `json:"key"`

	// Args are extra arguments needed for the command. This will depend on the
	// datastore used. The items in the args list can be of any type, but I
	// can't imagine needing anything except strings and numbers.
	Args []interface{} `json:"args"`

	// Id is an optional identifier for who is sending this command.
	Id []byte `json:"id"`

	// Secret is the sha1-hmac which is required for all commands which
	// add/change data in the datastore. The secret encompasses the command, the
	// key, and the id.
	Secret []byte `json:"secret"`
}

// ClientReturn is the structure that returns to the client are parsed into.
// This is going to be the same regardless of the client interface or data
// format.
type ClientReturn struct {

	// Error will be filled out if there was an error somewhere in the command
	Error []byte `json:"error,omitempty"`

	// Return will be filled out if the command completed successfully. It will
	// be filled with whatever was returned from the command
	Return interface{} `json:"return,omitempty"`

}

// ErrorReturn takes in an error and returns a ClientReturn for it
func ErrorReturn(err error) *ClientReturn {
	return &ClientReturn{Error: []byte(err.Error())}
}
<|endoftext|>


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

package main

import (
	"os/exec"
	"os/user"
	"testing"
)

// Test reading from the buffer.
// dmesg
func TestDmesg(t *testing.T) {
	_, err := exec.Command("go", "run", "dmesg.go").Output()
	if err != nil {
		t.Fatalf("Error running dmesg: %v", err)
	}
	// FIXME: How can the test verify the output is correct?
}

// Test clearing the buffer.
// dmesg -c
func TestClearDmesg(t *testing.T) {
	// Test requies root priviledges or CAP_SYSLOG capability.
	// FIXME: preferably unit tests do not require root priviledges
	if u, err := user.Current(); err != nil {
		t.Fatal("Cannot get current user", err)
	} else if u.Uid != "0" {
		t.Skipf("Test requires root priviledges (uid == 0), uid = %s", u.Uid)
	}

	// Clear
	out, err := exec.Command("go", "run", "dmesg.go", "-c").Output()
	if err != nil {
		t.Fatalf("Error running dmesg -c: %v", err)
	}

	// Read
	out, err = exec.Command("go", "run", "dmesg.go").Output()
	if err != nil {
		t.Fatalf("Error running dmesg: %v", err)
	}

	// Second run of dmesg.go should be cleared.
	// FIXME: This is actually non-determinstic as the system is free (but
	// unlikely) to write more messages inbetween the syscalls.
	if len(out) > 0 {
		t.Fatalf("The log was not cleared, got %v", out)
	}
}
<commit_msg>Simplify dmesg tests<commit_after>// Copyright 2016-2017 the u-root Authors. All rights reserved
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package main

import (
	"os/exec"
	"testing"
)

// Test reading from the buffer.
// dmesg
func TestDmesg(t *testing.T) {
	out, err := exec.Command("go", "run", "dmesg.go").Output()
	if err != nil {
		t.Fatalf("Error running dmesg: %v", err)
	}
	// Test passes if anything is read.
	if len(out) == 0 {
		t.Fatalf("Nothing read from dmesg")
	}
}
<|endoftext|>


<commit_before>package commands

import (
	"github.com/concourse/atc"
	"github.com/concourse/atc/web"
	"github.com/concourse/fly/commands/internal/flaghelpers"
	"github.com/concourse/fly/commands/internal/setpipelinehelpers"
	"github.com/concourse/fly/rc"
	"github.com/tedsuo/rata"
)

type SetPipelineCommand struct {
	SkipInteractive bool `short:"n"  long:"non-interactive"               description:"Skips interactions, uses default values"`

	Pipeline flaghelpers.PipelineFlag `short:"p"  long:"pipeline"  required:"true"  description:"Pipeline to configure"`
	Config   atc.PathFlag             `short:"c"  long:"config"    required:"true"  description:"Pipeline configuration file"`

	Var     []flaghelpers.VariablePairFlag     `short:"v"  long:"var"       value-name:"[NAME=STRING]"  description:"Specify a string value to set for a variable in the pipeline"`
	YAMLVar []flaghelpers.YAMLVariablePairFlag `short:"y"  long:"yaml-var"  value-name:"[NAME=YAML]"    description:"Specify a YAML value tos et for a variable in the pipeline"`

	VarsFrom []atc.PathFlag `short:"l"  long:"load-vars-from"  description:"Variable flag that can be used for filling in template values in configuration from a YAML file"`
}

func (command *SetPipelineCommand) Execute(args []string) error {
	configPath := command.Config
	templateVariablesFiles := command.VarsFrom
	pipelineName := string(command.Pipeline)

	target, err := rc.LoadTarget(Fly.Target)
	if err != nil {
		return err
	}

	err = target.Validate()
	if err != nil {
		return err
	}

	webRequestGenerator := rata.NewRequestGenerator(target.Client().URL(), web.Routes)

	atcConfig := setpipelinehelpers.ATCConfig{
		Team:                target.Team(),
		PipelineName:        pipelineName,
		WebRequestGenerator: webRequestGenerator,
		SkipInteraction:     command.SkipInteractive,
	}

	return atcConfig.Set(configPath, command.Var, command.YAMLVar, templateVariablesFiles)
}
<commit_msg>Fix typo in set-pipeline help text<commit_after>package commands

import (
	"github.com/concourse/atc"
	"github.com/concourse/atc/web"
	"github.com/concourse/fly/commands/internal/flaghelpers"
	"github.com/concourse/fly/commands/internal/setpipelinehelpers"
	"github.com/concourse/fly/rc"
	"github.com/tedsuo/rata"
)

type SetPipelineCommand struct {
	SkipInteractive bool `short:"n"  long:"non-interactive"               description:"Skips interactions, uses default values"`

	Pipeline flaghelpers.PipelineFlag `short:"p"  long:"pipeline"  required:"true"  description:"Pipeline to configure"`
	Config   atc.PathFlag             `short:"c"  long:"config"    required:"true"  description:"Pipeline configuration file"`

	Var     []flaghelpers.VariablePairFlag     `short:"v"  long:"var"       value-name:"[NAME=STRING]"  description:"Specify a string value to set for a variable in the pipeline"`
	YAMLVar []flaghelpers.YAMLVariablePairFlag `short:"y"  long:"yaml-var"  value-name:"[NAME=YAML]"    description:"Specify a YAML value to set for a variable in the pipeline"`

	VarsFrom []atc.PathFlag `short:"l"  long:"load-vars-from"  description:"Variable flag that can be used for filling in template values in configuration from a YAML file"`
}

func (command *SetPipelineCommand) Execute(args []string) error {
	configPath := command.Config
	templateVariablesFiles := command.VarsFrom
	pipelineName := string(command.Pipeline)

	target, err := rc.LoadTarget(Fly.Target)
	if err != nil {
		return err
	}

	err = target.Validate()
	if err != nil {
		return err
	}

	webRequestGenerator := rata.NewRequestGenerator(target.Client().URL(), web.Routes)

	atcConfig := setpipelinehelpers.ATCConfig{
		Team:                target.Team(),
		PipelineName:        pipelineName,
		WebRequestGenerator: webRequestGenerator,
		SkipInteraction:     command.SkipInteractive,
	}

	return atcConfig.Set(configPath, command.Var, command.YAMLVar, templateVariablesFiles)
}
<|endoftext|>


<commit_before>package commands

import (
	"fmt"
	"testing"
)

func TestVersionOnEmptyRepository(t *testing.T) {
	repo := NewRepository(t, "empty")
	defer repo.Test()

	repo.AddPath(repo.Path, ".git")
	repo.AddPath(repo.Path, "subdir")

	cmd := repo.Command("version")
	cmd.Output = fmt.Sprintf("git-media v%s", Version)

	cmd = repo.Command("version", "-comics")
	cmd.Output = fmt.Sprintf("git-media v%s\nNothing may see Gah Lak Tus and survive.", Version)
}
<commit_msg>アーア アアアア アーアー<commit_after>package commands

import (
	"fmt"
	"testing"
)

func TestVersionOnEmptyRepository(t *testing.T) {
	repo := NewRepository(t, "empty")
	defer repo.Test()

	repo.AddPath(repo.Path, ".git")
	repo.AddPath(repo.Path, "subdir")

	cmd := repo.Command("version")
	cmd.Output = fmt.Sprintf("git-media v%s", Version)

	cmd = repo.Command("version", "--comics")
	cmd.Output = fmt.Sprintf("git-media v%s\nNothing may see Gah Lak Tus and survive!", Version)

	cmd = repo.Command("version", "-c")
	cmd.Output = fmt.Sprintf("git-media v%s\nNothing may see Gah Lak Tus and survive!", Version)
}
<|endoftext|>


<commit_before>package goriak

import (
	"errors"
	"reflect"
	"strconv"
	"time"

	riak "github.com/basho/riak-go-client"
)

func decodeInterface(data *riak.FetchMapResponse, output interface{}, riakRequest requestData) error {
	return transMapToStruct(
		data.Map,
		reflect.ValueOf(output).Elem(),
		reflect.TypeOf(output).Elem(),
		data.Context,
		[]string{}, // Start with an empty path
		riakRequest,
	)
}

// Assings values from a Riak Map to a receiving Go struct
func transMapToStruct(data *riak.Map, rValue reflect.Value, rType reflect.Type, riakContext []byte, path []string, riakRequest requestData) error {

	num := rType.NumField()

	for i := 0; i < num; i++ {

		field := rType.Field(i)
		fieldVal := rValue.Field(i)
		registerName := field.Name
		tag := field.Tag.Get("goriak")

		// goriakcontext is a reserved keyword.
		// Use the tag `goriak:"goriakcontext"` to get the Riak context necessary for certaion Riak operations,
		// such as removing items from a Set.
		if tag == "goriakcontext" {
			rValue.Field(i).SetBytes(riakContext)
			continue
		}

		// Ignore this value
		if tag == "-" {
			continue
		}

		if len(tag) > 0 {
			registerName = tag
		}

		switch field.Type.Kind() {
		case reflect.String:
			if val, ok := data.Registers[registerName]; ok {
				fieldVal.SetString(string(val))
			}

		case reflect.Array:
			// []byte
			if fieldVal.Type().Elem().Kind() == reflect.Uint8 {
				if val, ok := data.Registers[registerName]; ok {
					for ii := 0; ii < fieldVal.Len(); ii++ {
						fieldVal.Index(ii).SetUint(uint64(val[ii]))
					}
				}
			}

		// Integer types
		case reflect.Int:
			fallthrough
		case reflect.Int8:
			fallthrough
		case reflect.Int16:
			fallthrough
		case reflect.Int32:
			fallthrough
		case reflect.Int64:
			if val, ok := data.Registers[registerName]; ok {
				if intVal, err := strconv.ParseInt(string(val), 10, 0); err == nil {
					fieldVal.SetInt(intVal)
				}
			}

		// Unsigned integers
		case reflect.Uint:
			fallthrough
		case reflect.Uint8:
			fallthrough
		case reflect.Uint16:
			fallthrough
		case reflect.Uint32:
			fallthrough
		case reflect.Uint64:
			if val, ok := data.Registers[registerName]; ok {
				if intVal, err := strconv.ParseUint(string(val), 10, 0); err == nil {
					fieldVal.SetUint(intVal)
				}
			}

		case reflect.Bool:
			if val, ok := data.Flags[registerName]; ok {
				fieldVal.SetBool(val)
			}

		case reflect.Slice:
			err := transRiakToSlice(rValue.Field(i), registerName, data)

			if err != nil {
				return err
			}

		case reflect.Map:
			if subMap, ok := data.Maps[registerName]; ok {
				err := transMapToMap(rValue.Field(i), subMap)

				if err != nil {
					return err
				}
			}

		case reflect.Struct:
			done := false

			// time.Time
			if bin, ok := data.Registers[registerName]; ok {
				if ts, ok := fieldVal.Interface().(time.Time); ok {
					err := ts.UnmarshalBinary(bin)

					if err != nil {
						return err
					}

					fieldVal.Set(reflect.ValueOf(ts))
					done = true
				}
			}

			if !done {

				if subMap, ok := data.Maps[registerName]; ok {
					// Struct
					newPath := append(path, registerName)

					err := transMapToStruct(subMap, fieldVal, fieldVal.Type(), riakContext, newPath, riakRequest)

					if err != nil {
						return err
					}
				}
			}

		case reflect.Ptr:

			helperPathData := helper{
				name:    registerName,
				path:    path,
				key:     riakRequest,
				context: riakContext,
			}

			switch fieldVal.Type().String() {
			case "*goriak.Counter":
				var counterValue int64

				if val, ok := data.Counters[registerName]; ok {
					counterValue = val
				}

				resCounter := &Counter{
					helper: helperPathData,
					val:    counterValue,
				}

				fieldVal.Set(reflect.ValueOf(resCounter))

			case "*goriak.Set":

				var setValue [][]byte

				if val, ok := data.Sets[registerName]; ok {
					setValue = val
				}

				resSet := &Set{
					helper: helperPathData,
					value:  setValue,
				}

				fieldVal.Set(reflect.ValueOf(resSet))

			case "*goriak.Flag":

				var flagValue bool

				if val, ok := data.Flags[registerName]; ok {
					flagValue = val
				}

				resFlag := &Flag{
					helper: helperPathData,
					val:    flagValue,
				}

				fieldVal.Set(reflect.ValueOf(resFlag))

			case "*goriak.Register":

				var registerValue []byte

				if val, ok := data.Registers[registerName]; ok {
					registerValue = val
				}

				resRegister := &Register{
					helper: helperPathData,
					val:    registerValue,
				}

				fieldVal.Set(reflect.ValueOf(resRegister))

			default:
				return errors.New("Unexpected ptr type: " + fieldVal.Type().String())
			}

		default:
			return errors.New("Unknown type: " + field.Type.Kind().String())
		}
	}

	return nil
}

// Converts Riak objects (can be either Sets or Registers) to Golang Slices
func transRiakToSlice(sliceValue reflect.Value, registerName string, data *riak.Map) error {

	switch sliceValue.Type().Elem().Kind() {

	// []int
	case reflect.Int:
		if setVal, ok := data.Sets[registerName]; ok {
			result := make([]int, len(setVal))

			for i, v := range setVal {
				intVal, err := strconv.ParseInt(string(v), 10, 64)

				if err != nil {
					return err
				}

				result[i] = int(intVal)
			}

			// Success!
			sliceValue.Set(reflect.ValueOf(result))
		}

	// []string
	case reflect.String:
		if setVal, ok := data.Sets[registerName]; ok {
			result := make([]string, len(setVal))

			for i, v := range setVal {
				result[i] = string(v)
			}

			// Success!
			sliceValue.Set(reflect.ValueOf(result))
		}

	// []byte
	case reflect.Uint8:
		if val, ok := data.Registers[registerName]; ok {
			sliceValue.SetBytes(val)
		}

	// [][]byte
	case reflect.Slice:

		if sliceValue.Type().Elem().Elem().Kind() == reflect.Uint8 {
			if val, ok := data.Sets[registerName]; ok {
				sliceValue.Set(reflect.ValueOf(val))
			}

			return nil
		}

		return errors.New("Unknown slice slice type: " + sliceValue.Type().Elem().Elem().Kind().String())

	// [][n]byte
	case reflect.Array:
		if sliceValue.Type().Elem().Elem().Kind() == reflect.Uint8 {
			if values, ok := data.Sets[registerName]; ok {

				lengthOfExpectedArray := sliceValue.Type().Elem().Len()

				// The type of the inner array
				arrayType := sliceValue.Type().Elem()

				// A slice with array Type items
				// The length is set to the amount of values in the Set from Riak
				sliceType := reflect.SliceOf(arrayType)
				finalSliceValue := reflect.MakeSlice(sliceType, len(values), len(values))

				for valueIndex, value := range values {

					// Create the array from Riak data
					newArray := reflect.New(arrayType).Elem()

					for i := 0; i < lengthOfExpectedArray; i++ {
						newArray.Index(i).Set(reflect.ValueOf(value[i]))
					}

					// Add array to slice
					finalSliceValue.Index(valueIndex).Set(newArray)
				}

				// Override the Slice from "Userland"
				sliceValue.Set(finalSliceValue)

			}

			return nil
		}

		return errors.New("Unknown slice array type: " + sliceValue.Type().Elem().Elem().Kind().String())

	default:
		return errors.New("Unknown slice type: " + sliceValue.Type().Elem().Kind().String())
	}

	return nil
}

func bytesToValue(input []byte, outputType reflect.Type) (reflect.Value, error) {

	outputKind := outputType.Kind()

	switch outputKind {
	case reflect.String:
		return reflect.ValueOf(string(input)), nil

	case reflect.Int:
		if i, err := strconv.ParseInt(string(input), 10, 0); err == nil {
			return reflect.ValueOf(int(i)), nil
		}

	case reflect.Int8:
		if i, err := strconv.ParseInt(string(input), 10, 8); err == nil {
			return reflect.ValueOf(int8(i)), nil
		}

	case reflect.Int16:
		if i, err := strconv.ParseInt(string(input), 10, 16); err == nil {
			return reflect.ValueOf(int16(i)), nil
		}

	case reflect.Int32:
		if i, err := strconv.ParseInt(string(input), 10, 32); err == nil {
			return reflect.ValueOf(int32(i)), nil
		}

	case reflect.Int64:
		if i, err := strconv.ParseInt(string(input), 10, 64); err == nil {
			return reflect.ValueOf(int64(i)), nil
		}

	case reflect.Slice:
		sliceItemType := outputType.Elem().Kind()

		switch sliceItemType {
		case reflect.Uint8:
			return reflect.ValueOf(input), nil
		}

	case reflect.Array:

		// Create new array of the expected type
		newArray := reflect.New(outputType).Elem()
		lengthOfExpectedArray := outputType.Len()
		arrayItemType := outputType.Elem().Kind()

		switch arrayItemType {
		// Byte array
		case reflect.Uint8:

			// Copy bytes
			for i := 0; i < lengthOfExpectedArray; i++ {
				newArray.Index(i).Set(reflect.ValueOf(input[i]))
			}

			return newArray, nil
		}
	}

	return reflect.ValueOf(nil), errors.New("Invalid input type: " + outputType.String())
}

// Converts a Riak Map to a Go Map
func transMapToMap(mapValue reflect.Value, data *riak.Map) error {

	mapKeyType := mapValue.Type().Key().Kind()

	// Initialize the map
	newMap := reflect.MakeMap(mapValue.Type())
	mapValue.Set(newMap)

	for key, val := range data.Registers {

		// Convert key (a string) to the correct reflect.Value
		keyValue, err := bytesToValue([]byte(key), mapValue.Type().Key())

		if err != nil {
			return errors.New("Unknown map key type: " + mapKeyType.String())
		}

		valValue, err := bytesToValue(val, mapValue.Type().Elem())

		if err != nil {
			return errors.New("Unknown map value type")
		}

		// Save value to the Go map
		mapValue.SetMapIndex(keyValue, valValue)
	}

	return nil
}
<commit_msg>Removed duplicate code in decoding<commit_after>package goriak

import (
	"errors"
	"reflect"
	"strconv"
	"time"

	riak "github.com/basho/riak-go-client"
)

func decodeInterface(data *riak.FetchMapResponse, output interface{}, riakRequest requestData) error {
	return transMapToStruct(
		data.Map,
		reflect.ValueOf(output).Elem(),
		reflect.TypeOf(output).Elem(),
		data.Context,
		[]string{}, // Start with an empty path
		riakRequest,
	)
}

// Assings values from a Riak Map to a receiving Go struct
func transMapToStruct(data *riak.Map, rValue reflect.Value, rType reflect.Type, riakContext []byte, path []string, riakRequest requestData) error {

	num := rType.NumField()

	for i := 0; i < num; i++ {

		field := rType.Field(i)
		fieldVal := rValue.Field(i)
		registerName := field.Name
		tag := field.Tag.Get("goriak")

		// goriakcontext is a reserved keyword.
		// Use the tag `goriak:"goriakcontext"` to get the Riak context necessary for certaion Riak operations,
		// such as removing items from a Set.
		if tag == "goriakcontext" {
			rValue.Field(i).SetBytes(riakContext)
			continue
		}

		// Ignore this value
		if tag == "-" {
			continue
		}

		if len(tag) > 0 {
			registerName = tag
		}

		switch field.Type.Kind() {
		case reflect.String:
			if val, ok := data.Registers[registerName]; ok {
				fieldVal.SetString(string(val))
			}

		case reflect.Array:
			// []byte
			if fieldVal.Type().Elem().Kind() == reflect.Uint8 {
				if val, ok := data.Registers[registerName]; ok {
					for ii := 0; ii < fieldVal.Len(); ii++ {
						fieldVal.Index(ii).SetUint(uint64(val[ii]))
					}
				}
			}

		// Integer types
		case reflect.Int:
			fallthrough
		case reflect.Int8:
			fallthrough
		case reflect.Int16:
			fallthrough
		case reflect.Int32:
			fallthrough
		case reflect.Int64:
			fallthrough
		case reflect.Uint:
			fallthrough
		case reflect.Uint8:
			fallthrough
		case reflect.Uint16:
			fallthrough
		case reflect.Uint32:
			fallthrough
		case reflect.Uint64:
			if val, ok := data.Registers[registerName]; ok {
				if newVal, err := bytesToValue(val, field.Type); err == nil {
					fieldVal.Set(newVal)
				}
			}

		case reflect.Bool:
			if val, ok := data.Flags[registerName]; ok {
				fieldVal.SetBool(val)
			}

		case reflect.Slice:
			err := transRiakToSlice(rValue.Field(i), registerName, data)

			if err != nil {
				return err
			}

		case reflect.Map:
			if subMap, ok := data.Maps[registerName]; ok {
				err := transMapToMap(rValue.Field(i), subMap)

				if err != nil {
					return err
				}
			}

		case reflect.Struct:
			done := false

			// time.Time
			if bin, ok := data.Registers[registerName]; ok {
				if ts, ok := fieldVal.Interface().(time.Time); ok {
					err := ts.UnmarshalBinary(bin)

					if err != nil {
						return err
					}

					fieldVal.Set(reflect.ValueOf(ts))
					done = true
				}
			}

			if !done {

				if subMap, ok := data.Maps[registerName]; ok {
					// Struct
					newPath := append(path, registerName)

					err := transMapToStruct(subMap, fieldVal, fieldVal.Type(), riakContext, newPath, riakRequest)

					if err != nil {
						return err
					}
				}
			}

		case reflect.Ptr:

			helperPathData := helper{
				name:    registerName,
				path:    path,
				key:     riakRequest,
				context: riakContext,
			}

			switch fieldVal.Type().String() {
			case "*goriak.Counter":
				var counterValue int64

				if val, ok := data.Counters[registerName]; ok {
					counterValue = val
				}

				resCounter := &Counter{
					helper: helperPathData,
					val:    counterValue,
				}

				fieldVal.Set(reflect.ValueOf(resCounter))

			case "*goriak.Set":

				var setValue [][]byte

				if val, ok := data.Sets[registerName]; ok {
					setValue = val
				}

				resSet := &Set{
					helper: helperPathData,
					value:  setValue,
				}

				fieldVal.Set(reflect.ValueOf(resSet))

			case "*goriak.Flag":

				var flagValue bool

				if val, ok := data.Flags[registerName]; ok {
					flagValue = val
				}

				resFlag := &Flag{
					helper: helperPathData,
					val:    flagValue,
				}

				fieldVal.Set(reflect.ValueOf(resFlag))

			case "*goriak.Register":

				var registerValue []byte

				if val, ok := data.Registers[registerName]; ok {
					registerValue = val
				}

				resRegister := &Register{
					helper: helperPathData,
					val:    registerValue,
				}

				fieldVal.Set(reflect.ValueOf(resRegister))

			default:
				return errors.New("Unexpected ptr type: " + fieldVal.Type().String())
			}

		default:
			return errors.New("Unknown type: " + field.Type.Kind().String())
		}
	}

	return nil
}

// Converts Riak objects (can be either Sets or Registers) to Golang Slices
func transRiakToSlice(sliceValue reflect.Value, registerName string, data *riak.Map) error {

	switch sliceValue.Type().Elem().Kind() {

	// []int
	case reflect.Int:
		if setVal, ok := data.Sets[registerName]; ok {
			result := make([]int, len(setVal))

			for i, v := range setVal {
				intVal, err := strconv.ParseInt(string(v), 10, 64)

				if err != nil {
					return err
				}

				result[i] = int(intVal)
			}

			// Success!
			sliceValue.Set(reflect.ValueOf(result))
		}

	// []string
	case reflect.String:
		if setVal, ok := data.Sets[registerName]; ok {
			result := make([]string, len(setVal))

			for i, v := range setVal {
				result[i] = string(v)
			}

			// Success!
			sliceValue.Set(reflect.ValueOf(result))
		}

	// []byte
	case reflect.Uint8:
		if val, ok := data.Registers[registerName]; ok {
			sliceValue.SetBytes(val)
		}

	// [][]byte
	case reflect.Slice:

		if sliceValue.Type().Elem().Elem().Kind() == reflect.Uint8 {
			if val, ok := data.Sets[registerName]; ok {
				sliceValue.Set(reflect.ValueOf(val))
			}

			return nil
		}

		return errors.New("Unknown slice slice type: " + sliceValue.Type().Elem().Elem().Kind().String())

	// [][n]byte
	case reflect.Array:
		if sliceValue.Type().Elem().Elem().Kind() == reflect.Uint8 {
			if values, ok := data.Sets[registerName]; ok {

				lengthOfExpectedArray := sliceValue.Type().Elem().Len()

				// The type of the inner array
				arrayType := sliceValue.Type().Elem()

				// A slice with array Type items
				// The length is set to the amount of values in the Set from Riak
				sliceType := reflect.SliceOf(arrayType)
				finalSliceValue := reflect.MakeSlice(sliceType, len(values), len(values))

				for valueIndex, value := range values {

					// Create the array from Riak data
					newArray := reflect.New(arrayType).Elem()

					for i := 0; i < lengthOfExpectedArray; i++ {
						newArray.Index(i).Set(reflect.ValueOf(value[i]))
					}

					// Add array to slice
					finalSliceValue.Index(valueIndex).Set(newArray)
				}

				// Override the Slice from "Userland"
				sliceValue.Set(finalSliceValue)

			}

			return nil
		}

		return errors.New("Unknown slice array type: " + sliceValue.Type().Elem().Elem().Kind().String())

	default:
		return errors.New("Unknown slice type: " + sliceValue.Type().Elem().Kind().String())
	}

	return nil
}

func bytesToValue(input []byte, outputType reflect.Type) (reflect.Value, error) {

	outputKind := outputType.Kind()

	switch outputKind {
	case reflect.String:
		return reflect.ValueOf(string(input)), nil

	case reflect.Int:
		if i, err := strconv.ParseInt(string(input), 10, 0); err == nil {
			return reflect.ValueOf(int(i)), nil
		}

	case reflect.Int8:
		if i, err := strconv.ParseInt(string(input), 10, 8); err == nil {
			return reflect.ValueOf(int8(i)), nil
		}

	case reflect.Int16:
		if i, err := strconv.ParseInt(string(input), 10, 16); err == nil {
			return reflect.ValueOf(int16(i)), nil
		}

	case reflect.Int32:
		if i, err := strconv.ParseInt(string(input), 10, 32); err == nil {
			return reflect.ValueOf(int32(i)), nil
		}

	case reflect.Int64:
		if i, err := strconv.ParseInt(string(input), 10, 64); err == nil {
			return reflect.ValueOf(int64(i)), nil
		}

	case reflect.Uint:
		if i, err := strconv.ParseUint(string(input), 10, 0); err == nil {
			return reflect.ValueOf(uint(i)), nil
		}

	case reflect.Uint8:
		if i, err := strconv.ParseUint(string(input), 10, 8); err == nil {
			return reflect.ValueOf(uint8(i)), nil
		}

	case reflect.Uint16:
		if i, err := strconv.ParseUint(string(input), 10, 16); err == nil {
			return reflect.ValueOf(uint16(i)), nil
		}

	case reflect.Uint32:
		if i, err := strconv.ParseUint(string(input), 10, 32); err == nil {
			return reflect.ValueOf(uint32(i)), nil
		}

	case reflect.Uint64:
		if i, err := strconv.ParseUint(string(input), 10, 64); err == nil {
			return reflect.ValueOf(uint64(i)), nil
		}

	case reflect.Slice:
		sliceItemType := outputType.Elem().Kind()

		switch sliceItemType {
		case reflect.Uint8:
			return reflect.ValueOf(input), nil
		}

	case reflect.Array:

		// Create new array of the expected type
		newArray := reflect.New(outputType).Elem()
		lengthOfExpectedArray := outputType.Len()
		arrayItemType := outputType.Elem().Kind()

		switch arrayItemType {
		// Byte array
		case reflect.Uint8:

			// Copy bytes
			for i := 0; i < lengthOfExpectedArray; i++ {
				newArray.Index(i).Set(reflect.ValueOf(input[i]))
			}

			return newArray, nil
		}
	}

	return reflect.ValueOf(nil), errors.New("Invalid input type: " + outputType.String())
}

// Converts a Riak Map to a Go Map
func transMapToMap(mapValue reflect.Value, data *riak.Map) error {

	mapKeyType := mapValue.Type().Key().Kind()

	// Initialize the map
	newMap := reflect.MakeMap(mapValue.Type())
	mapValue.Set(newMap)

	for key, val := range data.Registers {

		// Convert key (a string) to the correct reflect.Value
		keyValue, err := bytesToValue([]byte(key), mapValue.Type().Key())

		if err != nil {
			return errors.New("Unknown map key type: " + mapKeyType.String())
		}

		valValue, err := bytesToValue(val, mapValue.Type().Elem())

		if err != nil {
			return errors.New("Unknown map value type")
		}

		// Save value to the Go map
		mapValue.SetMapIndex(keyValue, valValue)
	}

	return nil
}
<|endoftext|>


<commit_before>package main

import (
	"net/http"

	"github.com/beatrichartz/martini-sockets"
	log "github.com/cihub/seelog"
	"github.com/go-martini/martini"
	"github.com/martini-contrib/encoder"
	"github.com/stampzilla/stampzilla-go/nodes/stampzilla-server/websocket"
)

// Webserver that serves static files

type WebServer struct {
	Config     *ServerConfig      `inject:""`
	WsClients  *websocket.Clients `inject:""`
	WebHandler *WebHandler        `inject:""`
}

func NewWebServer() *WebServer {
	return &WebServer{}
}

func (ws *WebServer) Start() {
	log.Info("Starting WEB (:" + ws.Config.WebPort + " in " + ws.Config.WebRoot + ")")

	//m := martini.Classic()
	r := martini.NewRouter()
	ma := martini.New()
	ma.Use(martini.Logger())
	ma.Use(martini.Recovery())
	ma.Use(martini.Static(ws.Config.WebRoot))
	ma.MapTo(r, (*martini.Routes)(nil))
	ma.Action(r.Handle)
	m := &martini.ClassicMartini{ma, r}

	m.Use(func(c martini.Context, w http.ResponseWriter) {
		c.MapTo(encoder.JsonEncoder{}, (*encoder.Encoder)(nil))
		w.Header().Set("Content-Type", "application/json; charset=utf-8")
	})

	m.Get("/socket", sockets.JSON(websocket.Message{}), ws.WsClients.WebsocketRoute)

	//Nodes
	m.Get("/api/nodes", ws.WebHandler.GetNodes)
	m.Get("/api/node/:id", ws.WebHandler.GetNode)
	m.Put("/api/node/:id/cmd", ws.WebHandler.CommandToNodePut)
	m.Get("/api/node/:id/cmd/**", ws.WebHandler.CommandToNodeGet)

	//Rules
	m.Get("/api/rules", ws.WebHandler.GetRules)

	//Schedule
	m.Get("/api/schedule", ws.WebHandler.GetScheduleTasks)
	m.Get("/api/schedule/entries", ws.WebHandler.GetScheduleEntries)

	log.Critical(http.ListenAndServe(":"+ws.Config.WebPort, m))
}
<commit_msg>Changed api paths from /api/node to /api/nodes<commit_after>package main

import (
	"net/http"

	"github.com/beatrichartz/martini-sockets"
	log "github.com/cihub/seelog"
	"github.com/go-martini/martini"
	"github.com/martini-contrib/encoder"
	"github.com/stampzilla/stampzilla-go/nodes/stampzilla-server/websocket"
)

// Webserver that serves static files

type WebServer struct {
	Config     *ServerConfig      `inject:""`
	WsClients  *websocket.Clients `inject:""`
	WebHandler *WebHandler        `inject:""`
}

func NewWebServer() *WebServer {
	return &WebServer{}
}

func (ws *WebServer) Start() {
	log.Info("Starting WEB (:" + ws.Config.WebPort + " in " + ws.Config.WebRoot + ")")

	//m := martini.Classic()
	r := martini.NewRouter()
	ma := martini.New()
	ma.Use(martini.Logger())
	ma.Use(martini.Recovery())
	ma.Use(martini.Static(ws.Config.WebRoot))
	ma.MapTo(r, (*martini.Routes)(nil))
	ma.Action(r.Handle)
	m := &martini.ClassicMartini{ma, r}

	m.Use(func(c martini.Context, w http.ResponseWriter) {
		c.MapTo(encoder.JsonEncoder{}, (*encoder.Encoder)(nil))
		w.Header().Set("Content-Type", "application/json; charset=utf-8")
	})

	m.Get("/socket", sockets.JSON(websocket.Message{}), ws.WsClients.WebsocketRoute)

	//Nodes
	m.Get("/api/nodes", ws.WebHandler.GetNodes)
	m.Get("/api/nodes/:id", ws.WebHandler.GetNode)
	m.Put("/api/nodes/:id/cmd", ws.WebHandler.CommandToNodePut)
	m.Get("/api/nodes/:id/cmd/**", ws.WebHandler.CommandToNodeGet)

	//Rules
	m.Get("/api/rules", ws.WebHandler.GetRules)

	//Schedule
	m.Get("/api/schedule", ws.WebHandler.GetScheduleTasks)
	m.Get("/api/schedule/entries", ws.WebHandler.GetScheduleEntries)

	log.Critical(http.ListenAndServe(":"+ws.Config.WebPort, m))
}
<|endoftext|>


<commit_before>package endpoint

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

//TODO: Need to rebalance the score when backend back to active

// Backend structure
type Backend struct {
	Mutex sync.Mutex

	Name      string
	Address   string
	Heartbeat string
	HBMethod  string

	// Consider inactive after max inactiveAfter
	InactiveAfter int

	HeartbeatTime time.Duration // Heartbeat time if health
	RetryTime     time.Duration // Retry to time after failed

	// The last request failed
	Failed bool
	Active bool
	Tries  int
	Score  int
}

type Backends []*Backend

type ByScore []*Backend

func (a ByScore) Len() int           { return len(a) }
func (a ByScore) Swap(i, j int)      { a[i], a[j] = a[j], a[i] }
func (a ByScore) Less(i, j int) bool { return a[i].Score < a[j].Score }

func NewBackend(name, address, heartbeat, hbmethod string,
	inactiveAfter, heartbeatTime, retryTime int) *Backend {
	return &Backend{
		Name:      name,
		Address:   address,
		Heartbeat: address,
		HBMethod:  hbmethod,

		InactiveAfter: inactiveAfter,
		HeartbeatTime: time.Duration(heartbeatTime) * time.Millisecond,
		RetryTime:     time.Duration(retryTime) * time.Millisecond,

		Failed: true,
		Active: true,
		Tries:  0,
		Score:  0,
	}
}

// Monitoring the backend, can add or remove if heartbeat fail
func (b *Backend) HeartCheck() {
	go func() {
		for {
			var request *http.Request
			var err error

			client := &http.Client{}
			request, err = http.NewRequest(b.HBMethod, b.Heartbeat, nil)
			request.Header.Set("User-Agent", "SSLB-Heartbeat")

			resp, err := client.Do(request)
			if err != nil || resp.StatusCode >= 400 {
				// Max tries before consider inactive
				if b.Tries >= b.InactiveAfter {
					log.Printf("Backend inactive [%s]", b.Name)
					b.Mutex.Lock()
					b.Active = false
					b.Mutex.Unlock()
				} else {
					// Ok that guy it's out of the game
					b.Mutex.Lock()
					b.Failed = true
					b.Tries++
					b.Mutex.Unlock()
					log.Printf("Error to check address [%s] name [%s] tries [%d]", b.Heartbeat, b.Name, b.Tries)
				}
			} else {
				defer resp.Body.Close()

				if b.Failed {
					log.Printf("Backend active [%s]", b.Name)
				}

				// Ok, let's keep working boys
				b.Mutex.Lock()
				b.Failed = false
				b.Active = true
				b.Tries = 0
				b.Mutex.Unlock()
			}

			if b.Failed {
				time.Sleep(b.RetryTime)
			} else {
				time.Sleep(b.HeartbeatTime)
			}
		}
	}()
}
<commit_msg>Fix wrong variable at backend constructor<commit_after>package endpoint

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

//TODO: Need to rebalance the score when backend back to active

// Backend structure
type Backend struct {
	Mutex sync.Mutex

	Name      string
	Address   string
	Heartbeat string
	HBMethod  string

	// Consider inactive after max inactiveAfter
	InactiveAfter int

	HeartbeatTime time.Duration // Heartbeat time if health
	RetryTime     time.Duration // Retry to time after failed

	// The last request failed
	Failed bool
	Active bool
	Tries  int
	Score  int
}

type Backends []*Backend

type ByScore []*Backend

func (a ByScore) Len() int           { return len(a) }
func (a ByScore) Swap(i, j int)      { a[i], a[j] = a[j], a[i] }
func (a ByScore) Less(i, j int) bool { return a[i].Score < a[j].Score }

func NewBackend(name, address, heartbeat, hbmethod string,
	inactiveAfter, heartbeatTime, retryTime int) *Backend {
	return &Backend{
		Name:      name,
		Address:   address,
		Heartbeat: heartbeat,
		HBMethod:  hbmethod,

		InactiveAfter: inactiveAfter,
		HeartbeatTime: time.Duration(heartbeatTime) * time.Millisecond,
		RetryTime:     time.Duration(retryTime) * time.Millisecond,

		Failed: true,
		Active: true,
		Tries:  0,
		Score:  0,
	}
}

// Monitoring the backend, can add or remove if heartbeat fail
func (b *Backend) HeartCheck() {
	go func() {
		for {
			var request *http.Request
			var err error

			client := &http.Client{}
			request, err = http.NewRequest(b.HBMethod, b.Heartbeat, nil)
			request.Header.Set("User-Agent", "SSLB-Heartbeat")

			resp, err := client.Do(request)
			if err != nil || resp.StatusCode >= 400 {
				// Max tries before consider inactive
				if b.Tries >= b.InactiveAfter {
					log.Printf("Backend inactive [%s]", b.Name)
					b.Mutex.Lock()
					b.Active = false
					b.Mutex.Unlock()
				} else {
					// Ok that guy it's out of the game
					b.Mutex.Lock()
					b.Failed = true
					b.Tries++
					b.Mutex.Unlock()
					log.Printf("Error to check address [%s] name [%s] tries [%d]", b.Heartbeat, b.Name, b.Tries)
				}
			} else {
				defer resp.Body.Close()

				if b.Failed {
					log.Printf("Backend active [%s]", b.Name)
				}

				// Ok, let's keep working boys
				b.Mutex.Lock()
				b.Failed = false
				b.Active = true
				b.Tries = 0
				b.Mutex.Unlock()
			}

			if b.Failed {
				time.Sleep(b.RetryTime)
			} else {
				time.Sleep(b.HeartbeatTime)
			}
		}
	}()
}
<|endoftext|>


<commit_before>/*
Copyright 2019 The Kubernetes 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 nodeaffinity

import (
	"context"
	"fmt"

	v1 "k8s.io/api/core/v1"
	"k8s.io/apimachinery/pkg/runtime"
	"k8s.io/component-helpers/scheduling/corev1/nodeaffinity"
	"k8s.io/kubernetes/pkg/scheduler/apis/config"
	"k8s.io/kubernetes/pkg/scheduler/apis/config/validation"
	"k8s.io/kubernetes/pkg/scheduler/framework"
	"k8s.io/kubernetes/pkg/scheduler/framework/plugins/helper"
	"k8s.io/kubernetes/pkg/scheduler/framework/plugins/names"
)

// NodeAffinity is a plugin that checks if a pod node selector matches the node label.
type NodeAffinity struct {
	handle              framework.Handle
	addedNodeSelector   *nodeaffinity.NodeSelector
	addedPrefSchedTerms *nodeaffinity.PreferredSchedulingTerms
}

var _ framework.PreFilterPlugin = &NodeAffinity{}
var _ framework.FilterPlugin = &NodeAffinity{}
var _ framework.PreScorePlugin = &NodeAffinity{}
var _ framework.ScorePlugin = &NodeAffinity{}
var _ framework.EnqueueExtensions = &NodeAffinity{}

const (
	// Name is the name of the plugin used in the plugin registry and configurations.
	Name = names.NodeAffinity

	// preScoreStateKey is the key in CycleState to NodeAffinity pre-computed data for Scoring.
	preScoreStateKey = "PreScore" + Name

	// preFilterStateKey is the key in CycleState to NodeAffinity pre-compute data for Filtering.
	preFilterStateKey = "PreFilter" + Name

	// ErrReasonPod is the reason for Pod's node affinity/selector not matching.
	ErrReasonPod = "node(s) didn't match Pod's node affinity/selector"

	// errReasonEnforced is the reason for added node affinity not matching.
	errReasonEnforced = "node(s) didn't match scheduler-enforced node affinity"
)

// Name returns name of the plugin. It is used in logs, etc.
func (pl *NodeAffinity) Name() string {
	return Name
}

type preFilterState struct {
	requiredNodeSelectorAndAffinity nodeaffinity.RequiredNodeAffinity
}

// Clone just returns the same state because it is not affected by pod additions or deletions.
func (s *preFilterState) Clone() framework.StateData {
	return s
}

// EventsToRegister returns the possible events that may make a Pod
// failed by this plugin schedulable.
func (pl *NodeAffinity) EventsToRegister() []framework.ClusterEvent {
	return []framework.ClusterEvent{
		{Resource: framework.Node, ActionType: framework.Add | framework.UpdateNodeLabel},
	}
}

// PreFilter builds and writes cycle state used by Filter.
func (pl *NodeAffinity) PreFilter(ctx context.Context, cycleState *framework.CycleState, pod *v1.Pod) *framework.Status {
	state := &preFilterState{requiredNodeSelectorAndAffinity: nodeaffinity.GetRequiredNodeAffinity(pod)}
	cycleState.Write(preFilterStateKey, state)
	return nil
}

// PreFilterExtensions not necessary for this plugin as state doesn't depend on pod additions or deletions.
func (pl *NodeAffinity) PreFilterExtensions() framework.PreFilterExtensions {
	return nil
}

// Filter checks if the Node matches the Pod .spec.affinity.nodeAffinity and
// the plugin's added affinity.
func (pl *NodeAffinity) Filter(ctx context.Context, state *framework.CycleState, pod *v1.Pod, nodeInfo *framework.NodeInfo) *framework.Status {
	node := nodeInfo.Node()
	if node == nil {
		return framework.NewStatus(framework.Error, "node not found")
	}
	if pl.addedNodeSelector != nil && !pl.addedNodeSelector.Match(node) {
		return framework.NewStatus(framework.UnschedulableAndUnresolvable, errReasonEnforced)
	}

	s, err := getPreFilterState(state)
	if err != nil {
		// Fallback to calculate requiredNodeSelector and requiredNodeAffinity
		// here when PreFilter is disabled.
		s = &preFilterState{requiredNodeSelectorAndAffinity: nodeaffinity.GetRequiredNodeAffinity(pod)}
	}

	// Ignore parsing errors for backwards compatibility.
	match, _ := s.requiredNodeSelectorAndAffinity.Match(node)
	if !match {
		return framework.NewStatus(framework.UnschedulableAndUnresolvable, ErrReasonPod)
	}

	return nil
}

// preScoreState computed at PreScore and used at Score.
type preScoreState struct {
	preferredNodeAffinity *nodeaffinity.PreferredSchedulingTerms
}

// Clone implements the mandatory Clone interface. We don't really copy the data since
// there is no need for that.
func (s *preScoreState) Clone() framework.StateData {
	return s
}

// PreScore builds and writes cycle state used by Score and NormalizeScore.
func (pl *NodeAffinity) PreScore(ctx context.Context, cycleState *framework.CycleState, pod *v1.Pod, nodes []*v1.Node) *framework.Status {
	if len(nodes) == 0 {
		return nil
	}
	preferredNodeAffinity, err := getPodPreferredNodeAffinity(pod)
	if err != nil {
		return framework.AsStatus(err)
	}
	state := &preScoreState{
		preferredNodeAffinity: preferredNodeAffinity,
	}
	cycleState.Write(preScoreStateKey, state)
	return nil
}

// Score returns the sum of the weights of the terms that match the Node.
// Terms came from the Pod .spec.affinity.nodeAffinity and from the plugin's
// default affinity.
func (pl *NodeAffinity) Score(ctx context.Context, state *framework.CycleState, pod *v1.Pod, nodeName string) (int64, *framework.Status) {
	nodeInfo, err := pl.handle.SnapshotSharedLister().NodeInfos().Get(nodeName)
	if err != nil {
		return 0, framework.AsStatus(fmt.Errorf("getting node %q from Snapshot: %w", nodeName, err))
	}

	node := nodeInfo.Node()
	if node == nil {
		return 0, framework.AsStatus(fmt.Errorf("getting node %q from Snapshot: %w", nodeName, err))
	}

	var count int64
	if pl.addedPrefSchedTerms != nil {
		count += pl.addedPrefSchedTerms.Score(node)
	}

	s, err := getPreScoreState(state)
	if err != nil {
		// Fallback to calculate preferredNodeAffinity here when PreScore is disabled.
		preferredNodeAffinity, err := getPodPreferredNodeAffinity(pod)
		if err != nil {
			return 0, framework.AsStatus(err)
		}
		s = &preScoreState{
			preferredNodeAffinity: preferredNodeAffinity,
		}
	}

	if s.preferredNodeAffinity != nil {
		count += s.preferredNodeAffinity.Score(node)
	}

	return count, nil
}

// NormalizeScore invoked after scoring all nodes.
func (pl *NodeAffinity) NormalizeScore(ctx context.Context, state *framework.CycleState, pod *v1.Pod, scores framework.NodeScoreList) *framework.Status {
	return helper.DefaultNormalizeScore(framework.MaxNodeScore, false, scores)
}

// ScoreExtensions of the Score plugin.
func (pl *NodeAffinity) ScoreExtensions() framework.ScoreExtensions {
	return pl
}

// New initializes a new plugin and returns it.
func New(plArgs runtime.Object, h framework.Handle) (framework.Plugin, error) {
	args, err := getArgs(plArgs)
	if err != nil {
		return nil, err
	}
	pl := &NodeAffinity{
		handle: h,
	}
	if args.AddedAffinity != nil {
		if ns := args.AddedAffinity.RequiredDuringSchedulingIgnoredDuringExecution; ns != nil {
			pl.addedNodeSelector, err = nodeaffinity.NewNodeSelector(ns)
			if err != nil {
				return nil, fmt.Errorf("parsing addedAffinity.requiredDuringSchedulingIgnoredDuringExecution: %w", err)
			}
		}
		// TODO: parse requiredDuringSchedulingRequiredDuringExecution when it gets added to the API.
		if terms := args.AddedAffinity.PreferredDuringSchedulingIgnoredDuringExecution; len(terms) != 0 {
			pl.addedPrefSchedTerms, err = nodeaffinity.NewPreferredSchedulingTerms(terms)
			if err != nil {
				return nil, fmt.Errorf("parsing addedAffinity.preferredDuringSchedulingIgnoredDuringExecution: %w", err)
			}
		}
	}
	return pl, nil
}

func getArgs(obj runtime.Object) (config.NodeAffinityArgs, error) {
	ptr, ok := obj.(*config.NodeAffinityArgs)
	if !ok {
		return config.NodeAffinityArgs{}, fmt.Errorf("args are not of type NodeAffinityArgs, got %T", obj)
	}
	return *ptr, validation.ValidateNodeAffinityArgs(nil, ptr)
}

func getPodPreferredNodeAffinity(pod *v1.Pod) (*nodeaffinity.PreferredSchedulingTerms, error) {
	affinity := pod.Spec.Affinity
	if affinity != nil && affinity.NodeAffinity != nil && affinity.NodeAffinity.PreferredDuringSchedulingIgnoredDuringExecution != nil {
		return nodeaffinity.NewPreferredSchedulingTerms(affinity.NodeAffinity.PreferredDuringSchedulingIgnoredDuringExecution)
	}
	return nil, nil
}

func getPreScoreState(cycleState *framework.CycleState) (*preScoreState, error) {
	c, err := cycleState.Read(preScoreStateKey)
	if err != nil {
		return nil, fmt.Errorf("reading %q from cycleState: %w", preScoreStateKey, err)
	}

	s, ok := c.(*preScoreState)
	if !ok {
		return nil, fmt.Errorf("invalid PreScore state, got type %T", c)
	}
	return s, nil
}

func getPreFilterState(cycleState *framework.CycleState) (*preFilterState, error) {
	c, err := cycleState.Read(preFilterStateKey)
	if err != nil {
		return nil, fmt.Errorf("reading %q from cycleState: %v", preFilterStateKey, err)
	}

	s, ok := c.(*preFilterState)
	if !ok {
		return nil, fmt.Errorf("invalid PreFilter state, got type %T", c)
	}
	return s, nil
}
<commit_msg>Fix wrong log<commit_after>/*
Copyright 2019 The Kubernetes 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 nodeaffinity

import (
	"context"
	"fmt"

	v1 "k8s.io/api/core/v1"
	"k8s.io/apimachinery/pkg/runtime"
	"k8s.io/component-helpers/scheduling/corev1/nodeaffinity"
	"k8s.io/kubernetes/pkg/scheduler/apis/config"
	"k8s.io/kubernetes/pkg/scheduler/apis/config/validation"
	"k8s.io/kubernetes/pkg/scheduler/framework"
	"k8s.io/kubernetes/pkg/scheduler/framework/plugins/helper"
	"k8s.io/kubernetes/pkg/scheduler/framework/plugins/names"
)

// NodeAffinity is a plugin that checks if a pod node selector matches the node label.
type NodeAffinity struct {
	handle              framework.Handle
	addedNodeSelector   *nodeaffinity.NodeSelector
	addedPrefSchedTerms *nodeaffinity.PreferredSchedulingTerms
}

var _ framework.PreFilterPlugin = &NodeAffinity{}
var _ framework.FilterPlugin = &NodeAffinity{}
var _ framework.PreScorePlugin = &NodeAffinity{}
var _ framework.ScorePlugin = &NodeAffinity{}
var _ framework.EnqueueExtensions = &NodeAffinity{}

const (
	// Name is the name of the plugin used in the plugin registry and configurations.
	Name = names.NodeAffinity

	// preScoreStateKey is the key in CycleState to NodeAffinity pre-computed data for Scoring.
	preScoreStateKey = "PreScore" + Name

	// preFilterStateKey is the key in CycleState to NodeAffinity pre-compute data for Filtering.
	preFilterStateKey = "PreFilter" + Name

	// ErrReasonPod is the reason for Pod's node affinity/selector not matching.
	ErrReasonPod = "node(s) didn't match Pod's node affinity/selector"

	// errReasonEnforced is the reason for added node affinity not matching.
	errReasonEnforced = "node(s) didn't match scheduler-enforced node affinity"
)

// Name returns name of the plugin. It is used in logs, etc.
func (pl *NodeAffinity) Name() string {
	return Name
}

type preFilterState struct {
	requiredNodeSelectorAndAffinity nodeaffinity.RequiredNodeAffinity
}

// Clone just returns the same state because it is not affected by pod additions or deletions.
func (s *preFilterState) Clone() framework.StateData {
	return s
}

// EventsToRegister returns the possible events that may make a Pod
// failed by this plugin schedulable.
func (pl *NodeAffinity) EventsToRegister() []framework.ClusterEvent {
	return []framework.ClusterEvent{
		{Resource: framework.Node, ActionType: framework.Add | framework.UpdateNodeLabel},
	}
}

// PreFilter builds and writes cycle state used by Filter.
func (pl *NodeAffinity) PreFilter(ctx context.Context, cycleState *framework.CycleState, pod *v1.Pod) *framework.Status {
	state := &preFilterState{requiredNodeSelectorAndAffinity: nodeaffinity.GetRequiredNodeAffinity(pod)}
	cycleState.Write(preFilterStateKey, state)
	return nil
}

// PreFilterExtensions not necessary for this plugin as state doesn't depend on pod additions or deletions.
func (pl *NodeAffinity) PreFilterExtensions() framework.PreFilterExtensions {
	return nil
}

// Filter checks if the Node matches the Pod .spec.affinity.nodeAffinity and
// the plugin's added affinity.
func (pl *NodeAffinity) Filter(ctx context.Context, state *framework.CycleState, pod *v1.Pod, nodeInfo *framework.NodeInfo) *framework.Status {
	node := nodeInfo.Node()
	if node == nil {
		return framework.NewStatus(framework.Error, "node not found")
	}
	if pl.addedNodeSelector != nil && !pl.addedNodeSelector.Match(node) {
		return framework.NewStatus(framework.UnschedulableAndUnresolvable, errReasonEnforced)
	}

	s, err := getPreFilterState(state)
	if err != nil {
		// Fallback to calculate requiredNodeSelector and requiredNodeAffinity
		// here when PreFilter is disabled.
		s = &preFilterState{requiredNodeSelectorAndAffinity: nodeaffinity.GetRequiredNodeAffinity(pod)}
	}

	// Ignore parsing errors for backwards compatibility.
	match, _ := s.requiredNodeSelectorAndAffinity.Match(node)
	if !match {
		return framework.NewStatus(framework.UnschedulableAndUnresolvable, ErrReasonPod)
	}

	return nil
}

// preScoreState computed at PreScore and used at Score.
type preScoreState struct {
	preferredNodeAffinity *nodeaffinity.PreferredSchedulingTerms
}

// Clone implements the mandatory Clone interface. We don't really copy the data since
// there is no need for that.
func (s *preScoreState) Clone() framework.StateData {
	return s
}

// PreScore builds and writes cycle state used by Score and NormalizeScore.
func (pl *NodeAffinity) PreScore(ctx context.Context, cycleState *framework.CycleState, pod *v1.Pod, nodes []*v1.Node) *framework.Status {
	if len(nodes) == 0 {
		return nil
	}
	preferredNodeAffinity, err := getPodPreferredNodeAffinity(pod)
	if err != nil {
		return framework.AsStatus(err)
	}
	state := &preScoreState{
		preferredNodeAffinity: preferredNodeAffinity,
	}
	cycleState.Write(preScoreStateKey, state)
	return nil
}

// Score returns the sum of the weights of the terms that match the Node.
// Terms came from the Pod .spec.affinity.nodeAffinity and from the plugin's
// default affinity.
func (pl *NodeAffinity) Score(ctx context.Context, state *framework.CycleState, pod *v1.Pod, nodeName string) (int64, *framework.Status) {
	nodeInfo, err := pl.handle.SnapshotSharedLister().NodeInfos().Get(nodeName)
	if err != nil {
		return 0, framework.AsStatus(fmt.Errorf("getting node %q from Snapshot: %w", nodeName, err))
	}

	node := nodeInfo.Node()

	var count int64
	if pl.addedPrefSchedTerms != nil {
		count += pl.addedPrefSchedTerms.Score(node)
	}

	s, err := getPreScoreState(state)
	if err != nil {
		// Fallback to calculate preferredNodeAffinity here when PreScore is disabled.
		preferredNodeAffinity, err := getPodPreferredNodeAffinity(pod)
		if err != nil {
			return 0, framework.AsStatus(err)
		}
		s = &preScoreState{
			preferredNodeAffinity: preferredNodeAffinity,
		}
	}

	if s.preferredNodeAffinity != nil {
		count += s.preferredNodeAffinity.Score(node)
	}

	return count, nil
}

// NormalizeScore invoked after scoring all nodes.
func (pl *NodeAffinity) NormalizeScore(ctx context.Context, state *framework.CycleState, pod *v1.Pod, scores framework.NodeScoreList) *framework.Status {
	return helper.DefaultNormalizeScore(framework.MaxNodeScore, false, scores)
}

// ScoreExtensions of the Score plugin.
func (pl *NodeAffinity) ScoreExtensions() framework.ScoreExtensions {
	return pl
}

// New initializes a new plugin and returns it.
func New(plArgs runtime.Object, h framework.Handle) (framework.Plugin, error) {
	args, err := getArgs(plArgs)
	if err != nil {
		return nil, err
	}
	pl := &NodeAffinity{
		handle: h,
	}
	if args.AddedAffinity != nil {
		if ns := args.AddedAffinity.RequiredDuringSchedulingIgnoredDuringExecution; ns != nil {
			pl.addedNodeSelector, err = nodeaffinity.NewNodeSelector(ns)
			if err != nil {
				return nil, fmt.Errorf("parsing addedAffinity.requiredDuringSchedulingIgnoredDuringExecution: %w", err)
			}
		}
		// TODO: parse requiredDuringSchedulingRequiredDuringExecution when it gets added to the API.
		if terms := args.AddedAffinity.PreferredDuringSchedulingIgnoredDuringExecution; len(terms) != 0 {
			pl.addedPrefSchedTerms, err = nodeaffinity.NewPreferredSchedulingTerms(terms)
			if err != nil {
				return nil, fmt.Errorf("parsing addedAffinity.preferredDuringSchedulingIgnoredDuringExecution: %w", err)
			}
		}
	}
	return pl, nil
}

func getArgs(obj runtime.Object) (config.NodeAffinityArgs, error) {
	ptr, ok := obj.(*config.NodeAffinityArgs)
	if !ok {
		return config.NodeAffinityArgs{}, fmt.Errorf("args are not of type NodeAffinityArgs, got %T", obj)
	}
	return *ptr, validation.ValidateNodeAffinityArgs(nil, ptr)
}

func getPodPreferredNodeAffinity(pod *v1.Pod) (*nodeaffinity.PreferredSchedulingTerms, error) {
	affinity := pod.Spec.Affinity
	if affinity != nil && affinity.NodeAffinity != nil && affinity.NodeAffinity.PreferredDuringSchedulingIgnoredDuringExecution != nil {
		return nodeaffinity.NewPreferredSchedulingTerms(affinity.NodeAffinity.PreferredDuringSchedulingIgnoredDuringExecution)
	}
	return nil, nil
}

func getPreScoreState(cycleState *framework.CycleState) (*preScoreState, error) {
	c, err := cycleState.Read(preScoreStateKey)
	if err != nil {
		return nil, fmt.Errorf("reading %q from cycleState: %w", preScoreStateKey, err)
	}

	s, ok := c.(*preScoreState)
	if !ok {
		return nil, fmt.Errorf("invalid PreScore state, got type %T", c)
	}
	return s, nil
}

func getPreFilterState(cycleState *framework.CycleState) (*preFilterState, error) {
	c, err := cycleState.Read(preFilterStateKey)
	if err != nil {
		return nil, fmt.Errorf("reading %q from cycleState: %v", preFilterStateKey, err)
	}

	s, ok := c.(*preFilterState)
	if !ok {
		return nil, fmt.Errorf("invalid PreFilter state, got type %T", c)
	}
	return s, nil
}
<|endoftext|>


<commit_before>package main

import (
	"../lib/libocit"
	"../lib/routes"
	"bytes"
	"encoding/json"
	"fmt"
	"io/ioutil"
	"log"
	"net/http"
	"os"
	"os/exec"
	"path"

//	"strings"
)

/*
#include <stdio.h>
#include <stdlib.h>
int CSystem(char *cmd){
	return system (cmd);
}
*/
import "C"

type OCTDConfig struct {
	TSurl    string
	Port     int
	CacheDir string
	Debug    bool
}

var pub_config OCTDConfig

func GetResult(w http.ResponseWriter, r *http.Request) {
	var realurl string
	filename := r.URL.Query().Get("File")
	ID := r.URL.Query().Get("ID")

	_, err := os.Stat(filename)
	if err == nil {
		//absolute path
		realurl = filename
	} else {
		json_dir := FindJsonDir(path.Join(pub_config.CacheDir, ID))
		realurl = path.Join(json_dir, filename)
		_, err = os.Stat(realurl)
		if err != nil {
			w.Write([]byte("Cannot find the file: " + realurl))
			return
		}
	}
	file, err := os.Open(realurl)
	defer file.Close()
	if err != nil {
		//FIXME: add to head
		w.Write([]byte("Cannot open the file: " + realurl))
		return
	}

	buf := bytes.NewBufferString("")
	buf.ReadFrom(file)

	w.Write([]byte(buf.String()))
}

func UploadFile(w http.ResponseWriter, r *http.Request) {
	real_url, params := libocit.ReceiveFile(w, r, pub_config.CacheDir)

	fmt.Println(params)

	if val, ok := params["id"]; ok {
		libocit.UntarFile(path.Join(pub_config.CacheDir, val), real_url)
	} else {

		libocit.UntarFile(pub_config.CacheDir, real_url)
	}
	var ret libocit.HttpRet
	ret.Status = "OK"
	ret_string, _ := json.Marshal(ret)
	w.Write([]byte(ret_string))

	return
}

func RunCommand(cmd string, dir string) {
	if pub_config.Debug {
		fmt.Println("Run the command < ", cmd, ">  in ", dir)
	}
	os.Chdir(dir)

	debugging := true
	if debugging {
		c := exec.Command("/bin/sh", "-c", cmd)
		c.Run()
	} else {
		C.CSystem(C.CString(cmd))
	}
	return

	// Golang bug? cannot get the standard output
	//	fmt.Println("Run the command ", cmd)
	//	c := exec.Command("/bin/sh", "-c", cmd)
	//	c.Run()
	//	fmt.Println("After run the command ", cmd)
}

func PullImage(container libocit.Container) {
	//FIXME: no need to do this!
	return
	if container.Distribution == "Docker" {
		cmd := "docker pull " + container.Class
		c := exec.Command("/bin/sh", "-c", cmd)
		c.Run()

		fmt.Println("Exec pull image ", cmd)
	}
}

func UpdateStatus(testCommand libocit.TestingCommand) {
	var testStatus libocit.TestingStatus

	post_url := pub_config.TSurl + "/" + testCommand.ID + "/status"
	if testCommand.Status == "deploy" {
		testStatus.Status = "Deployed"
	} else if testCommand.Status == "run" {
		testStatus.Status = "Finish"
	}
	testStatus.Object = testCommand.Object
	ts_string, _ := json.Marshal(testStatus)
	libocit.SendCommand(post_url, []byte(ts_string))
}

//This is for the un-formal testcase, for example with third-party libs included
//TODO, need to use the formal format, since the output will also be '.json'
func FindJsonDir(base_dir string) (json_dir string) {
	files_info, _ := ioutil.ReadDir(base_dir)
	for _, file := range files_info {
		if file.IsDir() {
			sub_json_dir := FindJsonDir(path.Join(base_dir, file.Name()))
			if len(sub_json_dir) > 1 {
				json_dir = sub_json_dir
				return json_dir
			}
		} else {
			fileSuffix := path.Ext(file.Name())
			if fileSuffix == ".json" {
				_, err := os.Stat(path.Join(base_dir, "source"))
				if err != nil {
					continue
				} else {
					//  ./casename.json, ./source/
					json_dir = base_dir
					return json_dir
				}
			}
		}
	}
	return json_dir
}

func TestingCommand(w http.ResponseWriter, r *http.Request) {
	result, _ := ioutil.ReadAll(r.Body)
	r.Body.Close()

	var testCommand libocit.TestingCommand
	json.Unmarshal([]byte(result), &testCommand)

	if len(testCommand.Command) > 0 {
		json_dir := FindJsonDir(path.Join(pub_config.CacheDir, testCommand.ID))
		dir := path.Join(json_dir, "source")
		RunCommand(testCommand.Command, dir)
	}
	//Send status update to the test server
	UpdateStatus(testCommand)

	var ret libocit.HttpRet
	ret.Status = "OK"
	ret_string, _ := json.Marshal(ret)
	w.Write([]byte(ret_string))
}

func RegisterToTestServer() {
	post_url := pub_config.TSurl + "/os"

	//TODO
	//Seems there will be lots of coding while getting the system info
	//Using config now.

	content := libocit.ReadFile("./host.conf")
	fmt.Println(content)
	ret := libocit.SendCommand(post_url, []byte(content))
	fmt.Println(ret)
}

func main() {
	content := libocit.ReadFile("./ocitd.conf")
	json.Unmarshal([]byte(content), &pub_config)

	RegisterToTestServer()

	var port string
	port = fmt.Sprintf(":%d", pub_config.Port)

	mux := routes.New()
	mux.Get("/result", GetResult)
	mux.Post("/task", UploadFile)
	mux.Post("/command", TestingCommand)

	http.Handle("/", mux)
	fmt.Println("Start to listen ", port)
	err := http.ListenAndServe(port, nil)
	if err != nil {
		log.Fatal("ListenAndServe: ", err)
	}
}
<commit_msg>update ocitd<commit_after>package main

import (
	"../lib/libocit"
	"../lib/routes"
	"bytes"
	"encoding/json"
	"fmt"
	"io/ioutil"
	"log"
	"net/http"
	"os"
	"os/exec"
	"path"

	//	"strings"
)

/*
#include <stdio.h>
#include <stdlib.h>
int CSystem(char *cmd){
	return system (cmd);
}
*/
import "C"

type OCTDConfig struct {
	TSurl    string
	Port     int
	CacheDir string
	Debug    bool
}

var pub_config OCTDConfig

func GetResult(w http.ResponseWriter, r *http.Request) {
	var realurl string
	filename := r.URL.Query().Get("File")
	ID := r.URL.Query().Get("ID")

	_, err := os.Stat(filename)
	if err == nil {
		//absolute path
		realurl = filename
	} else {
		json_dir := FindJsonDir(path.Join(pub_config.CacheDir, ID))
		realurl = path.Join(json_dir, filename)
		_, err = os.Stat(realurl)
		if err != nil {
			w.Write([]byte("Cannot find the file: " + realurl))
			return
		}
	}
	file, err := os.Open(realurl)
	defer file.Close()
	if err != nil {
		//FIXME: add to head
		w.Write([]byte("Cannot open the file: " + realurl))
		return
	}

	buf := bytes.NewBufferString("")
	buf.ReadFrom(file)

	w.Write([]byte(buf.String()))
}

func UploadFile(w http.ResponseWriter, r *http.Request) {
	real_url, params := libocit.ReceiveFile(w, r, pub_config.CacheDir)

	fmt.Println(params)

	if val, ok := params["id"]; ok {
		libocit.UntarFile(path.Join(pub_config.CacheDir, val), real_url)
	} else {

		libocit.UntarFile(pub_config.CacheDir, real_url)
	}
	var ret libocit.HttpRet
	ret.Status = "OK"
	ret_string, _ := json.Marshal(ret)
	w.Write([]byte(ret_string))

	return
}

func RunCommand(cmd string, dir string) {
	if pub_config.Debug {
		fmt.Println("Run the command < ", cmd, ">  in ", dir)
	}
	//check it since some case only has a config.json
	libocit.PreparePath(dir, "")
	os.Chdir(dir)

	debugging := true
	if debugging {
		c := exec.Command("/bin/sh", "-c", cmd)
		c.Run()
	} else {
		C.CSystem(C.CString(cmd))
	}
	return

	// Golang bug? cannot get the standard output
	//	fmt.Println("Run the command ", cmd)
	//	c := exec.Command("/bin/sh", "-c", cmd)
	//	c.Run()
	//	fmt.Println("After run the command ", cmd)
}

func PullImage(container libocit.Container) {
	//FIXME: no need to do this!
	return
	if container.Distribution == "Docker" {
		cmd := "docker pull " + container.Class
		c := exec.Command("/bin/sh", "-c", cmd)
		c.Run()

		fmt.Println("Exec pull image ", cmd)
	}
}

func UpdateStatus(testCommand libocit.TestingCommand) {
	var testStatus libocit.TestingStatus

	post_url := pub_config.TSurl + "/" + testCommand.ID + "/status"
	if testCommand.Status == "deploy" {
		testStatus.Status = "Deployed"
	} else if testCommand.Status == "run" {
		testStatus.Status = "Finish"
	}
	testStatus.Object = testCommand.Object
	ts_string, _ := json.Marshal(testStatus)
	libocit.SendCommand(post_url, []byte(ts_string))
}

//This is for the un-formal testcase, for example with third-party libs included
//TODO, need to use the formal format, since the output will also be '.json'
func FindJsonDir(base_dir string) (json_dir string) {
	files_info, _ := ioutil.ReadDir(base_dir)
	for _, file := range files_info {
		if file.IsDir() {
			sub_json_dir := FindJsonDir(path.Join(base_dir, file.Name()))
			if len(sub_json_dir) > 1 {
				json_dir = sub_json_dir
				return json_dir
			}
		} else {
			fileSuffix := path.Ext(file.Name())
			if fileSuffix == ".json" {
				_, err := os.Stat(path.Join(base_dir, "source"))
				json_dir = base_dir
				if err == nil {
					return json_dir
				}
			}
		}
	}
	return json_dir
}

func TestingCommand(w http.ResponseWriter, r *http.Request) {
	result, _ := ioutil.ReadAll(r.Body)
	r.Body.Close()

	var testCommand libocit.TestingCommand
	json.Unmarshal([]byte(result), &testCommand)

	if len(testCommand.Command) > 0 {
		json_dir := FindJsonDir(path.Join(pub_config.CacheDir, testCommand.ID))
		dir := path.Join(json_dir, "source")
		RunCommand(testCommand.Command, dir)
	}
	//Send status update to the test server
	UpdateStatus(testCommand)

	var ret libocit.HttpRet
	ret.Status = "OK"
	ret_string, _ := json.Marshal(ret)
	w.Write([]byte(ret_string))
}

func RegisterToTestServer() {
	post_url := pub_config.TSurl + "/os"

	//TODO
	//Seems there will be lots of coding while getting the system info
	//Using config now.

	content := libocit.ReadFile("./host.conf")
	fmt.Println(content)
	ret := libocit.SendCommand(post_url, []byte(content))
	fmt.Println(ret)
}

func main() {
	content := libocit.ReadFile("./ocitd.conf")
	json.Unmarshal([]byte(content), &pub_config)

	RegisterToTestServer()

	var port string
	port = fmt.Sprintf(":%d", pub_config.Port)

	mux := routes.New()
	mux.Get("/result", GetResult)
	mux.Post("/task", UploadFile)
	mux.Post("/command", TestingCommand)

	http.Handle("/", mux)
	fmt.Println("Start to listen ", port)
	err := http.ListenAndServe(port, nil)
	if err != nil {
		log.Fatal("ListenAndServe: ", err)
	}
}
<|endoftext|>


<commit_before>package pb

import (
	"fmt"
	"io"
	"math"
	"strings"
	"sync/atomic"
	"time"
)

var (
	// Default refresh rate - 200ms
	DefaultRefreshRate = time.Millisecond * 200

	BarStart = "["
	BarEnd   = "]"
	Empty    = "_"
	Current  = "="
	CurrentN = ">"
)

// Create new progress bar object
func New(total int) *ProgressBar {
	return &ProgressBar{
		Total:        int64(total),
		RefreshRate:  DefaultRefreshRate,
		ShowPercent:  true,
		ShowCounters: true,
		ShowBar:      true,
		ShowTimeLeft: true,
	}
}

// Create new object and start
func StartNew(total int) (pb *ProgressBar) {
	pb = New(total)
	pb.Start()
	return
}

// Callback for custom output
// For example:
// bar.Callback = func(s string) {
//     mySuperPrint(s)
// }
//
type Callback func(out string)

type ProgressBar struct {
	current int64 // current must be first member of struct (https://code.google.com/p/go/issues/detail?id=5278)

	Total                            int64
	RefreshRate                      time.Duration
	ShowPercent, ShowCounters        bool
	ShowSpeed, ShowTimeLeft, ShowBar bool
	Output                           io.Writer
	Callback                         Callback
	NotPrint                         bool
	Units                            int

	isFinish  bool
	startTime time.Time
}

// Start print
func (pb *ProgressBar) Start() {
	pb.startTime = time.Now()
	if pb.Total == 0 {
		pb.ShowBar = false
		pb.ShowTimeLeft = false
		pb.ShowPercent = false
	}
	go pb.writer()
}

// Increment current value
func (pb *ProgressBar) Increment() int {
	return pb.Add(1)
}

// Set current value
func (pb *ProgressBar) Set(current int) {
	atomic.StoreInt64(&pb.current, int64(current))
}

// Add to current value
func (pb *ProgressBar) Add(add int) int {
	return int(atomic.AddInt64(&pb.current, int64(add)))
}

// End print
func (pb *ProgressBar) Finish() {
	pb.isFinish = true
	pb.write(atomic.LoadInt64(&pb.current))
	if !pb.NotPrint {
		fmt.Println()
	}
}

// End print and write string 'str'
func (pb *ProgressBar) FinishPrint(str string) {
	pb.Finish()
	fmt.Println(str)
}

// implement io.Writer
func (pb *ProgressBar) Write(p []byte) (n int, err error) {
	n = len(p)
	pb.Add(n)
	return
}

// implement io.Reader
func (pb *ProgressBar) Read(p []byte) (n int, err error) {
	n = len(p)
	pb.Add(n)
	return
}

func (pb *ProgressBar) write(current int64) {
	width, _ := terminalWidth()
	var percentBox, countersBox, timeLeftBox, speedBox, barBox, end, out string

	// percents
	if pb.ShowPercent {
		percent := float64(current) / (float64(pb.Total) / float64(100))
		percentBox = fmt.Sprintf(" %#.02f %% ", percent)
	}

	// counters
	if pb.ShowCounters {
		if pb.Total > 0 {
			countersBox = fmt.Sprintf("%s / %s ", Format(current, pb.Units), Format(pb.Total, pb.Units))
		} else {
			countersBox = Format(current, pb.Units) + " "
		}
	}

	// time left
	if pb.ShowTimeLeft && current > 0 {
		fromStart := time.Now().Sub(pb.startTime)
		perEntry := fromStart / time.Duration(current)
		left := time.Duration(pb.Total-current) * perEntry
		left = (left / time.Second) * time.Second
		if left > 0 {
			timeLeftBox = left.String()
		}
	}

	// speed
	if pb.ShowSpeed && current > 0 {
		fromStart := time.Now().Sub(pb.startTime)
		speed := float64(current) / (float64(fromStart) / float64(time.Second))
		speedBox = Format(int64(speed), pb.Units) + "/s "
	}

	// bar
	if pb.ShowBar {
		size := width - len(countersBox+BarStart+BarEnd+percentBox+timeLeftBox+speedBox)
		if size > 0 {
			curCount := int(math.Ceil((float64(current) / float64(pb.Total)) * float64(size)))
			emptCount := size - curCount
			barBox = BarStart
			if emptCount < 0 {
				emptCount = 0
			}
			if curCount > size {
				curCount = size
			}
			if emptCount <= 0 {
				barBox += strings.Repeat(Current, curCount)
			} else if curCount > 0 {
				barBox += strings.Repeat(Current, curCount-1) + CurrentN
			}

			barBox += strings.Repeat(Empty, emptCount) + BarEnd
		}
	}

	// check len
	out = countersBox + barBox + percentBox + speedBox + timeLeftBox
	if len(out) < width {
		end = strings.Repeat(" ", width-len(out))
	}

	out = countersBox + barBox + percentBox + speedBox + timeLeftBox

	// and print!
	switch {
	case pb.Output != nil:
		fmt.Fprint(pb.Output, out+end)
	case pb.Callback != nil:
		pb.Callback(out + end)
	case !pb.NotPrint:
		fmt.Print("\r" + out + end)
	}
}

func (pb *ProgressBar) writer() {
	var c, oc int64
	for {
		if pb.isFinish {
			break
		}
		c = atomic.LoadInt64(&pb.current)
		if c != oc {
			pb.write(c)
			oc = c
		}
		time.Sleep(pb.RefreshRate)
	}
}

type window struct {
	Row    uint16
	Col    uint16
	Xpixel uint16
	Ypixel uint16
}
<commit_msg>Fixing hidden pb when current progress is 0.<commit_after>package pb

import (
	"fmt"
	"io"
	"math"
	"strings"
	"sync/atomic"
	"time"
)

var (
	// Default refresh rate - 200ms
	DefaultRefreshRate = time.Millisecond * 200

	BarStart = "["
	BarEnd   = "]"
	Empty    = "_"
	Current  = "="
	CurrentN = ">"
)

// Create new progress bar object
func New(total int) *ProgressBar {
	return &ProgressBar{
		Total:        int64(total),
		RefreshRate:  DefaultRefreshRate,
		ShowPercent:  true,
		ShowCounters: true,
		ShowBar:      true,
		ShowTimeLeft: true,
	}
}

// Create new object and start
func StartNew(total int) (pb *ProgressBar) {
	pb = New(total)
	pb.Start()
	return
}

// Callback for custom output
// For example:
// bar.Callback = func(s string) {
//     mySuperPrint(s)
// }
//
type Callback func(out string)

type ProgressBar struct {
	current int64 // current must be first member of struct (https://code.google.com/p/go/issues/detail?id=5278)

	Total                            int64
	RefreshRate                      time.Duration
	ShowPercent, ShowCounters        bool
	ShowSpeed, ShowTimeLeft, ShowBar bool
	Output                           io.Writer
	Callback                         Callback
	NotPrint                         bool
	Units                            int

	isFinish  bool
	startTime time.Time
}

// Start print
func (pb *ProgressBar) Start() {
	pb.startTime = time.Now()
	if pb.Total == 0 {
		pb.ShowBar = false
		pb.ShowTimeLeft = false
		pb.ShowPercent = false
	}
	go pb.writer()
}

// Increment current value
func (pb *ProgressBar) Increment() int {
	return pb.Add(1)
}

// Set current value
func (pb *ProgressBar) Set(current int) {
	atomic.StoreInt64(&pb.current, int64(current))
}

// Add to current value
func (pb *ProgressBar) Add(add int) int {
	return int(atomic.AddInt64(&pb.current, int64(add)))
}

// End print
func (pb *ProgressBar) Finish() {
	pb.isFinish = true
	pb.write(atomic.LoadInt64(&pb.current))
	if !pb.NotPrint {
		fmt.Println()
	}
}

// End print and write string 'str'
func (pb *ProgressBar) FinishPrint(str string) {
	pb.Finish()
	fmt.Println(str)
}

// implement io.Writer
func (pb *ProgressBar) Write(p []byte) (n int, err error) {
	n = len(p)
	pb.Add(n)
	return
}

// implement io.Reader
func (pb *ProgressBar) Read(p []byte) (n int, err error) {
	n = len(p)
	pb.Add(n)
	return
}

func (pb *ProgressBar) write(current int64) {
	width, _ := terminalWidth()
	var percentBox, countersBox, timeLeftBox, speedBox, barBox, end, out string

	// percents
	if pb.ShowPercent {
		percent := float64(current) / (float64(pb.Total) / float64(100))
		percentBox = fmt.Sprintf(" %#.02f %% ", percent)
	}

	// counters
	if pb.ShowCounters {
		if pb.Total > 0 {
			countersBox = fmt.Sprintf("%s / %s ", Format(current, pb.Units), Format(pb.Total, pb.Units))
		} else {
			countersBox = Format(current, pb.Units) + " "
		}
	}

	// time left
	if pb.ShowTimeLeft && current > 0 {
		fromStart := time.Now().Sub(pb.startTime)
		perEntry := fromStart / time.Duration(current)
		left := time.Duration(pb.Total-current) * perEntry
		left = (left / time.Second) * time.Second
		if left > 0 {
			timeLeftBox = left.String()
		}
	}

	// speed
	if pb.ShowSpeed && current > 0 {
		fromStart := time.Now().Sub(pb.startTime)
		speed := float64(current) / (float64(fromStart) / float64(time.Second))
		speedBox = Format(int64(speed), pb.Units) + "/s "
	}

	// bar
	if pb.ShowBar {
		size := width - len(countersBox+BarStart+BarEnd+percentBox+timeLeftBox+speedBox)
		if size > 0 {
			curCount := int(math.Ceil((float64(current) / float64(pb.Total)) * float64(size)))
			emptCount := size - curCount
			barBox = BarStart
			if emptCount < 0 {
				emptCount = 0
			}
			if curCount > size {
				curCount = size
			}
			if emptCount <= 0 {
				barBox += strings.Repeat(Current, curCount)
			} else if curCount > 0 {
				barBox += strings.Repeat(Current, curCount-1) + CurrentN
			}

			barBox += strings.Repeat(Empty, emptCount) + BarEnd
		}
	}

	// check len
	out = countersBox + barBox + percentBox + speedBox + timeLeftBox
	if len(out) < width {
		end = strings.Repeat(" ", width-len(out))
	}

	out = countersBox + barBox + percentBox + speedBox + timeLeftBox

	// and print!
	switch {
	case pb.Output != nil:
		fmt.Fprint(pb.Output, out+end)
	case pb.Callback != nil:
		pb.Callback(out + end)
	case !pb.NotPrint:
		fmt.Print("\r" + out + end)
	}
}

func (pb *ProgressBar) writer() {
	var c, oc int64
	oc = -1
	for {
		if pb.isFinish {
			break
		}
		c = atomic.LoadInt64(&pb.current)
		if c != oc {
			pb.write(c)
			oc = c
		}
		time.Sleep(pb.RefreshRate)
	}
}

type window struct {
	Row    uint16
	Col    uint16
	Xpixel uint16
	Ypixel uint16
}
<|endoftext|>


<commit_before>package pb

import (
	"fmt"
	"io"
	"math"
	"strings"
	"sync/atomic"
	"time"
)

const (
	// Default refresh rate - 200ms
	DEFAULT_REFRESH_RATE = time.Millisecond * 200
	FORMAT               = "[=>-]"
)

// DEPRECATED
// variables for backward compatibility, from now do not work
// use pb.Format and pb.SetRefreshRate
var (
	DefaultRefreshRate                         = DEFAULT_REFRESH_RATE
	BarStart, BarEnd, Empty, Current, CurrentN string
)

// Create new progress bar object
func New(total int) (pb *ProgressBar) {
	pb = &ProgressBar{
		Total:        int64(total),
		RefreshRate:  DEFAULT_REFRESH_RATE,
		ShowPercent:  true,
		ShowCounters: true,
		ShowBar:      true,
		ShowTimeLeft: true,
	}
	pb.Format(FORMAT)
	return
}

// Create new object and start
func StartNew(total int) (pb *ProgressBar) {
	pb = New(total)
	pb.Start()
	return
}

// Callback for custom output
// For example:
// bar.Callback = func(s string) {
//     mySuperPrint(s)
// }
//
type Callback func(out string)

type ProgressBar struct {
	current int64 // current must be first member of struct (https://code.google.com/p/go/issues/detail?id=5278)

	Total                            int64
	RefreshRate                      time.Duration
	ShowPercent, ShowCounters        bool
	ShowSpeed, ShowTimeLeft, ShowBar bool
	Output                           io.Writer
	Callback                         Callback
	NotPrint                         bool
	Units                            int

	isFinish  bool
	startTime time.Time

	BarStart string
	BarEnd   string
	Empty    string
	Current  string
	CurrentN string
}

// Start print
func (pb *ProgressBar) Start() {
	pb.startTime = time.Now()
	if pb.Total == 0 {
		pb.ShowBar = false
		pb.ShowTimeLeft = false
		pb.ShowPercent = false
	}
	go pb.writer()
}

// Increment current value
func (pb *ProgressBar) Increment() int {
	return pb.Add(1)
}

// Set current value
func (pb *ProgressBar) Set(current int) {
	atomic.StoreInt64(&pb.current, int64(current))
}

// Add to current value
func (pb *ProgressBar) Add(add int) int {
	return int(atomic.AddInt64(&pb.current, int64(add)))
}

// Set custom format for bar
// Example: bar.Format("[=>_]")
func (pb *ProgressBar) Format(format string) (bar *ProgressBar) {
	bar = pb
	formatEntries := strings.Split(format, "")
	if len(formatEntries) != 5 {
		return
	}
	pb.BarStart = formatEntries[0]
	pb.BarEnd = formatEntries[4]
	pb.Empty = formatEntries[3]
	pb.Current = formatEntries[1]
	pb.CurrentN = formatEntries[2]
	return
}

// Set bar refresh rate
func (pb *ProgressBar) SetRefreshRate(rate time.Duration) (bar *ProgressBar) {
	bar = pb
	pb.RefreshRate = rate
	return
}

// Set units
// bar.SetUnits(U_NO) - by default
// bar.SetUnits(U_BYTES) - for Mb, Kb, etc
func (pb *ProgressBar) SetUnits(units int) (bar *ProgressBar) {
	bar = pb
	switch units {
	case U_NO, U_BYTES:
		pb.Units = units
	}
	return
}

// End print
func (pb *ProgressBar) Finish() {
	pb.isFinish = true
	pb.write(atomic.LoadInt64(&pb.current))
	if !pb.NotPrint {
		fmt.Println()
	}
}

// End print and write string 'str'
func (pb *ProgressBar) FinishPrint(str string) {
	pb.Finish()
	fmt.Println(str)
}

// implement io.Writer
func (pb *ProgressBar) Write(p []byte) (n int, err error) {
	n = len(p)
	pb.Add(n)
	return
}

// implement io.Reader
func (pb *ProgressBar) Read(p []byte) (n int, err error) {
	n = len(p)
	pb.Add(n)
	return
}

func (pb *ProgressBar) write(current int64) {
	width, _ := terminalWidth()
	var percentBox, countersBox, timeLeftBox, speedBox, barBox, end, out string

	// percents
	if pb.ShowPercent {
		percent := float64(current) / (float64(pb.Total) / float64(100))
		percentBox = fmt.Sprintf(" %#.02f %% ", percent)
	}

	// counters
	if pb.ShowCounters {
		if pb.Total > 0 {
			countersBox = fmt.Sprintf("%s / %s ", Format(current, pb.Units), Format(pb.Total, pb.Units))
		} else {
			countersBox = Format(current, pb.Units) + " "
		}
	}

	// time left
	if pb.ShowTimeLeft && current > 0 {
		fromStart := time.Now().Sub(pb.startTime)
		perEntry := fromStart / time.Duration(current)
		left := time.Duration(pb.Total-current) * perEntry
		left = (left / time.Second) * time.Second
		if left > 0 {
			timeLeftBox = left.String()
		}
	}

	// speed
	if pb.ShowSpeed && current > 0 {
		fromStart := time.Now().Sub(pb.startTime)
		speed := float64(current) / (float64(fromStart) / float64(time.Second))
		speedBox = Format(int64(speed), pb.Units) + "/s "
	}

	// bar
	if pb.ShowBar {
		size := width - len(countersBox+pb.BarStart+pb.BarEnd+percentBox+timeLeftBox+speedBox)
		if size > 0 {
			curCount := int(math.Ceil((float64(current) / float64(pb.Total)) * float64(size)))
			emptCount := size - curCount
			barBox = pb.BarStart
			if emptCount < 0 {
				emptCount = 0
			}
			if curCount > size {
				curCount = size
			}
			if emptCount <= 0 {
				barBox += strings.Repeat(pb.Current, curCount)
			} else if curCount > 0 {
				barBox += strings.Repeat(pb.Current, curCount-1) + pb.CurrentN
			}

			barBox += strings.Repeat(pb.Empty, emptCount) + pb.BarEnd
		}
	}

	// check len
	out = countersBox + barBox + percentBox + speedBox + timeLeftBox
	if len(out) < width {
		end = strings.Repeat(" ", width-len(out))
	}

	out = countersBox + barBox + percentBox + speedBox + timeLeftBox

	// and print!
	switch {
	case pb.Output != nil:
		fmt.Fprint(pb.Output, out+end)
	case pb.Callback != nil:
		pb.Callback(out + end)
	case !pb.NotPrint:
		fmt.Print("\r" + out + end)
	}
}

func (pb *ProgressBar) writer() {
	var c, oc int64
	oc = -1
	for {
		if pb.isFinish {
			break
		}
		c = atomic.LoadInt64(&pb.current)
		if c != oc {
			pb.write(c)
			oc = c
		}
		time.Sleep(pb.RefreshRate)
	}
}

type window struct {
	Row    uint16
	Col    uint16
	Xpixel uint16
	Ypixel uint16
}
<commit_msg>finish should not do anything if called multiple times<commit_after>package pb

import (
	"fmt"
	"io"
	"math"
	"strings"
	"sync/atomic"
	"time"
)

const (
	// Default refresh rate - 200ms
	DEFAULT_REFRESH_RATE = time.Millisecond * 200
	FORMAT               = "[=>-]"
)

// DEPRECATED
// variables for backward compatibility, from now do not work
// use pb.Format and pb.SetRefreshRate
var (
	DefaultRefreshRate                         = DEFAULT_REFRESH_RATE
	BarStart, BarEnd, Empty, Current, CurrentN string
)

// Create new progress bar object
func New(total int) (pb *ProgressBar) {
	pb = &ProgressBar{
		Total:        int64(total),
		RefreshRate:  DEFAULT_REFRESH_RATE,
		ShowPercent:  true,
		ShowCounters: true,
		ShowBar:      true,
		ShowTimeLeft: true,
	}
	pb.Format(FORMAT)
	return
}

// Create new object and start
func StartNew(total int) (pb *ProgressBar) {
	pb = New(total)
	pb.Start()
	return
}

// Callback for custom output
// For example:
// bar.Callback = func(s string) {
//     mySuperPrint(s)
// }
//
type Callback func(out string)

type ProgressBar struct {
	current int64 // current must be first member of struct (https://code.google.com/p/go/issues/detail?id=5278)

	Total                            int64
	RefreshRate                      time.Duration
	ShowPercent, ShowCounters        bool
	ShowSpeed, ShowTimeLeft, ShowBar bool
	Output                           io.Writer
	Callback                         Callback
	NotPrint                         bool
	Units                            int

	isFinish  bool
	startTime time.Time

	BarStart string
	BarEnd   string
	Empty    string
	Current  string
	CurrentN string
}

// Start print
func (pb *ProgressBar) Start() {
	pb.startTime = time.Now()
	if pb.Total == 0 {
		pb.ShowBar = false
		pb.ShowTimeLeft = false
		pb.ShowPercent = false
	}
	go pb.writer()
}

// Increment current value
func (pb *ProgressBar) Increment() int {
	return pb.Add(1)
}

// Set current value
func (pb *ProgressBar) Set(current int) {
	atomic.StoreInt64(&pb.current, int64(current))
}

// Add to current value
func (pb *ProgressBar) Add(add int) int {
	return int(atomic.AddInt64(&pb.current, int64(add)))
}

// Set custom format for bar
// Example: bar.Format("[=>_]")
func (pb *ProgressBar) Format(format string) (bar *ProgressBar) {
	bar = pb
	formatEntries := strings.Split(format, "")
	if len(formatEntries) != 5 {
		return
	}
	pb.BarStart = formatEntries[0]
	pb.BarEnd = formatEntries[4]
	pb.Empty = formatEntries[3]
	pb.Current = formatEntries[1]
	pb.CurrentN = formatEntries[2]
	return
}

// Set bar refresh rate
func (pb *ProgressBar) SetRefreshRate(rate time.Duration) (bar *ProgressBar) {
	bar = pb
	pb.RefreshRate = rate
	return
}

// Set units
// bar.SetUnits(U_NO) - by default
// bar.SetUnits(U_BYTES) - for Mb, Kb, etc
func (pb *ProgressBar) SetUnits(units int) (bar *ProgressBar) {
	bar = pb
	switch units {
	case U_NO, U_BYTES:
		pb.Units = units
	}
	return
}

// Return true if finished
func (pb *ProgressBar) Finished() bool {
	return pb.isFinish
}

// End print
func (pb *ProgressBar) Finish() {
	if pb.isFinish {
		return
	}
	pb.isFinish = true
	pb.write(atomic.LoadInt64(&pb.current))
	if !pb.NotPrint {
		fmt.Println()
	}
}

// End print and write string 'str'
func (pb *ProgressBar) FinishPrint(str string) {
	pb.Finish()
	fmt.Println(str)
}

// implement io.Writer
func (pb *ProgressBar) Write(p []byte) (n int, err error) {
	n = len(p)
	pb.Add(n)
	return
}

// implement io.Reader
func (pb *ProgressBar) Read(p []byte) (n int, err error) {
	n = len(p)
	pb.Add(n)
	return
}

func (pb *ProgressBar) write(current int64) {
	width, _ := terminalWidth()
	var percentBox, countersBox, timeLeftBox, speedBox, barBox, end, out string

	// percents
	if pb.ShowPercent {
		percent := float64(current) / (float64(pb.Total) / float64(100))
		percentBox = fmt.Sprintf(" %#.02f %% ", percent)
	}

	// counters
	if pb.ShowCounters {
		if pb.Total > 0 {
			countersBox = fmt.Sprintf("%s / %s ", Format(current, pb.Units), Format(pb.Total, pb.Units))
		} else {
			countersBox = Format(current, pb.Units) + " "
		}
	}

	// time left
	if pb.ShowTimeLeft && current > 0 {
		fromStart := time.Now().Sub(pb.startTime)
		perEntry := fromStart / time.Duration(current)
		left := time.Duration(pb.Total-current) * perEntry
		left = (left / time.Second) * time.Second
		if left > 0 {
			timeLeftBox = left.String()
		}
	}

	// speed
	if pb.ShowSpeed && current > 0 {
		fromStart := time.Now().Sub(pb.startTime)
		speed := float64(current) / (float64(fromStart) / float64(time.Second))
		speedBox = Format(int64(speed), pb.Units) + "/s "
	}

	// bar
	if pb.ShowBar {
		size := width - len(countersBox+pb.BarStart+pb.BarEnd+percentBox+timeLeftBox+speedBox)
		if size > 0 {
			curCount := int(math.Ceil((float64(current) / float64(pb.Total)) * float64(size)))
			emptCount := size - curCount
			barBox = pb.BarStart
			if emptCount < 0 {
				emptCount = 0
			}
			if curCount > size {
				curCount = size
			}
			if emptCount <= 0 {
				barBox += strings.Repeat(pb.Current, curCount)
			} else if curCount > 0 {
				barBox += strings.Repeat(pb.Current, curCount-1) + pb.CurrentN
			}

			barBox += strings.Repeat(pb.Empty, emptCount) + pb.BarEnd
		}
	}

	// check len
	out = countersBox + barBox + percentBox + speedBox + timeLeftBox
	if len(out) < width {
		end = strings.Repeat(" ", width-len(out))
	}

	out = countersBox + barBox + percentBox + speedBox + timeLeftBox

	// and print!
	switch {
	case pb.Output != nil:
		fmt.Fprint(pb.Output, out+end)
	case pb.Callback != nil:
		pb.Callback(out + end)
	case !pb.NotPrint:
		fmt.Print("\r" + out + end)
	}
}

func (pb *ProgressBar) writer() {
	var c, oc int64
	oc = -1
	for {
		if pb.isFinish {
			break
		}
		c = atomic.LoadInt64(&pb.current)
		if c != oc {
			pb.write(c)
			oc = c
		}
		time.Sleep(pb.RefreshRate)
	}
}

type window struct {
	Row    uint16
	Col    uint16
	Xpixel uint16
	Ypixel uint16
}
<|endoftext|>