<commit_before>/*
Gapstone is a Go binding for the Capstone disassembly library. For examples,
try reading the *_test.go files.

	Library Author: Nguyen Anh Quynh
	Binding Author: Ben Nagy
	License: BSD style - see LICENSE file for details

(c) 2013 COSEINC. All Rights Reserved.
*/
package gapstone

// #cgo CFLAGS: -I/usr/include/capstone
// #cgo LDFLAGS: -lcapstone
// #include <stdlib.h>
// #include <capstone.h>
import "C"
import "unsafe"
import "reflect"
import "fmt"

type Errno int

func (e Errno) Error() string {
	s := errText[e]
	if s == "" {
		return fmt.Sprintf("cs_errno: %d (%v)", e, int(e))
	}
	return s
}

var (
	ErrOK     error = Errno(0)
	ErrOOM    error = Errno(1)
	ErrArch   error = Errno(2)
	ErrHandle error = Errno(3)
	ErrArg    error = Errno(4)
	ErrMode   error = Errno(5)
)

var errText = map[Errno]string{
	0: "cs_errno: 0 (No error)",
	1: "cs_errno: 1 (Out of Memory)",
	2: "cs_errno: 2 (Unsupported Architecture)",
	3: "cs_errno: 3 (Invalid Handle)",
	4: "cs_errno: 4 (Invalid Argument)",
	5: "cs_errno: 5 (Invalid Mode)",
}

// The arch and mode given at create time will determine how code is
// disassembled. After use you must close an Engine with engine.Close() to allow
// the C lib to free resources.
type Engine struct {
	handle C.csh
	arch   uint
	mode   uint
}

// Information that exists for every Instruction, regardless of arch. Structure
// members here will be promoted, so every Instruction will have them available.
type InstructionHeader struct {
	Id               uint
	Address          uint
	Size             uint
	Mnemonic         string
	OpStr            string
	RegistersRead    []uint
	RegistersWritten []uint
	Groups           []uint
}

// arch specific information will be filled in for exactly one of the
// substructures. Eg, an Engine created with New(CS_ARCH_ARM, CS_MODE_ARM) will
// fill in only the Arm structure member.
type Instruction struct {
	InstructionHeader
	Arm   ArmInstruction
	Arm64 Arm64Instruction
	Mips  MipsInstruction
	X86   X86Instruction
}

func fillGenericHeader(raw C.cs_insn, insn *Instruction) {
	insn.Id = uint(raw.id)
	insn.Address = uint(raw.address)
	insn.Size = uint(raw.size)
	insn.Mnemonic = C.GoString(&raw.mnemonic[0])
	insn.OpStr = C.GoString(&raw.op_str[0])
	for i := 0; i < int(raw.regs_read_count); i++ {
		insn.RegistersRead = append(insn.RegistersRead, uint(raw.regs_read[i]))
	}
	for i := 0; i < int(raw.regs_write_count); i++ {
		insn.RegistersWritten = append(insn.RegistersWritten, uint(raw.regs_write[i]))
	}
	for i := 0; i < int(raw.groups_count); i++ {
		insn.Groups = append(insn.Groups, uint(raw.groups[i]))
	}
}

// Close the underlying C handle and resources used by this Engine
func (e Engine) Close() error {
	res := C.cs_close(e.handle)
	return Errno(res)
}

// Accessor for the Engine architecture CS_ARCH_*
func (e Engine) Arch() uint { return e.arch }

// Accessor for the Engine mode CS_MODE_*
func (e Engine) Mode() uint { return e.mode }

// Version information.
func (e Engine) Version() (maj, min int) {
	C.cs_version((*C.int)(unsafe.Pointer(&maj)), (*C.int)(unsafe.Pointer(&min)))
	return
}

func (e Engine) Errno() error { return Errno(C.cs_errno(e.handle)) }

// The arch is implicit in the Engine. Accepts either a constant like ARM_REG_R0
// or insn.Arm.Operands[0].Reg, or anything that refers to a Register like
// insn.X86.SibBase etc
func (e Engine) RegName(reg uint) string {
	return C.GoString(C.cs_reg_name(e.handle, C.uint(reg)))
}

// The arch is implicit in the Engine. Accepts a constant like
// ARM_INSN_ADD, or insn.Id
func (e Engine) InsnName(insn uint) string {
	return C.GoString(C.cs_insn_name(e.handle, C.uint(insn)))
}

// Setter for Engine options CS_OPT_*
func (e Engine) SetOption(ty, value uint) error {
	res := C.cs_option(
		e.handle,
		C.cs_opt_type(ty),
		C.size_t(value),
	)

	if Errno(res) == ErrOK {
		return nil
	}
	return Errno(res)
}

// Disassemble a []byte full of opcodes.
//   * address - Address of the first instruction in the given code buffer.
//   * count - Number of instructions to disassemble, 0 to disassemble the whole []byte
//
// Underlying C resources are automatically free'd by this function.
func (e Engine) Disasm(input []byte, address, count uint64) ([]Instruction, error) {

	var insn *C.cs_insn
	bptr := (*C.uchar)(unsafe.Pointer(&input[0]))
	disassembled := C.cs_disasm_dyn(
		e.handle,
		bptr,
		C.size_t(len(input)),
		C.uint64_t(address),
		C.size_t(count),
		&insn,
	)

	if disassembled > 0 {
		defer C.cs_free(unsafe.Pointer(insn))
		// Create a slice, and reflect its header
		var insns []C.cs_insn
		h := (*reflect.SliceHeader)(unsafe.Pointer(&insns))
		// Manually fill in the ptr, len and cap from the raw C data
		h.Data = uintptr(unsafe.Pointer(insn))
		h.Len = int(disassembled)
		h.Cap = int(disassembled)

		switch e.arch {
		case CS_ARCH_ARM:
			return decomposeArm(insns), nil
		case CS_ARCH_ARM64:
			return decomposeArm64(insns), nil
		case CS_ARCH_MIPS:
			return decomposeMips(insns), nil
		case CS_ARCH_X86:
			return decomposeX86(insns), nil
		default:
			return []Instruction{}, ErrArch
		}
	}
	return []Instruction{}, e.Errno()
}

// Create a new Engine with the specified arch and mode
func New(arch, mode uint) (Engine, error) {
	var handle C.csh
	res := C.cs_open(C.cs_arch(arch), C.cs_mode(mode), &handle)
	if Errno(res) == ErrOK {
		return Engine{handle, arch, mode}, nil
	}
	return Engine{0, CS_ARCH_MAX, 0}, Errno(res)
}
<commit_msg>add support for cs_insn->bytes and CS_ERR_OPTION<commit_after>/*
Gapstone is a Go binding for the Capstone disassembly library. For examples,
try reading the *_test.go files.

	Library Author: Nguyen Anh Quynh
	Binding Author: Ben Nagy
	License: BSD style - see LICENSE file for details

(c) 2013 COSEINC. All Rights Reserved.
*/
package gapstone

// #cgo CFLAGS: -I/usr/include/capstone
// #cgo LDFLAGS: -lcapstone
// #include <stdlib.h>
// #include <capstone.h>
import "C"
import "unsafe"
import "reflect"
import "fmt"

type Errno int

func (e Errno) Error() string {
	s := errText[e]
	if s == "" {
		return fmt.Sprintf("cs_errno: %d (%v)", e, int(e))
	}
	return s
}

var (
	ErrOK     error = Errno(0)
	ErrOOM    error = Errno(1)
	ErrArch   error = Errno(2)
	ErrHandle error = Errno(3)
	ErrArg    error = Errno(4)
	ErrMode   error = Errno(5)
	ErrOption error = Errno(6)
)

var errText = map[Errno]string{
	0: "cs_errno: 0 (No error)",
	1: "cs_errno: 1 (Out of Memory)",
	2: "cs_errno: 2 (Unsupported Architecture)",
	3: "cs_errno: 3 (Invalid Handle)",
	4: "cs_errno: 4 (Invalid Argument)",
	5: "cs_errno: 5 (Invalid Mode)",
	6: "cs_errno: 6 (Invalid Option)",
}

// The arch and mode given at create time will determine how code is
// disassembled. After use you must close an Engine with engine.Close() to allow
// the C lib to free resources.
type Engine struct {
	handle C.csh
	arch   uint
	mode   uint
}

// Information that exists for every Instruction, regardless of arch. Structure
// members here will be promoted, so every Instruction will have them available.
type InstructionHeader struct {
	Id               uint
	Address          uint
	Size             uint
	Bytes            []byte
	Mnemonic         string
	OpStr            string
	RegistersRead    []uint
	RegistersWritten []uint
	Groups           []uint
}

// arch specific information will be filled in for exactly one of the
// substructures. Eg, an Engine created with New(CS_ARCH_ARM, CS_MODE_ARM) will
// fill in only the Arm structure member.
type Instruction struct {
	InstructionHeader
	Arm   ArmInstruction
	Arm64 Arm64Instruction
	Mips  MipsInstruction
	X86   X86Instruction
}

func fillGenericHeader(raw C.cs_insn, insn *Instruction) {

	insn.Id = uint(raw.id)
	insn.Address = uint(raw.address)
	insn.Size = uint(raw.size)
	insn.Mnemonic = C.GoString(&raw.mnemonic[0])
	insn.OpStr = C.GoString(&raw.op_str[0])

	for i := 0; i < int(raw.regs_read_count); i++ {
		insn.RegistersRead = append(insn.RegistersRead, uint(raw.regs_read[i]))
	}

	for i := 0; i < int(raw.regs_write_count); i++ {
		insn.RegistersWritten = append(insn.RegistersWritten, uint(raw.regs_write[i]))
	}

	for i := 0; i < int(raw.groups_count); i++ {
		insn.Groups = append(insn.Groups, uint(raw.groups[i]))
	}

	var bslice []byte
	h := (*reflect.SliceHeader)(unsafe.Pointer(&bslice))
	h.Data = uintptr(unsafe.Pointer(&raw.bytes[0]))
	h.Len = int(raw.size)
	h.Cap = int(raw.size)
	insn.Bytes = bslice

}

// Close the underlying C handle and resources used by this Engine
func (e Engine) Close() error {
	res := C.cs_close(e.handle)
	return Errno(res)
}

// Accessor for the Engine architecture CS_ARCH_*
func (e Engine) Arch() uint { return e.arch }

// Accessor for the Engine mode CS_MODE_*
func (e Engine) Mode() uint { return e.mode }

// Version information.
func (e Engine) Version() (maj, min int) {
	C.cs_version((*C.int)(unsafe.Pointer(&maj)), (*C.int)(unsafe.Pointer(&min)))
	return
}

func (e Engine) Errno() error { return Errno(C.cs_errno(e.handle)) }

// The arch is implicit in the Engine. Accepts either a constant like ARM_REG_R0
// or insn.Arm.Operands[0].Reg, or anything that refers to a Register like
// insn.X86.SibBase etc
func (e Engine) RegName(reg uint) string {
	return C.GoString(C.cs_reg_name(e.handle, C.uint(reg)))
}

// The arch is implicit in the Engine. Accepts a constant like
// ARM_INSN_ADD, or insn.Id
func (e Engine) InsnName(insn uint) string {
	return C.GoString(C.cs_insn_name(e.handle, C.uint(insn)))
}

// Setter for Engine options CS_OPT_*
func (e Engine) SetOption(ty, value uint) error {
	res := C.cs_option(
		e.handle,
		C.cs_opt_type(ty),
		C.size_t(value),
	)

	if Errno(res) == ErrOK {
		return nil
	}
	return Errno(res)
}

// Disassemble a []byte full of opcodes.
//   * address - Address of the first instruction in the given code buffer.
//   * count - Number of instructions to disassemble, 0 to disassemble the whole []byte
//
// Underlying C resources are automatically free'd by this function.
func (e Engine) Disasm(input []byte, address, count uint64) ([]Instruction, error) {

	var insn *C.cs_insn
	bptr := (*C.uchar)(unsafe.Pointer(&input[0]))
	disassembled := C.cs_disasm_dyn(
		e.handle,
		bptr,
		C.size_t(len(input)),
		C.uint64_t(address),
		C.size_t(count),
		&insn,
	)

	if disassembled > 0 {
		defer C.cs_free(unsafe.Pointer(insn))
		// Create a slice, and reflect its header
		var insns []C.cs_insn
		h := (*reflect.SliceHeader)(unsafe.Pointer(&insns))
		// Manually fill in the ptr, len and cap from the raw C data
		h.Data = uintptr(unsafe.Pointer(insn))
		h.Len = int(disassembled)
		h.Cap = int(disassembled)

		switch e.arch {
		case CS_ARCH_ARM:
			return decomposeArm(insns), nil
		case CS_ARCH_ARM64:
			return decomposeArm64(insns), nil
		case CS_ARCH_MIPS:
			return decomposeMips(insns), nil
		case CS_ARCH_X86:
			return decomposeX86(insns), nil
		default:
			return []Instruction{}, ErrArch
		}
	}
	return []Instruction{}, e.Errno()
}

// Create a new Engine with the specified arch and mode
func New(arch, mode uint) (Engine, error) {
	var handle C.csh
	res := C.cs_open(C.cs_arch(arch), C.cs_mode(mode), &handle)
	if Errno(res) == ErrOK {
		return Engine{handle, arch, mode}, nil
	}
	return Engine{0, CS_ARCH_MAX, 0}, Errno(res)
}
<|endoftext|>


<commit_before>// +build nacl

package websocket

import (
	"fmt"
	"net"
)

// Websocket listeners are not supported in NaCl.
// This file is needed for compilation only.

func Listener(protocol, address string) (net.Listener, error) {
	return nil, fmt.Errorf("Websocket Listener called in nacl code!")
}
<commit_msg>veyron/lib/websocket: fix build CL 8510.<commit_after>// +build nacl

package websocket

import (
	"fmt"
	"net"
)

// Websocket listeners are not supported in NaCl.
// This file is needed for compilation only.
func listener(protocol, address string, hybrid bool) (net.Listener, error) {
	return nil, fmt.Errorf("Websocket Listener called in nacl code!")
}

func Listener(protocol, address string) (net.Listener, error) {
	return nil, fmt.Errorf("Websocket Listener called in nacl code!")
}
<|endoftext|>


<commit_before>package runtimectl

import (
	"github.com/graniticio/granitic/ctl"
	"github.com/graniticio/granitic/instance"
	"github.com/graniticio/granitic/logging"
	"github.com/graniticio/granitic/ws"
	"sort"
)

const (
	LLComponentName = instance.FrameworkPrefix + "CommandLogLevel"
	llCommandName   = "log-level"
	llSummary       = "Views or sets a specific logging threshold for application or framework components."
	llUsage         = "log-level [component level] [-fw true]"
	llHelp          = "With no qualifier, this command shows a list of application components that have a specific logging threshold set. When a " +
		"component and a level are specified as qualifiers, the component's logging threshold is set at the specified level."
	llHelpTwo   = "Valid values for level are ALL, TRACE, DEBUG, INFO, WARN, ERROR, FATAL (case insensitive)."
	llHelpThree = "Setting the level to ALL has special behaviour - it efffectively removes the specific logging threshold for the component. The global log threshold will then apply to that component."
	llHelpFour  = "If the '-fw true' argument is supplied without qualifiers, a list of built-in framework components and their associated log levels will be shown."
)

type LogLevelCommand struct {
	FrameworkLogger    logging.Logger
	FrameworkManager   *logging.ComponentLoggerManager
	ApplicationManager *logging.ComponentLoggerManager
}

func (c *LogLevelCommand) ExecuteCommand(qualifiers []string, args map[string]string) (*ctl.CommandOutcome, []*ws.CategorisedError) {

	if len(qualifiers) == 0 {
		return c.showCurrentLevel(args)
	}

	return nil, nil
}

func (c *LogLevelCommand) showCurrentLevel(args map[string]string) (*ctl.CommandOutcome, []*ws.CategorisedError) {

	var comps []*logging.ComponentLevel
	var err error
	var frameworkLevels bool

	if frameworkLevels, err = operateOnFramework(args); err != nil {
		return nil, []*ws.CategorisedError{ctl.NewCommandClientError(err.Error())}
	}

	if frameworkLevels {
		comps = c.FrameworkManager.CurrentLevels()
	} else {
		comps = c.ApplicationManager.CurrentLevels()
	}

	sort.Sort(logging.ByName{comps})

	filtered := make([][]string, 0)

	for _, cl := range comps {

		if cl.Level != logging.All {
			filtered = append(filtered, []string{cl.Name, logging.LabelFromLevel(cl.Level)})
		}

	}

	co := new(ctl.CommandOutcome)
	co.OutputBody = filtered
	co.RenderHint = ctl.Columns

	return co, nil
}

func (c *LogLevelCommand) Name() string {
	return llCommandName
}

func (c *LogLevelCommand) Summmary() string {
	return llSummary
}

func (c *LogLevelCommand) Usage() string {
	return llUsage
}

func (c *LogLevelCommand) Help() []string {
	return []string{llHelp, llHelpTwo, llHelpThree, llHelpFour}
}
<commit_msg>Logging refactoring and commands<commit_after>package runtimectl

import (
	"fmt"
	"github.com/graniticio/granitic/ctl"
	"github.com/graniticio/granitic/instance"
	"github.com/graniticio/granitic/logging"
	"github.com/graniticio/granitic/ws"
	"sort"
)

const (
	LLComponentName = instance.FrameworkPrefix + "CommandLogLevel"
	llCommandName   = "log-level"
	llSummary       = "Views or sets a specific logging threshold for application or framework components."
	llUsage         = "log-level [component level] [-fw true]"
	llHelp          = "With no qualifier, this command shows a list of application components that have a specific logging threshold set. When a " +
		"component and a level are specified as qualifiers, the component's logging threshold is set at the specified level."
	llHelpTwo   = "Valid values for level are ALL, TRACE, DEBUG, INFO, WARN, ERROR, FATAL (case insensitive)."
	llHelpThree = "Setting the level to ALL has special behaviour - it efffectively removes the specific logging threshold for the component. The global log threshold will then apply to that component."
	llHelpFour  = "If the '-fw true' argument is supplied without qualifiers, a list of built-in framework components and their associated log levels will be shown."
)

type LogLevelCommand struct {
	FrameworkLogger    logging.Logger
	FrameworkManager   *logging.ComponentLoggerManager
	ApplicationManager *logging.ComponentLoggerManager
}

func (c *LogLevelCommand) ExecuteCommand(qualifiers []string, args map[string]string) (*ctl.CommandOutcome, []*ws.CategorisedError) {

	if len(qualifiers) == 0 {
		return c.showCurrentLevel(args)
	} else {
		return c.setLevel(qualifiers)
	}
}

func (c *LogLevelCommand) setLevel(qualifiers []string) (*ctl.CommandOutcome, []*ws.CategorisedError) {

	var err error
	var ll logging.LogLevel

	if len(qualifiers) < 2 {
		return nil, []*ws.CategorisedError{ctl.NewCommandClientError("You must provide a component name and a loging level.")}
	}

	name := qualifiers[0]
	label := qualifiers[1]

	if ll, err = logging.LogLevelFromLabel(label); err != nil {
		return nil, []*ws.CategorisedError{ctl.NewCommandClientError(err.Error())}
	}

	logger := c.ApplicationManager.LoggerByName(name)

	if logger == nil {
		logger = c.FrameworkManager.LoggerByName(name)
	}

	if logger == nil {
		m := fmt.Sprintf("Component %s does not exist or does not have a logger attached.", name)
		return nil, []*ws.CategorisedError{ctl.NewCommandClientError(m)}
	}

	logger.SetLocalThreshold(ll)

	return new(ctl.CommandOutcome), nil

}

func (c *LogLevelCommand) showCurrentLevel(args map[string]string) (*ctl.CommandOutcome, []*ws.CategorisedError) {

	var comps []*logging.ComponentLevel
	var err error
	var frameworkLevels bool

	if frameworkLevels, err = operateOnFramework(args); err != nil {
		return nil, []*ws.CategorisedError{ctl.NewCommandClientError(err.Error())}
	}

	if frameworkLevels {
		comps = c.FrameworkManager.CurrentLevels()
	} else {
		comps = c.ApplicationManager.CurrentLevels()
	}

	sort.Sort(logging.ByName{comps})

	filtered := make([][]string, 0)

	for _, cl := range comps {

		if cl.Level != logging.All {
			filtered = append(filtered, []string{cl.Name, logging.LabelFromLevel(cl.Level)})
		}

	}

	co := new(ctl.CommandOutcome)
	co.OutputBody = filtered
	co.RenderHint = ctl.Columns

	return co, nil
}

func (c *LogLevelCommand) Name() string {
	return llCommandName
}

func (c *LogLevelCommand) Summmary() string {
	return llSummary
}

func (c *LogLevelCommand) Usage() string {
	return llUsage
}

func (c *LogLevelCommand) Help() []string {
	return []string{llHelp, llHelpTwo, llHelpThree, llHelpFour}
}
<|endoftext|>


<commit_before>/*
 * Copyright 2017 Dgraph Labs, Inc. and Contributors
 *
 * 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 badger

import (
	"encoding/hex"

	"github.com/pkg/errors"
)

var (
	// ErrValueLogSize is returned when opt.ValueLogFileSize option is not within the valid
	// range.
	ErrValueLogSize = errors.New("Invalid ValueLogFileSize, must be between 1MB and 2GB")

	// ErrValueThreshold is returned when ValueThreshold is set to a value close to or greater than
	// uint16.
	ErrValueThreshold = errors.New("Invalid ValueThreshold, must be lower than uint16.")

	// ErrKeyNotFound is returned when key isn't found on a txn.Get.
	ErrKeyNotFound = errors.New("Key not found")

	// ErrTxnTooBig is returned if too many writes are fit into a single transaction.
	ErrTxnTooBig = errors.New("Txn is too big to fit into one request")

	// ErrConflict is returned when a transaction conflicts with another transaction. This can happen if
	// the read rows had been updated concurrently by another transaction.
	ErrConflict = errors.New("Transaction Conflict. Please retry")

	// ErrReadOnlyTxn is returned if an update function is called on a read-only transaction.
	ErrReadOnlyTxn = errors.New("No sets or deletes are allowed in a read-only transaction")

	// ErrDiscardedTxn is returned if a previously discarded transaction is re-used.
	ErrDiscardedTxn = errors.New("This transaction has been discarded. Create a new one")

	// ErrEmptyKey is returned if an empty key is passed on an update function.
	ErrEmptyKey = errors.New("Key cannot be empty")

	// ErrRetry is returned when a log file containing the value is not found.
	// This usually indicates that it may have been garbage collected, and the
	// operation needs to be retried.
	ErrRetry = errors.New("Unable to find log file. Please retry")

	// ErrThresholdZero is returned if threshold is set to zero, and value log GC is called.
	// In such a case, GC can't be run.
	ErrThresholdZero = errors.New(
		"Value log GC can't run because threshold is set to zero")

	// ErrNoRewrite is returned if a call for value log GC doesn't result in a log file rewrite.
	ErrNoRewrite = errors.New(
		"Value log GC attempt didn't result in any cleanup")

	// ErrRejected is returned if a value log GC is called either while another GC is running, or
	// after DB::Close has been called.
	ErrRejected = errors.New("Value log GC request rejected")

	// ErrInvalidRequest is returned if the user request is invalid.
	ErrInvalidRequest = errors.New("Invalid request")

	// ErrManagedTxn is returned if the user tries to use an API which isn't
	// allowed due to external management of transactions, when using ManagedDB.
	ErrManagedTxn = errors.New(
		"Invalid API request. Not allowed to perform this action using ManagedDB")

	// ErrInvalidDump if a data dump made previously cannot be loaded into the database.
	ErrInvalidDump = errors.New("Data dump cannot be read")

	// ErrZeroBandwidth is returned if the user passes in zero bandwidth for sequence.
	ErrZeroBandwidth = errors.New("Bandwidth must be greater than zero")

	// ErrInvalidLoadingMode is returned when opt.ValueLogLoadingMode option is not
	// within the valid range
	ErrInvalidLoadingMode = errors.New("Invalid ValueLogLoadingMode, must be FileIO or MemoryMap")

	// ErrReplayNeeded is returned when opt.ReadOnly is set but the
	// database requires a value log replay.
	ErrReplayNeeded = errors.New("Database was not properly closed, cannot open read-only")

	// ErrWindowsNotSupported is returned when opt.ReadOnly is used on Windows
	ErrWindowsNotSupported = errors.New("Read-only mode is not supported on Windows")

	// ErrTruncateNeeded is returned when the value log gets corrupt, and requires truncation of
	// corrupt data to allow Badger to run properly.
	ErrTruncateNeeded = errors.New("Data corruption detected. Value log truncate required to run DB. This would result in data loss.")
)

// Key length can't be more than uint16, as determined by table::header.
const maxKeySize = 1<<16 - 8 // 8 bytes are for storing timestamp

func exceedsMaxKeySizeError(key []byte) error {
	return errors.Errorf("Key with size %d exceeded %d limit. Key:\n%s",
		len(key), maxKeySize, hex.Dump(key[:1<<10]))
}

func exceedsMaxValueSizeError(value []byte, maxValueSize int64) error {
	return errors.Errorf("Value with size %d exceeded ValueLogFileSize (%d). Key:\n%s",
		len(value), maxValueSize, hex.Dump(value[:1<<10]))
}
<commit_msg>Fix the wordings of error message.<commit_after>/*
 * Copyright 2017 Dgraph Labs, Inc. and Contributors
 *
 * 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 badger

import (
	"encoding/hex"

	"github.com/pkg/errors"
)

var (
	// ErrValueLogSize is returned when opt.ValueLogFileSize option is not within the valid
	// range.
	ErrValueLogSize = errors.New("Invalid ValueLogFileSize, must be between 1MB and 2GB")

	// ErrValueThreshold is returned when ValueThreshold is set to a value close to or greater than
	// uint16.
	ErrValueThreshold = errors.New("Invalid ValueThreshold, must be lower than uint16.")

	// ErrKeyNotFound is returned when key isn't found on a txn.Get.
	ErrKeyNotFound = errors.New("Key not found")

	// ErrTxnTooBig is returned if too many writes are fit into a single transaction.
	ErrTxnTooBig = errors.New("Txn is too big to fit into one request")

	// ErrConflict is returned when a transaction conflicts with another transaction. This can happen if
	// the read rows had been updated concurrently by another transaction.
	ErrConflict = errors.New("Transaction Conflict. Please retry")

	// ErrReadOnlyTxn is returned if an update function is called on a read-only transaction.
	ErrReadOnlyTxn = errors.New("No sets or deletes are allowed in a read-only transaction")

	// ErrDiscardedTxn is returned if a previously discarded transaction is re-used.
	ErrDiscardedTxn = errors.New("This transaction has been discarded. Create a new one")

	// ErrEmptyKey is returned if an empty key is passed on an update function.
	ErrEmptyKey = errors.New("Key cannot be empty")

	// ErrRetry is returned when a log file containing the value is not found.
	// This usually indicates that it may have been garbage collected, and the
	// operation needs to be retried.
	ErrRetry = errors.New("Unable to find log file. Please retry")

	// ErrThresholdZero is returned if threshold is set to zero, and value log GC is called.
	// In such a case, GC can't be run.
	ErrThresholdZero = errors.New(
		"Value log GC can't run because threshold is set to zero")

	// ErrNoRewrite is returned if a call for value log GC doesn't result in a log file rewrite.
	ErrNoRewrite = errors.New(
		"Value log GC attempt didn't result in any cleanup")

	// ErrRejected is returned if a value log GC is called either while another GC is running, or
	// after DB::Close has been called.
	ErrRejected = errors.New("Value log GC request rejected")

	// ErrInvalidRequest is returned if the user request is invalid.
	ErrInvalidRequest = errors.New("Invalid request")

	// ErrManagedTxn is returned if the user tries to use an API which isn't
	// allowed due to external management of transactions, when using ManagedDB.
	ErrManagedTxn = errors.New(
		"Invalid API request. Not allowed to perform this action using ManagedDB")

	// ErrInvalidDump if a data dump made previously cannot be loaded into the database.
	ErrInvalidDump = errors.New("Data dump cannot be read")

	// ErrZeroBandwidth is returned if the user passes in zero bandwidth for sequence.
	ErrZeroBandwidth = errors.New("Bandwidth must be greater than zero")

	// ErrInvalidLoadingMode is returned when opt.ValueLogLoadingMode option is not
	// within the valid range
	ErrInvalidLoadingMode = errors.New("Invalid ValueLogLoadingMode, must be FileIO or MemoryMap")

	// ErrReplayNeeded is returned when opt.ReadOnly is set but the
	// database requires a value log replay.
	ErrReplayNeeded = errors.New("Database was not properly closed, cannot open read-only")

	// ErrWindowsNotSupported is returned when opt.ReadOnly is used on Windows
	ErrWindowsNotSupported = errors.New("Read-only mode is not supported on Windows")

	// ErrTruncateNeeded is returned when the value log gets corrupt, and requires truncation of
	// corrupt data to allow Badger to run properly.
	ErrTruncateNeeded = errors.New("Value log truncate required to run DB. This might result in data loss.")
)

// Key length can't be more than uint16, as determined by table::header.
const maxKeySize = 1<<16 - 8 // 8 bytes are for storing timestamp

func exceedsMaxKeySizeError(key []byte) error {
	return errors.Errorf("Key with size %d exceeded %d limit. Key:\n%s",
		len(key), maxKeySize, hex.Dump(key[:1<<10]))
}

func exceedsMaxValueSizeError(value []byte, maxValueSize int64) error {
	return errors.Errorf("Value with size %d exceeded ValueLogFileSize (%d). Key:\n%s",
		len(value), maxValueSize, hex.Dump(value[:1<<10]))
}
<|endoftext|>


<commit_before>package errors

import (
	"fmt"

	"github.com/Sirupsen/logrus"
)

type Error interface {
	Status() int
	Error() string
	Code() string
	NotFound() bool
	BadRequest() bool
	Unauthorized() bool
	Forbidden() bool
	Logrus(err error) *logrus.Entry
}

type Errors struct {
	ErrStatus  int    `json:"-"`
	ErrMessage string `json:"message"`
	ErrCode    string `json:"code,omitempty"`
}

func (e *Errors) Logrus(err error) *logrus.Entry {
	return logrus.WithField("code", e.Code()).WithError(err)
}

func (e *Errors) NotFound() bool {
	if e.ErrStatus == 404 {
		return true
	}

	return false
}

func (e *Errors) BadRequest() bool {
	if e.ErrStatus == 400 {
		return true
	}

	return false
}

func (e *Errors) Unauthorized() bool {
	if e.ErrStatus == 401 {
		return true
	}

	return false
}

func (e *Errors) Forbidden() bool {
	if e.ErrStatus == 403 {
		return true
	}

	return false
}

func (e *Errors) Status() int {
	return e.ErrStatus
}

func (e *Errors) Code() string {
	return e.ErrCode
}

func (e *Errors) Error() string {
	return e.ErrMessage
}

func New(message string) Error {
	return &Errors{
		ErrStatus:  500,
		ErrMessage: message,
	}
}

func NewStatus(status int, message string) Error {
	return &Errors{
		ErrStatus:  status,
		ErrMessage: message,
	}
}

func NewStatusf(status int, format string, v ...interface{}) Error {
	return &Errors{
		ErrStatus:  status,
		ErrMessage: fmt.Sprintf(format, v...),
	}
}

func Newf(format string, v ...interface{}) Error {
	return &Errors{
		ErrStatus:  500,
		ErrMessage: fmt.Sprintf(format, v...),
	}
}

func BadRequest(message string) Error {
	return &Errors{
		ErrStatus:  400,
		ErrMessage: message,
	}
}

func Unauthorized(message string) Error {
	return &Errors{
		ErrStatus:  401,
		ErrMessage: message,
	}
}

func Forbidden(message string) Error {
	return &Errors{
		ErrStatus:  403,
		ErrMessage: message,
	}
}

func NotFound(message string) Error {
	return &Errors{
		ErrStatus:  404,
		ErrMessage: message,
	}
}

func InternalError(message string) Error {
	return &Errors{
		ErrStatus:  500,
		ErrMessage: message,
	}
}

func BadRequestf(format string, v ...interface{}) Error {
	return &Errors{
		ErrStatus:  400,
		ErrMessage: fmt.Sprintf(format, v...),
	}
}

func Unauthorizedf(format string, v ...interface{}) Error {
	return &Errors{
		ErrStatus:  401,
		ErrMessage: fmt.Sprintf(format, v...),
	}
}

func Forbiddenf(format string, v ...interface{}) Error {
	return &Errors{
		ErrStatus:  403,
		ErrMessage: fmt.Sprintf(format, v...),
	}
}

func NotFoundf(format string, v ...interface{}) Error {
	return &Errors{
		ErrStatus:  404,
		ErrMessage: fmt.Sprintf(format, v...),
	}
}

func InternalErrorf(format string, v ...interface{}) Error {
	return &Errors{
		ErrStatus:  500,
		ErrMessage: fmt.Sprintf(format, v...),
	}
}

// With Code

func NewCode(code string, message string) Error {
	return &Errors{
		ErrStatus:  500,
		ErrCode:    code,
		ErrMessage: message,
	}
}

func NewStatusCode(status int, code, message string) Error {
	return &Errors{
		ErrStatus:  500,
		ErrCode:    code,
		ErrMessage: message,
	}
}

func NewStatusCodef(status int, code, format string, v ...interface{}) Error {
	return &Errors{
		ErrStatus:  status,
		ErrCode:    code,
		ErrMessage: fmt.Sprintf(format, v...),
	}
}

func NewCodef(code, format string, v ...interface{}) Error {
	return &Errors{
		ErrStatus:  500,
		ErrCode:    code,
		ErrMessage: fmt.Sprintf(format, v...),
	}
}

func BadRequestCode(code, message string) Error {
	return &Errors{
		ErrStatus:  400,
		ErrCode:    code,
		ErrMessage: message,
	}
}

func UnauthorizedCode(code, message string) Error {
	return &Errors{
		ErrStatus:  401,
		ErrCode:    code,
		ErrMessage: message,
	}
}

func ForbiddenCode(code, message string) Error {
	return &Errors{
		ErrStatus:  403,
		ErrCode:    code,
		ErrMessage: message,
	}
}

func NotFoundCode(code, message string) Error {
	return &Errors{
		ErrStatus:  404,
		ErrCode:    code,
		ErrMessage: message,
	}
}

func InternalErrorCode(code, message string) Error {
	return &Errors{
		ErrStatus:  500,
		ErrCode:    code,
		ErrMessage: message,
	}
}

func BadRequestCodef(code, format string, v ...interface{}) Error {
	return &Errors{
		ErrStatus:  400,
		ErrCode:    code,
		ErrMessage: fmt.Sprintf(format, v...),
	}
}

func UnauthorizedCodef(code, format string, v ...interface{}) Error {
	return &Errors{
		ErrStatus:  401,
		ErrCode:    code,
		ErrMessage: fmt.Sprintf(format, v...),
	}
}

func ForbiddenCodef(code, format string, v ...interface{}) Error {
	return &Errors{
		ErrStatus:  403,
		ErrCode:    code,
		ErrMessage: fmt.Sprintf(format, v...),
	}
}

func NotFoundCodef(code, format string, v ...interface{}) Error {
	return &Errors{
		ErrStatus:  404,
		ErrCode:    code,
		ErrMessage: fmt.Sprintf(format, v...),
	}
}

func InternalErrorCodef(code, format string, v ...interface{}) Error {
	return &Errors{
		ErrStatus:  500,
		ErrCode:    code,
		ErrMessage: fmt.Sprintf(format, v...),
	}
}

func IsNotFound(err error) bool {
	if cerr, ok := err.(Error); ok && cerr.Status() == 404 {
		return true
	}

	return false
}
<commit_msg>add logrus<commit_after>package errors

import (
	"fmt"

	"github.com/Sirupsen/logrus"
)

type Error interface {
	Status() int
	Error() string
	Code() string
	NotFound() bool
	BadRequest() bool
	Unauthorized() bool
	Forbidden() bool
	Logrus() *logrus.Entry
}

type Errors struct {
	ErrStatus  int    `json:"-"`
	ErrMessage string `json:"message"`
	ErrCode    string `json:"code,omitempty"`
}

func (e *Errors) Logrus() *logrus.Entry {
	return logrus.WithField("code", e.Code())
}

func (e *Errors) NotFound() bool {
	if e.ErrStatus == 404 {
		return true
	}

	return false
}

func (e *Errors) BadRequest() bool {
	if e.ErrStatus == 400 {
		return true
	}

	return false
}

func (e *Errors) Unauthorized() bool {
	if e.ErrStatus == 401 {
		return true
	}

	return false
}

func (e *Errors) Forbidden() bool {
	if e.ErrStatus == 403 {
		return true
	}

	return false
}

func (e *Errors) Status() int {
	return e.ErrStatus
}

func (e *Errors) Code() string {
	return e.ErrCode
}

func (e *Errors) Error() string {
	return e.ErrMessage
}

func New(message string) Error {
	return &Errors{
		ErrStatus:  500,
		ErrMessage: message,
	}
}

func NewStatus(status int, message string) Error {
	return &Errors{
		ErrStatus:  status,
		ErrMessage: message,
	}
}

func NewStatusf(status int, format string, v ...interface{}) Error {
	return &Errors{
		ErrStatus:  status,
		ErrMessage: fmt.Sprintf(format, v...),
	}
}

func Newf(format string, v ...interface{}) Error {
	return &Errors{
		ErrStatus:  500,
		ErrMessage: fmt.Sprintf(format, v...),
	}
}

func BadRequest(message string) Error {
	return &Errors{
		ErrStatus:  400,
		ErrMessage: message,
	}
}

func Unauthorized(message string) Error {
	return &Errors{
		ErrStatus:  401,
		ErrMessage: message,
	}
}

func Forbidden(message string) Error {
	return &Errors{
		ErrStatus:  403,
		ErrMessage: message,
	}
}

func NotFound(message string) Error {
	return &Errors{
		ErrStatus:  404,
		ErrMessage: message,
	}
}

func InternalError(message string) Error {
	return &Errors{
		ErrStatus:  500,
		ErrMessage: message,
	}
}

func BadRequestf(format string, v ...interface{}) Error {
	return &Errors{
		ErrStatus:  400,
		ErrMessage: fmt.Sprintf(format, v...),
	}
}

func Unauthorizedf(format string, v ...interface{}) Error {
	return &Errors{
		ErrStatus:  401,
		ErrMessage: fmt.Sprintf(format, v...),
	}
}

func Forbiddenf(format string, v ...interface{}) Error {
	return &Errors{
		ErrStatus:  403,
		ErrMessage: fmt.Sprintf(format, v...),
	}
}

func NotFoundf(format string, v ...interface{}) Error {
	return &Errors{
		ErrStatus:  404,
		ErrMessage: fmt.Sprintf(format, v...),
	}
}

func InternalErrorf(format string, v ...interface{}) Error {
	return &Errors{
		ErrStatus:  500,
		ErrMessage: fmt.Sprintf(format, v...),
	}
}

// With Code

func NewCode(code string, message string) Error {
	return &Errors{
		ErrStatus:  500,
		ErrCode:    code,
		ErrMessage: message,
	}
}

func NewStatusCode(status int, code, message string) Error {
	return &Errors{
		ErrStatus:  500,
		ErrCode:    code,
		ErrMessage: message,
	}
}

func NewStatusCodef(status int, code, format string, v ...interface{}) Error {
	return &Errors{
		ErrStatus:  status,
		ErrCode:    code,
		ErrMessage: fmt.Sprintf(format, v...),
	}
}

func NewCodef(code, format string, v ...interface{}) Error {
	return &Errors{
		ErrStatus:  500,
		ErrCode:    code,
		ErrMessage: fmt.Sprintf(format, v...),
	}
}

func BadRequestCode(code, message string) Error {
	return &Errors{
		ErrStatus:  400,
		ErrCode:    code,
		ErrMessage: message,
	}
}

func UnauthorizedCode(code, message string) Error {
	return &Errors{
		ErrStatus:  401,
		ErrCode:    code,
		ErrMessage: message,
	}
}

func ForbiddenCode(code, message string) Error {
	return &Errors{
		ErrStatus:  403,
		ErrCode:    code,
		ErrMessage: message,
	}
}

func NotFoundCode(code, message string) Error {
	return &Errors{
		ErrStatus:  404,
		ErrCode:    code,
		ErrMessage: message,
	}
}

func InternalErrorCode(code, message string) Error {
	return &Errors{
		ErrStatus:  500,
		ErrCode:    code,
		ErrMessage: message,
	}
}

func BadRequestCodef(code, format string, v ...interface{}) Error {
	return &Errors{
		ErrStatus:  400,
		ErrCode:    code,
		ErrMessage: fmt.Sprintf(format, v...),
	}
}

func UnauthorizedCodef(code, format string, v ...interface{}) Error {
	return &Errors{
		ErrStatus:  401,
		ErrCode:    code,
		ErrMessage: fmt.Sprintf(format, v...),
	}
}

func ForbiddenCodef(code, format string, v ...interface{}) Error {
	return &Errors{
		ErrStatus:  403,
		ErrCode:    code,
		ErrMessage: fmt.Sprintf(format, v...),
	}
}

func NotFoundCodef(code, format string, v ...interface{}) Error {
	return &Errors{
		ErrStatus:  404,
		ErrCode:    code,
		ErrMessage: fmt.Sprintf(format, v...),
	}
}

func InternalErrorCodef(code, format string, v ...interface{}) Error {
	return &Errors{
		ErrStatus:  500,
		ErrCode:    code,
		ErrMessage: fmt.Sprintf(format, v...),
	}
}

func IsNotFound(err error) bool {
	if cerr, ok := err.(Error); ok && cerr.Status() == 404 {
		return true
	}

	return false
}
<|endoftext|>


<commit_before>package main

import (
	"encoding/json"
	"io"
	"io/ioutil"

	"github.com/bradfitz/slice"
)

// Universe represents a set of configuration, often refered as data or database.
type Universe struct {
	Backgrounds     map[string][]Background
	Aptitudes       []Aptitude
	Characteristics []Characteristic
	Gauges          []Gauge
	Skills          []Skill
	Talents         []Talent
	Costs           CostMatrix
}

// ParseUniverse load an from a plain JSON file.
// It returns a well-formed universe that describe all the components of a game setting.
func ParseUniverse(file io.Reader) (Universe, error) {

	// Open and parse universe.
	raw, err := ioutil.ReadAll(file)
	if err != nil {
		return Universe{}, err
	}
	universe := Universe{}
	err = json.Unmarshal(raw, &universe)
	if err != nil {
		return Universe{}, err
	}

	// Add the type value to each history defined.
	for typ, backgrounds := range universe.Backgrounds {
		for i, _ := range backgrounds {
			universe.Backgrounds[typ][i].Type = typ
		}
	}

	// Sort the universe slices.
	slice.Sort(universe.Aptitudes, func(i, j int) bool {
		return universe.Aptitudes[i] < universe.Aptitudes[j]
	})

	slice.Sort(universe.Characteristics, func(i, j int) bool {
		return universe.Characteristics[i].Name < universe.Characteristics[j].Name
	})

	slice.Sort(universe.Gauges, func(i, j int) bool {
		return universe.Gauges[i].Name < universe.Gauges[j].Name
	})

	slice.Sort(universe.Skills, func(i, j int) bool {
		return universe.Skills[i].Name < universe.Skills[j].Name
	})

	slice.Sort(universe.Talents, func(i, j int) bool {
		return universe.Talents[i].Name < universe.Talents[j].Name
	})

	for k := range universe.Backgrounds {
		slice.Sort(universe.Backgrounds[k], func(i, j int) bool {
			return universe.Backgrounds[k][i].Name < universe.Backgrounds[k][j].Name
		})
	}

	// Check the aptitudes used in the universe.
	used := []Aptitude{}

	// Search for used aptitudes in Characteristics.
	for _, c := range universe.Characteristics {
		for _, a := range c.Aptitudes {
			used = append(used, a)
		}
	}

	// Search for used aptitudes in Skills.
	for _, c := range universe.Skills {
		for _, a := range c.Aptitudes {
			used = append(used, a)
		}
	}

	// Search for used aptitudes in Talents.
	for _, c := range universe.Talents {
		for _, a := range c.Aptitudes {
			used = append(used, a)
		}
	}

	// Sort the used slice to compare it with the universe aptitudes slice.
	slice.Sort(used, func(i, j int) bool {
		return used[i] < used[j]
	})

	// Remove duplicates on used aptitudes.
	k := 0
	for k < len(used)-1 {

		if used[k] == used[k+1] {
			used = append(used[:k], used[k+1:]...)
			continue
		}
		k++
	}

	// Loop on both aptitudes slices.
	var i, j int
	for i < len(universe.Aptitudes) && j < len(used) {

		// The aptitude does not exist in both slices.
		if universe.Aptitudes[i] != universe.Aptitudes[j] {
			break
		}
		i++
		j++
	}

	// Look for diffences in the slices.
	switch {
	// The universe uses more aptitudes than it defines.
	case len(universe.Aptitudes) < len(used):
		return Universe{}, NewError(UndefinedAptitude, used[len(used)-1])

	// The aptitude is used but not defined.
	case universe.Aptitudes[i] > used[j]:
		return Universe{}, NewError(UndefinedAptitude, used[j])

	// The universe defines some unused aptitudes.
	case len(universe.Aptitudes) > len(used):
		return Universe{}, NewError(UnusedAptitude, universe.Aptitudes[len(universe.Aptitudes)-1])

	// The aptitude is defined used but is not used.
	case universe.Aptitudes[i] < used[j]:
		return Universe{}, NewError(UnusedAptitude, universe.Aptitudes[i])
	}

	return universe, nil
}

// FindCharacteristic returns the characteristic correponding to the given label or a zero-value, and a boolean indicating if it was found.
func (u Universe) FindCharacteristic(label string) (Characteristic, bool) {

	for _, characteristic := range u.Characteristics {
		if characteristic.Name == label {
			return characteristic, true
		}
	}

	return Characteristic{}, false
}

// FindSkill returns the skill corresponding to the given label or a zero-value, and a boolean indicating if it was found.
func (u Universe) FindSkill(label string) (Skill, bool) {

	for _, skill := range u.Skills {
		if skill.Name == label {
			return skill, true
		}
	}

	return Skill{}, false
}

// FindTalent returns the talent corresponding to the given label or a zero value, and a boolean indicating if it was found.
func (u Universe) FindTalent(label string) (Talent, bool) {

	for _, talent := range u.Talents {
		if talent.Name == label {
			return talent, true
		}
	}

	return Talent{}, false
}

// FindAptitude returns the aptitude corresponding to the given label or a zero value, and a boolean indicating if it was found.
func (u Universe) FindAptitude(label string) (Aptitude, bool) {

	for _, aptitude := range u.Aptitudes {
		if string(aptitude) == label {
			return aptitude, true
		}
	}

	return Aptitude(""), false
}

// FindBackground returns the background corresponding to the given label
func (u Universe) FindBackground(typ string, label string) (Background, error) {

	histories, found := u.Backgrounds[typ]
	if !found {
		return Background{}, NewError(UndefinedBackgroundType, typ)
	}

	for _, background := range histories {
		if background.Name == label {
			return background, nil
		}
	}

	return Background{}, NewError(UndefinedBackgroundValue, typ, label)
}
<commit_msg>Remove the universe consistency checking from the ParseUniverse method<commit_after>package main

import (
	"encoding/json"
	"io"
	"io/ioutil"
)

// Universe represents a set of configuration, often refered as data or database.
type Universe struct {
	Backgrounds     map[string][]Background
	Aptitudes       []Aptitude
	Characteristics []Characteristic
	Gauges          []Gauge
	Skills          []Skill
	Talents         []Talent
	Costs           CostMatrix
}

// ParseUniverse load an from a plain JSON file.
// It returns a well-formed universe that describe all the components of a game setting.
func ParseUniverse(file io.Reader) (Universe, error) {

	// Open and parse universe.
	raw, err := ioutil.ReadAll(file)
	if err != nil {
		return Universe{}, err
	}
	universe := Universe{}
	err = json.Unmarshal(raw, &universe)
	if err != nil {
		return Universe{}, err
	}

	// Add the type value to each history defined.
	for typ, backgrounds := range universe.Backgrounds {
		for i, _ := range backgrounds {
			universe.Backgrounds[typ][i].Type = typ
		}
	}

	return universe, nil
}

// FindCharacteristic returns the characteristic correponding to the given label or a zero-value, and a boolean indicating if it was found.
func (u Universe) FindCharacteristic(label string) (Characteristic, bool) {

	for _, characteristic := range u.Characteristics {
		if characteristic.Name == label {
			return characteristic, true
		}
	}

	return Characteristic{}, false
}

// FindSkill returns the skill corresponding to the given label or a zero-value, and a boolean indicating if it was found.
func (u Universe) FindSkill(label string) (Skill, bool) {

	for _, skill := range u.Skills {
		if skill.Name == label {
			return skill, true
		}
	}

	return Skill{}, false
}

// FindTalent returns the talent corresponding to the given label or a zero value, and a boolean indicating if it was found.
func (u Universe) FindTalent(label string) (Talent, bool) {

	for _, talent := range u.Talents {
		if talent.Name == label {
			return talent, true
		}
	}

	return Talent{}, false
}

// FindAptitude returns the aptitude corresponding to the given label or a zero value, and a boolean indicating if it was found.
func (u Universe) FindAptitude(label string) (Aptitude, bool) {

	for _, aptitude := range u.Aptitudes {
		if string(aptitude) == label {
			return aptitude, true
		}
	}

	return Aptitude(""), false
}

// FindBackground returns the background corresponding to the given label
func (u Universe) FindBackground(typ string, label string) (Background, error) {

	histories, found := u.Backgrounds[typ]
	if !found {
		return Background{}, NewError(UndefinedBackgroundType, typ)
	}

	for _, background := range histories {
		if background.Name == label {
			return background, nil
		}
	}

	return Background{}, NewError(UndefinedBackgroundValue, typ, label)
}
<|endoftext|>


<commit_before><commit_msg>"Jeff: Give yourself to the Dark Side. It is the only way you can save your friends."<commit_after><|endoftext|>


<commit_before><commit_msg>"Jeff: Come to the dark side... together we will rule the galaxy."<commit_after><|endoftext|>


<commit_before>/*
Copyright 2020 The Knative Authors

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

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

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

package v1

import (
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apimachinery/pkg/runtime"
	"knative.dev/pkg/apis"
	duckv1 "knative.dev/pkg/apis/duck/v1"
	"knative.dev/pkg/kmeta"
)

// +genclient
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
// +k8s:defaulter-gen=true

// SinkBinding describes a Binding that is also a Source.
// The `sink` (from the Source duck) is resolved to a URL and
// then projected into the `subject` by augmenting the runtime
// contract of the referenced containers to have a `K_SINK`
// environment variable holding the endpoint to which to send
// cloud events.
type SinkBinding struct {
	metav1.TypeMeta   `json:",inline"`
	metav1.ObjectMeta `json:"metadata,omitempty"`

	Spec   SinkBindingSpec   `json:"spec"`
	Status SinkBindingStatus `json:"status"`
}

// Check the interfaces that SinkBinding should be implementing.
var (
	_ runtime.Object     = (*SinkBinding)(nil)
	_ kmeta.OwnerRefable = (*SinkBinding)(nil)
	_ apis.Validatable   = (*SinkBinding)(nil)
	_ apis.Defaultable   = (*SinkBinding)(nil)
	_ apis.HasSpec       = (*SinkBinding)(nil)
	_ duckv1.KRShaped    = (*SinkBinding)(nil)
)

// SinkBindingSpec holds the desired state of the SinkBinding (from the client).
type SinkBindingSpec struct {
	// inherits duck/v1 SourceSpec, which currently provides:
	// * Sink - a reference to an object that will resolve to a domain name or
	//   a URI directly to use as the sink.
	// * CloudEventOverrides - defines overrides to control the output format
	//   and modifications of the event sent to the sink.
	duckv1.SourceSpec `json:",inline"`

	// inherits duck/v1 BindingSpec, which currently provides:
	// * Subject - Subject references the resource(s) whose "runtime contract"
	//   should be augmented by Binding implementations.
	duckv1.BindingSpec `json:",inline"`
}

const (
	// SinkBindingConditionReady is configured to indicate whether the Binding
	// has been configured for resources subject to its runtime contract.
	SinkBindingConditionReady = apis.ConditionReady

	// SinkBindingConditionSinkProvided is configured to indicate whether the
	// sink has been properly extracted from the resolver.
	SinkBindingConditionSinkProvided apis.ConditionType = "SinkProvided"
)

// SinkBindingStatus communicates the observed state of the SinkBinding (from the controller).
type SinkBindingStatus struct {
	// inherits duck/v1 SourceStatus, which currently provides:
	// * ObservedGeneration - the 'Generation' of the Service that was last
	//   processed by the controller.
	// * Conditions - the latest available observations of a resource's current
	//   state.
	// * SinkURI - the current active sink URI that has been configured for the
	//   Source.
	duckv1.SourceStatus `json:",inline"`
}

// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object

// SinkBindingList contains a list of SinkBinding
type SinkBindingList struct {
	metav1.TypeMeta `json:",inline"`
	metav1.ListMeta `json:"metadata,omitempty"`
	Items           []SinkBinding `json:"items"`
}

// GetStatus retrieves the status of the SinkBinding. Implements the KRShaped interface.
func (s *SinkBinding) GetStatus() *duckv1.Status {
	return &s.Status.Status
}
<commit_msg>sinkbing implement bindable (#4794)<commit_after>/*
Copyright 2020 The Knative Authors

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

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

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

package v1

import (
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apimachinery/pkg/runtime"
	"knative.dev/pkg/apis"
	"knative.dev/pkg/apis/duck"
	duckv1 "knative.dev/pkg/apis/duck/v1"
	"knative.dev/pkg/kmeta"
)

// +genclient
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
// +k8s:defaulter-gen=true

// SinkBinding describes a Binding that is also a Source.
// The `sink` (from the Source duck) is resolved to a URL and
// then projected into the `subject` by augmenting the runtime
// contract of the referenced containers to have a `K_SINK`
// environment variable holding the endpoint to which to send
// cloud events.
type SinkBinding struct {
	metav1.TypeMeta   `json:",inline"`
	metav1.ObjectMeta `json:"metadata,omitempty"`

	Spec   SinkBindingSpec   `json:"spec"`
	Status SinkBindingStatus `json:"status"`
}

// Check the interfaces that SinkBinding should be implementing.
var (
	_ runtime.Object     = (*SinkBinding)(nil)
	_ kmeta.OwnerRefable = (*SinkBinding)(nil)
	_ apis.Validatable   = (*SinkBinding)(nil)
	_ apis.Defaultable   = (*SinkBinding)(nil)
	_ apis.HasSpec       = (*SinkBinding)(nil)
	_ duckv1.KRShaped    = (*SinkBinding)(nil)
	_ duck.Bindable      = (*SinkBinding)(nil)
)

// SinkBindingSpec holds the desired state of the SinkBinding (from the client).
type SinkBindingSpec struct {
	// inherits duck/v1 SourceSpec, which currently provides:
	// * Sink - a reference to an object that will resolve to a domain name or
	//   a URI directly to use as the sink.
	// * CloudEventOverrides - defines overrides to control the output format
	//   and modifications of the event sent to the sink.
	duckv1.SourceSpec `json:",inline"`

	// inherits duck/v1 BindingSpec, which currently provides:
	// * Subject - Subject references the resource(s) whose "runtime contract"
	//   should be augmented by Binding implementations.
	duckv1.BindingSpec `json:",inline"`
}

const (
	// SinkBindingConditionReady is configured to indicate whether the Binding
	// has been configured for resources subject to its runtime contract.
	SinkBindingConditionReady = apis.ConditionReady

	// SinkBindingConditionSinkProvided is configured to indicate whether the
	// sink has been properly extracted from the resolver.
	SinkBindingConditionSinkProvided apis.ConditionType = "SinkProvided"
)

// SinkBindingStatus communicates the observed state of the SinkBinding (from the controller).
type SinkBindingStatus struct {
	// inherits duck/v1 SourceStatus, which currently provides:
	// * ObservedGeneration - the 'Generation' of the Service that was last
	//   processed by the controller.
	// * Conditions - the latest available observations of a resource's current
	//   state.
	// * SinkURI - the current active sink URI that has been configured for the
	//   Source.
	duckv1.SourceStatus `json:",inline"`
}

// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object

// SinkBindingList contains a list of SinkBinding
type SinkBindingList struct {
	metav1.TypeMeta `json:",inline"`
	metav1.ListMeta `json:"metadata,omitempty"`
	Items           []SinkBinding `json:"items"`
}

// GetStatus retrieves the status of the SinkBinding. Implements the KRShaped interface.
func (s *SinkBinding) GetStatus() *duckv1.Status {
	return &s.Status.Status
}
<|endoftext|>


<commit_before>/*
Copyright 2017 The Kubernetes Authors All rights reserved.

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 plugin

import (
	"context"
	"fmt"
	"os/exec"
	"strings"
	"sync"
	"syscall"
	"time"

	"github.com/golang/glog"
	cpmtypes "k8s.io/node-problem-detector/pkg/custompluginmonitor/types"
	"k8s.io/node-problem-detector/pkg/util/tomb"
)

type Plugin struct {
	config     cpmtypes.CustomPluginConfig
	syncChan   chan struct{}
	resultChan chan cpmtypes.Result
	tomb       *tomb.Tomb
	sync.WaitGroup
}

func NewPlugin(config cpmtypes.CustomPluginConfig) *Plugin {
	return &Plugin{
		config:   config,
		syncChan: make(chan struct{}, *config.PluginGlobalConfig.Concurrency),
		// A 1000 size channel should be big enough.
		resultChan: make(chan cpmtypes.Result, 1000),
		tomb:       tomb.NewTomb(),
	}
}

func (p *Plugin) GetResultChan() <-chan cpmtypes.Result {
	return p.resultChan
}

func (p *Plugin) Run() {
	defer func() {
		glog.Info("Stopping plugin execution")
		p.tomb.Done()
	}()

	runTicker := time.NewTicker(*p.config.PluginGlobalConfig.InvokeInterval)
	defer runTicker.Stop()

	runner := func() {
		glog.Info("Start to run custom plugins")

		for _, rule := range p.config.Rules {
			p.syncChan <- struct{}{}
			p.Add(1)

			go func(rule *cpmtypes.CustomRule) {
				defer p.Done()
				defer func() {
					<-p.syncChan
				}()

				start := time.Now()
				exitStatus, message := p.run(*rule)
				end := time.Now()

				glog.V(3).Infof("Rule: %+v. Start time: %v. End time: %v. Duration: %v", rule, start, end, end.Sub(start))

				result := cpmtypes.Result{
					Rule:       rule,
					ExitStatus: exitStatus,
					Message:    message,
				}

				p.resultChan <- result

				glog.Infof("Add check result %+v for rule %+v", result, rule)
			}(rule)
		}

		p.Wait()
		glog.Info("Finish running custom plugins")
	}

	select {
	case <-p.tomb.Stopping():
		return
	default:
		runner()
	}

	for {
		select {
		case <-runTicker.C:
			runner()
		case <-p.tomb.Stopping():
			return
		}
	}
}

func (p *Plugin) run(rule cpmtypes.CustomRule) (exitStatus cpmtypes.Status, output string) {
	var ctx context.Context
	var cancel context.CancelFunc

	if rule.Timeout != nil && *rule.Timeout < *p.config.PluginGlobalConfig.Timeout {
		ctx, cancel = context.WithTimeout(context.Background(), *rule.Timeout)
	} else {
		ctx, cancel = context.WithTimeout(context.Background(), *p.config.PluginGlobalConfig.Timeout)
	}
	defer cancel()

	cmd := exec.CommandContext(ctx, rule.Path, rule.Args...)
	stdout, err := cmd.Output()
	if err != nil {
		if _, ok := err.(*exec.ExitError); !ok {
			glog.Errorf("Error in running plugin %q: error - %v. output - %q", rule.Path, err, string(stdout))
			return cpmtypes.Unknown, "Error in running plugin. Please check the error log"
		}
	}

	// trim suffix useless bytes
	output = string(stdout)
	output = strings.TrimSpace(output)

	if cmd.ProcessState.Sys().(syscall.WaitStatus).Signaled() {
		output = fmt.Sprintf("Timeout when running plugin %q: state - %s. output - %q", rule.Path, cmd.ProcessState.String(), output)
	}

	// cut at position max_output_length if stdout is longer than max_output_length bytes
	if len(output) > *p.config.PluginGlobalConfig.MaxOutputLength {
		output = output[:*p.config.PluginGlobalConfig.MaxOutputLength]
	}

	exitCode := cmd.ProcessState.Sys().(syscall.WaitStatus).ExitStatus()
	switch exitCode {
	case 0:
		return cpmtypes.OK, output
	case 1:
		return cpmtypes.NonOK, output
	default:
		return cpmtypes.Unknown, output
	}
}

func (p *Plugin) Stop() {
	p.tomb.Stop()
	glog.Info("Stop plugin execution")
}
<commit_msg>untangle plugin runner a bit<commit_after>/*
Copyright 2017 The Kubernetes Authors All rights reserved.

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 plugin

import (
	"context"
	"fmt"
	"os/exec"
	"strings"
	"sync"
	"syscall"
	"time"

	"github.com/golang/glog"
	cpmtypes "k8s.io/node-problem-detector/pkg/custompluginmonitor/types"
	"k8s.io/node-problem-detector/pkg/util/tomb"
)

type Plugin struct {
	config     cpmtypes.CustomPluginConfig
	syncChan   chan struct{}
	resultChan chan cpmtypes.Result
	tomb       *tomb.Tomb
	sync.WaitGroup
}

func NewPlugin(config cpmtypes.CustomPluginConfig) *Plugin {
	return &Plugin{
		config:   config,
		syncChan: make(chan struct{}, *config.PluginGlobalConfig.Concurrency),
		// A 1000 size channel should be big enough.
		resultChan: make(chan cpmtypes.Result, 1000),
		tomb:       tomb.NewTomb(),
	}
}

func (p *Plugin) GetResultChan() <-chan cpmtypes.Result {
	return p.resultChan
}

func (p *Plugin) Run() {
	defer func() {
		glog.Info("Stopping plugin execution")
		p.tomb.Done()
	}()

	runTicker := time.NewTicker(*p.config.PluginGlobalConfig.InvokeInterval)
	defer runTicker.Stop()

	// on boot run once
	select {
	case <-p.tomb.Stopping():
		return
	default:
		p.runRules()
	}

	// run every InvokeInterval
	for {
		select {
		case <-runTicker.C:
			p.runRules()
		case <-p.tomb.Stopping():
			return
		}
	}
}

// run each rule in parallel and wait for them to complete
func (p *Plugin) runRules() {
	glog.Info("Start to run custom plugins")

	for _, rule := range p.config.Rules {
		p.syncChan <- struct{}{}
		p.Add(1)
		go func(rule *cpmtypes.CustomRule) {
			defer p.Done()
			defer func() {
				<-p.syncChan
			}()

			start := time.Now()
			exitStatus, message := p.run(*rule)
			end := time.Now()

			glog.V(3).Infof("Rule: %+v. Start time: %v. End time: %v. Duration: %v", rule, start, end, end.Sub(start))

			result := cpmtypes.Result{
				Rule:       rule,
				ExitStatus: exitStatus,
				Message:    message,
			}

			p.resultChan <- result

			glog.Infof("Add check result %+v for rule %+v", result, rule)
		}(rule)
	}

	p.Wait()
	glog.Info("Finish running custom plugins")
}

func (p *Plugin) run(rule cpmtypes.CustomRule) (exitStatus cpmtypes.Status, output string) {
	var ctx context.Context
	var cancel context.CancelFunc

	if rule.Timeout != nil && *rule.Timeout < *p.config.PluginGlobalConfig.Timeout {
		ctx, cancel = context.WithTimeout(context.Background(), *rule.Timeout)
	} else {
		ctx, cancel = context.WithTimeout(context.Background(), *p.config.PluginGlobalConfig.Timeout)
	}
	defer cancel()

	cmd := exec.CommandContext(ctx, rule.Path, rule.Args...)
	stdout, err := cmd.Output()
	if err != nil {
		if _, ok := err.(*exec.ExitError); !ok {
			glog.Errorf("Error in running plugin %q: error - %v. output - %q", rule.Path, err, string(stdout))
			return cpmtypes.Unknown, "Error in running plugin. Please check the error log"
		}
	}

	// trim suffix useless bytes
	output = string(stdout)
	output = strings.TrimSpace(output)

	if cmd.ProcessState.Sys().(syscall.WaitStatus).Signaled() {
		output = fmt.Sprintf("Timeout when running plugin %q: state - %s. output - %q", rule.Path, cmd.ProcessState.String(), output)
	}

	// cut at position max_output_length if stdout is longer than max_output_length bytes
	if len(output) > *p.config.PluginGlobalConfig.MaxOutputLength {
		output = output[:*p.config.PluginGlobalConfig.MaxOutputLength]
	}

	exitCode := cmd.ProcessState.Sys().(syscall.WaitStatus).ExitStatus()
	switch exitCode {
	case 0:
		return cpmtypes.OK, output
	case 1:
		return cpmtypes.NonOK, output
	default:
		return cpmtypes.Unknown, output
	}
}

func (p *Plugin) Stop() {
	p.tomb.Stop()
	glog.Info("Stop plugin execution")
}
<|endoftext|>


<commit_before>/*
Copyright 2016 The Kubernetes Authors All rights reserved.

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 localpath

import (
	"fmt"
	"io/ioutil"
	"os"
	"path/filepath"
	"runtime"
	"strings"
	"testing"

	"k8s.io/client-go/util/homedir"
)

func TestReplaceWinDriveLetterToVolumeName(t *testing.T) {
	path, err := ioutil.TempDir("", "repwindl2vn")
	if err != nil {
		t.Fatalf("Error make tmp directory: %v", err)
	}
	defer os.RemoveAll(path)

	if runtime.GOOS != "windows" {
		// Replace to fake func.
		getWindowsVolumeName = func(d string) (string, error) {
			return `/`, nil
		}
		// Add dummy Windows drive letter.
		path = `C:` + path
	}

	if _, err := replaceWinDriveLetterToVolumeName(path); err != nil {
		t.Errorf("Error replace a Windows drive letter to a volume name: %v", err)
	}
}

func TestHasWindowsDriveLetter(t *testing.T) {
	cases := []struct {
		path string
		want bool
	}{
		{`C:\Users\Foo\.minikube`, true},
		{`D:\minikube\.minikube`, true},
		{`C\Foo\Bar\.minikube`, false},
		{`/home/foo/.minikube`, false},
	}

	for _, tc := range cases {
		if hasWindowsDriveLetter(tc.path) != tc.want {
			t.Errorf("%s have a Windows drive letter: %t", tc.path, tc.want)
		}
	}
}

func TestMiniPath(t *testing.T) {
	var testCases = []struct {
		env, basePath string
	}{
		{"/tmp/.minikube", "/tmp/"},
		{"/tmp/", "/tmp"},
		{"", homedir.HomeDir()},
	}
	for _, tc := range testCases {
		originalEnv := os.Getenv(MinikubeHome)
		defer func() { // revert to pre-test env var
			err := os.Setenv(MinikubeHome, originalEnv)
			if err != nil {
				t.Fatalf("Error reverting env %s to its original value (%s) var after test ", MinikubeHome, originalEnv)
			}
		}()
		t.Run(fmt.Sprintf("%s", tc.env), func(t *testing.T) {
			expectedPath := filepath.Join(tc.basePath, ".minikube")
			os.Setenv(MinikubeHome, tc.env)
			path := MiniPath()
			if path != expectedPath {
				t.Errorf("MiniPath expected to return '%s', but got '%s'", expectedPath, path)
			}
		})
	}
}

type propertyFnWithArg func(string) string
type propertyFnWithoutArg func() string

func TestPropertyWithNameArg(t *testing.T) {
	var testCases = []struct {
		propertyFunc propertyFnWithArg
	}{
		{Profile},
		{ClientCert},
		{ClientKey},
	}
	miniPath := MiniPath()
	mockedName := "foo"
	for _, tc := range testCases {
		t.Run(fmt.Sprintf("%v", tc.propertyFunc), func(t *testing.T) {
			if !strings.Contains(tc.propertyFunc(mockedName), MiniPath()) {
				t.Errorf("Propert %v doesn't contain miniPat %v", tc.propertyFunc, miniPath)
			}
			if !strings.Contains(tc.propertyFunc(mockedName), mockedName) {
				t.Errorf("Propert %v doesn't contain passed name inpath %v", tc.propertyFunc, mockedName)
			}
		})

	}
}

func TestPropertyWithoutNameArg(t *testing.T) {
	var testCases = []struct {
		propertyFunc propertyFnWithoutArg
	}{
		{ConfigFile},
		{CACert},
	}
	miniPath := MiniPath()
	for _, tc := range testCases {
		t.Run(fmt.Sprintf("%v", tc.propertyFunc), func(t *testing.T) {
			if !strings.Contains(tc.propertyFunc(), MiniPath()) {
				t.Errorf("Propert %v doesn't contain miniPat %v", tc.propertyFunc, miniPath)
			}
		})
	}
}
<commit_msg>test properties<commit_after>/*
Copyright 2016 The Kubernetes Authors All rights reserved.

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 localpath

import (
	"fmt"
	"io/ioutil"
	"os"
	"path/filepath"
	"runtime"
	"strings"
	"testing"

	"k8s.io/client-go/util/homedir"
)

func TestReplaceWinDriveLetterToVolumeName(t *testing.T) {
	path, err := ioutil.TempDir("", "repwindl2vn")
	if err != nil {
		t.Fatalf("Error make tmp directory: %v", err)
	}
	defer os.RemoveAll(path)

	if runtime.GOOS != "windows" {
		// Replace to fake func.
		getWindowsVolumeName = func(d string) (string, error) {
			return `/`, nil
		}
		// Add dummy Windows drive letter.
		path = `C:` + path
	}

	if _, err := replaceWinDriveLetterToVolumeName(path); err != nil {
		t.Errorf("Error replace a Windows drive letter to a volume name: %v", err)
	}
}

func TestHasWindowsDriveLetter(t *testing.T) {
	cases := []struct {
		path string
		want bool
	}{
		{`C:\Users\Foo\.minikube`, true},
		{`D:\minikube\.minikube`, true},
		{`C\Foo\Bar\.minikube`, false},
		{`/home/foo/.minikube`, false},
	}

	for _, tc := range cases {
		if hasWindowsDriveLetter(tc.path) != tc.want {
			t.Errorf("%s have a Windows drive letter: %t", tc.path, tc.want)
		}
	}
}

func TestMiniPath(t *testing.T) {
	var testCases = []struct {
		env, basePath string
	}{
		{"/tmp/.minikube", "/tmp/"},
		{"/tmp/", "/tmp"},
		{"", homedir.HomeDir()},
	}
	for _, tc := range testCases {
		originalEnv := os.Getenv(MinikubeHome)
		defer func() { // revert to pre-test env var
			err := os.Setenv(MinikubeHome, originalEnv)
			if err != nil {
				t.Fatalf("Error reverting env %s to its original value (%s) var after test ", MinikubeHome, originalEnv)
			}
		}()
		t.Run(tc.env, func(t *testing.T) {
			expectedPath := filepath.Join(tc.basePath, ".minikube")
			os.Setenv(MinikubeHome, tc.env)
			path := MiniPath()
			if path != expectedPath {
				t.Errorf("MiniPath expected to return '%s', but got '%s'", expectedPath, path)
			}
		})
	}
}

func TestMachinePath(t *testing.T) {
	var testCases = []struct {
		miniHome []string
		contains string
	}{
		{[]string{"tmp", "foo", "bar", "baz"}, "tmp"},
		{[]string{"tmp"}, "tmp"},
		{[]string{}, MiniPath()},
	}
	for _, tc := range testCases {
		t.Run(fmt.Sprintf("%s", tc.miniHome), func(t *testing.T) {
			machinePath := MachinePath("foo", tc.miniHome...)
			if !strings.Contains(machinePath, tc.contains) {
				t.Errorf("Function MachinePath returned (%v) which doesn't contain expected (%v)", machinePath, tc.contains)
			}
		})
	}
}

type propertyFnWithArg func(string) string

func TestPropertyWithNameArg(t *testing.T) {
	var testCases = []struct {
		propertyFunc propertyFnWithArg
		name         string
	}{
		{Profile, "Profile"},
		{ClientCert, "ClientCert"},
		{ClientKey, "ClientKey"},
	}
	miniPath := MiniPath()
	mockedName := "foo"
	for _, tc := range testCases {
		t.Run(tc.name, func(t *testing.T) {
			if !strings.Contains(tc.propertyFunc(mockedName), MiniPath()) {
				t.Errorf("Propert %s(%v) doesn't contain miniPat %v", tc.name, tc.propertyFunc, miniPath)
			}
			if !strings.Contains(tc.propertyFunc(mockedName), mockedName) {
				t.Errorf("Propert %s(%v) doesn't contain passed name inpath %v", tc.name, tc.propertyFunc, mockedName)
			}
		})

	}
}

type propertyFnWithoutArg func() string

func TestPropertyWithoutNameArg(t *testing.T) {
	var testCases = []struct {
		propertyFunc propertyFnWithoutArg
		name         string
	}{
		{ConfigFile, "ConfigFile"},
		{CACert, "CACert"},
	}
	miniPath := MiniPath()
	for _, tc := range testCases {
		t.Run(tc.name, func(t *testing.T) {
			if !strings.Contains(tc.propertyFunc(), MiniPath()) {
				t.Errorf("Propert %s(%v) doesn't contain miniPat %v", tc.name, tc.propertyFunc, miniPath)
			}
		})
	}
}
<|endoftext|>


<commit_before>package fasthttp

import (
	"sync"
	"sync/atomic"
	"time"
)

// BalancingClient is the interface for clients, which may be passed
// to LBClient.Clients.
type BalancingClient interface {
	DoDeadline(req *Request, resp *Response, deadline time.Time) error
	PendingRequests() int
}

// LBClient balances requests among available LBClient.Clients.
//
// It has the following features:
//
//   - Balances load among available clients using 'least loaded' + 'round robin'
//     hybrid technique.
//   - Dynamically decreases load on unhealthy clients.
//
// It is forbidden copying LBClient instances. Create new instances instead.
//
// It is safe calling LBClient methods from concurrently running goroutines.
type LBClient struct {
	noCopy noCopy

	// Clients must contain non-zero clients list.
	// Incoming requests are balanced among these clients.
	Clients []BalancingClient

	// HealthCheck is a callback called after each request.
	//
	// The request, response and the error returned by the client
	// is passed to HealthCheck, so the callback may determine whether
	// the client is healthy.
	//
	// Load on the current client is decreased if HealthCheck returns false.
	//
	// By default HealthCheck returns false if err != nil.
	HealthCheck func(req *Request, resp *Response, err error) bool

	// Timeout is the request timeout used when calling LBClient.Do.
	//
	// DefaultLBClientTimeout is used by default.
	Timeout time.Duration

	cs []*lbClient

	// nextIdx is for spreading requests among equally loaded clients
	// in a round-robin fashion.
	nextIdx uint32

	once sync.Once
}

// DefaultLBClientTimeout is the default request timeout used by LBClient
// when calling LBClient.Do.
//
// The timeout may be overriden via LBClient.Timeout.
const DefaultLBClientTimeout = time.Second

// DoDeadline calls DoDeadline on the least loaded client
func (cc *LBClient) DoDeadline(req *Request, resp *Response, deadline time.Time) error {
	return cc.get().DoDeadline(req, resp, deadline)
}

// DoTimeout calculates deadline and calls DoDeadline on the least loaded client
func (cc *LBClient) DoTimeout(req *Request, resp *Response, timeout time.Duration) error {
	deadline := time.Now().Add(timeout)
	return cc.get().DoDeadline(req, resp, deadline)
}

// Do calls calculates deadline using LBClient.Timeout and calls DoDeadline
// on the least loaded client.
func (cc *LBClient) Do(req *Request, resp *Response) error {
	timeout := cc.Timeout
	if timeout <= 0 {
		timeout = DefaultLBClientTimeout
	}
	return cc.DoTimeout(req, resp, timeout)
}

func (cc *LBClient) init() {
	for _, c := range cc.Clients {
		cc.cs = append(cc.cs, &lbClient{
			c:           c,
			healthCheck: cc.HealthCheck,
		})
	}
}

func (cc *LBClient) get() *lbClient {
	cc.once.Do(cc.init)

	cs := cc.cs
	idx := atomic.AddUint32(&cc.nextIdx, 1)
	idx %= uint32(len(cs))

	minC := cs[idx]
	minN := minC.PendingRequests()
	if minN == 0 {
		return minC
	}
	for _, c := range cs[idx+1:] {
		n := c.PendingRequests()
		if n == 0 {
			return c
		}
		if n < minN {
			minC = c
			minN = n
		}
	}
	for _, c := range cs[:idx] {
		n := c.PendingRequests()
		if n == 0 {
			return c
		}
		if n < minN {
			minC = c
			minN = n
		}
	}
	return minC
}

type lbClient struct {
	c           BalancingClient
	healthCheck func(req *Request, resp *Response, err error) bool
	penalty     uint32
}

func (c *lbClient) DoDeadline(req *Request, resp *Response, deadline time.Time) error {
	err := c.c.DoDeadline(req, resp, deadline)
	if !c.isHealthy(req, resp, err) && c.incPenalty() {
		// Penalize the client returning error, so the next requests
		// are routed to another clients.
		time.AfterFunc(penaltyDuration, c.decPenalty)
	}
	return err
}

func (c *lbClient) PendingRequests() int {
	n := c.c.PendingRequests()
	m := atomic.LoadUint32(&c.penalty)
	return n + int(m)
}

func (c *lbClient) isHealthy(req *Request, resp *Response, err error) bool {
	if c.healthCheck == nil {
		return err == nil
	}
	return c.healthCheck(req, resp, err)
}

func (c *lbClient) incPenalty() bool {
	m := atomic.AddUint32(&c.penalty, 1)
	if m > maxPenalty {
		c.decPenalty()
		return false
	}
	return true
}

func (c *lbClient) decPenalty() {
	atomic.AddUint32(&c.penalty, ^uint32(0))
}

const (
	maxPenalty = 300

	penaltyDuration = 3 * time.Second
)
<commit_msg>LBClient: panic on empty Clients<commit_after>package fasthttp

import (
	"sync"
	"sync/atomic"
	"time"
)

// BalancingClient is the interface for clients, which may be passed
// to LBClient.Clients.
type BalancingClient interface {
	DoDeadline(req *Request, resp *Response, deadline time.Time) error
	PendingRequests() int
}

// LBClient balances requests among available LBClient.Clients.
//
// It has the following features:
//
//   - Balances load among available clients using 'least loaded' + 'round robin'
//     hybrid technique.
//   - Dynamically decreases load on unhealthy clients.
//
// It is forbidden copying LBClient instances. Create new instances instead.
//
// It is safe calling LBClient methods from concurrently running goroutines.
type LBClient struct {
	noCopy noCopy

	// Clients must contain non-zero clients list.
	// Incoming requests are balanced among these clients.
	Clients []BalancingClient

	// HealthCheck is a callback called after each request.
	//
	// The request, response and the error returned by the client
	// is passed to HealthCheck, so the callback may determine whether
	// the client is healthy.
	//
	// Load on the current client is decreased if HealthCheck returns false.
	//
	// By default HealthCheck returns false if err != nil.
	HealthCheck func(req *Request, resp *Response, err error) bool

	// Timeout is the request timeout used when calling LBClient.Do.
	//
	// DefaultLBClientTimeout is used by default.
	Timeout time.Duration

	cs []*lbClient

	// nextIdx is for spreading requests among equally loaded clients
	// in a round-robin fashion.
	nextIdx uint32

	once sync.Once
}

// DefaultLBClientTimeout is the default request timeout used by LBClient
// when calling LBClient.Do.
//
// The timeout may be overriden via LBClient.Timeout.
const DefaultLBClientTimeout = time.Second

// DoDeadline calls DoDeadline on the least loaded client
func (cc *LBClient) DoDeadline(req *Request, resp *Response, deadline time.Time) error {
	return cc.get().DoDeadline(req, resp, deadline)
}

// DoTimeout calculates deadline and calls DoDeadline on the least loaded client
func (cc *LBClient) DoTimeout(req *Request, resp *Response, timeout time.Duration) error {
	deadline := time.Now().Add(timeout)
	return cc.get().DoDeadline(req, resp, deadline)
}

// Do calls calculates deadline using LBClient.Timeout and calls DoDeadline
// on the least loaded client.
func (cc *LBClient) Do(req *Request, resp *Response) error {
	timeout := cc.Timeout
	if timeout <= 0 {
		timeout = DefaultLBClientTimeout
	}
	return cc.DoTimeout(req, resp, timeout)
}

func (cc *LBClient) init() {
	if len(cc.Clients) == 0 {
		panic("BUG: LBClient.Clients cannot be empty")
	}
	for _, c := range cc.Clients {
		cc.cs = append(cc.cs, &lbClient{
			c:           c,
			healthCheck: cc.HealthCheck,
		})
	}
}

func (cc *LBClient) get() *lbClient {
	cc.once.Do(cc.init)

	cs := cc.cs
	idx := atomic.AddUint32(&cc.nextIdx, 1)
	idx %= uint32(len(cs))

	minC := cs[idx]
	minN := minC.PendingRequests()
	if minN == 0 {
		return minC
	}
	for _, c := range cs[idx+1:] {
		n := c.PendingRequests()
		if n == 0 {
			return c
		}
		if n < minN {
			minC = c
			minN = n
		}
	}
	for _, c := range cs[:idx] {
		n := c.PendingRequests()
		if n == 0 {
			return c
		}
		if n < minN {
			minC = c
			minN = n
		}
	}
	return minC
}

type lbClient struct {
	c           BalancingClient
	healthCheck func(req *Request, resp *Response, err error) bool
	penalty     uint32
}

func (c *lbClient) DoDeadline(req *Request, resp *Response, deadline time.Time) error {
	err := c.c.DoDeadline(req, resp, deadline)
	if !c.isHealthy(req, resp, err) && c.incPenalty() {
		// Penalize the client returning error, so the next requests
		// are routed to another clients.
		time.AfterFunc(penaltyDuration, c.decPenalty)
	}
	return err
}

func (c *lbClient) PendingRequests() int {
	n := c.c.PendingRequests()
	m := atomic.LoadUint32(&c.penalty)
	return n + int(m)
}

func (c *lbClient) isHealthy(req *Request, resp *Response, err error) bool {
	if c.healthCheck == nil {
		return err == nil
	}
	return c.healthCheck(req, resp, err)
}

func (c *lbClient) incPenalty() bool {
	m := atomic.AddUint32(&c.penalty, 1)
	if m > maxPenalty {
		c.decPenalty()
		return false
	}
	return true
}

func (c *lbClient) decPenalty() {
	atomic.AddUint32(&c.penalty, ^uint32(0))
}

const (
	maxPenalty = 300

	penaltyDuration = 3 * time.Second
)
<|endoftext|>


<commit_before><commit_msg>stats: add more projects and count only gortc authors<commit_after><|endoftext|>


<commit_before>package main

import (
	"fmt"
	"net/url"
	"os"
	"path"
	"path/filepath"
	"strings"
	"sync"

	"github.com/x-motemen/ghq/logger"
)

var (
	seen = make(map[string]bool)
	mu   = &sync.Mutex{}
)

func getRepoLock(localRepoRoot string) bool {
	mu.Lock()
	defer func() {
		seen[localRepoRoot] = true
		mu.Unlock()
	}()
	return !seen[localRepoRoot]
}

type getter struct {
	update, shallow, silent, ssh, recursive, bare bool
	vcs, branch                                   string
}

func (g *getter) get(argURL string) error {
	u, err := newURL(argURL, g.ssh, false)
	if err != nil {
		return fmt.Errorf("Could not parse URL %q: %w", argURL, err)
	}

	remote, err := NewRemoteRepository(u)
	if err != nil {
		return err
	}

	return g.getRemoteRepository(remote)
}

// getRemoteRepository clones or updates a remote repository remote.
// If doUpdate is true, updates the locally cloned repository. Otherwise does nothing.
// If isShallow is true, does shallow cloning. (no effect if already cloned or the VCS is Mercurial and git-svn)
func (g *getter) getRemoteRepository(remote RemoteRepository) error {
	remoteURL := remote.URL()
	local, err := LocalRepositoryFromURL(remoteURL)
	if err != nil {
		return err
	}

	var (
		fpath   = local.FullPath
		newPath = false
	)

	_, err = os.Stat(fpath)
	if err != nil {
		if os.IsNotExist(err) {
			newPath = true
			err = nil
		}
		if err != nil {
			return err
		}
	}

	switch {
	case newPath:
		if remoteURL.Scheme == "codecommit" {
			logger.Log("clone", fmt.Sprintf("%s -> %s", remoteURL.Opaque, fpath))
		} else {
			logger.Log("clone", fmt.Sprintf("%s -> %s", remoteURL, fpath))
		}
		var (
			localRepoRoot = fpath
			repoURL       = remoteURL
		)
		vcs, ok := vcsRegistry[g.vcs]
		if !ok {
			vcs, repoURL, err = remote.VCS()
			if err != nil {
				return err
			}
		}
		if l := detectLocalRepoRoot(remoteURL.Path, repoURL.Path); l != "" {
			localRepoRoot = filepath.Join(local.RootPath, remoteURL.Hostname(), l)
		}

		if remoteURL.Scheme == "codecommit" {
			repoURL, _ = url.Parse(remoteURL.Opaque)
		}
		if getRepoLock(localRepoRoot) {
			return vcs.Clone(&vcsGetOption{
				url:       repoURL,
				dir:       localRepoRoot,
				shallow:   g.shallow,
				silent:    g.silent,
				branch:    g.branch,
				recursive: g.recursive,
				bare:      g.bare,
			})
		}
		return nil
	case g.update:
		logger.Log("update", fpath)
		vcs, localRepoRoot := local.VCS()
		if vcs == nil {
			return fmt.Errorf("failed to detect VCS for %q", fpath)
		}
		if getRepoLock(localRepoRoot) {
			return vcs.Update(&vcsGetOption{
				dir:       localRepoRoot,
				silent:    g.silent,
				recursive: g.recursive,
			})
		}
		return nil
	}
	logger.Log("exists", fpath)
	return nil
}

func detectLocalRepoRoot(remotePath, repoPath string) string {
	remotePath = strings.TrimSuffix(strings.TrimSuffix(remotePath, "/"), ".git")
	repoPath = strings.TrimSuffix(strings.TrimSuffix(repoPath, "/"), ".git")
	pathParts := strings.Split(repoPath, "/")
	pathParts = pathParts[1:]
	for i := 0; i < len(pathParts); i++ {
		subPath := "/" + path.Join(pathParts[i:]...)
		if subIdx := strings.Index(remotePath, subPath); subIdx >= 0 {
			return remotePath[0:subIdx] + subPath
		}
	}
	return ""
}
<commit_msg>Simplify repository lock using sync.Map<commit_after>package main

import (
	"fmt"
	"net/url"
	"os"
	"path"
	"path/filepath"
	"strings"
	"sync"

	"github.com/x-motemen/ghq/logger"
)

var seen sync.Map

func getRepoLock(localRepoRoot string) bool {
	_, loaded := seen.LoadOrStore(localRepoRoot, struct{}{})
	return !loaded
}

type getter struct {
	update, shallow, silent, ssh, recursive, bare bool
	vcs, branch                                   string
}

func (g *getter) get(argURL string) error {
	u, err := newURL(argURL, g.ssh, false)
	if err != nil {
		return fmt.Errorf("Could not parse URL %q: %w", argURL, err)
	}

	remote, err := NewRemoteRepository(u)
	if err != nil {
		return err
	}

	return g.getRemoteRepository(remote)
}

// getRemoteRepository clones or updates a remote repository remote.
// If doUpdate is true, updates the locally cloned repository. Otherwise does nothing.
// If isShallow is true, does shallow cloning. (no effect if already cloned or the VCS is Mercurial and git-svn)
func (g *getter) getRemoteRepository(remote RemoteRepository) error {
	remoteURL := remote.URL()
	local, err := LocalRepositoryFromURL(remoteURL)
	if err != nil {
		return err
	}

	var (
		fpath   = local.FullPath
		newPath = false
	)

	_, err = os.Stat(fpath)
	if err != nil {
		if os.IsNotExist(err) {
			newPath = true
			err = nil
		}
		if err != nil {
			return err
		}
	}

	switch {
	case newPath:
		if remoteURL.Scheme == "codecommit" {
			logger.Log("clone", fmt.Sprintf("%s -> %s", remoteURL.Opaque, fpath))
		} else {
			logger.Log("clone", fmt.Sprintf("%s -> %s", remoteURL, fpath))
		}
		var (
			localRepoRoot = fpath
			repoURL       = remoteURL
		)
		vcs, ok := vcsRegistry[g.vcs]
		if !ok {
			vcs, repoURL, err = remote.VCS()
			if err != nil {
				return err
			}
		}
		if l := detectLocalRepoRoot(remoteURL.Path, repoURL.Path); l != "" {
			localRepoRoot = filepath.Join(local.RootPath, remoteURL.Hostname(), l)
		}

		if remoteURL.Scheme == "codecommit" {
			repoURL, _ = url.Parse(remoteURL.Opaque)
		}
		if getRepoLock(localRepoRoot) {
			return vcs.Clone(&vcsGetOption{
				url:       repoURL,
				dir:       localRepoRoot,
				shallow:   g.shallow,
				silent:    g.silent,
				branch:    g.branch,
				recursive: g.recursive,
				bare:      g.bare,
			})
		}
		return nil
	case g.update:
		logger.Log("update", fpath)
		vcs, localRepoRoot := local.VCS()
		if vcs == nil {
			return fmt.Errorf("failed to detect VCS for %q", fpath)
		}
		if getRepoLock(localRepoRoot) {
			return vcs.Update(&vcsGetOption{
				dir:       localRepoRoot,
				silent:    g.silent,
				recursive: g.recursive,
			})
		}
		return nil
	}
	logger.Log("exists", fpath)
	return nil
}

func detectLocalRepoRoot(remotePath, repoPath string) string {
	remotePath = strings.TrimSuffix(strings.TrimSuffix(remotePath, "/"), ".git")
	repoPath = strings.TrimSuffix(strings.TrimSuffix(repoPath, "/"), ".git")
	pathParts := strings.Split(repoPath, "/")
	pathParts = pathParts[1:]
	for i := 0; i < len(pathParts); i++ {
		subPath := "/" + path.Join(pathParts[i:]...)
		if subIdx := strings.Index(remotePath, subPath); subIdx >= 0 {
			return remotePath[0:subIdx] + subPath
		}
	}
	return ""
}
<|endoftext|>